mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-07 17:09:13 -10:00
fix(mobile): retire approval cards decided elsewhere or timed out (CW-6880)
The mobile page kept live Allow/Deny buttons on an approval card after the approval was decided from another client, cancelled by a turn teardown, or timed out; pressing one then failed against a request that no longer existed. Each card's actions now carry the approval id, and an `approval.decided` or `approval.timeout` event for that id replaces the buttons with "Decided: <decision>", "Cancelled" or "Timed out". Cards for other approvals are untouched. This is only the card-retirement item of CW-6880. Scope buttons, owner labels, snapshot rebuild of pending approvals, the sticky banner and notifications remain open there. Verification on this tree: - Real headless Chrome (playwright-core driving Google Chrome) against the page with the stream-messages token filled: four required cards; decided, timed-out and cancelled ids lost their buttons with the expected labels; the fourth card and an unknown id were unaffected; no page errors. - Existing mobile tests, including the QuickJS evaluation of the page script (mobile_stream_statuses_use_selected_locale): 11 run, 11 passed, 15340 skipped. - npm test: 547 Node tests (540 passed, 7 skipped, 0 failed) and 772 Vitest passed. npm run check:web: exit 0. - Not run: a paired phone against a live Runtime. Refs CW-6880, #6474 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NBKbhx19BRbZtvWK8rVKjz
This commit is contained in:
1 parent
8a659250aa
commit
b457a8affd
1 file changed
+16
@@ -572,6 +572,20 @@
|
||||
return { id: approvalId };
|
||||
}
|
||||
|
||||
function retireApproval(name, data) {
|
||||
if (name !== "approval.decided" && name !== "approval.timeout") return;
|
||||
const payload = eventPayload(data) || {};
|
||||
const approvalId = payload.approval_id || payload.id;
|
||||
if (!approvalId) return;
|
||||
const label = name === "approval.timeout"
|
||||
? "Timed out"
|
||||
: payload.cancelled ? "Cancelled" : "Decided: " + (payload.decision || "decided");
|
||||
for (const actions of document.querySelectorAll(".approval-actions")) {
|
||||
if (actions.dataset.approvalId !== String(approvalId)) continue;
|
||||
actions.innerHTML = "<span class='meta'>" + escapeHtml(label) + "</span>";
|
||||
}
|
||||
}
|
||||
|
||||
function pruneVisibleEvents() {
|
||||
const events = $("events");
|
||||
while (events.childElementCount > MAX_VISIBLE_EVENTS) {
|
||||
@@ -597,6 +611,7 @@
|
||||
|
||||
function appendEvent(name, data) {
|
||||
noteAgentEvent(name, data);
|
||||
retireApproval(name, data);
|
||||
const text = eventText(name, data);
|
||||
if (!text) return;
|
||||
const item = document.createElement("div");
|
||||
@@ -612,6 +627,7 @@
|
||||
if (approval) {
|
||||
const actions = document.createElement("div");
|
||||
actions.className = "approval-actions";
|
||||
actions.dataset.approvalId = String(approval.id);
|
||||
const allow = document.createElement("button");
|
||||
allow.className = "primary";
|
||||
allow.textContent = "Allow";
|
||||
|
||||
Reference in new issue
Block a user