feat(ui): move review feedback to the Output tab + review/worktree polish
- Feedback box + a new "Resume session" button move from the Git tab to the Output tab; the Git review block keeps Approve & Merge / Park / Cancel / Reset. - Add a "Parked" chip for Idle tasks that still hold an Active worktree. - Stop showing the "Session was Cancelled" band on cancel (failed-only now). - Fix the Worktrees-overview state-chip contrast (dark text on the colour).
This commit is contained in:
@@ -442,7 +442,7 @@
|
||||
"connection": { "online": "Online", "connecting": "Verbinden…", "offline": "Offline" },
|
||||
"shell": { "restartingWorker": "Worker wird neu gestartet…" },
|
||||
"agentStatus": { "idle": "Leerlauf", "queued": "In Warteschlange", "running": "Läuft", "review": "Prüfung", "children": "Wartet auf Verbesserungen", "done": "Fertig", "failed": "Fehlgeschlagen", "cancelled": "Abgebrochen" },
|
||||
"taskStatus": { "idle": "Leerlauf", "queued": "In Warteschlange", "running": "Läuft", "waitingForReview": "Wartet auf Prüfung", "waitingForChildren": "Wartet auf Verbesserungen", "done": "Fertig", "failed": "Fehlgeschlagen", "cancelled": "Abgebrochen" },
|
||||
"taskStatus": { "idle": "Leerlauf", "queued": "In Warteschlange", "running": "Läuft", "waitingForReview": "Wartet auf Prüfung", "waitingForChildren": "Wartet auf Verbesserungen", "done": "Fertig", "failed": "Fehlgeschlagen", "cancelled": "Abgebrochen", "parked": "Geparkt" },
|
||||
"planningBadge": { "active": "PLANUNG", "finalized": "GEPLANT" },
|
||||
"taskRow": { "createdPrefix": "Erstellt {0}", "stepsText": "{0}/{1} Schritte" },
|
||||
"tasksIsland": { "completedHeader": "ABGESCHLOSSEN", "completedHeaderCount": "ABGESCHLOSSEN · {0}" },
|
||||
|
||||
@@ -442,7 +442,7 @@
|
||||
"connection": { "online": "Online", "connecting": "Connecting…", "offline": "Offline" },
|
||||
"shell": { "restartingWorker": "Restarting worker…" },
|
||||
"agentStatus": { "idle": "Idle", "queued": "Queued", "running": "Running", "review": "Review", "children": "Waiting for Improvements", "done": "Done", "failed": "Failed", "cancelled": "Cancelled" },
|
||||
"taskStatus": { "idle": "Idle", "queued": "Queued", "running": "Running", "waitingForReview": "Waiting for Review", "waitingForChildren": "Waiting for Improvements", "done": "Done", "failed": "Failed", "cancelled": "Cancelled" },
|
||||
"taskStatus": { "idle": "Idle", "queued": "Queued", "running": "Running", "waitingForReview": "Waiting for Review", "waitingForChildren": "Waiting for Improvements", "done": "Done", "failed": "Failed", "cancelled": "Cancelled", "parked": "Parked" },
|
||||
"planningBadge": { "active": "PLANNING", "finalized": "PLANNED" },
|
||||
"taskRow": { "createdPrefix": "Created {0}", "stepsText": "{0}/{1} steps" },
|
||||
"tasksIsland": { "completedHeader": "COMPLETED", "completedHeaderCount": "COMPLETED · {0}" },
|
||||
|
||||
@@ -229,6 +229,15 @@
|
||||
<Setter Property="Foreground" Value="{StaticResource TextMuteBrush}" />
|
||||
</Style>
|
||||
|
||||
<!-- parked → slate-blue: an Idle task still holding its Active worktree -->
|
||||
<Style Selector="Border.chip.parked">
|
||||
<Setter Property="Background" Value="#22303A" />
|
||||
<Setter Property="BorderBrush" Value="#3A5060" />
|
||||
</Style>
|
||||
<Style Selector="Border.chip.parked > TextBlock">
|
||||
<Setter Property="Foreground" Value="#8FB9D6" />
|
||||
</Style>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- BUTTONS -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
@@ -166,10 +166,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
public string DiffAddText => $"+{DiffAdditions}";
|
||||
public string DiffDelText => $"-{DiffDeletions}";
|
||||
|
||||
public bool ShowRoadblock => IsFailed || IsCancelled;
|
||||
public bool ShowRoadblock => IsFailed;
|
||||
public string RoadblockMessage =>
|
||||
IsFailed ? "The session ended with an error." :
|
||||
IsCancelled ? "The session was cancelled." : "";
|
||||
IsFailed ? "The session ended with an error." : "";
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ShowSessionOutcome))]
|
||||
|
||||
@@ -18,6 +18,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
||||
[ObservableProperty] private PlanningPhase _planningPhase;
|
||||
[ObservableProperty] private string? _branch;
|
||||
[ObservableProperty] private string? _diffStat;
|
||||
[ObservableProperty] private ClaudeDo.Data.Models.WorktreeState? _worktreeState;
|
||||
[ObservableProperty] private DateTime? _scheduledFor;
|
||||
[ObservableProperty] private int _diffAdditions;
|
||||
[ObservableProperty] private int _diffDeletions;
|
||||
@@ -76,6 +77,8 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
||||
public bool IsOverdue => ScheduledFor is { } d && d.Date < DateTime.Today && !Done;
|
||||
public bool IsRunning => Status == TaskStatus.Running;
|
||||
public bool IsWaitingForReview => Status == TaskStatus.WaitingForReview;
|
||||
// Parked = set aside from review: Idle but still holding its Active worktree (vs a plain Idle task).
|
||||
public bool IsParked => Status == TaskStatus.Idle && WorktreeState == ClaudeDo.Data.Models.WorktreeState.Active;
|
||||
public bool IsQueued => Status == TaskStatus.Queued && string.IsNullOrEmpty(BlockedByTaskId);
|
||||
public bool IsWaiting => Status == TaskStatus.Queued && !string.IsNullOrEmpty(BlockedByTaskId);
|
||||
public bool CanRemoveFromQueue => IsQueued || HasQueuedSubtasks;
|
||||
@@ -105,7 +108,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
||||
public string DiffDeletionsText => $"−{DiffDeletions}";
|
||||
public string StepsText => Loc.T("vm.taskRow.stepsText", StepsCompleted, StepsCount);
|
||||
|
||||
public string StatusLabel => Status switch
|
||||
public string StatusLabel => IsParked ? Loc.T("vm.taskStatus.parked") : Status switch
|
||||
{
|
||||
TaskStatus.Idle => Loc.T("vm.taskStatus.idle"),
|
||||
TaskStatus.Queued => Loc.T("vm.taskStatus.queued"),
|
||||
@@ -136,6 +139,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
||||
OnPropertyChanged(nameof(StatusLabel));
|
||||
OnPropertyChanged(nameof(IsRunning));
|
||||
OnPropertyChanged(nameof(IsWaitingForReview));
|
||||
OnPropertyChanged(nameof(IsParked));
|
||||
OnPropertyChanged(nameof(IsQueued));
|
||||
OnPropertyChanged(nameof(IsWaiting));
|
||||
OnPropertyChanged(nameof(IsDraft));
|
||||
@@ -210,6 +214,11 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
||||
}
|
||||
|
||||
partial void OnBranchChanged(string? value) => OnPropertyChanged(nameof(HasBranch));
|
||||
partial void OnWorktreeStateChanged(ClaudeDo.Data.Models.WorktreeState? value)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsParked));
|
||||
OnPropertyChanged(nameof(StatusLabel));
|
||||
}
|
||||
partial void OnDoneChanged(bool value)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsOverdue));
|
||||
@@ -252,6 +261,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
||||
PlanningPhase = t.PlanningPhase;
|
||||
Branch = t.Worktree?.BranchName;
|
||||
DiffStat = t.Worktree?.DiffStat;
|
||||
WorktreeState = t.Worktree?.State;
|
||||
ScheduledFor = t.ScheduledFor;
|
||||
DiffAdditions = add;
|
||||
DiffDeletions = del;
|
||||
|
||||
@@ -212,6 +212,28 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Review footer: feedback + Resume session, shown while awaiting review.
|
||||
Lives here (with the live log) rather than the Git tab. -->
|
||||
<Border DockPanel.Dock="Bottom"
|
||||
IsVisible="{Binding IsWaitingForReview}"
|
||||
Margin="12,6,12,2">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBox Name="ReviewInput"
|
||||
KeyDown="OnReviewInputKeyDown"
|
||||
Text="{Binding ReviewFeedback, Mode=TwoWay}"
|
||||
AcceptsReturn="True"
|
||||
TextWrapping="Wrap"
|
||||
MaxHeight="120"
|
||||
PlaceholderText="Feedback for a re-run…"
|
||||
FontFamily="{StaticResource MonoFont}"
|
||||
FontSize="{StaticResource FontSizeMono}" />
|
||||
<Button Classes="btn" Content="Resume session"
|
||||
HorizontalAlignment="Left"
|
||||
ToolTip.Tip="{loc:Tr session.reviewContinueTip}"
|
||||
Command="{Binding RejectReviewCommand}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<ScrollViewer Name="LogScroll"
|
||||
VerticalScrollBarVisibility="Visible"
|
||||
AllowAutoHide="False"
|
||||
@@ -291,28 +313,15 @@
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Review decision — feedback + the four review verbs. Always present while
|
||||
awaiting review, even for sandbox runs with no worktree to merge. -->
|
||||
<!-- Review decision — the merge verbs. Feedback + Resume session moved to the
|
||||
Output tab. Present while awaiting review, even for sandbox runs. -->
|
||||
<StackPanel Spacing="10" IsVisible="{Binding IsWaitingForReview}">
|
||||
<Border Height="1" Background="{DynamicResource LineBrush}"
|
||||
IsVisible="{Binding Merge.ShowMergeSection}" />
|
||||
|
||||
<TextBox Name="ReviewInput"
|
||||
KeyDown="OnReviewInputKeyDown"
|
||||
Text="{Binding ReviewFeedback, Mode=TwoWay}"
|
||||
AcceptsReturn="True"
|
||||
TextWrapping="Wrap"
|
||||
MaxHeight="120"
|
||||
PlaceholderText="Feedback for a re-run…"
|
||||
FontFamily="{StaticResource MonoFont}"
|
||||
FontSize="{StaticResource FontSizeMono}" />
|
||||
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<Button Classes="btn accent" Content="Approve & Merge" Margin="0,0,8,8"
|
||||
Command="{Binding ApproveReviewCommand}" />
|
||||
<Button Classes="btn" Content="Send back" Margin="0,0,8,8"
|
||||
ToolTip.Tip="{loc:Tr session.reviewContinueTip}"
|
||||
Command="{Binding RejectReviewCommand}" />
|
||||
<Button Classes="btn" Content="Park" Margin="0,0,8,8"
|
||||
ToolTip.Tip="Set aside — back to Idle, keeps the worktree"
|
||||
Command="{Binding ParkReviewCommand}" />
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
|
||||
<!-- Status chip -->
|
||||
<Border Classes="chip"
|
||||
Classes.parked="{Binding IsParked}"
|
||||
Classes.running="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=Running}"
|
||||
Classes.review="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=WaitingForReview}"
|
||||
Classes.children="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=WaitingForChildren}"
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
IsVisible="{Binding HasOutcome}"/>
|
||||
<Border Grid.Column="3" CornerRadius="3" Padding="6,2" VerticalAlignment="Center"
|
||||
Background="{Binding State, Converter={StaticResource WorktreeStateColor}}">
|
||||
<TextBlock Classes="meta" Text="{Binding State}" Foreground="{DynamicResource TextBrush}"
|
||||
<TextBlock Classes="meta" Text="{Binding State}" Foreground="{DynamicResource DeepBrush}"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Border>
|
||||
<TextBlock Grid.Column="4" Classes="meta" Text="{Binding DiffStat}" VerticalAlignment="Center"/>
|
||||
|
||||
Reference in New Issue
Block a user