feat(claude-do): merge Task context menu: "Mark as → Idle" for cancelled tasks

ClaudeDo-Task: ad39dbb38d314e96803decc4e194e180
This commit is contained in:
mika kuns
2026-10-02 10:33:36 +02:00
5 changed files with 42 additions and 3 deletions
@@ -209,6 +209,7 @@
"ctxMarkAs": "Markieren als",
"ctxMarkDone": "Erledigt",
"ctxMarkCancelled": "Abgebrochen",
"ctxMarkIdle": "Offen",
"ctxOpenConPtySession": "Interaktive Sitzung öffnen",
"ctxOpenWorktree": "Worktree öffnen",
"ctxOpenPlanningSession": "Planungssitzung öffnen",
@@ -209,6 +209,7 @@
"ctxMarkAs": "Mark as",
"ctxMarkDone": "Done",
"ctxMarkCancelled": "Cancelled",
"ctxMarkIdle": "Idle",
"ctxOpenConPtySession": "Open interactive session",
"ctxOpenWorktree": "Open worktree",
"ctxOpenPlanningSession": "Open planning Session",
@@ -70,6 +70,7 @@ public partial class TaskRowView : UserControl
var markAs = new MenuItem { Header = Loc.T("tasks.ctxMarkAs"), DataContext = row };
markAs.Items.Add(MakeItem("tasks.ctxMarkDone", OnSetStatusClick, tag: "Done", reason: row.MarkAsDisabledReason));
markAs.Items.Add(MakeItem("tasks.ctxMarkCancelled", OnSetStatusClick, tag: "Cancelled", reason: row.MarkAsDisabledReason));
markAs.Items.Add(MakeItem("tasks.ctxMarkIdle", OnSetStatusClick, row.Status == TaskStatus.Cancelled, tag: "Idle", reason: row.MarkAsDisabledReason));
markAs.Items.Add(new Separator());
markAs.Items.Add(MakeItem("tasks.ctxMarkManual", OnToggleManualClick, !row.IsManual));
markAs.Items.Add(MakeItem("tasks.ctxMarkClaudeTask", OnToggleManualClick, row.IsManual));
+7 -3
View File
@@ -677,10 +677,14 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
throw new HubException("Cannot change the status of a running task. Cancel it first.");
// Queueing goes through the gated transition so draft subtasks can't be queued;
// Idle goes through ResetToIdleAsync so StartedAt/FinishedAt/Result are cleared;
// other statuses keep the unconditional "set status freely" affordance.
var result = parsed == TaskStatus.Queued
? await _state.EnqueueAsync(taskId, Context.ConnectionAborted)
: await _state.ForceSetStatusAsync(taskId, parsed, Context.ConnectionAborted);
var result = parsed switch
{
TaskStatus.Queued => await _state.EnqueueAsync(taskId, Context.ConnectionAborted),
TaskStatus.Idle => await _state.ResetToIdleAsync(taskId, Context.ConnectionAborted),
_ => await _state.ForceSetStatusAsync(taskId, parsed, Context.ConnectionAborted),
};
if (!result.Ok) throw new HubException(result.Reason ?? "set status failed");
return new SetTaskStatusResultDto(
result.BaseDirty is { } w ? new BaseDirtyWarningDto(w.ModifiedCount, w.UntrackedCount) : null);