feat(ui): queue planning subtasks sequentially and surface waiting status
Adds a "Queue subtasks sequentially" context-menu entry on rows with planning children, wires it to WorkerHub.QueuePlanningSubtasksAsync via IWorkerClient. TaskRowViewModel exposes IsWaiting/StatusChipClass for the new Waiting status, and HasPlanningChildren keeps parents expandable after they leave the planning state. TasksIslandViewModel auto-collapses parents whose every child is Done and includes Waiting children in the queued virtual list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -176,7 +176,7 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
||||
ListKind.Smart when list.Id == "smart:planned" => all.Where(t => t.ScheduledFor != null),
|
||||
ListKind.Virtual when list.Id == "virtual:queued" => all.Where(t =>
|
||||
(t.Status == TaskStatus.Queued && t.ParentTaskId == null) ||
|
||||
(IsPlanningStatus(t.Status) && all.Any(c => c.ParentTaskId == t.Id && c.Status == TaskStatus.Queued))),
|
||||
(IsPlanningStatus(t.Status) && all.Any(c => c.ParentTaskId == t.Id && (c.Status == TaskStatus.Queued || c.Status == TaskStatus.Waiting)))),
|
||||
ListKind.Virtual when list.Id == "virtual:running" => all.Where(t =>
|
||||
(t.Status == TaskStatus.Running && t.ParentTaskId == null) ||
|
||||
(IsPlanningStatus(t.Status) && all.Any(c => c.ParentTaskId == t.Id && c.Status == TaskStatus.Running))),
|
||||
@@ -197,6 +197,16 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
||||
foreach (var t in filteredList)
|
||||
Items.Add(TaskRowViewModel.FromEntity(t));
|
||||
|
||||
// Mark any top-level row that has at least one child as a planning parent,
|
||||
// so its subtasks remain expandable even after the parent is queued/running.
|
||||
var parentsWithChildren = Items
|
||||
.Where(r => r.IsChild && !string.IsNullOrEmpty(r.ParentTaskId))
|
||||
.Select(r => r.ParentTaskId!)
|
||||
.ToHashSet();
|
||||
foreach (var r in Items)
|
||||
if (parentsWithChildren.Contains(r.Id))
|
||||
r.HasPlanningChildren = true;
|
||||
|
||||
Regroup();
|
||||
UpdateSubtitle();
|
||||
}
|
||||
@@ -209,6 +219,23 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
||||
OpenItems.Clear();
|
||||
CompletedItems.Clear();
|
||||
|
||||
// Auto-collapse planning parents whose every child is Done (unless the user
|
||||
// has explicitly toggled the row — saved state wins).
|
||||
var childrenByParent = Items
|
||||
.Where(r => r.IsChild && !string.IsNullOrEmpty(r.ParentTaskId))
|
||||
.GroupBy(r => r.ParentTaskId!)
|
||||
.ToDictionary(g => g.Key, g => g.ToList());
|
||||
foreach (var parent in Items.Where(r => r.IsPlanningParent && !r.IsChild))
|
||||
{
|
||||
if (_expandedState.ContainsKey(parent.Id)) continue;
|
||||
if (childrenByParent.TryGetValue(parent.Id, out var kids)
|
||||
&& kids.Count > 0
|
||||
&& kids.All(c => c.Status == TaskStatus.Done))
|
||||
{
|
||||
parent.IsExpanded = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore IsExpanded from saved state
|
||||
foreach (var r in Items)
|
||||
{
|
||||
@@ -537,6 +564,14 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
||||
catch { }
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task QueuePlanningSubtasksAsync(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null || _worker is null) return;
|
||||
try { await _worker.QueuePlanningSubtasksAsync(row.Id); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task FinalizePlanningSessionAsync(TaskRowViewModel? row)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user