@burdenoff/microfe-bigconsole 2026.1008.10 → 2026.1008.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bigconsole/BigConsoleRoutes.d.ts.map +1 -1
- package/dist/bigconsole/BigConsoleRoutes.js +136 -127
- package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
- package/dist/bigconsole/assistant/assistantProduct.d.ts.map +1 -1
- package/dist/bigconsole/assistant/assistantProduct.js +3 -1
- package/dist/bigconsole/assistant/assistantProduct.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +31 -31
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +44 -44
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +36 -36
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +59 -59
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +15 -15
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +30 -30
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +41 -41
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +34 -34
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +34 -34
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +110 -110
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +21 -21
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +46 -46
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +91 -91
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js +101 -101
- package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/TemplateInstallOptions.js +31 -31
- package/dist/bigconsole/components/dashboard/TemplateLayoutPreview.js +15 -15
- package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -1
- package/dist/bigconsole/components/dashboard/WidgetPalette.js +46 -46
- package/dist/bigconsole/components/datasink/AlertExecutionHistory.js +37 -37
- package/dist/bigconsole/components/datasink/AlertRuleEditor.js +66 -66
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +35 -35
- package/dist/bigconsole/components/datasink/DataSinkCard.js +29 -29
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +18 -18
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +20 -20
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +47 -47
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +91 -91
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +35 -35
- package/dist/bigconsole/components/parser/DataSinkSelector.js +40 -40
- package/dist/bigconsole/components/parser/ImportParserDialog.js +120 -120
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +51 -51
- package/dist/bigconsole/components/pipeline/PipelineScopePicker.js +10 -10
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +27 -27
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +30 -30
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +4 -4
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +93 -93
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.d.ts.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +280 -273
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +4 -4
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js +48 -48
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +46 -46
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +61 -61
- package/dist/bigconsole/components/widgets/form/FormWidget.js +36 -36
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +42 -42
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +25 -25
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +4 -4
- package/dist/bigconsole/components/widgets/list/ListConfig.js +30 -30
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +38 -38
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +9 -9
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +9 -9
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +49 -49
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +39 -39
- package/dist/bigconsole/components/widgets/table/TableConfig.js +73 -73
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +64 -64
- package/dist/bigconsole/components/workflow/WorkflowOpenGuard.js +15 -15
- package/dist/bigconsole/components/workflow/WorkflowSinkLinkForm.js +15 -15
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +9 -9
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +67 -67
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
- package/dist/bigconsole/hooks/useDashboardLayoutBaseline.d.ts +15 -0
- package/dist/bigconsole/hooks/useDashboardLayoutBaseline.d.ts.map +1 -0
- package/dist/bigconsole/hooks/useDashboardLayoutBaseline.js +34 -0
- package/dist/bigconsole/hooks/useDashboardLayoutBaseline.js.map +1 -0
- package/dist/bigconsole/hooks/useDrilldown.js +3 -3
- package/dist/bigconsole/hooks/useGlobalFilters.js +3 -3
- package/dist/bigconsole/pages/AdminPage.js +130 -130
- package/dist/bigconsole/pages/DashboardBuilderPage.d.ts.map +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +72 -60
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +1 -1
- package/dist/bigconsole/pages/DataSinkAlertsPage.d.ts.map +1 -1
- package/dist/bigconsole/pages/DataSinkAlertsPage.js +30 -23
- package/dist/bigconsole/pages/DataSinkAlertsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.d.ts.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +272 -263
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +1 -1
- package/dist/bigconsole/pages/DataSourcesPage.js +5 -5
- package/dist/bigconsole/pages/InsightsPage.js +181 -181
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/OverviewPage.js +47 -47
- package/dist/bigconsole/pages/OverviewPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.d.ts.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +227 -211
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +97 -97
- package/dist/bigconsole/pages/PipelineBuilderPage.d.ts.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +256 -214
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +146 -146
- package/dist/bigconsole/pages/PipelinesPage.js +88 -88
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/SettingsPage.d.ts.map +1 -1
- package/dist/bigconsole/pages/SettingsPage.js +179 -173
- package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
- package/dist/bigconsole/pages/WidgetDemoPage.js +42 -42
- package/dist/bigconsole/pages/WorkflowViewPage.js +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +141 -141
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/providers/BigConsoleQuotaProvider.js +12 -12
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +34 -34
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +79 -79
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js +46 -46
- package/dist/bigconsole/store/widgetStore.d.ts +12 -0
- package/dist/bigconsole/store/widgetStore.d.ts.map +1 -1
- package/dist/bigconsole/store/widgetStore.js +3 -1
- package/dist/bigconsole/store/widgetStore.js.map +1 -1
- package/dist/bigconsole/utils/formDirty.d.ts +83 -0
- package/dist/bigconsole/utils/formDirty.d.ts.map +1 -0
- package/dist/bigconsole/utils/formDirty.js +23 -0
- package/dist/bigconsole/utils/formDirty.js.map +1 -0
- package/dist/bigconsole/utils/layoutBaseline.d.ts +131 -0
- package/dist/bigconsole/utils/layoutBaseline.d.ts.map +1 -0
- package/dist/bigconsole/utils/layoutBaseline.js +98 -0
- package/dist/bigconsole/utils/layoutBaseline.js.map +1 -0
- package/dist/translations/en.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -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 * Section ladder (BOFF-5635):\n * bare — header strip with the commit actions\n * primary — \"Stages\": the transform configuration this route exists for\n * standard — \"Basic information\" (identity + runtime status)\n * muted — per-stage editors nested inside the hero, plus the sidebar\n * preview and tips (supporting context, never the point)\n * tone — save failure\n *\n * The stage field grid is also where the module's worst responsive defect lived:\n * a bare `grid-cols-2` that never collapsed, crushing three controls into ~150px\n * columns at 390px. It now starts single-column and splits at `sm`.\n */\n\nimport { memo, useState, useCallback, useEffect, useMemo, useId } from 'react';\nimport { useParams, useSearchParams } from 'react-router';\nimport { PipelineScopePicker } from '../components/pipeline/PipelineScopePicker';\nimport { Button, IllustratedEmptyState, PagePurpose, Spinner } from '@burdenoff/fe-libs/ui';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { AccessDenied } from '@burdenoff/fe-libs/shared/components';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\nimport { useAppNavigate } from '../contexts';\nimport { usePipelineOperations } from '../hooks/usePipelineOperations';\nimport { useParserOperations } from '../hooks/useParserOperations';\nimport { PipelineStatusBadge } from '../components/pipeline/PipelineStatusBadge';\nimport { Section, SectionStack, SECTION_FOCUS_RING } from '../components/common';\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// SHARED CLASS RECIPES\n// ============================================================================\n\n/** Keeps header/panel actions at the 40px touch minimum on mobile. */\nconst TOUCH_TARGET = 'min-h-[var(--size-controlHeight-md)]';\n\n/**\n * One field vocabulary for the whole builder. Before this there were three\n * competing label scales (form `text-sm/primary`, stage grid\n * `text-xs/secondary`, preview `text-xs/secondary` non-bold) inside one screen.\n */\nconst FIELD_LABEL = 'mb-1 block text-sm font-medium text-text-primary';\nconst FIELD_HINT = 'mt-1 text-xs text-text-secondary';\nconst FIELD_GROUP_LEGEND = 'mb-1 text-xs font-semibold uppercase tracking-wide text-text-muted';\n\n/** Inputs sit on `bg-canvas` so a field never matches the card it lives on. */\nconst FIELD_CONTROL = `w-full min-w-0 rounded-input border border-[var(--color-border-subtle)] bg-bg-canvas px-3 py-2 text-sm text-text-primary ${SECTION_FOCUS_RING}`;\nconst FIELD_CONTROL_MONO = `${FIELD_CONTROL} font-mono`;\n\n/**\n * Icon action button: 40px touch target (was a ~24px `p-1` hit area). The hover\n * fill is deliberately NOT part of the base recipe — appending a second\n * `hover:bg-*` to a string that already carries one leaves the winner up to\n * stylesheet order, not to the caller, so the destructive variant could lose its\n * red hover. Each caller composes exactly one hover fill.\n */\nconst ICON_ACTION_BASE = `inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-button text-text-secondary motion-safe:transition-colors disabled:opacity-30 ${SECTION_FOCUS_RING}`;\nconst ICON_ACTION = `${ICON_ACTION_BASE} hover:bg-bg-surface hover:text-text-primary`;\nconst ICON_ACTION_DANGER = `${ICON_ACTION_BASE} hover:bg-[var(--color-status-error-bgSubtle)] hover:text-status-error-text`;\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 { t } = useI18n();\n const { pipelineId } = useParams<{ pipelineId: string }>();\n const navigate = useAppNavigate();\n const isEditMode = !!pipelineId && pipelineId !== 'new';\n const [searchParams, setSearchParams] = useSearchParams();\n const [loadedConsoleId, setLoadedConsoleId] = useState<string | null>(null);\n const consoleId = isEditMode ? (loadedConsoleId ?? 'default') : searchParams.get('consoleId') || 'default';\n const fieldId = useId();\n\n // Permissions\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_READ);\n const canCreate = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_CREATE);\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_UPDATE);\n // Save gate depends on mode: creating a new pipeline vs. editing an existing one.\n const canSave = isEditMode ? canUpdate : canCreate;\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 skipFetch: isEditMode && !loadedConsoleId,\n });\n\n // Load existing pipeline in edit mode\n useEffect(() => {\n if (isEditMode && pipelineId) {\n fetchPipeline(pipelineId).then((pipeline) => {\n if (pipeline) {\n setLoadedConsoleId(pipeline.consoleId);\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 // Translated option labels (values remain the untranslated logic keys).\n const statusOptionLabels: Record<PipelineStatus, string> = {\n draft: t('bigconsole.pipelines.builder.status.draft', 'Draft'),\n active: t('bigconsole.pipelines.builder.status.active', 'Active'),\n inactive: t('bigconsole.pipelines.builder.status.inactive', 'Inactive'),\n error: t('bigconsole.pipelines.builder.status.error', 'Error'),\n };\n\n const errorHandlingOptionLabels: Record<StageErrorHandling, string> = {\n fail: t('bigconsole.pipelines.builder.onError.fail', 'Fail'),\n skip: t('bigconsole.pipelines.builder.onError.skip', 'Skip'),\n fallback: t('bigconsole.pipelines.builder.onError.fallback', 'Fallback'),\n };\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 /** Why the save button is disabled — the button used to just fade out. */\n const blockingReason = useMemo(() => {\n if (!name.trim()) return 'Give the pipeline a name to save it.';\n if (stages.length === 0) return 'Add at least one stage to save this pipeline.';\n if (!stages.every((s) => s.parserId && s.inputKey && s.outputKey)) {\n return 'Every stage needs a parser, an input key and an output key.';\n }\n return null;\n }, [name, stages]);\n\n // Handlers\n const handleBack = useCallback(() => {\n navigate(`/pipelines?consoleId=${encodeURIComponent(consoleId)}`);\n }, [navigate, consoleId]);\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 || !canSave) 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(\n err instanceof Error\n ? err.message\n : t('bigconsole.pipelines.builder.errors.saveFailed', 'Failed to save pipeline')\n );\n } finally {\n setIsSaving(false);\n }\n }, [\n isValid,\n consoleId,\n canSave,\n isEditMode,\n pipelineId,\n name,\n description,\n status,\n stages,\n version,\n createPipeline,\n updatePipeline,\n navigate,\n t,\n ]);\n\n // Loading state\n if (pipelineLoading && isEditMode) {\n return (\n <div className=\"p-card-padding\">\n <div className=\"flex flex-col items-center justify-center py-16\" role=\"status\">\n <Spinner style={{ height: 'var(--size-icon-xl)', width: 'var(--size-icon-xl)' }} />\n <p className=\"mt-form-gap text-sm text-text-secondary\">\n {t('bigconsole.pipelines.builder.loading', 'Loading Pipeline...')}\n </p>\n </div>\n </div>\n );\n }\n\n // Read gate — editing an existing pipeline requires read access to load it.\n // Create mode ('new') is gated on the Save action (canCreate) instead.\n if (isEditMode && !permissionsLoading && !canRead) {\n return (\n <AccessDenied\n title={t('bigconsole.pipelines.builder.accessDenied.title', 'Access Denied')}\n description={t(\n 'bigconsole.pipelines.builder.accessDenied.description',\n \"You don't have permission to view this pipeline.\"\n )}\n />\n );\n }\n\n // Error state\n if (pipelineError) {\n return (\n <div className=\"p-card-padding\">\n <Section\n tone=\"danger\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.errors.loadFailed', 'Failed to load Pipeline')}\n description={pipelineError.message}\n icon={<ErrorIcon className=\"h-icon-sm w-icon-sm\" />}\n actions={\n <Button onClick={handleBack} className={TOUCH_TARGET}>\n {t('bigconsole.pipelines.builder.actions.backToPipelines', 'Back to Pipelines')}\n </Button>\n }\n data-testid=\"pipeline-builder-error\"\n >\n <p className=\"text-sm text-text-secondary\">\n The pipeline could not be read from the console service. Nothing was changed.\n </p>\n </Section>\n </div>\n );\n }\n\n return (\n <div className=\"p-card-padding\">\n <SectionStack>\n {/* Header strip — structure only, no surface. */}\n <header className=\"flex flex-col gap-form-gap sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"flex min-w-0 flex-col gap-control-gap\">\n <Button variant=\"ghost\" size=\"sm\" onClick={handleBack} className=\"w-fit\">\n <BackIcon className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.builder.actions.backToPipelines', 'Back to Pipelines')}\n </Button>\n <div className=\"min-w-0\">\n <h1 className=\"text-2xl font-bold leading-tight text-text-primary\">\n {isEditMode\n ? t('bigconsole.pipelines.builder.header.editTitle', 'Edit Pipeline')\n : t('bigconsole.pipelines.builder.header.createTitle', 'Create Pipeline')}\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {isEditMode\n ? t('bigconsole.pipelines.builder.header.editSubtitle', 'Update pipeline settings and stages')\n : t(\n 'bigconsole.pipelines.builder.header.createSubtitle',\n 'Create a new data transformation pipeline'\n )}\n </p>\n </div>\n </div>\n\n <div className=\"flex flex-col gap-1 sm:items-end\">\n <div className=\"flex flex-wrap items-center gap-control-gap\">\n <Button variant=\"secondary\" onClick={handleBack} className={TOUCH_TARGET}>\n {t('bigconsole.pipelines.builder.actions.cancel', 'Cancel')}\n </Button>\n <Button\n onClick={handleSave}\n disabled={!isValid || isSaving || !canSave}\n title={\n !canSave\n ? isEditMode\n ? t(\n 'bigconsole.pipelines.builder.actions.noUpdatePermission',\n \"You don't have permission to update pipelines.\"\n )\n : t(\n 'bigconsole.pipelines.builder.actions.noCreatePermission',\n \"You don't have permission to create pipelines.\"\n )\n : undefined\n }\n className={TOUCH_TARGET}\n >\n {isSaving\n ? t('bigconsole.pipelines.builder.actions.saving', 'Saving...')\n : isEditMode\n ? t('bigconsole.pipelines.builder.actions.saveChanges', 'Save Changes')\n : t('bigconsole.pipelines.builder.actions.createPipeline', 'Create Pipeline')}\n </Button>\n </div>\n {blockingReason && (\n <p className=\"text-xs text-text-secondary sm:text-right\" data-testid=\"pipeline-save-blocked-reason\">\n {blockingReason}\n </p>\n )}\n </div>\n </header>\n\n <PagePurpose className=\"max-w-[75ch]\">\n {t(\n 'bigconsole.pipelines.builder.header.purpose',\n 'Build a pipeline by chaining parser stages — each stage reads an input key, runs a parser, and writes a structured output key that the next stage (or a data sink) can use. Name it, add your stages in order, then test it before saving so your data flows end to end.'\n )}\n </PagePurpose>\n\n {/* Save failure */}\n {saveError && (\n <Section\n tone=\"danger\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.errors.saveFailed', 'Failed to save pipeline')}\n description={saveError}\n icon={<ErrorIcon className=\"h-icon-sm w-icon-sm\" />}\n data-testid=\"pipeline-save-error\"\n />\n )}\n\n <div className=\"grid grid-cols-1 gap-section-gap lg:grid-cols-3\">\n {/* Main form */}\n <div className=\"min-w-0 lg:col-span-2\">\n <SectionStack>\n <Section\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.basicInfo.heading', 'Basic Information')}\n description=\"How this pipeline is identified, and whether it runs.\"\n data-testid=\"pipeline-basic-info\"\n >\n <div className=\"flex flex-col gap-form-gap\">\n <PipelineScopePicker\n value={consoleId}\n disabled={isEditMode}\n onChange={(next) => {\n const params = new URLSearchParams(searchParams);\n params.set('consoleId', next);\n setSearchParams(params);\n setStages([]);\n }}\n />\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-name`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.basicInfo.nameLabel', 'Name')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id={`${fieldId}-name`}\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={t('bigconsole.pipelines.builder.basicInfo.namePlaceholder', 'My Pipeline')}\n className={FIELD_CONTROL}\n />\n </div>\n\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-description`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.basicInfo.descriptionLabel', 'Description')}\n </label>\n <textarea\n id={`${fieldId}-description`}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={t(\n 'bigconsole.pipelines.builder.basicInfo.descriptionPlaceholder',\n 'What does this pipeline do?'\n )}\n rows={3}\n className={`${FIELD_CONTROL} resize-y`}\n />\n </div>\n\n <div className=\"min-w-0 border-t border-[var(--color-border-subtle)] pt-form-gap\">\n <label htmlFor={`${fieldId}-status`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.basicInfo.statusLabel', 'Status')}\n </label>\n <select\n id={`${fieldId}-status`}\n value={status}\n onChange={(e) => setStatus(e.target.value as PipelineStatus)}\n className={FIELD_CONTROL}\n >\n {STATUS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {statusOptionLabels[opt.value]}\n </option>\n ))}\n </select>\n <p className={FIELD_HINT}>Only active pipelines process incoming data.</p>\n </div>\n </div>\n </Section>\n\n {/* Stages — the one primary block on this route. */}\n <Section\n emphasis=\"primary\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.stages.heading', 'Stages ({{count}})', {\n count: stages.length,\n })}\n description=\"Each stage reads an input key, runs a parser, and writes an output key for the next stage.\"\n actions={\n <Button size=\"sm\" onClick={handleAddStage} className={TOUCH_TARGET}>\n <PlusIcon className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.builder.stages.addStage', 'Add Stage')}\n </Button>\n }\n data-testid=\"pipeline-stages-editor\"\n >\n {stages.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title={t('bigconsole.pipelines.builder.stages.emptyTitle', 'No stages yet')}\n description={t(\n 'bigconsole.pipelines.builder.stages.emptyDescription',\n 'Add a stage to start building your pipeline.'\n )}\n action={\n <Button onClick={handleAddStage} className={TOUCH_TARGET}>\n <PlusIcon className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.builder.stages.addFirstStage', 'Add First Stage')}\n </Button>\n }\n />\n ) : (\n <ol className=\"flex flex-col gap-form-gap\">\n {stages.map((stage, index) => (\n // Stages are positional and a new stage has no id until it is saved.\n <li key={index} className=\"min-w-0\">\n <Section\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={3}\n title={\n <span className=\"flex min-w-0 items-center gap-icon-gap\">\n <span\n aria-hidden=\"true\"\n className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-pill bg-bg-surface text-xs font-semibold text-text-secondary\"\n >\n {index + 1}\n </span>\n <span className=\"min-w-0 truncate\">\n {stage.parserName ||\n t('bigconsole.pipelines.builder.stages.defaultStageName', 'Stage {{number}}', {\n number: index + 1,\n })}\n </span>\n </span>\n }\n actions={\n <>\n <button\n type=\"button\"\n onClick={() => handleMoveStage(index, 'up')}\n disabled={index === 0}\n className={ICON_ACTION}\n aria-label={`Move stage ${index + 1} up`}\n >\n <ArrowUpIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleMoveStage(index, 'down')}\n disabled={index === stages.length - 1}\n className={ICON_ACTION}\n aria-label={`Move stage ${index + 1} down`}\n >\n <ArrowDownIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleRemoveStage(index)}\n className={ICON_ACTION_DANGER}\n aria-label={`Remove stage ${index + 1}`}\n >\n <TrashIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n </>\n }\n data-testid=\"pipeline-stage-editor\"\n >\n <div className=\"flex flex-col gap-form-gap\">\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-parser-${index}`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.stages.parserLabel', 'Parser')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <select\n id={`${fieldId}-parser-${index}`}\n value={stage.parserId}\n onChange={(e) => handleParserSelect(index, e.target.value)}\n className={FIELD_CONTROL}\n >\n <option value=\"\">\n {t('bigconsole.pipelines.builder.stages.parserPlaceholder', 'Select a parser...')}\n </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 {/* Data contract */}\n <fieldset className=\"min-w-0\">\n <legend className={FIELD_GROUP_LEGEND}>Data contract</legend>\n <div className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-input-${index}`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.stages.inputKeyLabel', 'Input Key')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id={`${fieldId}-input-${index}`}\n type=\"text\"\n value={stage.inputKey}\n onChange={(e) => handleUpdateStage(index, { inputKey: e.target.value })}\n placeholder={t('bigconsole.pipelines.builder.stages.inputKeyPlaceholder', 'data')}\n className={FIELD_CONTROL_MONO}\n />\n </div>\n\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-output-${index}`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.stages.outputKeyLabel', 'Output Key')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id={`${fieldId}-output-${index}`}\n type=\"text\"\n value={stage.outputKey}\n onChange={(e) => handleUpdateStage(index, { outputKey: e.target.value })}\n placeholder={t(\n 'bigconsole.pipelines.builder.stages.outputKeyPlaceholder',\n 'result'\n )}\n className={FIELD_CONTROL_MONO}\n />\n </div>\n </div>\n </fieldset>\n\n {/* Failure policy */}\n <fieldset className=\"min-w-0\">\n <legend className={FIELD_GROUP_LEGEND}>Failure policy</legend>\n <div className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-onerror-${index}`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.stages.onErrorLabel', 'On Error')}\n </label>\n <select\n id={`${fieldId}-onerror-${index}`}\n value={stage.onError}\n onChange={(e) =>\n handleUpdateStage(index, {\n onError: e.target.value as StageErrorHandling,\n })\n }\n className={FIELD_CONTROL}\n >\n {ERROR_HANDLING_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {errorHandlingOptionLabels[opt.value]}\n </option>\n ))}\n </select>\n <p className={FIELD_HINT}>\n {ERROR_HANDLING_OPTIONS.find((opt) => opt.value === stage.onError)?.description}\n </p>\n </div>\n\n <div className=\"flex min-w-0 items-start\">\n <label\n htmlFor={`${fieldId}-enabled-${index}`}\n className={`flex cursor-pointer items-center gap-2 ${TOUCH_TARGET}`}\n >\n <input\n id={`${fieldId}-enabled-${index}`}\n type=\"checkbox\"\n checked={stage.enabled}\n onChange={(e) => handleUpdateStage(index, { enabled: e.target.checked })}\n className={`h-4 w-4 rounded border-[var(--color-border-subtle)] text-action-primary-bg ${SECTION_FOCUS_RING}`}\n />\n <span className=\"text-sm text-text-primary\">\n {t('bigconsole.pipelines.builder.stages.enabledLabel', 'Enabled')}\n </span>\n </label>\n </div>\n\n {stage.onError === 'fallback' && (\n <div className=\"min-w-0 sm:col-span-2\">\n <label htmlFor={`${fieldId}-fallback-${index}`} className={FIELD_LABEL}>\n {t(\n 'bigconsole.pipelines.builder.stages.fallbackValueLabel',\n 'Fallback Value (JSON)'\n )}\n </label>\n <input\n id={`${fieldId}-fallback-${index}`}\n type=\"text\"\n value={stage.fallbackValue}\n onChange={(e) => handleUpdateStage(index, { fallbackValue: e.target.value })}\n placeholder='{\"default\": true}'\n className={FIELD_CONTROL_MONO}\n />\n </div>\n )}\n </div>\n </fieldset>\n </div>\n </Section>\n </li>\n ))}\n </ol>\n )}\n </Section>\n </SectionStack>\n </div>\n\n {/* Sidebar — supporting context only. */}\n <div className=\"min-w-0\">\n <SectionStack>\n <Section\n emphasis=\"muted\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.preview.heading', 'Preview')}\n description=\"What will be saved.\"\n data-testid=\"pipeline-preview\"\n >\n <dl className=\"flex flex-col gap-3 text-sm\">\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-muted\">\n {t('bigconsole.pipelines.builder.preview.nameLabel', 'Name')}\n </dt>\n <dd className=\"break-words text-text-primary\">\n {name || t('bigconsole.pipelines.builder.preview.untitled', 'Untitled')}\n </dd>\n </div>\n\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-muted\">\n {t('bigconsole.pipelines.builder.preview.statusLabel', 'Status')}\n </dt>\n <dd className=\"mt-1\">\n <PipelineStatusBadge status={status} size=\"sm\" />\n </dd>\n </div>\n\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-muted\">\n {t('bigconsole.pipelines.builder.preview.stagesLabel', 'Stages')}\n </dt>\n <dd className=\"text-text-primary\">{stages.length}</dd>\n </div>\n\n {stages.length > 0 && (\n <div className=\"min-w-0 border-t border-[var(--color-border-subtle)] pt-3\">\n <dt className=\"text-xs text-text-muted\">\n {t('bigconsole.pipelines.builder.preview.dataFlowLabel', 'Data Flow')}\n </dt>\n <dd className=\"mt-1 flex flex-wrap items-center gap-1 text-xs\">\n {stages.map((s, i) => (\n <span key={i} className=\"flex items-center gap-1\">\n <code className=\"rounded-button bg-bg-surface px-1.5 py-0.5 font-mono break-all text-text-primary\">\n {s.inputKey}\n </code>\n <span aria-hidden=\"true\" className=\"text-text-muted\">\n →\n </span>\n </span>\n ))}\n <code className=\"rounded-button bg-bg-surface px-1.5 py-0.5 font-mono break-all text-text-primary\">\n {stages[stages.length - 1].outputKey}\n </code>\n </dd>\n </div>\n )}\n </dl>\n </Section>\n\n <Section\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.tips.heading', 'Tips')}\n data-testid=\"pipeline-builder-tips\"\n >\n <ul className=\"list-disc space-y-1 pl-4 text-sm text-text-secondary\">\n <li>\n {t(\n 'bigconsole.pipelines.builder.tips.item1',\n 'Each stage processes the output of the previous stage'\n )}\n </li>\n <li>\n {t('bigconsole.pipelines.builder.tips.item2', 'Use consistent input/output keys to chain data')}\n </li>\n <li>{t('bigconsole.pipelines.builder.tips.item3', 'Set error handling per stage for robustness')}</li>\n <li>\n {t('bigconsole.pipelines.builder.tips.item4', 'Disable stages to skip them during execution')}\n </li>\n </ul>\n </Section>\n </SectionStack>\n </div>\n </div>\n </SectionStack>\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 * Section ladder (BOFF-5635):\n * bare — header strip with the commit actions\n * primary — \"Stages\": the transform configuration this route exists for\n * standard — \"Basic information\" (identity + runtime status)\n * muted — per-stage editors nested inside the hero, plus the sidebar\n * preview and tips (supporting context, never the point)\n * tone — save failure\n *\n * The stage field grid is also where the module's worst responsive defect lived:\n * a bare `grid-cols-2` that never collapsed, crushing three controls into ~150px\n * columns at 390px. It now starts single-column and splits at `sm`.\n */\n\nimport { memo, useState, useCallback, useEffect, useMemo, useId } from 'react';\nimport { useParams, useSearchParams } from 'react-router';\nimport { PipelineScopePicker } from '../components/pipeline/PipelineScopePicker';\nimport { Button, IllustratedEmptyState, PagePurpose, Spinner } from '@burdenoff/fe-libs/ui';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useUnsavedChanges } from '@burdenoff/fe-libs/shared/hooks';\nimport { AccessDenied } from '@burdenoff/fe-libs/shared/components';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\nimport { useAppNavigate } from '../contexts';\nimport { isDirty } from '../utils/formDirty';\nimport { usePipelineOperations } from '../hooks/usePipelineOperations';\nimport { useParserOperations } from '../hooks/useParserOperations';\nimport { PipelineStatusBadge } from '../components/pipeline/PipelineStatusBadge';\nimport { Section, SectionStack, SECTION_FOCUS_RING } from '../components/common';\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// SHARED CLASS RECIPES\n// ============================================================================\n\n/** Keeps header/panel actions at the 40px touch minimum on mobile. */\nconst TOUCH_TARGET = 'min-h-[var(--size-controlHeight-md)]';\n\n/**\n * One field vocabulary for the whole builder. Before this there were three\n * competing label scales (form `text-sm/primary`, stage grid\n * `text-xs/secondary`, preview `text-xs/secondary` non-bold) inside one screen.\n */\nconst FIELD_LABEL = 'mb-1 block text-sm font-medium text-text-primary';\nconst FIELD_HINT = 'mt-1 text-xs text-text-secondary';\nconst FIELD_GROUP_LEGEND = 'mb-1 text-xs font-semibold uppercase tracking-wide text-text-muted';\n\n/** Inputs sit on `bg-canvas` so a field never matches the card it lives on. */\nconst FIELD_CONTROL = `w-full min-w-0 rounded-input border border-[var(--color-border-subtle)] bg-bg-canvas px-3 py-2 text-sm text-text-primary ${SECTION_FOCUS_RING}`;\nconst FIELD_CONTROL_MONO = `${FIELD_CONTROL} font-mono`;\n\n/**\n * Icon action button: 40px touch target (was a ~24px `p-1` hit area). The hover\n * fill is deliberately NOT part of the base recipe — appending a second\n * `hover:bg-*` to a string that already carries one leaves the winner up to\n * stylesheet order, not to the caller, so the destructive variant could lose its\n * red hover. Each caller composes exactly one hover fill.\n */\nconst ICON_ACTION_BASE = `inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-button text-text-secondary motion-safe:transition-colors disabled:opacity-30 ${SECTION_FOCUS_RING}`;\nconst ICON_ACTION = `${ICON_ACTION_BASE} hover:bg-bg-surface hover:text-text-primary`;\nconst ICON_ACTION_DANGER = `${ICON_ACTION_BASE} hover:bg-[var(--color-status-error-bgSubtle)] hover:text-status-error-text`;\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 { t } = useI18n();\n const { pipelineId } = useParams<{ pipelineId: string }>();\n const navigate = useAppNavigate();\n const isEditMode = !!pipelineId && pipelineId !== 'new';\n const [searchParams, setSearchParams] = useSearchParams();\n const [loadedConsoleId, setLoadedConsoleId] = useState<string | null>(null);\n const consoleId = isEditMode ? (loadedConsoleId ?? 'default') : searchParams.get('consoleId') || 'default';\n const fieldId = useId();\n\n // Permissions\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_READ);\n const canCreate = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_CREATE);\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.PIPELINE_UPDATE);\n // Save gate depends on mode: creating a new pipeline vs. editing an existing one.\n const canSave = isEditMode ? canUpdate : canCreate;\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 // The five form states as seeded (edit: by the fetch below, so null = clean until it lands) or as saved.\n const [baseline, setBaseline] = useState<readonly [string, string, PipelineStatus, StageForm[], number] | null>(\n isEditMode ? null : ['', '', 'draft', [], 1]\n );\n useUnsavedChanges({\n id: 'pipeline-editor',\n label: t('bigconsole.assistant.unsaved.pipelineEditor', 'the pipeline editor'),\n dirty: isDirty([name, description, status, stages, version], baseline),\n });\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 skipFetch: isEditMode && !loadedConsoleId,\n });\n\n // Load existing pipeline in edit mode\n useEffect(() => {\n if (isEditMode && pipelineId) {\n fetchPipeline(pipelineId).then((pipeline) => {\n if (pipeline) {\n setLoadedConsoleId(pipeline.consoleId);\n setName(pipeline.name);\n setDescription(pipeline.description || '');\n setStatus(pipeline.status);\n setVersion(pipeline.version);\n const seededStages: StageForm[] = (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 setStages(seededStages);\n setBaseline([pipeline.name, pipeline.description || '', pipeline.status, seededStages, pipeline.version]);\n }\n });\n }\n }, [isEditMode, pipelineId, fetchPipeline]);\n\n // Translated option labels (values remain the untranslated logic keys).\n const statusOptionLabels: Record<PipelineStatus, string> = {\n draft: t('bigconsole.pipelines.builder.status.draft', 'Draft'),\n active: t('bigconsole.pipelines.builder.status.active', 'Active'),\n inactive: t('bigconsole.pipelines.builder.status.inactive', 'Inactive'),\n error: t('bigconsole.pipelines.builder.status.error', 'Error'),\n };\n\n const errorHandlingOptionLabels: Record<StageErrorHandling, string> = {\n fail: t('bigconsole.pipelines.builder.onError.fail', 'Fail'),\n skip: t('bigconsole.pipelines.builder.onError.skip', 'Skip'),\n fallback: t('bigconsole.pipelines.builder.onError.fallback', 'Fallback'),\n };\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 /** Why the save button is disabled — the button used to just fade out. */\n const blockingReason = useMemo(() => {\n if (!name.trim()) return 'Give the pipeline a name to save it.';\n if (stages.length === 0) return 'Add at least one stage to save this pipeline.';\n if (!stages.every((s) => s.parserId && s.inputKey && s.outputKey)) {\n return 'Every stage needs a parser, an input key and an output key.';\n }\n return null;\n }, [name, stages]);\n\n // Handlers\n const handleBack = useCallback(() => {\n navigate(`/pipelines?consoleId=${encodeURIComponent(consoleId)}`);\n }, [navigate, consoleId]);\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 || !canSave) 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 setBaseline([name, description, status, stages, version]);\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 setBaseline([name, description, status, stages, version]);\n navigate(`/pipelines/${result.id}`);\n }\n }\n } catch (err) {\n setSaveError(\n err instanceof Error\n ? err.message\n : t('bigconsole.pipelines.builder.errors.saveFailed', 'Failed to save pipeline')\n );\n } finally {\n setIsSaving(false);\n }\n }, [\n isValid,\n consoleId,\n canSave,\n isEditMode,\n pipelineId,\n name,\n description,\n status,\n stages,\n version,\n createPipeline,\n updatePipeline,\n navigate,\n t,\n ]);\n\n // Loading state\n if (pipelineLoading && isEditMode) {\n return (\n <div className=\"p-card-padding\">\n <div className=\"flex flex-col items-center justify-center py-16\" role=\"status\">\n <Spinner style={{ height: 'var(--size-icon-xl)', width: 'var(--size-icon-xl)' }} />\n <p className=\"mt-form-gap text-sm text-text-secondary\">\n {t('bigconsole.pipelines.builder.loading', 'Loading Pipeline...')}\n </p>\n </div>\n </div>\n );\n }\n\n // Read gate — editing an existing pipeline requires read access to load it.\n // Create mode ('new') is gated on the Save action (canCreate) instead.\n if (isEditMode && !permissionsLoading && !canRead) {\n return (\n <AccessDenied\n title={t('bigconsole.pipelines.builder.accessDenied.title', 'Access Denied')}\n description={t(\n 'bigconsole.pipelines.builder.accessDenied.description',\n \"You don't have permission to view this pipeline.\"\n )}\n />\n );\n }\n\n // Error state\n if (pipelineError) {\n return (\n <div className=\"p-card-padding\">\n <Section\n tone=\"danger\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.errors.loadFailed', 'Failed to load Pipeline')}\n description={pipelineError.message}\n icon={<ErrorIcon className=\"h-icon-sm w-icon-sm\" />}\n actions={\n <Button onClick={handleBack} className={TOUCH_TARGET}>\n {t('bigconsole.pipelines.builder.actions.backToPipelines', 'Back to Pipelines')}\n </Button>\n }\n data-testid=\"pipeline-builder-error\"\n >\n <p className=\"text-sm text-text-secondary\">\n The pipeline could not be read from the console service. Nothing was changed.\n </p>\n </Section>\n </div>\n );\n }\n\n return (\n <div className=\"p-card-padding\">\n <SectionStack>\n {/* Header strip — structure only, no surface. */}\n <header className=\"flex flex-col gap-form-gap sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"flex min-w-0 flex-col gap-control-gap\">\n <Button variant=\"ghost\" size=\"sm\" onClick={handleBack} className=\"w-fit\">\n <BackIcon className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.builder.actions.backToPipelines', 'Back to Pipelines')}\n </Button>\n <div className=\"min-w-0\">\n <h1 className=\"text-2xl font-bold leading-tight text-text-primary\">\n {isEditMode\n ? t('bigconsole.pipelines.builder.header.editTitle', 'Edit Pipeline')\n : t('bigconsole.pipelines.builder.header.createTitle', 'Create Pipeline')}\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {isEditMode\n ? t('bigconsole.pipelines.builder.header.editSubtitle', 'Update pipeline settings and stages')\n : t(\n 'bigconsole.pipelines.builder.header.createSubtitle',\n 'Create a new data transformation pipeline'\n )}\n </p>\n </div>\n </div>\n\n <div className=\"flex flex-col gap-1 sm:items-end\">\n <div className=\"flex flex-wrap items-center gap-control-gap\">\n <Button variant=\"secondary\" onClick={handleBack} className={TOUCH_TARGET}>\n {t('bigconsole.pipelines.builder.actions.cancel', 'Cancel')}\n </Button>\n <Button\n onClick={handleSave}\n disabled={!isValid || isSaving || !canSave}\n title={\n !canSave\n ? isEditMode\n ? t(\n 'bigconsole.pipelines.builder.actions.noUpdatePermission',\n \"You don't have permission to update pipelines.\"\n )\n : t(\n 'bigconsole.pipelines.builder.actions.noCreatePermission',\n \"You don't have permission to create pipelines.\"\n )\n : undefined\n }\n className={TOUCH_TARGET}\n >\n {isSaving\n ? t('bigconsole.pipelines.builder.actions.saving', 'Saving...')\n : isEditMode\n ? t('bigconsole.pipelines.builder.actions.saveChanges', 'Save Changes')\n : t('bigconsole.pipelines.builder.actions.createPipeline', 'Create Pipeline')}\n </Button>\n </div>\n {blockingReason && (\n <p className=\"text-xs text-text-secondary sm:text-right\" data-testid=\"pipeline-save-blocked-reason\">\n {blockingReason}\n </p>\n )}\n </div>\n </header>\n\n <PagePurpose className=\"max-w-[75ch]\">\n {t(\n 'bigconsole.pipelines.builder.header.purpose',\n 'Build a pipeline by chaining parser stages — each stage reads an input key, runs a parser, and writes a structured output key that the next stage (or a data sink) can use. Name it, add your stages in order, then test it before saving so your data flows end to end.'\n )}\n </PagePurpose>\n\n {/* Save failure */}\n {saveError && (\n <Section\n tone=\"danger\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.errors.saveFailed', 'Failed to save pipeline')}\n description={saveError}\n icon={<ErrorIcon className=\"h-icon-sm w-icon-sm\" />}\n data-testid=\"pipeline-save-error\"\n />\n )}\n\n <div className=\"grid grid-cols-1 gap-section-gap lg:grid-cols-3\">\n {/* Main form */}\n <div className=\"min-w-0 lg:col-span-2\">\n <SectionStack>\n <Section\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.basicInfo.heading', 'Basic Information')}\n description=\"How this pipeline is identified, and whether it runs.\"\n data-testid=\"pipeline-basic-info\"\n >\n <div className=\"flex flex-col gap-form-gap\">\n <PipelineScopePicker\n value={consoleId}\n disabled={isEditMode}\n onChange={(next) => {\n const params = new URLSearchParams(searchParams);\n params.set('consoleId', next);\n setSearchParams(params);\n setStages([]);\n }}\n />\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-name`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.basicInfo.nameLabel', 'Name')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id={`${fieldId}-name`}\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={t('bigconsole.pipelines.builder.basicInfo.namePlaceholder', 'My Pipeline')}\n className={FIELD_CONTROL}\n />\n </div>\n\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-description`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.basicInfo.descriptionLabel', 'Description')}\n </label>\n <textarea\n id={`${fieldId}-description`}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={t(\n 'bigconsole.pipelines.builder.basicInfo.descriptionPlaceholder',\n 'What does this pipeline do?'\n )}\n rows={3}\n className={`${FIELD_CONTROL} resize-y`}\n />\n </div>\n\n <div className=\"min-w-0 border-t border-[var(--color-border-subtle)] pt-form-gap\">\n <label htmlFor={`${fieldId}-status`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.basicInfo.statusLabel', 'Status')}\n </label>\n <select\n id={`${fieldId}-status`}\n value={status}\n onChange={(e) => setStatus(e.target.value as PipelineStatus)}\n className={FIELD_CONTROL}\n >\n {STATUS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {statusOptionLabels[opt.value]}\n </option>\n ))}\n </select>\n <p className={FIELD_HINT}>Only active pipelines process incoming data.</p>\n </div>\n </div>\n </Section>\n\n {/* Stages — the one primary block on this route. */}\n <Section\n emphasis=\"primary\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.stages.heading', 'Stages ({{count}})', {\n count: stages.length,\n })}\n description=\"Each stage reads an input key, runs a parser, and writes an output key for the next stage.\"\n actions={\n <Button size=\"sm\" onClick={handleAddStage} className={TOUCH_TARGET}>\n <PlusIcon className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.builder.stages.addStage', 'Add Stage')}\n </Button>\n }\n data-testid=\"pipeline-stages-editor\"\n >\n {stages.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title={t('bigconsole.pipelines.builder.stages.emptyTitle', 'No stages yet')}\n description={t(\n 'bigconsole.pipelines.builder.stages.emptyDescription',\n 'Add a stage to start building your pipeline.'\n )}\n action={\n <Button onClick={handleAddStage} className={TOUCH_TARGET}>\n <PlusIcon className=\"h-icon-sm w-icon-sm\" />\n {t('bigconsole.pipelines.builder.stages.addFirstStage', 'Add First Stage')}\n </Button>\n }\n />\n ) : (\n <ol className=\"flex flex-col gap-form-gap\">\n {stages.map((stage, index) => (\n // Stages are positional and a new stage has no id until it is saved.\n <li key={index} className=\"min-w-0\">\n <Section\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={3}\n title={\n <span className=\"flex min-w-0 items-center gap-icon-gap\">\n <span\n aria-hidden=\"true\"\n className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-pill bg-bg-surface text-xs font-semibold text-text-secondary\"\n >\n {index + 1}\n </span>\n <span className=\"min-w-0 truncate\">\n {stage.parserName ||\n t('bigconsole.pipelines.builder.stages.defaultStageName', 'Stage {{number}}', {\n number: index + 1,\n })}\n </span>\n </span>\n }\n actions={\n <>\n <button\n type=\"button\"\n onClick={() => handleMoveStage(index, 'up')}\n disabled={index === 0}\n className={ICON_ACTION}\n aria-label={`Move stage ${index + 1} up`}\n >\n <ArrowUpIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleMoveStage(index, 'down')}\n disabled={index === stages.length - 1}\n className={ICON_ACTION}\n aria-label={`Move stage ${index + 1} down`}\n >\n <ArrowDownIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleRemoveStage(index)}\n className={ICON_ACTION_DANGER}\n aria-label={`Remove stage ${index + 1}`}\n >\n <TrashIcon className=\"h-icon-sm w-icon-sm\" />\n </button>\n </>\n }\n data-testid=\"pipeline-stage-editor\"\n >\n <div className=\"flex flex-col gap-form-gap\">\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-parser-${index}`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.stages.parserLabel', 'Parser')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <select\n id={`${fieldId}-parser-${index}`}\n value={stage.parserId}\n onChange={(e) => handleParserSelect(index, e.target.value)}\n className={FIELD_CONTROL}\n >\n <option value=\"\">\n {t('bigconsole.pipelines.builder.stages.parserPlaceholder', 'Select a parser...')}\n </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 {/* Data contract */}\n <fieldset className=\"min-w-0\">\n <legend className={FIELD_GROUP_LEGEND}>Data contract</legend>\n <div className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-input-${index}`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.stages.inputKeyLabel', 'Input Key')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id={`${fieldId}-input-${index}`}\n type=\"text\"\n value={stage.inputKey}\n onChange={(e) => handleUpdateStage(index, { inputKey: e.target.value })}\n placeholder={t('bigconsole.pipelines.builder.stages.inputKeyPlaceholder', 'data')}\n className={FIELD_CONTROL_MONO}\n />\n </div>\n\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-output-${index}`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.stages.outputKeyLabel', 'Output Key')}{' '}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id={`${fieldId}-output-${index}`}\n type=\"text\"\n value={stage.outputKey}\n onChange={(e) => handleUpdateStage(index, { outputKey: e.target.value })}\n placeholder={t(\n 'bigconsole.pipelines.builder.stages.outputKeyPlaceholder',\n 'result'\n )}\n className={FIELD_CONTROL_MONO}\n />\n </div>\n </div>\n </fieldset>\n\n {/* Failure policy */}\n <fieldset className=\"min-w-0\">\n <legend className={FIELD_GROUP_LEGEND}>Failure policy</legend>\n <div className=\"grid grid-cols-1 gap-form-gap sm:grid-cols-2\">\n <div className=\"min-w-0\">\n <label htmlFor={`${fieldId}-onerror-${index}`} className={FIELD_LABEL}>\n {t('bigconsole.pipelines.builder.stages.onErrorLabel', 'On Error')}\n </label>\n <select\n id={`${fieldId}-onerror-${index}`}\n value={stage.onError}\n onChange={(e) =>\n handleUpdateStage(index, {\n onError: e.target.value as StageErrorHandling,\n })\n }\n className={FIELD_CONTROL}\n >\n {ERROR_HANDLING_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {errorHandlingOptionLabels[opt.value]}\n </option>\n ))}\n </select>\n <p className={FIELD_HINT}>\n {ERROR_HANDLING_OPTIONS.find((opt) => opt.value === stage.onError)?.description}\n </p>\n </div>\n\n <div className=\"flex min-w-0 items-start\">\n <label\n htmlFor={`${fieldId}-enabled-${index}`}\n className={`flex cursor-pointer items-center gap-2 ${TOUCH_TARGET}`}\n >\n <input\n id={`${fieldId}-enabled-${index}`}\n type=\"checkbox\"\n checked={stage.enabled}\n onChange={(e) => handleUpdateStage(index, { enabled: e.target.checked })}\n className={`h-4 w-4 rounded border-[var(--color-border-subtle)] text-action-primary-bg ${SECTION_FOCUS_RING}`}\n />\n <span className=\"text-sm text-text-primary\">\n {t('bigconsole.pipelines.builder.stages.enabledLabel', 'Enabled')}\n </span>\n </label>\n </div>\n\n {stage.onError === 'fallback' && (\n <div className=\"min-w-0 sm:col-span-2\">\n <label htmlFor={`${fieldId}-fallback-${index}`} className={FIELD_LABEL}>\n {t(\n 'bigconsole.pipelines.builder.stages.fallbackValueLabel',\n 'Fallback Value (JSON)'\n )}\n </label>\n <input\n id={`${fieldId}-fallback-${index}`}\n type=\"text\"\n value={stage.fallbackValue}\n onChange={(e) => handleUpdateStage(index, { fallbackValue: e.target.value })}\n placeholder='{\"default\": true}'\n className={FIELD_CONTROL_MONO}\n />\n </div>\n )}\n </div>\n </fieldset>\n </div>\n </Section>\n </li>\n ))}\n </ol>\n )}\n </Section>\n </SectionStack>\n </div>\n\n {/* Sidebar — supporting context only. */}\n <div className=\"min-w-0\">\n <SectionStack>\n <Section\n emphasis=\"muted\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.preview.heading', 'Preview')}\n description=\"What will be saved.\"\n data-testid=\"pipeline-preview\"\n >\n <dl className=\"flex flex-col gap-3 text-sm\">\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-muted\">\n {t('bigconsole.pipelines.builder.preview.nameLabel', 'Name')}\n </dt>\n <dd className=\"break-words text-text-primary\">\n {name || t('bigconsole.pipelines.builder.preview.untitled', 'Untitled')}\n </dd>\n </div>\n\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-muted\">\n {t('bigconsole.pipelines.builder.preview.statusLabel', 'Status')}\n </dt>\n <dd className=\"mt-1\">\n <PipelineStatusBadge status={status} size=\"sm\" />\n </dd>\n </div>\n\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-muted\">\n {t('bigconsole.pipelines.builder.preview.stagesLabel', 'Stages')}\n </dt>\n <dd className=\"text-text-primary\">{stages.length}</dd>\n </div>\n\n {stages.length > 0 && (\n <div className=\"min-w-0 border-t border-[var(--color-border-subtle)] pt-3\">\n <dt className=\"text-xs text-text-muted\">\n {t('bigconsole.pipelines.builder.preview.dataFlowLabel', 'Data Flow')}\n </dt>\n <dd className=\"mt-1 flex flex-wrap items-center gap-1 text-xs\">\n {stages.map((s, i) => (\n <span key={i} className=\"flex items-center gap-1\">\n <code className=\"rounded-button bg-bg-surface px-1.5 py-0.5 font-mono break-all text-text-primary\">\n {s.inputKey}\n </code>\n <span aria-hidden=\"true\" className=\"text-text-muted\">\n →\n </span>\n </span>\n ))}\n <code className=\"rounded-button bg-bg-surface px-1.5 py-0.5 font-mono break-all text-text-primary\">\n {stages[stages.length - 1].outputKey}\n </code>\n </dd>\n </div>\n )}\n </dl>\n </Section>\n\n <Section\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={2}\n title={t('bigconsole.pipelines.builder.tips.heading', 'Tips')}\n data-testid=\"pipeline-builder-tips\"\n >\n <ul className=\"list-disc space-y-1 pl-4 text-sm text-text-secondary\">\n <li>\n {t(\n 'bigconsole.pipelines.builder.tips.item1',\n 'Each stage processes the output of the previous stage'\n )}\n </li>\n <li>\n {t('bigconsole.pipelines.builder.tips.item2', 'Use consistent input/output keys to chain data')}\n </li>\n <li>{t('bigconsole.pipelines.builder.tips.item3', 'Set error handling per stage for robustness')}</li>\n <li>\n {t('bigconsole.pipelines.builder.tips.item4', 'Disable stages to skip them during execution')}\n </li>\n </ul>\n </Section>\n </SectionStack>\n </div>\n </div>\n </SectionStack>\n </div>\n );\n});\n\nexport default PipelineBuilderPage;\n"],"mappings":"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"}
|