@burdenoff/microfe-bigconsole 2026.924.1 → 2026.924.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bigconsole/BigConsoleRoutes.js +137 -138
- package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
- package/dist/bigconsole/assistant/previewController.js +10 -10
- package/dist/bigconsole/assistant/useAssistantPanelShowsPreview.js +25 -0
- package/dist/bigconsole/assistant/useAssistantPanelShowsPreview.js.map +1 -0
- package/dist/bigconsole/components/DrilldownDashboardRenderer.js +17 -17
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +32 -32
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +52 -52
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +7 -7
- package/dist/bigconsole/components/dashboard/DashboardStatusPill.js +53 -0
- package/dist/bigconsole/components/dashboard/DashboardStatusPill.js.map +1 -0
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +60 -60
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +21 -21
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +30 -30
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +36 -36
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +34 -34
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +38 -38
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +121 -121
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +22 -22
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +46 -46
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +53 -53
- package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -1
- package/dist/bigconsole/components/dashboard/WidgetPalette.js +47 -47
- package/dist/bigconsole/components/dashboard/index.js +1 -0
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +35 -35
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +18 -18
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +20 -20
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +30 -29
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +48 -48
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +103 -103
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +35 -35
- package/dist/bigconsole/components/overview/DashboardGuide.js +214 -0
- package/dist/bigconsole/components/overview/DashboardGuide.js.map +1 -0
- package/dist/bigconsole/components/overview/DataHealthCard.js +97 -0
- package/dist/bigconsole/components/overview/DataHealthCard.js.map +1 -0
- package/dist/bigconsole/components/overview/OverviewQuickActions.js +32 -0
- package/dist/bigconsole/components/overview/OverviewQuickActions.js.map +1 -0
- package/dist/bigconsole/components/overview/OverviewStatCard.js +57 -0
- package/dist/bigconsole/components/overview/OverviewStatCard.js.map +1 -0
- package/dist/bigconsole/components/overview/RecentDashboardsPanel.js +107 -0
- package/dist/bigconsole/components/overview/RecentDashboardsPanel.js.map +1 -0
- package/dist/bigconsole/components/overview/dashboardGuideSteps.js +119 -0
- package/dist/bigconsole/components/overview/dashboardGuideSteps.js.map +1 -0
- package/dist/bigconsole/components/overview/index.js +8 -0
- package/dist/bigconsole/components/overview/overviewModel.js +119 -0
- package/dist/bigconsole/components/overview/overviewModel.js.map +1 -0
- package/dist/bigconsole/components/overview/useOverviewData.js +48 -0
- package/dist/bigconsole/components/overview/useOverviewData.js.map +1 -0
- package/dist/bigconsole/components/parser/DataSinkSelector.js +40 -40
- package/dist/bigconsole/components/parser/ImportParserDialog.js +127 -127
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +51 -51
- package/dist/bigconsole/components/preview/AiPreviewContent.js +5 -5
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +62 -61
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +82 -81
- package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +13 -13
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +70 -70
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +28 -28
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +25 -25
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js +48 -48
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +46 -46
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +61 -61
- package/dist/bigconsole/components/widgets/form/FormWidget.js +36 -36
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +42 -42
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +25 -25
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +21 -21
- package/dist/bigconsole/components/widgets/list/ListConfig.js +30 -30
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +38 -38
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +9 -9
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +9 -9
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +49 -49
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +39 -39
- package/dist/bigconsole/components/widgets/table/TableConfig.js +73 -73
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +64 -64
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +10 -10
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +68 -68
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
- package/dist/bigconsole/pages/AdminPage.js +136 -136
- package/dist/bigconsole/pages/DashboardBuilderPage.js +10 -10
- package/dist/bigconsole/pages/DashboardViewPage.js +61 -61
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +327 -348
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +5 -5
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +10 -10
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +83 -83
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +11 -11
- package/dist/bigconsole/pages/DataSourcesPage.js +5 -5
- package/dist/bigconsole/pages/InsightsPage.js +315 -315
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/OverviewPage.js +244 -0
- package/dist/bigconsole/pages/OverviewPage.js.map +1 -0
- package/dist/bigconsole/pages/ParserBuilderPage.js +5 -5
- package/dist/bigconsole/pages/ParserViewPage.js +98 -98
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +8 -8
- package/dist/bigconsole/pages/PipelineViewPage.js +46 -46
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +80 -80
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/SettingsPage.js +70 -70
- package/dist/bigconsole/pages/WidgetDemoPage.js +42 -42
- package/dist/bigconsole/pages/WorkflowViewPage.js +200 -200
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +78 -78
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +34 -34
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +79 -79
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js +46 -46
- package/dist/bigconsole/utils/createDialogParam.js +14 -0
- package/dist/bigconsole/utils/createDialogParam.js.map +1 -0
- package/dist/generated/global-operations.js +1 -1
- package/dist/generated/wspace-operations.js +285 -222
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/shared/hooks/useTr.js +10 -7
- package/dist/shared/hooks/useTr.js.map +1 -1
- package/package.json +1 -1
- package/dist/bigconsole/pages/HomePage.js +0 -318
- package/dist/bigconsole/pages/HomePage.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowViewPage.js","names":[],"sources":["../../../src/bigconsole/pages/WorkflowViewPage.tsx"],"sourcesContent":["/**\n * Workflow View Page\n *\n * Page for viewing FluidGrids Workflow details, linked DataSinks,\n * read-only workflow design preview, and real execution with polling.\n *\n * Section hierarchy (BOFF-5634):\n * - header (back link + identity + actions) ... `bare`\n * - execution result ......................... `standard` + success/danger tone\n * - \"Workflow design\" (the node canvas) ...... `primary` — the thing the route is about\n * - \"Execution stats\" ........................ `standard`, promoted to `primary` when the\n * workflow has no design preview to show\n * - \"Description\" / \"Webhook trigger\" /\n * \"Record history\" ......................... `muted` — supporting detail\n * - \"Linked data sinks\" ...................... `standard`\n * Exactly one `primary` renders in every branch.\n */\n\nimport { memo, useState, useEffect, useCallback } from 'react';\nimport { useParams } from 'react-router';\nimport { Button, IllustratedEmptyState, PagePurpose, NextSteps, Spinner } from '@burdenoff/fe-libs/ui';\nimport type { NextStep } from '@burdenoff/fe-libs/ui';\nimport { Section, SectionStack, SECTION_FOCUS_RING, sectionSurfaceClasses } from '../components/common';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeCopyText, nativeNotify, nativeToast } from '../../utils/nativeBridge';\nimport { useBigConsole } from '../context';\nimport { formatDistanceToNow } from 'date-fns';\nimport { useWorkflowOperations } from '../hooks/useWorkflowOperations';\nimport { WorkflowStatusBadge } from '../components/workflow/WorkflowStatusBadge';\nimport { WorkflowDeleteDialog } from '../components/workflow/WorkflowDeleteDialog';\nimport type { FluidGridsWorkflow } from '../types';\n\n// FluidGrids FE SDK — read-only embedded builder preview\nimport { WorkflowBuilder } from '@burdenoff/fluidgrids-fe-sdk';\nimport { BOOTSTRAP_RETRY_DELAY_MS } from '../constants';\n\n// RBAC\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { AccessDenied, PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst ArrowLeftIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n);\n\nconst EditIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n);\n\nconst TrashIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n);\n\nconst PlayIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\n />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n);\n\nconst CopyIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n);\n\nconst CheckIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n);\n\nconst DatabaseIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\"\n />\n </svg>\n);\n\nconst ChevronDownIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowViewPage = memo(function WorkflowViewPage() {\n const navigate = useAppNavigate();\n const { t } = useI18n();\n const { workflowId } = useParams<{ workflowId: string }>();\n\n // BigConsole context for apiGatewayUrl and authToken\n const { apiGatewayUrl, authToken, workspaceId } = useBigConsole();\n\n // RBAC\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_READ);\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_UPDATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_DELETE);\n const canExecute = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_EXECUTE);\n\n // Local state\n const [workflow, setWorkflow] = useState<FluidGridsWorkflow | null>(null);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [, setIsDeleting] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n const [webhookCopied, setWebhookCopied] = useState(false);\n const [showDesignPreview, setShowDesignPreview] = useState(false);\n // Track whether initial fetch has completed — prevents \"not found\" flash\n // before data has even been requested (loading starts as false with skipFetch: true)\n const [isReady, setIsReady] = useState(false);\n const [executionResult, setExecutionResult] = useState<{\n success: boolean;\n output: unknown;\n error: string | null;\n executionTimeMs: number;\n runId?: string;\n } | null>(null);\n\n // Operations\n const { loading, error, fetchWorkflow, deleteWorkflow, executeWorkflow, pollWorkflowExecution } =\n useWorkflowOperations({\n skipFetch: true,\n });\n\n // Load workflow on mount.\n // On a full page reload the workspace token may not be issued yet when this\n // effect first runs, causing the gateway to lack workspace context and\n // the resolver to return null. We retry once after a short delay to give\n // the auth bootstrap time to complete.\n useEffect(() => {\n if (!workflowId) {\n setIsReady(true);\n return;\n }\n\n let cancelled = false;\n\n const load = async (attempt: number) => {\n try {\n const result = await fetchWorkflow(workflowId);\n if (cancelled) return;\n\n if (result) {\n setWorkflow(result);\n setIsReady(true);\n } else if (attempt === 0) {\n // First attempt failed — likely workspace token race on full-page load.\n // Retry once after a short delay.\n setTimeout(() => {\n if (!cancelled) load(1);\n }, BOOTSTRAP_RETRY_DELAY_MS);\n } else {\n // Second attempt also failed — genuinely not found\n setIsReady(true);\n }\n } catch {\n // Network error, GraphQL error, etc. — surface the \"not found\" UI\n // rather than spinning forever with no escape hatch.\n if (!cancelled) setIsReady(true);\n }\n };\n\n load(0);\n return () => {\n cancelled = true;\n };\n }, [workflowId, fetchWorkflow]);\n\n // Handlers\n const handleBack = useCallback(() => {\n navigate(`/workflows`);\n }, [navigate]);\n\n const handleEdit = useCallback(() => {\n navigate(`/workflows/${workflowId}/edit`);\n }, [navigate, workflowId]);\n\n const handleDelete = useCallback(async () => {\n if (!workflowId) return;\n setIsDeleting(true);\n try {\n const success = await deleteWorkflow(workflowId);\n if (success) {\n if (isNative()) void nativeNotify('success');\n navigate(`/workflows`);\n } else if (isNative()) {\n void nativeNotify('error');\n }\n } catch {\n if (isNative()) void nativeNotify('error');\n } finally {\n setIsDeleting(false);\n setShowDeleteConfirm(false);\n }\n }, [workflowId, deleteWorkflow, navigate]);\n\n const handleExecute = useCallback(async () => {\n if (!workflowId) return;\n setIsExecuting(true);\n setExecutionResult(null);\n\n const startTime = Date.now();\n\n try {\n const result = await executeWorkflow(workflowId);\n\n if (result) {\n const executionTimeMs = Date.now() - startTime;\n\n // If workflow has external FluidGrids ID, the execution is async\n if (result.externalWorkflowId) {\n setExecutionResult({\n success: true,\n output: {\n externalWorkflowId: result.externalWorkflowId,\n executionCount: result.executionCount,\n status: t('bigconsole.workflows.view.executionTriggeredPolling', 'Triggered — polling for completion...'),\n },\n error: null,\n executionTimeMs,\n });\n\n // Poll for completion in the background\n pollWorkflowExecution(workflowId, {\n intervalMs: 3000,\n timeoutMs: 120000,\n onProgress: (updated) => {\n setWorkflow(updated);\n },\n }).then((final) => {\n if (final) {\n setWorkflow(final);\n setExecutionResult((prev) =>\n prev\n ? {\n ...prev,\n output: {\n ...((prev.output as Record<string, unknown>) || {}),\n status:\n final.status === 'error'\n ? t('bigconsole.workflows.view.executionStatusFailed', 'Failed')\n : t('bigconsole.workflows.view.executionStatusCompleted', 'Completed'),\n executionCount: final.executionCount,\n lastExecutedAt: final.lastExecutedAt,\n },\n executionTimeMs: Date.now() - startTime,\n }\n : prev\n );\n }\n });\n } else {\n // Local execution (no external FluidGrids workflow)\n setExecutionResult({\n success: true,\n output: {\n executionCount: result.executionCount,\n lastExecutedAt: result.lastExecutedAt,\n status: t('bigconsole.workflows.view.executionStatusCompleted', 'Completed'),\n },\n error: null,\n executionTimeMs,\n });\n }\n\n // Refresh workflow\n const updated = await fetchWorkflow(workflowId);\n if (updated) {\n setWorkflow(updated);\n }\n }\n } catch (err) {\n setExecutionResult({\n success: false,\n output: null,\n error:\n err instanceof Error ? err.message : t('bigconsole.workflows.errors.executionFailed', 'Execution failed'),\n executionTimeMs: Date.now() - startTime,\n });\n } finally {\n setIsExecuting(false);\n }\n }, [workflowId, executeWorkflow, fetchWorkflow, pollWorkflowExecution, t]);\n\n const handleCopyWebhook = useCallback(async () => {\n if (!workflow?.webhookUrl) return;\n try {\n await nativeCopyText(workflow.webhookUrl);\n setWebhookCopied(true);\n if (isNative()) void nativeToast(t('bigconsole.workflows.view.webhookCopiedToast', 'Webhook copied'));\n setTimeout(() => setWebhookCopied(false), 2000);\n } catch {\n // Clipboard not available\n }\n }, [workflow?.webhookUrl, t]);\n\n const handleViewDataSink = useCallback(\n (dataSinkId: string) => {\n navigate(`/datasinks/${dataSinkId}`);\n },\n [navigate]\n );\n\n // Back-to-list control — identical on the not-found branch and the loaded page,\n // so \"where am I\" reads the same however the route resolves.\n const backLink = (\n <button\n type=\"button\"\n onClick={handleBack}\n className={`inline-flex min-h-[var(--size-controlHeight-md)] items-center gap-1 rounded-button text-sm text-text-secondary motion-safe:transition-colors hover:text-text-primary ${SECTION_FOCUS_RING}`}\n >\n <ArrowLeftIcon className=\"w-4 h-4\" />\n {t('bigconsole.workflows.view.backToWorkflows', 'Back to Workflows')}\n </button>\n );\n\n // Loading state — show spinner until initial fetch completes OR during a\n // refetch, and while permissions are still loading (avoids a read-gate flash).\n if (!isReady || (loading && !workflow) || permissionsLoading) {\n return (\n <div className=\"mx-auto flex min-h-[400px] max-w-5xl items-center justify-center p-4 sm:p-[var(--space-pagePadding)]\">\n <Spinner size=\"lg\" />\n </div>\n );\n }\n\n // Read gate — no permission to view this workflow\n if (!canRead) {\n return (\n <AccessDenied\n title={t('bigconsole.workflows.errors.accessDeniedTitle', 'Access Denied')}\n description={t(\n 'bigconsole.workflows.errors.accessDeniedViewDescription',\n \"You don't have permission to view this workflow.\"\n )}\n />\n );\n }\n\n // Error or not found state — only shown AFTER initial fetch completed\n if (error || !workflow) {\n return (\n <div className=\"mx-auto max-w-5xl p-4 sm:p-[var(--space-pagePadding)]\">\n <SectionStack>\n <div>{backLink}</div>\n {/* Same surface the list page gives its empty states, so \"nothing to\n show\" looks the same wherever you hit it. */}\n <section\n aria-label=\"Workflow not found\"\n data-section-emphasis=\"standard\"\n data-testid=\"workflow-not-found\"\n className={sectionSurfaceClasses('standard')}\n >\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('bigconsole.workflows.view.notFoundTitle', 'Workflow not found')}\n description={\n error?.message ||\n t('bigconsole.workflows.view.notFoundDescription', 'The workflow you are looking for does not exist.')\n }\n />\n </section>\n </SectionStack>\n </div>\n );\n }\n\n const linkedDataSinkCount = workflow.dataSinkLinks?.length || 0;\n // The read-only canvas is the point of this route when it exists; when it does\n // not, the execution numbers become the page's single `primary` block.\n const hasDesignPreview = Boolean(workflow.externalWorkflowId);\n\n // Next-step guidance — omit steps that trigger a gated action the caller\n // cannot perform (execute → WORKFLOW_EXECUTE, edit → WORKFLOW_UPDATE).\n const nextSteps: NextStep[] = [\n ...(canExecute\n ? [\n {\n id: 'execute',\n label: t('bigconsole.workflows.view.nextStepExecuteLabel', 'Run the workflow'),\n description: t(\n 'bigconsole.workflows.view.nextStepExecuteDescription',\n 'Trigger an execution to pull fresh data now.'\n ),\n onClick: handleExecute,\n },\n ]\n : []),\n {\n id: 'design',\n label: t('bigconsole.workflows.view.nextStepDesignLabel', 'Inspect the design'),\n description: t(\n 'bigconsole.workflows.view.nextStepDesignDescription',\n 'Expand the read-only preview to see each step.'\n ),\n onClick: () => setShowDesignPreview(true),\n },\n ...(canUpdate\n ? [\n {\n id: 'edit',\n label: t('bigconsole.workflows.view.nextStepEditLabel', 'Edit in the builder'),\n description: t(\n 'bigconsole.workflows.view.nextStepEditDescription',\n 'Open the FluidGrids visual builder to change the flow.'\n ),\n onClick: handleEdit,\n },\n ]\n : []),\n {\n id: 'sinks',\n label: t('bigconsole.workflows.view.nextStepSinksLabel', 'Check the linked data sinks'),\n description: t(\n 'bigconsole.workflows.view.nextStepSinksDescription',\n 'See where this workflow writes its output.'\n ),\n onClick: () => navigate('/datasinks'),\n },\n ];\n\n return (\n <div className=\"mx-auto max-w-5xl p-4 sm:p-[var(--space-pagePadding)]\">\n <SectionStack>\n {/* ---------------------------------------------------------------- *\n * Page header — `bare` emphasis: back link, identity and the action\n * cluster. Structural only, so the blocks below own the visual weight.\n * ---------------------------------------------------------------- */}\n <header data-section-emphasis=\"bare\" className=\"min-w-0\">\n <div className=\"mb-form-gap\">{backLink}</div>\n\n <div className=\"flex flex-col gap-form-gap md:flex-row md:items-start md:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-icon-gap\">\n <h1 className=\"break-words text-2xl font-bold text-text-primary\">{workflow.name}</h1>\n <WorkflowStatusBadge status={workflow.status} />\n </div>\n <p className=\"mt-1 break-all font-mono text-sm text-text-secondary\">{workflow.key}</p>\n {workflow.externalWorkflowId && (\n <p className=\"mt-1 text-xs text-text-muted\">\n {t('bigconsole.workflows.view.fluidGridsIdLabel', 'FluidGrids ID:')}{' '}\n <span className=\"break-all font-mono\">{workflow.externalWorkflowId}</span>\n </p>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-control-gap\">\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_EXECUTE} deniedBehavior=\"disable\">\n <Button size=\"lg\" onClick={handleExecute} disabled={isExecuting}>\n <PlayIcon className=\"w-4 h-4\" />\n {isExecuting\n ? t('bigconsole.workflows.actions.executing', 'Executing...')\n : t('bigconsole.workflows.actions.execute', 'Execute')}\n </Button>\n </PermissionButton>\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_UPDATE} deniedBehavior=\"disable\">\n <Button size=\"lg\" variant=\"outline\" onClick={handleEdit}>\n <EditIcon className=\"w-4 h-4\" />\n {t('bigconsole.workflows.actions.edit', 'Edit')}\n </Button>\n </PermissionButton>\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_DELETE} deniedBehavior=\"hide\">\n <Button\n size=\"lg\"\n variant=\"ghost\"\n onClick={() => setShowDeleteConfirm(true)}\n className=\"text-[var(--color-status-error-text)] hover:bg-status-error-bg/10 hover:text-[var(--color-status-error-text)]\"\n >\n <TrashIcon className=\"w-4 h-4\" />\n {t('bigconsole.workflows.actions.delete', 'Delete')}\n </Button>\n </PermissionButton>\n </div>\n </div>\n </header>\n\n <PagePurpose>\n {t(\n 'bigconsole.workflows.view.purpose',\n 'A workflow is the visual ETL job that feeds this BigConsole — it fetches, transforms, and delivers data into linked data sinks. From here you can run it on demand, inspect its design and execution history, copy its webhook trigger, and edit it in the visual builder.'\n )}\n </PagePurpose>\n\n <NextSteps storageKey=\"bigconsole-workflow-view\" steps={nextSteps} />\n\n {/* Execution result — a status section, not a hand-rolled tinted div. */}\n {executionResult && (\n <Section\n headingLevel={2}\n tone={executionResult.success ? 'success' : 'danger'}\n title={\n executionResult.success\n ? t('bigconsole.workflows.view.executionResultTriggered', 'Execution Triggered')\n : t('bigconsole.workflows.view.executionResultFailed', 'Execution Failed')\n }\n description={\n executionResult.success\n ? 'The run was accepted. Results refresh below as the run progresses.'\n : 'The run could not be started. The detail below comes straight from the workflow service.'\n }\n meta={\n <span className=\"rounded-pill bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {executionResult.executionTimeMs}ms\n </span>\n }\n data-testid=\"workflow-execution-result\"\n >\n {executionResult.error ? (\n <p className=\"break-words text-sm text-[var(--color-status-error-text)]\">{executionResult.error}</p>\n ) : (\n <pre className=\"max-h-[200px] min-w-0 overflow-auto rounded-card bg-bg-sunken p-2 font-mono text-xs text-text-secondary\">\n {JSON.stringify(executionResult.output, null, 2)}\n </pre>\n )}\n {executionResult.runId && (\n <p className=\"mt-2 text-xs text-text-muted\">\n {t('bigconsole.workflows.view.runIdLabel', 'Run ID:')}{' '}\n <span className=\"break-all font-mono\">{executionResult.runId}</span>\n </p>\n )}\n </Section>\n )}\n\n {/* Overview row: supporting description beside the run numbers. */}\n <div className=\"grid grid-cols-1 gap-section-gap md:grid-cols-2\">\n <Section\n headingLevel={2}\n emphasis=\"muted\"\n title={t('bigconsole.workflows.view.descriptionLabel', 'Description')}\n description=\"What this workflow is for, as entered by its author.\"\n >\n <p className=\"break-words text-sm text-text-primary\">\n {workflow.description || t('bigconsole.workflows.view.noDescription', 'No description')}\n </p>\n </Section>\n\n <Section\n headingLevel={2}\n emphasis={hasDesignPreview ? 'standard' : 'primary'}\n title={t('bigconsole.workflows.view.executionStatsLabel', 'Execution Stats')}\n description=\"How often this workflow has run, and when it last did.\"\n data-testid=\"workflow-execution-stats\"\n >\n <div className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <p className=\"text-2xl font-bold text-text-primary\">{workflow.executionCount}</p>\n <p className=\"text-xs text-text-secondary\">\n {t('bigconsole.workflows.view.totalExecutionsLabel', 'Total Executions')}\n </p>\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {workflow.lastExecutedAt\n ? formatDistanceToNow(new Date(workflow.lastExecutedAt), { addSuffix: true })\n : t('bigconsole.workflows.view.never', 'Never')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('bigconsole.workflows.view.lastExecutedLabel', 'Last Executed')}\n </p>\n </div>\n </div>\n </Section>\n </div>\n\n {/* Workflow design — the node canvas, the one `primary` block here. */}\n {workflow.externalWorkflowId && (\n <Section\n headingLevel={2}\n emphasis=\"primary\"\n title={t('bigconsole.workflows.view.designPreviewTitle', 'Workflow Design Preview')}\n description=\"The steps this workflow runs, read-only. Open the builder to change them.\"\n actions={\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-expanded={showDesignPreview}\n aria-controls=\"workflow-design-canvas\"\n onClick={() => setShowDesignPreview((prev) => !prev)}\n >\n {showDesignPreview ? 'Hide design' : 'Show design'}\n <ChevronDownIcon\n className={`w-4 h-4 motion-safe:transition-transform ${showDesignPreview ? 'rotate-180' : ''}`}\n />\n </Button>\n }\n data-testid=\"workflow-design-preview\"\n >\n {showDesignPreview ? (\n <div\n id=\"workflow-design-canvas\"\n className=\"h-[320px] min-w-0 overflow-hidden rounded-card border border-[var(--color-border-subtle)] sm:h-[420px] lg:h-[450px]\"\n >\n <WorkflowBuilder\n apiGatewayUrl={apiGatewayUrl}\n workspaceId={workspaceId || 'default'}\n authToken={authToken}\n workflowId={workflow.externalWorkflowId}\n readonly\n hideHeader\n className=\"h-full\"\n />\n </div>\n ) : (\n <p id=\"workflow-design-canvas\" className=\"text-sm text-text-secondary\">\n The canvas is collapsed. Show the design to see every step, its order and its connections.\n </p>\n )}\n </Section>\n )}\n\n {/* Webhook trigger — supporting integration detail. */}\n {workflow.webhookUrl && (\n <Section\n headingLevel={2}\n emphasis=\"muted\"\n title={t('bigconsole.workflows.view.webhookUrlLabel', 'Webhook URL')}\n description=\"POST to this URL to run the workflow from an external system.\"\n actions={\n <Button variant=\"ghost\" size=\"sm\" onClick={handleCopyWebhook}>\n {webhookCopied ? (\n <>\n <CheckIcon className=\"w-4 h-4 text-status-success-text\" />\n {t('bigconsole.workflows.actions.copied', 'Copied!')}\n </>\n ) : (\n <>\n <CopyIcon className=\"w-4 h-4\" />\n {t('bigconsole.workflows.actions.copy', 'Copy')}\n </>\n )}\n </Button>\n }\n >\n <code className=\"block min-w-0 overflow-x-auto break-all rounded-card bg-bg-sunken px-3 py-2 font-mono text-sm text-text-primary\">\n {workflow.webhookUrl}\n </code>\n </Section>\n )}\n\n {/* Linked data sinks — relationships, normal grouped work. */}\n <Section\n headingLevel={2}\n title={t('bigconsole.workflows.view.linkedDataSinksTitle', 'Linked DataSinks ({{count}})', {\n count: linkedDataSinkCount,\n })}\n description=\"Where this workflow writes the data it produces.\"\n data-testid=\"workflow-linked-datasinks\"\n >\n {linkedDataSinkCount === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title={t('bigconsole.workflows.view.noDataSinksTitle', 'No data sinks linked')}\n description={t(\n 'bigconsole.workflows.view.noDataSinksDescription',\n \"This workflow has no data sinks linked yet — its output isn't being stored.\"\n )}\n />\n ) : (\n <ul className=\"flex flex-col gap-list-gap\">\n {workflow.dataSinkLinks?.map((link) => (\n <li\n key={link.id}\n className=\"flex flex-col gap-control-gap rounded-card bg-bg-sunken px-3 py-2 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"flex min-w-0 items-center gap-icon-gap\">\n <DatabaseIcon className=\"w-4 h-4 shrink-0 text-text-secondary\" />\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {link.dataSink?.name || link.dataSink?.key || link.dataSinkId}\n </p>\n {link.dataSink?.key && (\n <p className=\"truncate font-mono text-xs text-text-secondary\">{link.dataSink.key}</p>\n )}\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-control-gap\">\n {link.isEnabled ? (\n <span className=\"rounded-pill bg-[var(--color-status-success-bgSubtle)] px-2 py-0.5 text-xs font-medium text-status-success-text\">\n {t('bigconsole.workflows.view.dataSinkEnabled', 'Enabled')}\n </span>\n ) : (\n <span className=\"rounded-pill bg-bg-surface px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {t('bigconsole.workflows.view.dataSinkDisabled', 'Disabled')}\n </span>\n )}\n <span className=\"text-xs text-text-muted\">\n {t('bigconsole.workflows.view.dataSinkPriority', 'Priority: {{priority}}', {\n priority: link.priority,\n })}\n </span>\n {link.dataSink && (\n <button\n type=\"button\"\n onClick={() => handleViewDataSink(link.dataSinkId)}\n className={`inline-flex min-h-[var(--size-controlHeight-md)] items-center rounded-button px-2 text-xs font-medium text-text-link hover:underline sm:min-h-[var(--size-controlHeight-sm)] ${SECTION_FOCUS_RING}`}\n >\n {t('bigconsole.workflows.actions.view', 'View')}\n </button>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </Section>\n\n {/* Record history — lowest-value metadata, recessed. */}\n <Section headingLevel={2} emphasis=\"muted\" title=\"Record history\" padding=\"compact\">\n <dl className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">{t('bigconsole.workflows.view.createdLabel', 'Created')}</dt>\n <dd className=\"text-sm text-text-primary\">\n {formatDistanceToNow(new Date(workflow.createdAt), { addSuffix: true })}\n </dd>\n <dd className=\"truncate text-xs text-text-muted\">\n {t('bigconsole.workflows.view.byAuthor', 'by {{author}}', { author: workflow.createdBy })}\n </dd>\n </div>\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">\n {t('bigconsole.workflows.view.lastUpdatedLabel', 'Last Updated')}\n </dt>\n <dd className=\"text-sm text-text-primary\">\n {formatDistanceToNow(new Date(workflow.updatedAt), { addSuffix: true })}\n </dd>\n <dd className=\"truncate text-xs text-text-muted\">\n {t('bigconsole.workflows.view.byAuthor', 'by {{author}}', {\n author: workflow.updatedBy || workflow.createdBy,\n })}\n </dd>\n </div>\n </dl>\n </Section>\n </SectionStack>\n\n {/* Delete Confirmation Dialog */}\n {workflow && (\n <WorkflowDeleteDialog\n workflow={workflow}\n isOpen={showDeleteConfirm}\n onClose={() => setShowDeleteConfirm(false)}\n onConfirm={handleDelete}\n />\n )}\n </div>\n );\n});\n\nexport default WorkflowViewPage;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8CA,IAAM,MAAiB,EAAE,mBACvB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAoB,CAAA;CACrF,CAAA,EAGF,MAAY,EAAE,mBAClB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAGF,MAAa,EAAE,mBACnB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAGF,MAAY,EAAE,mBAClB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WAArE,CACE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA,EACF,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAuC,CAAA,CACxG;IAGF,MAAY,EAAE,mBAClB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAGF,MAAa,EAAE,mBACnB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAmB,CAAA;CACpF,CAAA,EAGF,MAAgB,EAAE,mBACtB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAGF,MAAmB,EAAE,mBACzB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAmB,CAAA;CACpF,CAAA,EAOK,IAAmB,EAAK,WAA4B;CAC/D,IAAM,IAAW,GAAgB,EAC3B,EAAE,SAAM,IAAS,EACjB,EAAE,kBAAe,GAAmC,EAGpD,EAAE,kBAAe,cAAW,mBAAgB,GAAe,EAG3D,EAAE,kBAAe,WAAW,MAAuB,IAAgB,EACnE,IAAU,EAAc,EAAuB,cAAc,EAC7D,IAAY,EAAc,EAAuB,gBAAgB;AACrD,GAAc,EAAuB,gBAAgB;CACvE,IAAM,IAAa,EAAc,EAAuB,iBAAiB,EAGnE,CAAC,GAAU,KAAe,EAAoC,KAAK,EACnE,CAAC,GAAmB,KAAwB,EAAS,GAAM,EAC3D,GAAG,KAAiB,EAAS,GAAM,EACnC,CAAC,GAAa,KAAkB,EAAS,GAAM,EAC/C,CAAC,IAAe,KAAoB,EAAS,GAAM,EACnD,CAAC,GAAmB,KAAwB,EAAS,GAAM,EAG3D,CAAC,IAAS,KAAc,EAAS,GAAM,EACvC,CAAC,GAAiB,KAAsB,EAMpC,KAAK,EAGT,EAAE,aAAS,UAAO,kBAAe,mBAAgB,oBAAiB,6BACtE,GAAsB,EACpB,WAAW,IACZ,CAAC;AAOJ,UAAgB;AACd,MAAI,CAAC,GAAY;AACf,KAAW,GAAK;AAChB;;EAGF,IAAI,IAAY,IAEV,IAAO,OAAO,MAAoB;AACtC,OAAI;IACF,IAAM,IAAS,MAAM,EAAc,EAAW;AAC9C,QAAI,EAAW;AAEf,IAAI,KACF,EAAY,EAAO,EACnB,EAAW,GAAK,IACP,MAAY,IAGrB,iBAAiB;AACf,KAAK,KAAW,EAAK,EAAE;OACtB,GAAyB,GAG5B,EAAW,GAAK;WAEZ;AAGN,IAAK,KAAW,EAAW,GAAK;;;AAKpC,SADA,EAAK,EAAE,QACM;AACX,OAAY;;IAEb,CAAC,GAAY,EAAc,CAAC;CAG/B,IAAM,KAAa,QAAkB;AACnC,IAAS,aAAa;IACrB,CAAC,EAAS,CAAC,EAER,IAAa,QAAkB;AACnC,IAAS,cAAc,EAAW,OAAO;IACxC,CAAC,GAAU,EAAW,CAAC,EAEpB,KAAe,EAAY,YAAY;AACtC,SACL;KAAc,GAAK;AACnB,OAAI;AAEF,IADgB,MAAM,EAAe,EAAW,IAE1C,GAAU,IAAO,EAAa,UAAU,EAC5C,EAAS,aAAa,IACb,GAAU,IACd,EAAa,QAAQ;WAEtB;AACN,IAAI,GAAU,IAAO,EAAa,QAAQ;aAClC;AAER,IADA,EAAc,GAAM,EACpB,EAAqB,GAAM;;;IAE5B;EAAC;EAAY;EAAgB;EAAS,CAAC,EAEpC,IAAgB,EAAY,YAAY;AAC5C,MAAI,CAAC,EAAY;AAEjB,EADA,EAAe,GAAK,EACpB,EAAmB,KAAK;EAExB,IAAM,IAAY,KAAK,KAAK;AAE5B,MAAI;GACF,IAAM,IAAS,MAAM,EAAgB,EAAW;AAEhD,OAAI,GAAQ;IACV,IAAM,IAAkB,KAAK,KAAK,GAAG;AAGrC,IAAI,EAAO,sBACT,EAAmB;KACjB,SAAS;KACT,QAAQ;MACN,oBAAoB,EAAO;MAC3B,gBAAgB,EAAO;MACvB,QAAQ,EAAE,uDAAuD,wCAAwC;MAC1G;KACD,OAAO;KACP;KACD,CAAC,EAGF,EAAsB,GAAY;KAChC,YAAY;KACZ,WAAW;KACX,aAAa,MAAY;AACvB,QAAY,EAAQ;;KAEvB,CAAC,CAAC,MAAM,MAAU;AACjB,KAAI,MACF,EAAY,EAAM,EAClB,GAAoB,MAClB,KACI;MACE,GAAG;MACH,QAAQ;OACN,GAAK,EAAK,UAAsC,EAAE;OAClD,QACE,EAAM,WAAW,UACb,EAAE,mDAAmD,SAAS,GAC9D,EAAE,sDAAsD,YAAY;OAC1E,gBAAgB,EAAM;OACtB,gBAAgB,EAAM;OACvB;MACD,iBAAiB,KAAK,KAAK,GAAG;MAC/B,CAEN;MAEH,IAGF,EAAmB;KACjB,SAAS;KACT,QAAQ;MACN,gBAAgB,EAAO;MACvB,gBAAgB,EAAO;MACvB,QAAQ,EAAE,sDAAsD,YAAY;MAC7E;KACD,OAAO;KACP;KACD,CAAC;IAIJ,IAAM,IAAU,MAAM,EAAc,EAAW;AAC/C,IAAI,KACF,EAAY,EAAQ;;WAGjB,GAAK;AACZ,KAAmB;IACjB,SAAS;IACT,QAAQ;IACR,OACE,aAAe,QAAQ,EAAI,UAAU,EAAE,+CAA+C,mBAAmB;IAC3G,iBAAiB,KAAK,KAAK,GAAG;IAC/B,CAAC;YACM;AACR,KAAe,GAAM;;IAEtB;EAAC;EAAY;EAAiB;EAAe;EAAuB;EAAE,CAAC,EAEpE,KAAoB,EAAY,YAAY;AAC3C,SAAU,WACf,KAAI;AAIF,GAHA,MAAM,EAAe,EAAS,WAAW,EACzC,EAAiB,GAAK,EAClB,GAAU,IAAO,GAAY,EAAE,gDAAgD,iBAAiB,CAAC,EACrG,iBAAiB,EAAiB,GAAM,EAAE,IAAK;UACzC;IAGP,CAAC,GAAU,YAAY,EAAE,CAAC,EAEvB,KAAqB,GACxB,MAAuB;AACtB,IAAS,cAAc,IAAa;IAEtC,CAAC,EAAS,CACX,EAIK,IACJ,kBAAC,UAAD;EACE,MAAK;EACL,SAAS;EACT,WAAW,wKAAwK;YAHrL,CAKE,kBAAC,IAAD,EAAe,WAAU,WAAY,CAAA,EACpC,EAAE,6CAA6C,oBAAoB,CAC7D;;AAKX,KAAI,CAAC,MAAY,MAAW,CAAC,KAAa,EACxC,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,IAAD,EAAS,MAAK,MAAO,CAAA;EACjB,CAAA;AAKV,KAAI,CAAC,EACH,QACE,kBAAC,GAAD;EACE,OAAO,EAAE,iDAAiD,gBAAgB;EAC1E,aAAa,EACX,2DACA,mDACD;EACD,CAAA;AAKN,KAAI,KAAS,CAAC,EACZ,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD,EAAA,UAAM,GAAe,CAAA,EAGrB,kBAAC,WAAD;GACE,cAAW;GACX,yBAAsB;GACtB,eAAY;GACZ,WAAW,EAAsB,WAAW;aAE5C,kBAAC,GAAD;IACE,cAAa;IACb,OAAO,EAAE,2CAA2C,qBAAqB;IACzE,aACE,GAAO,WACP,EAAE,iDAAiD,mDAAmD;IAExG,CAAA;GACM,CAAA,CACG,EAAA,CAAA;EACX,CAAA;CAIV,IAAM,IAAsB,EAAS,eAAe,UAAU,GAGxD,KAAmB,EAAQ,EAAS,oBAIpC,KAAwB;EAC5B,GAAI,IACA,CACE;GACE,IAAI;GACJ,OAAO,EAAE,kDAAkD,mBAAmB;GAC9E,aAAa,EACX,wDACA,+CACD;GACD,SAAS;GACV,CACF,GACD,EAAE;EACN;GACE,IAAI;GACJ,OAAO,EAAE,iDAAiD,qBAAqB;GAC/E,aAAa,EACX,uDACA,iDACD;GACD,eAAe,EAAqB,GAAK;GAC1C;EACD,GAAI,IACA,CACE;GACE,IAAI;GACJ,OAAO,EAAE,+CAA+C,sBAAsB;GAC9E,aAAa,EACX,qDACA,yDACD;GACD,SAAS;GACV,CACF,GACD,EAAE;EACN;GACE,IAAI;GACJ,OAAO,EAAE,gDAAgD,8BAA8B;GACvF,aAAa,EACX,sDACA,6CACD;GACD,eAAe,EAAS,aAAa;GACtC;EACF;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD,EAAA,UAAA;GAKE,kBAAC,UAAD;IAAQ,yBAAsB;IAAO,WAAU;cAA/C,CACE,kBAAC,OAAD;KAAK,WAAU;eAAe;KAAe,CAAA,EAE7C,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBAAoD,EAAS;SAAU,CAAA,EACrF,kBAAC,IAAD,EAAqB,QAAQ,EAAS,QAAU,CAAA,CAC5C;;OACN,kBAAC,KAAD;QAAG,WAAU;kBAAwD,EAAS;QAAQ,CAAA;OACrF,EAAS,sBACR,kBAAC,KAAD;QAAG,WAAU;kBAAb;SACG,EAAE,+CAA+C,iBAAiB;SAAE;SACrE,kBAAC,QAAD;UAAM,WAAU;oBAAuB,EAAS;UAA0B,CAAA;SACxE;;OAEF;SAEN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,GAAD;QAAkB,YAAY,EAAuB;QAAkB,gBAAe;kBACpF,kBAAC,GAAD;SAAQ,MAAK;SAAK,SAAS;SAAe,UAAU;mBAApD,CACE,kBAAC,IAAD,EAAU,WAAU,WAAY,CAAA,EAC/B,IACG,EAAE,0CAA0C,eAAe,GAC3D,EAAE,wCAAwC,UAAU,CACjD;;QACQ,CAAA;OACnB,kBAAC,GAAD;QAAkB,YAAY,EAAuB;QAAiB,gBAAe;kBACnF,kBAAC,GAAD;SAAQ,MAAK;SAAK,SAAQ;SAAU,SAAS;mBAA7C,CACE,kBAAC,IAAD,EAAU,WAAU,WAAY,CAAA,EAC/B,EAAE,qCAAqC,OAAO,CACxC;;QACQ,CAAA;OACnB,kBAAC,GAAD;QAAkB,YAAY,EAAuB;QAAiB,gBAAe;kBACnF,kBAAC,GAAD;SACE,MAAK;SACL,SAAQ;SACR,eAAe,EAAqB,GAAK;SACzC,WAAU;mBAJZ,CAME,kBAAC,IAAD,EAAW,WAAU,WAAY,CAAA,EAChC,EAAE,uCAAuC,SAAS,CAC5C;;QACQ,CAAA;OACf;QACF;OACC;;GAET,kBAAC,IAAD,EAAA,UACG,EACC,qCACA,6QACD,EACW,CAAA;GAEd,kBAAC,IAAD;IAAW,YAAW;IAA2B,OAAO;IAAa,CAAA;GAGpE,KACC,kBAAC,GAAD;IACE,cAAc;IACd,MAAM,EAAgB,UAAU,YAAY;IAC5C,OACE,EAAgB,UACZ,EAAE,sDAAsD,sBAAsB,GAC9E,EAAE,mDAAmD,mBAAmB;IAE9E,aACE,EAAgB,UACZ,uEACA;IAEN,MACE,kBAAC,QAAD;KAAM,WAAU;eAAhB,CACG,EAAgB,iBAAgB,KAC5B;;IAET,eAAY;cAlBd,CAoBG,EAAgB,QACf,kBAAC,KAAD;KAAG,WAAU;eAA6D,EAAgB;KAAU,CAAA,GAEpG,kBAAC,OAAD;KAAK,WAAU;eACZ,KAAK,UAAU,EAAgB,QAAQ,MAAM,EAAE;KAC5C,CAAA,EAEP,EAAgB,SACf,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAE,wCAAwC,UAAU;MAAE;MACvD,kBAAC,QAAD;OAAM,WAAU;iBAAuB,EAAgB;OAAa,CAAA;MAClE;OAEE;;GAIZ,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,cAAc;KACd,UAAS;KACT,OAAO,EAAE,8CAA8C,cAAc;KACrE,aAAY;eAEZ,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAS,eAAe,EAAE,2CAA2C,iBAAiB;MACrF,CAAA;KACI,CAAA,EAEV,kBAAC,GAAD;KACE,cAAc;KACd,UAAU,KAAmB,aAAa;KAC1C,OAAO,EAAE,iDAAiD,kBAAkB;KAC5E,aAAY;KACZ,eAAY;eAEZ,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAwC,EAAS;QAAmB,CAAA,EACjF,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAE,kDAAkD,mBAAmB;QACtE,CAAA,CACA;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAS,iBACN,EAAoB,IAAI,KAAK,EAAS,eAAe,EAAE,EAAE,WAAW,IAAM,CAAC,GAC3E,EAAE,mCAAmC,QAAQ;QAC/C,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAE,+CAA+C,gBAAgB;QAChE,CAAA,CACA;SACF;;KACE,CAAA,CACN;;GAGL,EAAS,sBACR,kBAAC,GAAD;IACE,cAAc;IACd,UAAS;IACT,OAAO,EAAE,gDAAgD,0BAA0B;IACnF,aAAY;IACZ,SACE,kBAAC,GAAD;KACE,SAAQ;KACR,MAAK;KACL,iBAAe;KACf,iBAAc;KACd,eAAe,GAAsB,MAAS,CAAC,EAAK;eALtD,CAOG,IAAoB,gBAAgB,eACrC,kBAAC,IAAD,EACE,WAAW,4CAA4C,IAAoB,eAAe,MAC1F,CAAA,CACK;;IAEX,eAAY;cAEX,IACC,kBAAC,OAAD;KACE,IAAG;KACH,WAAU;eAEV,kBAAC,IAAD;MACiB;MACf,aAAa,KAAe;MACjB;MACX,YAAY,EAAS;MACrB,UAAA;MACA,YAAA;MACA,WAAU;MACV,CAAA;KACE,CAAA,GAEN,kBAAC,KAAD;KAAG,IAAG;KAAyB,WAAU;eAA8B;KAEnE,CAAA;IAEE,CAAA;GAIX,EAAS,cACR,kBAAC,GAAD;IACE,cAAc;IACd,UAAS;IACT,OAAO,EAAE,6CAA6C,cAAc;IACpE,aAAY;IACZ,SACE,kBAAC,GAAD;KAAQ,SAAQ;KAAQ,MAAK;KAAK,SAAS;eACxC,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,IAAD,EAAW,WAAU,oCAAqC,CAAA,EACzD,EAAE,uCAAuC,UAAU,CACnD,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,IAAD,EAAU,WAAU,WAAY,CAAA,EAC/B,EAAE,qCAAqC,OAAO,CAC9C,EAAA,CAAA;KAEE,CAAA;cAGX,kBAAC,QAAD;KAAM,WAAU;eACb,EAAS;KACL,CAAA;IACC,CAAA;GAIZ,kBAAC,GAAD;IACE,cAAc;IACd,OAAO,EAAE,kDAAkD,gCAAgC,EACzF,OAAO,GACR,CAAC;IACF,aAAY;IACZ,eAAY;cAEX,MAAwB,IACvB,kBAAC,GAAD;KACE,cAAa;KACb,OAAO,EAAE,8CAA8C,uBAAuB;KAC9E,aAAa,EACX,oDACA,8EACD;KACD,CAAA,GAEF,kBAAC,MAAD;KAAI,WAAU;eACX,EAAS,eAAe,KAAK,MAC5B,kBAAC,MAAD;MAEE,WAAU;gBAFZ,CAIE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,IAAD,EAAc,WAAU,wCAAyC,CAAA,EACjE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAK,UAAU,QAAQ,EAAK,UAAU,OAAO,EAAK;SACjD,CAAA,EACH,EAAK,UAAU,OACd,kBAAC,KAAD;SAAG,WAAU;mBAAkD,EAAK,SAAS;SAAQ,CAAA,CAEnF;UACF;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACG,EAAK,YACJ,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAE,6CAA6C,UAAU;SACrD,CAAA,GAEP,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAE,8CAA8C,WAAW;SACvD,CAAA;QAET,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAE,8CAA8C,0BAA0B,EACzE,UAAU,EAAK,UAChB,CAAC;SACG,CAAA;QACN,EAAK,YACJ,kBAAC,UAAD;SACE,MAAK;SACL,eAAe,GAAmB,EAAK,WAAW;SAClD,WAAW;mBAEV,EAAE,qCAAqC,OAAO;SACxC,CAAA;QAEP;SACH;QAvCE,EAAK,GAuCP,CACL;KACC,CAAA;IAEC,CAAA;GAGV,kBAAC,GAAD;IAAS,cAAc;IAAG,UAAS;IAAQ,OAAM;IAAiB,SAAQ;cACxE,kBAAC,MAAD;KAAI,WAAU;eAAd,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,MAAD;QAAI,WAAU;kBAA+B,EAAE,0CAA0C,UAAU;QAAM,CAAA;OACzG,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAoB,IAAI,KAAK,EAAS,UAAU,EAAE,EAAE,WAAW,IAAM,CAAC;QACpE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,sCAAsC,iBAAiB,EAAE,QAAQ,EAAS,WAAW,CAAC;QACtF,CAAA;OACD;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,8CAA8C,eAAe;QAC7D,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAoB,IAAI,KAAK,EAAS,UAAU,EAAE,EAAE,WAAW,IAAM,CAAC;QACpE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,sCAAsC,iBAAiB,EACxD,QAAQ,EAAS,aAAa,EAAS,WACxC,CAAC;QACC,CAAA;OACD;QACH;;IACG,CAAA;GACG,EAAA,CAAA,EAGd,KACC,kBAAC,IAAD;GACY;GACV,QAAQ;GACR,eAAe,EAAqB,GAAM;GAC1C,WAAW;GACX,CAAA,CAEA;;EAER"}
|
|
1
|
+
{"version":3,"file":"WorkflowViewPage.js","names":[],"sources":["../../../src/bigconsole/pages/WorkflowViewPage.tsx"],"sourcesContent":["/**\n * Workflow View Page\n *\n * Page for viewing FluidGrids Workflow details, linked DataSinks,\n * read-only workflow design preview, and real execution with polling.\n *\n * Section hierarchy (BOFF-5634):\n * - header (back link + identity + actions) ... `bare`\n * - execution result ......................... `standard` + success/danger tone\n * - \"Workflow design\" (the node canvas) ...... `primary` — the thing the route is about\n * - \"Execution stats\" ........................ `standard`, promoted to `primary` when the\n * workflow has no design preview to show\n * - \"Description\" / \"Webhook trigger\" /\n * \"Record history\" ......................... `muted` — supporting detail\n * - \"Linked data sinks\" ...................... `standard`\n * Exactly one `primary` renders in every branch.\n */\n\nimport { memo, useState, useEffect, useCallback } from 'react';\nimport { useParams } from 'react-router';\nimport { Button, IllustratedEmptyState, PagePurpose, NextSteps, Spinner } from '@burdenoff/fe-libs/ui';\nimport type { NextStep } from '@burdenoff/fe-libs/ui';\nimport { Section, SectionStack, SECTION_FOCUS_RING, sectionSurfaceClasses } from '../components/common';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeCopyText, nativeNotify, nativeToast } from '../../utils/nativeBridge';\nimport { useBigConsole } from '../context';\nimport { formatDistanceToNow } from 'date-fns';\nimport { useWorkflowOperations } from '../hooks/useWorkflowOperations';\nimport { WorkflowStatusBadge } from '../components/workflow/WorkflowStatusBadge';\nimport { WorkflowDeleteDialog } from '../components/workflow/WorkflowDeleteDialog';\nimport type { FluidGridsWorkflow } from '../types';\n\n// FluidGrids FE SDK — read-only embedded builder preview\nimport { WorkflowBuilder } from '@burdenoff/fluidgrids-fe-sdk';\nimport { BOOTSTRAP_RETRY_DELAY_MS } from '../constants';\n\n// RBAC\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { AccessDenied, PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst ArrowLeftIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n);\n\nconst EditIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n);\n\nconst TrashIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n);\n\nconst PlayIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\n />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n);\n\nconst CopyIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n);\n\nconst CheckIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n);\n\nconst DatabaseIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\"\n />\n </svg>\n);\n\nconst ChevronDownIcon = ({ className }: { className?: string }) => (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n);\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowViewPage = memo(function WorkflowViewPage() {\n const navigate = useAppNavigate();\n const { t } = useI18n();\n const { workflowId } = useParams<{ workflowId: string }>();\n\n // BigConsole context for apiGatewayUrl and authToken\n const { apiGatewayUrl, authToken, workspaceId } = useBigConsole();\n\n // RBAC\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_READ);\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_UPDATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_DELETE);\n const canExecute = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_EXECUTE);\n\n // Local state\n const [workflow, setWorkflow] = useState<FluidGridsWorkflow | null>(null);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [, setIsDeleting] = useState(false);\n const [isExecuting, setIsExecuting] = useState(false);\n const [webhookCopied, setWebhookCopied] = useState(false);\n const [showDesignPreview, setShowDesignPreview] = useState(false);\n // Track whether initial fetch has completed — prevents \"not found\" flash\n // before data has even been requested (loading starts as false with skipFetch: true)\n const [isReady, setIsReady] = useState(false);\n const [executionResult, setExecutionResult] = useState<{\n success: boolean;\n output: unknown;\n error: string | null;\n executionTimeMs: number;\n runId?: string;\n } | null>(null);\n\n // Operations\n const { loading, error, fetchWorkflow, deleteWorkflow, executeWorkflow, pollWorkflowExecution } =\n useWorkflowOperations({\n skipFetch: true,\n });\n\n // Load workflow on mount.\n // On a full page reload the workspace token may not be issued yet when this\n // effect first runs, causing the gateway to lack workspace context and\n // the resolver to return null. We retry once after a short delay to give\n // the auth bootstrap time to complete.\n useEffect(() => {\n if (!workflowId) {\n setIsReady(true);\n return;\n }\n\n let cancelled = false;\n\n const load = async (attempt: number) => {\n try {\n const result = await fetchWorkflow(workflowId);\n if (cancelled) return;\n\n if (result) {\n setWorkflow(result);\n setIsReady(true);\n } else if (attempt === 0) {\n // First attempt failed — likely workspace token race on full-page load.\n // Retry once after a short delay.\n setTimeout(() => {\n if (!cancelled) load(1);\n }, BOOTSTRAP_RETRY_DELAY_MS);\n } else {\n // Second attempt also failed — genuinely not found\n setIsReady(true);\n }\n } catch {\n // Network error, GraphQL error, etc. — surface the \"not found\" UI\n // rather than spinning forever with no escape hatch.\n if (!cancelled) setIsReady(true);\n }\n };\n\n load(0);\n return () => {\n cancelled = true;\n };\n }, [workflowId, fetchWorkflow]);\n\n // Handlers\n const handleBack = useCallback(() => {\n navigate(`/workflows`);\n }, [navigate]);\n\n const handleEdit = useCallback(() => {\n navigate(`/workflows/${workflowId}/edit`);\n }, [navigate, workflowId]);\n\n const handleDelete = useCallback(async () => {\n if (!workflowId) return;\n setIsDeleting(true);\n try {\n const success = await deleteWorkflow(workflowId);\n if (success) {\n if (isNative()) void nativeNotify('success');\n navigate(`/workflows`);\n } else if (isNative()) {\n void nativeNotify('error');\n }\n } catch {\n if (isNative()) void nativeNotify('error');\n } finally {\n setIsDeleting(false);\n setShowDeleteConfirm(false);\n }\n }, [workflowId, deleteWorkflow, navigate]);\n\n const handleExecute = useCallback(async () => {\n if (!workflowId) return;\n setIsExecuting(true);\n setExecutionResult(null);\n\n const startTime = Date.now();\n\n try {\n const result = await executeWorkflow(workflowId);\n\n if (result) {\n const executionTimeMs = Date.now() - startTime;\n\n // If workflow has external FluidGrids ID, the execution is async\n if (result.externalWorkflowId) {\n setExecutionResult({\n success: true,\n output: {\n externalWorkflowId: result.externalWorkflowId,\n executionCount: result.executionCount,\n status: t('bigconsole.workflows.view.executionTriggeredPolling', 'Triggered — polling for completion...'),\n },\n error: null,\n executionTimeMs,\n });\n\n // Poll for completion in the background\n pollWorkflowExecution(workflowId, {\n intervalMs: 3000,\n timeoutMs: 120000,\n onProgress: (updated) => {\n setWorkflow(updated);\n },\n }).then((final) => {\n if (final) {\n setWorkflow(final);\n setExecutionResult((prev) =>\n prev\n ? {\n ...prev,\n output: {\n ...((prev.output as Record<string, unknown>) || {}),\n status:\n final.status === 'error'\n ? t('bigconsole.workflows.view.executionStatusFailed', 'Failed')\n : t('bigconsole.workflows.view.executionStatusCompleted', 'Completed'),\n executionCount: final.executionCount,\n lastExecutedAt: final.lastExecutedAt,\n },\n executionTimeMs: Date.now() - startTime,\n }\n : prev\n );\n }\n });\n } else {\n // Local execution (no external FluidGrids workflow)\n setExecutionResult({\n success: true,\n output: {\n executionCount: result.executionCount,\n lastExecutedAt: result.lastExecutedAt,\n status: t('bigconsole.workflows.view.executionStatusCompleted', 'Completed'),\n },\n error: null,\n executionTimeMs,\n });\n }\n\n // Refresh workflow\n const updated = await fetchWorkflow(workflowId);\n if (updated) {\n setWorkflow(updated);\n }\n }\n } catch (err) {\n setExecutionResult({\n success: false,\n output: null,\n error:\n err instanceof Error ? err.message : t('bigconsole.workflows.errors.executionFailed', 'Execution failed'),\n executionTimeMs: Date.now() - startTime,\n });\n } finally {\n setIsExecuting(false);\n }\n }, [workflowId, executeWorkflow, fetchWorkflow, pollWorkflowExecution, t]);\n\n const handleCopyWebhook = useCallback(async () => {\n if (!workflow?.webhookUrl) return;\n try {\n await nativeCopyText(workflow.webhookUrl);\n setWebhookCopied(true);\n if (isNative()) void nativeToast(t('bigconsole.workflows.view.webhookCopiedToast', 'Webhook copied'));\n setTimeout(() => setWebhookCopied(false), 2000);\n } catch {\n // Clipboard not available\n }\n }, [workflow?.webhookUrl, t]);\n\n const handleViewDataSink = useCallback(\n (dataSinkId: string) => {\n navigate(`/datasinks/${dataSinkId}`);\n },\n [navigate]\n );\n\n // Back-to-list control — identical on the not-found branch and the loaded page,\n // so \"where am I\" reads the same however the route resolves.\n const backLink = (\n <button\n type=\"button\"\n onClick={handleBack}\n className={`inline-flex min-h-[var(--size-controlHeight-md)] items-center gap-1 rounded-button text-sm text-text-secondary motion-safe:transition-colors hover:text-text-primary ${SECTION_FOCUS_RING}`}\n >\n <ArrowLeftIcon className=\"w-4 h-4\" />\n {t('bigconsole.workflows.view.backToWorkflows', 'Back to Workflows')}\n </button>\n );\n\n // Loading state — show spinner until initial fetch completes OR during a\n // refetch, and while permissions are still loading (avoids a read-gate flash).\n if (!isReady || (loading && !workflow) || permissionsLoading) {\n return (\n <div className=\"mx-auto flex min-h-[400px] max-w-5xl items-center justify-center p-4 sm:p-[var(--space-pagePadding)]\">\n <Spinner size=\"lg\" />\n </div>\n );\n }\n\n // Read gate — no permission to view this workflow\n if (!canRead) {\n return (\n <AccessDenied\n title={t('bigconsole.workflows.errors.accessDeniedTitle', 'Access Denied')}\n description={t(\n 'bigconsole.workflows.errors.accessDeniedViewDescription',\n \"You don't have permission to view this workflow.\"\n )}\n />\n );\n }\n\n // Error or not found state — only shown AFTER initial fetch completed\n if (error || !workflow) {\n return (\n <div className=\"mx-auto max-w-5xl p-4 sm:p-[var(--space-pagePadding)]\">\n <SectionStack>\n <div>{backLink}</div>\n {/* Same surface the list page gives its empty states, so \"nothing to\n show\" looks the same wherever you hit it. */}\n <section\n aria-label=\"Workflow not found\"\n data-section-emphasis=\"standard\"\n data-testid=\"workflow-not-found\"\n className={sectionSurfaceClasses('standard')}\n >\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('bigconsole.workflows.view.notFoundTitle', 'Workflow not found')}\n description={\n error?.message ||\n t('bigconsole.workflows.view.notFoundDescription', 'The workflow you are looking for does not exist.')\n }\n />\n </section>\n </SectionStack>\n </div>\n );\n }\n\n const linkedDataSinkCount = workflow.dataSinkLinks?.length || 0;\n // The read-only canvas is the point of this route when it exists; when it does\n // not, the execution numbers become the page's single `primary` block.\n const hasDesignPreview = Boolean(workflow.externalWorkflowId);\n\n // Next-step guidance — omit steps that trigger a gated action the caller\n // cannot perform (execute → WORKFLOW_EXECUTE, edit → WORKFLOW_UPDATE).\n const nextSteps: NextStep[] = [\n ...(canExecute\n ? [\n {\n id: 'execute',\n label: t('bigconsole.workflows.view.nextStepExecuteLabel', 'Run the workflow'),\n description: t(\n 'bigconsole.workflows.view.nextStepExecuteDescription',\n 'Trigger an execution to pull fresh data now.'\n ),\n onClick: handleExecute,\n },\n ]\n : []),\n {\n id: 'design',\n label: t('bigconsole.workflows.view.nextStepDesignLabel', 'Inspect the design'),\n description: t(\n 'bigconsole.workflows.view.nextStepDesignDescription',\n 'Expand the read-only preview to see each step.'\n ),\n onClick: () => setShowDesignPreview(true),\n },\n ...(canUpdate\n ? [\n {\n id: 'edit',\n label: t('bigconsole.workflows.view.nextStepEditLabel', 'Edit in the builder'),\n description: t(\n 'bigconsole.workflows.view.nextStepEditDescription',\n 'Open the FluidGrids visual builder to change the flow.'\n ),\n onClick: handleEdit,\n },\n ]\n : []),\n {\n id: 'sinks',\n label: t('bigconsole.workflows.view.nextStepSinksLabel', 'Check the linked data sinks'),\n description: t(\n 'bigconsole.workflows.view.nextStepSinksDescription',\n 'See where this workflow writes its output.'\n ),\n onClick: () => navigate('/datasinks'),\n },\n ];\n\n return (\n <div className=\"mx-auto max-w-5xl p-4 sm:p-[var(--space-pagePadding)]\">\n <SectionStack>\n {/* ---------------------------------------------------------------- *\n * Page header — `bare` emphasis: back link, identity and the action\n * cluster. Structural only, so the blocks below own the visual weight.\n * ---------------------------------------------------------------- */}\n <header data-section-emphasis=\"bare\" className=\"min-w-0\">\n <div className=\"mb-form-gap\">{backLink}</div>\n\n <div className=\"flex flex-col gap-form-gap md:flex-row md:items-start md:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-icon-gap\">\n <h1 className=\"break-words text-2xl font-bold text-text-primary\">{workflow.name}</h1>\n <WorkflowStatusBadge status={workflow.status} />\n </div>\n <p className=\"mt-1 break-all font-mono text-sm text-text-secondary\">{workflow.key}</p>\n {workflow.externalWorkflowId && (\n <p className=\"mt-1 text-xs text-text-muted\">\n {t('bigconsole.workflows.view.fluidGridsIdLabel', 'FluidGrids ID:')}{' '}\n <span className=\"break-all font-mono\">{workflow.externalWorkflowId}</span>\n </p>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-control-gap\">\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_EXECUTE} deniedBehavior=\"disable\">\n <Button size=\"lg\" onClick={handleExecute} disabled={isExecuting}>\n <PlayIcon className=\"w-4 h-4\" />\n {isExecuting\n ? t('bigconsole.workflows.actions.executing', 'Executing...')\n : t('bigconsole.workflows.actions.execute', 'Execute')}\n </Button>\n </PermissionButton>\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_UPDATE} deniedBehavior=\"disable\">\n <Button size=\"lg\" variant=\"outline\" onClick={handleEdit}>\n <EditIcon className=\"w-4 h-4\" />\n {t('bigconsole.workflows.actions.edit', 'Edit')}\n </Button>\n </PermissionButton>\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_DELETE} deniedBehavior=\"hide\">\n <Button\n size=\"lg\"\n variant=\"ghost\"\n onClick={() => setShowDeleteConfirm(true)}\n className=\"text-[var(--color-status-error-text)] hover:bg-status-error-bg/10 hover:text-[var(--color-status-error-text)]\"\n >\n <TrashIcon className=\"w-4 h-4\" />\n {t('bigconsole.workflows.actions.delete', 'Delete')}\n </Button>\n </PermissionButton>\n </div>\n </div>\n </header>\n\n <PagePurpose>\n {t(\n 'bigconsole.workflows.view.purpose',\n 'A workflow is the visual ETL job that feeds this BigConsole — it fetches, transforms, and delivers data into linked data sinks. From here you can run it on demand, inspect its design and execution history, copy its webhook trigger, and edit it in the visual builder.'\n )}\n </PagePurpose>\n\n <NextSteps storageKey=\"bigconsole-workflow-view\" steps={nextSteps} />\n\n {/* Execution result — a status section, not a hand-rolled tinted div. */}\n {executionResult && (\n <Section\n headingLevel={2}\n tone={executionResult.success ? 'success' : 'danger'}\n title={\n executionResult.success\n ? t('bigconsole.workflows.view.executionResultTriggered', 'Execution Triggered')\n : t('bigconsole.workflows.view.executionResultFailed', 'Execution Failed')\n }\n description={\n executionResult.success\n ? 'The run was accepted. Results refresh below as the run progresses.'\n : 'The run could not be started. The detail below comes straight from the workflow service.'\n }\n meta={\n <span className=\"rounded-pill bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {executionResult.executionTimeMs}ms\n </span>\n }\n data-testid=\"workflow-execution-result\"\n >\n {executionResult.error ? (\n <p className=\"break-words text-sm text-[var(--color-status-error-text)]\">{executionResult.error}</p>\n ) : (\n <pre className=\"max-h-[200px] min-w-0 overflow-auto rounded-card bg-bg-sunken p-2 font-mono text-xs text-text-secondary\">\n {JSON.stringify(executionResult.output, null, 2)}\n </pre>\n )}\n {executionResult.runId && (\n <p className=\"mt-2 text-xs text-text-muted\">\n {t('bigconsole.workflows.view.runIdLabel', 'Run ID:')}{' '}\n <span className=\"break-all font-mono\">{executionResult.runId}</span>\n </p>\n )}\n </Section>\n )}\n\n {/* Overview row: supporting description beside the run numbers. */}\n <div className=\"grid grid-cols-1 gap-section-gap md:grid-cols-2\">\n <Section\n headingLevel={2}\n emphasis=\"muted\"\n title={t('bigconsole.workflows.view.descriptionLabel', 'Description')}\n description=\"What this workflow is for, as entered by its author.\"\n >\n <p className=\"break-words text-sm text-text-primary\">\n {workflow.description || t('bigconsole.workflows.view.noDescription', 'No description')}\n </p>\n </Section>\n\n <Section\n headingLevel={2}\n emphasis={hasDesignPreview ? 'standard' : 'primary'}\n title={t('bigconsole.workflows.view.executionStatsLabel', 'Execution Stats')}\n description=\"How often this workflow has run, and when it last did.\"\n data-testid=\"workflow-execution-stats\"\n >\n <div className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <p className=\"text-2xl font-bold text-text-primary\">{workflow.executionCount}</p>\n <p className=\"text-xs text-text-secondary\">\n {t('bigconsole.workflows.view.totalExecutionsLabel', 'Total Executions')}\n </p>\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {workflow.lastExecutedAt\n ? formatDistanceToNow(new Date(workflow.lastExecutedAt), { addSuffix: true })\n : t('bigconsole.workflows.view.never', 'Never')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {t('bigconsole.workflows.view.lastExecutedLabel', 'Last Executed')}\n </p>\n </div>\n </div>\n </Section>\n </div>\n\n {/* Workflow design — the node canvas, the one `primary` block here. */}\n {workflow.externalWorkflowId && (\n <Section\n headingLevel={2}\n emphasis=\"primary\"\n title={t('bigconsole.workflows.view.designPreviewTitle', 'Workflow Design Preview')}\n description=\"The steps this workflow runs, read-only. Open the builder to change them.\"\n actions={\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-expanded={showDesignPreview}\n aria-controls=\"workflow-design-canvas\"\n onClick={() => setShowDesignPreview((prev) => !prev)}\n >\n {showDesignPreview ? 'Hide design' : 'Show design'}\n <ChevronDownIcon\n className={`w-4 h-4 motion-safe:transition-transform ${showDesignPreview ? 'rotate-180' : ''}`}\n />\n </Button>\n }\n data-testid=\"workflow-design-preview\"\n >\n {showDesignPreview ? (\n <div\n id=\"workflow-design-canvas\"\n className=\"h-[320px] min-w-0 overflow-hidden rounded-card border border-[var(--color-border-subtle)] sm:h-[420px] lg:h-[450px]\"\n >\n <WorkflowBuilder\n apiGatewayUrl={apiGatewayUrl}\n workspaceId={workspaceId || 'default'}\n authToken={authToken}\n workflowId={workflow.externalWorkflowId}\n readonly\n hideHeader\n className=\"h-full\"\n />\n </div>\n ) : (\n <p id=\"workflow-design-canvas\" className=\"text-sm text-text-secondary\">\n The canvas is collapsed. Show the design to see every step, its order and its connections.\n </p>\n )}\n </Section>\n )}\n\n {/* Webhook trigger — supporting integration detail. */}\n {workflow.webhookUrl && (\n <Section\n headingLevel={2}\n emphasis=\"muted\"\n title={t('bigconsole.workflows.view.webhookUrlLabel', 'Webhook URL')}\n description=\"POST to this URL to run the workflow from an external system.\"\n actions={\n <Button variant=\"ghost\" size=\"sm\" onClick={handleCopyWebhook}>\n {webhookCopied ? (\n <>\n <CheckIcon className=\"w-4 h-4 text-status-success-text\" />\n {t('bigconsole.workflows.actions.copied', 'Copied!')}\n </>\n ) : (\n <>\n <CopyIcon className=\"w-4 h-4\" />\n {t('bigconsole.workflows.actions.copy', 'Copy')}\n </>\n )}\n </Button>\n }\n >\n <code className=\"block min-w-0 overflow-x-auto break-all rounded-card bg-bg-sunken px-3 py-2 font-mono text-sm text-text-primary\">\n {workflow.webhookUrl}\n </code>\n </Section>\n )}\n\n {/* Linked data sinks — relationships, normal grouped work. */}\n <Section\n headingLevel={2}\n title={t('bigconsole.workflows.view.linkedDataSinksTitle', 'Linked DataSinks ({{count}})', {\n count: linkedDataSinkCount,\n })}\n description=\"Where this workflow writes the data it produces.\"\n data-testid=\"workflow-linked-datasinks\"\n >\n {linkedDataSinkCount === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title={t('bigconsole.workflows.view.noDataSinksTitle', 'No data sinks linked')}\n description={t(\n 'bigconsole.workflows.view.noDataSinksDescription',\n \"This workflow has no data sinks linked yet — its output isn't being stored.\"\n )}\n />\n ) : (\n <ul className=\"flex flex-col gap-list-gap\">\n {workflow.dataSinkLinks?.map((link) => (\n <li\n key={link.id}\n className=\"flex flex-col gap-control-gap rounded-card bg-bg-sunken px-3 py-2 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"flex min-w-0 items-center gap-icon-gap\">\n <DatabaseIcon className=\"w-4 h-4 shrink-0 text-text-secondary\" />\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {link.dataSink?.name || link.dataSink?.key || link.dataSinkId}\n </p>\n {link.dataSink?.key && (\n <p className=\"truncate font-mono text-xs text-text-secondary\">{link.dataSink.key}</p>\n )}\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-control-gap\">\n {link.isEnabled ? (\n <span className=\"rounded-pill bg-[var(--color-status-success-bgSubtle)] px-2 py-0.5 text-xs font-medium text-status-success-text\">\n {t('bigconsole.workflows.view.dataSinkEnabled', 'Enabled')}\n </span>\n ) : (\n <span className=\"rounded-pill bg-bg-surface px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {t('bigconsole.workflows.view.dataSinkDisabled', 'Disabled')}\n </span>\n )}\n <span className=\"text-xs text-text-muted\">\n {t('bigconsole.workflows.view.dataSinkPriority', 'Priority: {{priority}}', {\n priority: link.priority,\n })}\n </span>\n {link.dataSink && (\n <button\n type=\"button\"\n onClick={() => handleViewDataSink(link.dataSinkId)}\n className={`inline-flex min-h-[var(--size-controlHeight-md)] items-center rounded-button px-2 text-xs font-medium text-text-link hover:underline sm:min-h-[var(--size-controlHeight-sm)] ${SECTION_FOCUS_RING}`}\n >\n {t('bigconsole.workflows.actions.view', 'View')}\n </button>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </Section>\n\n {/* Record history — lowest-value metadata, recessed. */}\n <Section headingLevel={2} emphasis=\"muted\" title=\"Record history\" padding=\"compact\">\n <dl className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">{t('bigconsole.workflows.view.createdLabel', 'Created')}</dt>\n <dd className=\"text-sm text-text-primary\">\n {formatDistanceToNow(new Date(workflow.createdAt), { addSuffix: true })}\n </dd>\n <dd className=\"truncate text-xs text-text-muted\">\n {t('bigconsole.workflows.view.byAuthor', 'by {{author}}', { author: workflow.createdBy })}\n </dd>\n </div>\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">\n {t('bigconsole.workflows.view.lastUpdatedLabel', 'Last Updated')}\n </dt>\n <dd className=\"text-sm text-text-primary\">\n {formatDistanceToNow(new Date(workflow.updatedAt), { addSuffix: true })}\n </dd>\n <dd className=\"truncate text-xs text-text-muted\">\n {t('bigconsole.workflows.view.byAuthor', 'by {{author}}', {\n author: workflow.updatedBy || workflow.createdBy,\n })}\n </dd>\n </div>\n </dl>\n </Section>\n </SectionStack>\n\n {/* Delete Confirmation Dialog */}\n {workflow && (\n <WorkflowDeleteDialog\n workflow={workflow}\n isOpen={showDeleteConfirm}\n onClose={() => setShowDeleteConfirm(false)}\n onConfirm={handleDelete}\n />\n )}\n </div>\n );\n});\n\nexport default WorkflowViewPage;\n"],"mappings":"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"}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { useWorkflowStore as e } from "../store/workflowStore.js";
|
|
2
2
|
import { useAppNavigate as t } from "../contexts/NavigationContext.js";
|
|
3
3
|
import "../contexts/index.js";
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
4
|
+
import n from "../hooks/useWorkflowOperations.js";
|
|
5
|
+
import { newWorkflowPath as r } from "../BigConsoleRoutes.js";
|
|
6
|
+
import { SECTION_FOCUS_RING as i } from "../components/common/sectionStyles.js";
|
|
7
|
+
import { Section as a, SectionStack as ee } from "../components/common/Section.js";
|
|
6
8
|
import "../components/common/index.js";
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { useI18n as
|
|
18
|
-
import { AuroraBackground as S, Button as C, GradientText as w, IllustratedEmptyState as T, Input as E, PagePurpose as ne, Spinner as re } from "@burdenoff/fe-libs/ui";
|
|
19
|
-
import { Fragment as ie, jsx as D, jsxs as O } from "react/jsx-runtime";
|
|
9
|
+
import { BIGCONSOLE_PERMISSIONS as o } from "../../constants/permissions.js";
|
|
10
|
+
import { isNative as s, nativeNotify as c } from "../../utils/nativeBridge.js";
|
|
11
|
+
import l from "../components/workflow/WorkflowDeleteDialog.js";
|
|
12
|
+
import u from "../components/workflow/WorkflowCard.js";
|
|
13
|
+
import { memo as d, useCallback as f, useMemo as te, useState as p } from "react";
|
|
14
|
+
import { AccessDenied as m, PermissionButton as h } from "@burdenoff/fe-libs/shared/components";
|
|
15
|
+
import { usePermissions as g } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
16
|
+
import { AlertCircle as _, Plus as v, Search as y, Workflow as b } from "lucide-react";
|
|
17
|
+
import { AuroraBackground as ne, Button as x, GradientText as S, IllustratedEmptyState as C, Input as w, PagePurpose as T, Spinner as re } from "@burdenoff/fe-libs/ui";
|
|
18
|
+
import { Fragment as ie, jsx as E, jsxs as D } from "react/jsx-runtime";
|
|
19
|
+
import { useI18n as O } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
20
20
|
//#region src/bigconsole/pages/WorkflowsPage.tsx
|
|
21
|
-
var k =
|
|
22
|
-
let
|
|
21
|
+
var k = d(function() {
|
|
22
|
+
let d = t(), { t: k } = O(), { hasPermission: A, isLoading: j } = g(), M = A(o.WORKFLOW_READ), N = A(o.WORKFLOW_UPDATE), P = A(o.WORKFLOW_DELETE), F = A(o.WORKFLOW_EXECUTE), [I, L] = p("all"), [R, z] = p(null), B = e((e) => e.searchQuery), V = e((e) => e.setSearchQuery), H = e((e) => e.deleteDialogOpen), U = e((e) => e.currentWorkflow), W = e((e) => e.openDeleteDialog), G = e((e) => e.closeDeleteDialog), { loading: K, error: q, workflows: J, deleteWorkflow: Y, refetch: ae } = n(), { executeWorkflow: X } = n({ skipFetch: !0 }), oe = e((e) => e.workflowUIStates), Z = te(() => {
|
|
23
23
|
let e = [...J];
|
|
24
24
|
if (I !== "all" && (e = e.filter((e) => e.status === I)), B.trim()) {
|
|
25
25
|
let t = B.toLowerCase();
|
|
@@ -30,27 +30,27 @@ var k = f(function() {
|
|
|
30
30
|
J,
|
|
31
31
|
I,
|
|
32
32
|
B
|
|
33
|
-
]), Q =
|
|
34
|
-
|
|
35
|
-
}, [
|
|
36
|
-
|
|
37
|
-
}, [
|
|
38
|
-
|
|
39
|
-
}, [
|
|
33
|
+
]), Q = f(() => {
|
|
34
|
+
d(r());
|
|
35
|
+
}, [d]), se = f((e) => {
|
|
36
|
+
d(`/workflows/${e}`);
|
|
37
|
+
}, [d]), ce = f((e) => {
|
|
38
|
+
d(`/workflows/${e}/edit`);
|
|
39
|
+
}, [d]), le = f((e) => {
|
|
40
40
|
let t = J.find((t) => t.id === e);
|
|
41
41
|
t && W(t);
|
|
42
|
-
}, [J, W]), $ =
|
|
42
|
+
}, [J, W]), $ = f(async (e) => {
|
|
43
43
|
let t = J.find((t) => t.id === e);
|
|
44
44
|
if (t) {
|
|
45
45
|
if (z(null), await X(e)) {
|
|
46
|
-
|
|
46
|
+
s() && c("success"), z({
|
|
47
47
|
workflowName: t.name,
|
|
48
48
|
ok: !0,
|
|
49
49
|
message: k("bigconsole.workflows.run.triggered", "Run triggered. The execution count and last-run time update as the run progresses.")
|
|
50
50
|
});
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
s() && c("error"), z({
|
|
54
54
|
workflowName: t.name,
|
|
55
55
|
ok: !1,
|
|
56
56
|
message: k("bigconsole.workflows.run.failed", "The workflow could not be started. Nothing has been changed.")
|
|
@@ -60,12 +60,12 @@ var k = f(function() {
|
|
|
60
60
|
J,
|
|
61
61
|
X,
|
|
62
62
|
k
|
|
63
|
-
]), ue =
|
|
63
|
+
]), ue = f(async () => {
|
|
64
64
|
if (U) {
|
|
65
65
|
try {
|
|
66
|
-
await Y(U.id),
|
|
66
|
+
await Y(U.id), s() && c("success");
|
|
67
67
|
} catch (e) {
|
|
68
|
-
throw
|
|
68
|
+
throw s() && c("error"), e;
|
|
69
69
|
}
|
|
70
70
|
G();
|
|
71
71
|
}
|
|
@@ -99,91 +99,91 @@ var k = f(function() {
|
|
|
99
99
|
label: k("bigconsole.workflows.status.archived", "Archived")
|
|
100
100
|
}
|
|
101
101
|
];
|
|
102
|
-
if (!j && !M) return /* @__PURE__ */
|
|
102
|
+
if (!j && !M) return /* @__PURE__ */ E(m, {
|
|
103
103
|
title: k("bigconsole.workflows.errors.accessDeniedTitle", "Access Denied"),
|
|
104
104
|
description: k("bigconsole.workflows.errors.accessDeniedListDescription", "You don't have permission to view workflows.")
|
|
105
105
|
});
|
|
106
106
|
let fe = !K && J.length === 0, pe = !K && Z.length === 0 && J.length > 0;
|
|
107
|
-
return /* @__PURE__ */
|
|
107
|
+
return /* @__PURE__ */ D("div", {
|
|
108
108
|
className: "min-h-dvh bg-bg-canvas",
|
|
109
109
|
children: [
|
|
110
|
-
/* @__PURE__ */
|
|
110
|
+
/* @__PURE__ */ D("header", {
|
|
111
111
|
"data-section-emphasis": "bare",
|
|
112
112
|
className: "relative min-w-0 overflow-hidden border-b border-[var(--color-border-seam)] bg-[image:var(--gradient-gloss-card)]",
|
|
113
|
-
children: [/* @__PURE__ */
|
|
113
|
+
children: [/* @__PURE__ */ E(ne, { intensity: "subtle" }), /* @__PURE__ */ D("div", {
|
|
114
114
|
className: "relative flex flex-col gap-form-gap p-[var(--space-pagePadding)] sm:flex-row sm:items-center sm:justify-between",
|
|
115
|
-
children: [/* @__PURE__ */
|
|
115
|
+
children: [/* @__PURE__ */ D("div", {
|
|
116
116
|
className: "flex min-w-0 items-center gap-form-gap",
|
|
117
|
-
children: [/* @__PURE__ */
|
|
117
|
+
children: [/* @__PURE__ */ E("span", {
|
|
118
118
|
"aria-hidden": "true",
|
|
119
119
|
className: "flex h-control-lg w-[var(--size-controlHeight-lg)] shrink-0 items-center justify-center rounded-card bg-action-primary-bg",
|
|
120
|
-
children: /* @__PURE__ */
|
|
121
|
-
}), /* @__PURE__ */
|
|
120
|
+
children: /* @__PURE__ */ E(b, { className: "h-icon-lg w-icon-lg text-action-primary-text" })
|
|
121
|
+
}), /* @__PURE__ */ D("div", {
|
|
122
122
|
className: "min-w-0",
|
|
123
|
-
children: [/* @__PURE__ */
|
|
123
|
+
children: [/* @__PURE__ */ E("h1", {
|
|
124
124
|
className: "text-2xl font-bold text-text-primary",
|
|
125
|
-
children: /* @__PURE__ */
|
|
126
|
-
}), /* @__PURE__ */
|
|
125
|
+
children: /* @__PURE__ */ E(S, { children: k("bigconsole.workflows.list.title", "Workflows") })
|
|
126
|
+
}), /* @__PURE__ */ E("p", {
|
|
127
127
|
className: "text-sm text-text-secondary",
|
|
128
128
|
children: k("bigconsole.workflows.list.subtitle", "Design ETL workflows with FluidGrids and link them to DataSinks")
|
|
129
129
|
})]
|
|
130
130
|
})]
|
|
131
|
-
}), /* @__PURE__ */
|
|
131
|
+
}), /* @__PURE__ */ E("div", {
|
|
132
132
|
className: "flex flex-wrap items-center gap-control-gap",
|
|
133
|
-
children: /* @__PURE__ */
|
|
134
|
-
permission:
|
|
133
|
+
children: /* @__PURE__ */ E(h, {
|
|
134
|
+
permission: o.WORKFLOW_CREATE,
|
|
135
135
|
deniedBehavior: "disable",
|
|
136
|
-
children: /* @__PURE__ */
|
|
136
|
+
children: /* @__PURE__ */ D(x, {
|
|
137
137
|
onClick: Q,
|
|
138
|
-
children: [/* @__PURE__ */
|
|
138
|
+
children: [/* @__PURE__ */ E(v, { className: "h-icon-sm w-icon-sm" }), k("bigconsole.workflows.actions.designWorkflow", "Design Workflow")]
|
|
139
139
|
})
|
|
140
140
|
})
|
|
141
141
|
})]
|
|
142
142
|
})]
|
|
143
143
|
}),
|
|
144
|
-
/* @__PURE__ */
|
|
144
|
+
/* @__PURE__ */ E("div", {
|
|
145
145
|
className: "p-[var(--space-pagePadding)]",
|
|
146
|
-
children: /* @__PURE__ */
|
|
146
|
+
children: /* @__PURE__ */ D(ee, { children: [/* @__PURE__ */ E(T, { children: k("bigconsole.workflows.list.purpose", "Workflows are visual ETL jobs built with the FluidGrids builder — they fetch data from external systems, transform it, and load it into your BigConsole DataSinks on a schedule or on demand. Use them to keep dashboards fed with fresh, shaped data without writing glue code.") }), q ? /* @__PURE__ */ E(a, {
|
|
147
147
|
headingLevel: 2,
|
|
148
148
|
tone: "danger",
|
|
149
149
|
title: k("bigconsole.workflows.errors.loadFailedTitle", "Failed to load Workflows"),
|
|
150
150
|
description: "The workflow service did not respond. Nothing has been changed — retry when you are ready.",
|
|
151
|
-
icon: /* @__PURE__ */
|
|
152
|
-
actions: /* @__PURE__ */
|
|
151
|
+
icon: /* @__PURE__ */ E(_, { className: "h-icon-md w-icon-md" }),
|
|
152
|
+
actions: /* @__PURE__ */ E(x, {
|
|
153
153
|
size: "sm",
|
|
154
154
|
onClick: () => ae(),
|
|
155
155
|
children: k("bigconsole.workflows.actions.tryAgain", "Try Again")
|
|
156
156
|
}),
|
|
157
157
|
"data-testid": "workflows-error",
|
|
158
|
-
children: /* @__PURE__ */
|
|
158
|
+
children: /* @__PURE__ */ E("p", {
|
|
159
159
|
className: "break-words text-sm text-[var(--color-status-error-text)]",
|
|
160
160
|
children: q.message
|
|
161
161
|
})
|
|
162
|
-
}) : /* @__PURE__ */
|
|
162
|
+
}) : /* @__PURE__ */ D(ie, { children: [/* @__PURE__ */ E(a, {
|
|
163
163
|
headingLevel: 2,
|
|
164
164
|
title: "Filters",
|
|
165
165
|
description: "Narrow the list by status, or search by name, key or description.",
|
|
166
166
|
padding: "compact",
|
|
167
167
|
"data-testid": "workflows-filters",
|
|
168
|
-
children: /* @__PURE__ */
|
|
168
|
+
children: /* @__PURE__ */ D("div", {
|
|
169
169
|
className: "flex flex-col gap-form-gap lg:flex-row lg:items-center lg:justify-between",
|
|
170
|
-
children: [/* @__PURE__ */
|
|
170
|
+
children: [/* @__PURE__ */ E("div", {
|
|
171
171
|
role: "group",
|
|
172
172
|
"aria-label": "Filter workflows by status",
|
|
173
173
|
className: "flex flex-wrap items-center gap-1 rounded-card bg-bg-sunken p-1",
|
|
174
|
-
children: de.map((e) => /* @__PURE__ */
|
|
174
|
+
children: de.map((e) => /* @__PURE__ */ E("button", {
|
|
175
175
|
type: "button",
|
|
176
176
|
"aria-pressed": I === e.value,
|
|
177
177
|
onClick: () => L(e.value),
|
|
178
|
-
className: `min-h-[var(--size-controlHeight-md)] rounded-button px-3 text-sm font-medium motion-safe:transition-colors ${
|
|
178
|
+
className: `min-h-[var(--size-controlHeight-md)] rounded-button px-3 text-sm font-medium motion-safe:transition-colors ${i} ${I === e.value ? "bg-bg-surface text-text-primary shadow-[var(--shadow-elevation-1)]" : "text-text-secondary hover:text-text-primary"}`,
|
|
179
179
|
children: e.label
|
|
180
180
|
}, e.value))
|
|
181
|
-
}), /* @__PURE__ */
|
|
181
|
+
}), /* @__PURE__ */ D("div", {
|
|
182
182
|
className: "relative w-full lg:max-w-[360px]",
|
|
183
|
-
children: [/* @__PURE__ */
|
|
183
|
+
children: [/* @__PURE__ */ E(y, {
|
|
184
184
|
"aria-hidden": "true",
|
|
185
185
|
className: "pointer-events-none absolute left-3 top-1/2 h-icon-sm w-icon-sm -translate-y-1/2 text-text-muted"
|
|
186
|
-
}), /* @__PURE__ */
|
|
186
|
+
}), /* @__PURE__ */ E(w, {
|
|
187
187
|
type: "text",
|
|
188
188
|
"aria-label": k("bigconsole.workflows.filters.searchPlaceholder", "Search workflows..."),
|
|
189
189
|
placeholder: k("bigconsole.workflows.filters.searchPlaceholder", "Search workflows..."),
|
|
@@ -193,73 +193,73 @@ var k = f(function() {
|
|
|
193
193
|
})]
|
|
194
194
|
})]
|
|
195
195
|
})
|
|
196
|
-
}), /* @__PURE__ */
|
|
196
|
+
}), /* @__PURE__ */ D(a, {
|
|
197
197
|
headingLevel: 2,
|
|
198
198
|
emphasis: "primary",
|
|
199
199
|
title: k("bigconsole.workflows.list.title", "Workflows"),
|
|
200
200
|
description: "Every workflow in this workspace, most recently updated first.",
|
|
201
|
-
meta: /* @__PURE__ */
|
|
201
|
+
meta: /* @__PURE__ */ D("span", {
|
|
202
202
|
className: "rounded-pill bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary",
|
|
203
203
|
children: [Z.length, Z.length === J.length ? "" : ` of ${J.length}`]
|
|
204
204
|
}),
|
|
205
205
|
"data-testid": "workflows-results",
|
|
206
206
|
children: [
|
|
207
|
-
K && J.length === 0 && /* @__PURE__ */
|
|
207
|
+
K && J.length === 0 && /* @__PURE__ */ E("div", {
|
|
208
208
|
className: "flex min-h-[240px] items-center justify-center",
|
|
209
|
-
children: /* @__PURE__ */
|
|
209
|
+
children: /* @__PURE__ */ D("div", {
|
|
210
210
|
className: "text-center",
|
|
211
|
-
children: [/* @__PURE__ */
|
|
211
|
+
children: [/* @__PURE__ */ E(re, {
|
|
212
212
|
size: "lg",
|
|
213
213
|
className: "mb-form-gap"
|
|
214
|
-
}), /* @__PURE__ */
|
|
214
|
+
}), /* @__PURE__ */ E("p", {
|
|
215
215
|
className: "text-sm text-text-muted",
|
|
216
216
|
children: k("bigconsole.workflows.list.loading", "Loading workflows...")
|
|
217
217
|
})]
|
|
218
218
|
})
|
|
219
219
|
}),
|
|
220
|
-
fe && /* @__PURE__ */
|
|
220
|
+
fe && /* @__PURE__ */ E(C, {
|
|
221
221
|
illustration: "empty-data",
|
|
222
222
|
title: k("bigconsole.workflows.list.emptyTitle", "No Workflows yet"),
|
|
223
223
|
description: k("bigconsole.workflows.list.emptyDescription", "Design ETL workflows with the FluidGrids visual builder to fetch, transform, and deliver data into BigConsole DataSinks."),
|
|
224
|
-
action: /* @__PURE__ */
|
|
225
|
-
permission:
|
|
224
|
+
action: /* @__PURE__ */ E(h, {
|
|
225
|
+
permission: o.WORKFLOW_CREATE,
|
|
226
226
|
deniedBehavior: "disable",
|
|
227
|
-
children: /* @__PURE__ */
|
|
227
|
+
children: /* @__PURE__ */ D(x, {
|
|
228
228
|
onClick: Q,
|
|
229
|
-
children: [/* @__PURE__ */
|
|
229
|
+
children: [/* @__PURE__ */ E(v, { className: "h-icon-sm w-icon-sm" }), k("bigconsole.workflows.actions.designWorkflow", "Design Workflow")]
|
|
230
230
|
})
|
|
231
231
|
})
|
|
232
232
|
}),
|
|
233
|
-
pe && /* @__PURE__ */
|
|
233
|
+
pe && /* @__PURE__ */ E(C, {
|
|
234
234
|
illustration: "empty-search",
|
|
235
235
|
title: k("bigconsole.workflows.list.noResultsTitle", "No matching workflows"),
|
|
236
236
|
description: k("bigconsole.workflows.list.noResultsDescription", "No workflows match your filters")
|
|
237
237
|
}),
|
|
238
|
-
R && /* @__PURE__ */
|
|
238
|
+
R && /* @__PURE__ */ D("div", {
|
|
239
239
|
role: "status",
|
|
240
240
|
"aria-live": "polite",
|
|
241
241
|
className: `mb-form-gap flex flex-wrap items-center justify-between gap-icon-gap rounded-input border p-3 text-sm ${R.ok ? "border-[var(--color-status-success-border)] bg-[var(--color-status-success-bgSubtle)] text-[var(--color-status-success-text)]" : "border-[var(--color-status-error-border)] bg-[var(--color-status-error-bgSubtle)] text-[var(--color-status-error-text)]"}`,
|
|
242
242
|
"data-testid": "workflows-run-outcome",
|
|
243
|
-
children: [/* @__PURE__ */
|
|
243
|
+
children: [/* @__PURE__ */ D("span", {
|
|
244
244
|
className: "min-w-0",
|
|
245
245
|
children: [
|
|
246
|
-
/* @__PURE__ */
|
|
246
|
+
/* @__PURE__ */ E("strong", {
|
|
247
247
|
className: "font-semibold",
|
|
248
248
|
children: R.workflowName
|
|
249
249
|
}),
|
|
250
250
|
" — ",
|
|
251
251
|
R.message
|
|
252
252
|
]
|
|
253
|
-
}), /* @__PURE__ */
|
|
253
|
+
}), /* @__PURE__ */ E("button", {
|
|
254
254
|
type: "button",
|
|
255
255
|
onClick: () => z(null),
|
|
256
256
|
className: "rounded-button px-2 py-1 text-xs font-medium underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg-surface",
|
|
257
257
|
children: k("bigconsole.workflows.run.dismiss", "Dismiss")
|
|
258
258
|
})]
|
|
259
259
|
}),
|
|
260
|
-
Z.length > 0 && /* @__PURE__ */
|
|
260
|
+
Z.length > 0 && /* @__PURE__ */ E("div", {
|
|
261
261
|
className: "grid grid-cols-1 gap-form-gap sm:grid-cols-2 xl:grid-cols-3",
|
|
262
|
-
children: Z.map((e) => /* @__PURE__ */
|
|
262
|
+
children: Z.map((e) => /* @__PURE__ */ E(u, {
|
|
263
263
|
workflow: e,
|
|
264
264
|
onView: se,
|
|
265
265
|
onEdit: N ? ce : void 0,
|
|
@@ -271,7 +271,7 @@ var k = f(function() {
|
|
|
271
271
|
]
|
|
272
272
|
})] })] })
|
|
273
273
|
}),
|
|
274
|
-
U && /* @__PURE__ */
|
|
274
|
+
U && /* @__PURE__ */ E(l, {
|
|
275
275
|
workflow: U,
|
|
276
276
|
isOpen: H,
|
|
277
277
|
onClose: G,
|