@burdenoff/microfe-bigconsole 2026.622.1 → 2026.624.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bigconsole/BigConsoleRoutes.js +1 -1
- package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
- package/dist/bigconsole/components/DrilldownModal.js +4 -4
- package/dist/bigconsole/components/DrilldownModal.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +2 -2
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +1 -1
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +28 -28
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +4 -4
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDataViewer.js +2 -2
- package/dist/bigconsole/components/datasink/DataSinkDataViewer.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +2 -2
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +2 -2
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +2 -2
- package/dist/bigconsole/components/datasink/DataSinkTableViewer.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +25 -25
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedParsersPanel.js +1 -1
- package/dist/bigconsole/components/datasink/LinkedParsersPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +3 -3
- package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +2 -2
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +2 -2
- package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
- package/dist/bigconsole/components/parser/DataSinkSelector.js +3 -3
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ImportParserDialog.js +26 -26
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserCard.js +5 -5
- package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +6 -6
- package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserStatusBadge.js +1 -1
- package/dist/bigconsole/components/parser/ParserStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserTypeBadge.js +1 -1
- package/dist/bigconsole/components/parser/ParserTypeBadge.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineCard.js +2 -2
- package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js +1 -1
- package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +1 -1
- package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +11 -11
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +17 -17
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetConfigDialog.js +14 -14
- package/dist/bigconsole/components/widgets/WidgetConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetHeader.js +4 -4
- package/dist/bigconsole/components/widgets/WidgetHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js +3 -3
- package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetWrapper.js +266 -238
- package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +2 -2
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
- package/dist/bigconsole/components/widgets/custom/CustomWidget.js +5 -5
- package/dist/bigconsole/components/widgets/custom/CustomWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/LinearGauge.js +1 -1
- package/dist/bigconsole/components/widgets/gauge/LinearGauge.js.map +1 -1
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +2 -2
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi/KPIWidget.js +2 -2
- package/dist/bigconsole/components/widgets/kpi/KPIWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js +2 -2
- package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListItem.js +3 -3
- package/dist/bigconsole/components/widgets/list/ListItem.js.map +1 -1
- package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +3 -3
- package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/ComparisonBadge.js +1 -1
- package/dist/bigconsole/components/widgets/metric-card/ComparisonBadge.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js +2 -2
- package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +12 -12
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressBar.js +2 -2
- package/dist/bigconsole/components/widgets/progress/ProgressBar.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressWidget.js +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js +2 -2
- package/dist/bigconsole/components/widgets/retention/RetentionWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/states/EmptyState.js +1 -1
- package/dist/bigconsole/components/widgets/states/EmptyState.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableCell.js +1 -1
- package/dist/bigconsole/components/widgets/table/TableCell.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableHeader.js +2 -2
- package/dist/bigconsole/components/widgets/table/TableHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TablePagination.js +4 -4
- package/dist/bigconsole/components/widgets/table/TablePagination.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableWidget.js +5 -5
- package/dist/bigconsole/components/widgets/table/TableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/text-widget/TextWidget.js +1 -1
- package/dist/bigconsole/components/widgets/text-widget/TextWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +3 -3
- package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/utils/conditionalFormat.js +2 -2
- package/dist/bigconsole/components/widgets/utils/conditionalFormat.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +3 -3
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js +2 -2
- package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +1 -1
- package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +2 -2
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +2 -2
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +3 -3
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +2 -2
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +5 -5
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +4 -4
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +9 -9
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WidgetDemoPage.js +2 -2
- package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +5 -5
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +12 -12
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BigConsoleRenderer.js +2 -2
- package/dist/bigconsole/renderers/adapters/BigConsoleRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +5 -5
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js +2 -2
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
- package/package.json +1 -1
|
@@ -69,7 +69,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
69
69
|
/* @__PURE__ */ g(ee, { children: [/* @__PURE__ */ g("div", {
|
|
70
70
|
className: "flex items-center gap-3",
|
|
71
71
|
children: [/* @__PURE__ */ h("div", {
|
|
72
|
-
className: "flex size-10 items-center justify-center rounded-lg bg-primary/10",
|
|
72
|
+
className: "flex size-10 items-center justify-center rounded-lg bg-action-primary-bg/10",
|
|
73
73
|
children: /* @__PURE__ */ h(f, { className: "size-5 text-primary" })
|
|
74
74
|
}), /* @__PURE__ */ h(E, { children: "Import Dashboard" })]
|
|
75
75
|
}), /* @__PURE__ */ h(w, { children: "Upload a Dashboard export file to restore it into this workspace." })] }),
|
|
@@ -81,13 +81,13 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
81
81
|
onDrop: te,
|
|
82
82
|
className: "border-2 border-dashed rounded-lg p-8 text-center hover:border-primary transition-colors",
|
|
83
83
|
children: [
|
|
84
|
-
/* @__PURE__ */ h(l, { className: "size-12 mx-auto text-
|
|
84
|
+
/* @__PURE__ */ h(l, { className: "size-12 mx-auto text-text-secondary mb-4" }),
|
|
85
85
|
/* @__PURE__ */ h("p", {
|
|
86
86
|
className: "text-sm mb-2",
|
|
87
87
|
children: "Drag and drop a dashboard export file here"
|
|
88
88
|
}),
|
|
89
89
|
/* @__PURE__ */ h("p", {
|
|
90
|
-
className: "text-xs text-
|
|
90
|
+
className: "text-xs text-text-secondary mb-4",
|
|
91
91
|
children: "or"
|
|
92
92
|
}),
|
|
93
93
|
/* @__PURE__ */ h("input", {
|
|
@@ -103,7 +103,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
103
103
|
children: "Browse Files"
|
|
104
104
|
}),
|
|
105
105
|
/* @__PURE__ */ h("p", {
|
|
106
|
-
className: "text-xs text-
|
|
106
|
+
className: "text-xs text-text-secondary mt-4",
|
|
107
107
|
children: "Only .json files exported from BigConsole are supported"
|
|
108
108
|
})
|
|
109
109
|
]
|
|
@@ -115,7 +115,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
115
115
|
/* @__PURE__ */ g("div", {
|
|
116
116
|
className: "flex items-center justify-between",
|
|
117
117
|
children: [/* @__PURE__ */ h("span", {
|
|
118
|
-
className: "text-sm text-
|
|
118
|
+
className: "text-sm text-text-secondary",
|
|
119
119
|
children: "Dashboard"
|
|
120
120
|
}), /* @__PURE__ */ h("span", {
|
|
121
121
|
className: "text-sm font-medium",
|
|
@@ -125,7 +125,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
125
125
|
q.dashboardInfo.description && /* @__PURE__ */ g("div", {
|
|
126
126
|
className: "flex items-start justify-between",
|
|
127
127
|
children: [/* @__PURE__ */ h("span", {
|
|
128
|
-
className: "text-sm text-
|
|
128
|
+
className: "text-sm text-text-secondary",
|
|
129
129
|
children: "Description"
|
|
130
130
|
}), /* @__PURE__ */ h("span", {
|
|
131
131
|
className: "text-sm text-right max-w-[60%] truncate",
|
|
@@ -135,7 +135,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
135
135
|
/* @__PURE__ */ g("div", {
|
|
136
136
|
className: "flex items-center justify-between",
|
|
137
137
|
children: [/* @__PURE__ */ h("span", {
|
|
138
|
-
className: "text-sm text-
|
|
138
|
+
className: "text-sm text-text-secondary",
|
|
139
139
|
children: "Pages"
|
|
140
140
|
}), /* @__PURE__ */ h(_, {
|
|
141
141
|
variant: "secondary",
|
|
@@ -145,7 +145,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
145
145
|
/* @__PURE__ */ g("div", {
|
|
146
146
|
className: "flex items-center justify-between",
|
|
147
147
|
children: [/* @__PURE__ */ h("span", {
|
|
148
|
-
className: "text-sm text-
|
|
148
|
+
className: "text-sm text-text-secondary",
|
|
149
149
|
children: "Widgets"
|
|
150
150
|
}), /* @__PURE__ */ h(_, {
|
|
151
151
|
variant: "secondary",
|
|
@@ -155,33 +155,33 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
155
155
|
q.dashboardInfo.exportedFrom && /* @__PURE__ */ g("div", {
|
|
156
156
|
className: "flex items-center justify-between",
|
|
157
157
|
children: [/* @__PURE__ */ h("span", {
|
|
158
|
-
className: "text-sm text-
|
|
158
|
+
className: "text-sm text-text-secondary",
|
|
159
159
|
children: "Source ID"
|
|
160
160
|
}), /* @__PURE__ */ h("span", {
|
|
161
|
-
className: "text-xs text-
|
|
161
|
+
className: "text-xs text-text-secondary font-mono truncate max-w-[180px]",
|
|
162
162
|
children: q.dashboardInfo.exportedFrom
|
|
163
163
|
})]
|
|
164
164
|
}),
|
|
165
165
|
/* @__PURE__ */ g("div", {
|
|
166
166
|
className: "flex items-center justify-between",
|
|
167
167
|
children: [/* @__PURE__ */ h("span", {
|
|
168
|
-
className: "text-sm text-
|
|
168
|
+
className: "text-sm text-text-secondary",
|
|
169
169
|
children: "Schema Version"
|
|
170
170
|
}), /* @__PURE__ */ h("span", {
|
|
171
|
-
className: "text-xs text-
|
|
171
|
+
className: "text-xs text-text-secondary",
|
|
172
172
|
children: q.dashboardInfo.schemaVersion
|
|
173
173
|
})]
|
|
174
174
|
})
|
|
175
175
|
]
|
|
176
176
|
}) }),
|
|
177
177
|
q.errors.length > 0 && /* @__PURE__ */ h(y, {
|
|
178
|
-
className: "border-
|
|
178
|
+
className: "border-status-error-border/50 bg-status-error-bg/5",
|
|
179
179
|
children: /* @__PURE__ */ g(b, {
|
|
180
180
|
className: "p-3",
|
|
181
181
|
children: [/* @__PURE__ */ g("div", {
|
|
182
182
|
className: "flex items-center gap-2 mb-2",
|
|
183
|
-
children: [/* @__PURE__ */ h(p, { className: "size-4 text-
|
|
184
|
-
className: "text-sm font-medium text-
|
|
183
|
+
children: [/* @__PURE__ */ h(p, { className: "size-4 text-status-error-text" }), /* @__PURE__ */ g("span", {
|
|
184
|
+
className: "text-sm font-medium text-status-error-text",
|
|
185
185
|
children: [
|
|
186
186
|
"Errors (",
|
|
187
187
|
q.errors.length,
|
|
@@ -189,7 +189,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
189
189
|
]
|
|
190
190
|
})]
|
|
191
191
|
}), /* @__PURE__ */ h("ul", {
|
|
192
|
-
className: "text-xs text-
|
|
192
|
+
className: "text-xs text-status-error-text space-y-1",
|
|
193
193
|
children: q.errors.map((e, t) => /* @__PURE__ */ g("li", { children: [
|
|
194
194
|
/* @__PURE__ */ g("span", {
|
|
195
195
|
className: "font-mono",
|
|
@@ -345,7 +345,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
345
345
|
children: "Dashboard Already Exists"
|
|
346
346
|
}),
|
|
347
347
|
/* @__PURE__ */ g("p", {
|
|
348
|
-
className: "text-sm text-
|
|
348
|
+
className: "text-sm text-text-secondary mb-4",
|
|
349
349
|
children: [
|
|
350
350
|
"Dashboard \"",
|
|
351
351
|
J.dashboard?.name,
|
|
@@ -363,7 +363,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
363
363
|
children: "Dashboard Updated!"
|
|
364
364
|
}),
|
|
365
365
|
/* @__PURE__ */ g("p", {
|
|
366
|
-
className: "text-sm text-
|
|
366
|
+
className: "text-sm text-text-secondary mb-4",
|
|
367
367
|
children: [
|
|
368
368
|
"Dashboard \"",
|
|
369
369
|
J.dashboard?.name,
|
|
@@ -381,7 +381,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
381
381
|
children: "Import Successful!"
|
|
382
382
|
}),
|
|
383
383
|
/* @__PURE__ */ g("p", {
|
|
384
|
-
className: "text-sm text-
|
|
384
|
+
className: "text-sm text-text-secondary mb-4",
|
|
385
385
|
children: [
|
|
386
386
|
"Dashboard \"",
|
|
387
387
|
J.dashboard?.name,
|
|
@@ -393,23 +393,23 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
393
393
|
children: /* @__PURE__ */ g(b, {
|
|
394
394
|
className: "p-4",
|
|
395
395
|
children: [/* @__PURE__ */ h("p", {
|
|
396
|
-
className: "text-xs font-medium text-
|
|
396
|
+
className: "text-xs font-medium text-text-secondary mb-2",
|
|
397
397
|
children: "Import Summary"
|
|
398
398
|
}), /* @__PURE__ */ g("div", {
|
|
399
399
|
className: "grid grid-cols-2 gap-x-6 gap-y-1 text-xs",
|
|
400
400
|
children: [
|
|
401
401
|
/* @__PURE__ */ h("span", {
|
|
402
|
-
className: "text-
|
|
402
|
+
className: "text-text-secondary",
|
|
403
403
|
children: "Pages:"
|
|
404
404
|
}),
|
|
405
405
|
/* @__PURE__ */ h("span", { children: J.stats.pagesCreated }),
|
|
406
406
|
/* @__PURE__ */ h("span", {
|
|
407
|
-
className: "text-
|
|
407
|
+
className: "text-text-secondary",
|
|
408
408
|
children: "Widgets:"
|
|
409
409
|
}),
|
|
410
410
|
/* @__PURE__ */ h("span", { children: J.stats.widgetsCreated }),
|
|
411
411
|
/* @__PURE__ */ h("span", {
|
|
412
|
-
className: "text-
|
|
412
|
+
className: "text-text-secondary",
|
|
413
413
|
children: "Actions:"
|
|
414
414
|
}),
|
|
415
415
|
/* @__PURE__ */ h("span", { children: J.stats.actionsCreated })
|
|
@@ -421,21 +421,21 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
421
421
|
]
|
|
422
422
|
}),
|
|
423
423
|
K && /* @__PURE__ */ h(y, {
|
|
424
|
-
className: "border-
|
|
424
|
+
className: "border-status-error-border/50 bg-status-error-bg/5",
|
|
425
425
|
children: /* @__PURE__ */ h(b, {
|
|
426
426
|
className: "p-3",
|
|
427
427
|
children: /* @__PURE__ */ h("p", {
|
|
428
|
-
className: "text-sm text-
|
|
428
|
+
className: "text-sm text-status-error-text",
|
|
429
429
|
children: K.message
|
|
430
430
|
})
|
|
431
431
|
})
|
|
432
432
|
}),
|
|
433
433
|
J && !J.success && J.errorMessage && /* @__PURE__ */ h(y, {
|
|
434
|
-
className: "border-
|
|
434
|
+
className: "border-status-error-border/50 bg-status-error-bg/5",
|
|
435
435
|
children: /* @__PURE__ */ h(b, {
|
|
436
436
|
className: "p-3",
|
|
437
437
|
children: /* @__PURE__ */ h("p", {
|
|
438
|
-
className: "text-sm text-
|
|
438
|
+
className: "text-sm text-status-error-text",
|
|
439
439
|
children: J.errorMessage
|
|
440
440
|
})
|
|
441
441
|
})
|
|
@@ -466,7 +466,7 @@ var j = t(function({ isOpen: t, onClose: j, onSuccess: M }) {
|
|
|
466
466
|
children: [/* @__PURE__ */ h(f, { className: "size-4" }), "Import Dashboard"]
|
|
467
467
|
}),
|
|
468
468
|
N === "importing" && /* @__PURE__ */ g("div", {
|
|
469
|
-
className: "flex items-center gap-2 text-sm text-
|
|
469
|
+
className: "flex items-center gap-2 text-sm text-text-secondary",
|
|
470
470
|
children: [/* @__PURE__ */ h(k, { className: "size-4" }), "Importing..."]
|
|
471
471
|
}),
|
|
472
472
|
N === "complete" && /* @__PURE__ */ h(v, {
|
|
@@ -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-primary/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-muted-foreground mb-4\" />\n <p className=\"text-sm mb-2\">Drag and drop a dashboard export file here</p>\n <p className=\"text-xs text-muted-foreground 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-muted-foreground 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-muted-foreground\">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-muted-foreground\">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-muted-foreground\">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-muted-foreground\">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-muted-foreground\">Source ID</span>\n <span className=\"text-xs text-muted-foreground 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-muted-foreground\">Schema Version</span>\n <span className=\"text-xs text-muted-foreground\">\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-destructive/50 bg-destructive/5\">\n <CardContent className=\"p-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <XCircle className=\"size-4 text-destructive\" />\n <span className=\"text-sm font-medium text-destructive\">\n Errors ({validationResult.errors.length})\n </span>\n </div>\n <ul className=\"text-xs text-destructive 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-muted-foreground 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-muted-foreground 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-muted-foreground 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-muted-foreground mb-2\">Import Summary</p>\n <div className=\"grid grid-cols-2 gap-x-6 gap-y-1 text-xs\">\n <span className=\"text-muted-foreground\">Pages:</span>\n <span>{importResult.stats.pagesCreated}</span>\n <span className=\"text-muted-foreground\">Widgets:</span>\n <span>{importResult.stats.widgetsCreated}</span>\n <span className=\"text-muted-foreground\">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-destructive/50 bg-destructive/5\">\n <CardContent className=\"p-3\">\n <p className=\"text-sm text-destructive\">{error.message}</p>\n </CardContent>\n </Card>\n )}\n\n {importResult && !importResult.success && importResult.errorMessage && (\n <Card className=\"border-destructive/50 bg-destructive/5\">\n <CardContent className=\"p-3\">\n <p className=\"text-sm text-destructive\">{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-muted-foreground\">\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\">\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheTTLSelector.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/CacheTTLSelector.tsx"],"sourcesContent":["/**\n * Cache TTL Selector\n *\n * Component for selecting cache duration with preset options and custom input.\n */\n\nimport { memo, useState, useEffect, useCallback, useRef } from 'react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface CacheTTLOption {\n value: number;\n label: string;\n description: string;\n recommended?: boolean;\n}\n\ninterface CacheTTLSelectorProps {\n /** Current TTL value in seconds (null for no cache) */\n value: number | null;\n /** Callback when value changes */\n onChange: (value: number) => void;\n /** Whether selector is disabled */\n disabled?: boolean;\n /** Error message */\n error?: string;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst PRESET_OPTIONS: CacheTTLOption[] = [\n {\n value: 300, // 5 minutes\n label: '5 minutes',\n description: 'Best for real-time dashboards',\n },\n {\n value: 900, // 15 minutes\n label: '15 minutes',\n description: 'Balanced performance',\n recommended: true,\n },\n {\n value: 3600, // 1 hour\n label: '1 hour',\n description: 'For data that changes hourly',\n },\n {\n value: 86400, // 24 hours\n label: '24 hours',\n description: 'For daily reports',\n },\n];\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/**\n * Check if value is a preset option\n */\nfunction isPresetValue(value: number | null): boolean {\n if (value === null) return false;\n return PRESET_OPTIONS.some((opt) => opt.value === value);\n}\n\n/**\n * Format seconds to human-readable string\n */\nfunction formatDuration(seconds: number): string {\n if (seconds < 60) {\n return `${seconds} seconds`;\n }\n if (seconds < 3600) {\n return `${Math.floor(seconds / 60)} minutes`;\n }\n if (seconds < 86400) {\n return `${Math.floor(seconds / 3600)} hours`;\n }\n return `${Math.floor(seconds / 86400)} days`;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const CacheTTLSelector = memo(function CacheTTLSelector({\n value,\n onChange,\n disabled = false,\n error,\n}: CacheTTLSelectorProps) {\n // Track whether custom mode is active\n const [isCustom, setIsCustom] = useState(!isPresetValue(value) && value !== null);\n const [customValue, setCustomValue] = useState(value?.toString() || '');\n const [validationError, setValidationError] = useState<string | null>(null);\n const prevValueRef = useRef(value);\n\n // Sync custom value when external value changes (using deferred update to avoid cascading renders)\n useEffect(() => {\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n if (value !== null && !isPresetValue(value)) {\n // Defer state update to avoid synchronous setState in effect\n queueMicrotask(() => {\n setCustomValue(value.toString());\n setIsCustom(true);\n });\n }\n }\n }, [value]);\n\n // Handle preset selection\n const handlePresetChange = useCallback(\n (presetValue: number) => {\n if (disabled) return;\n setIsCustom(false);\n onChange(presetValue);\n },\n [disabled, onChange]\n );\n\n // Handle custom mode activation\n const handleCustomSelect = useCallback(() => {\n if (disabled) return;\n setIsCustom(true);\n const parsed = parseInt(customValue);\n if (!isNaN(parsed) && parsed >= 30 && parsed <= 86400) {\n onChange(parsed);\n }\n }, [disabled, customValue, onChange]);\n\n // Handle custom value change with validation\n const handleCustomChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = e.target.value;\n setCustomValue(inputValue);\n\n // Validate input\n if (inputValue === '') {\n setValidationError(null);\n return;\n }\n\n const parsed = parseInt(inputValue);\n\n if (isNaN(parsed)) {\n setValidationError('Please enter a valid number');\n return;\n }\n\n if (parsed < 30) {\n setValidationError('Minimum cache duration is 30 seconds');\n return;\n }\n\n if (parsed > 86400) {\n setValidationError('Maximum cache duration is 86400 seconds (24 hours)');\n return;\n }\n\n // Valid value\n setValidationError(null);\n onChange(parsed);\n },\n [onChange]\n );\n\n return (\n <div className=\"space-y-3\">\n {/* Label */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Cache Duration</label>\n <p className=\"text-xs text-text-secondary\">How long should data be cached before refreshing?</p>\n </div>\n\n {/* Options */}\n <div className=\"space-y-2\">\n {/* Preset options */}\n {PRESET_OPTIONS.map((option) => (\n <label\n key={option.value}\n className={`\n flex items-start gap-3\n p-3\n border rounded-lg\n cursor-pointer\n transition-all\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${\n !isCustom && value === option.value\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-default hover:border-border-hover'\n }\n `}\n >\n <input\n type=\"radio\"\n name=\"cache-ttl\"\n checked={!isCustom && value === option.value}\n onChange={() => handlePresetChange(option.value)}\n disabled={disabled}\n className={`\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n `}\n />\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">{option.label}</span>\n {option.recommended && (\n <span className=\"px-1.5 py-0.5 text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded\">\n Recommended\n </span>\n )}\n </div>\n <p className=\"text-xs text-text-secondary mt-0.5\">{option.description}</p>\n </div>\n </label>\n ))}\n\n {/* Custom option */}\n <label\n className={`\n flex items-start gap-3\n p-3\n border rounded-lg\n cursor-pointer\n transition-all\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${\n isCustom\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-default hover:border-border-hover'\n }\n `}\n >\n <input\n type=\"radio\"\n name=\"cache-ttl\"\n checked={isCustom}\n onChange={handleCustomSelect}\n disabled={disabled}\n className={`\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n `}\n />\n <div className=\"flex-1\">\n <span className=\"text-sm font-medium text-text-primary\">Custom</span>\n <p className=\"text-xs text-text-secondary mt-0.5\">Enter a custom cache duration (30 - 86400 seconds)</p>\n {isCustom && (\n <>\n <div className=\"mt-3 flex items-center gap-2\">\n <input\n type=\"number\"\n value={customValue}\n onChange={handleCustomChange}\n disabled={disabled}\n min={30}\n max={86400}\n placeholder=\"300\"\n className={`\n w-32 px-3 py-2\n bg-bg-muted\n border rounded-md\n text-sm text-text-primary\n placeholder-text-tertiary\n focus:outline-none\n focus:border-action-primary-bg\n focus:ring-2\n focus:ring-action-primary-bg/20\n ${error || validationError ? 'border-state-error' : 'border-border-default'}\n `}\n />\n <span className=\"text-sm text-text-secondary\">seconds</span>\n {customValue && !isNaN(parseInt(customValue)) && !validationError && (\n <span className=\"text-xs text-text-tertiary\">({formatDuration(parseInt(customValue))})</span>\n )}\n </div>\n {validationError && (\n <div className=\"flex items-center gap-1 mt-1\">\n <svg\n className=\"w-3.5 h-3.5 text-state-error flex-shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span className=\"text-xs text-state-error\">{validationError}</span>\n </div>\n )}\n </>\n )}\n </div>\n </label>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"flex items-start gap-2\">\n <svg\n className=\"w-4 h-4 text-state-error flex-shrink-0 mt-0.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <p className=\"text-xs text-state-error\">{error}</p>\n </div>\n )}\n\n {/* Info message */}\n {value !== null && !error && (\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span>Data will be cached for {formatDuration(value)} before being refreshed</span>\n </div>\n )}\n </div>\n );\n});\n\nexport default CacheTTLSelector;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CacheTTLSelector.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/CacheTTLSelector.tsx"],"sourcesContent":["/**\n * Cache TTL Selector\n *\n * Component for selecting cache duration with preset options and custom input.\n */\n\nimport { memo, useState, useEffect, useCallback, useRef } from 'react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface CacheTTLOption {\n value: number;\n label: string;\n description: string;\n recommended?: boolean;\n}\n\ninterface CacheTTLSelectorProps {\n /** Current TTL value in seconds (null for no cache) */\n value: number | null;\n /** Callback when value changes */\n onChange: (value: number) => void;\n /** Whether selector is disabled */\n disabled?: boolean;\n /** Error message */\n error?: string;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst PRESET_OPTIONS: CacheTTLOption[] = [\n {\n value: 300, // 5 minutes\n label: '5 minutes',\n description: 'Best for real-time dashboards',\n },\n {\n value: 900, // 15 minutes\n label: '15 minutes',\n description: 'Balanced performance',\n recommended: true,\n },\n {\n value: 3600, // 1 hour\n label: '1 hour',\n description: 'For data that changes hourly',\n },\n {\n value: 86400, // 24 hours\n label: '24 hours',\n description: 'For daily reports',\n },\n];\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/**\n * Check if value is a preset option\n */\nfunction isPresetValue(value: number | null): boolean {\n if (value === null) return false;\n return PRESET_OPTIONS.some((opt) => opt.value === value);\n}\n\n/**\n * Format seconds to human-readable string\n */\nfunction formatDuration(seconds: number): string {\n if (seconds < 60) {\n return `${seconds} seconds`;\n }\n if (seconds < 3600) {\n return `${Math.floor(seconds / 60)} minutes`;\n }\n if (seconds < 86400) {\n return `${Math.floor(seconds / 3600)} hours`;\n }\n return `${Math.floor(seconds / 86400)} days`;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const CacheTTLSelector = memo(function CacheTTLSelector({\n value,\n onChange,\n disabled = false,\n error,\n}: CacheTTLSelectorProps) {\n // Track whether custom mode is active\n const [isCustom, setIsCustom] = useState(!isPresetValue(value) && value !== null);\n const [customValue, setCustomValue] = useState(value?.toString() || '');\n const [validationError, setValidationError] = useState<string | null>(null);\n const prevValueRef = useRef(value);\n\n // Sync custom value when external value changes (using deferred update to avoid cascading renders)\n useEffect(() => {\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n if (value !== null && !isPresetValue(value)) {\n // Defer state update to avoid synchronous setState in effect\n queueMicrotask(() => {\n setCustomValue(value.toString());\n setIsCustom(true);\n });\n }\n }\n }, [value]);\n\n // Handle preset selection\n const handlePresetChange = useCallback(\n (presetValue: number) => {\n if (disabled) return;\n setIsCustom(false);\n onChange(presetValue);\n },\n [disabled, onChange]\n );\n\n // Handle custom mode activation\n const handleCustomSelect = useCallback(() => {\n if (disabled) return;\n setIsCustom(true);\n const parsed = parseInt(customValue);\n if (!isNaN(parsed) && parsed >= 30 && parsed <= 86400) {\n onChange(parsed);\n }\n }, [disabled, customValue, onChange]);\n\n // Handle custom value change with validation\n const handleCustomChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = e.target.value;\n setCustomValue(inputValue);\n\n // Validate input\n if (inputValue === '') {\n setValidationError(null);\n return;\n }\n\n const parsed = parseInt(inputValue);\n\n if (isNaN(parsed)) {\n setValidationError('Please enter a valid number');\n return;\n }\n\n if (parsed < 30) {\n setValidationError('Minimum cache duration is 30 seconds');\n return;\n }\n\n if (parsed > 86400) {\n setValidationError('Maximum cache duration is 86400 seconds (24 hours)');\n return;\n }\n\n // Valid value\n setValidationError(null);\n onChange(parsed);\n },\n [onChange]\n );\n\n return (\n <div className=\"space-y-3\">\n {/* Label */}\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Cache Duration</label>\n <p className=\"text-xs text-text-secondary\">How long should data be cached before refreshing?</p>\n </div>\n\n {/* Options */}\n <div className=\"space-y-2\">\n {/* Preset options */}\n {PRESET_OPTIONS.map((option) => (\n <label\n key={option.value}\n className={`\n flex items-start gap-3\n p-3\n border rounded-lg\n cursor-pointer\n transition-all\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${\n !isCustom && value === option.value\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-default hover:border-border-hover'\n }\n `}\n >\n <input\n type=\"radio\"\n name=\"cache-ttl\"\n checked={!isCustom && value === option.value}\n onChange={() => handlePresetChange(option.value)}\n disabled={disabled}\n className={`\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n `}\n />\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">{option.label}</span>\n {option.recommended && (\n <span className=\"px-1.5 py-0.5 text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded\">\n Recommended\n </span>\n )}\n </div>\n <p className=\"text-xs text-text-secondary mt-0.5\">{option.description}</p>\n </div>\n </label>\n ))}\n\n {/* Custom option */}\n <label\n className={`\n flex items-start gap-3\n p-3\n border rounded-lg\n cursor-pointer\n transition-all\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${\n isCustom\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-default hover:border-border-hover'\n }\n `}\n >\n <input\n type=\"radio\"\n name=\"cache-ttl\"\n checked={isCustom}\n onChange={handleCustomSelect}\n disabled={disabled}\n className={`\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n `}\n />\n <div className=\"flex-1\">\n <span className=\"text-sm font-medium text-text-primary\">Custom</span>\n <p className=\"text-xs text-text-secondary mt-0.5\">Enter a custom cache duration (30 - 86400 seconds)</p>\n {isCustom && (\n <>\n <div className=\"mt-3 flex items-center gap-2\">\n <input\n type=\"number\"\n value={customValue}\n onChange={handleCustomChange}\n disabled={disabled}\n min={30}\n max={86400}\n placeholder=\"300\"\n className={`\n w-32 px-3 py-2\n bg-bg-sunken\n border rounded-md\n text-sm text-text-primary\n placeholder-text-tertiary\n focus:outline-none\n focus:border-action-primary-bg\n focus:ring-2\n focus:ring-action-primary-bg/20\n ${error || validationError ? 'border-state-error' : 'border-border-default'}\n `}\n />\n <span className=\"text-sm text-text-secondary\">seconds</span>\n {customValue && !isNaN(parseInt(customValue)) && !validationError && (\n <span className=\"text-xs text-text-tertiary\">({formatDuration(parseInt(customValue))})</span>\n )}\n </div>\n {validationError && (\n <div className=\"flex items-center gap-1 mt-1\">\n <svg\n className=\"w-3.5 h-3.5 text-state-error flex-shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span className=\"text-xs text-state-error\">{validationError}</span>\n </div>\n )}\n </>\n )}\n </div>\n </label>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"flex items-start gap-2\">\n <svg\n className=\"w-4 h-4 text-state-error flex-shrink-0 mt-0.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <p className=\"text-xs text-state-error\">{error}</p>\n </div>\n )}\n\n {/* Info message */}\n {value !== null && !error && (\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span>Data will be cached for {formatDuration(value)} before being refreshed</span>\n </div>\n )}\n </div>\n );\n});\n\nexport default CacheTTLSelector;\n"],"mappings":"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"}
|
|
@@ -99,25 +99,25 @@ var o = t(function({ dataSink: t, setupState: o, onView: s, onEdit: c, onRefresh
|
|
|
99
99
|
/* @__PURE__ */ r("button", {
|
|
100
100
|
type: "button",
|
|
101
101
|
onClick: p,
|
|
102
|
-
className: "flex-1 px-3 py-1.5 text-xs font-medium text-text-primary bg-bg-
|
|
102
|
+
className: "flex-1 px-3 py-1.5 text-xs font-medium text-text-primary bg-bg-sunken hover:bg-border-default rounded-md transition-colors",
|
|
103
103
|
children: "View"
|
|
104
104
|
}),
|
|
105
105
|
/* @__PURE__ */ r("button", {
|
|
106
106
|
type: "button",
|
|
107
107
|
onClick: m,
|
|
108
|
-
className: "px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-
|
|
108
|
+
className: "px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors",
|
|
109
109
|
children: "Edit"
|
|
110
110
|
}),
|
|
111
111
|
/* @__PURE__ */ r("button", {
|
|
112
112
|
type: "button",
|
|
113
113
|
onClick: h,
|
|
114
|
-
className: "px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-
|
|
114
|
+
className: "px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors",
|
|
115
115
|
children: "Refresh"
|
|
116
116
|
}),
|
|
117
117
|
u && /* @__PURE__ */ r("button", {
|
|
118
118
|
type: "button",
|
|
119
119
|
onClick: g,
|
|
120
|
-
className: "px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-
|
|
120
|
+
className: "px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors",
|
|
121
121
|
children: "Export"
|
|
122
122
|
}),
|
|
123
123
|
/* @__PURE__ */ r("button", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataSinkCard.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/DataSinkCard.tsx"],"sourcesContent":["/**\n * DataSink Card\n *\n * Card component for displaying DataSink information in a list/grid view.\n */\n\nimport { memo, useCallback } from 'react';\nimport { formatDistanceToNow } from 'date-fns';\nimport { DataSinkStatusBadge } from './DataSinkStatusBadge';\nimport type { DataSink, DataSinkSetupState } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface DataSinkCardProps {\n /** DataSink data */\n dataSink: DataSink;\n /** Setup state override */\n setupState?: DataSinkSetupState;\n /** Callback when view is clicked */\n onView?: (id: string) => void;\n /** Callback when edit is clicked */\n onEdit?: (id: string) => void;\n /** Callback when refresh is clicked */\n onRefresh?: (id: string) => void;\n /** Callback when export is clicked */\n onExport?: (id: string) => void;\n /** Callback when delete is clicked */\n onDelete?: (id: string) => void;\n /** Callback to continue setup */\n onContinueSetup?: (id: string) => void;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const DataSinkCard = memo(function DataSinkCard({\n dataSink,\n setupState,\n onView,\n onEdit,\n onRefresh,\n onExport,\n onDelete,\n onContinueSetup,\n}: DataSinkCardProps) {\n // Event handlers\n const handleView = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onView?.(dataSink.id);\n },\n [dataSink.id, onView]\n );\n\n const handleEdit = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(dataSink.id);\n },\n [dataSink.id, onEdit]\n );\n\n const handleRefresh = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRefresh?.(dataSink.id);\n },\n [dataSink.id, onRefresh]\n );\n\n const handleExport = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onExport?.(dataSink.id);\n },\n [dataSink.id, onExport]\n );\n\n const handleDelete = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onDelete?.(dataSink.id);\n },\n [dataSink.id, onDelete]\n );\n\n const handleContinueSetup = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onContinueSetup?.(dataSink.id);\n },\n [dataSink.id, onContinueSetup]\n );\n\n const currentSetupState = setupState ?? dataSink.setupState;\n const isSetupComplete = currentSetupState === 'completed';\n\n // Format last refreshed time\n const lastRefreshedText = dataSink.lastRefreshedAt\n ? formatDistanceToNow(new Date(dataSink.lastRefreshedAt), { addSuffix: true })\n : 'Never';\n\n return (\n <div\n className={`\n p-4\n bg-bg-surface\n border border-border-default\n rounded-lg\n hover:border-action-primary-bg/50\n transition-colors\n cursor-pointer\n `}\n onClick={handleView}\n >\n {/* Header */}\n <div className=\"flex items-start justify-between mb-3\">\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-sm font-semibold text-text-primary truncate\">{dataSink.name || 'Untitled DataSink'}</h3>\n <p className=\"text-xs text-text-secondary font-mono mt-0.5 truncate\">{dataSink.key}</p>\n </div>\n <DataSinkStatusBadge status={dataSink.status} size=\"sm\" />\n </div>\n\n {/* Description */}\n {dataSink.description && <p className=\"text-xs text-text-secondary mb-3 line-clamp-2\">{dataSink.description}</p>}\n\n {/* Stats */}\n <div className=\"flex items-center gap-4 text-xs text-text-secondary mb-3\">\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n {lastRefreshedText}\n </span>\n {dataSink.linkedWorkflowCount !== undefined && dataSink.linkedWorkflowCount > 0 && (\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1\"\n />\n </svg>\n {dataSink.linkedWorkflowCount} workflow{dataSink.linkedWorkflowCount !== 1 ? 's' : ''}\n </span>\n )}\n </div>\n\n {/* Setup state indicator */}\n {!isSetupComplete && (\n <div className=\"mb-3 p-2 bg-state-warning/10 border border-state-warning/20 rounded-md\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-state-warning\">Setup incomplete</span>\n <button\n type=\"button\"\n onClick={handleContinueSetup}\n className=\"text-xs font-medium text-action-primary-bg hover:underline\"\n >\n Continue\n </button>\n </div>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex items-center gap-2 pt-2 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={handleView}\n className=\"flex-1 px-3 py-1.5 text-xs font-medium text-text-primary bg-bg-
|
|
1
|
+
{"version":3,"file":"DataSinkCard.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/DataSinkCard.tsx"],"sourcesContent":["/**\n * DataSink Card\n *\n * Card component for displaying DataSink information in a list/grid view.\n */\n\nimport { memo, useCallback } from 'react';\nimport { formatDistanceToNow } from 'date-fns';\nimport { DataSinkStatusBadge } from './DataSinkStatusBadge';\nimport type { DataSink, DataSinkSetupState } from '../../types';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface DataSinkCardProps {\n /** DataSink data */\n dataSink: DataSink;\n /** Setup state override */\n setupState?: DataSinkSetupState;\n /** Callback when view is clicked */\n onView?: (id: string) => void;\n /** Callback when edit is clicked */\n onEdit?: (id: string) => void;\n /** Callback when refresh is clicked */\n onRefresh?: (id: string) => void;\n /** Callback when export is clicked */\n onExport?: (id: string) => void;\n /** Callback when delete is clicked */\n onDelete?: (id: string) => void;\n /** Callback to continue setup */\n onContinueSetup?: (id: string) => void;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const DataSinkCard = memo(function DataSinkCard({\n dataSink,\n setupState,\n onView,\n onEdit,\n onRefresh,\n onExport,\n onDelete,\n onContinueSetup,\n}: DataSinkCardProps) {\n // Event handlers\n const handleView = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onView?.(dataSink.id);\n },\n [dataSink.id, onView]\n );\n\n const handleEdit = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(dataSink.id);\n },\n [dataSink.id, onEdit]\n );\n\n const handleRefresh = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRefresh?.(dataSink.id);\n },\n [dataSink.id, onRefresh]\n );\n\n const handleExport = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onExport?.(dataSink.id);\n },\n [dataSink.id, onExport]\n );\n\n const handleDelete = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onDelete?.(dataSink.id);\n },\n [dataSink.id, onDelete]\n );\n\n const handleContinueSetup = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onContinueSetup?.(dataSink.id);\n },\n [dataSink.id, onContinueSetup]\n );\n\n const currentSetupState = setupState ?? dataSink.setupState;\n const isSetupComplete = currentSetupState === 'completed';\n\n // Format last refreshed time\n const lastRefreshedText = dataSink.lastRefreshedAt\n ? formatDistanceToNow(new Date(dataSink.lastRefreshedAt), { addSuffix: true })\n : 'Never';\n\n return (\n <div\n className={`\n p-4\n bg-bg-surface\n border border-border-default\n rounded-lg\n hover:border-action-primary-bg/50\n transition-colors\n cursor-pointer\n `}\n onClick={handleView}\n >\n {/* Header */}\n <div className=\"flex items-start justify-between mb-3\">\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-sm font-semibold text-text-primary truncate\">{dataSink.name || 'Untitled DataSink'}</h3>\n <p className=\"text-xs text-text-secondary font-mono mt-0.5 truncate\">{dataSink.key}</p>\n </div>\n <DataSinkStatusBadge status={dataSink.status} size=\"sm\" />\n </div>\n\n {/* Description */}\n {dataSink.description && <p className=\"text-xs text-text-secondary mb-3 line-clamp-2\">{dataSink.description}</p>}\n\n {/* Stats */}\n <div className=\"flex items-center gap-4 text-xs text-text-secondary mb-3\">\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n {lastRefreshedText}\n </span>\n {dataSink.linkedWorkflowCount !== undefined && dataSink.linkedWorkflowCount > 0 && (\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1\"\n />\n </svg>\n {dataSink.linkedWorkflowCount} workflow{dataSink.linkedWorkflowCount !== 1 ? 's' : ''}\n </span>\n )}\n </div>\n\n {/* Setup state indicator */}\n {!isSetupComplete && (\n <div className=\"mb-3 p-2 bg-state-warning/10 border border-state-warning/20 rounded-md\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-state-warning\">Setup incomplete</span>\n <button\n type=\"button\"\n onClick={handleContinueSetup}\n className=\"text-xs font-medium text-action-primary-bg hover:underline\"\n >\n Continue\n </button>\n </div>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex items-center gap-2 pt-2 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={handleView}\n className=\"flex-1 px-3 py-1.5 text-xs font-medium text-text-primary bg-bg-sunken hover:bg-border-default rounded-md transition-colors\"\n >\n View\n </button>\n <button\n type=\"button\"\n onClick={handleEdit}\n className=\"px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n Edit\n </button>\n <button\n type=\"button\"\n onClick={handleRefresh}\n className=\"px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n Refresh\n </button>\n {onExport && (\n <button\n type=\"button\"\n onClick={handleExport}\n className=\"px-3 py-1.5 text-xs font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n Export\n </button>\n )}\n <button\n type=\"button\"\n onClick={handleDelete}\n className=\"px-3 py-1.5 text-xs font-medium text-state-error hover:bg-state-error/10 rounded-md transition-colors\"\n >\n Delete\n </button>\n </div>\n </div>\n );\n});\n\nexport default DataSinkCard;\n"],"mappings":"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"}
|
|
@@ -10,14 +10,14 @@ var a = e(function({ data: e, dataPath: a, maxHeight: o = "400px", showCopyButto
|
|
|
10
10
|
return /* @__PURE__ */ i("div", {
|
|
11
11
|
className: "relative",
|
|
12
12
|
children: [(a || s) && /* @__PURE__ */ i("div", {
|
|
13
|
-
className: "flex items-center justify-between p-2 bg-bg-
|
|
13
|
+
className: "flex items-center justify-between p-2 bg-bg-sunken border-b border-border-default rounded-t-md",
|
|
14
14
|
children: [a && /* @__PURE__ */ i("span", {
|
|
15
15
|
className: "text-xs text-text-secondary font-mono",
|
|
16
16
|
children: ["Path: ", a]
|
|
17
17
|
}), s && /* @__PURE__ */ r("button", {
|
|
18
18
|
type: "button",
|
|
19
19
|
onClick: d,
|
|
20
|
-
className: "\n px-2 py-1\n text-xs font-medium\n text-text-primary\n bg-bg-surface\n hover:bg-bg-
|
|
20
|
+
className: "\n px-2 py-1\n text-xs font-medium\n text-text-primary\n bg-bg-surface\n hover:bg-bg-sunken\n rounded\n transition-colors\n ",
|
|
21
21
|
children: c ? "Copied!" : "Copy"
|
|
22
22
|
})]
|
|
23
23
|
}), /* @__PURE__ */ r("pre", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataSinkDataViewer.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/DataSinkDataViewer.tsx"],"sourcesContent":["/**\n * DataSink Data Viewer\n *\n * Component for viewing DataSink data as formatted JSON.\n */\n\nimport { memo, useState, useCallback } from 'react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface DataSinkDataViewerProps {\n /** Data to display */\n data: unknown;\n /** Optional path to display */\n dataPath?: string;\n /** Maximum height */\n maxHeight?: string;\n /** Whether to show copy button */\n showCopyButton?: boolean;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const DataSinkDataViewer = memo(function DataSinkDataViewer({\n data,\n dataPath,\n maxHeight = '400px',\n showCopyButton = true,\n}: DataSinkDataViewerProps) {\n const [isCopied, setIsCopied] = useState(false);\n\n // Format data as JSON\n const formattedData = JSON.stringify(data, null, 2);\n\n // Copy to clipboard\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(formattedData);\n setIsCopied(true);\n setTimeout(() => setIsCopied(false), 2000);\n } catch (err) {}\n }, [formattedData]);\n\n return (\n <div className=\"relative\">\n {/* Header with path and copy button */}\n {(dataPath || showCopyButton) && (\n <div className=\"flex items-center justify-between p-2 bg-bg-
|
|
1
|
+
{"version":3,"file":"DataSinkDataViewer.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/DataSinkDataViewer.tsx"],"sourcesContent":["/**\n * DataSink Data Viewer\n *\n * Component for viewing DataSink data as formatted JSON.\n */\n\nimport { memo, useState, useCallback } from 'react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface DataSinkDataViewerProps {\n /** Data to display */\n data: unknown;\n /** Optional path to display */\n dataPath?: string;\n /** Maximum height */\n maxHeight?: string;\n /** Whether to show copy button */\n showCopyButton?: boolean;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const DataSinkDataViewer = memo(function DataSinkDataViewer({\n data,\n dataPath,\n maxHeight = '400px',\n showCopyButton = true,\n}: DataSinkDataViewerProps) {\n const [isCopied, setIsCopied] = useState(false);\n\n // Format data as JSON\n const formattedData = JSON.stringify(data, null, 2);\n\n // Copy to clipboard\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(formattedData);\n setIsCopied(true);\n setTimeout(() => setIsCopied(false), 2000);\n } catch (err) {}\n }, [formattedData]);\n\n return (\n <div className=\"relative\">\n {/* Header with path and copy button */}\n {(dataPath || showCopyButton) && (\n <div className=\"flex items-center justify-between p-2 bg-bg-sunken border-b border-border-default rounded-t-md\">\n {dataPath && <span className=\"text-xs text-text-secondary font-mono\">Path: {dataPath}</span>}\n {showCopyButton && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className={`\n px-2 py-1\n text-xs font-medium\n text-text-primary\n bg-bg-surface\n hover:bg-bg-sunken\n rounded\n transition-colors\n `}\n >\n {isCopied ? 'Copied!' : 'Copy'}\n </button>\n )}\n </div>\n )}\n\n {/* Data display */}\n <pre\n className={`\n p-4\n bg-bg-surface\n border border-border-default\n ${dataPath || showCopyButton ? 'rounded-b-md border-t-0' : 'rounded-md'}\n overflow-auto\n text-sm\n `}\n style={{ maxHeight }}\n >\n <code className=\"text-text-primary font-mono\">{formattedData}</code>\n </pre>\n </div>\n );\n});\n\nexport default DataSinkDataViewer;\n"],"mappings":";;;AA2BA,IAAa,IAAqB,EAAK,SAA4B,EACjE,SACA,aACA,eAAY,SACZ,oBAAiB,MACS;CAC1B,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM,EAGzC,IAAgB,KAAK,UAAU,GAAM,MAAM,EAAE,EAG7C,IAAa,EAAY,YAAY;AACzC,MAAI;AAGF,GAFA,MAAM,UAAU,UAAU,UAAU,EAAc,EAClD,EAAY,GAAK,EACjB,iBAAiB,EAAY,GAAM,EAAE,IAAK;UAC9B;IACb,CAAC,EAAc,CAAC;AAEnB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,EAEI,KAAY,MACZ,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,KAAY,kBAAC,QAAD;IAAM,WAAU;cAAhB,CAAwD,UAAO,EAAgB;OAC3F,KACC,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,WAAW;cAUV,IAAW,YAAY;IACjB,CAAA,CAEP;MAIR,kBAAC,OAAD;GACE,WAAW;;;;YAIP,KAAY,IAAiB,4BAA4B,aAAa;;;;GAI1E,OAAO,EAAE,cAAW;aAEpB,kBAAC,QAAD;IAAM,WAAU;cAA+B;IAAqB,CAAA;GAChE,CAAA,CACF;;EAER"}
|
|
@@ -33,7 +33,7 @@ var i = e(function({ dataSink: e, isOpen: i, onClose: a, onConfirm: o, isDeletin
|
|
|
33
33
|
children: "Are you sure you want to delete this DataSink?"
|
|
34
34
|
}),
|
|
35
35
|
/* @__PURE__ */ r("div", {
|
|
36
|
-
className: "bg-bg-
|
|
36
|
+
className: "bg-bg-sunken p-3 rounded-md",
|
|
37
37
|
children: [/* @__PURE__ */ n("p", {
|
|
38
38
|
className: "text-sm font-medium text-text-primary",
|
|
39
39
|
children: e.name || "Untitled DataSink"
|
|
@@ -67,7 +67,7 @@ var i = e(function({ dataSink: e, isOpen: i, onClose: a, onConfirm: o, isDeletin
|
|
|
67
67
|
type: "button",
|
|
68
68
|
onClick: a,
|
|
69
69
|
disabled: s,
|
|
70
|
-
className: "\n px-4 py-2\n text-sm font-medium\n text-text-primary\n bg-bg-
|
|
70
|
+
className: "\n px-4 py-2\n text-sm font-medium\n text-text-primary\n bg-bg-sunken\n hover:bg-border-default\n disabled:opacity-50 disabled:cursor-not-allowed\n rounded-md\n transition-colors\n ",
|
|
71
71
|
children: "Cancel"
|
|
72
72
|
}), /* @__PURE__ */ n("button", {
|
|
73
73
|
type: "button",
|