feat(ui): add WorkConsole detail component
Standalone terminal-styled card with traffic-light title bar, roadblock band, and three tabs (Output / Actions / Session). Renders fully via design-time sample data; does not touch DetailsIslandView. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using ClaudeDo.Ui.ViewModels.Islands;
|
||||
|
||||
namespace ClaudeDo.Ui.ViewModels.Islands.Detail;
|
||||
|
||||
public sealed class WorkConsoleChildOutcomeRowViewModel
|
||||
{
|
||||
public required string Title { get; init; }
|
||||
public bool HasRoadblock { get; init; }
|
||||
public string RoadblockText { get; init; } = "";
|
||||
public required string StatusLabel { get; init; }
|
||||
}
|
||||
|
||||
public sealed partial class WorkConsoleViewModel : ViewModelBase
|
||||
{
|
||||
// ── Tab selection ──────────────────────────────────────────────
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(IsOutputTab))]
|
||||
[NotifyPropertyChangedFor(nameof(IsActionsTab))]
|
||||
[NotifyPropertyChangedFor(nameof(IsSessionTab))]
|
||||
private string _selectedTab = "output";
|
||||
|
||||
public bool IsOutputTab => SelectedTab == "output";
|
||||
public bool IsActionsTab => SelectedTab == "actions";
|
||||
public bool IsSessionTab => SelectedTab == "session";
|
||||
|
||||
[RelayCommand]
|
||||
private void SelectTab(string tab) => SelectedTab = tab;
|
||||
|
||||
// ── Info header ────────────────────────────────────────────────
|
||||
[ObservableProperty] private string _model = "";
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(TurnsText))]
|
||||
private int _turns;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(DiffAddText))]
|
||||
private int _diffAdditions;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(DiffDelText))]
|
||||
private int _diffDeletions;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ShowRoadblock))]
|
||||
private bool _isRunning;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ShowRoadblock))]
|
||||
private bool _isDone;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ShowRoadblock))]
|
||||
private bool _isFailed;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ShowRoadblock))]
|
||||
private bool _isCancelled;
|
||||
|
||||
[ObservableProperty] private string _sessionLabel = "";
|
||||
|
||||
public string TurnsText => $"{Turns} turns";
|
||||
public string DiffAddText => $"+{DiffAdditions}";
|
||||
public string DiffDelText => $"-{DiffDeletions}";
|
||||
|
||||
// ── Roadblock ──────────────────────────────────────────────────
|
||||
public bool ShowRoadblock => IsFailed || IsCancelled;
|
||||
|
||||
[ObservableProperty] private string _roadblockMessage = "";
|
||||
[ObservableProperty] private bool _showContinue;
|
||||
[ObservableProperty] private bool _showResetAndRetry;
|
||||
|
||||
[RelayCommand] private void Continue() { }
|
||||
[RelayCommand] private void ResetAndRetry() { }
|
||||
|
||||
// ── Actions tab ────────────────────────────────────────────────
|
||||
public ObservableCollection<string> MergeTargetBranches { get; } = new();
|
||||
|
||||
[ObservableProperty] private string? _selectedMergeTarget;
|
||||
[ObservableProperty] private bool _canMergeAll;
|
||||
[ObservableProperty] private string _mergeAllDisabledReason = "";
|
||||
[ObservableProperty] private string? _mergeAllError;
|
||||
|
||||
[RelayCommand] private void OpenDiff() { }
|
||||
[RelayCommand] private void OpenWorktree() { }
|
||||
[RelayCommand] private void ReviewCombinedDiff() { }
|
||||
[RelayCommand] private void MergeAll() { }
|
||||
|
||||
// ── Session tab ────────────────────────────────────────────────
|
||||
[ObservableProperty] private bool _isWaitingForReview;
|
||||
[ObservableProperty] private string _reviewFeedback = "";
|
||||
|
||||
public ObservableCollection<WorkConsoleChildOutcomeRowViewModel> ChildOutcomes { get; } = new();
|
||||
public bool HasChildOutcomes => ChildOutcomes.Count > 0;
|
||||
|
||||
[RelayCommand] private void ApproveReview() { }
|
||||
[RelayCommand] private void RejectReview() { }
|
||||
[RelayCommand] private void ParkReview() { }
|
||||
[RelayCommand] private void CancelReview() { }
|
||||
|
||||
public ObservableCollection<LogLineViewModel> Log { get; } = new();
|
||||
|
||||
public WorkConsoleViewModel()
|
||||
{
|
||||
ChildOutcomes.CollectionChanged += (_, _) => OnPropertyChanged(nameof(HasChildOutcomes));
|
||||
|
||||
// ── Design-time sample data ────────────────────────────────
|
||||
_model = "sonnet";
|
||||
_turns = 40;
|
||||
_diffAdditions = 84;
|
||||
_diffDeletions = 31;
|
||||
_isRunning = true;
|
||||
_sessionLabel = "feat/work-console";
|
||||
|
||||
MergeTargetBranches.Add("main");
|
||||
MergeTargetBranches.Add("develop");
|
||||
_selectedMergeTarget = "main";
|
||||
_canMergeAll = true;
|
||||
|
||||
Log.Add(new LogLineViewModel { Kind = LogKind.Sys, Text = "Starting claude session…" });
|
||||
Log.Add(new LogLineViewModel { Kind = LogKind.Claude, Text = "Reading DetailsIslandView.axaml to understand existing layout." });
|
||||
Log.Add(new LogLineViewModel { Kind = LogKind.Tool, Text = "Read(src/ClaudeDo.Ui/Views/Islands/DetailsIslandView.axaml)" });
|
||||
Log.Add(new LogLineViewModel { Kind = LogKind.Claude, Text = "Building WorkConsole component with three tabs." });
|
||||
Log.Add(new LogLineViewModel { Kind = LogKind.Stdout, Text = "dotnet build succeeded — 0 error(s)" });
|
||||
|
||||
ChildOutcomes.Add(new WorkConsoleChildOutcomeRowViewModel
|
||||
{
|
||||
Title = "Add WorkConsole XAML",
|
||||
StatusLabel = "Done"
|
||||
});
|
||||
ChildOutcomes.Add(new WorkConsoleChildOutcomeRowViewModel
|
||||
{
|
||||
Title = "Wire ViewModel bindings",
|
||||
HasRoadblock = true,
|
||||
RoadblockText = "Missing token",
|
||||
StatusLabel = "Failed"
|
||||
});
|
||||
|
||||
// To preview roadblock state: _isFailed = true; _roadblockMessage = "Session ended unexpectedly"; _showResetAndRetry = true; _isRunning = false;
|
||||
// To preview review state: _isWaitingForReview = true; _isDone = false; _isRunning = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user