@burdenoff/microfe-bigconsole 2026.924.2 → 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.
Files changed (124) hide show
  1. package/dist/bigconsole/BigConsoleRoutes.js +137 -138
  2. package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
  3. package/dist/bigconsole/assistant/previewController.js +10 -10
  4. package/dist/bigconsole/components/DrilldownDashboardRenderer.js +17 -17
  5. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +32 -32
  6. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +52 -52
  7. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  8. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +7 -7
  9. package/dist/bigconsole/components/dashboard/DashboardStatusPill.js +53 -0
  10. package/dist/bigconsole/components/dashboard/DashboardStatusPill.js.map +1 -0
  11. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +60 -60
  12. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +21 -21
  13. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +30 -30
  14. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +36 -36
  15. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +34 -34
  16. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +38 -38
  17. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  18. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +121 -121
  19. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  20. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +22 -22
  21. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +46 -46
  22. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +53 -53
  23. package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -1
  24. package/dist/bigconsole/components/dashboard/WidgetPalette.js +47 -47
  25. package/dist/bigconsole/components/dashboard/index.js +1 -0
  26. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +35 -35
  27. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +18 -18
  28. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +20 -20
  29. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +30 -29
  30. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
  31. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +48 -48
  32. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +103 -103
  33. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  34. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +35 -35
  35. package/dist/bigconsole/components/overview/DashboardGuide.js +214 -0
  36. package/dist/bigconsole/components/overview/DashboardGuide.js.map +1 -0
  37. package/dist/bigconsole/components/overview/DataHealthCard.js +97 -0
  38. package/dist/bigconsole/components/overview/DataHealthCard.js.map +1 -0
  39. package/dist/bigconsole/components/overview/OverviewQuickActions.js +32 -0
  40. package/dist/bigconsole/components/overview/OverviewQuickActions.js.map +1 -0
  41. package/dist/bigconsole/components/overview/OverviewStatCard.js +57 -0
  42. package/dist/bigconsole/components/overview/OverviewStatCard.js.map +1 -0
  43. package/dist/bigconsole/components/overview/RecentDashboardsPanel.js +107 -0
  44. package/dist/bigconsole/components/overview/RecentDashboardsPanel.js.map +1 -0
  45. package/dist/bigconsole/components/overview/dashboardGuideSteps.js +119 -0
  46. package/dist/bigconsole/components/overview/dashboardGuideSteps.js.map +1 -0
  47. package/dist/bigconsole/components/overview/index.js +8 -0
  48. package/dist/bigconsole/components/overview/overviewModel.js +119 -0
  49. package/dist/bigconsole/components/overview/overviewModel.js.map +1 -0
  50. package/dist/bigconsole/components/overview/useOverviewData.js +48 -0
  51. package/dist/bigconsole/components/overview/useOverviewData.js.map +1 -0
  52. package/dist/bigconsole/components/parser/DataSinkSelector.js +40 -40
  53. package/dist/bigconsole/components/parser/ImportParserDialog.js +127 -127
  54. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  55. package/dist/bigconsole/components/parser/ParserSelector.js +51 -51
  56. package/dist/bigconsole/components/preview/AiPreviewContent.js +5 -5
  57. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +33 -33
  58. package/dist/bigconsole/components/preview/AiPreviewPanel.js +38 -38
  59. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +13 -13
  60. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +70 -70
  61. package/dist/bigconsole/components/widgets/PropertiesPanel.js +28 -28
  62. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +25 -25
  63. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +48 -48
  64. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +46 -46
  65. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +61 -61
  66. package/dist/bigconsole/components/widgets/form/FormWidget.js +36 -36
  67. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +42 -42
  68. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +25 -25
  69. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +21 -21
  70. package/dist/bigconsole/components/widgets/list/ListConfig.js +30 -30
  71. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +38 -38
  72. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +9 -9
  73. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +9 -9
  74. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +49 -49
  75. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +39 -39
  76. package/dist/bigconsole/components/widgets/table/TableConfig.js +73 -73
  77. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +64 -64
  78. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +10 -10
  79. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +68 -68
  80. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  81. package/dist/bigconsole/pages/AdminPage.js +136 -136
  82. package/dist/bigconsole/pages/DashboardBuilderPage.js +10 -10
  83. package/dist/bigconsole/pages/DashboardViewPage.js +61 -61
  84. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  85. package/dist/bigconsole/pages/DashboardsPage.js +327 -348
  86. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  87. package/dist/bigconsole/pages/DataParsersPage.js +5 -5
  88. package/dist/bigconsole/pages/DataSinkBuilderPage.js +10 -10
  89. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  90. package/dist/bigconsole/pages/DataSinkViewPage.js +83 -83
  91. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  92. package/dist/bigconsole/pages/DataSinksPage.js +11 -11
  93. package/dist/bigconsole/pages/DataSourcesPage.js +5 -5
  94. package/dist/bigconsole/pages/InsightsPage.js +315 -315
  95. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  96. package/dist/bigconsole/pages/OverviewPage.js +244 -0
  97. package/dist/bigconsole/pages/OverviewPage.js.map +1 -0
  98. package/dist/bigconsole/pages/ParserBuilderPage.js +5 -5
  99. package/dist/bigconsole/pages/ParserViewPage.js +98 -98
  100. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  101. package/dist/bigconsole/pages/PipelineBuilderPage.js +8 -8
  102. package/dist/bigconsole/pages/PipelineViewPage.js +46 -46
  103. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  104. package/dist/bigconsole/pages/PipelinesPage.js +80 -80
  105. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  106. package/dist/bigconsole/pages/SettingsPage.js +70 -70
  107. package/dist/bigconsole/pages/WidgetDemoPage.js +42 -42
  108. package/dist/bigconsole/pages/WorkflowViewPage.js +200 -200
  109. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  110. package/dist/bigconsole/pages/WorkflowsPage.js +78 -78
  111. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  112. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +34 -34
  113. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +79 -79
  114. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +46 -46
  115. package/dist/bigconsole/utils/createDialogParam.js +14 -0
  116. package/dist/bigconsole/utils/createDialogParam.js.map +1 -0
  117. package/dist/generated/global-operations.js +1 -1
  118. package/dist/generated/wspace-operations.js +285 -222
  119. package/dist/generated/wspace-operations.js.map +1 -1
  120. package/dist/shared/hooks/useTr.js +10 -7
  121. package/dist/shared/hooks/useTr.js.map +1 -1
  122. package/package.json +1 -1
  123. package/dist/bigconsole/pages/HomePage.js +0 -318
  124. 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":"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"}
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 { SECTION_FOCUS_RING as n } from "../components/common/sectionStyles.js";
5
- import { Section as r, SectionStack as i } from "../components/common/Section.js";
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 a from "../hooks/useWorkflowOperations.js";
8
- import { newWorkflowPath as o } from "../BigConsoleRoutes.js";
9
- import { BIGCONSOLE_PERMISSIONS as s } from "../../constants/permissions.js";
10
- import { isNative as c, nativeNotify as l } from "../../utils/nativeBridge.js";
11
- import u from "../components/workflow/WorkflowDeleteDialog.js";
12
- import d from "../components/workflow/WorkflowCard.js";
13
- import { memo as f, useCallback as p, useMemo as ee, useState as m } from "react";
14
- import { AccessDenied as h, PermissionButton as g } from "@burdenoff/fe-libs/shared/components";
15
- import { usePermissions as _ } from "@burdenoff/fe-libs/shared/providers/shell";
16
- import { AlertCircle as v, Plus as y, Search as b, Workflow as x } from "lucide-react";
17
- import { useI18n as te } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
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 = f(function() {
22
- let f = t(), { t: k } = te(), { hasPermission: A, isLoading: j } = _(), M = A(s.WORKFLOW_READ), N = A(s.WORKFLOW_UPDATE), P = A(s.WORKFLOW_DELETE), F = A(s.WORKFLOW_EXECUTE), [I, L] = m("all"), [R, z] = m(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 } = a(), { executeWorkflow: X } = a({ skipFetch: !0 }), oe = e((e) => e.workflowUIStates), Z = ee(() => {
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 = p(() => {
34
- f(o());
35
- }, [f]), se = p((e) => {
36
- f(`/workflows/${e}`);
37
- }, [f]), ce = p((e) => {
38
- f(`/workflows/${e}/edit`);
39
- }, [f]), le = p((e) => {
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]), $ = p(async (e) => {
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
- c() && l("success"), z({
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
- c() && l("error"), z({
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 = p(async () => {
63
+ ]), ue = f(async () => {
64
64
  if (U) {
65
65
  try {
66
- await Y(U.id), c() && l("success");
66
+ await Y(U.id), s() && c("success");
67
67
  } catch (e) {
68
- throw c() && l("error"), e;
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__ */ D(h, {
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__ */ O("div", {
107
+ return /* @__PURE__ */ D("div", {
108
108
  className: "min-h-dvh bg-bg-canvas",
109
109
  children: [
110
- /* @__PURE__ */ O("header", {
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__ */ D(S, { intensity: "subtle" }), /* @__PURE__ */ O("div", {
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__ */ O("div", {
115
+ children: [/* @__PURE__ */ D("div", {
116
116
  className: "flex min-w-0 items-center gap-form-gap",
117
- children: [/* @__PURE__ */ D("span", {
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__ */ D(x, { className: "h-icon-lg w-icon-lg text-action-primary-text" })
121
- }), /* @__PURE__ */ O("div", {
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__ */ D("h1", {
123
+ children: [/* @__PURE__ */ E("h1", {
124
124
  className: "text-2xl font-bold text-text-primary",
125
- children: /* @__PURE__ */ D(w, { children: k("bigconsole.workflows.list.title", "Workflows") })
126
- }), /* @__PURE__ */ D("p", {
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__ */ D("div", {
131
+ }), /* @__PURE__ */ E("div", {
132
132
  className: "flex flex-wrap items-center gap-control-gap",
133
- children: /* @__PURE__ */ D(g, {
134
- permission: s.WORKFLOW_CREATE,
133
+ children: /* @__PURE__ */ E(h, {
134
+ permission: o.WORKFLOW_CREATE,
135
135
  deniedBehavior: "disable",
136
- children: /* @__PURE__ */ O(C, {
136
+ children: /* @__PURE__ */ D(x, {
137
137
  onClick: Q,
138
- children: [/* @__PURE__ */ D(y, { className: "h-icon-sm w-icon-sm" }), k("bigconsole.workflows.actions.designWorkflow", "Design Workflow")]
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__ */ D("div", {
144
+ /* @__PURE__ */ E("div", {
145
145
  className: "p-[var(--space-pagePadding)]",
146
- children: /* @__PURE__ */ O(i, { children: [/* @__PURE__ */ D(ne, { 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__ */ D(r, {
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__ */ D(v, { className: "h-icon-md w-icon-md" }),
152
- actions: /* @__PURE__ */ D(C, {
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__ */ D("p", {
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__ */ O(ie, { children: [/* @__PURE__ */ D(r, {
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__ */ O("div", {
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__ */ D("div", {
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__ */ D("button", {
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 ${n} ${I === e.value ? "bg-bg-surface text-text-primary shadow-[var(--shadow-elevation-1)]" : "text-text-secondary hover:text-text-primary"}`,
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__ */ O("div", {
181
+ }), /* @__PURE__ */ D("div", {
182
182
  className: "relative w-full lg:max-w-[360px]",
183
- children: [/* @__PURE__ */ D(b, {
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__ */ D(E, {
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__ */ O(r, {
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__ */ O("span", {
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__ */ D("div", {
207
+ K && J.length === 0 && /* @__PURE__ */ E("div", {
208
208
  className: "flex min-h-[240px] items-center justify-center",
209
- children: /* @__PURE__ */ O("div", {
209
+ children: /* @__PURE__ */ D("div", {
210
210
  className: "text-center",
211
- children: [/* @__PURE__ */ D(re, {
211
+ children: [/* @__PURE__ */ E(re, {
212
212
  size: "lg",
213
213
  className: "mb-form-gap"
214
- }), /* @__PURE__ */ D("p", {
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__ */ D(T, {
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__ */ D(g, {
225
- permission: s.WORKFLOW_CREATE,
224
+ action: /* @__PURE__ */ E(h, {
225
+ permission: o.WORKFLOW_CREATE,
226
226
  deniedBehavior: "disable",
227
- children: /* @__PURE__ */ O(C, {
227
+ children: /* @__PURE__ */ D(x, {
228
228
  onClick: Q,
229
- children: [/* @__PURE__ */ D(y, { className: "h-icon-sm w-icon-sm" }), k("bigconsole.workflows.actions.designWorkflow", "Design Workflow")]
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__ */ D(T, {
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__ */ O("div", {
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__ */ O("span", {
243
+ children: [/* @__PURE__ */ D("span", {
244
244
  className: "min-w-0",
245
245
  children: [
246
- /* @__PURE__ */ D("strong", {
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__ */ D("button", {
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__ */ D("div", {
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__ */ D(d, {
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__ */ D(u, {
274
+ U && /* @__PURE__ */ E(l, {
275
275
  workflow: U,
276
276
  isOpen: H,
277
277
  onClose: G,