From 2455eacb1f572b6e0a9681a0c25b34376a01cc1c Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 4 Jun 2026 15:06:53 +0200 Subject: [PATCH] feat(ui): roadblock badge on the task card; relocate review actions off the row Co-Authored-By: Claude Sonnet 4.6 --- src/ClaudeDo.Ui/Design/IslandStyles.axaml | 3 ++ .../ViewModels/Islands/TaskRowViewModel.cs | 7 +++ .../Views/Islands/TaskRowView.axaml | 54 +++---------------- .../Views/Islands/TaskRowView.axaml.cs | 37 ------------- 4 files changed, 17 insertions(+), 84 deletions(-) diff --git a/src/ClaudeDo.Ui/Design/IslandStyles.axaml b/src/ClaudeDo.Ui/Design/IslandStyles.axaml index e2f489b..3c10dfd 100644 --- a/src/ClaudeDo.Ui/Design/IslandStyles.axaml +++ b/src/ClaudeDo.Ui/Design/IslandStyles.axaml @@ -85,6 +85,9 @@ M13 4 H20 V11 H18 V7.4 L11.4 14 L10 12.6 L16.6 6 H13 Z M4 6 H10 V8 H6 V18 H16 V14 H18 V20 H4 Z + + M12 3 L22 20 H2 Z M11 9 H13 V14 H11 Z M11 16 H13 V18 H11 Z + M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65a.5.5 0 0 0 .12-.64l-2-3.46a.5.5 0 0 0-.61-.22l-2.49 1a7.03 7.03 0 0 0-1.69-.98l-.38-2.65a.5.5 0 0 0-.5-.42h-4a.5.5 0 0 0-.5.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1a.5.5 0 0 0-.61.22l-2 3.46a.5.5 0 0 0 .12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65a.5.5 0 0 0-.12.64l2 3.46a.5.5 0 0 0 .61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65a.5.5 0 0 0 .5.42h4a.5.5 0 0 0 .5-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1a.5.5 0 0 0 .61-.22l2-3.46a.5.5 0 0 0-.12-.64l-2.11-1.65z diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs index fde68a3..647a929 100644 --- a/src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Islands/TaskRowViewModel.cs @@ -30,6 +30,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase [ObservableProperty] private bool _hasQueuedSubtasks; [ObservableProperty] private bool _showListChip = true; [ObservableProperty] private bool _parentFinalized; + [ObservableProperty] private int _roadblockCount; public DateTime CreatedAt { get; init; } public string CreatedAtFormatted => CreatedAt == default ? "—" : Loc.T("vm.taskRow.createdPrefix", CreatedAt.ToString("MMM d")); @@ -75,6 +76,10 @@ public sealed partial class TaskRowViewModel : ViewModelBase && PlanningPhase == PlanningPhase.Finalized && !HasQueuedSubtasks; public bool HasSchedule => ScheduledFor.HasValue; + public bool HasRoadblock => RoadblockCount > 0; + public string RoadblockTooltip => RoadblockCount == 1 + ? "1 roadblock reported during the run — see details" + : $"{RoadblockCount} roadblocks reported during the run — see details"; public string DiffAdditionsText => $"+{DiffAdditions}"; public string DiffDeletionsText => $"−{DiffDeletions}"; @@ -174,6 +179,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase } partial void OnDiffAdditionsChanged(int value) { OnPropertyChanged(nameof(HasDiff)); OnPropertyChanged(nameof(DiffAdditionsText)); } partial void OnDiffDeletionsChanged(int value) { OnPropertyChanged(nameof(HasDiff)); OnPropertyChanged(nameof(DiffDeletionsText)); } + partial void OnRoadblockCountChanged(int value) { OnPropertyChanged(nameof(HasRoadblock)); OnPropertyChanged(nameof(RoadblockTooltip)); } public void RefreshLocalized() { @@ -207,6 +213,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase DiffDeletions = del; ParentTaskId = t.ParentTaskId; BlockedByTaskId = t.BlockedByTaskId; + RoadblockCount = t.RoadblockCount; } // Best-effort parse of diff stat strings like "+12 -3" or "12 additions, 3 deletions". diff --git a/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml b/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml index d4aaae9..d664935 100644 --- a/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml +++ b/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml @@ -129,6 +129,13 @@ + + + - - - - - diff --git a/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml.cs b/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml.cs index 1fe56c6..3cc2024 100644 --- a/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml.cs +++ b/src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml.cs @@ -88,43 +88,6 @@ public partial class TaskRowView : UserControl await vm.SetStatusOnRowAsync(row, status); } - private async void OnApproveReviewClick(object? sender, RoutedEventArgs e) - { - if (DataContext is TaskRowViewModel row && FindTasksVm() is { } vm) - await vm.ApproveReviewCommand.ExecuteAsync(row); - } - - private async void OnParkReviewClick(object? sender, RoutedEventArgs e) - { - if (DataContext is TaskRowViewModel row && FindTasksVm() is { } vm) - await vm.RejectReviewToIdleCommand.ExecuteAsync(row); - } - - private async void OnCancelReviewClick(object? sender, RoutedEventArgs e) - { - if (DataContext is TaskRowViewModel row && FindTasksVm() is { } vm) - await vm.CancelReviewCommand.ExecuteAsync(row); - } - - private void OnRejectReviewClick(object? sender, RoutedEventArgs e) - { - if (DataContext is not TaskRowViewModel) return; - RejectFeedback.Text = ""; - RejectAnchor.Flyout?.ShowAt(RejectAnchor); - } - - private async void OnRejectConfirmClick(object? sender, RoutedEventArgs e) - { - RejectAnchor.Flyout?.Hide(); - if (DataContext is not TaskRowViewModel row || FindTasksVm() is not { } vm) return; - var feedback = RejectFeedback.Text ?? ""; - if (string.IsNullOrWhiteSpace(feedback)) return; - await vm.RejectReviewToQueueAsync(row, feedback); - } - - private void OnRejectCancelClick(object? sender, RoutedEventArgs e) - => RejectAnchor.Flyout?.Hide(); - private void OnScheduleForClick(object? sender, RoutedEventArgs e) { if (DataContext is not TaskRowViewModel row) return;