From 8fff6dae8070a675e9603cf6f0bd42b2b0c4bc91 Mon Sep 17 00:00:00 2001 From: Hayt <41ea58f1e64c243627e8acde7c89be667052ee6e17d8f021c1195be4324ebf04@buzz.block.builderlab.xyz> Date: Wed, 12 Aug 2026 23:03:30 -0400 Subject: [PATCH] fix(desktop): navigable processing rows, honest feedback status, relay-scoped nav gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close the desktop half of Thufir's #4768 pass-1 findings that need no relay change. The relay-contract consumption (canonical action DTO, real cancel route) waits on #3777. Processing report rows were disabled in the list, but the enforcement progress/retry/cancel UI lives only inside the detail view — so the row was locked exactly when an operator needs to inspect a pending or failed action. Keep processing rows navigable; the detail view already suppresses the resolve form for any non-open report. Feedback triage `status` was optional on the wire types and silently defaulted to "new" when absent, misreporting a reviewed/archived entry as new after reload. Make `status` required on both feedback DTOs and read it directly, and type PATCH's actual `{status}` echo instead of claiming a full summary record. The Moderation nav resolver keyed its 60s cache on pubkey alone, but NIP-11 discovery is relay-dependent — a workspace switch could serve the previous relay's verdict. Key the resolver on the connected relay origin (and gate its `enabled` on a resolved origin), and defer the `?section=moderation` invalid-section redirect while the resolver is unresolved so a direct link is not bounced before the probe can authorize. Co-authored-by: Will Pfleger Signed-off-by: Will Pfleger --- .../admin-console/AdminConsoleFeedbackTab.tsx | 20 +- .../admin-console/AdminConsolePanel.tsx | 15 +- .../admin-console/adminConsolePanel.test.mjs | 67 ------ .../adminConsolePanelEvents.jsdom-test.mjs | 205 ++++++++++++++++++ desktop/src/features/admin-console/api.ts | 18 +- .../src/features/admin-console/hooks.test.mjs | 49 +++++ desktop/src/features/admin-console/hooks.ts | 22 +- .../src/features/settings/ui/SettingsView.tsx | 10 +- 8 files changed, 307 insertions(+), 99 deletions(-) create mode 100644 desktop/src/features/admin-console/hooks.test.mjs diff --git a/desktop/src/features/admin-console/AdminConsoleFeedbackTab.tsx b/desktop/src/features/admin-console/AdminConsoleFeedbackTab.tsx index 2ff1292dbd..a0e88f7022 100644 --- a/desktop/src/features/admin-console/AdminConsoleFeedbackTab.tsx +++ b/desktop/src/features/admin-console/AdminConsoleFeedbackTab.tsx @@ -93,7 +93,7 @@ export function FeedbackTab({ >
{text} - {status && status !== "new" && ( + {status !== "new" && ( {status} @@ -321,7 +321,7 @@ function FeedbackStatusControl({ onStatusChanged, }: { feedbackId: string; - currentStatus: AdminFeedbackStatus | null | undefined; + currentStatus: AdminFeedbackStatus | null; origin: string; onStatusChanged: (newStatus: AdminFeedbackStatus) => void; }) { @@ -391,9 +391,9 @@ export function FeedbackDetail({ onBack: () => void; }) { // Local status state: initialized from server, updated on PATCH. - const [localStatus, setLocalStatus] = useState< - AdminFeedbackStatus | null | undefined - >(undefined); + const [localStatus, setLocalStatus] = useState( + null, + ); const detailState: AsyncState = useAsyncLoad( () => getAdminFeedback(origin, feedbackId), @@ -402,16 +402,12 @@ export function FeedbackDetail({ ); // Sync localStatus from server data on load (but not on every re-render). + // `status` is a required wire field — read it directly, never default a + // missing value to "new" (that would misreport a reviewed/archived entry). // biome-ignore lint/correctness/useExhaustiveDependencies: intentional — sync once when data arrives useEffect(() => { if (detailState.status === "ok") { - setLocalStatus( - ( - detailState.data as AdminFeedbackDto & { - status?: AdminFeedbackStatus; - } - ).status ?? "new", - ); + setLocalStatus(detailState.data.status); } }, [detailState.status === "ok"]); diff --git a/desktop/src/features/admin-console/AdminConsolePanel.tsx b/desktop/src/features/admin-console/AdminConsolePanel.tsx index 6695852dab..d28b759ad0 100644 --- a/desktop/src/features/admin-console/AdminConsolePanel.tsx +++ b/desktop/src/features/admin-console/AdminConsolePanel.tsx @@ -591,15 +591,14 @@ function ReportsTab({ const isProcessing = status === "processing"; return (
  • + {/* Processing rows stay navigable: the enforcement state (progress, + retry, cancel) lives inside the detail view, so disabling the row + would hide exactly the controls an operator needs while an action + is pending. Detail suppresses only the resolve form for a + non-open report. */}