@burdenoff/microfe-bigconsole 2026.805.1 → 2026.805.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bigconsole/AdminRoot.js +21 -16
- package/dist/bigconsole/AdminRoot.js.map +1 -1
- package/dist/bigconsole/BigConsoleRoot.js +44 -39
- package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +109 -113
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +115 -113
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +71 -62
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +116 -100
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +56 -54
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +126 -125
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +151 -150
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +77 -76
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +97 -96
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +172 -191
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +100 -98
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +75 -83
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +151 -154
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +187 -193
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
- package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -0
- package/dist/bigconsole/components/dashboard/WidgetPalette.js +110 -108
- package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +102 -103
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +20 -20
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +36 -41
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +38 -37
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +113 -117
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +182 -197
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +166 -168
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/DataSinkSelector.js +87 -86
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ImportParserDialog.js +196 -211
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +130 -128
- package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +66 -63
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +95 -91
- package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +243 -230
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +149 -145
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +504 -470
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js +87 -76
- package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +44 -47
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js +143 -142
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +101 -88
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +135 -134
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
- package/dist/bigconsole/components/widgets/form/FormWidget.js +167 -159
- package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +69 -68
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +64 -72
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +60 -59
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListConfig.js +57 -56
- package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +70 -69
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +35 -34
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +20 -19
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +178 -177
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +76 -75
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js +183 -168
- package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +187 -180
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +120 -118
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +40 -38
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +150 -148
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +189 -175
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +200 -187
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +379 -324
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +185 -178
- package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +195 -170
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +224 -200
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +281 -268
- package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSourcesPage.js +8 -7
- package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
- package/dist/bigconsole/pages/InsightsPage.js +238 -208
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +480 -413
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +192 -172
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +198 -163
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +138 -133
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +162 -136
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/SettingsPage.js +177 -172
- package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
- package/dist/bigconsole/pages/WidgetDemoPage.js +121 -83
- package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +269 -242
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +153 -138
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +111 -109
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +127 -126
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js +103 -103
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
- package/dist/constants/permissions.js +83 -0
- package/dist/constants/permissions.js.map +1 -0
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImportDashboardDialog.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/ImportDashboardDialog.tsx"],"sourcesContent":["/**\n * ImportDashboardDialog Component\n *\n * Modal dialog for importing a dashboard from JSON file.\n * Supports both creating new dashboards and updating existing ones.\n * Uses fe-libs shared UI components for consistent styling.\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 { Checkbox } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Upload, FileJson, Check, AlertTriangle, XCircle, ArrowLeft, RefreshCw, Info } from 'lucide-react';\nimport { useImportDashboard, type ImportDashboardOptions } from '../../hooks';\nimport { useBigConsoleAnalytics } from '../../hooks/useBigConsoleAnalytics';\nimport { reportBigConsoleQuotaError } from '../../utils/quota';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ImportDashboardDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess?: (dashboardId: string, dashboardName: string, originalUpdated: boolean) => void;\n}\n\ntype ImportStep = 'select' | 'preview' | 'importing' | 'complete';\n\n// ============================================================================\n// Helper: Extract dashboard ID from content\n// ============================================================================\n\nfunction extractDashboardId(content: string | null): string | null {\n if (!content) return null;\n try {\n const parsed = JSON.parse(content);\n return parsed.exportedFrom?.dashboardId || parsed.dashboard?.id || null;\n } catch {\n return null;\n }\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ImportDashboardDialog: FC<ImportDashboardDialogProps> = memo(function ImportDashboardDialog({\n isOpen,\n onClose,\n onSuccess,\n}) {\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 [visibility, setVisibility] = useState<'PRIVATE' | 'TEAM' | 'PUBLIC'>('PRIVATE');\n const [skipWarnings, setSkipWarnings] = useState(false);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const { loading, error, validationResult, importResult, validateImport, importDashboard, clearState } =\n useImportDashboard();\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 setVisibility('PRIVATE');\n setSkipWarnings(false);\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('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 = await validateImport(content);\n if (result) {\n setStep('preview');\n if (result.dashboardInfo?.name) {\n setNameOverride(result.dashboardInfo.name);\n }\n }\n };\n reader.onerror = () => {\n alert('Failed to read file');\n };\n reader.readAsText(file);\n },\n [validateImport]\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: ImportDashboardOptions = {\n name: nameOverride.trim() || undefined,\n visibility,\n skipWarnings,\n };\n\n emitBigConsoleEvent('bigconsole.dashboard.import_clicked', { source: 'import' });\n\n try {\n const result = await importDashboard(fileContent, options);\n\n if (result?.success && result.dashboard) {\n setStep('complete');\n emitBigConsoleEvent('bigconsole.dashboard.imported', {\n dashboardId: result.dashboard.id,\n source: 'import',\n originalUpdated: result.originalUpdated ?? false,\n });\n onSuccess?.(result.dashboard.id, result.dashboard.name, result.originalUpdated ?? false);\n } else {\n setStep('preview');\n }\n } catch (err) {\n if (reportBigConsoleQuotaError(err, 'project')) {\n onClose();\n return;\n }\n setStep('preview');\n }\n }, [emitBigConsoleEvent, fileContent, importDashboard, nameOverride, onClose, onSuccess, skipWarnings, visibility]);\n\n const canClose = !loading && step !== 'importing';\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && canClose && onClose()}>\n <DialogContent className=\"sm:max-w-lg max-h-[85vh] flex flex-col\">\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-lg bg-action-primary-bg/10\">\n <Upload className=\"size-5 text-primary\" />\n </div>\n <DialogTitle>Import Dashboard</DialogTitle>\n </div>\n <DialogDescription>Upload a Dashboard export file to restore it into this workspace.</DialogDescription>\n </DialogHeader>\n\n <div className=\"flex-1 overflow-y-auto py-4 space-y-4\">\n {/* Step 1: File Selection */}\n {step === 'select' && (\n <div\n onDragOver={(e) => e.preventDefault()}\n onDrop={handleDrop}\n className=\"border-2 border-dashed rounded-lg p-8 text-center hover:border-primary transition-colors\"\n >\n <FileJson className=\"size-12 mx-auto text-text-secondary mb-4\" />\n <p className=\"text-sm mb-2\">Drag and drop a dashboard export file here</p>\n <p className=\"text-xs text-text-secondary mb-4\">or</p>\n <input ref={fileInputRef} type=\"file\" accept=\".json\" onChange={handleFileSelect} className=\"hidden\" />\n <Button onClick={() => fileInputRef.current?.click()} disabled={loading}>\n Browse Files\n </Button>\n <p className=\"text-xs text-text-secondary mt-4\">\n Only .json files exported from BigConsole are supported\n </p>\n </div>\n )}\n\n {/* Step 2: Preview & Options */}\n {(step === 'preview' || step === 'importing') && validationResult && (\n <>\n {/* Dashboard Info */}\n <Card>\n <CardContent className=\"p-4 space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">Dashboard</span>\n <span className=\"text-sm font-medium\">{validationResult.dashboardInfo.name}</span>\n </div>\n {validationResult.dashboardInfo.description && (\n <div className=\"flex items-start justify-between\">\n <span className=\"text-sm text-text-secondary\">Description</span>\n <span className=\"text-sm text-right max-w-[60%] truncate\">\n {validationResult.dashboardInfo.description}\n </span>\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">Pages</span>\n <Badge variant=\"secondary\">{validationResult.dashboardInfo.pageCount}</Badge>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">Widgets</span>\n <Badge variant=\"secondary\">{validationResult.dashboardInfo.widgetCount}</Badge>\n </div>\n {validationResult.dashboardInfo.exportedFrom && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">Source ID</span>\n <span className=\"text-xs text-text-secondary font-mono truncate max-w-[180px]\">\n {validationResult.dashboardInfo.exportedFrom}\n </span>\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">Schema Version</span>\n <span className=\"text-xs text-text-secondary\">{validationResult.dashboardInfo.schemaVersion}</span>\n </div>\n </CardContent>\n </Card>\n\n {/* Validation Errors */}\n {validationResult.errors.length > 0 && (\n <Card className=\"border-status-error-border/50 bg-status-error-bg/5\">\n <CardContent className=\"p-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <XCircle className=\"size-4 text-status-error-text\" />\n <span className=\"text-sm font-medium text-status-error-text\">\n Errors ({validationResult.errors.length})\n </span>\n </div>\n <ul className=\"text-xs text-status-error-text space-y-1\">\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 </CardContent>\n </Card>\n )}\n\n {/* Validation Warnings */}\n {validationResult.warnings.length > 0 && (\n <Card className=\"border-yellow-500/50 bg-yellow-500/5\">\n <CardContent className=\"p-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <AlertTriangle className=\"size-4 text-yellow-600\" />\n <span className=\"text-sm font-medium text-yellow-600\">\n Warnings ({validationResult.warnings.length})\n </span>\n </div>\n <ul className=\"text-xs text-yellow-600 space-y-1\">\n {validationResult.warnings.map((warn, idx) => (\n <li key={idx}>\n <span className=\"font-mono\">[{warn.code}]</span> {warn.message}\n </li>\n ))}\n </ul>\n </CardContent>\n </Card>\n )}\n\n {/* Import Options */}\n {validationResult.isValid && (\n <div className=\"space-y-4\">\n <p className=\"text-sm font-medium\">Import Options</p>\n\n {/* Import Info */}\n <Card className=\"border-blue-500/50 bg-blue-500/5\">\n <CardContent className=\"p-3\">\n <div className=\"flex items-start gap-2\">\n <Info className=\"size-4 text-blue-600 mt-0.5 shrink-0\" />\n <div className=\"text-xs text-blue-700 dark:text-blue-400\">\n {extractDashboardId(fileContent) ? (\n <>\n <p className=\"font-medium mb-1\">Import will check for existing dashboard</p>\n <p>\n If the original dashboard (ID:{' '}\n <code className=\"font-mono bg-blue-200/50 px-1 rounded\">\n {extractDashboardId(fileContent)?.slice(0, 8)}...\n </code>\n ) exists:\n </p>\n <ul className=\"list-disc list-inside mt-1 space-y-0.5\">\n <li>With changes → Update the existing dashboard</li>\n <li>No changes → Show "already exists" message</li>\n </ul>\n <p className=\"mt-1\">If original doesn't exist → Create a new dashboard</p>\n </>\n ) : (\n <>\n <p className=\"font-medium mb-1\">A new dashboard will be created</p>\n <p>Import as a new dashboard with the specified configuration.</p>\n </>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-name\">Dashboard Name</Label>\n <Input\n id=\"import-name\"\n type=\"text\"\n value={nameOverride}\n onChange={(e) => setNameOverride(e.target.value)}\n placeholder={validationResult.dashboardInfo.name}\n disabled={step === 'importing'}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label>Visibility</Label>\n <div className=\"flex gap-2\">\n {(['PRIVATE', 'TEAM', 'PUBLIC'] as const).map((v) => (\n <Button\n key={v}\n type=\"button\"\n variant={visibility === v ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setVisibility(v)}\n disabled={step === 'importing'}\n >\n {v.charAt(0) + v.slice(1).toLowerCase()}\n </Button>\n ))}\n </div>\n </div>\n\n {validationResult.warnings.length > 0 && (\n <div className=\"flex items-start space-x-3\">\n <Checkbox\n id=\"skipWarnings\"\n checked={skipWarnings}\n onCheckedChange={(checked) => setSkipWarnings(checked === true)}\n disabled={step === 'importing'}\n />\n <div className=\"grid gap-1.5 leading-none\">\n <Label htmlFor=\"skipWarnings\" className=\"cursor-pointer\">\n Acknowledge warnings and proceed\n </Label>\n </div>\n </div>\n )}\n </div>\n )}\n </>\n )}\n\n {/* Step 3: Complete */}\n {step === 'complete' && importResult?.success && (\n <div className=\"text-center py-6\">\n {/* Already Exists - No Changes */}\n {importResult.alreadyExists && (\n <>\n <div className=\"size-16 mx-auto mb-4 rounded-full bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center\">\n <Info className=\"size-8 text-blue-600\" />\n </div>\n <h3 className=\"text-lg font-medium mb-2\">Dashboard Already Exists</h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n Dashboard "{importResult.dashboard?.name}" already exists with the same data. No changes\n were made.\n </p>\n </>\n )}\n\n {/* Updated Existing */}\n {importResult.originalUpdated && !importResult.alreadyExists && (\n <>\n <div className=\"size-16 mx-auto mb-4 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center\">\n <RefreshCw className=\"size-8 text-green-600\" />\n </div>\n <h3 className=\"text-lg font-medium mb-2\">Dashboard Updated!</h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n Dashboard "{importResult.dashboard?.name}" has been updated with the imported data.\n </p>\n </>\n )}\n\n {/* Created New */}\n {!importResult.originalUpdated && !importResult.alreadyExists && (\n <>\n <div className=\"size-16 mx-auto mb-4 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center\">\n <Check className=\"size-8 text-green-600\" />\n </div>\n <h3 className=\"text-lg font-medium mb-2\">Import Successful!</h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n Dashboard "{importResult.dashboard?.name}" has been created.\n </p>\n\n {importResult.stats && (\n <Card className=\"inline-block text-left\">\n <CardContent className=\"p-4\">\n <p className=\"text-xs font-medium text-text-secondary mb-2\">Import Summary</p>\n <div className=\"grid grid-cols-2 gap-x-6 gap-y-1 text-xs\">\n <span className=\"text-text-secondary\">Pages:</span>\n <span>{importResult.stats.pagesCreated}</span>\n <span className=\"text-text-secondary\">Widgets:</span>\n <span>{importResult.stats.widgetsCreated}</span>\n <span className=\"text-text-secondary\">Actions:</span>\n <span>{importResult.stats.actionsCreated}</span>\n </div>\n </CardContent>\n </Card>\n )}\n </>\n )}\n </div>\n )}\n\n {/* Error */}\n {error && (\n <Card className=\"border-status-error-border/50 bg-status-error-bg/5\">\n <CardContent className=\"p-3\">\n <p className=\"text-sm text-status-error-text\">{error.message}</p>\n </CardContent>\n </Card>\n )}\n\n {importResult && !importResult.success && importResult.errorMessage && (\n <Card className=\"border-status-error-border/50 bg-status-error-bg/5\">\n <CardContent className=\"p-3\">\n <p className=\"text-sm text-status-error-text\">{importResult.errorMessage}</p>\n </CardContent>\n </Card>\n )}\n </div>\n\n <DialogFooter className=\"flex-row justify-between sm:justify-between\">\n <div>\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 Back\n </Button>\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n {step !== 'complete' && (\n <Button variant=\"outline\" onClick={onClose} disabled={!canClose}>\n Cancel\n </Button>\n )}\n\n {step === 'preview' && validationResult?.isValid && (\n <Button\n onClick={handleImport}\n disabled={loading || (validationResult.warnings.length > 0 && !skipWarnings)}\n >\n <Upload className=\"size-4\" />\n Import Dashboard\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 Importing...\n </div>\n )}\n\n {step === 'complete' && <Button onClick={onClose}>Done</Button>}\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default ImportDashboardDialog;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ImportDashboardDialog.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/ImportDashboardDialog.tsx"],"sourcesContent":["/**\n * ImportDashboardDialog Component\n *\n * Modal dialog for importing a dashboard from JSON file.\n * Supports both creating new dashboards and updating existing ones.\n * Uses fe-libs shared UI components for consistent styling.\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 { Checkbox } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Upload, FileJson, Check, AlertTriangle, XCircle, ArrowLeft, RefreshCw, Info } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useImportDashboard, type ImportDashboardOptions } from '../../hooks';\nimport { useBigConsoleAnalytics } from '../../hooks/useBigConsoleAnalytics';\nimport { reportBigConsoleQuotaError } from '../../utils/quota';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ImportDashboardDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess?: (dashboardId: string, dashboardName: string, originalUpdated: boolean) => void;\n}\n\ntype ImportStep = 'select' | 'preview' | 'importing' | 'complete';\n\n// ============================================================================\n// Helper: Extract dashboard ID from content\n// ============================================================================\n\nfunction extractDashboardId(content: string | null): string | null {\n if (!content) return null;\n try {\n const parsed = JSON.parse(content);\n return parsed.exportedFrom?.dashboardId || parsed.dashboard?.id || null;\n } catch {\n return null;\n }\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ImportDashboardDialog: FC<ImportDashboardDialogProps> = memo(function ImportDashboardDialog({\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 [visibility, setVisibility] = useState<'PRIVATE' | 'TEAM' | 'PUBLIC'>('PRIVATE');\n const [skipWarnings, setSkipWarnings] = useState(false);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const { loading, error, validationResult, importResult, validateImport, importDashboard, clearState } =\n useImportDashboard();\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 setVisibility('PRIVATE');\n setSkipWarnings(false);\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.dashboards.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 = await validateImport(content);\n if (result) {\n setStep('preview');\n if (result.dashboardInfo?.name) {\n setNameOverride(result.dashboardInfo.name);\n }\n }\n };\n reader.onerror = () => {\n alert(t('bigconsole.dashboards.import.failedToReadFile', '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: ImportDashboardOptions = {\n name: nameOverride.trim() || undefined,\n visibility,\n skipWarnings,\n };\n\n emitBigConsoleEvent('bigconsole.dashboard.import_clicked', { source: 'import' });\n\n try {\n const result = await importDashboard(fileContent, options);\n\n if (result?.success && result.dashboard) {\n setStep('complete');\n emitBigConsoleEvent('bigconsole.dashboard.imported', {\n dashboardId: result.dashboard.id,\n source: 'import',\n originalUpdated: result.originalUpdated ?? false,\n });\n onSuccess?.(result.dashboard.id, result.dashboard.name, result.originalUpdated ?? false);\n } else {\n setStep('preview');\n }\n } catch (err) {\n if (reportBigConsoleQuotaError(err, 'project')) {\n onClose();\n return;\n }\n setStep('preview');\n }\n }, [emitBigConsoleEvent, fileContent, importDashboard, nameOverride, onClose, onSuccess, skipWarnings, visibility]);\n\n const canClose = !loading && step !== 'importing';\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && canClose && onClose()}>\n <DialogContent className=\"sm:max-w-lg max-h-[85vh] flex flex-col\">\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-lg bg-action-primary-bg/10\">\n <Upload className=\"size-5 text-primary\" />\n </div>\n <DialogTitle>{t('bigconsole.dashboards.import.title', 'Import Dashboard')}</DialogTitle>\n </div>\n <DialogDescription>\n {t(\n 'bigconsole.dashboards.import.description',\n 'Upload a Dashboard export file to restore it into this workspace.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex-1 overflow-y-auto py-4 space-y-4\">\n {/* Step 1: File Selection */}\n {step === 'select' && (\n <div\n onDragOver={(e) => e.preventDefault()}\n onDrop={handleDrop}\n className=\"border-2 border-dashed rounded-lg p-8 text-center hover:border-primary transition-colors\"\n >\n <FileJson className=\"size-12 mx-auto text-text-secondary mb-4\" />\n <p className=\"text-sm mb-2\">\n {t('bigconsole.dashboards.import.dropzoneTitle', 'Drag and drop a dashboard export file here')}\n </p>\n <p className=\"text-xs text-text-secondary mb-4\">{t('bigconsole.dashboards.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.dashboards.import.browseFiles', 'Browse Files')}\n </Button>\n <p className=\"text-xs text-text-secondary mt-4\">\n {t(\n 'bigconsole.dashboards.import.supportedFilesHint',\n 'Only .json files exported from BigConsole are supported'\n )}\n </p>\n </div>\n )}\n\n {/* Step 2: Preview & Options */}\n {(step === 'preview' || step === 'importing') && validationResult && (\n <>\n {/* Dashboard Info */}\n <Card>\n <CardContent className=\"p-4 space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dashboards.import.fieldDashboard', 'Dashboard')}\n </span>\n <span className=\"text-sm font-medium\">{validationResult.dashboardInfo.name}</span>\n </div>\n {validationResult.dashboardInfo.description && (\n <div className=\"flex items-start justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dashboards.import.fieldDescription', 'Description')}\n </span>\n <span className=\"text-sm text-right max-w-[60%] truncate\">\n {validationResult.dashboardInfo.description}\n </span>\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dashboards.import.fieldPages', 'Pages')}\n </span>\n <Badge variant=\"secondary\">{validationResult.dashboardInfo.pageCount}</Badge>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dashboards.import.fieldWidgets', 'Widgets')}\n </span>\n <Badge variant=\"secondary\">{validationResult.dashboardInfo.widgetCount}</Badge>\n </div>\n {validationResult.dashboardInfo.exportedFrom && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dashboards.import.fieldSourceId', 'Source ID')}\n </span>\n <span className=\"text-xs text-text-secondary font-mono truncate max-w-[180px]\">\n {validationResult.dashboardInfo.exportedFrom}\n </span>\n </div>\n )}\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dashboards.import.fieldSchemaVersion', 'Schema Version')}\n </span>\n <span className=\"text-xs text-text-secondary\">{validationResult.dashboardInfo.schemaVersion}</span>\n </div>\n </CardContent>\n </Card>\n\n {/* Validation Errors */}\n {validationResult.errors.length > 0 && (\n <Card className=\"border-status-error-border/50 bg-status-error-bg/5\">\n <CardContent className=\"p-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <XCircle className=\"size-4 text-status-error-text\" />\n <span className=\"text-sm font-medium text-status-error-text\">\n {t('bigconsole.dashboards.import.errorsCount', 'Errors ({{count}})', {\n count: validationResult.errors.length,\n })}\n </span>\n </div>\n <ul className=\"text-xs text-status-error-text space-y-1\">\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 </CardContent>\n </Card>\n )}\n\n {/* Validation Warnings */}\n {validationResult.warnings.length > 0 && (\n <Card className=\"border-yellow-500/50 bg-yellow-500/5\">\n <CardContent className=\"p-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <AlertTriangle className=\"size-4 text-yellow-600\" />\n <span className=\"text-sm font-medium text-yellow-600\">\n {t('bigconsole.dashboards.import.warningsCount', 'Warnings ({{count}})', {\n count: validationResult.warnings.length,\n })}\n </span>\n </div>\n <ul className=\"text-xs text-yellow-600 space-y-1\">\n {validationResult.warnings.map((warn, idx) => (\n <li key={idx}>\n <span className=\"font-mono\">[{warn.code}]</span> {warn.message}\n </li>\n ))}\n </ul>\n </CardContent>\n </Card>\n )}\n\n {/* Import Options */}\n {validationResult.isValid && (\n <div className=\"space-y-4\">\n <p className=\"text-sm font-medium\">\n {t('bigconsole.dashboards.import.optionsTitle', 'Import Options')}\n </p>\n\n {/* Import Info */}\n <Card className=\"border-blue-500/50 bg-blue-500/5\">\n <CardContent className=\"p-3\">\n <div className=\"flex items-start gap-2\">\n <Info className=\"size-4 text-blue-600 mt-0.5 shrink-0\" />\n <div className=\"text-xs text-blue-700 dark:text-blue-400\">\n {extractDashboardId(fileContent) ? (\n <>\n <p className=\"font-medium mb-1\">\n {t(\n 'bigconsole.dashboards.import.checkExistingTitle',\n 'Import will check for existing dashboard'\n )}\n </p>\n <p>\n {t(\n 'bigconsole.dashboards.import.checkExistingIdPrefix',\n 'If the original dashboard (ID:'\n )}{' '}\n <code className=\"font-mono bg-blue-200/50 px-1 rounded\">\n {extractDashboardId(fileContent)?.slice(0, 8)}...\n </code>\n {t('bigconsole.dashboards.import.checkExistingIdSuffix', ') exists:')}\n </p>\n <ul className=\"list-disc list-inside mt-1 space-y-0.5\">\n <li>\n {t(\n 'bigconsole.dashboards.import.checkExistingWithChanges',\n 'With changes → Update the existing dashboard'\n )}\n </li>\n <li>\n {t(\n 'bigconsole.dashboards.import.checkExistingNoChanges',\n 'No changes → Show \"already exists\" message'\n )}\n </li>\n </ul>\n <p className=\"mt-1\">\n {t(\n 'bigconsole.dashboards.import.checkExistingNotFound',\n \"If original doesn't exist → Create a new dashboard\"\n )}\n </p>\n </>\n ) : (\n <>\n <p className=\"font-medium mb-1\">\n {t('bigconsole.dashboards.import.newDashboardTitle', 'A new dashboard will be created')}\n </p>\n <p>\n {t(\n 'bigconsole.dashboards.import.newDashboardBody',\n 'Import as a new dashboard with the specified configuration.'\n )}\n </p>\n </>\n )}\n </div>\n </div>\n </CardContent>\n </Card>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-name\">\n {t('bigconsole.dashboards.import.dashboardNameLabel', 'Dashboard Name')}\n </Label>\n <Input\n id=\"import-name\"\n type=\"text\"\n value={nameOverride}\n onChange={(e) => setNameOverride(e.target.value)}\n placeholder={validationResult.dashboardInfo.name}\n disabled={step === 'importing'}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label>{t('bigconsole.dashboards.import.visibilityLabel', 'Visibility')}</Label>\n <div className=\"flex gap-2\">\n {(['PRIVATE', 'TEAM', 'PUBLIC'] as const).map((v) => (\n <Button\n key={v}\n type=\"button\"\n variant={visibility === v ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setVisibility(v)}\n disabled={step === 'importing'}\n >\n {v === 'PRIVATE'\n ? t('bigconsole.dashboards.import.visibilityPrivate', 'Private')\n : v === 'TEAM'\n ? t('bigconsole.dashboards.import.visibilityTeam', 'Team')\n : t('bigconsole.dashboards.import.visibilityPublic', 'Public')}\n </Button>\n ))}\n </div>\n </div>\n\n {validationResult.warnings.length > 0 && (\n <div className=\"flex items-start space-x-3\">\n <Checkbox\n id=\"skipWarnings\"\n checked={skipWarnings}\n onCheckedChange={(checked) => setSkipWarnings(checked === true)}\n disabled={step === 'importing'}\n />\n <div className=\"grid gap-1.5 leading-none\">\n <Label htmlFor=\"skipWarnings\" className=\"cursor-pointer\">\n {t('bigconsole.dashboards.import.acknowledgeWarnings', 'Acknowledge warnings and proceed')}\n </Label>\n </div>\n </div>\n )}\n </div>\n )}\n </>\n )}\n\n {/* Step 3: Complete */}\n {step === 'complete' && importResult?.success && (\n <div className=\"text-center py-6\">\n {/* Already Exists - No Changes */}\n {importResult.alreadyExists && (\n <>\n <div className=\"size-16 mx-auto mb-4 rounded-full bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center\">\n <Info className=\"size-8 text-blue-600\" />\n </div>\n <h3 className=\"text-lg font-medium mb-2\">\n {t('bigconsole.dashboards.import.alreadyExistsTitle', 'Dashboard Already Exists')}\n </h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n {t(\n 'bigconsole.dashboards.import.alreadyExistsBody',\n 'Dashboard \"{{name}}\" already exists with the same data. No changes were made.',\n { name: importResult.dashboard?.name ?? '' }\n )}\n </p>\n </>\n )}\n\n {/* Updated Existing */}\n {importResult.originalUpdated && !importResult.alreadyExists && (\n <>\n <div className=\"size-16 mx-auto mb-4 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center\">\n <RefreshCw className=\"size-8 text-green-600\" />\n </div>\n <h3 className=\"text-lg font-medium mb-2\">\n {t('bigconsole.dashboards.import.updatedTitle', 'Dashboard Updated!')}\n </h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n {t(\n 'bigconsole.dashboards.import.updatedBody',\n 'Dashboard \"{{name}}\" has been updated with the imported data.',\n { name: importResult.dashboard?.name ?? '' }\n )}\n </p>\n </>\n )}\n\n {/* Created New */}\n {!importResult.originalUpdated && !importResult.alreadyExists && (\n <>\n <div className=\"size-16 mx-auto mb-4 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center\">\n <Check className=\"size-8 text-green-600\" />\n </div>\n <h3 className=\"text-lg font-medium mb-2\">\n {t('bigconsole.dashboards.import.successTitle', 'Import Successful!')}\n </h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n {t('bigconsole.dashboards.import.successBody', 'Dashboard \"{{name}}\" has been created.', {\n name: importResult.dashboard?.name ?? '',\n })}\n </p>\n\n {importResult.stats && (\n <Card className=\"inline-block text-left\">\n <CardContent className=\"p-4\">\n <p className=\"text-xs font-medium text-text-secondary mb-2\">\n {t('bigconsole.dashboards.import.summaryTitle', 'Import Summary')}\n </p>\n <div className=\"grid grid-cols-2 gap-x-6 gap-y-1 text-xs\">\n <span className=\"text-text-secondary\">\n {t('bigconsole.dashboards.import.summaryPages', 'Pages:')}\n </span>\n <span>{importResult.stats.pagesCreated}</span>\n <span className=\"text-text-secondary\">\n {t('bigconsole.dashboards.import.summaryWidgets', 'Widgets:')}\n </span>\n <span>{importResult.stats.widgetsCreated}</span>\n <span className=\"text-text-secondary\">\n {t('bigconsole.dashboards.import.summaryActions', 'Actions:')}\n </span>\n <span>{importResult.stats.actionsCreated}</span>\n </div>\n </CardContent>\n </Card>\n )}\n </>\n )}\n </div>\n )}\n\n {/* Error */}\n {error && (\n <Card className=\"border-status-error-border/50 bg-status-error-bg/5\">\n <CardContent className=\"p-3\">\n <p className=\"text-sm text-status-error-text\">{error.message}</p>\n </CardContent>\n </Card>\n )}\n\n {importResult && !importResult.success && importResult.errorMessage && (\n <Card className=\"border-status-error-border/50 bg-status-error-bg/5\">\n <CardContent className=\"p-3\">\n <p className=\"text-sm text-status-error-text\">{importResult.errorMessage}</p>\n </CardContent>\n </Card>\n )}\n </div>\n\n <DialogFooter className=\"flex-row justify-between sm:justify-between\">\n <div>\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.dashboards.import.back', 'Back')}\n </Button>\n )}\n </div>\n\n <div className=\"flex items-center gap-2\">\n {step !== 'complete' && (\n <Button variant=\"outline\" onClick={onClose} disabled={!canClose}>\n {t('bigconsole.dashboards.import.cancel', 'Cancel')}\n </Button>\n )}\n\n {step === 'preview' && validationResult?.isValid && (\n <Button\n onClick={handleImport}\n disabled={loading || (validationResult.warnings.length > 0 && !skipWarnings)}\n >\n <Upload className=\"size-4\" />\n {t('bigconsole.dashboards.import.importButton', 'Import Dashboard')}\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.dashboards.import.importing', 'Importing...')}\n </div>\n )}\n\n {step === 'complete' && <Button onClick={onClose}>{t('bigconsole.dashboards.import.done', 'Done')}</Button>}\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default ImportDashboardDialog;\n"],"mappings":"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"}
|
|
@@ -1,137 +1,139 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { BIGCONSOLE_PERMISSIONS as e } from "../../../../constants/permissions.js";
|
|
2
|
+
import { SEMANTIC_COLORS as t } from "../../../utils/semanticTokens.js";
|
|
3
|
+
import { useCallback as n, useEffect as r, useRef as i, useState as a } from "react";
|
|
4
|
+
import { usePermissions as o } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
5
|
+
import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
6
|
+
import { createPortal as u } from "react-dom";
|
|
5
7
|
//#region src/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.tsx
|
|
6
|
-
function
|
|
7
|
-
let [
|
|
8
|
+
function d({ pages: d, activePageId: f, onPageSelect: p, onPageCreate: m, onPageRename: h, onPageDuplicate: g, onPageDelete: _, onPagesReorder: v, editable: y = !0, className: b = "" }) {
|
|
9
|
+
let { hasPermission: x } = o(), S = x(e.DASHBOARD_PAGE_CREATE), C = x(e.DASHBOARD_PAGE_UPDATE), w = x(e.DASHBOARD_PAGE_DELETE), [T, E] = a(null), [D, O] = a(null), [k, A] = a(null), [j, M] = a(""), [N, P] = a(null), [F, I] = a({
|
|
8
10
|
x: 0,
|
|
9
11
|
y: 0
|
|
10
|
-
}),
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}, [
|
|
12
|
+
}), L = i(null), R = i(null);
|
|
13
|
+
r(() => {
|
|
14
|
+
k && L.current && (L.current.focus(), L.current.select());
|
|
15
|
+
}, [k]), r(() => {
|
|
14
16
|
function e(e) {
|
|
15
|
-
|
|
17
|
+
R.current && !R.current.contains(e.target) && P(null);
|
|
16
18
|
}
|
|
17
19
|
return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
18
20
|
}, []);
|
|
19
|
-
let
|
|
20
|
-
|
|
21
|
-
}, []),
|
|
22
|
-
e.preventDefault(), e.dataTransfer.dropEffect = "move",
|
|
23
|
-
}, [
|
|
24
|
-
if (
|
|
25
|
-
let e = [...
|
|
21
|
+
let z = n((e, t) => {
|
|
22
|
+
E(t), e.dataTransfer.effectAllowed = "move";
|
|
23
|
+
}, []), B = n((e, t) => {
|
|
24
|
+
e.preventDefault(), e.dataTransfer.dropEffect = "move", T && T !== t && O(t);
|
|
25
|
+
}, [T]), V = n(() => {
|
|
26
|
+
if (T && D && T !== D && v) {
|
|
27
|
+
let e = [...d], t = e.findIndex((e) => e.id === T), n = e.findIndex((e) => e.id === D);
|
|
26
28
|
if (t !== -1 && n !== -1) {
|
|
27
29
|
let [r] = e.splice(t, 1);
|
|
28
|
-
e.splice(n, 0, r),
|
|
30
|
+
e.splice(n, 0, r), v(e.map((e) => e.id));
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
|
-
|
|
33
|
+
E(null), O(null);
|
|
32
34
|
}, [
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
]),
|
|
38
|
-
e.preventDefault(),
|
|
35
|
+
T,
|
|
36
|
+
D,
|
|
37
|
+
d,
|
|
38
|
+
v
|
|
39
|
+
]), H = n((e, t) => {
|
|
40
|
+
e.preventDefault(), P(t), I({
|
|
39
41
|
x: e.clientX,
|
|
40
42
|
y: e.clientY
|
|
41
43
|
});
|
|
42
|
-
}, []),
|
|
43
|
-
|
|
44
|
-
}, []),
|
|
45
|
-
|
|
44
|
+
}, []), U = n((e, t) => {
|
|
45
|
+
A(e), M(t), P(null);
|
|
46
|
+
}, []), W = n(() => {
|
|
47
|
+
k && j.trim() && h && h(k, j.trim()), A(null), M("");
|
|
46
48
|
}, [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
]),
|
|
51
|
-
|
|
52
|
-
}, []),
|
|
53
|
-
e.key === "Enter" ?
|
|
54
|
-
}, [
|
|
55
|
-
return /* @__PURE__ */
|
|
56
|
-
ref:
|
|
57
|
-
className:
|
|
49
|
+
k,
|
|
50
|
+
j,
|
|
51
|
+
h
|
|
52
|
+
]), G = n(() => {
|
|
53
|
+
A(null), M("");
|
|
54
|
+
}, []), K = n((e) => {
|
|
55
|
+
e.key === "Enter" ? W() : e.key === "Escape" && G();
|
|
56
|
+
}, [W, G]);
|
|
57
|
+
return /* @__PURE__ */ l("div", {
|
|
58
|
+
ref: R,
|
|
59
|
+
className: b,
|
|
58
60
|
style: {
|
|
59
61
|
display: "flex",
|
|
60
62
|
alignItems: "center",
|
|
61
63
|
gap: "4px",
|
|
62
64
|
padding: "0 8px",
|
|
63
65
|
overflowX: "auto",
|
|
64
|
-
backgroundColor:
|
|
65
|
-
borderBottom: `1px solid ${
|
|
66
|
+
backgroundColor: t.bgSecondary,
|
|
67
|
+
borderBottom: `1px solid ${t.borderDefault}`,
|
|
66
68
|
minHeight: "40px"
|
|
67
69
|
},
|
|
68
70
|
children: [
|
|
69
|
-
|
|
70
|
-
draggable:
|
|
71
|
-
onDragStart: (
|
|
72
|
-
onDragOver: (
|
|
73
|
-
onDragEnd:
|
|
74
|
-
onContextMenu: (
|
|
75
|
-
onClick: () => !
|
|
76
|
-
onDoubleClick: () =>
|
|
71
|
+
d.sort((e, t) => e.order - t.order).map((e) => /* @__PURE__ */ c("div", {
|
|
72
|
+
draggable: y && C && !k,
|
|
73
|
+
onDragStart: (t) => z(t, e.id),
|
|
74
|
+
onDragOver: (t) => B(t, e.id),
|
|
75
|
+
onDragEnd: V,
|
|
76
|
+
onContextMenu: (t) => y && (C || w || !!g) && H(t, e.id),
|
|
77
|
+
onClick: () => !k && p(e.id),
|
|
78
|
+
onDoubleClick: () => y && C && U(e.id, e.name),
|
|
77
79
|
style: {
|
|
78
80
|
position: "relative",
|
|
79
81
|
display: "flex",
|
|
80
82
|
alignItems: "center",
|
|
81
83
|
gap: "6px",
|
|
82
84
|
padding: "8px 12px",
|
|
83
|
-
backgroundColor:
|
|
84
|
-
borderBottom:
|
|
85
|
-
cursor:
|
|
86
|
-
opacity:
|
|
87
|
-
borderLeft:
|
|
85
|
+
backgroundColor: f === e.id ? t.bgPrimary : "transparent",
|
|
86
|
+
borderBottom: f === e.id ? `2px solid ${t.actionPrimaryBg}` : "2px solid transparent",
|
|
87
|
+
cursor: k === e.id ? "text" : "pointer",
|
|
88
|
+
opacity: T === e.id ? .5 : 1,
|
|
89
|
+
borderLeft: D === e.id ? `2px solid ${t.actionPrimaryBg}` : "none",
|
|
88
90
|
flexShrink: 0,
|
|
89
91
|
transition: "background-color 0.15s, border-color 0.15s"
|
|
90
92
|
},
|
|
91
|
-
children:
|
|
92
|
-
ref:
|
|
93
|
+
children: k === e.id ? /* @__PURE__ */ c("input", {
|
|
94
|
+
ref: L,
|
|
93
95
|
type: "text",
|
|
94
|
-
value:
|
|
95
|
-
onChange: (e) =>
|
|
96
|
-
onKeyDown:
|
|
97
|
-
onBlur:
|
|
96
|
+
value: j,
|
|
97
|
+
onChange: (e) => M(e.target.value),
|
|
98
|
+
onKeyDown: K,
|
|
99
|
+
onBlur: W,
|
|
98
100
|
style: {
|
|
99
101
|
width: "100px",
|
|
100
102
|
padding: "2px 4px",
|
|
101
|
-
border: `1px solid ${
|
|
103
|
+
border: `1px solid ${t.actionPrimaryBg}`,
|
|
102
104
|
borderRadius: "2px",
|
|
103
105
|
fontSize: "13px",
|
|
104
106
|
outline: "none",
|
|
105
|
-
backgroundColor:
|
|
106
|
-
color:
|
|
107
|
+
backgroundColor: t.bgPrimary,
|
|
108
|
+
color: t.textPrimary
|
|
107
109
|
},
|
|
108
110
|
onClick: (e) => e.stopPropagation()
|
|
109
|
-
}) : /* @__PURE__ */ s
|
|
111
|
+
}) : /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("span", {
|
|
110
112
|
style: {
|
|
111
113
|
fontSize: "13px",
|
|
112
|
-
fontWeight:
|
|
113
|
-
color:
|
|
114
|
+
fontWeight: f === e.id ? 600 : 400,
|
|
115
|
+
color: f === e.id ? t.textPrimary : t.textSecondary
|
|
114
116
|
},
|
|
115
|
-
children:
|
|
116
|
-
}),
|
|
117
|
+
children: e.name
|
|
118
|
+
}), e.widgetCount !== void 0 && /* @__PURE__ */ c("span", {
|
|
117
119
|
style: {
|
|
118
120
|
fontSize: "10px",
|
|
119
|
-
color:
|
|
120
|
-
backgroundColor:
|
|
121
|
+
color: t.textTertiary,
|
|
122
|
+
backgroundColor: t.borderDefault,
|
|
121
123
|
padding: "1px 4px",
|
|
122
124
|
borderRadius: "8px"
|
|
123
125
|
},
|
|
124
|
-
children:
|
|
126
|
+
children: e.widgetCount
|
|
125
127
|
})] })
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
onClick:
|
|
128
|
+
}, e.id)),
|
|
129
|
+
y && m && S && /* @__PURE__ */ c("button", {
|
|
130
|
+
onClick: m,
|
|
129
131
|
style: {
|
|
130
132
|
display: "flex",
|
|
131
133
|
alignItems: "center",
|
|
132
134
|
justifyContent: "center",
|
|
133
135
|
padding: "6px 12px",
|
|
134
|
-
backgroundColor:
|
|
136
|
+
backgroundColor: t.actionPrimaryBg,
|
|
135
137
|
border: "none",
|
|
136
138
|
borderRadius: "4px",
|
|
137
139
|
cursor: "pointer",
|
|
@@ -143,13 +145,13 @@ function l({ pages: l, activePageId: u, onPageSelect: d, onPageCreate: f, onPage
|
|
|
143
145
|
},
|
|
144
146
|
children: "+ Add Page"
|
|
145
147
|
}),
|
|
146
|
-
|
|
148
|
+
N && u(/* @__PURE__ */ l("div", {
|
|
147
149
|
style: {
|
|
148
150
|
position: "fixed",
|
|
149
|
-
left:
|
|
150
|
-
top:
|
|
151
|
-
backgroundColor:
|
|
152
|
-
border: `1px solid ${
|
|
151
|
+
left: F.x,
|
|
152
|
+
top: F.y,
|
|
153
|
+
backgroundColor: t.bgPrimary,
|
|
154
|
+
border: `1px solid ${t.borderDefault}`,
|
|
153
155
|
borderRadius: "6px",
|
|
154
156
|
boxShadow: "0 8px 24px rgba(0,0,0,0.2)",
|
|
155
157
|
zIndex: 99999,
|
|
@@ -157,59 +159,59 @@ function l({ pages: l, activePageId: u, onPageSelect: d, onPageCreate: f, onPage
|
|
|
157
159
|
},
|
|
158
160
|
onClick: (e) => e.stopPropagation(),
|
|
159
161
|
children: [
|
|
160
|
-
/* @__PURE__ */
|
|
162
|
+
C && /* @__PURE__ */ c("button", {
|
|
161
163
|
onClick: () => {
|
|
162
|
-
let e =
|
|
163
|
-
e &&
|
|
164
|
+
let e = d.find((e) => e.id === N);
|
|
165
|
+
e && U(N, e.name);
|
|
164
166
|
},
|
|
165
167
|
style: {
|
|
166
168
|
display: "block",
|
|
167
169
|
width: "100%",
|
|
168
170
|
padding: "8px 12px",
|
|
169
171
|
textAlign: "left",
|
|
170
|
-
backgroundColor:
|
|
172
|
+
backgroundColor: t.bgPrimary,
|
|
171
173
|
border: "none",
|
|
172
174
|
cursor: "pointer",
|
|
173
175
|
fontSize: "13px",
|
|
174
|
-
color:
|
|
176
|
+
color: t.textPrimary
|
|
175
177
|
},
|
|
176
178
|
children: "Rename"
|
|
177
179
|
}),
|
|
178
|
-
|
|
180
|
+
g && S && /* @__PURE__ */ c("button", {
|
|
179
181
|
onClick: () => {
|
|
180
|
-
|
|
182
|
+
g(N), P(null);
|
|
181
183
|
},
|
|
182
184
|
style: {
|
|
183
185
|
display: "block",
|
|
184
186
|
width: "100%",
|
|
185
187
|
padding: "8px 12px",
|
|
186
188
|
textAlign: "left",
|
|
187
|
-
backgroundColor:
|
|
189
|
+
backgroundColor: t.bgPrimary,
|
|
188
190
|
border: "none",
|
|
189
191
|
cursor: "pointer",
|
|
190
192
|
fontSize: "13px",
|
|
191
|
-
color:
|
|
193
|
+
color: t.textPrimary
|
|
192
194
|
},
|
|
193
195
|
children: "Duplicate"
|
|
194
196
|
}),
|
|
195
|
-
|
|
197
|
+
_ && w && d.length > 1 && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("div", { style: {
|
|
196
198
|
height: "1px",
|
|
197
|
-
backgroundColor:
|
|
199
|
+
backgroundColor: t.borderDefault,
|
|
198
200
|
margin: "4px 0"
|
|
199
|
-
} }), /* @__PURE__ */
|
|
201
|
+
} }), /* @__PURE__ */ c("button", {
|
|
200
202
|
onClick: () => {
|
|
201
|
-
window.confirm("Are you sure you want to delete this page?") &&
|
|
203
|
+
window.confirm("Are you sure you want to delete this page?") && _(N), P(null);
|
|
202
204
|
},
|
|
203
205
|
style: {
|
|
204
206
|
display: "block",
|
|
205
207
|
width: "100%",
|
|
206
208
|
padding: "8px 12px",
|
|
207
209
|
textAlign: "left",
|
|
208
|
-
backgroundColor:
|
|
210
|
+
backgroundColor: t.bgPrimary,
|
|
209
211
|
border: "none",
|
|
210
212
|
cursor: "pointer",
|
|
211
213
|
fontSize: "13px",
|
|
212
|
-
color:
|
|
214
|
+
color: t.statusErrorText
|
|
213
215
|
},
|
|
214
216
|
children: "Delete"
|
|
215
217
|
})] })
|
|
@@ -219,6 +221,6 @@ function l({ pages: l, activePageId: u, onPageSelect: d, onPageCreate: f, onPage
|
|
|
219
221
|
});
|
|
220
222
|
}
|
|
221
223
|
//#endregion
|
|
222
|
-
export {
|
|
224
|
+
export { d as default };
|
|
223
225
|
|
|
224
226
|
//# sourceMappingURL=PageTabsManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageTabsManager.js","names":[],"sources":["../../../../../src/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.tsx"],"sourcesContent":["/**\n * PageTabsManager Component\n *\n * Manages dashboard page tabs with drag-and-drop reordering.\n */\n\nimport React, { useState, useCallback, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { SEMANTIC_COLORS } from '../../../utils/semanticTokens';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardPageTab {\n id: string;\n name: string;\n order: number;\n widgetCount?: number;\n}\n\nexport interface PageTabsManagerProps {\n pages: DashboardPageTab[];\n activePageId: string;\n onPageSelect: (pageId: string) => void;\n onPageCreate?: () => void;\n onPageRename?: (pageId: string, newName: string) => void;\n onPageDuplicate?: (pageId: string) => void;\n onPageDelete?: (pageId: string) => void;\n onPagesReorder?: (pageIds: string[]) => void;\n editable?: boolean;\n className?: string;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function PageTabsManager({\n pages,\n activePageId,\n onPageSelect,\n onPageCreate,\n onPageRename,\n onPageDuplicate,\n onPageDelete,\n onPagesReorder,\n editable = true,\n className = '',\n}: PageTabsManagerProps) {\n const [draggedId, setDraggedId] = useState<string | null>(null);\n const [dragOverId, setDragOverId] = useState<string | null>(null);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editingName, setEditingName] = useState('');\n const [contextMenuId, setContextMenuId] = useState<string | null>(null);\n const [contextMenuPos, setContextMenuPos] = useState({ x: 0, y: 0 });\n\n const editInputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Focus input when editing\n useEffect(() => {\n if (editingId && editInputRef.current) {\n editInputRef.current.focus();\n editInputRef.current.select();\n }\n }, [editingId]);\n\n // Close context menu on click outside\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setContextMenuId(null);\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n // Drag handlers\n const handleDragStart = useCallback((e: React.DragEvent, pageId: string) => {\n setDraggedId(pageId);\n e.dataTransfer.effectAllowed = 'move';\n }, []);\n\n const handleDragOver = useCallback(\n (e: React.DragEvent, pageId: string) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n if (draggedId && draggedId !== pageId) {\n setDragOverId(pageId);\n }\n },\n [draggedId]\n );\n\n const handleDragEnd = useCallback(() => {\n if (draggedId && dragOverId && draggedId !== dragOverId && onPagesReorder) {\n const orderedPages = [...pages];\n const draggedIndex = orderedPages.findIndex((p) => p.id === draggedId);\n const targetIndex = orderedPages.findIndex((p) => p.id === dragOverId);\n\n if (draggedIndex !== -1 && targetIndex !== -1) {\n const [draggedPage] = orderedPages.splice(draggedIndex, 1);\n orderedPages.splice(targetIndex, 0, draggedPage);\n onPagesReorder(orderedPages.map((p) => p.id));\n }\n }\n\n setDraggedId(null);\n setDragOverId(null);\n }, [draggedId, dragOverId, pages, onPagesReorder]);\n\n // Context menu handler\n const handleContextMenu = useCallback((e: React.MouseEvent, pageId: string) => {\n e.preventDefault();\n setContextMenuId(pageId);\n setContextMenuPos({ x: e.clientX, y: e.clientY });\n }, []);\n\n // Start editing\n const handleStartEdit = useCallback((pageId: string, currentName: string) => {\n setEditingId(pageId);\n setEditingName(currentName);\n setContextMenuId(null);\n }, []);\n\n // Save edit\n const handleSaveEdit = useCallback(() => {\n if (editingId && editingName.trim() && onPageRename) {\n onPageRename(editingId, editingName.trim());\n }\n setEditingId(null);\n setEditingName('');\n }, [editingId, editingName, onPageRename]);\n\n // Cancel edit\n const handleCancelEdit = useCallback(() => {\n setEditingId(null);\n setEditingName('');\n }, []);\n\n // Handle key press in edit mode\n const handleEditKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n handleSaveEdit();\n } else if (e.key === 'Escape') {\n handleCancelEdit();\n }\n },\n [handleSaveEdit, handleCancelEdit]\n );\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n padding: '0 8px',\n overflowX: 'auto',\n backgroundColor: SEMANTIC_COLORS.bgSecondary,\n borderBottom: `1px solid ${SEMANTIC_COLORS.borderDefault}`,\n minHeight: '40px',\n }}\n >\n {/* Page Tabs */}\n {pages\n .sort((a, b) => a.order - b.order)\n .map((page) => (\n <div\n key={page.id}\n draggable={editable && !editingId}\n onDragStart={(e) => handleDragStart(e, page.id)}\n onDragOver={(e) => handleDragOver(e, page.id)}\n onDragEnd={handleDragEnd}\n onContextMenu={(e) => editable && handleContextMenu(e, page.id)}\n onClick={() => !editingId && onPageSelect(page.id)}\n onDoubleClick={() => editable && handleStartEdit(page.id, page.name)}\n style={{\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n padding: '8px 12px',\n backgroundColor: activePageId === page.id ? SEMANTIC_COLORS.bgPrimary : 'transparent',\n borderBottom:\n activePageId === page.id ? `2px solid ${SEMANTIC_COLORS.actionPrimaryBg}` : '2px solid transparent',\n cursor: editingId === page.id ? 'text' : 'pointer',\n opacity: draggedId === page.id ? 0.5 : 1,\n borderLeft: dragOverId === page.id ? `2px solid ${SEMANTIC_COLORS.actionPrimaryBg}` : 'none',\n flexShrink: 0,\n transition: 'background-color 0.15s, border-color 0.15s',\n }}\n >\n {editingId === page.id ? (\n <input\n ref={editInputRef}\n type=\"text\"\n value={editingName}\n onChange={(e) => setEditingName(e.target.value)}\n onKeyDown={handleEditKeyDown}\n onBlur={handleSaveEdit}\n style={{\n width: '100px',\n padding: '2px 4px',\n border: `1px solid ${SEMANTIC_COLORS.actionPrimaryBg}`,\n borderRadius: '2px',\n fontSize: '13px',\n outline: 'none',\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n color: SEMANTIC_COLORS.textPrimary,\n }}\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <>\n <span\n style={{\n fontSize: '13px',\n fontWeight: activePageId === page.id ? 600 : 400,\n color: activePageId === page.id ? SEMANTIC_COLORS.textPrimary : SEMANTIC_COLORS.textSecondary,\n }}\n >\n {page.name}\n </span>\n {page.widgetCount !== undefined && (\n <span\n style={{\n fontSize: '10px',\n color: SEMANTIC_COLORS.textTertiary,\n backgroundColor: SEMANTIC_COLORS.borderDefault,\n padding: '1px 4px',\n borderRadius: '8px',\n }}\n >\n {page.widgetCount}\n </span>\n )}\n </>\n )}\n </div>\n ))}\n\n {/* Add Page Button */}\n {editable && onPageCreate && (\n <button\n onClick={onPageCreate}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '6px 12px',\n backgroundColor: SEMANTIC_COLORS.actionPrimaryBg,\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n color: '#ffffff',\n fontSize: '12px',\n fontWeight: 500,\n flexShrink: 0,\n marginLeft: '8px',\n }}\n >\n + Add Page\n </button>\n )}\n\n {/* Context Menu - rendered via portal */}\n {contextMenuId &&\n createPortal(\n <div\n style={{\n position: 'fixed',\n left: contextMenuPos.x,\n top: contextMenuPos.y,\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n border: `1px solid ${SEMANTIC_COLORS.borderDefault}`,\n borderRadius: '6px',\n boxShadow: '0 8px 24px rgba(0,0,0,0.2)',\n zIndex: 99999,\n minWidth: '140px',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n onClick={() => {\n const page = pages.find((p) => p.id === contextMenuId);\n if (page) handleStartEdit(contextMenuId, page.name);\n }}\n style={{\n display: 'block',\n width: '100%',\n padding: '8px 12px',\n textAlign: 'left',\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n border: 'none',\n cursor: 'pointer',\n fontSize: '13px',\n color: SEMANTIC_COLORS.textPrimary,\n }}\n >\n Rename\n </button>\n {onPageDuplicate && (\n <button\n onClick={() => {\n onPageDuplicate(contextMenuId);\n setContextMenuId(null);\n }}\n style={{\n display: 'block',\n width: '100%',\n padding: '8px 12px',\n textAlign: 'left',\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n border: 'none',\n cursor: 'pointer',\n fontSize: '13px',\n color: SEMANTIC_COLORS.textPrimary,\n }}\n >\n Duplicate\n </button>\n )}\n {onPageDelete && pages.length > 1 && (\n <>\n <div style={{ height: '1px', backgroundColor: SEMANTIC_COLORS.borderDefault, margin: '4px 0' }} />\n <button\n onClick={() => {\n if (window.confirm('Are you sure you want to delete this page?')) {\n onPageDelete(contextMenuId);\n }\n setContextMenuId(null);\n }}\n style={{\n display: 'block',\n width: '100%',\n padding: '8px 12px',\n textAlign: 'left',\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n border: 'none',\n cursor: 'pointer',\n fontSize: '13px',\n color: SEMANTIC_COLORS.statusErrorText,\n }}\n >\n Delete\n </button>\n </>\n )}\n </div>,\n document.body\n )}\n </div>\n );\n}\n\nexport default PageTabsManager;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PageTabsManager.js","names":[],"sources":["../../../../../src/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.tsx"],"sourcesContent":["/**\n * PageTabsManager Component\n *\n * Manages dashboard page tabs with drag-and-drop reordering.\n */\n\nimport React, { useState, useCallback, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { SEMANTIC_COLORS } from '../../../utils/semanticTokens';\nimport { BIGCONSOLE_PERMISSIONS } from '../../../../constants/permissions';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardPageTab {\n id: string;\n name: string;\n order: number;\n widgetCount?: number;\n}\n\nexport interface PageTabsManagerProps {\n pages: DashboardPageTab[];\n activePageId: string;\n onPageSelect: (pageId: string) => void;\n onPageCreate?: () => void;\n onPageRename?: (pageId: string, newName: string) => void;\n onPageDuplicate?: (pageId: string) => void;\n onPageDelete?: (pageId: string) => void;\n onPagesReorder?: (pageIds: string[]) => void;\n editable?: boolean;\n className?: string;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function PageTabsManager({\n pages,\n activePageId,\n onPageSelect,\n onPageCreate,\n onPageRename,\n onPageDuplicate,\n onPageDelete,\n onPagesReorder,\n editable = true,\n className = '',\n}: PageTabsManagerProps) {\n const { hasPermission } = usePermissions();\n const canCreatePage = hasPermission(BIGCONSOLE_PERMISSIONS.DASHBOARD_PAGE_CREATE);\n const canUpdatePage = hasPermission(BIGCONSOLE_PERMISSIONS.DASHBOARD_PAGE_UPDATE);\n const canDeletePage = hasPermission(BIGCONSOLE_PERMISSIONS.DASHBOARD_PAGE_DELETE);\n\n const [draggedId, setDraggedId] = useState<string | null>(null);\n const [dragOverId, setDragOverId] = useState<string | null>(null);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editingName, setEditingName] = useState('');\n const [contextMenuId, setContextMenuId] = useState<string | null>(null);\n const [contextMenuPos, setContextMenuPos] = useState({ x: 0, y: 0 });\n\n const editInputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Focus input when editing\n useEffect(() => {\n if (editingId && editInputRef.current) {\n editInputRef.current.focus();\n editInputRef.current.select();\n }\n }, [editingId]);\n\n // Close context menu on click outside\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setContextMenuId(null);\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n // Drag handlers\n const handleDragStart = useCallback((e: React.DragEvent, pageId: string) => {\n setDraggedId(pageId);\n e.dataTransfer.effectAllowed = 'move';\n }, []);\n\n const handleDragOver = useCallback(\n (e: React.DragEvent, pageId: string) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n if (draggedId && draggedId !== pageId) {\n setDragOverId(pageId);\n }\n },\n [draggedId]\n );\n\n const handleDragEnd = useCallback(() => {\n if (draggedId && dragOverId && draggedId !== dragOverId && onPagesReorder) {\n const orderedPages = [...pages];\n const draggedIndex = orderedPages.findIndex((p) => p.id === draggedId);\n const targetIndex = orderedPages.findIndex((p) => p.id === dragOverId);\n\n if (draggedIndex !== -1 && targetIndex !== -1) {\n const [draggedPage] = orderedPages.splice(draggedIndex, 1);\n orderedPages.splice(targetIndex, 0, draggedPage);\n onPagesReorder(orderedPages.map((p) => p.id));\n }\n }\n\n setDraggedId(null);\n setDragOverId(null);\n }, [draggedId, dragOverId, pages, onPagesReorder]);\n\n // Context menu handler\n const handleContextMenu = useCallback((e: React.MouseEvent, pageId: string) => {\n e.preventDefault();\n setContextMenuId(pageId);\n setContextMenuPos({ x: e.clientX, y: e.clientY });\n }, []);\n\n // Start editing\n const handleStartEdit = useCallback((pageId: string, currentName: string) => {\n setEditingId(pageId);\n setEditingName(currentName);\n setContextMenuId(null);\n }, []);\n\n // Save edit\n const handleSaveEdit = useCallback(() => {\n if (editingId && editingName.trim() && onPageRename) {\n onPageRename(editingId, editingName.trim());\n }\n setEditingId(null);\n setEditingName('');\n }, [editingId, editingName, onPageRename]);\n\n // Cancel edit\n const handleCancelEdit = useCallback(() => {\n setEditingId(null);\n setEditingName('');\n }, []);\n\n // Handle key press in edit mode\n const handleEditKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n handleSaveEdit();\n } else if (e.key === 'Escape') {\n handleCancelEdit();\n }\n },\n [handleSaveEdit, handleCancelEdit]\n );\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n padding: '0 8px',\n overflowX: 'auto',\n backgroundColor: SEMANTIC_COLORS.bgSecondary,\n borderBottom: `1px solid ${SEMANTIC_COLORS.borderDefault}`,\n minHeight: '40px',\n }}\n >\n {/* Page Tabs */}\n {pages\n .sort((a, b) => a.order - b.order)\n .map((page) => (\n <div\n key={page.id}\n draggable={editable && canUpdatePage && !editingId}\n onDragStart={(e) => handleDragStart(e, page.id)}\n onDragOver={(e) => handleDragOver(e, page.id)}\n onDragEnd={handleDragEnd}\n onContextMenu={(e) =>\n editable && (canUpdatePage || canDeletePage || !!onPageDuplicate) && handleContextMenu(e, page.id)\n }\n onClick={() => !editingId && onPageSelect(page.id)}\n onDoubleClick={() => editable && canUpdatePage && handleStartEdit(page.id, page.name)}\n style={{\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n padding: '8px 12px',\n backgroundColor: activePageId === page.id ? SEMANTIC_COLORS.bgPrimary : 'transparent',\n borderBottom:\n activePageId === page.id ? `2px solid ${SEMANTIC_COLORS.actionPrimaryBg}` : '2px solid transparent',\n cursor: editingId === page.id ? 'text' : 'pointer',\n opacity: draggedId === page.id ? 0.5 : 1,\n borderLeft: dragOverId === page.id ? `2px solid ${SEMANTIC_COLORS.actionPrimaryBg}` : 'none',\n flexShrink: 0,\n transition: 'background-color 0.15s, border-color 0.15s',\n }}\n >\n {editingId === page.id ? (\n <input\n ref={editInputRef}\n type=\"text\"\n value={editingName}\n onChange={(e) => setEditingName(e.target.value)}\n onKeyDown={handleEditKeyDown}\n onBlur={handleSaveEdit}\n style={{\n width: '100px',\n padding: '2px 4px',\n border: `1px solid ${SEMANTIC_COLORS.actionPrimaryBg}`,\n borderRadius: '2px',\n fontSize: '13px',\n outline: 'none',\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n color: SEMANTIC_COLORS.textPrimary,\n }}\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <>\n <span\n style={{\n fontSize: '13px',\n fontWeight: activePageId === page.id ? 600 : 400,\n color: activePageId === page.id ? SEMANTIC_COLORS.textPrimary : SEMANTIC_COLORS.textSecondary,\n }}\n >\n {page.name}\n </span>\n {page.widgetCount !== undefined && (\n <span\n style={{\n fontSize: '10px',\n color: SEMANTIC_COLORS.textTertiary,\n backgroundColor: SEMANTIC_COLORS.borderDefault,\n padding: '1px 4px',\n borderRadius: '8px',\n }}\n >\n {page.widgetCount}\n </span>\n )}\n </>\n )}\n </div>\n ))}\n\n {/* Add Page Button */}\n {editable && onPageCreate && canCreatePage && (\n <button\n onClick={onPageCreate}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '6px 12px',\n backgroundColor: SEMANTIC_COLORS.actionPrimaryBg,\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n color: '#ffffff',\n fontSize: '12px',\n fontWeight: 500,\n flexShrink: 0,\n marginLeft: '8px',\n }}\n >\n + Add Page\n </button>\n )}\n\n {/* Context Menu - rendered via portal */}\n {contextMenuId &&\n createPortal(\n <div\n style={{\n position: 'fixed',\n left: contextMenuPos.x,\n top: contextMenuPos.y,\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n border: `1px solid ${SEMANTIC_COLORS.borderDefault}`,\n borderRadius: '6px',\n boxShadow: '0 8px 24px rgba(0,0,0,0.2)',\n zIndex: 99999,\n minWidth: '140px',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {canUpdatePage && (\n <button\n onClick={() => {\n const page = pages.find((p) => p.id === contextMenuId);\n if (page) handleStartEdit(contextMenuId, page.name);\n }}\n style={{\n display: 'block',\n width: '100%',\n padding: '8px 12px',\n textAlign: 'left',\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n border: 'none',\n cursor: 'pointer',\n fontSize: '13px',\n color: SEMANTIC_COLORS.textPrimary,\n }}\n >\n Rename\n </button>\n )}\n {onPageDuplicate && canCreatePage && (\n <button\n onClick={() => {\n onPageDuplicate(contextMenuId);\n setContextMenuId(null);\n }}\n style={{\n display: 'block',\n width: '100%',\n padding: '8px 12px',\n textAlign: 'left',\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n border: 'none',\n cursor: 'pointer',\n fontSize: '13px',\n color: SEMANTIC_COLORS.textPrimary,\n }}\n >\n Duplicate\n </button>\n )}\n {onPageDelete && canDeletePage && pages.length > 1 && (\n <>\n <div style={{ height: '1px', backgroundColor: SEMANTIC_COLORS.borderDefault, margin: '4px 0' }} />\n <button\n onClick={() => {\n if (window.confirm('Are you sure you want to delete this page?')) {\n onPageDelete(contextMenuId);\n }\n setContextMenuId(null);\n }}\n style={{\n display: 'block',\n width: '100%',\n padding: '8px 12px',\n textAlign: 'left',\n backgroundColor: SEMANTIC_COLORS.bgPrimary,\n border: 'none',\n cursor: 'pointer',\n fontSize: '13px',\n color: SEMANTIC_COLORS.statusErrorText,\n }}\n >\n Delete\n </button>\n </>\n )}\n </div>,\n document.body\n )}\n </div>\n );\n}\n\nexport default PageTabsManager;\n"],"mappings":";;;;;;;AAwCA,SAAgB,EAAgB,EAC9B,UACA,iBACA,iBACA,iBACA,iBACA,oBACA,iBACA,mBACA,cAAW,IACX,eAAY,MACW;CACvB,IAAM,EAAE,qBAAkB,GAAgB,EACpC,IAAgB,EAAc,EAAuB,sBAAsB,EAC3E,IAAgB,EAAc,EAAuB,sBAAsB,EAC3E,IAAgB,EAAc,EAAuB,sBAAsB,EAE3E,CAAC,GAAW,KAAgB,EAAwB,KAAK,EACzD,CAAC,GAAY,KAAiB,EAAwB,KAAK,EAC3D,CAAC,GAAW,KAAgB,EAAwB,KAAK,EACzD,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAe,KAAoB,EAAwB,KAAK,EACjE,CAAC,GAAgB,KAAqB,EAAS;EAAE,GAAG;EAAG,GAAG;EAAG,CAAC,EAE9D,IAAe,EAAyB,KAAK,EAC7C,IAAe,EAAuB,KAAK;AAWjD,CARA,QAAgB;AACd,EAAI,KAAa,EAAa,YAC5B,EAAa,QAAQ,OAAO,EAC5B,EAAa,QAAQ,QAAQ;IAE9B,CAAC,EAAU,CAAC,EAGf,QAAgB;EACd,SAAS,EAAmB,GAAmB;AAC7C,GAAI,EAAa,WAAW,CAAC,EAAa,QAAQ,SAAS,EAAM,OAAe,IAC9E,EAAiB,KAAK;;AAK1B,SADA,SAAS,iBAAiB,aAAa,EAAmB,QAC7C,SAAS,oBAAoB,aAAa,EAAmB;IACzE,EAAE,CAAC;CAGN,IAAM,IAAkB,GAAa,GAAoB,MAAmB;AAE1E,EADA,EAAa,EAAO,EACpB,EAAE,aAAa,gBAAgB;IAC9B,EAAE,CAAC,EAEA,IAAiB,GACpB,GAAoB,MAAmB;AAGtC,EAFA,EAAE,gBAAgB,EAClB,EAAE,aAAa,aAAa,QACxB,KAAa,MAAc,KAC7B,EAAc,EAAO;IAGzB,CAAC,EAAU,CACZ,EAEK,IAAgB,QAAkB;AACtC,MAAI,KAAa,KAAc,MAAc,KAAc,GAAgB;GACzE,IAAM,IAAe,CAAC,GAAG,EAAM,EACzB,IAAe,EAAa,WAAW,MAAM,EAAE,OAAO,EAAU,EAChE,IAAc,EAAa,WAAW,MAAM,EAAE,OAAO,EAAW;AAEtE,OAAI,MAAiB,MAAM,MAAgB,IAAI;IAC7C,IAAM,CAAC,KAAe,EAAa,OAAO,GAAc,EAAE;AAE1D,IADA,EAAa,OAAO,GAAa,GAAG,EAAY,EAChD,EAAe,EAAa,KAAK,MAAM,EAAE,GAAG,CAAC;;;AAKjD,EADA,EAAa,KAAK,EAClB,EAAc,KAAK;IAClB;EAAC;EAAW;EAAY;EAAO;EAAe,CAAC,EAG5C,IAAoB,GAAa,GAAqB,MAAmB;AAG7E,EAFA,EAAE,gBAAgB,EAClB,EAAiB,EAAO,EACxB,EAAkB;GAAE,GAAG,EAAE;GAAS,GAAG,EAAE;GAAS,CAAC;IAChD,EAAE,CAAC,EAGA,IAAkB,GAAa,GAAgB,MAAwB;AAG3E,EAFA,EAAa,EAAO,EACpB,EAAe,EAAY,EAC3B,EAAiB,KAAK;IACrB,EAAE,CAAC,EAGA,IAAiB,QAAkB;AAKvC,EAJI,KAAa,EAAY,MAAM,IAAI,KACrC,EAAa,GAAW,EAAY,MAAM,CAAC,EAE7C,EAAa,KAAK,EAClB,EAAe,GAAG;IACjB;EAAC;EAAW;EAAa;EAAa,CAAC,EAGpC,IAAmB,QAAkB;AAEzC,EADA,EAAa,KAAK,EAClB,EAAe,GAAG;IACjB,EAAE,CAAC,EAGA,IAAoB,GACvB,MAA2B;AAC1B,EAAI,EAAE,QAAQ,UACZ,GAAgB,GACP,EAAE,QAAQ,YACnB,GAAkB;IAGtB,CAAC,GAAgB,EAAiB,CACnC;AAED,QACE,kBAAC,OAAD;EACE,KAAK;EACM;EACX,OAAO;GACL,SAAS;GACT,YAAY;GACZ,KAAK;GACL,SAAS;GACT,WAAW;GACX,iBAAiB,EAAgB;GACjC,cAAc,aAAa,EAAgB;GAC3C,WAAW;GACZ;YAZH;GAeG,EACE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,KAAK,MACJ,kBAAC,OAAD;IAEE,WAAW,KAAY,KAAiB,CAAC;IACzC,cAAc,MAAM,EAAgB,GAAG,EAAK,GAAG;IAC/C,aAAa,MAAM,EAAe,GAAG,EAAK,GAAG;IAC7C,WAAW;IACX,gBAAgB,MACd,MAAa,KAAiB,KAAiB,CAAC,CAAC,MAAoB,EAAkB,GAAG,EAAK,GAAG;IAEpG,eAAe,CAAC,KAAa,EAAa,EAAK,GAAG;IAClD,qBAAqB,KAAY,KAAiB,EAAgB,EAAK,IAAI,EAAK,KAAK;IACrF,OAAO;KACL,UAAU;KACV,SAAS;KACT,YAAY;KACZ,KAAK;KACL,SAAS;KACT,iBAAiB,MAAiB,EAAK,KAAK,EAAgB,YAAY;KACxE,cACE,MAAiB,EAAK,KAAK,aAAa,EAAgB,oBAAoB;KAC9E,QAAQ,MAAc,EAAK,KAAK,SAAS;KACzC,SAAS,MAAc,EAAK,KAAK,KAAM;KACvC,YAAY,MAAe,EAAK,KAAK,aAAa,EAAgB,oBAAoB;KACtF,YAAY;KACZ,YAAY;KACb;cAEA,MAAc,EAAK,KAClB,kBAAC,SAAD;KACE,KAAK;KACL,MAAK;KACL,OAAO;KACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;KAC/C,WAAW;KACX,QAAQ;KACR,OAAO;MACL,OAAO;MACP,SAAS;MACT,QAAQ,aAAa,EAAgB;MACrC,cAAc;MACd,UAAU;MACV,SAAS;MACT,iBAAiB,EAAgB;MACjC,OAAO,EAAgB;MACxB;KACD,UAAU,MAAM,EAAE,iBAAiB;KACnC,CAAA,GAEF,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,QAAD;KACE,OAAO;MACL,UAAU;MACV,YAAY,MAAiB,EAAK,KAAK,MAAM;MAC7C,OAAO,MAAiB,EAAK,KAAK,EAAgB,cAAc,EAAgB;MACjF;eAEA,EAAK;KACD,CAAA,EACN,EAAK,gBAAgB,KAAA,KACpB,kBAAC,QAAD;KACE,OAAO;MACL,UAAU;MACV,OAAO,EAAgB;MACvB,iBAAiB,EAAgB;MACjC,SAAS;MACT,cAAc;MACf;eAEA,EAAK;KACD,CAAA,CAER,EAAA,CAAA;IAED,EAxEC,EAAK,GAwEN,CACN;GAGH,KAAY,KAAgB,KAC3B,kBAAC,UAAD;IACE,SAAS;IACT,OAAO;KACL,SAAS;KACT,YAAY;KACZ,gBAAgB;KAChB,SAAS;KACT,iBAAiB,EAAgB;KACjC,QAAQ;KACR,cAAc;KACd,QAAQ;KACR,OAAO;KACP,UAAU;KACV,YAAY;KACZ,YAAY;KACZ,YAAY;KACb;cACF;IAEQ,CAAA;GAIV,KACC,EACE,kBAAC,OAAD;IACE,OAAO;KACL,UAAU;KACV,MAAM,EAAe;KACrB,KAAK,EAAe;KACpB,iBAAiB,EAAgB;KACjC,QAAQ,aAAa,EAAgB;KACrC,cAAc;KACd,WAAW;KACX,QAAQ;KACR,UAAU;KACX;IACD,UAAU,MAAM,EAAE,iBAAiB;cAZrC;KAcG,KACC,kBAAC,UAAD;MACE,eAAe;OACb,IAAM,IAAO,EAAM,MAAM,MAAM,EAAE,OAAO,EAAc;AACtD,OAAI,KAAM,EAAgB,GAAe,EAAK,KAAK;;MAErD,OAAO;OACL,SAAS;OACT,OAAO;OACP,SAAS;OACT,WAAW;OACX,iBAAiB,EAAgB;OACjC,QAAQ;OACR,QAAQ;OACR,UAAU;OACV,OAAO,EAAgB;OACxB;gBACF;MAEQ,CAAA;KAEV,KAAmB,KAClB,kBAAC,UAAD;MACE,eAAe;AAEb,OADA,EAAgB,EAAc,EAC9B,EAAiB,KAAK;;MAExB,OAAO;OACL,SAAS;OACT,OAAO;OACP,SAAS;OACT,WAAW;OACX,iBAAiB,EAAgB;OACjC,QAAQ;OACR,QAAQ;OACR,UAAU;OACV,OAAO,EAAgB;OACxB;gBACF;MAEQ,CAAA;KAEV,KAAgB,KAAiB,EAAM,SAAS,KAC/C,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD,EAAK,OAAO;MAAE,QAAQ;MAAO,iBAAiB,EAAgB;MAAe,QAAQ;MAAS,EAAI,CAAA,EAClG,kBAAC,UAAD;MACE,eAAe;AAIb,OAHI,OAAO,QAAQ,6CAA6C,IAC9D,EAAa,EAAc,EAE7B,EAAiB,KAAK;;MAExB,OAAO;OACL,SAAS;OACT,OAAO;OACP,SAAS;OACT,WAAW;OACX,iBAAiB,EAAgB;OACjC,QAAQ;OACR,QAAQ;OACR,UAAU;OACV,OAAO,EAAgB;OACxB;gBACF;MAEQ,CAAA,CACR,EAAA,CAAA;KAED;OACN,SAAS,KACV;GACC"}
|