diff --git a/frontend/src/components/shared/confirmation-dialog.tsx b/frontend/src/components/shared/confirmation-dialog.tsx index da12862a..1ec2bacb 100644 --- a/frontend/src/components/shared/confirmation-dialog.tsx +++ b/frontend/src/components/shared/confirmation-dialog.tsx @@ -46,13 +46,19 @@ function ConfirmationDialog({ isOpen, itemName = 'this', itemType = 'item', - title = 'Confirm Action', + title, }: ConfirmationDialogProps) { const [isProcessing, setIsProcessing] = useState(false); + // Derive a contextual title from confirm verb + item type so callers don't + // see "Confirm Action" for a Delete prompt or a Save prompt. Explicit + // `title` always wins. + const verb = confirmText.trim(); + const resolvedTitle = title ?? (verb && verb !== 'Confirm' ? `${verb} ${itemType}` : 'Confirm Action'); + const defaultDescription = description || ( <> - Are you sure you want to perform this action on{' '} + Are you sure you want to {verb.toLowerCase() || 'perform this action on'}{' '} {itemName} {itemType}? ); @@ -102,7 +108,7 @@ function ConfirmationDialog({ > - {title} + {resolvedTitle} {defaultDescription} diff --git a/frontend/src/components/ui/sidebar.tsx b/frontend/src/components/ui/sidebar.tsx index 335ed4e7..efe1c335 100644 --- a/frontend/src/components/ui/sidebar.tsx +++ b/frontend/src/components/ui/sidebar.tsx @@ -94,9 +94,15 @@ function Sidebar({ {...props} > { const handleKeyDown = (event: KeyboardEvent) => { - if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) { - event.preventDefault(); - toggleSidebar(); + if (event.key !== SIDEBAR_KEYBOARD_SHORTCUT || !(event.metaKey || event.ctrlKey)) { + return; } + + const target = event.target as HTMLElement | null; + + if (target) { + const tag = target.tagName; + + if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable) { + return; + } + } + + event.preventDefault(); + toggleSidebar(); }; window.addEventListener('keydown', handleKeyDown); diff --git a/frontend/src/pages/settings/settings-api-tokens.tsx b/frontend/src/pages/settings/settings-api-tokens.tsx index 30dacc84..2f9a7bbc 100644 --- a/frontend/src/pages/settings/settings-api-tokens.tsx +++ b/frontend/src/pages/settings/settings-api-tokens.tsx @@ -646,7 +646,11 @@ function SettingsAPITokens() { variant="outline" > - {field.value ? field.value.toLocaleDateString() : Pick date} + {field.value ? ( + format(field.value, 'd MMM yyyy', { locale: enUS }) + ) : ( + Pick date + )} [ { accessorKey: 'name', - cell: ({ row }) =>
{row.getValue('name')}
, + cell: ({ row }) =>
{row.getValue('name')}
, enableHiding: false, header: ({ column }) => ( ), + // Name flexes to fill remaining width — fixed `size` would push + // the Type column off-screen on narrow viewports (e.g. 375px). meta: { searchable: true }, - size: 400, }, { accessorKey: 'type', cell: ({ row }) => { const providerType = row.getValue('type') as ProviderType; const Icon = providerIcons[providerType]; + const label = providerTypes.find((p) => p.type === providerType)?.label || providerType; return ( - - {Icon && } - {providerTypes.find((p) => p.type === providerType)?.label || providerType} + + {Icon && } + {label} ); }, @@ -166,6 +171,7 @@ function SettingsProviders() { /> ), meta: { searchable: true }, + minSize: 110, size: 160, }, { diff --git a/frontend/src/pages/templates/template.tsx b/frontend/src/pages/templates/template.tsx index ee13fecf..4b35139c 100644 --- a/frontend/src/pages/templates/template.tsx +++ b/frontend/src/pages/templates/template.tsx @@ -746,6 +746,7 @@ function Template() { /> - {isSaving ? : } + {isSaving ? ( + + ) : ( + diff --git a/frontend/src/providers/flow-provider.tsx b/frontend/src/providers/flow-provider.tsx index e1e2b27f..45898aef 100644 --- a/frontend/src/providers/flow-provider.tsx +++ b/frontend/src/providers/flow-provider.tsx @@ -177,12 +177,18 @@ export function FlowProvider({ children }: FlowProviderProps) { const flowStatus = useMemo(() => flowData?.flow?.status, [flowData?.flow?.status]); - // Show toast notification when flow loading error occurs + // Show toast notification when flow loading error occurs. + // A single Postgres "no rows in result set" surfaces here every time a sibling + // query/subscription retries against an invalid flow id; without a stable + // toast id Sonner would stack 8 copies of the same message before the page + // redirects. Surface a friendly message and drop the raw SQL detail entirely. useEffect(() => { if (flowError) { - const description = flowError.message || 'An error occurred while loading flow'; - toast.error('Failed to load flow', { - description, + const raw = flowError.message ?? ''; + const isNotFound = /no rows in result set|not found/i.test(raw); + toast.error(isNotFound ? 'Flow not found' : 'Failed to load flow', { + description: isNotFound ? undefined : raw || undefined, + id: 'flow-load-error', }); Log.error('Error loading flow:', flowError); }