@burdenoff/microfe-bigconsole 2026.622.1 → 2026.624.2
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 +1 -1
- package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
- package/dist/bigconsole/components/DrilldownModal.js +4 -4
- package/dist/bigconsole/components/DrilldownModal.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +2 -2
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +1 -1
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +28 -28
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +4 -4
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDataViewer.js +2 -2
- package/dist/bigconsole/components/datasink/DataSinkDataViewer.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +2 -2
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +2 -2
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +2 -2
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +25 -25
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedParsersPanel.js +1 -1
- package/dist/bigconsole/components/datasink/LinkedParsersPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +3 -3
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +2 -2
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +2 -2
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
- package/dist/bigconsole/components/parser/DataSinkSelector.js +3 -3
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ImportParserDialog.js +26 -26
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserCard.js +5 -5
- package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +6 -6
- package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserStatusBadge.js +1 -1
- package/dist/bigconsole/components/parser/ParserStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserTypeBadge.js +1 -1
- package/dist/bigconsole/components/parser/ParserTypeBadge.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineCard.js +2 -2
- package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js +1 -1
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +1 -1
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +11 -11
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +17 -17
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetConfigDialog.js +14 -14
- package/dist/bigconsole/components/widgets/WidgetConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetHeader.js +4 -4
- package/dist/bigconsole/components/widgets/WidgetHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js +3 -3
- package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetWrapper.js +266 -238
- package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +2 -2
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
- package/dist/bigconsole/components/widgets/custom/CustomWidget.js +5 -5
- package/dist/bigconsole/components/widgets/custom/CustomWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/LinearGauge.js +1 -1
- package/dist/bigconsole/components/widgets/gauge/LinearGauge.js.map +1 -1
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +2 -2
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi/KPIWidget.js +2 -2
- package/dist/bigconsole/components/widgets/kpi/KPIWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js +2 -2
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListItem.js +3 -3
- package/dist/bigconsole/components/widgets/list/ListItem.js.map +1 -1
- package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +3 -3
- package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/ComparisonBadge.js +1 -1
- package/dist/bigconsole/components/widgets/metric-card/ComparisonBadge.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js +2 -2
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +12 -12
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressBar.js +2 -2
- package/dist/bigconsole/components/widgets/progress/ProgressBar.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressWidget.js +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js +2 -2
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/EmptyState.js +1 -1
- package/dist/bigconsole/components/widgets/states/EmptyState.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableCell.js +1 -1
- package/dist/bigconsole/components/widgets/table/TableCell.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableHeader.js +2 -2
- package/dist/bigconsole/components/widgets/table/TableHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TablePagination.js +4 -4
- package/dist/bigconsole/components/widgets/table/TablePagination.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableWidget.js +5 -5
- package/dist/bigconsole/components/widgets/table/TableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/text-widget/TextWidget.js +1 -1
- package/dist/bigconsole/components/widgets/text-widget/TextWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +3 -3
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/utils/conditionalFormat.js +2 -2
- package/dist/bigconsole/components/widgets/utils/conditionalFormat.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +3 -3
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js +2 -2
- package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +1 -1
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +2 -2
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +2 -2
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +3 -3
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +2 -2
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +5 -5
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +4 -4
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +9 -9
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WidgetDemoPage.js +2 -2
- package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +5 -5
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +12 -12
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BigConsoleRenderer.js +2 -2
- package/dist/bigconsole/renderers/adapters/BigConsoleRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +5 -5
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js +2 -2
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
- package/package.json +1 -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\nimport { memo, useState, useEffect, useCallback } from 'react';\nimport { useParams } from 'react-router-dom';\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// ============================================================================\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 ErrorIcon = ({ 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=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\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 { workflowId } = useParams<{ workflowId: string }>();\n\n // BigConsole context for apiGatewayUrl and authToken\n const { apiGatewayUrl, authToken, workspaceId } = useBigConsole();\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: '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: final.status === 'error' ? 'Failed' : '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: '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: err instanceof Error ? err.message : 'Execution failed',\n executionTimeMs: Date.now() - startTime,\n });\n } finally {\n setIsExecuting(false);\n }\n }, [workflowId, executeWorkflow, fetchWorkflow, pollWorkflowExecution]);\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('Webhook copied');\n setTimeout(() => setWebhookCopied(false), 2000);\n } catch {\n // Clipboard not available\n }\n }, [workflow?.webhookUrl]);\n\n const handleViewDataSink = useCallback(\n (dataSinkId: string) => {\n navigate(`/datasinks/${dataSinkId}`);\n },\n [navigate]\n );\n\n // Loading state — show spinner until initial fetch completes OR during a refetch\n if (!isReady || (loading && !workflow)) {\n return (\n <div className=\"p-6 flex items-center justify-center min-h-[400px]\">\n <svg className=\"w-8 h-8 text-action-primary-bg animate-spin\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n </div>\n );\n }\n\n // Error or not found state — only shown AFTER initial fetch completed\n if (error || !workflow) {\n return (\n <div className=\"p-6\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"inline-flex items-center gap-1 text-sm text-text-secondary hover:text-text-primary mb-4\"\n >\n <ArrowLeftIcon className=\"w-4 h-4\" />\n Back to Workflows\n </button>\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <div className=\"p-3 rounded-full bg-state-error/10 mb-4\">\n <ErrorIcon className=\"w-8 h-8 text-state-error\" />\n </div>\n <h3 className=\"text-lg font-medium text-text-primary mb-2\">Workflow not found</h3>\n <p className=\"text-sm text-text-secondary\">\n {error?.message || 'The workflow you are looking for does not exist.'}\n </p>\n </div>\n </div>\n );\n }\n\n const linkedDataSinkCount = workflow.dataSinkLinks?.length || 0;\n\n return (\n <div className=\"p-6 max-w-5xl mx-auto\">\n {/* Header */}\n <div className=\"mb-8\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"inline-flex items-center gap-1 text-sm text-text-secondary hover:text-text-primary mb-4\"\n >\n <ArrowLeftIcon className=\"w-4 h-4\" />\n Back to Workflows\n </button>\n\n <div className=\"flex items-start justify-between\">\n <div>\n <div className=\"flex items-center gap-3 mb-2\">\n <h1 className=\"text-2xl font-bold text-text-primary\">{workflow.name}</h1>\n <WorkflowStatusBadge status={workflow.status} />\n </div>\n <p className=\"text-sm text-text-secondary font-mono\">{workflow.key}</p>\n {workflow.externalWorkflowId && (\n <p className=\"text-xs text-text-tertiary mt-1\">\n FluidGrids ID: <span className=\"font-mono\">{workflow.externalWorkflowId}</span>\n </p>\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleExecute}\n disabled={isExecuting}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-state-success hover:bg-state-success/90 rounded-md transition-colors disabled:opacity-50\"\n >\n <PlayIcon className=\"w-4 h-4\" />\n {isExecuting ? 'Executing...' : 'Execute'}\n </button>\n <button\n type=\"button\"\n onClick={handleEdit}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-primary bg-bg-muted hover:bg-border-default rounded-md transition-colors\"\n >\n <EditIcon className=\"w-4 h-4\" />\n Edit\n </button>\n <button\n type=\"button\"\n onClick={() => setShowDeleteConfirm(true)}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-state-error bg-state-error/10 hover:bg-state-error/20 rounded-md transition-colors\"\n >\n <TrashIcon className=\"w-4 h-4\" />\n Delete\n </button>\n </div>\n </div>\n </div>\n\n {/* Execution Result */}\n {executionResult && (\n <div\n className={`mb-6 p-4 rounded-lg border ${\n executionResult.success\n ? 'bg-state-success/10 border-state-success/20'\n : 'bg-state-error/10 border-state-error/20'\n }`}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {executionResult.success ? 'Execution Triggered' : 'Execution Failed'}\n </h3>\n <span className=\"text-xs text-text-secondary\">{executionResult.executionTimeMs}ms</span>\n </div>\n {executionResult.error ? (\n <p className=\"text-sm text-state-error\">{executionResult.error}</p>\n ) : (\n <pre className=\"text-xs text-text-secondary font-mono bg-bg-muted p-2 rounded overflow-auto max-h-[200px]\">\n {JSON.stringify(executionResult.output, null, 2)}\n </pre>\n )}\n {executionResult.runId && (\n <p className=\"text-xs text-text-tertiary mt-2\">\n Run ID: <span className=\"font-mono\">{executionResult.runId}</span>\n </p>\n )}\n </div>\n )}\n\n {/* Info Grid */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-8\">\n {/* Description */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Description</h3>\n <p className=\"text-sm text-text-primary\">{workflow.description || 'No description'}</p>\n </div>\n\n {/* Execution Stats */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Execution Stats</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-2xl font-bold text-text-primary\">{workflow.executionCount}</p>\n <p className=\"text-xs text-text-secondary\">Total Executions</p>\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {workflow.lastExecutedAt\n ? formatDistanceToNow(new Date(workflow.lastExecutedAt), { addSuffix: true })\n : 'Never'}\n </p>\n <p className=\"text-xs text-text-secondary\">Last Executed</p>\n </div>\n </div>\n </div>\n </div>\n\n {/* Webhook URL */}\n {workflow.webhookUrl && (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4 mb-8\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Webhook URL</h3>\n <div className=\"flex items-center gap-2\">\n <code className=\"flex-1 text-sm text-text-primary font-mono bg-bg-muted px-3 py-2 rounded overflow-auto\">\n {workflow.webhookUrl}\n </code>\n <button\n type=\"button\"\n onClick={handleCopyWebhook}\n className=\"flex items-center gap-1 px-3 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {webhookCopied ? (\n <>\n <CheckIcon className=\"w-4 h-4 text-state-success\" />\n Copied!\n </>\n ) : (\n <>\n <CopyIcon className=\"w-4 h-4\" />\n Copy\n </>\n )}\n </button>\n </div>\n </div>\n )}\n\n {/* Workflow Design Preview (collapsible) */}\n {workflow.externalWorkflowId && (\n <div className=\"bg-bg-surface border border-border-default rounded-lg mb-8 overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setShowDesignPreview((prev) => !prev)}\n className=\"w-full flex items-center justify-between px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-muted transition-colors\"\n >\n <span>Workflow Design Preview</span>\n <ChevronDownIcon\n className={`w-4 h-4 text-text-secondary transition-transform ${showDesignPreview ? 'rotate-180' : ''}`}\n />\n </button>\n {showDesignPreview && (\n <div className=\"border-t border-border-default\" style={{ height: '450px' }}>\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 </div>\n )}\n\n {/* Linked DataSinks */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4 mb-8\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-4\">Linked DataSinks ({linkedDataSinkCount})</h3>\n {linkedDataSinkCount === 0 ? (\n <p className=\"text-sm text-text-secondary\">No DataSinks linked to this workflow.</p>\n ) : (\n <div className=\"space-y-2\">\n {workflow.dataSinkLinks?.map((link) => (\n <div key={link.id} className=\"flex items-center justify-between px-3 py-2 bg-bg-muted rounded-md\">\n <div className=\"flex items-center gap-3\">\n <DatabaseIcon className=\"w-4 h-4 text-text-secondary\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {link.dataSink?.name || link.dataSink?.key || link.dataSinkId}\n </p>\n {link.dataSink?.key && <p className=\"text-xs text-text-secondary font-mono\">{link.dataSink.key}</p>}\n </div>\n </div>\n <div className=\"flex items-center gap-4\">\n <div className=\"flex items-center gap-2\">\n {link.isEnabled ? (\n <span className=\"text-xs text-state-success\">Enabled</span>\n ) : (\n <span className=\"text-xs text-text-secondary\">Disabled</span>\n )}\n <span className=\"text-xs text-text-secondary\">Priority: {link.priority}</span>\n </div>\n {link.dataSink && (\n <button\n type=\"button\"\n onClick={() => handleViewDataSink(link.dataSinkId)}\n className=\"text-xs text-action-primary-bg hover:underline\"\n >\n View\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Timestamps */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Created</h3>\n <p className=\"text-sm text-text-primary\">\n {formatDistanceToNow(new Date(workflow.createdAt), { addSuffix: true })}\n </p>\n <p className=\"text-xs text-text-secondary\">by {workflow.createdBy}</p>\n </div>\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Last Updated</h3>\n <p className=\"text-sm text-text-primary\">\n {formatDistanceToNow(new Date(workflow.updatedAt), { addSuffix: true })}\n </p>\n <p className=\"text-xs text-text-secondary\">by {workflow.updatedBy || workflow.createdBy}</p>\n </div>\n </div>\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\nimport { memo, useState, useEffect, useCallback } from 'react';\nimport { useParams } from 'react-router-dom';\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// ============================================================================\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 ErrorIcon = ({ 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=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\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 { workflowId } = useParams<{ workflowId: string }>();\n\n // BigConsole context for apiGatewayUrl and authToken\n const { apiGatewayUrl, authToken, workspaceId } = useBigConsole();\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: '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: final.status === 'error' ? 'Failed' : '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: '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: err instanceof Error ? err.message : 'Execution failed',\n executionTimeMs: Date.now() - startTime,\n });\n } finally {\n setIsExecuting(false);\n }\n }, [workflowId, executeWorkflow, fetchWorkflow, pollWorkflowExecution]);\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('Webhook copied');\n setTimeout(() => setWebhookCopied(false), 2000);\n } catch {\n // Clipboard not available\n }\n }, [workflow?.webhookUrl]);\n\n const handleViewDataSink = useCallback(\n (dataSinkId: string) => {\n navigate(`/datasinks/${dataSinkId}`);\n },\n [navigate]\n );\n\n // Loading state — show spinner until initial fetch completes OR during a refetch\n if (!isReady || (loading && !workflow)) {\n return (\n <div className=\"p-6 flex items-center justify-center min-h-[400px]\">\n <svg className=\"w-8 h-8 text-action-primary-bg animate-spin\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n </div>\n );\n }\n\n // Error or not found state — only shown AFTER initial fetch completed\n if (error || !workflow) {\n return (\n <div className=\"p-6\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"inline-flex items-center gap-1 text-sm text-text-secondary hover:text-text-primary mb-4\"\n >\n <ArrowLeftIcon className=\"w-4 h-4\" />\n Back to Workflows\n </button>\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <div className=\"p-3 rounded-full bg-state-error/10 mb-4\">\n <ErrorIcon className=\"w-8 h-8 text-state-error\" />\n </div>\n <h3 className=\"text-lg font-medium text-text-primary mb-2\">Workflow not found</h3>\n <p className=\"text-sm text-text-secondary\">\n {error?.message || 'The workflow you are looking for does not exist.'}\n </p>\n </div>\n </div>\n );\n }\n\n const linkedDataSinkCount = workflow.dataSinkLinks?.length || 0;\n\n return (\n <div className=\"p-6 max-w-5xl mx-auto\">\n {/* Header */}\n <div className=\"mb-8\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"inline-flex items-center gap-1 text-sm text-text-secondary hover:text-text-primary mb-4\"\n >\n <ArrowLeftIcon className=\"w-4 h-4\" />\n Back to Workflows\n </button>\n\n <div className=\"flex items-start justify-between\">\n <div>\n <div className=\"flex items-center gap-3 mb-2\">\n <h1 className=\"text-2xl font-bold text-text-primary\">{workflow.name}</h1>\n <WorkflowStatusBadge status={workflow.status} />\n </div>\n <p className=\"text-sm text-text-secondary font-mono\">{workflow.key}</p>\n {workflow.externalWorkflowId && (\n <p className=\"text-xs text-text-tertiary mt-1\">\n FluidGrids ID: <span className=\"font-mono\">{workflow.externalWorkflowId}</span>\n </p>\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleExecute}\n disabled={isExecuting}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-state-success hover:bg-state-success/90 rounded-md transition-colors disabled:opacity-50\"\n >\n <PlayIcon className=\"w-4 h-4\" />\n {isExecuting ? 'Executing...' : 'Execute'}\n </button>\n <button\n type=\"button\"\n onClick={handleEdit}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-text-primary bg-bg-sunken hover:bg-border-default rounded-md transition-colors\"\n >\n <EditIcon className=\"w-4 h-4\" />\n Edit\n </button>\n <button\n type=\"button\"\n onClick={() => setShowDeleteConfirm(true)}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-state-error bg-state-error/10 hover:bg-state-error/20 rounded-md transition-colors\"\n >\n <TrashIcon className=\"w-4 h-4\" />\n Delete\n </button>\n </div>\n </div>\n </div>\n\n {/* Execution Result */}\n {executionResult && (\n <div\n className={`mb-6 p-4 rounded-lg border ${\n executionResult.success\n ? 'bg-state-success/10 border-state-success/20'\n : 'bg-state-error/10 border-state-error/20'\n }`}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {executionResult.success ? 'Execution Triggered' : 'Execution Failed'}\n </h3>\n <span className=\"text-xs text-text-secondary\">{executionResult.executionTimeMs}ms</span>\n </div>\n {executionResult.error ? (\n <p className=\"text-sm text-state-error\">{executionResult.error}</p>\n ) : (\n <pre className=\"text-xs text-text-secondary font-mono bg-bg-sunken p-2 rounded overflow-auto max-h-[200px]\">\n {JSON.stringify(executionResult.output, null, 2)}\n </pre>\n )}\n {executionResult.runId && (\n <p className=\"text-xs text-text-tertiary mt-2\">\n Run ID: <span className=\"font-mono\">{executionResult.runId}</span>\n </p>\n )}\n </div>\n )}\n\n {/* Info Grid */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6 mb-8\">\n {/* Description */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Description</h3>\n <p className=\"text-sm text-text-primary\">{workflow.description || 'No description'}</p>\n </div>\n\n {/* Execution Stats */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Execution Stats</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-2xl font-bold text-text-primary\">{workflow.executionCount}</p>\n <p className=\"text-xs text-text-secondary\">Total Executions</p>\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {workflow.lastExecutedAt\n ? formatDistanceToNow(new Date(workflow.lastExecutedAt), { addSuffix: true })\n : 'Never'}\n </p>\n <p className=\"text-xs text-text-secondary\">Last Executed</p>\n </div>\n </div>\n </div>\n </div>\n\n {/* Webhook URL */}\n {workflow.webhookUrl && (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4 mb-8\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Webhook URL</h3>\n <div className=\"flex items-center gap-2\">\n <code className=\"flex-1 text-sm text-text-primary font-mono bg-bg-sunken px-3 py-2 rounded overflow-auto\">\n {workflow.webhookUrl}\n </code>\n <button\n type=\"button\"\n onClick={handleCopyWebhook}\n className=\"flex items-center gap-1 px-3 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {webhookCopied ? (\n <>\n <CheckIcon className=\"w-4 h-4 text-state-success\" />\n Copied!\n </>\n ) : (\n <>\n <CopyIcon className=\"w-4 h-4\" />\n Copy\n </>\n )}\n </button>\n </div>\n </div>\n )}\n\n {/* Workflow Design Preview (collapsible) */}\n {workflow.externalWorkflowId && (\n <div className=\"bg-bg-surface border border-border-default rounded-lg mb-8 overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setShowDesignPreview((prev) => !prev)}\n className=\"w-full flex items-center justify-between px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <span>Workflow Design Preview</span>\n <ChevronDownIcon\n className={`w-4 h-4 text-text-secondary transition-transform ${showDesignPreview ? 'rotate-180' : ''}`}\n />\n </button>\n {showDesignPreview && (\n <div className=\"border-t border-border-default\" style={{ height: '450px' }}>\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 </div>\n )}\n\n {/* Linked DataSinks */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4 mb-8\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-4\">Linked DataSinks ({linkedDataSinkCount})</h3>\n {linkedDataSinkCount === 0 ? (\n <p className=\"text-sm text-text-secondary\">No DataSinks linked to this workflow.</p>\n ) : (\n <div className=\"space-y-2\">\n {workflow.dataSinkLinks?.map((link) => (\n <div key={link.id} className=\"flex items-center justify-between px-3 py-2 bg-bg-sunken rounded-md\">\n <div className=\"flex items-center gap-3\">\n <DatabaseIcon className=\"w-4 h-4 text-text-secondary\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {link.dataSink?.name || link.dataSink?.key || link.dataSinkId}\n </p>\n {link.dataSink?.key && <p className=\"text-xs text-text-secondary font-mono\">{link.dataSink.key}</p>}\n </div>\n </div>\n <div className=\"flex items-center gap-4\">\n <div className=\"flex items-center gap-2\">\n {link.isEnabled ? (\n <span className=\"text-xs text-state-success\">Enabled</span>\n ) : (\n <span className=\"text-xs text-text-secondary\">Disabled</span>\n )}\n <span className=\"text-xs text-text-secondary\">Priority: {link.priority}</span>\n </div>\n {link.dataSink && (\n <button\n type=\"button\"\n onClick={() => handleViewDataSink(link.dataSinkId)}\n className=\"text-xs text-action-primary-bg hover:underline\"\n >\n View\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Timestamps */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Created</h3>\n <p className=\"text-sm text-text-primary\">\n {formatDistanceToNow(new Date(workflow.createdAt), { addSuffix: true })}\n </p>\n <p className=\"text-xs text-text-secondary\">by {workflow.createdBy}</p>\n </div>\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">Last Updated</h3>\n <p className=\"text-sm text-text-primary\">\n {formatDistanceToNow(new Date(workflow.updatedAt), { addSuffix: true })}\n </p>\n <p className=\"text-xs text-text-secondary\">by {workflow.updatedBy || workflow.createdBy}</p>\n </div>\n </div>\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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"}
|
|
@@ -364,23 +364,23 @@ var d = new s.HostConfig({
|
|
|
364
364
|
children: /* @__PURE__ */ o("div", {
|
|
365
365
|
className: "animate-pulse space-y-3 w-full",
|
|
366
366
|
children: [
|
|
367
|
-
/* @__PURE__ */ a("div", { className: "h-5 bg-
|
|
367
|
+
/* @__PURE__ */ a("div", { className: "h-5 bg-bg-sunken rounded w-3/4" }),
|
|
368
368
|
/* @__PURE__ */ o("div", {
|
|
369
369
|
className: "flex gap-3",
|
|
370
|
-
children: [/* @__PURE__ */ a("div", { className: "h-10 w-10 bg-
|
|
370
|
+
children: [/* @__PURE__ */ a("div", { className: "h-10 w-10 bg-bg-sunken rounded-full" }), /* @__PURE__ */ o("div", {
|
|
371
371
|
className: "flex-1 space-y-2",
|
|
372
|
-
children: [/* @__PURE__ */ a("div", { className: "h-4 bg-
|
|
372
|
+
children: [/* @__PURE__ */ a("div", { className: "h-4 bg-bg-sunken rounded w-1/2" }), /* @__PURE__ */ a("div", { className: "h-3 bg-bg-sunken rounded w-1/3" })]
|
|
373
373
|
})]
|
|
374
374
|
}),
|
|
375
|
-
/* @__PURE__ */ a("div", { className: "h-4 bg-
|
|
376
|
-
/* @__PURE__ */ a("div", { className: "h-4 bg-
|
|
375
|
+
/* @__PURE__ */ a("div", { className: "h-4 bg-bg-sunken rounded w-full" }),
|
|
376
|
+
/* @__PURE__ */ a("div", { className: "h-4 bg-bg-sunken rounded w-5/6" }),
|
|
377
377
|
/* @__PURE__ */ o("div", {
|
|
378
378
|
className: "grid grid-cols-2 gap-2 mt-4",
|
|
379
379
|
children: [
|
|
380
|
-
/* @__PURE__ */ a("div", { className: "h-3 bg-
|
|
381
|
-
/* @__PURE__ */ a("div", { className: "h-3 bg-
|
|
382
|
-
/* @__PURE__ */ a("div", { className: "h-3 bg-
|
|
383
|
-
/* @__PURE__ */ a("div", { className: "h-3 bg-
|
|
380
|
+
/* @__PURE__ */ a("div", { className: "h-3 bg-bg-sunken rounded" }),
|
|
381
|
+
/* @__PURE__ */ a("div", { className: "h-3 bg-bg-sunken rounded" }),
|
|
382
|
+
/* @__PURE__ */ a("div", { className: "h-3 bg-bg-sunken rounded" }),
|
|
383
|
+
/* @__PURE__ */ a("div", { className: "h-3 bg-bg-sunken rounded" })
|
|
384
384
|
]
|
|
385
385
|
})
|
|
386
386
|
]
|
|
@@ -431,9 +431,9 @@ var d = new s.HostConfig({
|
|
|
431
431
|
className: "text-center max-w-sm",
|
|
432
432
|
children: [
|
|
433
433
|
/* @__PURE__ */ a("div", {
|
|
434
|
-
className: "w-12 h-12 mx-auto mb-3 rounded-full bg-
|
|
434
|
+
className: "w-12 h-12 mx-auto mb-3 rounded-full bg-bg-sunken flex items-center justify-center",
|
|
435
435
|
children: /* @__PURE__ */ a("svg", {
|
|
436
|
-
className: "w-6 h-6 text-
|
|
436
|
+
className: "w-6 h-6 text-text-secondary",
|
|
437
437
|
fill: "none",
|
|
438
438
|
viewBox: "0 0 24 24",
|
|
439
439
|
stroke: "currentColor",
|
|
@@ -450,7 +450,7 @@ var d = new s.HostConfig({
|
|
|
450
450
|
children: "No content"
|
|
451
451
|
}),
|
|
452
452
|
/* @__PURE__ */ a("p", {
|
|
453
|
-
className: "text-sm text-
|
|
453
|
+
className: "text-sm text-text-secondary mt-1",
|
|
454
454
|
children: "Configure a template or provide data to display an Adaptive Card"
|
|
455
455
|
})
|
|
456
456
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdaptiveCardRenderer.js","names":[],"sources":["../../../../src/bigconsole/renderers/adapters/AdaptiveCardRenderer.tsx"],"sourcesContent":["/**\n * Adaptive Card Renderer (v2.1)\n *\n * Renders widgets using the official Microsoft Adaptive Cards SDK.\n * Based on patterns from https://github.com/microsoft/AdaptiveCards\n *\n * Supports full template binding with data context including:\n * - Nested object access: ${creator.name}\n * - Array iteration with $data\n * - Conditional rendering with $when\n * - Date formatting: {{DATE(${field},SHORT)}}\n * - All Adaptive Card elements and actions\n * - Markdown rendering in TextBlocks\n *\n * @see https://adaptivecards.io/\n */\n\nimport React, { memo, useEffect, useRef, useCallback, useState } from 'react';\nimport * as AdaptiveCards from 'adaptivecards';\nimport type { RendererProps } from '../types/renderer';\n\n// Type for the templating module\ntype ACDataModule = typeof import('adaptivecards-templating');\n\n// ============================================================================\n// Fallback Template Expansion (when adaptivecards-templating fails)\n// ============================================================================\n\n/**\n * Simple template expansion fallback.\n * Handles basic ${property}, ${object.property} syntax, and $data iteration.\n * Used when adaptivecards-templating library fails to load.\n */\nfunction expandTemplateFallback(\n template: unknown,\n data: Record<string, unknown>,\n rootData?: Record<string, unknown>\n): unknown {\n // Keep reference to root data for nested expansions\n const root = rootData || data;\n\n if (typeof template === 'string') {\n // Replace ${property} patterns\n return template.replace(/\\$\\{([^}]+)\\}/g, (match, path) => {\n const trimmedPath = path.trim();\n // Try current data first, then root data\n let value = getNestedValue(data, trimmedPath);\n if (value === undefined && root !== data) {\n value = getNestedValue(root, trimmedPath);\n }\n return value !== undefined ? String(value) : match;\n });\n }\n\n if (Array.isArray(template)) {\n return template.flatMap((item) => {\n const expanded = expandTemplateFallback(item, data, root);\n return Array.isArray(expanded) ? expanded : [expanded];\n });\n }\n\n if (template && typeof template === 'object') {\n const templateObj = template as Record<string, unknown>;\n\n // Handle $data iteration\n if ('$data' in templateObj) {\n const dataPath = templateObj.$data;\n let arrayData: unknown[] = [];\n\n if (typeof dataPath === 'string') {\n // Extract array path from ${arrayName} pattern\n const match = dataPath.match(/^\\$\\{([^}]+)\\}$/);\n if (match) {\n const arrValue = getNestedValue(data, match[1].trim()) || getNestedValue(root, match[1].trim());\n if (Array.isArray(arrValue)) {\n arrayData = arrValue;\n }\n }\n } else if (Array.isArray(dataPath)) {\n arrayData = dataPath;\n }\n\n if (arrayData.length > 0) {\n // Create a copy of template without $data for each array item\n const templateWithoutData = Object.fromEntries(Object.entries(templateObj).filter(([key]) => key !== '$data'));\n return arrayData.map((item) => {\n const itemData =\n typeof item === 'object' && item !== null ? (item as Record<string, unknown>) : { value: item };\n // Merge item data with root data for nested references\n const mergedData = { ...root, ...itemData };\n return expandTemplateFallback(templateWithoutData, mergedData, root);\n });\n }\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(templateObj)) {\n if (key === '$data') continue; // Already handled above\n if (key === '$when') continue; // Skip conditional rendering in fallback\n result[key] = expandTemplateFallback(value, data, root);\n }\n return result;\n }\n\n return template;\n}\n\n/**\n * Get nested property value from object using dot notation.\n * e.g., getNestedValue({a: {b: 1}}, 'a.b') => 1\n */\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n// ============================================================================\n// Markdown Processing Setup (from official adaptivecards-react)\n// ============================================================================\n\n/**\n * Simple markdown processor for Adaptive Cards.\n * Handles basic markdown syntax: **bold**, *italic*, [links](url), `code`\n */\nconst processMarkdown = (text: string): string => {\n if (!text) return '';\n\n const html = text\n // Escape HTML first\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n // Bold: **text** or __text__\n .replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>')\n .replace(/__(.+?)__/g, '<strong>$1</strong>')\n // Italic: *text* or _text_\n .replace(/\\*(.+?)\\*/g, '<em>$1</em>')\n .replace(/_(.+?)_/g, '<em>$1</em>')\n // Code: `code`\n .replace(\n /`(.+?)`/g,\n '<code style=\"background:#f3f4f6;padding:0.125rem 0.25rem;border-radius:0.25rem;font-family:monospace;\">$1</code>'\n )\n // Links: [text](url)\n .replace(\n /\\[(.+?)\\]\\((.+?)\\)/g,\n '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"color:#2563eb;text-decoration:underline;\">$1</a>'\n )\n // Line breaks\n .replace(/\\n/g, '<br/>');\n\n return html;\n};\n\n// Set up global markdown processor for Adaptive Cards\nif (!AdaptiveCards.AdaptiveCard.onProcessMarkdown) {\n AdaptiveCards.AdaptiveCard.onProcessMarkdown = (text, result) => {\n result.outputHtml = processMarkdown(text);\n result.didProcess = true;\n };\n}\n\n// ============================================================================\n// Host Config - Customize Adaptive Card appearance\n// ============================================================================\n\nconst hostConfig = new AdaptiveCards.HostConfig({\n fontFamily: 'Inter, system-ui, -apple-system, sans-serif',\n containerStyles: {\n default: {\n backgroundColor: '#ffffff',\n foregroundColors: {\n default: {\n default: '#1f2937',\n subtle: '#6b7280',\n },\n accent: {\n default: '#2563eb',\n subtle: '#3b82f6',\n },\n attention: {\n default: '#dc2626',\n subtle: '#ef4444',\n },\n good: {\n default: '#16a34a',\n subtle: '#22c55e',\n },\n warning: {\n default: '#d97706',\n subtle: '#f59e0b',\n },\n light: {\n default: '#9ca3af',\n subtle: '#d1d5db',\n },\n dark: {\n default: '#111827',\n subtle: '#374151',\n },\n },\n },\n emphasis: {\n backgroundColor: '#f3f4f6',\n foregroundColors: {\n default: {\n default: '#1f2937',\n subtle: '#6b7280',\n },\n accent: {\n default: '#2563eb',\n subtle: '#3b82f6',\n },\n attention: {\n default: '#dc2626',\n subtle: '#ef4444',\n },\n good: {\n default: '#16a34a',\n subtle: '#22c55e',\n },\n warning: {\n default: '#d97706',\n subtle: '#f59e0b',\n },\n light: {\n default: '#9ca3af',\n subtle: '#d1d5db',\n },\n dark: {\n default: '#111827',\n subtle: '#374151',\n },\n },\n },\n },\n spacing: {\n small: 4,\n default: 8,\n medium: 12,\n large: 16,\n extraLarge: 24,\n padding: 16,\n },\n separator: {\n lineThickness: 1,\n lineColor: '#e5e7eb',\n },\n imageSizes: {\n small: 40,\n medium: 80,\n large: 160,\n },\n actions: {\n maxActions: 5,\n spacing: AdaptiveCards.Spacing.Default,\n buttonSpacing: 8,\n showCard: {\n actionMode: AdaptiveCards.ShowCardActionMode.Inline,\n inlineTopMargin: 12,\n },\n actionsOrientation: AdaptiveCards.Orientation.Horizontal,\n actionAlignment: AdaptiveCards.ActionAlignment.Left,\n },\n adaptiveCard: {\n allowCustomStyle: true,\n },\n textBlock: {\n headingLevel: 2,\n },\n factSet: {\n title: {\n color: AdaptiveCards.TextColor.Default,\n size: AdaptiveCards.TextSize.Default,\n isSubtle: true,\n weight: AdaptiveCards.TextWeight.Bolder,\n wrap: true,\n },\n value: {\n color: AdaptiveCards.TextColor.Default,\n size: AdaptiveCards.TextSize.Default,\n isSubtle: false,\n weight: AdaptiveCards.TextWeight.Default,\n wrap: true,\n },\n spacing: 8,\n },\n});\n\n// Dark mode host config - duplicating base config with dark overrides\nconst darkHostConfig = new AdaptiveCards.HostConfig({\n fontFamily: 'Inter, system-ui, -apple-system, sans-serif',\n spacing: {\n small: 4,\n default: 8,\n medium: 12,\n large: 16,\n extraLarge: 24,\n padding: 16,\n },\n imageSizes: {\n small: 40,\n medium: 80,\n large: 160,\n },\n actions: {\n maxActions: 5,\n spacing: AdaptiveCards.Spacing.Default,\n buttonSpacing: 8,\n showCard: {\n actionMode: AdaptiveCards.ShowCardActionMode.Inline,\n inlineTopMargin: 12,\n },\n actionsOrientation: AdaptiveCards.Orientation.Horizontal,\n actionAlignment: AdaptiveCards.ActionAlignment.Left,\n },\n adaptiveCard: {\n allowCustomStyle: true,\n },\n textBlock: {\n headingLevel: 2,\n },\n factSet: {\n title: {\n color: AdaptiveCards.TextColor.Default,\n size: AdaptiveCards.TextSize.Default,\n isSubtle: true,\n weight: AdaptiveCards.TextWeight.Bolder,\n wrap: true,\n },\n value: {\n color: AdaptiveCards.TextColor.Default,\n size: AdaptiveCards.TextSize.Default,\n isSubtle: false,\n weight: AdaptiveCards.TextWeight.Default,\n wrap: true,\n },\n spacing: 8,\n },\n containerStyles: {\n default: {\n backgroundColor: '#111827',\n foregroundColors: {\n default: {\n default: '#f9fafb',\n subtle: '#9ca3af',\n },\n accent: {\n default: '#60a5fa',\n subtle: '#3b82f6',\n },\n attention: {\n default: '#f87171',\n subtle: '#ef4444',\n },\n good: {\n default: '#4ade80',\n subtle: '#22c55e',\n },\n warning: {\n default: '#fbbf24',\n subtle: '#f59e0b',\n },\n light: {\n default: '#d1d5db',\n subtle: '#9ca3af',\n },\n dark: {\n default: '#f9fafb',\n subtle: '#e5e7eb',\n },\n },\n },\n emphasis: {\n backgroundColor: '#1f2937',\n foregroundColors: {\n default: {\n default: '#f9fafb',\n subtle: '#9ca3af',\n },\n accent: {\n default: '#60a5fa',\n subtle: '#3b82f6',\n },\n attention: {\n default: '#f87171',\n subtle: '#ef4444',\n },\n good: {\n default: '#4ade80',\n subtle: '#22c55e',\n },\n warning: {\n default: '#fbbf24',\n subtle: '#f59e0b',\n },\n light: {\n default: '#d1d5db',\n subtle: '#9ca3af',\n },\n dark: {\n default: '#f9fafb',\n subtle: '#e5e7eb',\n },\n },\n },\n },\n separator: {\n lineThickness: 1,\n lineColor: '#374151',\n },\n});\n\n// ============================================================================\n// Main Renderer Component\n// ============================================================================\n\nexport const AdaptiveCardRenderer: React.FC<RendererProps> = memo(function AdaptiveCardRenderer({\n widget,\n data,\n template,\n isLoading,\n error,\n onAction,\n}) {\n const containerRef = useRef<HTMLDivElement>(null);\n const cardRef = useRef<AdaptiveCards.AdaptiveCard | null>(null);\n const [renderError, setRenderError] = useState<string | null>(null);\n const [isDarkMode, setIsDarkMode] = useState(false);\n const [templateWarnings, setTemplateWarnings] = useState<string[]>([]);\n const [acDataModule, setAcDataModule] = useState<ACDataModule | null>(null);\n const [templatingError, setTemplatingError] = useState<string | null>(null);\n\n // Load adaptivecards-templating dynamically to avoid Node.js polyfill issues\n useEffect(() => {\n let mounted = true;\n\n import('adaptivecards-templating')\n .then((module) => {\n if (mounted) {\n setAcDataModule(module);\n }\n })\n .catch((err) => {\n if (mounted) {\n setTemplatingError(err.message || 'Failed to load templating library');\n }\n });\n\n return () => {\n mounted = false;\n };\n }, []);\n\n // Detect dark mode\n useEffect(() => {\n const checkDarkMode = () => {\n setIsDarkMode(document.documentElement.classList.contains('dark'));\n };\n checkDarkMode();\n\n // Watch for changes\n const observer = new MutationObserver(checkDarkMode);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n return () => observer.disconnect();\n }, []);\n\n // Handle action execution\n const handleAction = useCallback(\n (action: AdaptiveCards.Action) => {\n if (action instanceof AdaptiveCards.OpenUrlAction) {\n // Open URL in new tab\n if (action.url) {\n window.open(action.url, '_blank', 'noopener,noreferrer');\n }\n } else if (action instanceof AdaptiveCards.SubmitAction) {\n // Call onAction callback with action data\n if (onAction) {\n onAction(action.title || 'submit', (action.data as Record<string, unknown>) || {});\n }\n } else if (action instanceof AdaptiveCards.ExecuteAction) {\n // Call onAction callback with verb and data\n if (onAction) {\n onAction(action.verb || 'execute', (action.data as Record<string, unknown>) || {});\n }\n } else if (action instanceof AdaptiveCards.ShowCardAction) {\n // ShowCard is handled inline by the SDK\n } else {\n }\n },\n [onAction]\n );\n\n // Render the Adaptive Card\n useEffect(() => {\n if (!containerRef.current) return;\n if (isLoading) return;\n\n // Clear previous content safely\n containerRef.current.innerHTML = '';\n setRenderError(null);\n setTemplateWarnings([]);\n\n // Debug logging\n\n try {\n let cardPayload: object | null = null;\n let warnings: string[] = [];\n\n // Determine the card payload\n if (template) {\n // We have a template - use templating engine if available\n const templateObj = typeof template === 'string' ? JSON.parse(template) : template;\n\n if (acDataModule) {\n try {\n // Create template instance using dynamically loaded module\n const cardTemplate = new acDataModule.Template(templateObj);\n\n // Create evaluation context with data\n // Supports $root for data, $host for host application context\n const context = {\n $root: data || {},\n $host: {\n widgetId: widget?.id,\n widgetTitle: widget?.title,\n theme: isDarkMode ? 'dark' : 'light',\n },\n };\n\n // Expand template with data\n cardPayload = cardTemplate.expand(context);\n\n // Capture any template expansion warnings\n warnings = cardTemplate.getLastTemplateExpansionWarnings();\n if (warnings.length > 0) {\n setTemplateWarnings(warnings);\n }\n } catch (templatingErr) {\n // Templating library threw an error - use fallback\n cardPayload = expandTemplateFallback(templateObj, (data || {}) as Record<string, unknown>) as object;\n warnings.push('Using simplified template expansion (some features may not work)');\n setTemplateWarnings(warnings);\n }\n } else {\n // Templating not available - use fallback expansion\n cardPayload = expandTemplateFallback(templateObj, (data || {}) as Record<string, unknown>) as object;\n if (templatingError) {\n warnings.push(`Using fallback expansion: ${templatingError}`);\n setTemplateWarnings(warnings);\n }\n }\n } else if (data && typeof data === 'object' && 'type' in data && data.type === 'AdaptiveCard') {\n // Data is already an Adaptive Card\n cardPayload = data;\n } else if (data && typeof data === 'object' && 'body' in data) {\n // Data has body property - treat as Adaptive Card\n cardPayload = {\n type: 'AdaptiveCard',\n version: '1.6',\n ...data,\n };\n }\n\n if (!cardPayload) {\n setRenderError('No template or valid Adaptive Card data provided');\n return;\n }\n\n // Create or reuse Adaptive Card instance\n if (!cardRef.current) {\n cardRef.current = new AdaptiveCards.AdaptiveCard();\n }\n const adaptiveCard = cardRef.current;\n\n // Set host config based on theme\n adaptiveCard.hostConfig = isDarkMode ? darkHostConfig : hostConfig;\n\n // Set action handler\n adaptiveCard.onExecuteAction = handleAction;\n\n // Parse the card payload\n adaptiveCard.parse(cardPayload);\n\n // Render to HTML element\n const renderedCard = adaptiveCard.render();\n\n if (renderedCard) {\n // Apply additional styling\n renderedCard.style.height = '100%';\n renderedCard.style.overflow = 'auto';\n\n // Add class for styling consistency\n renderedCard.classList.add('adaptive-card-container');\n\n // Append to container\n containerRef.current.appendChild(renderedCard);\n } else {\n setRenderError('Failed to render Adaptive Card');\n }\n } catch (e) {\n setRenderError((e as Error).message || 'Unknown error rendering card');\n }\n }, [template, data, widget, isLoading, isDarkMode, handleAction, acDataModule, templatingError]);\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center h-full p-4 animate-in fade-in duration-200\">\n <div className=\"animate-pulse space-y-3 w-full\">\n <div className=\"h-5 bg-muted rounded w-3/4\" />\n <div className=\"flex gap-3\">\n <div className=\"h-10 w-10 bg-muted rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 bg-muted rounded w-1/2\" />\n <div className=\"h-3 bg-muted rounded w-1/3\" />\n </div>\n </div>\n <div className=\"h-4 bg-muted rounded w-full\" />\n <div className=\"h-4 bg-muted rounded w-5/6\" />\n <div className=\"grid grid-cols-2 gap-2 mt-4\">\n <div className=\"h-3 bg-muted rounded\" />\n <div className=\"h-3 bg-muted rounded\" />\n <div className=\"h-3 bg-muted rounded\" />\n <div className=\"h-3 bg-muted rounded\" />\n </div>\n </div>\n </div>\n );\n }\n\n // Error state\n if (error || renderError) {\n return (\n <div className=\"flex items-center justify-center h-full p-4\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-12 h-12 mx-auto mb-3 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center\">\n <svg\n className=\"w-6 h-6 text-red-600 dark:text-red-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <p className=\"font-medium text-state-error\">Error rendering card</p>\n <p className=\"text-sm text-secondary mt-1\">{error || renderError}</p>\n {templateWarnings.length > 0 && (\n <div className=\"mt-3 p-2 bg-yellow-50 dark:bg-yellow-900/20 rounded text-left\">\n <p className=\"text-xs font-medium text-yellow-700 dark:text-yellow-400 mb-1\">Template Warnings:</p>\n {templateWarnings.map((warning, i) => (\n <p key={i} className=\"text-xs text-yellow-600 dark:text-yellow-300\">\n {warning}\n </p>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Empty state - no template or data\n if (!template && !data) {\n return (\n <div className=\"flex items-center justify-center h-full p-4 animate-in fade-in duration-200\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-12 h-12 mx-auto mb-3 rounded-full bg-muted flex items-center justify-center\">\n <svg className=\"w-6 h-6 text-muted-foreground\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n </div>\n <p className=\"font-medium text-secondary\">No content</p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Configure a template or provide data to display an Adaptive Card\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div\n ref={containerRef}\n className=\"adaptive-card-wrapper h-full overflow-auto\"\n style={{\n // CSS custom properties for further customization\n ['--ac-font-family' as string]: 'Inter, system-ui, -apple-system, sans-serif',\n }}\n />\n );\n});\n\n// ============================================================================\n// Global Styles for Adaptive Cards\n// ============================================================================\n\n// Inject global styles for Adaptive Cards\nconst styleId = 'adaptive-card-global-styles';\nif (typeof document !== 'undefined' && !document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n .adaptive-card-wrapper {\n font-family: Inter, system-ui, -apple-system, sans-serif;\n }\n\n .adaptive-card-wrapper .ac-textBlock {\n font-family: inherit;\n }\n\n .adaptive-card-wrapper .ac-image.ac-image-person {\n border-radius: 50%;\n object-fit: cover;\n }\n\n .adaptive-card-wrapper .ac-pushButton {\n font-family: inherit;\n font-weight: 500;\n border-radius: 0.375rem;\n padding: 0.5rem 1rem;\n transition: all 0.15s ease-in-out;\n }\n\n .adaptive-card-wrapper .ac-pushButton:hover {\n filter: brightness(0.95);\n }\n\n .adaptive-card-wrapper .ac-input {\n font-family: inherit;\n border-radius: 0.375rem;\n border: 1px solid #d1d5db;\n padding: 0.5rem 0.75rem;\n }\n\n .dark .adaptive-card-wrapper .ac-input {\n border-color: #4b5563;\n background-color: #1f2937;\n color: #f9fafb;\n }\n\n .adaptive-card-wrapper .ac-input:focus {\n outline: none;\n ring: 2px;\n ring-color: #3b82f6;\n }\n\n .adaptive-card-wrapper .ac-separator {\n margin: 0.5rem 0;\n }\n\n .adaptive-card-wrapper .ac-factSet {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: 0.25rem 1rem;\n }\n\n .adaptive-card-wrapper .ac-fact-title {\n color: #6b7280;\n }\n\n .dark .adaptive-card-wrapper .ac-fact-title {\n color: #9ca3af;\n }\n\n .adaptive-card-wrapper .ac-actionSet {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid #e5e7eb;\n }\n\n .dark .adaptive-card-wrapper .ac-actionSet {\n border-top-color: #374151;\n }\n\n /* Markdown rendered code blocks in dark mode */\n .dark .adaptive-card-wrapper code {\n background: #374151 !important;\n color: #f9fafb !important;\n }\n\n /* Markdown links in dark mode */\n .dark .adaptive-card-wrapper a {\n color: #60a5fa !important;\n }\n\n /* TextBlock with markdown - ensure proper wrapping */\n .adaptive-card-wrapper .ac-textBlock p {\n margin: 0;\n }\n\n .adaptive-card-wrapper .ac-textBlock strong {\n font-weight: 600;\n }\n\n .adaptive-card-wrapper .ac-textBlock em {\n font-style: italic;\n }\n `;\n document.head.appendChild(style);\n}\n\nexport default AdaptiveCardRenderer;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AdaptiveCardRenderer.js","names":[],"sources":["../../../../src/bigconsole/renderers/adapters/AdaptiveCardRenderer.tsx"],"sourcesContent":["/**\n * Adaptive Card Renderer (v2.1)\n *\n * Renders widgets using the official Microsoft Adaptive Cards SDK.\n * Based on patterns from https://github.com/microsoft/AdaptiveCards\n *\n * Supports full template binding with data context including:\n * - Nested object access: ${creator.name}\n * - Array iteration with $data\n * - Conditional rendering with $when\n * - Date formatting: {{DATE(${field},SHORT)}}\n * - All Adaptive Card elements and actions\n * - Markdown rendering in TextBlocks\n *\n * @see https://adaptivecards.io/\n */\n\nimport React, { memo, useEffect, useRef, useCallback, useState } from 'react';\nimport * as AdaptiveCards from 'adaptivecards';\nimport type { RendererProps } from '../types/renderer';\n\n// Type for the templating module\ntype ACDataModule = typeof import('adaptivecards-templating');\n\n// ============================================================================\n// Fallback Template Expansion (when adaptivecards-templating fails)\n// ============================================================================\n\n/**\n * Simple template expansion fallback.\n * Handles basic ${property}, ${object.property} syntax, and $data iteration.\n * Used when adaptivecards-templating library fails to load.\n */\nfunction expandTemplateFallback(\n template: unknown,\n data: Record<string, unknown>,\n rootData?: Record<string, unknown>\n): unknown {\n // Keep reference to root data for nested expansions\n const root = rootData || data;\n\n if (typeof template === 'string') {\n // Replace ${property} patterns\n return template.replace(/\\$\\{([^}]+)\\}/g, (match, path) => {\n const trimmedPath = path.trim();\n // Try current data first, then root data\n let value = getNestedValue(data, trimmedPath);\n if (value === undefined && root !== data) {\n value = getNestedValue(root, trimmedPath);\n }\n return value !== undefined ? String(value) : match;\n });\n }\n\n if (Array.isArray(template)) {\n return template.flatMap((item) => {\n const expanded = expandTemplateFallback(item, data, root);\n return Array.isArray(expanded) ? expanded : [expanded];\n });\n }\n\n if (template && typeof template === 'object') {\n const templateObj = template as Record<string, unknown>;\n\n // Handle $data iteration\n if ('$data' in templateObj) {\n const dataPath = templateObj.$data;\n let arrayData: unknown[] = [];\n\n if (typeof dataPath === 'string') {\n // Extract array path from ${arrayName} pattern\n const match = dataPath.match(/^\\$\\{([^}]+)\\}$/);\n if (match) {\n const arrValue = getNestedValue(data, match[1].trim()) || getNestedValue(root, match[1].trim());\n if (Array.isArray(arrValue)) {\n arrayData = arrValue;\n }\n }\n } else if (Array.isArray(dataPath)) {\n arrayData = dataPath;\n }\n\n if (arrayData.length > 0) {\n // Create a copy of template without $data for each array item\n const templateWithoutData = Object.fromEntries(Object.entries(templateObj).filter(([key]) => key !== '$data'));\n return arrayData.map((item) => {\n const itemData =\n typeof item === 'object' && item !== null ? (item as Record<string, unknown>) : { value: item };\n // Merge item data with root data for nested references\n const mergedData = { ...root, ...itemData };\n return expandTemplateFallback(templateWithoutData, mergedData, root);\n });\n }\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(templateObj)) {\n if (key === '$data') continue; // Already handled above\n if (key === '$when') continue; // Skip conditional rendering in fallback\n result[key] = expandTemplateFallback(value, data, root);\n }\n return result;\n }\n\n return template;\n}\n\n/**\n * Get nested property value from object using dot notation.\n * e.g., getNestedValue({a: {b: 1}}, 'a.b') => 1\n */\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n// ============================================================================\n// Markdown Processing Setup (from official adaptivecards-react)\n// ============================================================================\n\n/**\n * Simple markdown processor for Adaptive Cards.\n * Handles basic markdown syntax: **bold**, *italic*, [links](url), `code`\n */\nconst processMarkdown = (text: string): string => {\n if (!text) return '';\n\n const html = text\n // Escape HTML first\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n // Bold: **text** or __text__\n .replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>')\n .replace(/__(.+?)__/g, '<strong>$1</strong>')\n // Italic: *text* or _text_\n .replace(/\\*(.+?)\\*/g, '<em>$1</em>')\n .replace(/_(.+?)_/g, '<em>$1</em>')\n // Code: `code`\n .replace(\n /`(.+?)`/g,\n '<code style=\"background:#f3f4f6;padding:0.125rem 0.25rem;border-radius:0.25rem;font-family:monospace;\">$1</code>'\n )\n // Links: [text](url)\n .replace(\n /\\[(.+?)\\]\\((.+?)\\)/g,\n '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"color:#2563eb;text-decoration:underline;\">$1</a>'\n )\n // Line breaks\n .replace(/\\n/g, '<br/>');\n\n return html;\n};\n\n// Set up global markdown processor for Adaptive Cards\nif (!AdaptiveCards.AdaptiveCard.onProcessMarkdown) {\n AdaptiveCards.AdaptiveCard.onProcessMarkdown = (text, result) => {\n result.outputHtml = processMarkdown(text);\n result.didProcess = true;\n };\n}\n\n// ============================================================================\n// Host Config - Customize Adaptive Card appearance\n// ============================================================================\n\nconst hostConfig = new AdaptiveCards.HostConfig({\n fontFamily: 'Inter, system-ui, -apple-system, sans-serif',\n containerStyles: {\n default: {\n backgroundColor: '#ffffff',\n foregroundColors: {\n default: {\n default: '#1f2937',\n subtle: '#6b7280',\n },\n accent: {\n default: '#2563eb',\n subtle: '#3b82f6',\n },\n attention: {\n default: '#dc2626',\n subtle: '#ef4444',\n },\n good: {\n default: '#16a34a',\n subtle: '#22c55e',\n },\n warning: {\n default: '#d97706',\n subtle: '#f59e0b',\n },\n light: {\n default: '#9ca3af',\n subtle: '#d1d5db',\n },\n dark: {\n default: '#111827',\n subtle: '#374151',\n },\n },\n },\n emphasis: {\n backgroundColor: '#f3f4f6',\n foregroundColors: {\n default: {\n default: '#1f2937',\n subtle: '#6b7280',\n },\n accent: {\n default: '#2563eb',\n subtle: '#3b82f6',\n },\n attention: {\n default: '#dc2626',\n subtle: '#ef4444',\n },\n good: {\n default: '#16a34a',\n subtle: '#22c55e',\n },\n warning: {\n default: '#d97706',\n subtle: '#f59e0b',\n },\n light: {\n default: '#9ca3af',\n subtle: '#d1d5db',\n },\n dark: {\n default: '#111827',\n subtle: '#374151',\n },\n },\n },\n },\n spacing: {\n small: 4,\n default: 8,\n medium: 12,\n large: 16,\n extraLarge: 24,\n padding: 16,\n },\n separator: {\n lineThickness: 1,\n lineColor: '#e5e7eb',\n },\n imageSizes: {\n small: 40,\n medium: 80,\n large: 160,\n },\n actions: {\n maxActions: 5,\n spacing: AdaptiveCards.Spacing.Default,\n buttonSpacing: 8,\n showCard: {\n actionMode: AdaptiveCards.ShowCardActionMode.Inline,\n inlineTopMargin: 12,\n },\n actionsOrientation: AdaptiveCards.Orientation.Horizontal,\n actionAlignment: AdaptiveCards.ActionAlignment.Left,\n },\n adaptiveCard: {\n allowCustomStyle: true,\n },\n textBlock: {\n headingLevel: 2,\n },\n factSet: {\n title: {\n color: AdaptiveCards.TextColor.Default,\n size: AdaptiveCards.TextSize.Default,\n isSubtle: true,\n weight: AdaptiveCards.TextWeight.Bolder,\n wrap: true,\n },\n value: {\n color: AdaptiveCards.TextColor.Default,\n size: AdaptiveCards.TextSize.Default,\n isSubtle: false,\n weight: AdaptiveCards.TextWeight.Default,\n wrap: true,\n },\n spacing: 8,\n },\n});\n\n// Dark mode host config - duplicating base config with dark overrides\nconst darkHostConfig = new AdaptiveCards.HostConfig({\n fontFamily: 'Inter, system-ui, -apple-system, sans-serif',\n spacing: {\n small: 4,\n default: 8,\n medium: 12,\n large: 16,\n extraLarge: 24,\n padding: 16,\n },\n imageSizes: {\n small: 40,\n medium: 80,\n large: 160,\n },\n actions: {\n maxActions: 5,\n spacing: AdaptiveCards.Spacing.Default,\n buttonSpacing: 8,\n showCard: {\n actionMode: AdaptiveCards.ShowCardActionMode.Inline,\n inlineTopMargin: 12,\n },\n actionsOrientation: AdaptiveCards.Orientation.Horizontal,\n actionAlignment: AdaptiveCards.ActionAlignment.Left,\n },\n adaptiveCard: {\n allowCustomStyle: true,\n },\n textBlock: {\n headingLevel: 2,\n },\n factSet: {\n title: {\n color: AdaptiveCards.TextColor.Default,\n size: AdaptiveCards.TextSize.Default,\n isSubtle: true,\n weight: AdaptiveCards.TextWeight.Bolder,\n wrap: true,\n },\n value: {\n color: AdaptiveCards.TextColor.Default,\n size: AdaptiveCards.TextSize.Default,\n isSubtle: false,\n weight: AdaptiveCards.TextWeight.Default,\n wrap: true,\n },\n spacing: 8,\n },\n containerStyles: {\n default: {\n backgroundColor: '#111827',\n foregroundColors: {\n default: {\n default: '#f9fafb',\n subtle: '#9ca3af',\n },\n accent: {\n default: '#60a5fa',\n subtle: '#3b82f6',\n },\n attention: {\n default: '#f87171',\n subtle: '#ef4444',\n },\n good: {\n default: '#4ade80',\n subtle: '#22c55e',\n },\n warning: {\n default: '#fbbf24',\n subtle: '#f59e0b',\n },\n light: {\n default: '#d1d5db',\n subtle: '#9ca3af',\n },\n dark: {\n default: '#f9fafb',\n subtle: '#e5e7eb',\n },\n },\n },\n emphasis: {\n backgroundColor: '#1f2937',\n foregroundColors: {\n default: {\n default: '#f9fafb',\n subtle: '#9ca3af',\n },\n accent: {\n default: '#60a5fa',\n subtle: '#3b82f6',\n },\n attention: {\n default: '#f87171',\n subtle: '#ef4444',\n },\n good: {\n default: '#4ade80',\n subtle: '#22c55e',\n },\n warning: {\n default: '#fbbf24',\n subtle: '#f59e0b',\n },\n light: {\n default: '#d1d5db',\n subtle: '#9ca3af',\n },\n dark: {\n default: '#f9fafb',\n subtle: '#e5e7eb',\n },\n },\n },\n },\n separator: {\n lineThickness: 1,\n lineColor: '#374151',\n },\n});\n\n// ============================================================================\n// Main Renderer Component\n// ============================================================================\n\nexport const AdaptiveCardRenderer: React.FC<RendererProps> = memo(function AdaptiveCardRenderer({\n widget,\n data,\n template,\n isLoading,\n error,\n onAction,\n}) {\n const containerRef = useRef<HTMLDivElement>(null);\n const cardRef = useRef<AdaptiveCards.AdaptiveCard | null>(null);\n const [renderError, setRenderError] = useState<string | null>(null);\n const [isDarkMode, setIsDarkMode] = useState(false);\n const [templateWarnings, setTemplateWarnings] = useState<string[]>([]);\n const [acDataModule, setAcDataModule] = useState<ACDataModule | null>(null);\n const [templatingError, setTemplatingError] = useState<string | null>(null);\n\n // Load adaptivecards-templating dynamically to avoid Node.js polyfill issues\n useEffect(() => {\n let mounted = true;\n\n import('adaptivecards-templating')\n .then((module) => {\n if (mounted) {\n setAcDataModule(module);\n }\n })\n .catch((err) => {\n if (mounted) {\n setTemplatingError(err.message || 'Failed to load templating library');\n }\n });\n\n return () => {\n mounted = false;\n };\n }, []);\n\n // Detect dark mode\n useEffect(() => {\n const checkDarkMode = () => {\n setIsDarkMode(document.documentElement.classList.contains('dark'));\n };\n checkDarkMode();\n\n // Watch for changes\n const observer = new MutationObserver(checkDarkMode);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n return () => observer.disconnect();\n }, []);\n\n // Handle action execution\n const handleAction = useCallback(\n (action: AdaptiveCards.Action) => {\n if (action instanceof AdaptiveCards.OpenUrlAction) {\n // Open URL in new tab\n if (action.url) {\n window.open(action.url, '_blank', 'noopener,noreferrer');\n }\n } else if (action instanceof AdaptiveCards.SubmitAction) {\n // Call onAction callback with action data\n if (onAction) {\n onAction(action.title || 'submit', (action.data as Record<string, unknown>) || {});\n }\n } else if (action instanceof AdaptiveCards.ExecuteAction) {\n // Call onAction callback with verb and data\n if (onAction) {\n onAction(action.verb || 'execute', (action.data as Record<string, unknown>) || {});\n }\n } else if (action instanceof AdaptiveCards.ShowCardAction) {\n // ShowCard is handled inline by the SDK\n } else {\n }\n },\n [onAction]\n );\n\n // Render the Adaptive Card\n useEffect(() => {\n if (!containerRef.current) return;\n if (isLoading) return;\n\n // Clear previous content safely\n containerRef.current.innerHTML = '';\n setRenderError(null);\n setTemplateWarnings([]);\n\n // Debug logging\n\n try {\n let cardPayload: object | null = null;\n let warnings: string[] = [];\n\n // Determine the card payload\n if (template) {\n // We have a template - use templating engine if available\n const templateObj = typeof template === 'string' ? JSON.parse(template) : template;\n\n if (acDataModule) {\n try {\n // Create template instance using dynamically loaded module\n const cardTemplate = new acDataModule.Template(templateObj);\n\n // Create evaluation context with data\n // Supports $root for data, $host for host application context\n const context = {\n $root: data || {},\n $host: {\n widgetId: widget?.id,\n widgetTitle: widget?.title,\n theme: isDarkMode ? 'dark' : 'light',\n },\n };\n\n // Expand template with data\n cardPayload = cardTemplate.expand(context);\n\n // Capture any template expansion warnings\n warnings = cardTemplate.getLastTemplateExpansionWarnings();\n if (warnings.length > 0) {\n setTemplateWarnings(warnings);\n }\n } catch (templatingErr) {\n // Templating library threw an error - use fallback\n cardPayload = expandTemplateFallback(templateObj, (data || {}) as Record<string, unknown>) as object;\n warnings.push('Using simplified template expansion (some features may not work)');\n setTemplateWarnings(warnings);\n }\n } else {\n // Templating not available - use fallback expansion\n cardPayload = expandTemplateFallback(templateObj, (data || {}) as Record<string, unknown>) as object;\n if (templatingError) {\n warnings.push(`Using fallback expansion: ${templatingError}`);\n setTemplateWarnings(warnings);\n }\n }\n } else if (data && typeof data === 'object' && 'type' in data && data.type === 'AdaptiveCard') {\n // Data is already an Adaptive Card\n cardPayload = data;\n } else if (data && typeof data === 'object' && 'body' in data) {\n // Data has body property - treat as Adaptive Card\n cardPayload = {\n type: 'AdaptiveCard',\n version: '1.6',\n ...data,\n };\n }\n\n if (!cardPayload) {\n setRenderError('No template or valid Adaptive Card data provided');\n return;\n }\n\n // Create or reuse Adaptive Card instance\n if (!cardRef.current) {\n cardRef.current = new AdaptiveCards.AdaptiveCard();\n }\n const adaptiveCard = cardRef.current;\n\n // Set host config based on theme\n adaptiveCard.hostConfig = isDarkMode ? darkHostConfig : hostConfig;\n\n // Set action handler\n adaptiveCard.onExecuteAction = handleAction;\n\n // Parse the card payload\n adaptiveCard.parse(cardPayload);\n\n // Render to HTML element\n const renderedCard = adaptiveCard.render();\n\n if (renderedCard) {\n // Apply additional styling\n renderedCard.style.height = '100%';\n renderedCard.style.overflow = 'auto';\n\n // Add class for styling consistency\n renderedCard.classList.add('adaptive-card-container');\n\n // Append to container\n containerRef.current.appendChild(renderedCard);\n } else {\n setRenderError('Failed to render Adaptive Card');\n }\n } catch (e) {\n setRenderError((e as Error).message || 'Unknown error rendering card');\n }\n }, [template, data, widget, isLoading, isDarkMode, handleAction, acDataModule, templatingError]);\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center h-full p-4 animate-in fade-in duration-200\">\n <div className=\"animate-pulse space-y-3 w-full\">\n <div className=\"h-5 bg-bg-sunken rounded w-3/4\" />\n <div className=\"flex gap-3\">\n <div className=\"h-10 w-10 bg-bg-sunken rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 bg-bg-sunken rounded w-1/2\" />\n <div className=\"h-3 bg-bg-sunken rounded w-1/3\" />\n </div>\n </div>\n <div className=\"h-4 bg-bg-sunken rounded w-full\" />\n <div className=\"h-4 bg-bg-sunken rounded w-5/6\" />\n <div className=\"grid grid-cols-2 gap-2 mt-4\">\n <div className=\"h-3 bg-bg-sunken rounded\" />\n <div className=\"h-3 bg-bg-sunken rounded\" />\n <div className=\"h-3 bg-bg-sunken rounded\" />\n <div className=\"h-3 bg-bg-sunken rounded\" />\n </div>\n </div>\n </div>\n );\n }\n\n // Error state\n if (error || renderError) {\n return (\n <div className=\"flex items-center justify-center h-full p-4\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-12 h-12 mx-auto mb-3 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center\">\n <svg\n className=\"w-6 h-6 text-red-600 dark:text-red-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <p className=\"font-medium text-state-error\">Error rendering card</p>\n <p className=\"text-sm text-secondary mt-1\">{error || renderError}</p>\n {templateWarnings.length > 0 && (\n <div className=\"mt-3 p-2 bg-yellow-50 dark:bg-yellow-900/20 rounded text-left\">\n <p className=\"text-xs font-medium text-yellow-700 dark:text-yellow-400 mb-1\">Template Warnings:</p>\n {templateWarnings.map((warning, i) => (\n <p key={i} className=\"text-xs text-yellow-600 dark:text-yellow-300\">\n {warning}\n </p>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Empty state - no template or data\n if (!template && !data) {\n return (\n <div className=\"flex items-center justify-center h-full p-4 animate-in fade-in duration-200\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-12 h-12 mx-auto mb-3 rounded-full bg-bg-sunken flex items-center justify-center\">\n <svg className=\"w-6 h-6 text-text-secondary\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z\"\n />\n </svg>\n </div>\n <p className=\"font-medium text-secondary\">No content</p>\n <p className=\"text-sm text-text-secondary mt-1\">\n Configure a template or provide data to display an Adaptive Card\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div\n ref={containerRef}\n className=\"adaptive-card-wrapper h-full overflow-auto\"\n style={{\n // CSS custom properties for further customization\n ['--ac-font-family' as string]: 'Inter, system-ui, -apple-system, sans-serif',\n }}\n />\n );\n});\n\n// ============================================================================\n// Global Styles for Adaptive Cards\n// ============================================================================\n\n// Inject global styles for Adaptive Cards\nconst styleId = 'adaptive-card-global-styles';\nif (typeof document !== 'undefined' && !document.getElementById(styleId)) {\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n .adaptive-card-wrapper {\n font-family: Inter, system-ui, -apple-system, sans-serif;\n }\n\n .adaptive-card-wrapper .ac-textBlock {\n font-family: inherit;\n }\n\n .adaptive-card-wrapper .ac-image.ac-image-person {\n border-radius: 50%;\n object-fit: cover;\n }\n\n .adaptive-card-wrapper .ac-pushButton {\n font-family: inherit;\n font-weight: 500;\n border-radius: 0.375rem;\n padding: 0.5rem 1rem;\n transition: all 0.15s ease-in-out;\n }\n\n .adaptive-card-wrapper .ac-pushButton:hover {\n filter: brightness(0.95);\n }\n\n .adaptive-card-wrapper .ac-input {\n font-family: inherit;\n border-radius: 0.375rem;\n border: 1px solid #d1d5db;\n padding: 0.5rem 0.75rem;\n }\n\n .dark .adaptive-card-wrapper .ac-input {\n border-color: #4b5563;\n background-color: #1f2937;\n color: #f9fafb;\n }\n\n .adaptive-card-wrapper .ac-input:focus {\n outline: none;\n ring: 2px;\n ring-color: #3b82f6;\n }\n\n .adaptive-card-wrapper .ac-separator {\n margin: 0.5rem 0;\n }\n\n .adaptive-card-wrapper .ac-factSet {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: 0.25rem 1rem;\n }\n\n .adaptive-card-wrapper .ac-fact-title {\n color: #6b7280;\n }\n\n .dark .adaptive-card-wrapper .ac-fact-title {\n color: #9ca3af;\n }\n\n .adaptive-card-wrapper .ac-actionSet {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid #e5e7eb;\n }\n\n .dark .adaptive-card-wrapper .ac-actionSet {\n border-top-color: #374151;\n }\n\n /* Markdown rendered code blocks in dark mode */\n .dark .adaptive-card-wrapper code {\n background: #374151 !important;\n color: #f9fafb !important;\n }\n\n /* Markdown links in dark mode */\n .dark .adaptive-card-wrapper a {\n color: #60a5fa !important;\n }\n\n /* TextBlock with markdown - ensure proper wrapping */\n .adaptive-card-wrapper .ac-textBlock p {\n margin: 0;\n }\n\n .adaptive-card-wrapper .ac-textBlock strong {\n font-weight: 600;\n }\n\n .adaptive-card-wrapper .ac-textBlock em {\n font-style: italic;\n }\n `;\n document.head.appendChild(style);\n}\n\nexport default AdaptiveCardRenderer;\n"],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ var i = e.lazy(() => import("../../components/widgets/metric-card/index.js").the
|
|
|
35
35
|
return d ? /* @__PURE__ */ t(e.Suspense, {
|
|
36
36
|
fallback: /* @__PURE__ */ t("div", {
|
|
37
37
|
className: "flex items-center justify-center h-full animate-in fade-in duration-200",
|
|
38
|
-
children: /* @__PURE__ */ t("div", { className: "animate-pulse bg-
|
|
38
|
+
children: /* @__PURE__ */ t("div", { className: "animate-pulse bg-bg-sunken rounded w-full h-full" })
|
|
39
39
|
}),
|
|
40
40
|
children: /* @__PURE__ */ t(d, {
|
|
41
41
|
widget: r,
|
|
@@ -47,7 +47,7 @@ var i = e.lazy(() => import("../../components/widgets/metric-card/index.js").the
|
|
|
47
47
|
onDrilldown: l
|
|
48
48
|
})
|
|
49
49
|
}) : /* @__PURE__ */ t("div", {
|
|
50
|
-
className: "flex items-center justify-center h-full bg-
|
|
50
|
+
className: "flex items-center justify-center h-full bg-bg-sunken rounded-lg p-4 animate-in fade-in duration-200",
|
|
51
51
|
children: /* @__PURE__ */ n("div", {
|
|
52
52
|
className: "text-center text-secondary",
|
|
53
53
|
children: [/* @__PURE__ */ t("p", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BigConsoleRenderer.js","names":[],"sources":["../../../../src/bigconsole/renderers/adapters/BigConsoleRenderer.tsx"],"sourcesContent":["/**\n * BigConsole Native Renderer\n *\n * Pass-through renderer that uses the native BigConsole widget system.\n * This is the default renderer for all widget types.\n */\n\nimport React from 'react';\nimport type { RendererProps } from '../types/renderer';\nimport { type WidgetComponentProps } from '../../components/widgets/WidgetRegistry';\n\n// Type for widget module exports (used in lazy imports)\ninterface WidgetModule {\n [key: string]: unknown;\n}\n\n// Helper to resolve the widget component from a module\nfunction resolveWidget(m: WidgetModule, ...names: string[]): { default: React.ComponentType<WidgetComponentProps> } {\n for (const name of names) {\n if (m[name]) return { default: m[name] as React.ComponentType<WidgetComponentProps> };\n }\n return { default: (m as { default: React.ComponentType<WidgetComponentProps> }).default };\n}\n\n// Lazy load widget components (handle both default and named exports)\nconst MetricCardWidget = React.lazy(() =>\n import('../../components/widgets/metric-card').then((m: WidgetModule) => resolveWidget(m, 'MetricCardWidget'))\n);\nconst ChartWidget = React.lazy(() =>\n import('../../components/widgets/chart').then((m: WidgetModule) => resolveWidget(m, 'ChartWidget'))\n);\nconst TableWidget = React.lazy(() =>\n import('../../components/widgets/table').then((m: WidgetModule) => resolveWidget(m, 'TableWidget'))\n);\nconst GaugeWidget = React.lazy(() =>\n import('../../components/widgets/gauge').then((m: WidgetModule) => resolveWidget(m, 'GaugeWidget'))\n);\nconst ProgressWidget = React.lazy(() =>\n import('../../components/widgets/progress').then((m: WidgetModule) => resolveWidget(m, 'ProgressWidget'))\n);\nconst ListWidget = React.lazy(() =>\n import('../../components/widgets/list').then((m: WidgetModule) => resolveWidget(m, 'ListWidget'))\n);\nconst TextWidget = React.lazy(() =>\n import('../../components/widgets/text-widget').then((m: WidgetModule) => resolveWidget(m, 'TextWidget'))\n);\nconst KanbanWidget = React.lazy(() =>\n import('../../components/widgets/kanban').then((m: WidgetModule) => resolveWidget(m, 'KanbanWidget'))\n);\nconst TimelineWidget = React.lazy(() =>\n import('../../components/widgets/timeline').then((m: WidgetModule) => resolveWidget(m, 'TimelineWidget'))\n);\nconst CalendarWidget = React.lazy(() =>\n import('../../components/widgets/calendar').then((m: WidgetModule) => resolveWidget(m, 'CalendarWidget'))\n);\nconst MapWidget = React.lazy(() =>\n import('../../components/widgets/map-widget').then((m: WidgetModule) => resolveWidget(m, 'MapWidget'))\n);\nconst HeatmapWidget = React.lazy(() =>\n import('../../components/widgets/heatmap').then((m: WidgetModule) => resolveWidget(m, 'HeatmapWidget'))\n);\nconst FunnelWidget = React.lazy(() =>\n import('../../components/widgets/funnel').then((m: WidgetModule) =>\n resolveWidget(m, 'FunnelWidget', 'FunnelChartWidget')\n )\n);\nconst RetentionWidget = React.lazy(() =>\n import('../../components/widgets/retention').then((m: WidgetModule) => resolveWidget(m, 'RetentionWidget'))\n);\nconst IframeWidget = React.lazy(() =>\n import('../../components/widgets/iframe-widget').then((m: WidgetModule) => resolveWidget(m, 'IframeWidget'))\n);\nconst CustomWidget = React.lazy(() =>\n import('../../components/widgets/custom').then((m: WidgetModule) => resolveWidget(m, 'CustomWidget'))\n);\nconst KpiComparisonWidget = React.lazy(() =>\n import('../../components/widgets/kpi-comparison').then((m: WidgetModule) => resolveWidget(m, 'KpiComparisonWidget'))\n);\nconst PivotTableWidget = React.lazy(() =>\n import('../../components/widgets/pivot-table').then((m: WidgetModule) => resolveWidget(m, 'PivotTableWidget'))\n);\nconst FormWidget = React.lazy(() =>\n import('../../components/widgets/form').then((m: WidgetModule) => resolveWidget(m, 'FormWidget'))\n);\n\n// Widget component map\nconst WIDGET_COMPONENTS: Record<string, React.ComponentType<WidgetComponentProps>> = {\n metric_card: MetricCardWidget,\n chart: ChartWidget,\n table: TableWidget,\n gauge: GaugeWidget,\n progress: ProgressWidget,\n list: ListWidget,\n text: TextWidget,\n kanban: KanbanWidget,\n timeline: TimelineWidget,\n calendar: CalendarWidget,\n map: MapWidget,\n heatmap: HeatmapWidget,\n funnel_chart: FunnelWidget,\n retention: RetentionWidget,\n form: FormWidget,\n iframe: IframeWidget,\n custom: CustomWidget,\n kpi_card_comparison: KpiComparisonWidget,\n pivot_table: PivotTableWidget,\n // Type aliases for backwards compatibility\n kpi: KpiComparisonWidget,\n kpi_comparison: KpiComparisonWidget,\n metric: MetricCardWidget,\n funnel: FunnelWidget,\n pivot: PivotTableWidget,\n};\n\n/**\n * BigConsole Native Renderer Component\n */\nexport const BigConsoleRenderer: React.FC<RendererProps> = ({\n widget,\n data,\n isEditMode,\n isSelected,\n isLoading,\n error,\n onDrilldown,\n onAction: _onAction,\n}) => {\n // Normalize widget type to lowercase for lookup (handles CUSTOM -> custom, etc.)\n const normalizedType = widget.type?.toLowerCase() || '';\n const WidgetComponent = WIDGET_COMPONENTS[normalizedType];\n\n if (!WidgetComponent) {\n return (\n <div className=\"flex items-center justify-center h-full bg-
|
|
1
|
+
{"version":3,"file":"BigConsoleRenderer.js","names":[],"sources":["../../../../src/bigconsole/renderers/adapters/BigConsoleRenderer.tsx"],"sourcesContent":["/**\n * BigConsole Native Renderer\n *\n * Pass-through renderer that uses the native BigConsole widget system.\n * This is the default renderer for all widget types.\n */\n\nimport React from 'react';\nimport type { RendererProps } from '../types/renderer';\nimport { type WidgetComponentProps } from '../../components/widgets/WidgetRegistry';\n\n// Type for widget module exports (used in lazy imports)\ninterface WidgetModule {\n [key: string]: unknown;\n}\n\n// Helper to resolve the widget component from a module\nfunction resolveWidget(m: WidgetModule, ...names: string[]): { default: React.ComponentType<WidgetComponentProps> } {\n for (const name of names) {\n if (m[name]) return { default: m[name] as React.ComponentType<WidgetComponentProps> };\n }\n return { default: (m as { default: React.ComponentType<WidgetComponentProps> }).default };\n}\n\n// Lazy load widget components (handle both default and named exports)\nconst MetricCardWidget = React.lazy(() =>\n import('../../components/widgets/metric-card').then((m: WidgetModule) => resolveWidget(m, 'MetricCardWidget'))\n);\nconst ChartWidget = React.lazy(() =>\n import('../../components/widgets/chart').then((m: WidgetModule) => resolveWidget(m, 'ChartWidget'))\n);\nconst TableWidget = React.lazy(() =>\n import('../../components/widgets/table').then((m: WidgetModule) => resolveWidget(m, 'TableWidget'))\n);\nconst GaugeWidget = React.lazy(() =>\n import('../../components/widgets/gauge').then((m: WidgetModule) => resolveWidget(m, 'GaugeWidget'))\n);\nconst ProgressWidget = React.lazy(() =>\n import('../../components/widgets/progress').then((m: WidgetModule) => resolveWidget(m, 'ProgressWidget'))\n);\nconst ListWidget = React.lazy(() =>\n import('../../components/widgets/list').then((m: WidgetModule) => resolveWidget(m, 'ListWidget'))\n);\nconst TextWidget = React.lazy(() =>\n import('../../components/widgets/text-widget').then((m: WidgetModule) => resolveWidget(m, 'TextWidget'))\n);\nconst KanbanWidget = React.lazy(() =>\n import('../../components/widgets/kanban').then((m: WidgetModule) => resolveWidget(m, 'KanbanWidget'))\n);\nconst TimelineWidget = React.lazy(() =>\n import('../../components/widgets/timeline').then((m: WidgetModule) => resolveWidget(m, 'TimelineWidget'))\n);\nconst CalendarWidget = React.lazy(() =>\n import('../../components/widgets/calendar').then((m: WidgetModule) => resolveWidget(m, 'CalendarWidget'))\n);\nconst MapWidget = React.lazy(() =>\n import('../../components/widgets/map-widget').then((m: WidgetModule) => resolveWidget(m, 'MapWidget'))\n);\nconst HeatmapWidget = React.lazy(() =>\n import('../../components/widgets/heatmap').then((m: WidgetModule) => resolveWidget(m, 'HeatmapWidget'))\n);\nconst FunnelWidget = React.lazy(() =>\n import('../../components/widgets/funnel').then((m: WidgetModule) =>\n resolveWidget(m, 'FunnelWidget', 'FunnelChartWidget')\n )\n);\nconst RetentionWidget = React.lazy(() =>\n import('../../components/widgets/retention').then((m: WidgetModule) => resolveWidget(m, 'RetentionWidget'))\n);\nconst IframeWidget = React.lazy(() =>\n import('../../components/widgets/iframe-widget').then((m: WidgetModule) => resolveWidget(m, 'IframeWidget'))\n);\nconst CustomWidget = React.lazy(() =>\n import('../../components/widgets/custom').then((m: WidgetModule) => resolveWidget(m, 'CustomWidget'))\n);\nconst KpiComparisonWidget = React.lazy(() =>\n import('../../components/widgets/kpi-comparison').then((m: WidgetModule) => resolveWidget(m, 'KpiComparisonWidget'))\n);\nconst PivotTableWidget = React.lazy(() =>\n import('../../components/widgets/pivot-table').then((m: WidgetModule) => resolveWidget(m, 'PivotTableWidget'))\n);\nconst FormWidget = React.lazy(() =>\n import('../../components/widgets/form').then((m: WidgetModule) => resolveWidget(m, 'FormWidget'))\n);\n\n// Widget component map\nconst WIDGET_COMPONENTS: Record<string, React.ComponentType<WidgetComponentProps>> = {\n metric_card: MetricCardWidget,\n chart: ChartWidget,\n table: TableWidget,\n gauge: GaugeWidget,\n progress: ProgressWidget,\n list: ListWidget,\n text: TextWidget,\n kanban: KanbanWidget,\n timeline: TimelineWidget,\n calendar: CalendarWidget,\n map: MapWidget,\n heatmap: HeatmapWidget,\n funnel_chart: FunnelWidget,\n retention: RetentionWidget,\n form: FormWidget,\n iframe: IframeWidget,\n custom: CustomWidget,\n kpi_card_comparison: KpiComparisonWidget,\n pivot_table: PivotTableWidget,\n // Type aliases for backwards compatibility\n kpi: KpiComparisonWidget,\n kpi_comparison: KpiComparisonWidget,\n metric: MetricCardWidget,\n funnel: FunnelWidget,\n pivot: PivotTableWidget,\n};\n\n/**\n * BigConsole Native Renderer Component\n */\nexport const BigConsoleRenderer: React.FC<RendererProps> = ({\n widget,\n data,\n isEditMode,\n isSelected,\n isLoading,\n error,\n onDrilldown,\n onAction: _onAction,\n}) => {\n // Normalize widget type to lowercase for lookup (handles CUSTOM -> custom, etc.)\n const normalizedType = widget.type?.toLowerCase() || '';\n const WidgetComponent = WIDGET_COMPONENTS[normalizedType];\n\n if (!WidgetComponent) {\n return (\n <div className=\"flex items-center justify-center h-full bg-bg-sunken rounded-lg p-4 animate-in fade-in duration-200\">\n <div className=\"text-center text-secondary\">\n <p className=\"font-medium\">Unknown Widget Type</p>\n <p className=\"text-sm\">{widget.type}</p>\n </div>\n </div>\n );\n }\n\n return (\n <React.Suspense\n fallback={\n <div className=\"flex items-center justify-center h-full animate-in fade-in duration-200\">\n <div className=\"animate-pulse bg-bg-sunken rounded w-full h-full\" />\n </div>\n }\n >\n <WidgetComponent\n widget={widget}\n data={data}\n isEditMode={isEditMode}\n isSelected={isSelected}\n isLoading={isLoading}\n error={error}\n onDrilldown={onDrilldown}\n />\n </React.Suspense>\n );\n};\n\nexport default BigConsoleRenderer;\n"],"mappings":"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"}
|
|
@@ -25,7 +25,7 @@ function o(t) {
|
|
|
25
25
|
let c = a.match(/^`([^`]+)`/);
|
|
26
26
|
if (c) {
|
|
27
27
|
r.push(/* @__PURE__ */ i("code", {
|
|
28
|
-
className: "bg-
|
|
28
|
+
className: "bg-bg-sunken px-1 rounded text-sm",
|
|
29
29
|
children: c[1]
|
|
30
30
|
}, o++)), a = a.slice(c[0].length);
|
|
31
31
|
continue;
|
|
@@ -67,7 +67,7 @@ function s(e) {
|
|
|
67
67
|
switch (e) {
|
|
68
68
|
case "primary": return "bg-state-success hover:bg-state-success/90 text-white transition-colors";
|
|
69
69
|
case "danger": return "bg-state-error hover:bg-state-error/90 text-white transition-colors";
|
|
70
|
-
default: return "bg-
|
|
70
|
+
default: return "bg-bg-sunken hover:bg-bg-sunken/80 text-primary transition-colors";
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
function c(e, t) {
|
|
@@ -332,9 +332,9 @@ var g = t(function({ widget: e, data: t, template: o, isLoading: s, error: l, on
|
|
|
332
332
|
children: /* @__PURE__ */ a("div", {
|
|
333
333
|
className: "animate-pulse space-y-2 w-full",
|
|
334
334
|
children: [
|
|
335
|
-
/* @__PURE__ */ i("div", { className: "h-4 bg-
|
|
336
|
-
/* @__PURE__ */ i("div", { className: "h-4 bg-
|
|
337
|
-
/* @__PURE__ */ i("div", { className: "h-4 bg-
|
|
335
|
+
/* @__PURE__ */ i("div", { className: "h-4 bg-bg-sunken rounded w-3/4" }),
|
|
336
|
+
/* @__PURE__ */ i("div", { className: "h-4 bg-bg-sunken rounded w-1/2" }),
|
|
337
|
+
/* @__PURE__ */ i("div", { className: "h-4 bg-bg-sunken rounded w-5/6" })
|
|
338
338
|
]
|
|
339
339
|
})
|
|
340
340
|
}) : l ? /* @__PURE__ */ i("div", {
|