From fd4cd2ac9ce54976fcb6057a0f0d981d03019a14 Mon Sep 17 00:00:00 2001 From: jay Date: Mon, 8 Jun 2026 15:16:46 -0400 Subject: [PATCH] Admin: inline flag-reason popover (replaces prompt()) Per Codex's polish note: flagging a source now opens a small inline popover for the optional reason (consistent with the calm admin UI) instead of a native prompt(). Clearing a flag stays immediate. Backdrop/Escape/Cancel close it; Enter confirms. Optimistic with revert-on-failure, like the other actions. Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/routes/admin/+page.svelte | 76 +++++++++++++++++++++----- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/frontend/src/routes/admin/+page.svelte b/frontend/src/routes/admin/+page.svelte index 896747a..5b8453c 100644 --- a/frontend/src/routes/admin/+page.svelte +++ b/frontend/src/routes/admin/+page.svelte @@ -84,18 +84,24 @@ try { await postJSON(`/api/admin/sources/${s.id}/active`, { active: next }); } catch { s.active = next ? 0 : 1; } } - async function toggleReview(s) { - if (s.review_flag) { - const prevR = s.review_reason; - s.review_flag = 0; s.review_reason = null; - try { await postJSON(`/api/admin/sources/${s.id}/review`, { flag: false }); } - catch { s.review_flag = 1; s.review_reason = prevR; } - } else { - const reason = (prompt('Flag this source for review — optional note:') || '').trim(); - s.review_flag = 1; s.review_reason = reason || null; - try { await postJSON(`/api/admin/sources/${s.id}/review`, { flag: true, reason: reason || null }); } - catch { s.review_flag = 0; s.review_reason = null; } - } + // Flagging opens a small inline popover for the reason; clearing is immediate. + let flagging = $state(null); // the source being flagged + let flagReason = $state(''); + function openFlag(s) { flagging = s; flagReason = ''; } + function cancelFlag() { flagging = null; flagReason = ''; } + async function confirmFlag() { + const s = flagging; + const reason = flagReason.trim() || null; + s.review_flag = 1; s.review_reason = reason; // optimistic + flagging = null; flagReason = ''; + try { await postJSON(`/api/admin/sources/${s.id}/review`, { flag: true, reason }); } + catch { s.review_flag = 0; s.review_reason = null; } + } + async function clearReview(s) { + const prevR = s.review_reason; + s.review_flag = 0; s.review_reason = null; // optimistic + try { await postJSON(`/api/admin/sources/${s.id}/review`, { flag: false }); } + catch { s.review_flag = 1; s.review_reason = prevR; } } // Feedback inbox: filter + read/unread + delete. @@ -322,7 +328,7 @@ - + {/each} @@ -465,6 +471,27 @@ {/if} +{#if flagging} + + + +{/if} +