@burdenoff/microfe-bigconsole 2026.624.2 → 2026.625.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/BigConsoleRoutes.js +93 -93
- package/dist/bigconsole/assistant/assistantApi.js +215 -0
- package/dist/bigconsole/assistant/assistantApi.js.map +1 -0
- package/dist/bigconsole/assistant/createSandboxAssistantTransport.js +119 -0
- package/dist/bigconsole/assistant/createSandboxAssistantTransport.js.map +1 -0
- package/dist/bigconsole/assistant/index.js +2 -0
- package/dist/bigconsole/assistant/pageContext.js +51 -0
- package/dist/bigconsole/assistant/pageContext.js.map +1 -0
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +48 -48
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +52 -52
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +33 -33
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +179 -179
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/WidgetPalette.js +38 -38
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +32 -32
- package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js +31 -31
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +98 -98
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ExportParserDialog.js +31 -31
- package/dist/bigconsole/components/parser/ImportParserDialog.js +162 -162
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +79 -79
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +307 -307
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetConfigDialog.js +222 -222
- package/dist/bigconsole/components/widgets/WidgetConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetTypeSelector.js +23 -23
- package/dist/bigconsole/index.js +3 -0
- package/dist/bigconsole/pages/DashboardBuilderPage.js +74 -74
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +168 -189
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +266 -310
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +148 -194
- package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +252 -246
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +256 -231
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +173 -219
- package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
- package/dist/bigconsole/pages/HomePage.js +125 -141
- package/dist/bigconsole/pages/HomePage.js.map +1 -1
- package/dist/bigconsole/pages/InsightsPage.js +159 -184
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +401 -393
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +220 -201
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +212 -206
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +204 -181
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +107 -150
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/SettingsPage.js +184 -171
- package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
- package/dist/bigconsole/pages/WidgetDemoPage.js +69 -81
- package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +230 -216
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +106 -149
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/generated/wspace-operations.js +87 -36
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/index.js +3 -1
- package/package.json +6 -2
|
@@ -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';\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\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 const result = await importDashboard(fileContent, options);\n\n if (result?.success && result.dashboard) {\n setStep('complete');\n onSuccess?.(result.dashboard.id, result.dashboard.name, result.originalUpdated ?? false);\n } else {\n setStep('preview');\n }\n }, [fileContent, nameOverride, visibility, skipWarnings, importDashboard, onSuccess]);\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\">\n {validationResult.dashboardInfo.schemaVersion}\n </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 { useImportDashboard, type ImportDashboardOptions } from '../../hooks';\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\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 const result = await importDashboard(fileContent, options);\n\n if (result?.success && result.dashboard) {\n setStep('complete');\n onSuccess?.(result.dashboard.id, result.dashboard.name, result.originalUpdated ?? false);\n } else {\n setStep('preview');\n }\n }, [fileContent, nameOverride, visibility, skipWarnings, importDashboard, onSuccess]);\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,8 +1,8 @@
|
|
|
1
1
|
import { WIDGET_CATEGORY_LABELS as e, getWidgetCategories as t, getWidgetKey as n } from "../widgets/WidgetRegistry.js";
|
|
2
2
|
import { memo as r, useCallback as i, useMemo as a, useState as o } from "react";
|
|
3
3
|
import { Activity as s, BarChart3 as c, Calendar as l, ChevronDown as u, ChevronRight as d, Columns as f, ExternalLink as p, FileText as m, Filter as h, Gauge as g, GitBranch as _, Grid3x3 as v, GripVertical as y, Layers as b, LayoutDashboard as x, List as S, MapPin as C, Puzzle as w, Search as T, Table as E, TrendingUp as D, Type as O, X as k } from "lucide-react";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { Input as A } from "@burdenoff/fe-libs/ui";
|
|
5
|
+
import { jsx as j, jsxs as M } from "react/jsx-runtime";
|
|
6
6
|
//#region src/bigconsole/components/dashboard/WidgetPalette.tsx
|
|
7
7
|
var N = {
|
|
8
8
|
TrendingUp: D,
|
|
@@ -311,43 +311,43 @@ var F = {
|
|
|
311
311
|
}, [f]), I = i((e) => {
|
|
312
312
|
c?.(e.type, e);
|
|
313
313
|
}, [c]);
|
|
314
|
-
return r ? /* @__PURE__ */
|
|
314
|
+
return r ? /* @__PURE__ */ M("div", {
|
|
315
315
|
style: F.container,
|
|
316
316
|
children: [
|
|
317
|
-
/* @__PURE__ */
|
|
317
|
+
/* @__PURE__ */ M("div", {
|
|
318
318
|
style: F.header,
|
|
319
|
-
children: [/* @__PURE__ */
|
|
319
|
+
children: [/* @__PURE__ */ M("div", {
|
|
320
320
|
style: F.headerTop,
|
|
321
|
-
children: [/* @__PURE__ */
|
|
321
|
+
children: [/* @__PURE__ */ M("div", {
|
|
322
322
|
style: F.headerTitle,
|
|
323
|
-
children: [/* @__PURE__ */
|
|
323
|
+
children: [/* @__PURE__ */ j("div", {
|
|
324
324
|
style: F.headerIcon,
|
|
325
|
-
children: /* @__PURE__ */
|
|
325
|
+
children: /* @__PURE__ */ j(b, { style: {
|
|
326
326
|
width: "18px",
|
|
327
327
|
height: "18px",
|
|
328
328
|
color: "var(--color-action-primary-text)"
|
|
329
329
|
} })
|
|
330
|
-
}), /* @__PURE__ */
|
|
330
|
+
}), /* @__PURE__ */ M("div", { children: [/* @__PURE__ */ j("h3", {
|
|
331
331
|
style: F.title,
|
|
332
332
|
children: "Widgets"
|
|
333
|
-
}), /* @__PURE__ */
|
|
333
|
+
}), /* @__PURE__ */ j("p", {
|
|
334
334
|
style: F.subtitle,
|
|
335
335
|
children: "Drag or click to add"
|
|
336
336
|
})] })]
|
|
337
|
-
}), /* @__PURE__ */
|
|
337
|
+
}), /* @__PURE__ */ j("button", {
|
|
338
338
|
type: "button",
|
|
339
339
|
onClick: s,
|
|
340
340
|
style: F.closeButton,
|
|
341
341
|
onMouseOver: (e) => e.currentTarget.style.backgroundColor = "var(--color-bg-hover)",
|
|
342
342
|
onMouseOut: (e) => e.currentTarget.style.backgroundColor = "transparent",
|
|
343
|
-
children: /* @__PURE__ */
|
|
343
|
+
children: /* @__PURE__ */ j(k, { style: {
|
|
344
344
|
width: "16px",
|
|
345
345
|
height: "16px"
|
|
346
346
|
} })
|
|
347
347
|
})]
|
|
348
|
-
}), /* @__PURE__ */
|
|
348
|
+
}), /* @__PURE__ */ M("div", {
|
|
349
349
|
style: F.searchContainer,
|
|
350
|
-
children: [/* @__PURE__ */
|
|
350
|
+
children: [/* @__PURE__ */ j(T, { style: F.searchIcon }), /* @__PURE__ */ j(A, {
|
|
351
351
|
type: "text",
|
|
352
352
|
placeholder: "Search widgets...",
|
|
353
353
|
value: g,
|
|
@@ -356,32 +356,32 @@ var F = {
|
|
|
356
356
|
})]
|
|
357
357
|
})]
|
|
358
358
|
}),
|
|
359
|
-
/* @__PURE__ */
|
|
359
|
+
/* @__PURE__ */ j("div", {
|
|
360
360
|
style: F.content,
|
|
361
|
-
children: /* @__PURE__ */
|
|
361
|
+
children: /* @__PURE__ */ M("div", {
|
|
362
362
|
style: F.scrollArea,
|
|
363
|
-
children: [E.map((e) => /* @__PURE__ */
|
|
363
|
+
children: [E.map((e) => /* @__PURE__ */ M("div", {
|
|
364
364
|
style: F.categoryContainer,
|
|
365
|
-
children: [/* @__PURE__ */
|
|
365
|
+
children: [/* @__PURE__ */ M("button", {
|
|
366
366
|
type: "button",
|
|
367
367
|
onClick: () => D(e.category),
|
|
368
368
|
style: F.categoryHeader,
|
|
369
369
|
onMouseOver: (e) => e.currentTarget.style.backgroundColor = "var(--color-bg-hover)",
|
|
370
370
|
onMouseOut: (e) => e.currentTarget.style.backgroundColor = "transparent",
|
|
371
371
|
children: [
|
|
372
|
-
v.has(e.category) ? /* @__PURE__ */
|
|
373
|
-
/* @__PURE__ */
|
|
372
|
+
v.has(e.category) ? /* @__PURE__ */ j(u, { style: F.categoryChevron }) : /* @__PURE__ */ j(d, { style: F.categoryChevron }),
|
|
373
|
+
/* @__PURE__ */ j("span", {
|
|
374
374
|
style: F.categoryLabel,
|
|
375
375
|
children: e.label
|
|
376
376
|
}),
|
|
377
|
-
/* @__PURE__ */
|
|
377
|
+
/* @__PURE__ */ j("span", {
|
|
378
378
|
style: F.categoryCount,
|
|
379
379
|
children: e.widgets.length
|
|
380
380
|
})
|
|
381
381
|
]
|
|
382
|
-
}), v.has(e.category) && /* @__PURE__ */
|
|
382
|
+
}), v.has(e.category) && /* @__PURE__ */ M("div", {
|
|
383
383
|
style: F.widgetList,
|
|
384
|
-
children: [m && e.category === "Installed" && /* @__PURE__ */
|
|
384
|
+
children: [m && e.category === "Installed" && /* @__PURE__ */ j("div", {
|
|
385
385
|
style: {
|
|
386
386
|
fontSize: "var(--font-size-body-xs)",
|
|
387
387
|
color: "var(--color-text-muted)",
|
|
@@ -390,7 +390,7 @@ var F = {
|
|
|
390
390
|
children: "Loading..."
|
|
391
391
|
}), e.widgets.map((e) => {
|
|
392
392
|
let t = P(e.icon), r = n(e), i = S === r;
|
|
393
|
-
return /* @__PURE__ */
|
|
393
|
+
return /* @__PURE__ */ M("div", {
|
|
394
394
|
draggable: !0,
|
|
395
395
|
onDragStart: (t) => O(t, e),
|
|
396
396
|
onDragEnd: N,
|
|
@@ -402,17 +402,17 @@ var F = {
|
|
|
402
402
|
...i ? F.widgetCardHover : {}
|
|
403
403
|
},
|
|
404
404
|
children: [
|
|
405
|
-
/* @__PURE__ */
|
|
406
|
-
/* @__PURE__ */
|
|
405
|
+
/* @__PURE__ */ j(y, { style: F.dragHandle }),
|
|
406
|
+
/* @__PURE__ */ j("div", {
|
|
407
407
|
style: F.widgetIcon,
|
|
408
|
-
children: /* @__PURE__ */
|
|
408
|
+
children: /* @__PURE__ */ j(t, { style: F.widgetIconInner })
|
|
409
409
|
}),
|
|
410
|
-
/* @__PURE__ */
|
|
410
|
+
/* @__PURE__ */ M("div", {
|
|
411
411
|
style: F.widgetText,
|
|
412
|
-
children: [/* @__PURE__ */
|
|
412
|
+
children: [/* @__PURE__ */ j("div", {
|
|
413
413
|
style: F.widgetName,
|
|
414
414
|
children: e.name
|
|
415
|
-
}), /* @__PURE__ */
|
|
415
|
+
}), /* @__PURE__ */ j("div", {
|
|
416
416
|
style: F.widgetDescription,
|
|
417
417
|
children: e.description
|
|
418
418
|
})]
|
|
@@ -421,26 +421,26 @@ var F = {
|
|
|
421
421
|
}, r);
|
|
422
422
|
})]
|
|
423
423
|
})]
|
|
424
|
-
}, e.category)), E.length === 0 && /* @__PURE__ */
|
|
424
|
+
}, e.category)), E.length === 0 && /* @__PURE__ */ M("div", {
|
|
425
425
|
style: F.emptyState,
|
|
426
426
|
children: [
|
|
427
|
-
/* @__PURE__ */
|
|
427
|
+
/* @__PURE__ */ j("div", {
|
|
428
428
|
style: F.emptyIcon,
|
|
429
|
-
children: /* @__PURE__ */
|
|
429
|
+
children: /* @__PURE__ */ j(T, { style: {
|
|
430
430
|
width: "24px",
|
|
431
431
|
height: "24px",
|
|
432
432
|
color: "var(--color-text-muted)"
|
|
433
433
|
} })
|
|
434
434
|
}),
|
|
435
|
-
/* @__PURE__ */
|
|
435
|
+
/* @__PURE__ */ M("p", {
|
|
436
436
|
style: F.emptyText,
|
|
437
437
|
children: [
|
|
438
438
|
"No widgets found for \"",
|
|
439
|
-
/* @__PURE__ */
|
|
439
|
+
/* @__PURE__ */ j("strong", { children: g }),
|
|
440
440
|
"\""
|
|
441
441
|
]
|
|
442
442
|
}),
|
|
443
|
-
/* @__PURE__ */
|
|
443
|
+
/* @__PURE__ */ j("button", {
|
|
444
444
|
type: "button",
|
|
445
445
|
onClick: () => _(""),
|
|
446
446
|
style: F.clearButton,
|
|
@@ -450,9 +450,9 @@ var F = {
|
|
|
450
450
|
})]
|
|
451
451
|
})
|
|
452
452
|
}),
|
|
453
|
-
/* @__PURE__ */
|
|
453
|
+
/* @__PURE__ */ j("div", {
|
|
454
454
|
style: F.footer,
|
|
455
|
-
children: /* @__PURE__ */
|
|
455
|
+
children: /* @__PURE__ */ j("p", {
|
|
456
456
|
style: F.footerText,
|
|
457
457
|
children: "Drag widgets to position them on the canvas"
|
|
458
458
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { memo as e, useCallback as t, useMemo as n, useState as r } from "react";
|
|
2
2
|
import { ChevronLeft as i, ChevronRight as a, ChevronsLeft as o, ChevronsRight as s, Settings2 as c, X as l } from "lucide-react";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { Button as u } from "@burdenoff/fe-libs/ui";
|
|
4
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
5
5
|
import { Table as p, TableBody as m, TableCell as h, TableHead as g, TableHeader as _, TableRow as v } from "@burdenoff/fe-libs/ui/table";
|
|
6
6
|
//#region src/bigconsole/components/datasink/DataSinkTableViewer.tsx
|
|
7
7
|
function y(e) {
|
|
@@ -57,15 +57,15 @@ var w = e(function({ data: e, maxHeight: w = "400px" }) {
|
|
|
57
57
|
}, []), L = t(() => {
|
|
58
58
|
O(null), A(!1);
|
|
59
59
|
}, []);
|
|
60
|
-
return j.length === 0 ? /* @__PURE__ */
|
|
60
|
+
return j.length === 0 ? /* @__PURE__ */ d("div", {
|
|
61
61
|
className: "flex items-center justify-center p-8 text-text-secondary text-body-sm",
|
|
62
62
|
children: "No tabular data available. Data must be an array of objects for table view."
|
|
63
|
-
}) : /* @__PURE__ */
|
|
63
|
+
}) : /* @__PURE__ */ f("div", {
|
|
64
64
|
className: "relative",
|
|
65
65
|
children: [
|
|
66
|
-
/* @__PURE__ */
|
|
66
|
+
/* @__PURE__ */ f("div", {
|
|
67
67
|
className: "flex items-center justify-between p-3 bg-bg-sunken border-b border-border-default",
|
|
68
|
-
children: [/* @__PURE__ */
|
|
68
|
+
children: [/* @__PURE__ */ f("span", {
|
|
69
69
|
className: "text-xs text-text-secondary",
|
|
70
70
|
children: [
|
|
71
71
|
j.length,
|
|
@@ -73,39 +73,39 @@ var w = e(function({ data: e, maxHeight: w = "400px" }) {
|
|
|
73
73
|
N.length,
|
|
74
74
|
" columns"
|
|
75
75
|
]
|
|
76
|
-
}), /* @__PURE__ */
|
|
76
|
+
}), /* @__PURE__ */ d("div", {
|
|
77
77
|
className: "flex items-center gap-2",
|
|
78
|
-
children: /* @__PURE__ */ u
|
|
78
|
+
children: /* @__PURE__ */ d(u, {
|
|
79
79
|
variant: "ghost",
|
|
80
80
|
size: "sm",
|
|
81
81
|
onClick: () => A((e) => !e),
|
|
82
|
-
children: /* @__PURE__ */
|
|
82
|
+
children: /* @__PURE__ */ d(c, { className: "w-4 h-4" })
|
|
83
83
|
})
|
|
84
84
|
})]
|
|
85
85
|
}),
|
|
86
|
-
k && /* @__PURE__ */
|
|
86
|
+
k && /* @__PURE__ */ f("div", {
|
|
87
87
|
className: "absolute right-0 top-10 z-10 bg-bg-surface border border-border-default rounded-md shadow-lg p-3 min-w-[200px] max-h-[300px] overflow-auto",
|
|
88
|
-
children: [/* @__PURE__ */
|
|
88
|
+
children: [/* @__PURE__ */ f("div", {
|
|
89
89
|
className: "flex items-center justify-between mb-2",
|
|
90
|
-
children: [/* @__PURE__ */
|
|
90
|
+
children: [/* @__PURE__ */ d("span", {
|
|
91
91
|
className: "text-xs font-medium text-text-primary",
|
|
92
92
|
children: "Select Columns"
|
|
93
|
-
}), /* @__PURE__ */ u
|
|
93
|
+
}), /* @__PURE__ */ d(u, {
|
|
94
94
|
variant: "ghost",
|
|
95
95
|
size: "sm",
|
|
96
96
|
onClick: L,
|
|
97
|
-
children: /* @__PURE__ */
|
|
97
|
+
children: /* @__PURE__ */ d(l, { className: "w-3 h-3" })
|
|
98
98
|
})]
|
|
99
|
-
}), /* @__PURE__ */
|
|
99
|
+
}), /* @__PURE__ */ d("div", {
|
|
100
100
|
className: "space-y-1",
|
|
101
|
-
children: M.map((e) => /* @__PURE__ */
|
|
101
|
+
children: M.map((e) => /* @__PURE__ */ f("label", {
|
|
102
102
|
className: "flex items-center gap-2 text-xs text-text-secondary hover:text-text-primary cursor-pointer",
|
|
103
|
-
children: [/* @__PURE__ */
|
|
103
|
+
children: [/* @__PURE__ */ d("input", {
|
|
104
104
|
type: "checkbox",
|
|
105
105
|
checked: !D || D.includes(e.key),
|
|
106
106
|
onChange: () => I(e.key),
|
|
107
107
|
className: "rounded border-border-default"
|
|
108
|
-
}), /* @__PURE__ */
|
|
108
|
+
}), /* @__PURE__ */ d("span", {
|
|
109
109
|
className: "truncate",
|
|
110
110
|
title: e.key,
|
|
111
111
|
children: e.label
|
|
@@ -113,17 +113,17 @@ var w = e(function({ data: e, maxHeight: w = "400px" }) {
|
|
|
113
113
|
}, e.key))
|
|
114
114
|
})]
|
|
115
115
|
}),
|
|
116
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ d("div", {
|
|
117
117
|
className: "overflow-auto",
|
|
118
118
|
style: { maxHeight: w },
|
|
119
|
-
children: /* @__PURE__ */
|
|
119
|
+
children: /* @__PURE__ */ f(p, { children: [/* @__PURE__ */ d(_, { children: /* @__PURE__ */ d(v, { children: N.map((e) => /* @__PURE__ */ d(g, {
|
|
120
120
|
title: e.path,
|
|
121
121
|
children: e.label
|
|
122
|
-
}, e.key)) }) }), /* @__PURE__ */
|
|
122
|
+
}, e.key)) }) }), /* @__PURE__ */ d(m, { children: P.map((e, t) => /* @__PURE__ */ d(v, { children: N.map((t) => /* @__PURE__ */ d(h, { children: C(S(e, t.path)) }, t.key)) }, t)) })] })
|
|
123
123
|
}),
|
|
124
|
-
F > 1 && /* @__PURE__ */
|
|
124
|
+
F > 1 && /* @__PURE__ */ f("div", {
|
|
125
125
|
className: "flex items-center justify-between p-3 bg-bg-sunken border-t border-border-default",
|
|
126
|
-
children: [/* @__PURE__ */
|
|
126
|
+
children: [/* @__PURE__ */ f("span", {
|
|
127
127
|
className: "text-xs text-text-secondary",
|
|
128
128
|
children: [
|
|
129
129
|
"Page ",
|
|
@@ -131,36 +131,36 @@ var w = e(function({ data: e, maxHeight: w = "400px" }) {
|
|
|
131
131
|
" of ",
|
|
132
132
|
F
|
|
133
133
|
]
|
|
134
|
-
}), /* @__PURE__ */
|
|
134
|
+
}), /* @__PURE__ */ f("div", {
|
|
135
135
|
className: "flex items-center gap-1",
|
|
136
136
|
children: [
|
|
137
|
-
/* @__PURE__ */ u
|
|
137
|
+
/* @__PURE__ */ d(u, {
|
|
138
138
|
variant: "ghost",
|
|
139
139
|
size: "sm",
|
|
140
140
|
onClick: () => E(0),
|
|
141
141
|
disabled: T === 0,
|
|
142
|
-
children: /* @__PURE__ */
|
|
142
|
+
children: /* @__PURE__ */ d(o, { className: "w-4 h-4" })
|
|
143
143
|
}),
|
|
144
|
-
/* @__PURE__ */ u
|
|
144
|
+
/* @__PURE__ */ d(u, {
|
|
145
145
|
variant: "ghost",
|
|
146
146
|
size: "sm",
|
|
147
147
|
onClick: () => E((e) => Math.max(0, e - 1)),
|
|
148
148
|
disabled: T === 0,
|
|
149
|
-
children: /* @__PURE__ */
|
|
149
|
+
children: /* @__PURE__ */ d(i, { className: "w-4 h-4" })
|
|
150
150
|
}),
|
|
151
|
-
/* @__PURE__ */ u
|
|
151
|
+
/* @__PURE__ */ d(u, {
|
|
152
152
|
variant: "ghost",
|
|
153
153
|
size: "sm",
|
|
154
154
|
onClick: () => E((e) => Math.min(F - 1, e + 1)),
|
|
155
155
|
disabled: T >= F - 1,
|
|
156
|
-
children: /* @__PURE__ */
|
|
156
|
+
children: /* @__PURE__ */ d(a, { className: "w-4 h-4" })
|
|
157
157
|
}),
|
|
158
|
-
/* @__PURE__ */ u
|
|
158
|
+
/* @__PURE__ */ d(u, {
|
|
159
159
|
variant: "ghost",
|
|
160
160
|
size: "sm",
|
|
161
161
|
onClick: () => E(F - 1),
|
|
162
162
|
disabled: T >= F - 1,
|
|
163
|
-
children: /* @__PURE__ */
|
|
163
|
+
children: /* @__PURE__ */ d(s, { className: "w-4 h-4" })
|
|
164
164
|
})
|
|
165
165
|
]
|
|
166
166
|
})]
|