feat: allow ticket implementation cancellation

This commit is contained in:
2026-08-25 09:52:21 +09:00
parent c1d46859a3
commit 9a05bfa0c3
3 changed files with 524 additions and 96 deletions
@@ -55,6 +55,10 @@
let readyOperationKey = $state<string | null>(null);
let manualRuntimeId = $state("");
let manualWorkerId = $state("");
let cancellationReason = $state("");
const coderAssignment = $derived(
ticket.assignments.find((assignment) => assignment.role === "coder") ?? null,
);
const selectedRepository = $derived(
(loadedRepositories?.items ?? []).find((repository: RepositorySummary) => repository.id === repositoryId) ?? null,
);
@@ -162,6 +166,18 @@
});
}
async function cancelImplementation(event: SubmitEvent): Promise<void> {
event.preventDefault();
if (!coderAssignment || !cancellationReason.trim()) return;
if (
await mutate("cancel-implementation", "/implementation-cancellations", {
operation_id: crypto.randomUUID(),
assignment_id: coderAssignment.assignment_id,
reason: cancellationReason.trim(),
})
) cancellationReason = "";
}
async function saveEdit(event: SubmitEvent) {
event.preventDefault();
if (
@@ -416,6 +432,24 @@
</button>
</form>
{/if}
{#if ticket.state === "inprogress" && coderAssignment}
<details class="ticket-cancel-implementation">
<summary>Cancel implementation</summary>
<form class="ticket-control-form" onsubmit={cancelImplementation}>
<p class="workspace-empty-copy">
Cancel the assigned Coder, remove its assignment, and return this Ticket to ready.
</p>
<label>Reason<textarea bind:value={cancellationReason} rows="3" required></textarea></label>
<button
class="workspace-danger-button"
type="submit"
disabled={busy !== null || !cancellationReason.trim()}
>
{busy === "cancel-implementation" ? "Cancelling…" : "Cancel and return to ready"}
</button>
</form>
</details>
{/if}
{#if ticket.assignment_diagnostics.length > 0}
{#each ticket.assignment_diagnostics as diagnostic}
<p class="workspace-callout">{diagnostic}</p>