feat(ui): surface depends_on blocking in status chip, chain label, and detail pane
Usability-Audit 2026-09-10 found three gaps versus the dependency-chain-display spec: a Queued task blocked on an unmet task_dependencies edge rendered the same chip as one about to run, a cross-list predecessor silently dropped the "after #N" chip, and the detail pane showed nothing about a wait at all. - TaskRowViewModel gains IsBlockedByDependency/DependencyWaitLabel (extrinsic, assigned by TasksIslandViewModel like the existing chain fields); IsQueued/ IsWaiting/StatusChipClass/StatusLabel/StatusChipTooltip now account for it alongside the existing BlockedByTaskId planning-chain link. - TasksIslandViewModel.ApplyDependencyWaitState computes the blocked flag and wait label per row; a new RefreshExternalDependencyCacheAsync backfills Number/Title/Status for predecessors not loaded into the current list's Items (reusing the already-open DbContext, no new hub method), so BuildAfterLabel/blocking both resolve a listenfremder Vorgänger correctly. - New "waiting" chip style (IslandStyles.axaml) and locale keys (en+de); TaskHeaderBar shows a "Waiting on #N" line bound straight to the same row. Tests: TasksIslandChainTests (blocked/unblocked chip, cross-list predecessor), DetailsIslandDependencyWaitTests (new), TaskRowViewModelNotificationsTests updated for the new notification set.
This commit is contained in:
@@ -281,10 +281,41 @@ public class TaskRowViewModelNotificationsTests
|
||||
nameof(TaskRowViewModel.IsQueued),
|
||||
nameof(TaskRowViewModel.IsWaiting),
|
||||
nameof(TaskRowViewModel.StatusChipClass),
|
||||
nameof(TaskRowViewModel.StatusLabel),
|
||||
nameof(TaskRowViewModel.StatusChipTooltip),
|
||||
nameof(TaskRowViewModel.CanRemoveFromQueue),
|
||||
}, raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsBlockedByDependencyChanged_Notifies_Dependents()
|
||||
{
|
||||
var vm = new TaskRowViewModel { Id = "t" };
|
||||
var raised = Raised(vm, () => vm.IsBlockedByDependency = true);
|
||||
Assert.Equal(new HashSet<string?>
|
||||
{
|
||||
nameof(TaskRowViewModel.IsBlockedByDependency),
|
||||
nameof(TaskRowViewModel.IsQueued),
|
||||
nameof(TaskRowViewModel.IsWaiting),
|
||||
nameof(TaskRowViewModel.StatusChipClass),
|
||||
nameof(TaskRowViewModel.StatusLabel),
|
||||
nameof(TaskRowViewModel.StatusChipTooltip),
|
||||
nameof(TaskRowViewModel.CanRemoveFromQueue),
|
||||
}, raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DependencyWaitLabelChanged_Notifies_Dependents()
|
||||
{
|
||||
var vm = new TaskRowViewModel { Id = "t" };
|
||||
var raised = Raised(vm, () => vm.DependencyWaitLabel = "#42");
|
||||
Assert.Equal(new HashSet<string?>
|
||||
{
|
||||
nameof(TaskRowViewModel.DependencyWaitLabel),
|
||||
nameof(TaskRowViewModel.StatusChipTooltip),
|
||||
}, raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasPlanningChildrenChanged_Notifies_Dependents()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user