Repository navigation
fix(terminal): render TerminalModals in TerminalWindow, with each action reporting the parent's real outcome (#16285) - #16313
Conversation
…ion reporting the parent's real outcome (#16285) TerminalWindow rendered its own copies of the reconnect, destructive-command, emergency-kill and legacy workflow-step modals. TerminalModals, the extraction of those four, rendered nowhere and reported success after a fixed setTimeout. TerminalWindow now renders TerminalModals and hands it each action as a function prop. TerminalModals awaits the action through withTimeout. It shows a rejection (or a synchronous throw) as the error, and reports success only once the action settles. The parent actions now return their real outcome: - the command and workflow-step sends are awaited; - a failed kill rethrows after it is logged to the terminal; - the modal's reconnect rejects with the connection error. withTimeout (autobot-frontend/src/utils/withTimeout.ts) lands here, as its first consumer. #16253 will import it rather than add it. The success, timeout and fallback-error strings go through i18n in all 11 locales. The 15 terminal.window keys that only the removed inline modals used are dropped. The untranslated ratchet goes down by 13 per locale: those 13 keys were still English.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review at
i18n: 18 new keys in Nit, non-blocking: the two auto-hide timers aren't cleared on unmount, so closing the terminal within 5–10 s of a result sets a value on an unmounted component. Clearing them in |
|
Correction to my review above: the branch adds 17 i18n keys, not 18. Comparing leaf paths between base and branch |
✅ SSOT Configuration Compliance: Passing🎉 No new hardcoded values of either class — Known backlog in |
…asurements, and fold in #16315's auto-hide timer leak (#16313, #16315) The four literals in frontend_fragmentation_ratchet_test.py still pinned this branch's pre-consolidation counts, so the ratchet read its own improvement as a regression: modal 26->25, button_definition_files 102->101, css_rule_declarations 9434->9405, distinct_class_names 5627->5623. TerminalModals' handleError/handleSuccess auto-hide timers were never tracked or cleared: a component unmounted mid-window still wrote to a torn-down ref, and a second message in the same slot could be blanked early by the first message's own timer. Folded in per #16315 (filed as a same-file review nit on this PR, to avoid a re-push during the merge-train freeze): each message slot's timer is tracked in a Map, a new message cancels its slot's pending timer, and onBeforeUnmount clears whatever is left. Closes #16315.
|
Root-caused the shard 4/12 red: this PR's own consolidation work lowered four measured counts below the pinned ratchet baseline in Also folded in #16315 (same-file review nit, filed to avoid a re-push during the merge-train freeze): Pushed as 54eb554. |
|
Content review: approve. Real correctness fix, not just a refactor: the old The folded-in #16315 fix is sound: per-slot ( Fragmentation ratchet moves are all in the shrinking direction (distinct_class_names 5627→5623, css_rule_declarations 9434→9405, modal 26→25, button_definition_files 102→101) — consistent with deleting the duplicated inline modal markup TerminalWindow used to carry alongside the unused TerminalModals component. closingIssuesReferences=[16285,16315], matches its own two |
Closes #16285. Closes #16315 (folded in, see below). Refs #16253, #16274 and #16312 (found while fixing this).
Thinking Path
TerminalModals.vuewas an extraction of TerminalWindow's four confirmation modals, but nothing rendered it. It reported every action as a success after a fixedsetTimeout(six "Simulate async operation" sites), and it raced each action against a deadline timer that it never cleared.executeConfirmedCommandandconfirmWorkflowStepnow await the send (executeCommandandexecuteAutomatedCommandreturnsendInput's promise).confirmEmergencyKilllogs the failure to the terminal, then rethrows it.reconnectFromModal, which closes the modal only once connected and rejects with the connection error.withTimeoutlands here as its first consumer (AC4). It's the utility drafted for canonical(frontend): SystemStatusDetails is declared three times, and SystemAlert twice with no importers #16253, atautobot-frontend/src/utils/withTimeout.ts. canonical(frontend): SystemStatusDetails is declared three times, and SystemAlert twice with no importers #16253 will import it rather than add it. When it rebases, it drops its own copy and its test, and a grep confirms a single definition.What Changed
components/terminal/TerminalWindow.vue<TerminalModals>instead of the inline reconnect, command, kill and legacy workflow-step modals, which are removed.pulse-success,pulse,blink,flash) are each still used.showLegacyModal, which they never did before.components/terminal/TerminalModals.vuereconnectAction,executeCommandAction,emergencyKillAction,confirmStepAction,skipStepAction,manualControlAction.runActiondoeswithTimeout(Promise.resolve().then(action), …). It reports success only after the action settles, and shows the error otherwise.utils/withTimeout.ts, plus its test (see above).terminal.modalskeys, translated in every locale.terminal.windowkeys that only the removed inline modals used. A grep finds no other reference to them.repo_tests/i18n_untranslated_ratchet_test.pyTerminalModals.stories.ts: meta-level args supply actions that resolve.handleError/handleSuccess's auto-hidesetTimeouts were never tracked, so an unmount mid-window still fired into a disposed ref, and a second message in the same slot could be blanked early by the first message's own timer. Each of the 8 message refs (error/success × connection/command/kill/workflow) now has its own tracked timer in aMap; a new message cancels its own slot's pending timer viaActionRun.slot, andonBeforeUnmountclears whatever is left.issue-16315-terminal-modal-timers) also targets fix(terminal): TerminalModals' message auto-hide timers are never cleared, on unmount or when a newer message replaces them #16315, filed againstDev_new_guibefore this PR'srunAction/withTimeoutrewrite of these handlers landed. Its diff and test (.aui-dialog-actionsbutton indices, a hand-rolledPromise.racetimeout, and fix(terminal): TerminalModals' action-timeout race leaves the loser's setTimeout uncleared #16395's now-superseded guard timer) no longer match this file's current shape. This PR supersedes it.components/__tests__/TerminalModals.test.ts(new):withTimeoutdeadline (AC4);components/__tests__/TerminalWindow.test.ts:Verification
Acceptance criteria, read from the pushed branch:
<TerminalModals>.modal-overlay,confirmation-modal,btn-danger,risk-levelandpulse-dangerhave 0 matches inTerminalWindow.vue.TerminalModals.vue.withTimeout(call is inrunAction, which all six actions go through, andexport function withTimeoutexists once inautobot-frontend/src.autobot-frontend/src/components/terminal/TerminalModals.vue):scheduleAutoHideclearsautoHideTimers.get(slotKey)before arming a new one;ActionRun.slotthreads a distinct key ('connection'|'command'|'kill'|'workflow') to each of the four action families'handleError/handleSuccesscalls.onBeforeUnmount": present, iteratesautoHideTimers.values()and clears each.vi.getTimerCount() === 0after unmount with a message showing":TerminalModals.test.ts::'clears every pending auto-hide timer on unmount (#16315)'.TerminalModals.test.ts::"a later message in the same slot outlives the earlier message's auto-hide timer (#16315)".CI is the evidence for vitest, vue-tsc and the ratchet. The repo's pre-commit and pre-push hooks ran on the commit.
Out of scope: #16312. The legacy workflow-step modal can never open: nothing sets
showLegacyModal, and nothing readsisAdvancedMode.Model Used
Claude Opus 5 (
claude-opus-5)