@burdenoff/microfe-bigconsole 2026.924.2 → 2026.925.1
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/BigConsoleRoot.js +94 -84
- package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
- package/dist/bigconsole/BigConsoleRoutes.js +137 -138
- package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
- package/dist/bigconsole/assistant/previewController.js +7 -7
- package/dist/bigconsole/components/DrilldownDashboardRenderer.js +17 -17
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +32 -32
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +52 -52
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +7 -7
- package/dist/bigconsole/components/dashboard/DashboardStatusPill.js +53 -0
- package/dist/bigconsole/components/dashboard/DashboardStatusPill.js.map +1 -0
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +60 -60
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +21 -21
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +30 -30
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +36 -36
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +34 -34
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +38 -38
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +121 -121
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +22 -22
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +46 -46
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +53 -53
- package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -1
- package/dist/bigconsole/components/dashboard/WidgetPalette.js +47 -47
- package/dist/bigconsole/components/dashboard/index.js +1 -0
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +35 -35
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +18 -18
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +20 -20
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +30 -29
- package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +48 -48
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +126 -114
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +35 -35
- package/dist/bigconsole/components/overview/DashboardGuide.js +214 -0
- package/dist/bigconsole/components/overview/DashboardGuide.js.map +1 -0
- package/dist/bigconsole/components/overview/DataHealthCard.js +97 -0
- package/dist/bigconsole/components/overview/DataHealthCard.js.map +1 -0
- package/dist/bigconsole/components/overview/OverviewQuickActions.js +32 -0
- package/dist/bigconsole/components/overview/OverviewQuickActions.js.map +1 -0
- package/dist/bigconsole/components/overview/OverviewStatCard.js +57 -0
- package/dist/bigconsole/components/overview/OverviewStatCard.js.map +1 -0
- package/dist/bigconsole/components/overview/RecentDashboardsPanel.js +107 -0
- package/dist/bigconsole/components/overview/RecentDashboardsPanel.js.map +1 -0
- package/dist/bigconsole/components/overview/dashboardGuideSteps.js +119 -0
- package/dist/bigconsole/components/overview/dashboardGuideSteps.js.map +1 -0
- package/dist/bigconsole/components/overview/index.js +8 -0
- package/dist/bigconsole/components/overview/overviewModel.js +119 -0
- package/dist/bigconsole/components/overview/overviewModel.js.map +1 -0
- package/dist/bigconsole/components/overview/useOverviewData.js +48 -0
- package/dist/bigconsole/components/overview/useOverviewData.js.map +1 -0
- package/dist/bigconsole/components/parser/DataSinkSelector.js +40 -40
- package/dist/bigconsole/components/parser/ImportParserDialog.js +127 -127
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +51 -51
- package/dist/bigconsole/components/preview/AiPreviewContent.js +5 -5
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +32 -32
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +37 -37
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +13 -13
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +70 -70
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +28 -28
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +25 -25
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js +48 -48
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +46 -46
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +61 -61
- package/dist/bigconsole/components/widgets/form/FormWidget.js +36 -36
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +42 -42
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +25 -25
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +21 -21
- package/dist/bigconsole/components/widgets/list/ListConfig.js +30 -30
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +38 -38
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +9 -9
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +9 -9
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +49 -49
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +39 -39
- package/dist/bigconsole/components/widgets/table/TableConfig.js +73 -73
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +64 -64
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +10 -10
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +68 -68
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
- package/dist/bigconsole/hooks/useDataSinkOperations.js +92 -89
- package/dist/bigconsole/hooks/useDataSinkOperations.js.map +1 -1
- package/dist/bigconsole/hooks/useImportDataSink.js +96 -91
- package/dist/bigconsole/hooks/useImportDataSink.js.map +1 -1
- package/dist/bigconsole/pages/AdminPage.js +136 -136
- package/dist/bigconsole/pages/DashboardBuilderPage.js +10 -10
- package/dist/bigconsole/pages/DashboardViewPage.js +61 -61
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +327 -348
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +5 -5
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +82 -80
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +83 -83
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +11 -11
- package/dist/bigconsole/pages/DataSourcesPage.js +5 -5
- package/dist/bigconsole/pages/InsightsPage.js +315 -315
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/OverviewPage.js +244 -0
- package/dist/bigconsole/pages/OverviewPage.js.map +1 -0
- package/dist/bigconsole/pages/ParserBuilderPage.js +5 -5
- package/dist/bigconsole/pages/ParserViewPage.js +98 -98
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +8 -8
- package/dist/bigconsole/pages/PipelineViewPage.js +46 -46
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +80 -80
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/SettingsPage.js +70 -70
- package/dist/bigconsole/pages/WidgetDemoPage.js +42 -42
- package/dist/bigconsole/pages/WorkflowViewPage.js +200 -200
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +78 -78
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/providers/BigConsoleQuotaProvider.js +36 -35
- package/dist/bigconsole/providers/BigConsoleQuotaProvider.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +34 -34
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +79 -79
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js +46 -46
- package/dist/bigconsole/utils/createDialogParam.js +14 -0
- package/dist/bigconsole/utils/createDialogParam.js.map +1 -0
- package/dist/bigconsole/utils/quota.js +51 -23
- package/dist/bigconsole/utils/quota.js.map +1 -1
- package/dist/generated/global-operations.js +1 -1
- package/dist/generated/wspace-operations.js +285 -222
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/shared/hooks/useTr.js +10 -7
- package/dist/shared/hooks/useTr.js.map +1 -1
- package/package.json +1 -1
- package/dist/bigconsole/pages/HomePage.js +0 -318
- package/dist/bigconsole/pages/HomePage.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImportDataSinkDialog.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/ImportDataSinkDialog.tsx"],"sourcesContent":["/**\n * ImportDataSinkDialog Component\n *\n * Modal dialog for importing a DataSink from JSON file.\n * Supports both creating new DataSinks and updating existing ones.\n */\n\nimport { type FC, memo, useState, useCallback, useEffect, useRef } from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Label } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Upload, FileJson, Check, XCircle, ArrowLeft, RefreshCw, Info } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useImportDataSink, type ImportDataSinkOptions } from '../../hooks';\nimport { useBigConsoleAnalytics } from '../../hooks/useBigConsoleAnalytics';\nimport { Section, SectionStack } from '../common';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ImportDataSinkDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess?: (dataSinkId: string, dataSinkName: string | null, originalUpdated: boolean) => void;\n}\n\ntype ImportStep = 'select' | 'preview' | 'importing' | 'complete';\n\n/**\n * Wizard steps. The dialog previously moved between three screens with no\n * indicator at all, so a user could not tell where they were.\n */\nconst WIZARD_STEPS: { id: ImportStep; label: string }[] = [\n { id: 'select', label: 'Choose file' },\n { id: 'preview', label: 'Review' },\n { id: 'complete', label: 'Done' },\n];\n\n/** Index of the wizard step currently on screen ('importing' still shows Review). */\nfunction wizardIndex(step: ImportStep): number {\n if (step === 'select') return 0;\n if (step === 'complete') return 2;\n return 1;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ImportDataSinkDialog: FC<ImportDataSinkDialogProps> = memo(function ImportDataSinkDialog({\n isOpen,\n onClose,\n onSuccess,\n}) {\n const { t } = useI18n();\n const [step, setStep] = useState<ImportStep>('select');\n const [, setSelectedFile] = useState<File | null>(null);\n const [fileContent, setFileContent] = useState<string | null>(null);\n const [nameOverride, setNameOverride] = useState('');\n const [keyOverride, setKeyOverride] = useState('');\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const {\n loading,\n error,\n validationResult,\n importResult,\n validateImport,\n importDataSink,\n extractDataSinkId,\n clearState,\n } = useImportDataSink();\n const emitBigConsoleEvent = useBigConsoleAnalytics();\n\n // Reset state when dialog opens\n useEffect(() => {\n if (isOpen) {\n setStep('select');\n setSelectedFile(null);\n setFileContent(null);\n setNameOverride('');\n setKeyOverride('');\n clearState();\n }\n }, [isOpen, clearState]);\n\n // Handle file selection\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n if (!file.name.endsWith('.json')) {\n alert(t('bigconsole.dataSinks.import.selectJsonFile', 'Please select a JSON file'));\n return;\n }\n\n setSelectedFile(file);\n\n const reader = new FileReader();\n reader.onload = async (event) => {\n const content = event.target?.result as string;\n setFileContent(content);\n\n const result = validateImport(content);\n if (result.isValid && result.dataSinkInfo) {\n setStep('preview');\n setNameOverride(result.dataSinkInfo.name || '');\n setKeyOverride(result.dataSinkInfo.key || '');\n } else {\n setStep('preview');\n }\n };\n reader.onerror = () => {\n alert(t('bigconsole.dataSinks.import.readFileError', 'Failed to read file'));\n };\n reader.readAsText(file);\n },\n [validateImport, t]\n );\n\n // Handle file drop\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n const file = e.dataTransfer.files?.[0];\n if (file) {\n const dt = new DataTransfer();\n dt.items.add(file);\n if (fileInputRef.current) {\n fileInputRef.current.files = dt.files;\n fileInputRef.current.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }, []);\n\n // Handle import\n const handleImport = useCallback(async () => {\n if (!fileContent) return;\n\n setStep('importing');\n\n const options: ImportDataSinkOptions = {\n name: nameOverride.trim() || undefined,\n key: keyOverride.trim() || undefined,\n };\n\n emitBigConsoleEvent('bigconsole.data_sink.import_clicked', { source: 'import' });\n\n const result = await importDataSink(fileContent, options);\n\n if (result?.success && result.dataSink) {\n setStep('complete');\n emitBigConsoleEvent('bigconsole.data_sink.imported', {\n dataSinkId: result.dataSink.id,\n source: 'import',\n originalUpdated: result.originalUpdated ?? false,\n });\n onSuccess?.(result.dataSink.id, result.dataSink.name, result.originalUpdated ?? false);\n } else {\n setStep('preview');\n }\n }, [emitBigConsoleEvent, fileContent, importDataSink, keyOverride, nameOverride, onSuccess]);\n\n const canClose = !loading && step !== 'importing';\n const dataSinkId = fileContent ? extractDataSinkId(fileContent) : null;\n const currentStepIndex = wizardIndex(step);\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && canClose && onClose()}>\n <DialogContent className=\"flex max-h-[85vh] flex-col sm:max-w-lg\">\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-card bg-bg-accentSubtle\">\n <Upload className=\"size-5 text-text-link\" />\n </div>\n <DialogTitle>{t('bigconsole.dataSinks.import.title', 'Import DataSink')}</DialogTitle>\n </div>\n <DialogDescription>\n {t(\n 'bigconsole.dataSinks.import.description',\n 'Upload a DataSink export file to restore it into this workspace.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n {/* Step indicator — structural strip so the wizard reads as a sequence. */}\n <ol className=\"flex flex-wrap items-center gap-x-icon-gap gap-y-1 text-xs\" aria-label=\"Import progress\">\n {WIZARD_STEPS.map((wizardStep, index) => (\n <li\n key={wizardStep.id}\n aria-current={index === currentStepIndex ? 'step' : undefined}\n className={`flex items-center gap-icon-gap ${\n index === currentStepIndex ? 'font-semibold text-text-primary' : 'text-text-muted'\n }`}\n >\n <span\n className={`inline-flex size-5 items-center justify-center rounded-pill text-[10px] ${\n index <= currentStepIndex ? 'bg-action-primary-bg text-action-primary-text' : 'bg-bg-sunken'\n }`}\n >\n {index + 1}\n </span>\n {wizardStep.label}\n {index < WIZARD_STEPS.length - 1 && (\n <span aria-hidden=\"true\" className=\"text-text-muted\">\n ›\n </span>\n )}\n </li>\n ))}\n </ol>\n\n <div className=\"min-w-0 flex-1 overflow-y-auto py-4\">\n <SectionStack>\n {/* Step 1: File Selection */}\n {step === 'select' && (\n <Section\n title=\"Choose an export file\"\n description={t(\n 'bigconsole.dataSinks.import.supportedFilesHint',\n 'Only .json files exported from BigConsole are supported'\n )}\n headingLevel={3}\n bodyClassName=\"mt-form-gap\"\n >\n <div\n onDragOver={(e) => e.preventDefault()}\n onDrop={handleDrop}\n className=\"rounded-card border-2 border-dashed border-[var(--color-border-default)] p-8 text-center hover:border-[var(--color-action-primary-bg)] motion-safe:transition-colors\"\n >\n <FileJson className=\"mx-auto mb-4 size-12 text-text-secondary\" />\n <p className=\"mb-2 text-sm\">\n {t('bigconsole.dataSinks.import.dropzoneText', 'Drag and drop a DataSink export file here')}\n </p>\n <p className=\"mb-4 text-xs text-text-secondary\">{t('bigconsole.dataSinks.import.or', 'or')}</p>\n <input ref={fileInputRef} type=\"file\" accept=\".json\" onChange={handleFileSelect} className=\"hidden\" />\n <Button onClick={() => fileInputRef.current?.click()} disabled={loading}>\n {t('bigconsole.dataSinks.import.browseFiles', 'Browse Files')}\n </Button>\n </div>\n </Section>\n )}\n\n {/* Step 2: Preview & Options */}\n {(step === 'preview' || step === 'importing') && validationResult && (\n <>\n {/* What is in the file — supporting detail. */}\n {validationResult.dataSinkInfo && (\n <Section\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={3}\n title=\"File contents\"\n description=\"What this export file describes.\"\n bodyClassName=\"space-y-2\"\n >\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.nameLabel', 'Name')}\n </span>\n <span className=\"min-w-0 truncate text-sm font-medium\">\n {validationResult.dataSinkInfo.name || t('bigconsole.dataSinks.import.unnamed', 'Unnamed')}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.keyLabel', 'Key')}\n </span>\n <span className=\"min-w-0 truncate font-mono text-xs\">{validationResult.dataSinkInfo.key}</span>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.statusLabel', 'Status')}\n </span>\n <Badge variant=\"secondary\">{validationResult.dataSinkInfo.status}</Badge>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.setupStateLabel', 'Setup State')}\n </span>\n <Badge variant=\"outline\">{validationResult.dataSinkInfo.setupState}</Badge>\n </div>\n {validationResult.dataSinkInfo.exportedFrom && (\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.sourceIdLabel', 'Source ID')}\n </span>\n <span className=\"min-w-0 max-w-[180px] truncate font-mono text-xs text-text-secondary\">\n {validationResult.dataSinkInfo.exportedFrom}\n </span>\n </div>\n )}\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.schemaVersionLabel', 'Schema Version')}\n </span>\n <span className=\"text-xs text-text-secondary\">{validationResult.dataSinkInfo.schemaVersion}</span>\n </div>\n </Section>\n )}\n\n {/* Validation Errors */}\n {validationResult.errors.length > 0 && (\n <Section\n tone=\"danger\"\n padding=\"compact\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.errorsHeading', 'Errors ({{count}})', {\n count: validationResult.errors.length,\n })}\n icon={<XCircle className=\"size-4\" />}\n >\n <ul className=\"space-y-1 text-xs text-status-error-text\">\n {validationResult.errors.map((err, idx) => (\n <li key={idx}>\n <span className=\"font-mono\">[{err.code}]</span> {err.message}\n </li>\n ))}\n </ul>\n </Section>\n )}\n\n {/* Import Options */}\n {validationResult.isValid && (\n <Section\n title={t('bigconsole.dataSinks.import.optionsHeading', 'Import Options')}\n description=\"Rename the sink or give it a different key before importing.\"\n headingLevel={3}\n bodyClassName=\"space-y-form-gap\"\n >\n <Section\n tone=\"info\"\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={4}\n icon={<Info className=\"size-4\" />}\n title={\n dataSinkId\n ? t(\n 'bigconsole.dataSinks.import.checkExistingHeading',\n 'Import will check for existing DataSink'\n )\n : t('bigconsole.dataSinks.import.newWillBeCreatedHeading', 'A new DataSink will be created')\n }\n >\n <div className=\"text-xs text-[var(--color-status-info-text)]\">\n {dataSinkId ? (\n <>\n <p>\n {t('bigconsole.dataSinks.import.ifOriginalExistsPrefix', 'If the original DataSink (ID:')}{' '}\n <code className=\"rounded-input bg-bg-surface px-1 font-mono\">\n {dataSinkId.slice(0, 8)}...\n </code>\n {t('bigconsole.dataSinks.import.ifOriginalExistsSuffix', ') exists:')}\n </p>\n <ul className=\"mt-1 list-inside list-disc space-y-0.5\">\n <li>\n {t(\n 'bigconsole.dataSinks.import.withChangesUpdate',\n 'With changes → Update the existing DataSink'\n )}\n </li>\n <li>\n {t(\n 'bigconsole.dataSinks.import.noChangesMessage',\n 'No changes → Show \"already exists\" message'\n )}\n </li>\n </ul>\n <p className=\"mt-1\">\n {t(\n 'bigconsole.dataSinks.import.ifNotExistsCreate',\n \"If original doesn't exist → Create a new DataSink\"\n )}\n </p>\n </>\n ) : (\n <p>\n {t(\n 'bigconsole.dataSinks.import.newWillBeCreatedBody',\n 'Import as a new DataSink with the specified configuration.'\n )}\n </p>\n )}\n </div>\n </Section>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-name\">\n {t('bigconsole.dataSinks.import.nameFieldLabel', 'DataSink Name')}\n </Label>\n <Input\n id=\"import-name\"\n type=\"text\"\n value={nameOverride}\n onChange={(e) => setNameOverride(e.target.value)}\n placeholder={\n validationResult.dataSinkInfo?.name ||\n t('bigconsole.dataSinks.import.namePlaceholder', 'DataSink name')\n }\n disabled={step === 'importing'}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-key\">\n {t('bigconsole.dataSinks.import.keyFieldLabel', 'DataSink Key')}\n </Label>\n <Input\n id=\"import-key\"\n type=\"text\"\n value={keyOverride}\n onChange={(e) => setKeyOverride(e.target.value)}\n placeholder={\n validationResult.dataSinkInfo?.key ||\n t('bigconsole.dataSinks.import.keyPlaceholder', 'datasink-key')\n }\n disabled={step === 'importing'}\n />\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.keyHelp',\n 'Use a unique key to avoid conflicts with existing DataSinks.'\n )}\n </p>\n </div>\n </Section>\n )}\n </>\n )}\n\n {/* Step 3: Complete */}\n {step === 'complete' && importResult?.success && (\n <>\n {/* Already Exists - No Changes */}\n {importResult.alreadyExists && (\n <Section\n tone=\"info\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.alreadyExistsTitle', 'DataSink Already Exists')}\n icon={<Info className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.alreadyExistsBody',\n 'DataSink \"{{name}}\" already exists with the same data. No changes were made.',\n { name: importResult.dataSink?.name || importResult.dataSink?.key || '' }\n )}\n </p>\n </Section>\n )}\n\n {/* Updated Existing */}\n {importResult.originalUpdated && !importResult.alreadyExists && (\n <Section\n tone=\"success\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.updatedTitle', 'DataSink Updated!')}\n icon={<RefreshCw className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.updatedBody',\n 'DataSink \"{{name}}\" has been updated with the imported data.',\n { name: importResult.dataSink?.name || importResult.dataSink?.key || '' }\n )}\n </p>\n </Section>\n )}\n\n {/* Created New */}\n {!importResult.originalUpdated && !importResult.alreadyExists && (\n <Section\n tone=\"success\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.successTitle', 'Import Successful!')}\n icon={<Check className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.successBody', 'DataSink \"{{name}}\" has been created.', {\n name: importResult.dataSink?.name || importResult.dataSink?.key || '',\n })}\n </p>\n </Section>\n )}\n </>\n )}\n\n {/* Error */}\n {error && (\n <Section tone=\"danger\" padding=\"compact\" headingLevel={3} title=\"Import failed\">\n <p className=\"text-sm text-status-error-text\">{error.message}</p>\n </Section>\n )}\n\n {importResult && !importResult.success && importResult.errorMessage && (\n <Section tone=\"danger\" padding=\"compact\" headingLevel={3} title=\"Import failed\">\n <p className=\"text-sm text-status-error-text\">{importResult.errorMessage}</p>\n </Section>\n )}\n </SectionStack>\n </div>\n\n <DialogFooter className=\"flex flex-col-reverse gap-control-gap sm:flex-row sm:justify-between\">\n {step === 'preview' ? (\n <Button\n variant=\"ghost\"\n onClick={() => {\n setStep('select');\n setSelectedFile(null);\n setFileContent(null);\n clearState();\n }}\n disabled={loading}\n >\n <ArrowLeft className=\"size-4\" />\n {t('bigconsole.dataSinks.import.back', 'Back')}\n </Button>\n ) : (\n <span aria-hidden=\"true\" className=\"hidden sm:block\" />\n )}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n {step !== 'complete' && (\n <Button variant=\"outline\" onClick={onClose} disabled={!canClose}>\n {t('bigconsole.dataSinks.import.cancel', 'Cancel')}\n </Button>\n )}\n\n {step === 'preview' && validationResult?.isValid && (\n <Button onClick={handleImport} disabled={loading}>\n <Upload className=\"size-4\" />\n {t('bigconsole.dataSinks.import.importButton', 'Import DataSink')}\n </Button>\n )}\n\n {step === 'importing' && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Spinner className=\"size-4\" />\n {t('bigconsole.dataSinks.import.importing', 'Importing...')}\n </div>\n )}\n\n {step === 'complete' && <Button onClick={onClose}>{t('bigconsole.dataSinks.import.done', 'Done')}</Button>}\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default ImportDataSinkDialog;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ImportDataSinkDialog.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/ImportDataSinkDialog.tsx"],"sourcesContent":["/**\n * ImportDataSinkDialog Component\n *\n * Modal dialog for importing a DataSink from JSON file.\n * Supports both creating new DataSinks and updating existing ones.\n */\n\nimport { type FC, memo, useState, useCallback, useEffect, useRef } from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Label } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Upload, FileJson, Check, XCircle, ArrowLeft, RefreshCw, Info } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useImportDataSink, type ImportDataSinkOptions } from '../../hooks';\nimport { useBigConsoleAnalytics } from '../../hooks/useBigConsoleAnalytics';\nimport { Section, SectionStack } from '../common';\nimport { reportBigConsoleQuotaError } from '../../utils/quota';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ImportDataSinkDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess?: (dataSinkId: string, dataSinkName: string | null, originalUpdated: boolean) => void;\n}\n\ntype ImportStep = 'select' | 'preview' | 'importing' | 'complete';\n\n/**\n * Wizard steps. The dialog previously moved between three screens with no\n * indicator at all, so a user could not tell where they were.\n */\nconst WIZARD_STEPS: { id: ImportStep; label: string }[] = [\n { id: 'select', label: 'Choose file' },\n { id: 'preview', label: 'Review' },\n { id: 'complete', label: 'Done' },\n];\n\n/** Index of the wizard step currently on screen ('importing' still shows Review). */\nfunction wizardIndex(step: ImportStep): number {\n if (step === 'select') return 0;\n if (step === 'complete') return 2;\n return 1;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ImportDataSinkDialog: FC<ImportDataSinkDialogProps> = memo(function ImportDataSinkDialog({\n isOpen,\n onClose,\n onSuccess,\n}) {\n const { t } = useI18n();\n const [step, setStep] = useState<ImportStep>('select');\n const [, setSelectedFile] = useState<File | null>(null);\n const [fileContent, setFileContent] = useState<string | null>(null);\n const [nameOverride, setNameOverride] = useState('');\n const [keyOverride, setKeyOverride] = useState('');\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const {\n loading,\n error,\n validationResult,\n importResult,\n validateImport,\n importDataSink,\n extractDataSinkId,\n clearState,\n } = useImportDataSink();\n const emitBigConsoleEvent = useBigConsoleAnalytics();\n\n // Reset state when dialog opens\n useEffect(() => {\n if (isOpen) {\n setStep('select');\n setSelectedFile(null);\n setFileContent(null);\n setNameOverride('');\n setKeyOverride('');\n clearState();\n }\n }, [isOpen, clearState]);\n\n // Handle file selection\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n if (!file.name.endsWith('.json')) {\n alert(t('bigconsole.dataSinks.import.selectJsonFile', 'Please select a JSON file'));\n return;\n }\n\n setSelectedFile(file);\n\n const reader = new FileReader();\n reader.onload = async (event) => {\n const content = event.target?.result as string;\n setFileContent(content);\n\n const result = validateImport(content);\n if (result.isValid && result.dataSinkInfo) {\n setStep('preview');\n setNameOverride(result.dataSinkInfo.name || '');\n setKeyOverride(result.dataSinkInfo.key || '');\n } else {\n setStep('preview');\n }\n };\n reader.onerror = () => {\n alert(t('bigconsole.dataSinks.import.readFileError', 'Failed to read file'));\n };\n reader.readAsText(file);\n },\n [validateImport, t]\n );\n\n // Handle file drop\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n const file = e.dataTransfer.files?.[0];\n if (file) {\n const dt = new DataTransfer();\n dt.items.add(file);\n if (fileInputRef.current) {\n fileInputRef.current.files = dt.files;\n fileInputRef.current.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }, []);\n\n // Handle import\n const handleImport = useCallback(async () => {\n if (!fileContent) return;\n\n setStep('importing');\n\n const options: ImportDataSinkOptions = {\n name: nameOverride.trim() || undefined,\n key: keyOverride.trim() || undefined,\n };\n\n emitBigConsoleEvent('bigconsole.data_sink.import_clicked', { source: 'import' });\n\n let result: Awaited<ReturnType<typeof importDataSink>>;\n try {\n result = await importDataSink(fileContent, options);\n } catch (err) {\n // Quota refusals (e.g. \"Set up billing\" for an org without a billing\n // account, BOFF-7913) are shown by the shared quota dialog.\n if (reportBigConsoleQuotaError(err)) {\n onClose();\n return;\n }\n setStep('preview');\n return;\n }\n\n if (result?.success && result.dataSink) {\n setStep('complete');\n emitBigConsoleEvent('bigconsole.data_sink.imported', {\n dataSinkId: result.dataSink.id,\n source: 'import',\n originalUpdated: result.originalUpdated ?? false,\n });\n onSuccess?.(result.dataSink.id, result.dataSink.name, result.originalUpdated ?? false);\n } else {\n setStep('preview');\n }\n }, [emitBigConsoleEvent, fileContent, importDataSink, keyOverride, nameOverride, onClose, onSuccess]);\n\n const canClose = !loading && step !== 'importing';\n const dataSinkId = fileContent ? extractDataSinkId(fileContent) : null;\n const currentStepIndex = wizardIndex(step);\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && canClose && onClose()}>\n <DialogContent className=\"flex max-h-[85vh] flex-col sm:max-w-lg\">\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-card bg-bg-accentSubtle\">\n <Upload className=\"size-5 text-text-link\" />\n </div>\n <DialogTitle>{t('bigconsole.dataSinks.import.title', 'Import DataSink')}</DialogTitle>\n </div>\n <DialogDescription>\n {t(\n 'bigconsole.dataSinks.import.description',\n 'Upload a DataSink export file to restore it into this workspace.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n {/* Step indicator — structural strip so the wizard reads as a sequence. */}\n <ol className=\"flex flex-wrap items-center gap-x-icon-gap gap-y-1 text-xs\" aria-label=\"Import progress\">\n {WIZARD_STEPS.map((wizardStep, index) => (\n <li\n key={wizardStep.id}\n aria-current={index === currentStepIndex ? 'step' : undefined}\n className={`flex items-center gap-icon-gap ${\n index === currentStepIndex ? 'font-semibold text-text-primary' : 'text-text-muted'\n }`}\n >\n <span\n className={`inline-flex size-5 items-center justify-center rounded-pill text-[10px] ${\n index <= currentStepIndex ? 'bg-action-primary-bg text-action-primary-text' : 'bg-bg-sunken'\n }`}\n >\n {index + 1}\n </span>\n {wizardStep.label}\n {index < WIZARD_STEPS.length - 1 && (\n <span aria-hidden=\"true\" className=\"text-text-muted\">\n ›\n </span>\n )}\n </li>\n ))}\n </ol>\n\n <div className=\"min-w-0 flex-1 overflow-y-auto py-4\">\n <SectionStack>\n {/* Step 1: File Selection */}\n {step === 'select' && (\n <Section\n title=\"Choose an export file\"\n description={t(\n 'bigconsole.dataSinks.import.supportedFilesHint',\n 'Only .json files exported from BigConsole are supported'\n )}\n headingLevel={3}\n bodyClassName=\"mt-form-gap\"\n >\n <div\n onDragOver={(e) => e.preventDefault()}\n onDrop={handleDrop}\n className=\"rounded-card border-2 border-dashed border-[var(--color-border-default)] p-8 text-center hover:border-[var(--color-action-primary-bg)] motion-safe:transition-colors\"\n >\n <FileJson className=\"mx-auto mb-4 size-12 text-text-secondary\" />\n <p className=\"mb-2 text-sm\">\n {t('bigconsole.dataSinks.import.dropzoneText', 'Drag and drop a DataSink export file here')}\n </p>\n <p className=\"mb-4 text-xs text-text-secondary\">{t('bigconsole.dataSinks.import.or', 'or')}</p>\n <input ref={fileInputRef} type=\"file\" accept=\".json\" onChange={handleFileSelect} className=\"hidden\" />\n <Button onClick={() => fileInputRef.current?.click()} disabled={loading}>\n {t('bigconsole.dataSinks.import.browseFiles', 'Browse Files')}\n </Button>\n </div>\n </Section>\n )}\n\n {/* Step 2: Preview & Options */}\n {(step === 'preview' || step === 'importing') && validationResult && (\n <>\n {/* What is in the file — supporting detail. */}\n {validationResult.dataSinkInfo && (\n <Section\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={3}\n title=\"File contents\"\n description=\"What this export file describes.\"\n bodyClassName=\"space-y-2\"\n >\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.nameLabel', 'Name')}\n </span>\n <span className=\"min-w-0 truncate text-sm font-medium\">\n {validationResult.dataSinkInfo.name || t('bigconsole.dataSinks.import.unnamed', 'Unnamed')}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.keyLabel', 'Key')}\n </span>\n <span className=\"min-w-0 truncate font-mono text-xs\">{validationResult.dataSinkInfo.key}</span>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.statusLabel', 'Status')}\n </span>\n <Badge variant=\"secondary\">{validationResult.dataSinkInfo.status}</Badge>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.setupStateLabel', 'Setup State')}\n </span>\n <Badge variant=\"outline\">{validationResult.dataSinkInfo.setupState}</Badge>\n </div>\n {validationResult.dataSinkInfo.exportedFrom && (\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.sourceIdLabel', 'Source ID')}\n </span>\n <span className=\"min-w-0 max-w-[180px] truncate font-mono text-xs text-text-secondary\">\n {validationResult.dataSinkInfo.exportedFrom}\n </span>\n </div>\n )}\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.schemaVersionLabel', 'Schema Version')}\n </span>\n <span className=\"text-xs text-text-secondary\">{validationResult.dataSinkInfo.schemaVersion}</span>\n </div>\n </Section>\n )}\n\n {/* Validation Errors */}\n {validationResult.errors.length > 0 && (\n <Section\n tone=\"danger\"\n padding=\"compact\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.errorsHeading', 'Errors ({{count}})', {\n count: validationResult.errors.length,\n })}\n icon={<XCircle className=\"size-4\" />}\n >\n <ul className=\"space-y-1 text-xs text-status-error-text\">\n {validationResult.errors.map((err, idx) => (\n <li key={idx}>\n <span className=\"font-mono\">[{err.code}]</span> {err.message}\n </li>\n ))}\n </ul>\n </Section>\n )}\n\n {/* Import Options */}\n {validationResult.isValid && (\n <Section\n title={t('bigconsole.dataSinks.import.optionsHeading', 'Import Options')}\n description=\"Rename the sink or give it a different key before importing.\"\n headingLevel={3}\n bodyClassName=\"space-y-form-gap\"\n >\n <Section\n tone=\"info\"\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={4}\n icon={<Info className=\"size-4\" />}\n title={\n dataSinkId\n ? t(\n 'bigconsole.dataSinks.import.checkExistingHeading',\n 'Import will check for existing DataSink'\n )\n : t('bigconsole.dataSinks.import.newWillBeCreatedHeading', 'A new DataSink will be created')\n }\n >\n <div className=\"text-xs text-[var(--color-status-info-text)]\">\n {dataSinkId ? (\n <>\n <p>\n {t('bigconsole.dataSinks.import.ifOriginalExistsPrefix', 'If the original DataSink (ID:')}{' '}\n <code className=\"rounded-input bg-bg-surface px-1 font-mono\">\n {dataSinkId.slice(0, 8)}...\n </code>\n {t('bigconsole.dataSinks.import.ifOriginalExistsSuffix', ') exists:')}\n </p>\n <ul className=\"mt-1 list-inside list-disc space-y-0.5\">\n <li>\n {t(\n 'bigconsole.dataSinks.import.withChangesUpdate',\n 'With changes → Update the existing DataSink'\n )}\n </li>\n <li>\n {t(\n 'bigconsole.dataSinks.import.noChangesMessage',\n 'No changes → Show \"already exists\" message'\n )}\n </li>\n </ul>\n <p className=\"mt-1\">\n {t(\n 'bigconsole.dataSinks.import.ifNotExistsCreate',\n \"If original doesn't exist → Create a new DataSink\"\n )}\n </p>\n </>\n ) : (\n <p>\n {t(\n 'bigconsole.dataSinks.import.newWillBeCreatedBody',\n 'Import as a new DataSink with the specified configuration.'\n )}\n </p>\n )}\n </div>\n </Section>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-name\">\n {t('bigconsole.dataSinks.import.nameFieldLabel', 'DataSink Name')}\n </Label>\n <Input\n id=\"import-name\"\n type=\"text\"\n value={nameOverride}\n onChange={(e) => setNameOverride(e.target.value)}\n placeholder={\n validationResult.dataSinkInfo?.name ||\n t('bigconsole.dataSinks.import.namePlaceholder', 'DataSink name')\n }\n disabled={step === 'importing'}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-key\">\n {t('bigconsole.dataSinks.import.keyFieldLabel', 'DataSink Key')}\n </Label>\n <Input\n id=\"import-key\"\n type=\"text\"\n value={keyOverride}\n onChange={(e) => setKeyOverride(e.target.value)}\n placeholder={\n validationResult.dataSinkInfo?.key ||\n t('bigconsole.dataSinks.import.keyPlaceholder', 'datasink-key')\n }\n disabled={step === 'importing'}\n />\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.keyHelp',\n 'Use a unique key to avoid conflicts with existing DataSinks.'\n )}\n </p>\n </div>\n </Section>\n )}\n </>\n )}\n\n {/* Step 3: Complete */}\n {step === 'complete' && importResult?.success && (\n <>\n {/* Already Exists - No Changes */}\n {importResult.alreadyExists && (\n <Section\n tone=\"info\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.alreadyExistsTitle', 'DataSink Already Exists')}\n icon={<Info className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.alreadyExistsBody',\n 'DataSink \"{{name}}\" already exists with the same data. No changes were made.',\n { name: importResult.dataSink?.name || importResult.dataSink?.key || '' }\n )}\n </p>\n </Section>\n )}\n\n {/* Updated Existing */}\n {importResult.originalUpdated && !importResult.alreadyExists && (\n <Section\n tone=\"success\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.updatedTitle', 'DataSink Updated!')}\n icon={<RefreshCw className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.updatedBody',\n 'DataSink \"{{name}}\" has been updated with the imported data.',\n { name: importResult.dataSink?.name || importResult.dataSink?.key || '' }\n )}\n </p>\n </Section>\n )}\n\n {/* Created New */}\n {!importResult.originalUpdated && !importResult.alreadyExists && (\n <Section\n tone=\"success\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.successTitle', 'Import Successful!')}\n icon={<Check className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.successBody', 'DataSink \"{{name}}\" has been created.', {\n name: importResult.dataSink?.name || importResult.dataSink?.key || '',\n })}\n </p>\n </Section>\n )}\n </>\n )}\n\n {/* Error */}\n {error && (\n <Section tone=\"danger\" padding=\"compact\" headingLevel={3} title=\"Import failed\">\n <p className=\"text-sm text-status-error-text\">{error.message}</p>\n </Section>\n )}\n\n {importResult && !importResult.success && importResult.errorMessage && (\n <Section tone=\"danger\" padding=\"compact\" headingLevel={3} title=\"Import failed\">\n <p className=\"text-sm text-status-error-text\">{importResult.errorMessage}</p>\n </Section>\n )}\n </SectionStack>\n </div>\n\n <DialogFooter className=\"flex flex-col-reverse gap-control-gap sm:flex-row sm:justify-between\">\n {step === 'preview' ? (\n <Button\n variant=\"ghost\"\n onClick={() => {\n setStep('select');\n setSelectedFile(null);\n setFileContent(null);\n clearState();\n }}\n disabled={loading}\n >\n <ArrowLeft className=\"size-4\" />\n {t('bigconsole.dataSinks.import.back', 'Back')}\n </Button>\n ) : (\n <span aria-hidden=\"true\" className=\"hidden sm:block\" />\n )}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n {step !== 'complete' && (\n <Button variant=\"outline\" onClick={onClose} disabled={!canClose}>\n {t('bigconsole.dataSinks.import.cancel', 'Cancel')}\n </Button>\n )}\n\n {step === 'preview' && validationResult?.isValid && (\n <Button onClick={handleImport} disabled={loading}>\n <Upload className=\"size-4\" />\n {t('bigconsole.dataSinks.import.importButton', 'Import DataSink')}\n </Button>\n )}\n\n {step === 'importing' && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Spinner className=\"size-4\" />\n {t('bigconsole.dataSinks.import.importing', 'Importing...')}\n </div>\n )}\n\n {step === 'complete' && <Button onClick={onClose}>{t('bigconsole.dataSinks.import.done', 'Done')}</Button>}\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default ImportDataSinkDialog;\n"],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "../common/sectionStyles.js";
|
|
2
2
|
import "../common/index.js";
|
|
3
3
|
import { memo as e, useCallback as t, useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
5
|
+
import { useI18n as c } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
6
6
|
//#region src/bigconsole/components/datasink/RefreshTypeSelector.tsx
|
|
7
7
|
var l = e(function({ value: e, onChange: l, disabled: u = !1, error: d }) {
|
|
8
|
-
let { t: f } =
|
|
8
|
+
let { t: f } = c(), p = r(() => [
|
|
9
9
|
{
|
|
10
10
|
label: f("bigconsole.dataSinks.refreshType.presetEvery5MinutesLabel", "Every 5 minutes"),
|
|
11
11
|
cron: "*/5 * * * *",
|
|
@@ -135,19 +135,19 @@ var l = e(function({ value: e, onChange: l, disabled: u = !1, error: d }) {
|
|
|
135
135
|
S,
|
|
136
136
|
v
|
|
137
137
|
]);
|
|
138
|
-
return /* @__PURE__ */
|
|
138
|
+
return /* @__PURE__ */ s("div", {
|
|
139
139
|
className: "space-y-4",
|
|
140
140
|
children: [
|
|
141
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("label", {
|
|
142
142
|
className: "block text-sm font-medium text-text-primary mb-1",
|
|
143
143
|
children: f("bigconsole.dataSinks.refreshType.heading", "Refresh Type")
|
|
144
|
-
}), /* @__PURE__ */
|
|
144
|
+
}), /* @__PURE__ */ o("p", {
|
|
145
145
|
className: "text-xs text-text-secondary",
|
|
146
146
|
children: f("bigconsole.dataSinks.refreshType.headingDescription", "When should this data be updated?")
|
|
147
147
|
})] }),
|
|
148
|
-
/* @__PURE__ */
|
|
148
|
+
/* @__PURE__ */ s("div", {
|
|
149
149
|
className: "space-y-list-gap",
|
|
150
|
-
children: [/* @__PURE__ */
|
|
150
|
+
children: [/* @__PURE__ */ s("label", {
|
|
151
151
|
className: `
|
|
152
152
|
flex cursor-pointer items-start gap-3
|
|
153
153
|
rounded-input
|
|
@@ -156,65 +156,65 @@ var l = e(function({ value: e, onChange: l, disabled: u = !1, error: d }) {
|
|
|
156
156
|
${u ? "cursor-not-allowed opacity-50" : ""}
|
|
157
157
|
${g === "manual" ? "border-[var(--color-action-primary-bg)] bg-bg-accentSubtle" : "border-[var(--color-border-subtle)] hover:border-[var(--color-border-strong)]"}
|
|
158
158
|
`,
|
|
159
|
-
children: [/* @__PURE__ */
|
|
159
|
+
children: [/* @__PURE__ */ o("input", {
|
|
160
160
|
type: "radio",
|
|
161
161
|
name: "refresh-type",
|
|
162
162
|
checked: g === "manual",
|
|
163
163
|
onChange: () => D("manual"),
|
|
164
164
|
disabled: u,
|
|
165
165
|
className: "\n mt-0.5\n h-4 w-4\n border-[var(--color-border-default)]\n text-action-primary-bg\n focus-visible:ring-2\n focus-visible:ring-ring\n "
|
|
166
|
-
}), /* @__PURE__ */
|
|
166
|
+
}), /* @__PURE__ */ s("div", {
|
|
167
167
|
className: "flex-1",
|
|
168
|
-
children: [/* @__PURE__ */
|
|
168
|
+
children: [/* @__PURE__ */ o("span", {
|
|
169
169
|
className: "text-sm font-medium text-text-primary",
|
|
170
170
|
children: f("bigconsole.dataSinks.refreshType.manualLabel", "Manual")
|
|
171
|
-
}), /* @__PURE__ */
|
|
171
|
+
}), /* @__PURE__ */ o("p", {
|
|
172
172
|
className: "text-xs text-text-secondary mt-0.5",
|
|
173
173
|
children: f("bigconsole.dataSinks.refreshType.manualDescription", "Data refreshes only when you click the \"Refresh\" button")
|
|
174
174
|
})]
|
|
175
175
|
})]
|
|
176
|
-
}), /* @__PURE__ */
|
|
176
|
+
}), /* @__PURE__ */ s("div", {
|
|
177
177
|
className: `
|
|
178
178
|
rounded-input border
|
|
179
179
|
motion-safe:transition-colors
|
|
180
180
|
${u ? "opacity-50" : ""}
|
|
181
181
|
${g === "scheduled" ? "border-[var(--color-action-primary-bg)] bg-bg-accentSubtle" : "border-[var(--color-border-subtle)]"}
|
|
182
182
|
`,
|
|
183
|
-
children: [/* @__PURE__ */
|
|
183
|
+
children: [/* @__PURE__ */ s("label", {
|
|
184
184
|
className: `
|
|
185
185
|
flex items-start gap-3
|
|
186
186
|
p-4
|
|
187
187
|
cursor-pointer
|
|
188
188
|
${u ? "cursor-not-allowed" : ""}
|
|
189
189
|
`,
|
|
190
|
-
children: [/* @__PURE__ */
|
|
190
|
+
children: [/* @__PURE__ */ o("input", {
|
|
191
191
|
type: "radio",
|
|
192
192
|
name: "refresh-type",
|
|
193
193
|
checked: g === "scheduled",
|
|
194
194
|
onChange: () => D("scheduled"),
|
|
195
195
|
disabled: u,
|
|
196
196
|
className: "\n mt-0.5\n h-4 w-4\n border-[var(--color-border-default)]\n text-action-primary-bg\n focus-visible:ring-2\n focus-visible:ring-ring\n "
|
|
197
|
-
}), /* @__PURE__ */
|
|
197
|
+
}), /* @__PURE__ */ s("div", {
|
|
198
198
|
className: "flex-1",
|
|
199
|
-
children: [/* @__PURE__ */
|
|
199
|
+
children: [/* @__PURE__ */ o("span", {
|
|
200
200
|
className: "text-sm font-medium text-text-primary",
|
|
201
201
|
children: f("bigconsole.dataSinks.refreshType.automaticLabel", "Automatic")
|
|
202
|
-
}), /* @__PURE__ */
|
|
202
|
+
}), /* @__PURE__ */ o("p", {
|
|
203
203
|
className: "text-xs text-text-secondary mt-0.5",
|
|
204
204
|
children: f("bigconsole.dataSinks.refreshType.automaticDescription", "Data refreshes on a schedule")
|
|
205
205
|
})]
|
|
206
206
|
})]
|
|
207
|
-
}), g === "scheduled" && /* @__PURE__ */
|
|
207
|
+
}), g === "scheduled" && /* @__PURE__ */ s("div", {
|
|
208
208
|
className: "space-y-form-gap px-4 pb-4",
|
|
209
209
|
children: [
|
|
210
|
-
/* @__PURE__ */
|
|
210
|
+
/* @__PURE__ */ s("div", {
|
|
211
211
|
className: "border-t border-[var(--color-border-subtle)] pt-4",
|
|
212
|
-
children: [/* @__PURE__ */
|
|
212
|
+
children: [/* @__PURE__ */ o("label", {
|
|
213
213
|
className: "mb-2 block text-xs font-medium text-text-secondary",
|
|
214
214
|
children: f("bigconsole.dataSinks.refreshType.scheduleLabel", "Schedule")
|
|
215
|
-
}), /* @__PURE__ */
|
|
215
|
+
}), /* @__PURE__ */ o("div", {
|
|
216
216
|
className: "grid grid-cols-1 gap-2 sm:grid-cols-2",
|
|
217
|
-
children: p.map((e) => /* @__PURE__ */
|
|
217
|
+
children: p.map((e) => /* @__PURE__ */ o("button", {
|
|
218
218
|
type: "button",
|
|
219
219
|
onClick: () => O(e),
|
|
220
220
|
disabled: u,
|
|
@@ -228,14 +228,14 @@ var l = e(function({ value: e, onChange: l, disabled: u = !1, error: d }) {
|
|
|
228
228
|
${u ? "cursor-not-allowed" : "cursor-pointer"}
|
|
229
229
|
${!b && v?.cron === e.cron ? "border-[var(--color-action-primary-bg)] bg-bg-accentSubtle text-text-link" : "border-[var(--color-border-subtle)] hover:border-[var(--color-border-strong)]"}
|
|
230
230
|
`,
|
|
231
|
-
children: /* @__PURE__ */
|
|
231
|
+
children: /* @__PURE__ */ o("span", {
|
|
232
232
|
className: "text-sm font-medium",
|
|
233
233
|
children: e.label
|
|
234
234
|
})
|
|
235
235
|
}, e.cron))
|
|
236
236
|
})]
|
|
237
237
|
}),
|
|
238
|
-
/* @__PURE__ */
|
|
238
|
+
/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("button", {
|
|
239
239
|
type: "button",
|
|
240
240
|
onClick: k,
|
|
241
241
|
disabled: u,
|
|
@@ -245,9 +245,9 @@ var l = e(function({ value: e, onChange: l, disabled: u = !1, error: d }) {
|
|
|
245
245
|
${b ? "text-text-link" : "text-text-secondary hover:text-text-primary"}
|
|
246
246
|
`,
|
|
247
247
|
children: b ? f("bigconsole.dataSinks.refreshType.usingCustomSchedule", "Using custom schedule") : f("bigconsole.dataSinks.refreshType.useCustomSchedule", "Use custom schedule...")
|
|
248
|
-
}), b && /* @__PURE__ */
|
|
248
|
+
}), b && /* @__PURE__ */ s("div", {
|
|
249
249
|
className: "mt-2",
|
|
250
|
-
children: [/* @__PURE__ */
|
|
250
|
+
children: [/* @__PURE__ */ o("input", {
|
|
251
251
|
type: "text",
|
|
252
252
|
"aria-label": "Custom cron expression",
|
|
253
253
|
value: S,
|
|
@@ -255,22 +255,22 @@ var l = e(function({ value: e, onChange: l, disabled: u = !1, error: d }) {
|
|
|
255
255
|
disabled: u,
|
|
256
256
|
placeholder: "*/15 * * * *",
|
|
257
257
|
className: "\n h-control-md w-full min-w-0\n rounded-input\n border border-[var(--color-border-default)]\n bg-bg-sunken\n px-3\n font-mono\n text-sm text-text-primary\n focus-visible:outline-none\n focus-visible:ring-2\n focus-visible:ring-ring\n "
|
|
258
|
-
}), /* @__PURE__ */
|
|
258
|
+
}), /* @__PURE__ */ o("p", {
|
|
259
259
|
className: "mt-1 text-xs text-text-muted",
|
|
260
260
|
children: f("bigconsole.dataSinks.refreshType.customCronHelp", "Enter a cron expression (e.g., */15 * * * * for every 15 minutes)")
|
|
261
261
|
})]
|
|
262
262
|
})] }),
|
|
263
|
-
/* @__PURE__ */
|
|
263
|
+
/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("label", {
|
|
264
264
|
htmlFor: "refresh-timezone",
|
|
265
265
|
className: "mb-2 block text-xs font-medium text-text-secondary",
|
|
266
266
|
children: f("bigconsole.dataSinks.refreshType.timezoneLabel", "Timezone")
|
|
267
|
-
}), /* @__PURE__ */
|
|
267
|
+
}), /* @__PURE__ */ o("select", {
|
|
268
268
|
id: "refresh-timezone",
|
|
269
269
|
value: w,
|
|
270
270
|
onChange: j,
|
|
271
271
|
disabled: u,
|
|
272
272
|
className: "\n h-control-md w-full min-w-0\n rounded-input\n border border-[var(--color-border-default)]\n bg-bg-sunken\n px-3\n text-sm text-text-primary\n focus-visible:outline-none\n focus-visible:ring-2\n focus-visible:ring-ring\n ",
|
|
273
|
-
children: m.map((e) => /* @__PURE__ */
|
|
273
|
+
children: m.map((e) => /* @__PURE__ */ o("option", {
|
|
274
274
|
value: e.value,
|
|
275
275
|
children: e.label
|
|
276
276
|
}, e.value))
|
|
@@ -279,20 +279,20 @@ var l = e(function({ value: e, onChange: l, disabled: u = !1, error: d }) {
|
|
|
279
279
|
})]
|
|
280
280
|
})]
|
|
281
281
|
}),
|
|
282
|
-
d && /* @__PURE__ */
|
|
282
|
+
d && /* @__PURE__ */ s("div", {
|
|
283
283
|
className: "flex items-start gap-2",
|
|
284
|
-
children: [/* @__PURE__ */
|
|
284
|
+
children: [/* @__PURE__ */ o("svg", {
|
|
285
285
|
className: "w-4 h-4 text-status-error-text flex-shrink-0 mt-0.5",
|
|
286
286
|
fill: "none",
|
|
287
287
|
stroke: "currentColor",
|
|
288
288
|
viewBox: "0 0 24 24",
|
|
289
|
-
children: /* @__PURE__ */
|
|
289
|
+
children: /* @__PURE__ */ o("path", {
|
|
290
290
|
strokeLinecap: "round",
|
|
291
291
|
strokeLinejoin: "round",
|
|
292
292
|
strokeWidth: 2,
|
|
293
293
|
d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
294
294
|
})
|
|
295
|
-
}), /* @__PURE__ */
|
|
295
|
+
}), /* @__PURE__ */ o("p", {
|
|
296
296
|
className: "text-xs text-status-error-text",
|
|
297
297
|
children: d
|
|
298
298
|
})]
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { splitGuideEmphasis as e } from "./dashboardGuideSteps.js";
|
|
2
|
+
import { Fragment as t, memo as n, useId as r } from "react";
|
|
3
|
+
import { ArrowRight as i, ChevronDown as a, Database as o, FileCode2 as s, GraduationCap as c, LayoutDashboard as l, LayoutGrid as u, Lightbulb as d, Share2 as f, Sparkles as p, Upload as m } from "lucide-react";
|
|
4
|
+
import { Badge as h, Button as g } from "@burdenoff/fe-libs/ui";
|
|
5
|
+
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
6
|
+
//#region src/bigconsole/components/overview/DashboardGuide.tsx
|
|
7
|
+
var y = {
|
|
8
|
+
createDataSink: /* @__PURE__ */ _(o, {
|
|
9
|
+
className: "size-4",
|
|
10
|
+
"aria-hidden": "true"
|
|
11
|
+
}),
|
|
12
|
+
loadData: /* @__PURE__ */ _(m, {
|
|
13
|
+
className: "size-4",
|
|
14
|
+
"aria-hidden": "true"
|
|
15
|
+
}),
|
|
16
|
+
shapeWithParser: /* @__PURE__ */ _(s, {
|
|
17
|
+
className: "size-4",
|
|
18
|
+
"aria-hidden": "true"
|
|
19
|
+
}),
|
|
20
|
+
createDashboard: /* @__PURE__ */ _(l, {
|
|
21
|
+
className: "size-4",
|
|
22
|
+
"aria-hidden": "true"
|
|
23
|
+
}),
|
|
24
|
+
addWidgets: /* @__PURE__ */ _(u, {
|
|
25
|
+
className: "size-4",
|
|
26
|
+
"aria-hidden": "true"
|
|
27
|
+
}),
|
|
28
|
+
saveAndShare: /* @__PURE__ */ _(f, {
|
|
29
|
+
className: "size-4",
|
|
30
|
+
"aria-hidden": "true"
|
|
31
|
+
})
|
|
32
|
+
};
|
|
33
|
+
function b(n) {
|
|
34
|
+
return e(n).map((e, n) => e.emphasis ? /* @__PURE__ */ _("strong", {
|
|
35
|
+
className: "font-semibold text-text-primary",
|
|
36
|
+
children: e.text
|
|
37
|
+
}, n) : /* @__PURE__ */ _(t, { children: e.text }, n));
|
|
38
|
+
}
|
|
39
|
+
var x = ({ action: e, variant: t, onNavigate: n }) => /* @__PURE__ */ v(g, {
|
|
40
|
+
type: "button",
|
|
41
|
+
size: "sm",
|
|
42
|
+
variant: t,
|
|
43
|
+
onClick: () => n(e.path),
|
|
44
|
+
className: "min-h-11 sm:min-h-9",
|
|
45
|
+
children: [e.label, t === "default" ? /* @__PURE__ */ _(i, {
|
|
46
|
+
className: "size-4",
|
|
47
|
+
"aria-hidden": "true"
|
|
48
|
+
}) : null]
|
|
49
|
+
}), S = n(function({ step: e, number: t, optionalLabel: n, stepPrefix: r, onNavigate: i }) {
|
|
50
|
+
return /* @__PURE__ */ v("li", {
|
|
51
|
+
"data-tour": `bigconsole-overview-guide-step-${e.id}`,
|
|
52
|
+
"data-testid": `overview-guide-step-${e.id}`,
|
|
53
|
+
className: "flex h-full flex-col gap-3 rounded-card border border-[var(--color-border-seam)] bg-bg-canvas p-4",
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ v("div", {
|
|
56
|
+
className: "flex items-start gap-3",
|
|
57
|
+
children: [/* @__PURE__ */ _("span", {
|
|
58
|
+
"aria-hidden": "true",
|
|
59
|
+
className: "inline-flex size-8 shrink-0 items-center justify-center rounded-full bg-action-primary-bg text-sm font-semibold tabular-nums text-action-primary-text",
|
|
60
|
+
children: t
|
|
61
|
+
}), /* @__PURE__ */ v("div", {
|
|
62
|
+
className: "flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1 pt-1",
|
|
63
|
+
children: [
|
|
64
|
+
/* @__PURE__ */ _("span", {
|
|
65
|
+
className: "text-text-secondary",
|
|
66
|
+
children: y[e.id]
|
|
67
|
+
}),
|
|
68
|
+
/* @__PURE__ */ v("h3", {
|
|
69
|
+
className: "text-sm font-semibold text-text-primary",
|
|
70
|
+
children: [/* @__PURE__ */ _("span", {
|
|
71
|
+
className: "sr-only",
|
|
72
|
+
children: `${r} `
|
|
73
|
+
}), e.title]
|
|
74
|
+
}),
|
|
75
|
+
e.optional ? /* @__PURE__ */ _(h, {
|
|
76
|
+
variant: "secondary",
|
|
77
|
+
children: n
|
|
78
|
+
}) : null
|
|
79
|
+
]
|
|
80
|
+
})]
|
|
81
|
+
}),
|
|
82
|
+
/* @__PURE__ */ _("p", {
|
|
83
|
+
className: "text-sm leading-relaxed text-text-secondary",
|
|
84
|
+
children: b(e.body)
|
|
85
|
+
}),
|
|
86
|
+
e.tips.length > 0 ? /* @__PURE__ */ _("ul", {
|
|
87
|
+
className: "space-y-1.5",
|
|
88
|
+
children: e.tips.map((e) => /* @__PURE__ */ v("li", {
|
|
89
|
+
className: "flex gap-2 text-xs leading-relaxed text-text-secondary",
|
|
90
|
+
children: [/* @__PURE__ */ _(d, {
|
|
91
|
+
className: "mt-0.5 size-3.5 shrink-0 text-[var(--color-status-warning-text)]",
|
|
92
|
+
"aria-hidden": "true"
|
|
93
|
+
}), /* @__PURE__ */ _("span", { children: b(e) })]
|
|
94
|
+
}, e))
|
|
95
|
+
}) : null,
|
|
96
|
+
/* @__PURE__ */ v("div", {
|
|
97
|
+
className: "mt-auto space-y-1.5 pt-1",
|
|
98
|
+
children: [/* @__PURE__ */ v("div", {
|
|
99
|
+
className: "flex flex-wrap items-center gap-2",
|
|
100
|
+
children: [e.action ? /* @__PURE__ */ _(x, {
|
|
101
|
+
action: e.action,
|
|
102
|
+
variant: "default",
|
|
103
|
+
onNavigate: i
|
|
104
|
+
}) : e.noPermissionMessage ? /* @__PURE__ */ _("p", {
|
|
105
|
+
className: "text-xs text-text-muted",
|
|
106
|
+
children: e.noPermissionMessage
|
|
107
|
+
}) : null, e.secondaryAction ? /* @__PURE__ */ _(x, {
|
|
108
|
+
action: e.secondaryAction,
|
|
109
|
+
variant: "ghost",
|
|
110
|
+
onNavigate: i
|
|
111
|
+
}) : null]
|
|
112
|
+
}), e.action?.hint ? /* @__PURE__ */ _("p", {
|
|
113
|
+
className: "text-xs text-text-muted",
|
|
114
|
+
children: e.action.hint
|
|
115
|
+
}) : null]
|
|
116
|
+
})
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
}), C = n(function({ steps: e, alternative: n, labels: o, expanded: s, onToggle: l, onNavigate: u }) {
|
|
120
|
+
let d = r(), f = r();
|
|
121
|
+
return /* @__PURE__ */ v("section", {
|
|
122
|
+
"aria-labelledby": d,
|
|
123
|
+
"data-tour": "bigconsole-overview-guide",
|
|
124
|
+
"data-testid": "overview-guide",
|
|
125
|
+
className: "rounded-card border border-[var(--color-border-seam)] bg-bg-surface shadow-[var(--shadow-elevation-1)]",
|
|
126
|
+
children: [/* @__PURE__ */ v("div", {
|
|
127
|
+
className: "flex flex-col gap-3 p-5 sm:flex-row sm:items-center sm:justify-between",
|
|
128
|
+
children: [/* @__PURE__ */ v("div", {
|
|
129
|
+
className: "flex min-w-0 items-start gap-3",
|
|
130
|
+
children: [/* @__PURE__ */ _("span", {
|
|
131
|
+
"aria-hidden": "true",
|
|
132
|
+
className: "inline-flex size-10 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
|
|
133
|
+
children: /* @__PURE__ */ _(c, { className: "size-5" })
|
|
134
|
+
}), /* @__PURE__ */ v("div", {
|
|
135
|
+
className: "min-w-0",
|
|
136
|
+
children: [/* @__PURE__ */ _("h2", {
|
|
137
|
+
id: d,
|
|
138
|
+
className: "text-lg font-semibold tracking-tight text-text-primary",
|
|
139
|
+
children: o.title
|
|
140
|
+
}), /* @__PURE__ */ _("p", {
|
|
141
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
142
|
+
children: o.subtitle
|
|
143
|
+
})]
|
|
144
|
+
})]
|
|
145
|
+
}), /* @__PURE__ */ v(g, {
|
|
146
|
+
type: "button",
|
|
147
|
+
variant: "outline",
|
|
148
|
+
size: "sm",
|
|
149
|
+
onClick: l,
|
|
150
|
+
"aria-expanded": s,
|
|
151
|
+
"aria-controls": f,
|
|
152
|
+
className: "min-h-11 shrink-0 self-start sm:min-h-9 sm:self-center",
|
|
153
|
+
"data-testid": "overview-guide-toggle",
|
|
154
|
+
children: [s ? o.hide : o.show, /* @__PURE__ */ _(a, {
|
|
155
|
+
className: `size-4 transition-transform motion-reduce:transition-none ${s ? "rotate-180" : ""}`,
|
|
156
|
+
"aria-hidden": "true"
|
|
157
|
+
})]
|
|
158
|
+
})]
|
|
159
|
+
}), /* @__PURE__ */ v("div", {
|
|
160
|
+
id: f,
|
|
161
|
+
hidden: !s,
|
|
162
|
+
className: "space-y-5 border-t border-[var(--color-border-seam)] p-5",
|
|
163
|
+
children: [
|
|
164
|
+
/* @__PURE__ */ _("div", {
|
|
165
|
+
"aria-hidden": "true",
|
|
166
|
+
className: "flex flex-wrap items-center gap-2",
|
|
167
|
+
children: o.flow.map((e, n) => /* @__PURE__ */ v(t, { children: [n > 0 ? /* @__PURE__ */ _(i, { className: "size-3.5 text-text-muted" }) : null, /* @__PURE__ */ _("span", {
|
|
168
|
+
className: "rounded-pill border border-[var(--color-border-seam)] bg-bg-sunken px-2.5 py-1 text-xs font-medium text-text-secondary",
|
|
169
|
+
children: e
|
|
170
|
+
})] }, e))
|
|
171
|
+
}),
|
|
172
|
+
/* @__PURE__ */ _("ol", {
|
|
173
|
+
role: "list",
|
|
174
|
+
className: "grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3",
|
|
175
|
+
children: e.map((e, t) => /* @__PURE__ */ _(S, {
|
|
176
|
+
step: e,
|
|
177
|
+
number: t + 1,
|
|
178
|
+
optionalLabel: o.optional,
|
|
179
|
+
stepPrefix: o.stepPrefix(t + 1),
|
|
180
|
+
onNavigate: u
|
|
181
|
+
}, e.id))
|
|
182
|
+
}),
|
|
183
|
+
n ? /* @__PURE__ */ v("div", {
|
|
184
|
+
"data-testid": "overview-guide-ai",
|
|
185
|
+
className: "flex flex-col gap-3 rounded-card border border-dashed border-[var(--color-border-seam)] p-4 sm:flex-row sm:items-center sm:justify-between",
|
|
186
|
+
children: [/* @__PURE__ */ v("div", {
|
|
187
|
+
className: "flex min-w-0 items-start gap-3",
|
|
188
|
+
children: [/* @__PURE__ */ _(p, {
|
|
189
|
+
className: "mt-0.5 size-4 shrink-0 text-text-secondary",
|
|
190
|
+
"aria-hidden": "true"
|
|
191
|
+
}), /* @__PURE__ */ v("div", {
|
|
192
|
+
className: "min-w-0",
|
|
193
|
+
children: [/* @__PURE__ */ _("p", {
|
|
194
|
+
className: "text-sm font-semibold text-text-primary",
|
|
195
|
+
children: n.title
|
|
196
|
+
}), /* @__PURE__ */ _("p", {
|
|
197
|
+
className: "mt-1 text-sm leading-relaxed text-text-secondary",
|
|
198
|
+
children: b(n.body)
|
|
199
|
+
})]
|
|
200
|
+
})]
|
|
201
|
+
}), /* @__PURE__ */ _(x, {
|
|
202
|
+
action: n.action,
|
|
203
|
+
variant: "outline",
|
|
204
|
+
onNavigate: u
|
|
205
|
+
})]
|
|
206
|
+
}) : null
|
|
207
|
+
]
|
|
208
|
+
})]
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
//#endregion
|
|
212
|
+
export { C as default, b as renderGuideEmphasis };
|
|
213
|
+
|
|
214
|
+
//# sourceMappingURL=DashboardGuide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardGuide.js","names":[],"sources":["../../../../src/bigconsole/components/overview/DashboardGuide.tsx"],"sourcesContent":["/**\n * DashboardGuide\n *\n * \"How to create a complete dashboard, end to end\" — a numbered, deep-linked\n * walkthrough on the Overview. Props-only (no data fetching, no context): the\n * page builds the steps with `buildDashboardGuideSteps` and passes translated\n * labels, which keeps it renderable in tests and Storybook.\n *\n * It intentionally does not use fe-libs `NextSteps`: that component shows an\n * \"N to go\" counter that only decreases for steps marked `done`, and this guide\n * teaches the flow rather than tracking completion.\n */\n\nimport { type FC, type ReactNode, Fragment, memo, useId } from 'react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport {\n ArrowRight,\n ChevronDown,\n Database,\n FileCode2,\n GraduationCap,\n LayoutDashboard,\n LayoutGrid,\n Lightbulb,\n Share2,\n Sparkles,\n Upload,\n} from 'lucide-react';\nimport {\n splitGuideEmphasis,\n type GuideAction,\n type GuideAlternative,\n type GuideStep,\n type GuideStepId,\n} from './dashboardGuideSteps';\n\nexport interface DashboardGuideLabels {\n title: string;\n subtitle: string;\n show: string;\n hide: string;\n optional: string;\n /** Short names for the visual flow strip, in order. */\n flow: string[];\n /** Screen-reader prefix for a step heading, e.g. \"Step 2:\". */\n stepPrefix: (stepNumber: number) => string;\n}\n\nexport interface DashboardGuideProps {\n steps: GuideStep[];\n alternative?: GuideAlternative | null;\n labels: DashboardGuideLabels;\n expanded: boolean;\n onToggle: () => void;\n onNavigate: (path: string) => void;\n}\n\nconst STEP_ICONS: Record<GuideStepId, ReactNode> = {\n createDataSink: <Database className=\"size-4\" aria-hidden=\"true\" />,\n loadData: <Upload className=\"size-4\" aria-hidden=\"true\" />,\n shapeWithParser: <FileCode2 className=\"size-4\" aria-hidden=\"true\" />,\n createDashboard: <LayoutDashboard className=\"size-4\" aria-hidden=\"true\" />,\n addWidgets: <LayoutGrid className=\"size-4\" aria-hidden=\"true\" />,\n saveAndShare: <Share2 className=\"size-4\" aria-hidden=\"true\" />,\n};\n\n/** Render `**label**` markers as emphasised on-screen labels. */\nexport function renderGuideEmphasis(text: string): ReactNode {\n return splitGuideEmphasis(text).map((segment, index) =>\n segment.emphasis ? (\n <strong key={index} className=\"font-semibold text-text-primary\">\n {segment.text}\n </strong>\n ) : (\n <Fragment key={index}>{segment.text}</Fragment>\n )\n );\n}\n\nconst GuideActionButton: FC<{\n action: GuideAction;\n variant: 'default' | 'ghost' | 'outline';\n onNavigate: (path: string) => void;\n}> = ({ action, variant, onNavigate }) => (\n <Button\n type=\"button\"\n size=\"sm\"\n variant={variant}\n onClick={() => onNavigate(action.path)}\n className=\"min-h-11 sm:min-h-9\"\n >\n {action.label}\n {variant === 'default' ? <ArrowRight className=\"size-4\" aria-hidden=\"true\" /> : null}\n </Button>\n);\n\nconst GuideStepCard: FC<{\n step: GuideStep;\n number: number;\n optionalLabel: string;\n stepPrefix: string;\n onNavigate: (path: string) => void;\n}> = memo(function GuideStepCard({ step, number, optionalLabel, stepPrefix, onNavigate }) {\n return (\n <li\n data-tour={`bigconsole-overview-guide-step-${step.id}`}\n data-testid={`overview-guide-step-${step.id}`}\n className=\"flex h-full flex-col gap-3 rounded-card border border-[var(--color-border-seam)] bg-bg-canvas p-4\"\n >\n <div className=\"flex items-start gap-3\">\n <span\n aria-hidden=\"true\"\n className=\"inline-flex size-8 shrink-0 items-center justify-center rounded-full bg-action-primary-bg text-sm font-semibold tabular-nums text-action-primary-text\"\n >\n {number}\n </span>\n <div className=\"flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1 pt-1\">\n <span className=\"text-text-secondary\">{STEP_ICONS[step.id]}</span>\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {/* The number badge is decorative; the heading carries the step number. */}\n <span className=\"sr-only\">{`${stepPrefix} `}</span>\n {step.title}\n </h3>\n {step.optional ? <Badge variant=\"secondary\">{optionalLabel}</Badge> : null}\n </div>\n </div>\n\n <p className=\"text-sm leading-relaxed text-text-secondary\">{renderGuideEmphasis(step.body)}</p>\n\n {step.tips.length > 0 ? (\n <ul className=\"space-y-1.5\">\n {step.tips.map((tip) => (\n <li key={tip} className=\"flex gap-2 text-xs leading-relaxed text-text-secondary\">\n <Lightbulb\n className=\"mt-0.5 size-3.5 shrink-0 text-[var(--color-status-warning-text)]\"\n aria-hidden=\"true\"\n />\n <span>{renderGuideEmphasis(tip)}</span>\n </li>\n ))}\n </ul>\n ) : null}\n\n <div className=\"mt-auto space-y-1.5 pt-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {step.action ? (\n <GuideActionButton action={step.action} variant=\"default\" onNavigate={onNavigate} />\n ) : step.noPermissionMessage ? (\n <p className=\"text-xs text-text-muted\">{step.noPermissionMessage}</p>\n ) : null}\n {step.secondaryAction ? (\n <GuideActionButton action={step.secondaryAction} variant=\"ghost\" onNavigate={onNavigate} />\n ) : null}\n </div>\n {step.action?.hint ? <p className=\"text-xs text-text-muted\">{step.action.hint}</p> : null}\n </div>\n </li>\n );\n});\n\nexport const DashboardGuide: FC<DashboardGuideProps> = memo(function DashboardGuide({\n steps,\n alternative,\n labels,\n expanded,\n onToggle,\n onNavigate,\n}) {\n const headingId = useId();\n const bodyId = useId();\n\n return (\n <section\n aria-labelledby={headingId}\n data-tour=\"bigconsole-overview-guide\"\n data-testid=\"overview-guide\"\n className=\"rounded-card border border-[var(--color-border-seam)] bg-bg-surface shadow-[var(--shadow-elevation-1)]\"\n >\n <div className=\"flex flex-col gap-3 p-5 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n aria-hidden=\"true\"\n className=\"inline-flex size-10 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\"\n >\n <GraduationCap className=\"size-5\" />\n </span>\n <div className=\"min-w-0\">\n <h2 id={headingId} className=\"text-lg font-semibold tracking-tight text-text-primary\">\n {labels.title}\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">{labels.subtitle}</p>\n </div>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onToggle}\n aria-expanded={expanded}\n aria-controls={bodyId}\n className=\"min-h-11 shrink-0 self-start sm:min-h-9 sm:self-center\"\n data-testid=\"overview-guide-toggle\"\n >\n {expanded ? labels.hide : labels.show}\n <ChevronDown\n className={`size-4 transition-transform motion-reduce:transition-none ${expanded ? 'rotate-180' : ''}`}\n aria-hidden=\"true\"\n />\n </Button>\n </div>\n\n {/* Kept in the DOM (hidden when collapsed) so aria-controls always\n references an element. */}\n <div id={bodyId} hidden={!expanded} className=\"space-y-5 border-t border-[var(--color-border-seam)] p-5\">\n {/* Visual summary of the flow. Decorative: the numbered step headings\n below carry the same information for assistive technology. */}\n <div aria-hidden=\"true\" className=\"flex flex-wrap items-center gap-2\">\n {labels.flow.map((name, index) => (\n <Fragment key={name}>\n {index > 0 ? <ArrowRight className=\"size-3.5 text-text-muted\" /> : null}\n <span className=\"rounded-pill border border-[var(--color-border-seam)] bg-bg-sunken px-2.5 py-1 text-xs font-medium text-text-secondary\">\n {name}\n </span>\n </Fragment>\n ))}\n </div>\n\n {/* role=\"list\": WebKit drops list semantics from unstyled lists. */}\n <ol role=\"list\" className=\"grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {steps.map((step, index) => (\n <GuideStepCard\n key={step.id}\n step={step}\n number={index + 1}\n optionalLabel={labels.optional}\n stepPrefix={labels.stepPrefix(index + 1)}\n onNavigate={onNavigate}\n />\n ))}\n </ol>\n\n {alternative ? (\n <div\n data-testid=\"overview-guide-ai\"\n className=\"flex flex-col gap-3 rounded-card border border-dashed border-[var(--color-border-seam)] p-4 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"flex min-w-0 items-start gap-3\">\n <Sparkles className=\"mt-0.5 size-4 shrink-0 text-text-secondary\" aria-hidden=\"true\" />\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">{alternative.title}</p>\n <p className=\"mt-1 text-sm leading-relaxed text-text-secondary\">\n {renderGuideEmphasis(alternative.body)}\n </p>\n </div>\n </div>\n <GuideActionButton action={alternative.action} variant=\"outline\" onNavigate={onNavigate} />\n </div>\n ) : null}\n </div>\n </section>\n );\n});\n\nexport default DashboardGuide;\n"],"mappings":"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"}
|