fix(ui): guard retry action while recovery resolves

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-18 20:54:51 +00:00
1 parent 28fb9d5cef
commit 7f679f2850
4 files changed
+31 -1

No files matched your search

+1
View File
@@ -456,6 +456,7 @@ interface IssueChatThreadProps {
scheduledRetry?: IssueScheduledRetry | null;
recoveryAction?: IssueRecoveryAction | null;
onResolveRecoveryAction?: (outcome: RecoveryResolveOutcome) => void;
recoveryActionPending?: boolean;
onReissueIsolatedRecoveryAction?: (request: RecoveryReissueRequest) => void;
reissueIsolatedRecoveryActionPending?: boolean;
onReconcileForwardRecoveryAction?: () => void;
+23
View File
@@ -233,6 +233,29 @@ describe("TaskChatThread recovery actions", () => {
expect(container.querySelector('[data-testid="task-chat-recovery-try-again"]')).toBeNull();
});
it("disables Try again while recovery resolution is pending", () => {
const onResolveRecoveryAction = vi.fn();
render(
<TaskChatThread
comments={[recoveryComment]}
onAdd={async () => {}}
issueId="issue-1"
issueStatus="blocked"
recoveryAction={recoveryAction}
onResolveRecoveryAction={onResolveRecoveryAction}
recoveryActionPending
/>,
);
const retry = container.querySelector<HTMLButtonElement>(
'[data-testid="task-chat-recovery-try-again"]',
)!;
expect(retry.disabled).toBe(true);
flushSync(() => retry.click());
expect(onResolveRecoveryAction).not.toHaveBeenCalled();
});
});
describe("TaskChatThread composer alignment (PAP-498)", () => {
+3 -1
View File
@@ -149,6 +149,7 @@ export function TaskChatThread(props: TaskChatThreadProps) {
liveIssueIds,
recoveryAction,
onResolveRecoveryAction,
recoveryActionPending,
} = props;
const liveWorkLinks = useMemo(
@@ -644,13 +645,14 @@ export function TaskChatThread(props: TaskChatThreadProps) {
variant="outline"
size="xs"
data-testid="task-chat-recovery-try-again"
disabled={recoveryActionPending}
onClick={() => onResolveRecoveryAction("todo")}
>
Try again
</Button>
);
},
[onResolveRecoveryAction, recoveryAction],
[onResolveRecoveryAction, recoveryAction, recoveryActionPending],
);
const renderInteraction = useCallback(
+4
View File
@@ -961,6 +961,7 @@ type IssueDetailChatTabProps = {
scheduledRetry: Issue["scheduledRetry"] | null;
recoveryAction: Issue["activeRecoveryAction"];
onResolveRecoveryAction?: (outcome: import("../components/IssueRecoveryActionCard").RecoveryResolveOutcome) => void;
recoveryActionPending?: boolean;
onReissueIsolatedRecoveryAction?: (request: import("../components/IssueRecoveryActionCard").RecoveryReissueRequest) => void;
reissueIsolatedRecoveryActionPending?: boolean;
onReconcileForwardRecoveryAction?: () => void;
@@ -1067,6 +1068,7 @@ const IssueDetailChatTab = memo(function IssueDetailChatTab({
scheduledRetry,
recoveryAction,
onResolveRecoveryAction,
recoveryActionPending,
onReissueIsolatedRecoveryAction,
reissueIsolatedRecoveryActionPending,
onReconcileForwardRecoveryAction,
@@ -1342,6 +1344,7 @@ const IssueDetailChatTab = memo(function IssueDetailChatTab({
scheduledRetry={scheduledRetry}
recoveryAction={recoveryAction ?? null}
onResolveRecoveryAction={onResolveRecoveryAction}
recoveryActionPending={recoveryActionPending}
onReissueIsolatedRecoveryAction={onReissueIsolatedRecoveryAction}
reissueIsolatedRecoveryActionPending={reissueIsolatedRecoveryActionPending}
onReconcileForwardRecoveryAction={onReconcileForwardRecoveryAction}
@@ -5285,6 +5288,7 @@ export function IssueDetail() {
scheduledRetry={issue.scheduledRetry ?? null}
recoveryAction={issue.activeRecoveryAction ?? null}
onResolveRecoveryAction={handleResolveRecoveryAction}
recoveryActionPending={resolveRecoveryAction.isPending}
onReissueIsolatedRecoveryAction={handleReissueIsolatedRecoveryAction}
reissueIsolatedRecoveryActionPending={reissueIsolatedRecoveryAction.isPending}
onReconcileForwardRecoveryAction={handleReconcileForwardRecoveryAction}