@burdenoff/microfe-bigconsole 2026.729.1 → 2026.729.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/components/DrilldownDashboardRenderer.js +1 -1
- package/dist/bigconsole/components/DrilldownDashboardRenderer.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +4 -4
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +5 -5
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +3 -3
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +4 -4
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +6 -6
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +9 -9
- 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/SetupStateBadge.js +8 -8
- package/dist/bigconsole/components/datasink/SetupStateBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +13 -13
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
- package/dist/bigconsole/components/parser/DataSinkSelector.js +2 -2
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ExpressionEditor.js +1 -1
- package/dist/bigconsole/components/parser/ExpressionEditor.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserCard.js +1 -1
- package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +2 -2
- package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserStatusBadge.js +2 -2
- package/dist/bigconsole/components/parser/ParserStatusBadge.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 +5 -5
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +3 -3
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +3 -3
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js +2 -2
- package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
- package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js +3 -3
- package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.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/gauge/GaugeConfig.js +3 -3
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/heatmap/HeatmapWidget.js +52 -32
- package/dist/bigconsole/components/widgets/heatmap/HeatmapWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +3 -3
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi/KPIWidget.js +1 -1
- 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/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 +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +6 -6
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +1 -1
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressBar.js +4 -4
- 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/ErrorState.js +2 -2
- package/dist/bigconsole/components/widgets/states/ErrorState.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js +2 -2
- package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +1 -1
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +6 -6
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +5 -5
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js +6 -6
- package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +17 -17
- 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 +24 -24
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +8 -8
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +9 -9
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +12 -12
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +6 -6
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +2 -2
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PipelineBuilderPage.js","names":[],"sources":["../../../src/bigconsole/pages/PipelineBuilderPage.tsx"],"sourcesContent":["/**\n * Pipeline Builder Page\n *\n * Create and edit Pipelines with stage management.\n * Supports adding, removing, and reordering stages.\n */\n\nimport { memo, useState, useCallback, useEffect, useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useAppNavigate } from '../contexts';\nimport { usePipelineOperations } from '../hooks/usePipelineOperations';\nimport { useParserOperations } from '../hooks/useParserOperations';\nimport { PipelineStatusBadge } from '../components/pipeline/PipelineStatusBadge';\nimport type { PipelineStatus, StageErrorHandling, ParserType } from '../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface StageForm {\n id?: string;\n parserId: string;\n parserName: string;\n parserType: ParserType | null;\n inputKey: string;\n outputKey: string;\n enabled: boolean;\n onError: StageErrorHandling;\n fallbackValue: string;\n description: string;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst BackIcon = ({ 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=\"M10 19l-7-7m0 0l7-7m-7 7h18\" />\n </svg>\n);\n\nconst PlusIcon = ({ 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=\"M12 4v16m8-8H4\" />\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 ArrowUpIcon = ({ 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 15l7-7 7 7\" />\n </svg>\n);\n\nconst ArrowDownIcon = ({ 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\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\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst STATUS_OPTIONS: { value: PipelineStatus; label: string }[] = [\n { value: 'draft', label: 'Draft' },\n { value: 'active', label: 'Active' },\n { value: 'inactive', label: 'Inactive' },\n];\n\nconst ERROR_HANDLING_OPTIONS: { value: StageErrorHandling; label: string; description: string }[] = [\n { value: 'fail', label: 'Fail', description: 'Stop pipeline execution on error' },\n { value: 'skip', label: 'Skip', description: 'Skip this stage and continue' },\n { value: 'fallback', label: 'Fallback', description: 'Use fallback value on error' },\n];\n\nconst DEFAULT_STAGE: StageForm = {\n parserId: '',\n parserName: '',\n parserType: null,\n inputKey: 'data',\n outputKey: 'result',\n enabled: true,\n onError: 'fail',\n fallbackValue: '',\n description: '',\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const PipelineBuilderPage = memo(function PipelineBuilderPage() {\n const { pipelineId } = useParams<{ pipelineId: string }>();\n const navigate = useAppNavigate();\n const isEditMode = !!pipelineId && pipelineId !== 'new';\n // Use default consoleId for now (should come from context in production)\n const consoleId = 'default';\n\n // Form state\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [status, setStatus] = useState<PipelineStatus>('draft');\n const [stages, setStages] = useState<StageForm[]>([]);\n const [version, setVersion] = useState(1);\n const [isSaving, setIsSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // Operations\n const {\n loading: pipelineLoading,\n error: pipelineError,\n fetchPipeline,\n createPipeline,\n updatePipeline,\n } = usePipelineOperations({\n consoleId,\n skipFetch: true,\n });\n\n const { parsers } = useParserOperations({\n consoleId,\n });\n\n // Load existing pipeline in edit mode\n useEffect(() => {\n if (isEditMode && pipelineId) {\n fetchPipeline(pipelineId).then((pipeline) => {\n if (pipeline) {\n setName(pipeline.name);\n setDescription(pipeline.description || '');\n setStatus(pipeline.status);\n setVersion(pipeline.version);\n setStages(\n (pipeline.stages || []).map((s) => ({\n id: s.id,\n parserId: s.parserId,\n parserName: s.parserName || '',\n parserType: s.parserType,\n inputKey: s.inputKey,\n outputKey: s.outputKey,\n enabled: s.enabled,\n onError: s.onError,\n fallbackValue: s.fallbackValue ? JSON.stringify(s.fallbackValue) : '',\n description: s.description || '',\n }))\n );\n }\n });\n }\n }, [isEditMode, pipelineId, fetchPipeline]);\n\n // Validation\n const isValid = useMemo(() => {\n if (!name.trim()) return false;\n if (stages.length === 0) return false;\n return stages.every((s) => s.parserId && s.inputKey && s.outputKey);\n }, [name, stages]);\n\n // Handlers\n const handleBack = useCallback(() => {\n navigate(`/pipelines`);\n }, [navigate]);\n\n const handleAddStage = useCallback(() => {\n setStages((prev) => [...prev, { ...DEFAULT_STAGE }]);\n }, []);\n\n const handleRemoveStage = useCallback((index: number) => {\n setStages((prev) => prev.filter((_, i) => i !== index));\n }, []);\n\n const handleMoveStage = useCallback((index: number, direction: 'up' | 'down') => {\n setStages((prev) => {\n const newStages = [...prev];\n const targetIndex = direction === 'up' ? index - 1 : index + 1;\n if (targetIndex < 0 || targetIndex >= newStages.length) return prev;\n [newStages[index], newStages[targetIndex]] = [newStages[targetIndex], newStages[index]];\n return newStages;\n });\n }, []);\n\n const handleUpdateStage = useCallback((index: number, updates: Partial<StageForm>) => {\n setStages((prev) => prev.map((stage, i) => (i === index ? { ...stage, ...updates } : stage)));\n }, []);\n\n const handleParserSelect = useCallback(\n (index: number, parserId: string) => {\n const parser = parsers.find((p) => p.id === parserId);\n if (parser) {\n handleUpdateStage(index, {\n parserId: parser.id,\n parserName: parser.name,\n parserType: parser.type,\n });\n }\n },\n [parsers, handleUpdateStage]\n );\n\n const handleSave = useCallback(async () => {\n if (!isValid || !consoleId) return;\n\n setIsSaving(true);\n setSaveError(null);\n\n try {\n const stageInputs = stages.map((s) => ({\n parserId: s.parserId,\n parserName: s.parserName,\n parserType: s.parserType || undefined,\n inputKey: s.inputKey,\n outputKey: s.outputKey,\n enabled: s.enabled,\n onError: s.onError,\n fallbackValue: s.fallbackValue ? JSON.parse(s.fallbackValue) : undefined,\n description: s.description || undefined,\n }));\n\n if (isEditMode && pipelineId) {\n const result = await updatePipeline(\n pipelineId,\n {\n name,\n description: description || undefined,\n status,\n },\n version\n );\n if (result) {\n navigate(`/pipelines/${pipelineId}`);\n }\n } else {\n const result = await createPipeline({\n consoleId,\n name,\n description: description || undefined,\n status,\n stages: stageInputs,\n });\n if (result) {\n navigate(`/pipelines/${result.id}`);\n }\n }\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : 'Failed to save pipeline');\n } finally {\n setIsSaving(false);\n }\n }, [\n isValid,\n consoleId,\n isEditMode,\n pipelineId,\n name,\n description,\n status,\n stages,\n version,\n createPipeline,\n updatePipeline,\n navigate,\n ]);\n\n // Loading state\n if (pipelineLoading && isEditMode) {\n return (\n <div className=\"p-6\">\n <div className=\"flex flex-col items-center justify-center py-16\">\n <svg className=\"w-8 h-8 text-action-primary-bg animate-spin mb-4\" 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 <p className=\"text-sm text-text-secondary\">Loading Pipeline...</p>\n </div>\n </div>\n );\n }\n\n // Error state\n if (pipelineError) {\n return (\n <div className=\"p-6\">\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\">Failed to load Pipeline</h3>\n <p className=\"text-sm text-text-secondary mb-4\">{pipelineError.message}</p>\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n Back to Pipelines\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"p-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-6\">\n <div className=\"flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n <BackIcon className=\"w-5 h-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">{isEditMode ? 'Edit Pipeline' : 'Create Pipeline'}</h1>\n <p className=\"text-sm text-text-secondary mt-1\">\n {isEditMode ? 'Update pipeline settings and stages' : 'Create a new data transformation pipeline'}\n </p>\n </div>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 text-sm font-medium text-text-primary bg-bg-sunken hover:bg-border-default rounded-md transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={!isValid || isSaving}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors disabled:opacity-50\"\n >\n {isSaving ? 'Saving...' : isEditMode ? 'Save Changes' : 'Create Pipeline'}\n </button>\n </div>\n </div>\n\n <PagePurpose className=\"mb-6\">\n Build a pipeline by chaining parser stages — each stage reads an input key, runs a parser, and writes a\n structured output key that the next stage (or a data sink) can use. Name it, add your stages in order, then test\n it before saving so your data flows end to end.\n </PagePurpose>\n\n {/* Error Message */}\n {saveError && (\n <div className=\"mb-6 p-4 bg-state-error/10 border border-state-error/20 rounded-md\">\n <p className=\"text-sm text-state-error\">{saveError}</p>\n </div>\n )}\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n {/* Main Form */}\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Basic Info */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Basic Information</h2>\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Name <span className=\"text-state-error\">*</span>\n </label>\n <input\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"My Pipeline\"\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Description</label>\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"What does this pipeline do?\"\n rows={3}\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg resize-none\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Status</label>\n <select\n value={status}\n onChange={(e) => setStatus(e.target.value as PipelineStatus)}\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n {STATUS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n </div>\n\n {/* Stages — primary emphasis zone */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Stages ({stages.length})</h2>\n <button\n type=\"button\"\n onClick={handleAddStage}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n <PlusIcon className=\"w-4 h-4\" />\n Add Stage\n </button>\n </div>\n\n {stages.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No stages yet\"\n description=\"Add a stage to start building your pipeline.\"\n action={\n <button\n type=\"button\"\n onClick={handleAddStage}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n <PlusIcon className=\"w-4 h-4\" />\n Add First Stage\n </button>\n }\n />\n ) : (\n <div className=\"space-y-4\">\n {stages.map((stage, index) => (\n <div key={index} className=\"p-4 bg-bg-sunken border border-border-default rounded-lg\">\n <div className=\"flex items-center justify-between mb-4\">\n <div className=\"flex items-center gap-2\">\n <span className=\"w-6 h-6 flex items-center justify-center text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded-full\">\n {index + 1}\n </span>\n <span className=\"font-medium text-text-primary\">\n {stage.parserName || `Stage ${index + 1}`}\n </span>\n </div>\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => handleMoveStage(index, 'up')}\n disabled={index === 0}\n className=\"p-1 text-text-secondary hover:text-text-primary hover:bg-bg-surface rounded disabled:opacity-30\"\n >\n <ArrowUpIcon className=\"w-4 h-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleMoveStage(index, 'down')}\n disabled={index === stages.length - 1}\n className=\"p-1 text-text-secondary hover:text-text-primary hover:bg-bg-surface rounded disabled:opacity-30\"\n >\n <ArrowDownIcon className=\"w-4 h-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleRemoveStage(index)}\n className=\"p-1 text-text-secondary hover:text-state-error hover:bg-state-error/10 rounded\"\n >\n <TrashIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"col-span-2\">\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n Parser <span className=\"text-state-error\">*</span>\n </label>\n <select\n value={stage.parserId}\n onChange={(e) => handleParserSelect(index, e.target.value)}\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n <option value=\"\">Select a parser...</option>\n {parsers.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name} ({p.type.toUpperCase()})\n </option>\n ))}\n </select>\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n Input Key <span className=\"text-state-error\">*</span>\n </label>\n <input\n type=\"text\"\n value={stage.inputKey}\n onChange={(e) => handleUpdateStage(index, { inputKey: e.target.value })}\n placeholder=\"data\"\n className=\"w-full px-3 py-2 text-sm font-mono text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n Output Key <span className=\"text-state-error\">*</span>\n </label>\n <input\n type=\"text\"\n value={stage.outputKey}\n onChange={(e) => handleUpdateStage(index, { outputKey: e.target.value })}\n placeholder=\"result\"\n className=\"w-full px-3 py-2 text-sm font-mono text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">On Error</label>\n <select\n value={stage.onError}\n onChange={(e) =>\n handleUpdateStage(index, {\n onError: e.target.value as StageErrorHandling,\n })\n }\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n {ERROR_HANDLING_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"flex items-center\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={stage.enabled}\n onChange={(e) => handleUpdateStage(index, { enabled: e.target.checked })}\n className=\"w-4 h-4 rounded border-border-default text-action-primary-bg focus:ring-action-primary-bg\"\n />\n <span className=\"text-sm text-text-primary\">Enabled</span>\n </label>\n </div>\n\n {stage.onError === 'fallback' && (\n <div className=\"col-span-2\">\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n Fallback Value (JSON)\n </label>\n <input\n type=\"text\"\n value={stage.fallbackValue}\n onChange={(e) => handleUpdateStage(index, { fallbackValue: e.target.value })}\n placeholder='{\"default\": true}'\n className=\"w-full px-3 py-2 text-sm font-mono text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </GlassCard>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Preview */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Preview</h2>\n\n <div className=\"space-y-3\">\n <div>\n <span className=\"text-xs text-text-secondary\">Name</span>\n <p className=\"text-sm text-text-primary\">{name || 'Untitled'}</p>\n </div>\n\n <div>\n <span className=\"text-xs text-text-secondary\">Status</span>\n <div className=\"mt-1\">\n <PipelineStatusBadge status={status} />\n </div>\n </div>\n\n <div>\n <span className=\"text-xs text-text-secondary\">Stages</span>\n <p className=\"text-sm text-text-primary\">{stages.length}</p>\n </div>\n\n {stages.length > 0 && (\n <div>\n <span className=\"text-xs text-text-secondary\">Data Flow</span>\n <div className=\"mt-1 text-xs font-mono text-text-secondary\">\n {stages.map((s, i) => (\n <span key={i}>\n {s.inputKey}\n {i < stages.length - 1 && ' → '}\n </span>\n ))}\n {stages.length > 0 && ` → ${stages[stages.length - 1].outputKey}`}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Help */}\n <div className=\"bg-bg-sunken border border-border-default rounded-lg p-6\">\n <h3 className=\"text-sm font-semibold text-text-primary mb-2\">Tips</h3>\n <ul className=\"text-xs text-text-secondary space-y-2\">\n <li>• Each stage processes the output of the previous stage</li>\n <li>• Use consistent input/output keys to chain data</li>\n <li>• Set error handling per stage for robustness</li>\n <li>• Disable stages to skip them during execution</li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n );\n});\n\nexport default PipelineBuilderPage;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PipelineBuilderPage.js","names":[],"sources":["../../../src/bigconsole/pages/PipelineBuilderPage.tsx"],"sourcesContent":["/**\n * Pipeline Builder Page\n *\n * Create and edit Pipelines with stage management.\n * Supports adding, removing, and reordering stages.\n */\n\nimport { memo, useState, useCallback, useEffect, useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useAppNavigate } from '../contexts';\nimport { usePipelineOperations } from '../hooks/usePipelineOperations';\nimport { useParserOperations } from '../hooks/useParserOperations';\nimport { PipelineStatusBadge } from '../components/pipeline/PipelineStatusBadge';\nimport type { PipelineStatus, StageErrorHandling, ParserType } from '../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface StageForm {\n id?: string;\n parserId: string;\n parserName: string;\n parserType: ParserType | null;\n inputKey: string;\n outputKey: string;\n enabled: boolean;\n onError: StageErrorHandling;\n fallbackValue: string;\n description: string;\n}\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst BackIcon = ({ 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=\"M10 19l-7-7m0 0l7-7m-7 7h18\" />\n </svg>\n);\n\nconst PlusIcon = ({ 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=\"M12 4v16m8-8H4\" />\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 ArrowUpIcon = ({ 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 15l7-7 7 7\" />\n </svg>\n);\n\nconst ArrowDownIcon = ({ 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\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\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst STATUS_OPTIONS: { value: PipelineStatus; label: string }[] = [\n { value: 'draft', label: 'Draft' },\n { value: 'active', label: 'Active' },\n { value: 'inactive', label: 'Inactive' },\n];\n\nconst ERROR_HANDLING_OPTIONS: { value: StageErrorHandling; label: string; description: string }[] = [\n { value: 'fail', label: 'Fail', description: 'Stop pipeline execution on error' },\n { value: 'skip', label: 'Skip', description: 'Skip this stage and continue' },\n { value: 'fallback', label: 'Fallback', description: 'Use fallback value on error' },\n];\n\nconst DEFAULT_STAGE: StageForm = {\n parserId: '',\n parserName: '',\n parserType: null,\n inputKey: 'data',\n outputKey: 'result',\n enabled: true,\n onError: 'fail',\n fallbackValue: '',\n description: '',\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const PipelineBuilderPage = memo(function PipelineBuilderPage() {\n const { pipelineId } = useParams<{ pipelineId: string }>();\n const navigate = useAppNavigate();\n const isEditMode = !!pipelineId && pipelineId !== 'new';\n // Use default consoleId for now (should come from context in production)\n const consoleId = 'default';\n\n // Form state\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [status, setStatus] = useState<PipelineStatus>('draft');\n const [stages, setStages] = useState<StageForm[]>([]);\n const [version, setVersion] = useState(1);\n const [isSaving, setIsSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n\n // Operations\n const {\n loading: pipelineLoading,\n error: pipelineError,\n fetchPipeline,\n createPipeline,\n updatePipeline,\n } = usePipelineOperations({\n consoleId,\n skipFetch: true,\n });\n\n const { parsers } = useParserOperations({\n consoleId,\n });\n\n // Load existing pipeline in edit mode\n useEffect(() => {\n if (isEditMode && pipelineId) {\n fetchPipeline(pipelineId).then((pipeline) => {\n if (pipeline) {\n setName(pipeline.name);\n setDescription(pipeline.description || '');\n setStatus(pipeline.status);\n setVersion(pipeline.version);\n setStages(\n (pipeline.stages || []).map((s) => ({\n id: s.id,\n parserId: s.parserId,\n parserName: s.parserName || '',\n parserType: s.parserType,\n inputKey: s.inputKey,\n outputKey: s.outputKey,\n enabled: s.enabled,\n onError: s.onError,\n fallbackValue: s.fallbackValue ? JSON.stringify(s.fallbackValue) : '',\n description: s.description || '',\n }))\n );\n }\n });\n }\n }, [isEditMode, pipelineId, fetchPipeline]);\n\n // Validation\n const isValid = useMemo(() => {\n if (!name.trim()) return false;\n if (stages.length === 0) return false;\n return stages.every((s) => s.parserId && s.inputKey && s.outputKey);\n }, [name, stages]);\n\n // Handlers\n const handleBack = useCallback(() => {\n navigate(`/pipelines`);\n }, [navigate]);\n\n const handleAddStage = useCallback(() => {\n setStages((prev) => [...prev, { ...DEFAULT_STAGE }]);\n }, []);\n\n const handleRemoveStage = useCallback((index: number) => {\n setStages((prev) => prev.filter((_, i) => i !== index));\n }, []);\n\n const handleMoveStage = useCallback((index: number, direction: 'up' | 'down') => {\n setStages((prev) => {\n const newStages = [...prev];\n const targetIndex = direction === 'up' ? index - 1 : index + 1;\n if (targetIndex < 0 || targetIndex >= newStages.length) return prev;\n [newStages[index], newStages[targetIndex]] = [newStages[targetIndex], newStages[index]];\n return newStages;\n });\n }, []);\n\n const handleUpdateStage = useCallback((index: number, updates: Partial<StageForm>) => {\n setStages((prev) => prev.map((stage, i) => (i === index ? { ...stage, ...updates } : stage)));\n }, []);\n\n const handleParserSelect = useCallback(\n (index: number, parserId: string) => {\n const parser = parsers.find((p) => p.id === parserId);\n if (parser) {\n handleUpdateStage(index, {\n parserId: parser.id,\n parserName: parser.name,\n parserType: parser.type,\n });\n }\n },\n [parsers, handleUpdateStage]\n );\n\n const handleSave = useCallback(async () => {\n if (!isValid || !consoleId) return;\n\n setIsSaving(true);\n setSaveError(null);\n\n try {\n const stageInputs = stages.map((s) => ({\n parserId: s.parserId,\n parserName: s.parserName,\n parserType: s.parserType || undefined,\n inputKey: s.inputKey,\n outputKey: s.outputKey,\n enabled: s.enabled,\n onError: s.onError,\n fallbackValue: s.fallbackValue ? JSON.parse(s.fallbackValue) : undefined,\n description: s.description || undefined,\n }));\n\n if (isEditMode && pipelineId) {\n const result = await updatePipeline(\n pipelineId,\n {\n name,\n description: description || undefined,\n status,\n },\n version\n );\n if (result) {\n navigate(`/pipelines/${pipelineId}`);\n }\n } else {\n const result = await createPipeline({\n consoleId,\n name,\n description: description || undefined,\n status,\n stages: stageInputs,\n });\n if (result) {\n navigate(`/pipelines/${result.id}`);\n }\n }\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : 'Failed to save pipeline');\n } finally {\n setIsSaving(false);\n }\n }, [\n isValid,\n consoleId,\n isEditMode,\n pipelineId,\n name,\n description,\n status,\n stages,\n version,\n createPipeline,\n updatePipeline,\n navigate,\n ]);\n\n // Loading state\n if (pipelineLoading && isEditMode) {\n return (\n <div className=\"p-6\">\n <div className=\"flex flex-col items-center justify-center py-16\">\n <svg className=\"w-8 h-8 text-action-primary-bg animate-spin mb-4\" 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 <p className=\"text-sm text-text-secondary\">Loading Pipeline...</p>\n </div>\n </div>\n );\n }\n\n // Error state\n if (pipelineError) {\n return (\n <div className=\"p-6\">\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <div className=\"p-3 rounded-full bg-status-error-bg/10 mb-4\">\n <ErrorIcon className=\"w-8 h-8 text-status-error-text\" />\n </div>\n <h3 className=\"text-lg font-medium text-text-primary mb-2\">Failed to load Pipeline</h3>\n <p className=\"text-sm text-text-secondary mb-4\">{pipelineError.message}</p>\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n Back to Pipelines\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"p-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-6\">\n <div className=\"flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n <BackIcon className=\"w-5 h-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">{isEditMode ? 'Edit Pipeline' : 'Create Pipeline'}</h1>\n <p className=\"text-sm text-text-secondary mt-1\">\n {isEditMode ? 'Update pipeline settings and stages' : 'Create a new data transformation pipeline'}\n </p>\n </div>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 text-sm font-medium text-text-primary bg-bg-sunken hover:bg-border-default rounded-md transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={!isValid || isSaving}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors disabled:opacity-50\"\n >\n {isSaving ? 'Saving...' : isEditMode ? 'Save Changes' : 'Create Pipeline'}\n </button>\n </div>\n </div>\n\n <PagePurpose className=\"mb-6\">\n Build a pipeline by chaining parser stages — each stage reads an input key, runs a parser, and writes a\n structured output key that the next stage (or a data sink) can use. Name it, add your stages in order, then test\n it before saving so your data flows end to end.\n </PagePurpose>\n\n {/* Error Message */}\n {saveError && (\n <div className=\"mb-6 p-4 bg-status-error-bg/10 border border-status-error-border/20 rounded-md\">\n <p className=\"text-sm text-status-error-text\">{saveError}</p>\n </div>\n )}\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n {/* Main Form */}\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Basic Info */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Basic Information</h2>\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Name <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"My Pipeline\"\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Description</label>\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"What does this pipeline do?\"\n rows={3}\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg resize-none\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Status</label>\n <select\n value={status}\n onChange={(e) => setStatus(e.target.value as PipelineStatus)}\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n {STATUS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n </div>\n\n {/* Stages — primary emphasis zone */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Stages ({stages.length})</h2>\n <button\n type=\"button\"\n onClick={handleAddStage}\n className=\"inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n <PlusIcon className=\"w-4 h-4\" />\n Add Stage\n </button>\n </div>\n\n {stages.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No stages yet\"\n description=\"Add a stage to start building your pipeline.\"\n action={\n <button\n type=\"button\"\n onClick={handleAddStage}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n <PlusIcon className=\"w-4 h-4\" />\n Add First Stage\n </button>\n }\n />\n ) : (\n <div className=\"space-y-4\">\n {stages.map((stage, index) => (\n <div key={index} className=\"p-4 bg-bg-sunken border border-border-default rounded-lg\">\n <div className=\"flex items-center justify-between mb-4\">\n <div className=\"flex items-center gap-2\">\n <span className=\"w-6 h-6 flex items-center justify-center text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded-full\">\n {index + 1}\n </span>\n <span className=\"font-medium text-text-primary\">\n {stage.parserName || `Stage ${index + 1}`}\n </span>\n </div>\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => handleMoveStage(index, 'up')}\n disabled={index === 0}\n className=\"p-1 text-text-secondary hover:text-text-primary hover:bg-bg-surface rounded disabled:opacity-30\"\n >\n <ArrowUpIcon className=\"w-4 h-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleMoveStage(index, 'down')}\n disabled={index === stages.length - 1}\n className=\"p-1 text-text-secondary hover:text-text-primary hover:bg-bg-surface rounded disabled:opacity-30\"\n >\n <ArrowDownIcon className=\"w-4 h-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleRemoveStage(index)}\n className=\"p-1 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg/10 rounded\"\n >\n <TrashIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"col-span-2\">\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n Parser <span className=\"text-status-error-text\">*</span>\n </label>\n <select\n value={stage.parserId}\n onChange={(e) => handleParserSelect(index, e.target.value)}\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n <option value=\"\">Select a parser...</option>\n {parsers.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name} ({p.type.toUpperCase()})\n </option>\n ))}\n </select>\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n Input Key <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n value={stage.inputKey}\n onChange={(e) => handleUpdateStage(index, { inputKey: e.target.value })}\n placeholder=\"data\"\n className=\"w-full px-3 py-2 text-sm font-mono text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n Output Key <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n value={stage.outputKey}\n onChange={(e) => handleUpdateStage(index, { outputKey: e.target.value })}\n placeholder=\"result\"\n className=\"w-full px-3 py-2 text-sm font-mono text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">On Error</label>\n <select\n value={stage.onError}\n onChange={(e) =>\n handleUpdateStage(index, {\n onError: e.target.value as StageErrorHandling,\n })\n }\n className=\"w-full px-3 py-2 text-sm text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n {ERROR_HANDLING_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"flex items-center\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={stage.enabled}\n onChange={(e) => handleUpdateStage(index, { enabled: e.target.checked })}\n className=\"w-4 h-4 rounded border-border-default text-action-primary-bg focus:ring-action-primary-bg\"\n />\n <span className=\"text-sm text-text-primary\">Enabled</span>\n </label>\n </div>\n\n {stage.onError === 'fallback' && (\n <div className=\"col-span-2\">\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n Fallback Value (JSON)\n </label>\n <input\n type=\"text\"\n value={stage.fallbackValue}\n onChange={(e) => handleUpdateStage(index, { fallbackValue: e.target.value })}\n placeholder='{\"default\": true}'\n className=\"w-full px-3 py-2 text-sm font-mono text-text-primary bg-bg-surface border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </GlassCard>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Preview */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Preview</h2>\n\n <div className=\"space-y-3\">\n <div>\n <span className=\"text-xs text-text-secondary\">Name</span>\n <p className=\"text-sm text-text-primary\">{name || 'Untitled'}</p>\n </div>\n\n <div>\n <span className=\"text-xs text-text-secondary\">Status</span>\n <div className=\"mt-1\">\n <PipelineStatusBadge status={status} />\n </div>\n </div>\n\n <div>\n <span className=\"text-xs text-text-secondary\">Stages</span>\n <p className=\"text-sm text-text-primary\">{stages.length}</p>\n </div>\n\n {stages.length > 0 && (\n <div>\n <span className=\"text-xs text-text-secondary\">Data Flow</span>\n <div className=\"mt-1 text-xs font-mono text-text-secondary\">\n {stages.map((s, i) => (\n <span key={i}>\n {s.inputKey}\n {i < stages.length - 1 && ' → '}\n </span>\n ))}\n {stages.length > 0 && ` → ${stages[stages.length - 1].outputKey}`}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Help */}\n <div className=\"bg-bg-sunken border border-border-default rounded-lg p-6\">\n <h3 className=\"text-sm font-semibold text-text-primary mb-2\">Tips</h3>\n <ul className=\"text-xs text-text-secondary space-y-2\">\n <li>• Each stage processes the output of the previous stage</li>\n <li>• Use consistent input/output keys to chain data</li>\n <li>• Set error handling per stage for robustness</li>\n <li>• Disable stages to skip them during execution</li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n );\n});\n\nexport default PipelineBuilderPage;\n"],"mappings":"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"}
|
|
@@ -96,11 +96,11 @@ var b = ({ className: e }) => /* @__PURE__ */ v("svg", {
|
|
|
96
96
|
let t = {
|
|
97
97
|
fail: {
|
|
98
98
|
label: "Fail",
|
|
99
|
-
className: "bg-
|
|
99
|
+
className: "bg-status-error-bg/10 text-status-error-text"
|
|
100
100
|
},
|
|
101
101
|
skip: {
|
|
102
102
|
label: "Skip",
|
|
103
|
-
className: "bg-
|
|
103
|
+
className: "bg-status-warning-bg/10 text-status-warning-text"
|
|
104
104
|
},
|
|
105
105
|
fallback: {
|
|
106
106
|
label: "Fallback",
|
|
@@ -180,8 +180,8 @@ var b = ({ className: e }) => /* @__PURE__ */ v("svg", {
|
|
|
180
180
|
className: "flex flex-col items-center justify-center py-16 text-center",
|
|
181
181
|
children: [
|
|
182
182
|
/* @__PURE__ */ v("div", {
|
|
183
|
-
className: "p-3 rounded-full bg-
|
|
184
|
-
children: /* @__PURE__ */ v(w, { className: "w-8 h-8 text-
|
|
183
|
+
className: "p-3 rounded-full bg-status-error-bg/10 mb-4",
|
|
184
|
+
children: /* @__PURE__ */ v(w, { className: "w-8 h-8 text-status-error-text" })
|
|
185
185
|
}),
|
|
186
186
|
/* @__PURE__ */ v("h3", {
|
|
187
187
|
className: "text-lg font-medium text-text-primary mb-2",
|
|
@@ -227,7 +227,7 @@ var b = ({ className: e }) => /* @__PURE__ */ v("svg", {
|
|
|
227
227
|
/* @__PURE__ */ y("button", {
|
|
228
228
|
type: "button",
|
|
229
229
|
onClick: () => R(!L),
|
|
230
|
-
className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-
|
|
230
|
+
className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-status-success-text bg-status-success-bg/10 hover:bg-status-success-bg/20 rounded-md transition-colors",
|
|
231
231
|
children: [/* @__PURE__ */ v(C, { className: "w-4 h-4" }), "Test"]
|
|
232
232
|
}),
|
|
233
233
|
/* @__PURE__ */ y("button", {
|
|
@@ -239,7 +239,7 @@ var b = ({ className: e }) => /* @__PURE__ */ v("svg", {
|
|
|
239
239
|
/* @__PURE__ */ y("button", {
|
|
240
240
|
type: "button",
|
|
241
241
|
onClick: Y,
|
|
242
|
-
className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-
|
|
242
|
+
className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-status-error-text bg-status-error-bg/10 hover:bg-status-error-bg/20 rounded-md transition-colors",
|
|
243
243
|
children: [/* @__PURE__ */ v(S, { className: "w-4 h-4" }), "Delete"]
|
|
244
244
|
})
|
|
245
245
|
]
|
|
@@ -384,11 +384,11 @@ var b = ({ className: e }) => /* @__PURE__ */ v("svg", {
|
|
|
384
384
|
children: [
|
|
385
385
|
/* @__PURE__ */ y("div", {
|
|
386
386
|
className: "flex items-center gap-2 mb-2",
|
|
387
|
-
children: [F.status === "completed" ? /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(T, { className: "w-4 h-4 text-
|
|
388
|
-
className: "text-sm font-medium text-
|
|
387
|
+
children: [F.status === "completed" ? /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(T, { className: "w-4 h-4 text-status-success-text" }), /* @__PURE__ */ v("span", {
|
|
388
|
+
className: "text-sm font-medium text-status-success-text",
|
|
389
389
|
children: "Test Passed"
|
|
390
|
-
})] }) : /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(w, { className: "w-4 h-4 text-
|
|
391
|
-
className: "text-sm font-medium text-
|
|
390
|
+
})] }) : /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(w, { className: "w-4 h-4 text-status-error-text" }), /* @__PURE__ */ v("span", {
|
|
391
|
+
className: "text-sm font-medium text-status-error-text",
|
|
392
392
|
children: "Test Failed"
|
|
393
393
|
})] }), F.totalExecutionTimeMs && /* @__PURE__ */ y("span", {
|
|
394
394
|
className: "text-xs text-text-secondary",
|
|
@@ -409,10 +409,10 @@ var b = ({ className: e }) => /* @__PURE__ */ v("svg", {
|
|
|
409
409
|
F.error && /* @__PURE__ */ y("div", {
|
|
410
410
|
className: "mt-2",
|
|
411
411
|
children: [/* @__PURE__ */ v("label", {
|
|
412
|
-
className: "block text-sm font-medium text-
|
|
412
|
+
className: "block text-sm font-medium text-status-error-text mb-2",
|
|
413
413
|
children: "Error"
|
|
414
414
|
}), /* @__PURE__ */ v("pre", {
|
|
415
|
-
className: "w-full p-3 text-xs font-mono text-
|
|
415
|
+
className: "w-full p-3 text-xs font-mono text-status-error-text bg-status-error-bg/10 border border-status-error-border/20 rounded-md overflow-auto",
|
|
416
416
|
children: F.error
|
|
417
417
|
})]
|
|
418
418
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PipelineViewPage.js","names":[],"sources":["../../../src/bigconsole/pages/PipelineViewPage.tsx"],"sourcesContent":["/**\n * Pipeline View Page\n *\n * Display Pipeline details, stages, and execution history.\n * Supports testing pipeline with sample input.\n */\n\nimport { memo, useState, useCallback, useEffect } from 'react';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport { GlassCard, IllustratedEmptyState, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { usePipelineOperations } from '../hooks/usePipelineOperations';\nimport { usePipelineStore } from '../store/pipelineStore';\nimport { PipelineStatusBadge } from '../components/pipeline/PipelineStatusBadge';\nimport { PipelineDeleteDialog } from '../components/pipeline/PipelineDeleteDialog';\nimport type { Pipeline, PipelineExecution, PipelineStage } from '../types';\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst BackIcon = ({ 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=\"M10 19l-7-7m0 0l7-7m-7 7h18\" />\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 DeleteIcon = ({ 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 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 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 ArrowRightIcon = ({ 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=\"M14 5l7 7m0 0l-7 7m7-7H3\" />\n </svg>\n);\n\n// ============================================================================\n// STAGE ERROR BADGE\n// ============================================================================\n\nconst StageErrorBadge = ({ handling }: { handling: string }) => {\n const config = {\n fail: { label: 'Fail', className: 'bg-state-error/10 text-state-error' },\n skip: { label: 'Skip', className: 'bg-state-warning/10 text-state-warning' },\n fallback: { label: 'Fallback', className: 'bg-action-primary-bg/10 text-action-primary-bg' },\n };\n const c = config[handling as keyof typeof config] || config.fail;\n return <span className={`px-1.5 py-0.5 text-xs font-medium rounded ${c.className}`}>{c.label}</span>;\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const PipelineViewPage = memo(function PipelineViewPage() {\n const { pipelineId } = useParams<{ pipelineId: string }>();\n const navigate = useAppNavigate();\n // Use default consoleId for now (should come from context in production)\n const consoleId = 'default';\n const [searchParams] = useSearchParams();\n\n // Local state\n const [pipeline, setPipeline] = useState<Pipeline | null>(null);\n const [testInput, setTestInput] = useState('{\\n \"data\": \"sample\"\\n}');\n const [testResult, setTestResult] = useState<PipelineExecution | null>(null);\n const [showTestPanel, setShowTestPanel] = useState(searchParams.get('test') === 'true');\n\n // Store state\n const deleteDialogOpen = usePipelineStore((state) => state.deleteDialogOpen);\n const openDeleteDialog = usePipelineStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = usePipelineStore((state) => state.closeDeleteDialog);\n\n // Operations\n const { loading, error, fetchPipeline, deletePipeline, testPipeline } = usePipelineOperations({\n consoleId,\n skipFetch: true,\n });\n\n // Fetch pipeline on mount\n useEffect(() => {\n if (pipelineId) {\n fetchPipeline(pipelineId).then((result) => {\n if (result) {\n setPipeline(result);\n }\n });\n }\n }, [pipelineId, fetchPipeline]);\n\n // Handlers\n const handleBack = useCallback(() => {\n navigate(`/pipelines`);\n }, [navigate]);\n\n const handleEdit = useCallback(() => {\n navigate(`/pipelines/${pipelineId}/edit`);\n }, [navigate, pipelineId]);\n\n const handleDeleteClick = useCallback(() => {\n if (pipeline) {\n openDeleteDialog(pipeline);\n }\n }, [pipeline, openDeleteDialog]);\n\n const handleDeleteConfirm = useCallback(async () => {\n if (pipeline) {\n const success = await deletePipeline(pipeline.id);\n if (success) {\n if (isNative()) void nativeNotify('success');\n closeDeleteDialog();\n navigate(`/pipelines`);\n } else if (isNative()) {\n void nativeNotify('error');\n }\n }\n }, [pipeline, deletePipeline, closeDeleteDialog, navigate]);\n\n const handleViewParser = useCallback(\n (parserId: string) => {\n navigate(`/dashboards/${consoleId}/parsers/${parserId}`);\n },\n [navigate, consoleId]\n );\n\n const handleTest = useCallback(async () => {\n if (!pipeline) return;\n\n try {\n const result = await testPipeline({\n pipelineId: pipeline.id,\n inputData: testInput,\n });\n if (result) {\n setTestResult(result);\n }\n } catch (err) {}\n }, [pipeline, testPipeline, testInput]);\n\n // Loading state\n if (loading && !pipeline) {\n return (\n <div className=\"p-6\">\n <div className=\"flex flex-col items-center justify-center py-16\">\n <svg className=\"w-8 h-8 text-action-primary-bg animate-spin mb-4\" 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 <p className=\"text-sm text-text-secondary\">Loading Pipeline...</p>\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"p-6\">\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\">Failed to load Pipeline</h3>\n <p className=\"text-sm text-text-secondary mb-4\">{error.message}</p>\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n Back to Pipelines\n </button>\n </div>\n </div>\n );\n }\n\n // Not found state\n if (!pipeline) {\n return (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"Pipeline not found\"\n description=\"The pipeline you're looking for doesn't exist or has been deleted.\"\n action={\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n Back to Pipelines\n </button>\n }\n />\n </div>\n );\n }\n\n return (\n <div className=\"p-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-6\">\n <div className=\"flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n <BackIcon className=\"w-5 h-5\" />\n </button>\n <div>\n <div className=\"flex items-center gap-3\">\n <h1 className=\"text-2xl font-bold text-text-primary\">{pipeline.name}</h1>\n <PipelineStatusBadge status={pipeline.status} />\n </div>\n {pipeline.description && <p className=\"text-sm text-text-secondary mt-1\">{pipeline.description}</p>}\n </div>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => setShowTestPanel(!showTestPanel)}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-state-success bg-state-success/10 hover:bg-state-success/20 rounded-md transition-colors\"\n >\n <PlayIcon className=\"w-4 h-4\" />\n Test\n </button>\n <button\n type=\"button\"\n onClick={handleEdit}\n className=\"inline-flex items-center gap-2 px-3 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={handleDeleteClick}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-state-error bg-state-error/10 hover:bg-state-error/20 rounded-md transition-colors\"\n >\n <DeleteIcon className=\"w-4 h-4\" />\n Delete\n </button>\n </div>\n </div>\n\n <PagePurpose className=\"mb-6\">\n A pipeline chains parsers and a data sink into a repeatable flow. Review its stages here, test it with sample\n input to confirm the output, then edit the stages or run it to process real data into the connected sink.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"bigconsole-pipeline-view\"\n steps={[\n {\n id: 'test',\n label: 'Test with sample input',\n description: 'Run the pipeline against a sample to verify each stage.',\n onClick: () => setShowTestPanel(true),\n },\n {\n id: 'edit',\n label: 'Edit the stages',\n description: 'Add, reorder, or configure the parsers in this pipeline.',\n onClick: handleEdit,\n },\n {\n id: 'sinks',\n label: 'Review the target data sink',\n description: 'See where the processed data lands.',\n onClick: () => navigate('/datasinks'),\n },\n ]}\n />\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n {/* Main Content */}\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Stages — primary emphasis zone */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">\n Pipeline Stages ({pipeline.stages?.length || 0})\n </h2>\n\n {!pipeline.stages || pipeline.stages.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No stages defined\"\n description=\"Edit the pipeline to add parser stages.\"\n />\n ) : (\n <div className=\"space-y-3\">\n {pipeline.stages.map((stage: PipelineStage, index: number) => (\n <div key={stage.id} className=\"flex items-center gap-3\">\n {/* Stage Card */}\n <div\n className={`\n flex-1 p-4 rounded-lg border\n ${stage.enabled ? 'bg-bg-surface border-border-default' : 'bg-bg-sunken border-border-default opacity-60'}\n `}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"w-6 h-6 flex items-center justify-center text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded-full\">\n {index + 1}\n </span>\n <span className=\"font-medium text-text-primary\">\n {stage.parserName || `Stage ${index + 1}`}\n </span>\n {stage.parserType && (\n <span className=\"px-1.5 py-0.5 text-xs font-medium bg-bg-sunken text-text-secondary rounded\">\n {stage.parserType.toUpperCase()}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n <StageErrorBadge handling={stage.onError} />\n {!stage.enabled && (\n <span className=\"px-1.5 py-0.5 text-xs font-medium bg-bg-sunken text-text-secondary rounded\">\n Disabled\n </span>\n )}\n </div>\n </div>\n\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <span className=\"font-mono bg-bg-sunken px-1.5 py-0.5 rounded\">{stage.inputKey}</span>\n <ArrowRightIcon className=\"w-3 h-3\" />\n <span className=\"font-mono bg-bg-sunken px-1.5 py-0.5 rounded\">{stage.outputKey}</span>\n </div>\n\n {stage.description && <p className=\"text-xs text-text-secondary mt-2\">{stage.description}</p>}\n\n {stage.parserId && (\n <button\n type=\"button\"\n onClick={() => handleViewParser(stage.parserId)}\n className=\"mt-2 text-xs text-action-primary-bg hover:underline\"\n >\n View Parser\n </button>\n )}\n </div>\n\n {/* Arrow to next stage */}\n {index < (pipeline.stages?.length || 0) - 1 && (\n <ArrowRightIcon className=\"w-5 h-5 text-text-secondary flex-shrink-0 hidden md:block\" />\n )}\n </div>\n ))}\n </div>\n )}\n </GlassCard>\n\n {/* Test Panel */}\n {showTestPanel && (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Test Pipeline</h2>\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Input JSON</label>\n <textarea\n value={testInput}\n onChange={(e) => setTestInput(e.target.value)}\n className=\"w-full h-32 px-3 py-2 text-sm font-mono text-text-primary bg-bg-sunken border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg resize-none\"\n placeholder='{\"key\": \"value\"}'\n />\n </div>\n\n <button\n type=\"button\"\n onClick={handleTest}\n disabled={loading}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors disabled:opacity-50\"\n >\n <PlayIcon className=\"w-4 h-4\" />\n {loading ? 'Running...' : 'Run Test'}\n </button>\n\n {testResult && (\n <div className=\"mt-4\">\n <div className=\"flex items-center gap-2 mb-2\">\n {testResult.status === 'completed' ? (\n <>\n <CheckIcon className=\"w-4 h-4 text-state-success\" />\n <span className=\"text-sm font-medium text-state-success\">Test Passed</span>\n </>\n ) : (\n <>\n <ErrorIcon className=\"w-4 h-4 text-state-error\" />\n <span className=\"text-sm font-medium text-state-error\">Test Failed</span>\n </>\n )}\n {testResult.totalExecutionTimeMs && (\n <span className=\"text-xs text-text-secondary\">({testResult.totalExecutionTimeMs}ms)</span>\n )}\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Output</label>\n <pre className=\"w-full p-3 text-xs font-mono text-text-primary bg-bg-sunken border border-border-default rounded-md overflow-auto max-h-48\">\n {JSON.stringify(testResult.outputData, null, 2) || 'null'}\n </pre>\n </div>\n\n {testResult.error && (\n <div className=\"mt-2\">\n <label className=\"block text-sm font-medium text-state-error mb-2\">Error</label>\n <pre className=\"w-full p-3 text-xs font-mono text-state-error bg-state-error/10 border border-state-error/20 rounded-md overflow-auto\">\n {testResult.error}\n </pre>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Details */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Details</h2>\n\n <dl className=\"space-y-3\">\n <div>\n <dt className=\"text-xs text-text-secondary\">Status</dt>\n <dd className=\"mt-1\">\n <PipelineStatusBadge status={pipeline.status} />\n </dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Stages</dt>\n <dd className=\"text-sm text-text-primary\">{pipeline.stages?.length || 0}</dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Last Executed</dt>\n <dd className=\"text-sm text-text-primary\">\n {pipeline.lastExecutedAt ? new Date(pipeline.lastExecutedAt).toLocaleString() : 'Never'}\n </dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Version</dt>\n <dd className=\"text-sm text-text-primary\">{pipeline.version}</dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Created</dt>\n <dd className=\"text-sm text-text-primary\">{new Date(pipeline.createdAt).toLocaleString()}</dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Updated</dt>\n <dd className=\"text-sm text-text-primary\">{new Date(pipeline.updatedAt).toLocaleString()}</dd>\n </div>\n </dl>\n </div>\n </div>\n </div>\n\n {/* Delete Dialog */}\n {pipeline && (\n <PipelineDeleteDialog\n pipeline={pipeline}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n </div>\n );\n});\n\nexport default PipelineViewPage;\n"],"mappings":";;;;;;;;;;;;AAsBA,IAAM,KAAY,EAAE,mBAClB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAgC,CAAA;CACjG,CAAA,EAGF,KAAY,EAAE,mBAClB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAGF,KAAc,EAAE,mBACpB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAGF,KAAY,EAAE,mBAClB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WAArE,CACE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA,EACF,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAuC,CAAA,CACxG;IAGF,KAAa,EAAE,mBACnB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EACE,eAAc;EACd,gBAAe;EACf,aAAa;EACb,GAAE;EACF,CAAA;CACE,CAAA,EAGF,KAAa,EAAE,mBACnB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAAmB,CAAA;CACpF,CAAA,EAGF,KAAkB,EAAE,mBACxB,kBAAC,OAAD;CAAgB;CAAW,MAAK;CAAO,QAAO;CAAe,SAAQ;WACnE,kBAAC,QAAD;EAAM,eAAc;EAAQ,gBAAe;EAAQ,aAAa;EAAG,GAAE;EAA6B,CAAA;CAC9F,CAAA,EAOF,KAAmB,EAAE,kBAAqC;CAC9D,IAAM,IAAS;EACb,MAAM;GAAE,OAAO;GAAQ,WAAW;GAAsC;EACxE,MAAM;GAAE,OAAO;GAAQ,WAAW;GAA0C;EAC5E,UAAU;GAAE,OAAO;GAAY,WAAW;GAAkD;EAC7F,EACK,IAAI,EAAO,MAAoC,EAAO;AAC5D,QAAO,kBAAC,QAAD;EAAM,WAAW,6CAA6C,EAAE;YAAc,EAAE;EAAa,CAAA;GAOzF,IAAmB,EAAK,WAA4B;CAC/D,IAAM,EAAE,kBAAe,GAAmC,EACpD,IAAW,GAAgB,EAE3B,IAAY,WACZ,CAAC,KAAgB,GAAiB,EAGlC,CAAC,GAAU,KAAe,EAA0B,KAAK,EACzD,CAAC,GAAW,KAAgB,EAAS,+BAA2B,EAChE,CAAC,GAAY,KAAiB,EAAmC,KAAK,EACtE,CAAC,GAAe,KAAoB,EAAS,EAAa,IAAI,OAAO,KAAK,OAAO,EAGjF,IAAmB,GAAkB,MAAU,EAAM,iBAAiB,EACtE,IAAmB,GAAkB,MAAU,EAAM,iBAAiB,EACtE,IAAoB,GAAkB,MAAU,EAAM,kBAAkB,EAGxE,EAAE,YAAS,UAAO,kBAAe,mBAAgB,oBAAiB,EAAsB;EAC5F;EACA,WAAW;EACZ,CAAC;AAGF,SAAgB;AACd,EAAI,KACF,EAAc,EAAW,CAAC,MAAM,MAAW;AACzC,GAAI,KACF,EAAY,EAAO;IAErB;IAEH,CAAC,GAAY,EAAc,CAAC;CAG/B,IAAM,IAAa,QAAkB;AACnC,IAAS,aAAa;IACrB,CAAC,EAAS,CAAC,EAER,IAAa,QAAkB;AACnC,IAAS,cAAc,EAAW,OAAO;IACxC,CAAC,GAAU,EAAW,CAAC,EAEpB,IAAoB,QAAkB;AAC1C,EAAI,KACF,EAAiB,EAAS;IAE3B,CAAC,GAAU,EAAiB,CAAC,EAE1B,IAAsB,EAAY,YAAY;AAClD,EAAI,MACc,MAAM,EAAe,EAAS,GAAG,IAE3C,GAAU,IAAO,EAAa,UAAU,EAC5C,GAAmB,EACnB,EAAS,aAAa,IACb,GAAU,IACd,EAAa,QAAQ;IAG7B;EAAC;EAAU;EAAgB;EAAmB;EAAS,CAAC,EAErD,IAAmB,GACtB,MAAqB;AACpB,IAAS,eAAe,EAAU,WAAW,IAAW;IAE1D,CAAC,GAAU,EAAU,CACtB,EAEK,IAAa,EAAY,YAAY;AACpC,QAEL,KAAI;GACF,IAAM,IAAS,MAAM,EAAa;IAChC,YAAY,EAAS;IACrB,WAAW;IACZ,CAAC;AACF,GAAI,KACF,EAAc,EAAO;UAEX;IACb;EAAC;EAAU;EAAc;EAAU,CAAC;AAiEvC,QA9DI,KAAW,CAAC,IAEZ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;IAAmD,MAAK;IAAO,SAAQ;cAAtF,CACE,kBAAC,UAAD;KAAQ,WAAU;KAAa,IAAG;KAAK,IAAG;KAAK,GAAE;KAAK,QAAO;KAAe,aAAY;KAAM,CAAA,EAC9F,kBAAC,QAAD;KACE,WAAU;KACV,MAAK;KACL,GAAE;KACF,CAAA,CACE;OACN,kBAAC,KAAD;IAAG,WAAU;cAA8B;IAAuB,CAAA,CAC9D;;EACF,CAAA,GAKN,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD,EAAW,WAAU,4BAA6B,CAAA;KAC9C,CAAA;IACN,kBAAC,MAAD;KAAI,WAAU;eAA6C;KAA4B,CAAA;IACvF,kBAAC,KAAD;KAAG,WAAU;eAAoC,EAAM;KAAY,CAAA;IACnE,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eACX;KAEQ,CAAA;IACL;;EACF,CAAA,GAKL,IAsBH,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;gBAEV,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;MACzB,CAAA,EACT,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBAAwC,EAAS;OAAU,CAAA,EACzE,kBAAC,GAAD,EAAqB,QAAQ,EAAS,QAAU,CAAA,CAC5C;SACL,EAAS,eAAe,kBAAC,KAAD;MAAG,WAAU;gBAAoC,EAAS;MAAgB,CAAA,CAC/F,EAAA,CAAA,CACF;QAEN,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAiB,CAAC,EAAc;OAC/C,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA,EAAA,OAEzB;;MACT,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA,EAAA,OAEzB;;MACT,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA,EAAA,SAE3B;;MACL;OACF;;GAEN,kBAAC,GAAD;IAAa,WAAU;cAAO;IAGhB,CAAA;GAEd,kBAAC,GAAD;IACE,YAAW;IACX,OAAO;KACL;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,eAAe,EAAiB,GAAK;MACtC;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,SAAS;MACV;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,eAAe,EAAS,aAAa;MACtC;KACF;IACD,CAAA;GAEF,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,OAAD;KAAK,WAAU;eAAf,CAEE,kBAAC,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;gBAA5C,CACE,kBAAC,MAAD;OAAI,WAAU;iBAAd;QAA6D;QACzC,EAAS,QAAQ,UAAU;QAAE;QAC5C;UAEJ,CAAC,EAAS,UAAU,EAAS,OAAO,WAAW,IAC9C,kBAAC,GAAD;OACE,cAAa;OACb,OAAM;OACN,aAAY;OACZ,CAAA,GAEF,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAS,OAAO,KAAK,GAAsB,MAC1C,kBAAC,OAAD;QAAoB,WAAU;kBAA9B,CAEE,kBAAC,OAAD;SACE,WAAW;;0BAEP,EAAM,UAAU,wCAAwC,gDAAgD;;mBAH9G;UAME,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,OAAD;YAAK,WAAU;sBAAf;aACE,kBAAC,QAAD;cAAM,WAAU;wBACb,IAAQ;cACJ,CAAA;aACP,kBAAC,QAAD;cAAM,WAAU;wBACb,EAAM,cAAc,SAAS,IAAQ;cACjC,CAAA;aACN,EAAM,cACL,kBAAC,QAAD;cAAM,WAAU;wBACb,EAAM,WAAW,aAAa;cAC1B,CAAA;aAEL;eACN,kBAAC,OAAD;YAAK,WAAU;sBAAf,CACE,kBAAC,GAAD,EAAiB,UAAU,EAAM,SAAW,CAAA,EAC3C,CAAC,EAAM,WACN,kBAAC,QAAD;aAAM,WAAU;uBAA6E;aAEtF,CAAA,CAEL;cACF;;UAEN,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,QAAD;aAAM,WAAU;uBAAgD,EAAM;aAAgB,CAAA;YACtF,kBAAC,GAAD,EAAgB,WAAU,WAAY,CAAA;YACtC,kBAAC,QAAD;aAAM,WAAU;uBAAgD,EAAM;aAAiB,CAAA;YACnF;;UAEL,EAAM,eAAe,kBAAC,KAAD;WAAG,WAAU;qBAAoC,EAAM;WAAgB,CAAA;UAE5F,EAAM,YACL,kBAAC,UAAD;WACE,MAAK;WACL,eAAe,EAAiB,EAAM,SAAS;WAC/C,WAAU;qBACX;WAEQ,CAAA;UAEP;YAGL,KAAS,EAAS,QAAQ,UAAU,KAAK,KACxC,kBAAC,GAAD,EAAgB,WAAU,6DAA8D,CAAA,CAEtF;UAvDI,EAAM,GAuDV,CACN;OACE,CAAA,CAEE;SAGX,KACC,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBAA+C;OAAkB,CAAA,EAE/E,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;SAAO,WAAU;mBAAmD;SAAkB,CAAA,EACtF,kBAAC,YAAD;SACE,OAAO;SACP,WAAW,MAAM,EAAa,EAAE,OAAO,MAAM;SAC7C,WAAU;SACV,aAAY;SACZ,CAAA,CACE,EAAA,CAAA;QAEN,kBAAC,UAAD;SACE,MAAK;SACL,SAAS;SACT,UAAU;SACV,WAAU;mBAJZ,CAME,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA,EAC/B,IAAU,eAAe,WACnB;;QAER,KACC,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACG,EAAW,WAAW,cACrB,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAW,WAAU,8BAA+B,CAAA,EACpD,kBAAC,QAAD;YAAM,WAAU;sBAAyC;YAAkB,CAAA,CAC1E,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAW,WAAU,4BAA6B,CAAA,EAClD,kBAAC,QAAD;YAAM,WAAU;sBAAuC;YAAkB,CAAA,CACxE,EAAA,CAAA,EAEJ,EAAW,wBACV,kBAAC,QAAD;YAAM,WAAU;sBAAhB;aAA8C;aAAE,EAAW;aAAqB;aAAU;cAExF;;UAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;WAAO,WAAU;qBAAmD;WAAc,CAAA,EAClF,kBAAC,OAAD;WAAK,WAAU;qBACZ,KAAK,UAAU,EAAW,YAAY,MAAM,EAAE,IAAI;WAC/C,CAAA,CACF,EAAA,CAAA;UAEL,EAAW,SACV,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,SAAD;YAAO,WAAU;sBAAkD;YAAa,CAAA,EAChF,kBAAC,OAAD;YAAK,WAAU;sBACZ,EAAW;YACR,CAAA,CACF;;UAEJ;;QAEJ;SACF;QAEJ;QAGN,kBAAC,OAAD;KAAK,WAAU;eAEb,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBAA+C;OAAY,CAAA,EAEzE,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA8B;SAAW,CAAA,EACvD,kBAAC,MAAD;SAAI,WAAU;mBACZ,kBAAC,GAAD,EAAqB,QAAQ,EAAS,QAAU,CAAA;SAC7C,CAAA,CACD,EAAA,CAAA;QAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA8B;SAAW,CAAA,EACvD,kBAAC,MAAD;SAAI,WAAU;mBAA6B,EAAS,QAAQ,UAAU;SAAO,CAAA,CACzE,EAAA,CAAA;QAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA8B;SAAkB,CAAA,EAC9D,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAS,iBAAiB,IAAI,KAAK,EAAS,eAAe,CAAC,gBAAgB,GAAG;SAC7E,CAAA,CACD,EAAA,CAAA;QAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA8B;SAAY,CAAA,EACxD,kBAAC,MAAD;SAAI,WAAU;mBAA6B,EAAS;SAAa,CAAA,CAC7D,EAAA,CAAA;QAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA8B;SAAY,CAAA,EACxD,kBAAC,MAAD;SAAI,WAAU;mBAA6B,IAAI,KAAK,EAAS,UAAU,CAAC,gBAAgB;SAAM,CAAA,CAC1F,EAAA,CAAA;QAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA8B;SAAY,CAAA,EACxD,kBAAC,MAAD;SAAI,WAAU;mBAA6B,IAAI,KAAK,EAAS,UAAU,CAAC,gBAAgB;SAAM,CAAA,CAC1F,EAAA,CAAA;QACH;SACD;;KACF,CAAA,CACF;;GAGL,KACC,kBAAC,GAAD;IACY;IACV,QAAQ;IACR,SAAS;IACT,WAAW;IACX,CAAA;GAEA;MAzSJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,QACE,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,WAAU;cACX;IAEQ,CAAA;GAEX,CAAA;EACE,CAAA;EA4RV"}
|
|
1
|
+
{"version":3,"file":"PipelineViewPage.js","names":[],"sources":["../../../src/bigconsole/pages/PipelineViewPage.tsx"],"sourcesContent":["/**\n * Pipeline View Page\n *\n * Display Pipeline details, stages, and execution history.\n * Supports testing pipeline with sample input.\n */\n\nimport { memo, useState, useCallback, useEffect } from 'react';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport { GlassCard, IllustratedEmptyState, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { usePipelineOperations } from '../hooks/usePipelineOperations';\nimport { usePipelineStore } from '../store/pipelineStore';\nimport { PipelineStatusBadge } from '../components/pipeline/PipelineStatusBadge';\nimport { PipelineDeleteDialog } from '../components/pipeline/PipelineDeleteDialog';\nimport type { Pipeline, PipelineExecution, PipelineStage } from '../types';\n\n// ============================================================================\n// ICONS\n// ============================================================================\n\nconst BackIcon = ({ 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=\"M10 19l-7-7m0 0l7-7m-7 7h18\" />\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 DeleteIcon = ({ 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 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 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 ArrowRightIcon = ({ 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=\"M14 5l7 7m0 0l-7 7m7-7H3\" />\n </svg>\n);\n\n// ============================================================================\n// STAGE ERROR BADGE\n// ============================================================================\n\nconst StageErrorBadge = ({ handling }: { handling: string }) => {\n const config = {\n fail: { label: 'Fail', className: 'bg-status-error-bg/10 text-status-error-text' },\n skip: { label: 'Skip', className: 'bg-status-warning-bg/10 text-status-warning-text' },\n fallback: { label: 'Fallback', className: 'bg-action-primary-bg/10 text-action-primary-bg' },\n };\n const c = config[handling as keyof typeof config] || config.fail;\n return <span className={`px-1.5 py-0.5 text-xs font-medium rounded ${c.className}`}>{c.label}</span>;\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const PipelineViewPage = memo(function PipelineViewPage() {\n const { pipelineId } = useParams<{ pipelineId: string }>();\n const navigate = useAppNavigate();\n // Use default consoleId for now (should come from context in production)\n const consoleId = 'default';\n const [searchParams] = useSearchParams();\n\n // Local state\n const [pipeline, setPipeline] = useState<Pipeline | null>(null);\n const [testInput, setTestInput] = useState('{\\n \"data\": \"sample\"\\n}');\n const [testResult, setTestResult] = useState<PipelineExecution | null>(null);\n const [showTestPanel, setShowTestPanel] = useState(searchParams.get('test') === 'true');\n\n // Store state\n const deleteDialogOpen = usePipelineStore((state) => state.deleteDialogOpen);\n const openDeleteDialog = usePipelineStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = usePipelineStore((state) => state.closeDeleteDialog);\n\n // Operations\n const { loading, error, fetchPipeline, deletePipeline, testPipeline } = usePipelineOperations({\n consoleId,\n skipFetch: true,\n });\n\n // Fetch pipeline on mount\n useEffect(() => {\n if (pipelineId) {\n fetchPipeline(pipelineId).then((result) => {\n if (result) {\n setPipeline(result);\n }\n });\n }\n }, [pipelineId, fetchPipeline]);\n\n // Handlers\n const handleBack = useCallback(() => {\n navigate(`/pipelines`);\n }, [navigate]);\n\n const handleEdit = useCallback(() => {\n navigate(`/pipelines/${pipelineId}/edit`);\n }, [navigate, pipelineId]);\n\n const handleDeleteClick = useCallback(() => {\n if (pipeline) {\n openDeleteDialog(pipeline);\n }\n }, [pipeline, openDeleteDialog]);\n\n const handleDeleteConfirm = useCallback(async () => {\n if (pipeline) {\n const success = await deletePipeline(pipeline.id);\n if (success) {\n if (isNative()) void nativeNotify('success');\n closeDeleteDialog();\n navigate(`/pipelines`);\n } else if (isNative()) {\n void nativeNotify('error');\n }\n }\n }, [pipeline, deletePipeline, closeDeleteDialog, navigate]);\n\n const handleViewParser = useCallback(\n (parserId: string) => {\n navigate(`/dashboards/${consoleId}/parsers/${parserId}`);\n },\n [navigate, consoleId]\n );\n\n const handleTest = useCallback(async () => {\n if (!pipeline) return;\n\n try {\n const result = await testPipeline({\n pipelineId: pipeline.id,\n inputData: testInput,\n });\n if (result) {\n setTestResult(result);\n }\n } catch (err) {}\n }, [pipeline, testPipeline, testInput]);\n\n // Loading state\n if (loading && !pipeline) {\n return (\n <div className=\"p-6\">\n <div className=\"flex flex-col items-center justify-center py-16\">\n <svg className=\"w-8 h-8 text-action-primary-bg animate-spin mb-4\" 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 <p className=\"text-sm text-text-secondary\">Loading Pipeline...</p>\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"p-6\">\n <div className=\"flex flex-col items-center justify-center py-16 text-center\">\n <div className=\"p-3 rounded-full bg-status-error-bg/10 mb-4\">\n <ErrorIcon className=\"w-8 h-8 text-status-error-text\" />\n </div>\n <h3 className=\"text-lg font-medium text-text-primary mb-2\">Failed to load Pipeline</h3>\n <p className=\"text-sm text-text-secondary mb-4\">{error.message}</p>\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n Back to Pipelines\n </button>\n </div>\n </div>\n );\n }\n\n // Not found state\n if (!pipeline) {\n return (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"Pipeline not found\"\n description=\"The pipeline you're looking for doesn't exist or has been deleted.\"\n action={\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors\"\n >\n Back to Pipelines\n </button>\n }\n />\n </div>\n );\n }\n\n return (\n <div className=\"p-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between mb-6\">\n <div className=\"flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-2 text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n <BackIcon className=\"w-5 h-5\" />\n </button>\n <div>\n <div className=\"flex items-center gap-3\">\n <h1 className=\"text-2xl font-bold text-text-primary\">{pipeline.name}</h1>\n <PipelineStatusBadge status={pipeline.status} />\n </div>\n {pipeline.description && <p className=\"text-sm text-text-secondary mt-1\">{pipeline.description}</p>}\n </div>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => setShowTestPanel(!showTestPanel)}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-status-success-text bg-status-success-bg/10 hover:bg-status-success-bg/20 rounded-md transition-colors\"\n >\n <PlayIcon className=\"w-4 h-4\" />\n Test\n </button>\n <button\n type=\"button\"\n onClick={handleEdit}\n className=\"inline-flex items-center gap-2 px-3 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={handleDeleteClick}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium text-status-error-text bg-status-error-bg/10 hover:bg-status-error-bg/20 rounded-md transition-colors\"\n >\n <DeleteIcon className=\"w-4 h-4\" />\n Delete\n </button>\n </div>\n </div>\n\n <PagePurpose className=\"mb-6\">\n A pipeline chains parsers and a data sink into a repeatable flow. Review its stages here, test it with sample\n input to confirm the output, then edit the stages or run it to process real data into the connected sink.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"bigconsole-pipeline-view\"\n steps={[\n {\n id: 'test',\n label: 'Test with sample input',\n description: 'Run the pipeline against a sample to verify each stage.',\n onClick: () => setShowTestPanel(true),\n },\n {\n id: 'edit',\n label: 'Edit the stages',\n description: 'Add, reorder, or configure the parsers in this pipeline.',\n onClick: handleEdit,\n },\n {\n id: 'sinks',\n label: 'Review the target data sink',\n description: 'See where the processed data lands.',\n onClick: () => navigate('/datasinks'),\n },\n ]}\n />\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n {/* Main Content */}\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Stages — primary emphasis zone */}\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">\n Pipeline Stages ({pipeline.stages?.length || 0})\n </h2>\n\n {!pipeline.stages || pipeline.stages.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No stages defined\"\n description=\"Edit the pipeline to add parser stages.\"\n />\n ) : (\n <div className=\"space-y-3\">\n {pipeline.stages.map((stage: PipelineStage, index: number) => (\n <div key={stage.id} className=\"flex items-center gap-3\">\n {/* Stage Card */}\n <div\n className={`\n flex-1 p-4 rounded-lg border\n ${stage.enabled ? 'bg-bg-surface border-border-default' : 'bg-bg-sunken border-border-default opacity-60'}\n `}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center gap-2\">\n <span className=\"w-6 h-6 flex items-center justify-center text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded-full\">\n {index + 1}\n </span>\n <span className=\"font-medium text-text-primary\">\n {stage.parserName || `Stage ${index + 1}`}\n </span>\n {stage.parserType && (\n <span className=\"px-1.5 py-0.5 text-xs font-medium bg-bg-sunken text-text-secondary rounded\">\n {stage.parserType.toUpperCase()}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n <StageErrorBadge handling={stage.onError} />\n {!stage.enabled && (\n <span className=\"px-1.5 py-0.5 text-xs font-medium bg-bg-sunken text-text-secondary rounded\">\n Disabled\n </span>\n )}\n </div>\n </div>\n\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <span className=\"font-mono bg-bg-sunken px-1.5 py-0.5 rounded\">{stage.inputKey}</span>\n <ArrowRightIcon className=\"w-3 h-3\" />\n <span className=\"font-mono bg-bg-sunken px-1.5 py-0.5 rounded\">{stage.outputKey}</span>\n </div>\n\n {stage.description && <p className=\"text-xs text-text-secondary mt-2\">{stage.description}</p>}\n\n {stage.parserId && (\n <button\n type=\"button\"\n onClick={() => handleViewParser(stage.parserId)}\n className=\"mt-2 text-xs text-action-primary-bg hover:underline\"\n >\n View Parser\n </button>\n )}\n </div>\n\n {/* Arrow to next stage */}\n {index < (pipeline.stages?.length || 0) - 1 && (\n <ArrowRightIcon className=\"w-5 h-5 text-text-secondary flex-shrink-0 hidden md:block\" />\n )}\n </div>\n ))}\n </div>\n )}\n </GlassCard>\n\n {/* Test Panel */}\n {showTestPanel && (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Test Pipeline</h2>\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Input JSON</label>\n <textarea\n value={testInput}\n onChange={(e) => setTestInput(e.target.value)}\n className=\"w-full h-32 px-3 py-2 text-sm font-mono text-text-primary bg-bg-sunken border border-border-default rounded-md focus:outline-none focus:ring-2 focus:ring-action-primary-bg resize-none\"\n placeholder='{\"key\": \"value\"}'\n />\n </div>\n\n <button\n type=\"button\"\n onClick={handleTest}\n disabled={loading}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md transition-colors disabled:opacity-50\"\n >\n <PlayIcon className=\"w-4 h-4\" />\n {loading ? 'Running...' : 'Run Test'}\n </button>\n\n {testResult && (\n <div className=\"mt-4\">\n <div className=\"flex items-center gap-2 mb-2\">\n {testResult.status === 'completed' ? (\n <>\n <CheckIcon className=\"w-4 h-4 text-status-success-text\" />\n <span className=\"text-sm font-medium text-status-success-text\">Test Passed</span>\n </>\n ) : (\n <>\n <ErrorIcon className=\"w-4 h-4 text-status-error-text\" />\n <span className=\"text-sm font-medium text-status-error-text\">Test Failed</span>\n </>\n )}\n {testResult.totalExecutionTimeMs && (\n <span className=\"text-xs text-text-secondary\">({testResult.totalExecutionTimeMs}ms)</span>\n )}\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">Output</label>\n <pre className=\"w-full p-3 text-xs font-mono text-text-primary bg-bg-sunken border border-border-default rounded-md overflow-auto max-h-48\">\n {JSON.stringify(testResult.outputData, null, 2) || 'null'}\n </pre>\n </div>\n\n {testResult.error && (\n <div className=\"mt-2\">\n <label className=\"block text-sm font-medium text-status-error-text mb-2\">Error</label>\n <pre className=\"w-full p-3 text-xs font-mono text-status-error-text bg-status-error-bg/10 border border-status-error-border/20 rounded-md overflow-auto\">\n {testResult.error}\n </pre>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Details */}\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-6\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Details</h2>\n\n <dl className=\"space-y-3\">\n <div>\n <dt className=\"text-xs text-text-secondary\">Status</dt>\n <dd className=\"mt-1\">\n <PipelineStatusBadge status={pipeline.status} />\n </dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Stages</dt>\n <dd className=\"text-sm text-text-primary\">{pipeline.stages?.length || 0}</dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Last Executed</dt>\n <dd className=\"text-sm text-text-primary\">\n {pipeline.lastExecutedAt ? new Date(pipeline.lastExecutedAt).toLocaleString() : 'Never'}\n </dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Version</dt>\n <dd className=\"text-sm text-text-primary\">{pipeline.version}</dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Created</dt>\n <dd className=\"text-sm text-text-primary\">{new Date(pipeline.createdAt).toLocaleString()}</dd>\n </div>\n\n <div>\n <dt className=\"text-xs text-text-secondary\">Updated</dt>\n <dd className=\"text-sm text-text-primary\">{new Date(pipeline.updatedAt).toLocaleString()}</dd>\n </div>\n </dl>\n </div>\n </div>\n </div>\n\n {/* Delete Dialog */}\n {pipeline && (\n <PipelineDeleteDialog\n pipeline={pipeline}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n </div>\n );\n});\n\nexport default PipelineViewPage;\n"],"mappings":"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"}
|
|
@@ -289,7 +289,7 @@ var x = ({ className: e }) => /* @__PURE__ */ _("svg", {
|
|
|
289
289
|
type: "button",
|
|
290
290
|
onClick: Q,
|
|
291
291
|
disabled: P,
|
|
292
|
-
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-
|
|
292
|
+
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-status-success-bg hover:bg-status-success-bg/90 rounded-md transition-colors disabled:opacity-50",
|
|
293
293
|
children: [/* @__PURE__ */ _(w, { className: "w-4 h-4" }), P ? "Executing..." : "Execute"]
|
|
294
294
|
}),
|
|
295
295
|
/* @__PURE__ */ v("button", {
|
|
@@ -301,7 +301,7 @@ var x = ({ className: e }) => /* @__PURE__ */ _("svg", {
|
|
|
301
301
|
/* @__PURE__ */ v("button", {
|
|
302
302
|
type: "button",
|
|
303
303
|
onClick: () => M(!0),
|
|
304
|
-
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-
|
|
304
|
+
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-status-error-text bg-status-error-bg/10 hover:bg-status-error-bg/20 rounded-md transition-colors",
|
|
305
305
|
children: [/* @__PURE__ */ _(C, { className: "w-4 h-4" }), "Delete"]
|
|
306
306
|
})
|
|
307
307
|
]
|
|
@@ -342,7 +342,7 @@ var x = ({ className: e }) => /* @__PURE__ */ _("svg", {
|
|
|
342
342
|
]
|
|
343
343
|
}),
|
|
344
344
|
H && /* @__PURE__ */ v("div", {
|
|
345
|
-
className: `mb-6 p-4 rounded-lg border ${H.success ? "bg-
|
|
345
|
+
className: `mb-6 p-4 rounded-lg border ${H.success ? "bg-status-success-bg/10 border-status-success-border/20" : "bg-status-error-bg/10 border-status-error-border/20"}`,
|
|
346
346
|
children: [
|
|
347
347
|
/* @__PURE__ */ v("div", {
|
|
348
348
|
className: "flex items-center justify-between mb-2",
|
|
@@ -355,7 +355,7 @@ var x = ({ className: e }) => /* @__PURE__ */ _("svg", {
|
|
|
355
355
|
})]
|
|
356
356
|
}),
|
|
357
357
|
H.error ? /* @__PURE__ */ _("p", {
|
|
358
|
-
className: "text-sm text-
|
|
358
|
+
className: "text-sm text-status-error-text",
|
|
359
359
|
children: H.error
|
|
360
360
|
}) : /* @__PURE__ */ _("pre", {
|
|
361
361
|
className: "text-xs text-text-secondary font-mono bg-bg-sunken p-2 rounded overflow-auto max-h-[200px]",
|
|
@@ -420,7 +420,7 @@ var x = ({ className: e }) => /* @__PURE__ */ _("svg", {
|
|
|
420
420
|
type: "button",
|
|
421
421
|
onClick: ce,
|
|
422
422
|
className: "flex items-center gap-1 px-3 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors",
|
|
423
|
-
children: I ? /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(E, { className: "w-4 h-4 text-
|
|
423
|
+
children: I ? /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(E, { className: "w-4 h-4 text-status-success-text" }), "Copied!"] }) : /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(T, { className: "w-4 h-4" }), "Copy"] })
|
|
424
424
|
})]
|
|
425
425
|
})]
|
|
426
426
|
}),
|
|
@@ -476,7 +476,7 @@ var x = ({ className: e }) => /* @__PURE__ */ _("svg", {
|
|
|
476
476
|
children: [/* @__PURE__ */ v("div", {
|
|
477
477
|
className: "flex items-center gap-2",
|
|
478
478
|
children: [e.isEnabled ? /* @__PURE__ */ _("span", {
|
|
479
|
-
className: "text-xs text-
|
|
479
|
+
className: "text-xs text-status-success-text",
|
|
480
480
|
children: "Enabled"
|
|
481
481
|
}) : /* @__PURE__ */ _("span", {
|
|
482
482
|
className: "text-xs text-text-secondary",
|