From 9b1c3fbc3202d9ac78acea2e02bb919f8424db63 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Sai Potteri Date: Wed, 19 Aug 2026 17:18:52 +0530 Subject: [PATCH] fix: hide AI activity panel when monitor unreachable; show access message on form 4xx --- src/components/DetailViewPanel.tsx | 28 ++++++++++++++++------------ src/components/FormModal.tsx | 28 ++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/components/DetailViewPanel.tsx b/src/components/DetailViewPanel.tsx index 30b6153..b2f5584 100644 --- a/src/components/DetailViewPanel.tsx +++ b/src/components/DetailViewPanel.tsx @@ -318,18 +318,22 @@ export default function DetailViewPanel({ viewId, instanceId, onTitle }: Props) )} - - {instance.loading ? ( - - ) : ( - - )} - + {/* Hidden entirely when the monitoring service can't be read — + app-user tokens have no scope on /monitor/*, so for them this + panel can never load. */} + {!instance.aiUnavailable && ( + + {instance.loading ? ( + + ) : ( + + )} + + )} {instance.loading ? ( diff --git a/src/components/FormModal.tsx b/src/components/FormModal.tsx index fbc2647..ef5a091 100644 --- a/src/components/FormModal.tsx +++ b/src/components/FormModal.tsx @@ -24,6 +24,7 @@ import { SelectValue, } from "@/components/ui/select"; import { + ApiError, getFormScreen, performActivity, startWorkflow, @@ -68,11 +69,18 @@ export default function FormModal({ activityId, instanceId, title, onClose, onSu const [succeeded, setSucceeded] = useState(false); const [error, setError] = useState(null); - const { data, isPending } = useQuery({ + const { data, isPending, isError, error: loadError } = useQuery({ queryKey: ["form-screen", activityId, instanceId], queryFn: () => getFormScreen(activityId, instanceId) as Promise, + // A 4xx (no permission / wrong state) won't change on retry. + retry: (count, err) => (err instanceof ApiError && err.status < 500 ? false : count < 1), }); + const loadErrorMessage = + loadError instanceof ApiError && loadError.status === 403 + ? "You don't have access to this form." + : "This form couldn't be loaded. Please try again."; + const fields: FormField[] = data?.fields ?? data?.form_json?.fields ?? []; const gridConfig: GridItem[] = data?.grid_config ?? []; const formTitle = data?.activity_name || title || "Form"; @@ -234,6 +242,14 @@ export default function FormModal({ activityId, instanceId, title, onClose, onSu ))} + ) : isError ? ( +
+ + {loadErrorMessage} +
) : (
{rows.map((row, ri) => ( @@ -300,9 +316,17 @@ export default function FormModal({ activityId, instanceId, title, onClose, onSu )} + {isError && ( + + + + )} + {/* mx-0/mb-0 cancel DialogFooter's default negative margins, which assume the content keeps its own padding — this dialog is p-0. */} - {!isPending && ( + {!isPending && !isError && (

* Required