@burdenoff/microfe-bigconsole 2026.924.3 → 2026.925.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,12 @@
1
- import { Section as e, SectionStack as t } from "../common/Section.js";
1
+ import { reportBigConsoleQuotaError as e } from "../../utils/quota.js";
2
+ import { Section as t, SectionStack as n } from "../common/Section.js";
2
3
  import "../common/index.js";
3
- import n from "../../hooks/useBigConsoleAnalytics.js";
4
- import ee from "../../hooks/useImportDataSink.js";
4
+ import r from "../../hooks/useBigConsoleAnalytics.js";
5
+ import i from "../../hooks/useImportDataSink.js";
5
6
  import "../../hooks/index.js";
6
- import { memo as r, useCallback as i, useEffect as te, useRef as a, useState as o } from "react";
7
- import { ArrowLeft as s, Check as c, FileJson as l, Info as u, RefreshCw as d, Upload as f, XCircle as p } from "lucide-react";
8
- import { Badge as m, Button as h, Dialog as ne, DialogContent as g, DialogDescription as re, DialogFooter as _, DialogHeader as v, DialogTitle as y, Input as b, Label as x, Spinner as S } from "@burdenoff/fe-libs/ui";
7
+ import { memo as a, useCallback as o, useEffect as s, useRef as c, useState as l } from "react";
8
+ import { ArrowLeft as u, Check as d, FileJson as ee, Info as f, RefreshCw as te, Upload as p, XCircle as m } from "lucide-react";
9
+ import { Badge as h, Button as g, Dialog as _, DialogContent as ne, DialogDescription as re, DialogFooter as v, DialogHeader as y, DialogTitle as b, Input as x, Label as S, Spinner as ie } from "@burdenoff/fe-libs/ui";
9
10
  import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
10
11
  import { useI18n as E } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
12
  //#region src/bigconsole/components/datasink/ImportDataSinkDialog.tsx
@@ -26,12 +27,12 @@ var D = [
26
27
  function O(e) {
27
28
  return e === "select" ? 0 : e === "complete" ? 2 : 1;
28
29
  }
29
- var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
30
- let { t: j } = E(), [M, N] = o("select"), [, P] = o(null), [F, I] = o(null), [L, R] = o(""), [z, B] = o(""), V = a(null), { loading: H, error: U, validationResult: W, importResult: G, validateImport: K, importDataSink: q, extractDataSinkId: J, clearState: Y } = ee(), X = n();
31
- te(() => {
32
- r && (N("select"), P(null), I(null), R(""), B(""), Y());
33
- }, [r, Y]);
34
- let ie = i(async (e) => {
30
+ var k = a(function({ isOpen: a, onClose: k, onSuccess: A }) {
31
+ let { t: j } = E(), [M, N] = l("select"), [, P] = l(null), [F, I] = l(null), [L, R] = l(""), [z, B] = l(""), V = c(null), { loading: H, error: U, validationResult: W, importResult: G, validateImport: K, importDataSink: q, extractDataSinkId: J, clearState: Y } = i(), X = r();
32
+ s(() => {
33
+ a && (N("select"), P(null), I(null), R(""), B(""), Y());
34
+ }, [a, Y]);
35
+ let ae = o(async (e) => {
35
36
  let t = e.target.files?.[0];
36
37
  if (!t) return;
37
38
  if (!t.name.endsWith(".json")) {
@@ -48,47 +49,58 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
48
49
  }, n.onerror = () => {
49
50
  alert(j("bigconsole.dataSinks.import.readFileError", "Failed to read file"));
50
51
  }, n.readAsText(t);
51
- }, [K, j]), ae = i((e) => {
52
+ }, [K, j]), oe = o((e) => {
52
53
  e.preventDefault();
53
54
  let t = e.dataTransfer.files?.[0];
54
55
  if (t) {
55
56
  let e = new DataTransfer();
56
57
  e.items.add(t), V.current && (V.current.files = e.files, V.current.dispatchEvent(new Event("change", { bubbles: !0 })));
57
58
  }
58
- }, []), oe = i(async () => {
59
+ }, []), se = o(async () => {
59
60
  if (!F) return;
60
61
  N("importing");
61
- let e = {
62
+ let t = {
62
63
  name: L.trim() || void 0,
63
64
  key: z.trim() || void 0
64
65
  };
65
66
  X("bigconsole.data_sink.import_clicked", { source: "import" });
66
- let t = await q(F, e);
67
- t?.success && t.dataSink ? (N("complete"), X("bigconsole.data_sink.imported", {
68
- dataSinkId: t.dataSink.id,
67
+ let n;
68
+ try {
69
+ n = await q(F, t);
70
+ } catch (t) {
71
+ if (e(t)) {
72
+ k();
73
+ return;
74
+ }
75
+ N("preview");
76
+ return;
77
+ }
78
+ n?.success && n.dataSink ? (N("complete"), X("bigconsole.data_sink.imported", {
79
+ dataSinkId: n.dataSink.id,
69
80
  source: "import",
70
- originalUpdated: t.originalUpdated ?? !1
71
- }), A?.(t.dataSink.id, t.dataSink.name, t.originalUpdated ?? !1)) : N("preview");
81
+ originalUpdated: n.originalUpdated ?? !1
82
+ }), A?.(n.dataSink.id, n.dataSink.name, n.originalUpdated ?? !1)) : N("preview");
72
83
  }, [
73
84
  X,
74
85
  F,
75
86
  q,
76
87
  z,
77
88
  L,
89
+ k,
78
90
  A
79
91
  ]), Z = !H && M !== "importing", Q = F ? J(F) : null, $ = O(M);
80
- return /* @__PURE__ */ w(ne, {
81
- open: r,
92
+ return /* @__PURE__ */ w(_, {
93
+ open: a,
82
94
  onOpenChange: (e) => !e && Z && k(),
83
- children: /* @__PURE__ */ T(g, {
95
+ children: /* @__PURE__ */ T(ne, {
84
96
  className: "flex max-h-[85vh] flex-col sm:max-w-lg",
85
97
  children: [
86
- /* @__PURE__ */ T(v, { children: [/* @__PURE__ */ T("div", {
98
+ /* @__PURE__ */ T(y, { children: [/* @__PURE__ */ T("div", {
87
99
  className: "flex items-center gap-3",
88
100
  children: [/* @__PURE__ */ w("div", {
89
101
  className: "flex size-10 items-center justify-center rounded-card bg-bg-accentSubtle",
90
- children: /* @__PURE__ */ w(f, { className: "size-5 text-text-link" })
91
- }), /* @__PURE__ */ w(y, { children: j("bigconsole.dataSinks.import.title", "Import DataSink") })]
102
+ children: /* @__PURE__ */ w(p, { className: "size-5 text-text-link" })
103
+ }), /* @__PURE__ */ w(b, { children: j("bigconsole.dataSinks.import.title", "Import DataSink") })]
92
104
  }), /* @__PURE__ */ w(re, { children: j("bigconsole.dataSinks.import.description", "Upload a DataSink export file to restore it into this workspace.") })] }),
93
105
  /* @__PURE__ */ w("ol", {
94
106
  className: "flex flex-wrap items-center gap-x-icon-gap gap-y-1 text-xs",
@@ -112,18 +124,18 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
112
124
  }),
113
125
  /* @__PURE__ */ w("div", {
114
126
  className: "min-w-0 flex-1 overflow-y-auto py-4",
115
- children: /* @__PURE__ */ T(t, { children: [
116
- M === "select" && /* @__PURE__ */ w(e, {
127
+ children: /* @__PURE__ */ T(n, { children: [
128
+ M === "select" && /* @__PURE__ */ w(t, {
117
129
  title: "Choose an export file",
118
130
  description: j("bigconsole.dataSinks.import.supportedFilesHint", "Only .json files exported from BigConsole are supported"),
119
131
  headingLevel: 3,
120
132
  bodyClassName: "mt-form-gap",
121
133
  children: /* @__PURE__ */ T("div", {
122
134
  onDragOver: (e) => e.preventDefault(),
123
- onDrop: ae,
135
+ onDrop: oe,
124
136
  className: "rounded-card border-2 border-dashed border-[var(--color-border-default)] p-8 text-center hover:border-[var(--color-action-primary-bg)] motion-safe:transition-colors",
125
137
  children: [
126
- /* @__PURE__ */ w(l, { className: "mx-auto mb-4 size-12 text-text-secondary" }),
138
+ /* @__PURE__ */ w(ee, { className: "mx-auto mb-4 size-12 text-text-secondary" }),
127
139
  /* @__PURE__ */ w("p", {
128
140
  className: "mb-2 text-sm",
129
141
  children: j("bigconsole.dataSinks.import.dropzoneText", "Drag and drop a DataSink export file here")
@@ -136,10 +148,10 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
136
148
  ref: V,
137
149
  type: "file",
138
150
  accept: ".json",
139
- onChange: ie,
151
+ onChange: ae,
140
152
  className: "hidden"
141
153
  }),
142
- /* @__PURE__ */ w(h, {
154
+ /* @__PURE__ */ w(g, {
143
155
  onClick: () => V.current?.click(),
144
156
  disabled: H,
145
157
  children: j("bigconsole.dataSinks.import.browseFiles", "Browse Files")
@@ -148,7 +160,7 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
148
160
  })
149
161
  }),
150
162
  (M === "preview" || M === "importing") && W && /* @__PURE__ */ T(C, { children: [
151
- W.dataSinkInfo && /* @__PURE__ */ T(e, {
163
+ W.dataSinkInfo && /* @__PURE__ */ T(t, {
152
164
  emphasis: "muted",
153
165
  padding: "compact",
154
166
  headingLevel: 3,
@@ -181,7 +193,7 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
181
193
  children: [/* @__PURE__ */ w("span", {
182
194
  className: "text-sm text-text-secondary",
183
195
  children: j("bigconsole.dataSinks.import.statusLabel", "Status")
184
- }), /* @__PURE__ */ w(m, {
196
+ }), /* @__PURE__ */ w(h, {
185
197
  variant: "secondary",
186
198
  children: W.dataSinkInfo.status
187
199
  })]
@@ -191,7 +203,7 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
191
203
  children: [/* @__PURE__ */ w("span", {
192
204
  className: "text-sm text-text-secondary",
193
205
  children: j("bigconsole.dataSinks.import.setupStateLabel", "Setup State")
194
- }), /* @__PURE__ */ w(m, {
206
+ }), /* @__PURE__ */ w(h, {
195
207
  variant: "outline",
196
208
  children: W.dataSinkInfo.setupState
197
209
  })]
@@ -218,12 +230,12 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
218
230
  })
219
231
  ]
220
232
  }),
221
- W.errors.length > 0 && /* @__PURE__ */ w(e, {
233
+ W.errors.length > 0 && /* @__PURE__ */ w(t, {
222
234
  tone: "danger",
223
235
  padding: "compact",
224
236
  headingLevel: 3,
225
237
  title: j("bigconsole.dataSinks.import.errorsHeading", "Errors ({{count}})", { count: W.errors.length }),
226
- icon: /* @__PURE__ */ w(p, { className: "size-4" }),
238
+ icon: /* @__PURE__ */ w(m, { className: "size-4" }),
227
239
  children: /* @__PURE__ */ w("ul", {
228
240
  className: "space-y-1 text-xs text-status-error-text",
229
241
  children: W.errors.map((e, t) => /* @__PURE__ */ T("li", { children: [
@@ -240,18 +252,18 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
240
252
  ] }, t))
241
253
  })
242
254
  }),
243
- W.isValid && /* @__PURE__ */ T(e, {
255
+ W.isValid && /* @__PURE__ */ T(t, {
244
256
  title: j("bigconsole.dataSinks.import.optionsHeading", "Import Options"),
245
257
  description: "Rename the sink or give it a different key before importing.",
246
258
  headingLevel: 3,
247
259
  bodyClassName: "space-y-form-gap",
248
260
  children: [
249
- /* @__PURE__ */ w(e, {
261
+ /* @__PURE__ */ w(t, {
250
262
  tone: "info",
251
263
  emphasis: "muted",
252
264
  padding: "compact",
253
265
  headingLevel: 4,
254
- icon: /* @__PURE__ */ w(u, { className: "size-4" }),
266
+ icon: /* @__PURE__ */ w(f, { className: "size-4" }),
255
267
  title: Q ? j("bigconsole.dataSinks.import.checkExistingHeading", "Import will check for existing DataSink") : j("bigconsole.dataSinks.import.newWillBeCreatedHeading", "A new DataSink will be created"),
256
268
  children: /* @__PURE__ */ w("div", {
257
269
  className: "text-xs text-[var(--color-status-info-text)]",
@@ -278,10 +290,10 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
278
290
  }),
279
291
  /* @__PURE__ */ T("div", {
280
292
  className: "space-y-2",
281
- children: [/* @__PURE__ */ w(x, {
293
+ children: [/* @__PURE__ */ w(S, {
282
294
  htmlFor: "import-name",
283
295
  children: j("bigconsole.dataSinks.import.nameFieldLabel", "DataSink Name")
284
- }), /* @__PURE__ */ w(b, {
296
+ }), /* @__PURE__ */ w(x, {
285
297
  id: "import-name",
286
298
  type: "text",
287
299
  value: L,
@@ -293,11 +305,11 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
293
305
  /* @__PURE__ */ T("div", {
294
306
  className: "space-y-2",
295
307
  children: [
296
- /* @__PURE__ */ w(x, {
308
+ /* @__PURE__ */ w(S, {
297
309
  htmlFor: "import-key",
298
310
  children: j("bigconsole.dataSinks.import.keyFieldLabel", "DataSink Key")
299
311
  }),
300
- /* @__PURE__ */ w(b, {
312
+ /* @__PURE__ */ w(x, {
301
313
  id: "import-key",
302
314
  type: "text",
303
315
  value: z,
@@ -315,38 +327,38 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
315
327
  })
316
328
  ] }),
317
329
  M === "complete" && G?.success && /* @__PURE__ */ T(C, { children: [
318
- G.alreadyExists && /* @__PURE__ */ w(e, {
330
+ G.alreadyExists && /* @__PURE__ */ w(t, {
319
331
  tone: "info",
320
332
  headingLevel: 3,
321
333
  title: j("bigconsole.dataSinks.import.alreadyExistsTitle", "DataSink Already Exists"),
322
- icon: /* @__PURE__ */ w(u, { className: "h-icon-sm w-icon-sm" }),
334
+ icon: /* @__PURE__ */ w(f, { className: "h-icon-sm w-icon-sm" }),
323
335
  children: /* @__PURE__ */ w("p", {
324
336
  className: "text-sm text-text-secondary",
325
337
  children: j("bigconsole.dataSinks.import.alreadyExistsBody", "DataSink \"{{name}}\" already exists with the same data. No changes were made.", { name: G.dataSink?.name || G.dataSink?.key || "" })
326
338
  })
327
339
  }),
328
- G.originalUpdated && !G.alreadyExists && /* @__PURE__ */ w(e, {
340
+ G.originalUpdated && !G.alreadyExists && /* @__PURE__ */ w(t, {
329
341
  tone: "success",
330
342
  headingLevel: 3,
331
343
  title: j("bigconsole.dataSinks.import.updatedTitle", "DataSink Updated!"),
332
- icon: /* @__PURE__ */ w(d, { className: "h-icon-sm w-icon-sm" }),
344
+ icon: /* @__PURE__ */ w(te, { className: "h-icon-sm w-icon-sm" }),
333
345
  children: /* @__PURE__ */ w("p", {
334
346
  className: "text-sm text-text-secondary",
335
347
  children: j("bigconsole.dataSinks.import.updatedBody", "DataSink \"{{name}}\" has been updated with the imported data.", { name: G.dataSink?.name || G.dataSink?.key || "" })
336
348
  })
337
349
  }),
338
- !G.originalUpdated && !G.alreadyExists && /* @__PURE__ */ w(e, {
350
+ !G.originalUpdated && !G.alreadyExists && /* @__PURE__ */ w(t, {
339
351
  tone: "success",
340
352
  headingLevel: 3,
341
353
  title: j("bigconsole.dataSinks.import.successTitle", "Import Successful!"),
342
- icon: /* @__PURE__ */ w(c, { className: "h-icon-sm w-icon-sm" }),
354
+ icon: /* @__PURE__ */ w(d, { className: "h-icon-sm w-icon-sm" }),
343
355
  children: /* @__PURE__ */ w("p", {
344
356
  className: "text-sm text-text-secondary",
345
357
  children: j("bigconsole.dataSinks.import.successBody", "DataSink \"{{name}}\" has been created.", { name: G.dataSink?.name || G.dataSink?.key || "" })
346
358
  })
347
359
  })
348
360
  ] }),
349
- U && /* @__PURE__ */ w(e, {
361
+ U && /* @__PURE__ */ w(t, {
350
362
  tone: "danger",
351
363
  padding: "compact",
352
364
  headingLevel: 3,
@@ -356,7 +368,7 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
356
368
  children: U.message
357
369
  })
358
370
  }),
359
- G && !G.success && G.errorMessage && /* @__PURE__ */ w(e, {
371
+ G && !G.success && G.errorMessage && /* @__PURE__ */ w(t, {
360
372
  tone: "danger",
361
373
  padding: "compact",
362
374
  headingLevel: 3,
@@ -368,37 +380,37 @@ var k = r(function({ isOpen: r, onClose: k, onSuccess: A }) {
368
380
  })
369
381
  ] })
370
382
  }),
371
- /* @__PURE__ */ T(_, {
383
+ /* @__PURE__ */ T(v, {
372
384
  className: "flex flex-col-reverse gap-control-gap sm:flex-row sm:justify-between",
373
- children: [M === "preview" ? /* @__PURE__ */ T(h, {
385
+ children: [M === "preview" ? /* @__PURE__ */ T(g, {
374
386
  variant: "ghost",
375
387
  onClick: () => {
376
388
  N("select"), P(null), I(null), Y();
377
389
  },
378
390
  disabled: H,
379
- children: [/* @__PURE__ */ w(s, { className: "size-4" }), j("bigconsole.dataSinks.import.back", "Back")]
391
+ children: [/* @__PURE__ */ w(u, { className: "size-4" }), j("bigconsole.dataSinks.import.back", "Back")]
380
392
  }) : /* @__PURE__ */ w("span", {
381
393
  "aria-hidden": "true",
382
394
  className: "hidden sm:block"
383
395
  }), /* @__PURE__ */ T("div", {
384
396
  className: "flex flex-wrap items-center gap-2",
385
397
  children: [
386
- M !== "complete" && /* @__PURE__ */ w(h, {
398
+ M !== "complete" && /* @__PURE__ */ w(g, {
387
399
  variant: "outline",
388
400
  onClick: k,
389
401
  disabled: !Z,
390
402
  children: j("bigconsole.dataSinks.import.cancel", "Cancel")
391
403
  }),
392
- M === "preview" && W?.isValid && /* @__PURE__ */ T(h, {
393
- onClick: oe,
404
+ M === "preview" && W?.isValid && /* @__PURE__ */ T(g, {
405
+ onClick: se,
394
406
  disabled: H,
395
- children: [/* @__PURE__ */ w(f, { className: "size-4" }), j("bigconsole.dataSinks.import.importButton", "Import DataSink")]
407
+ children: [/* @__PURE__ */ w(p, { className: "size-4" }), j("bigconsole.dataSinks.import.importButton", "Import DataSink")]
396
408
  }),
397
409
  M === "importing" && /* @__PURE__ */ T("div", {
398
410
  className: "flex items-center gap-2 text-sm text-text-secondary",
399
- children: [/* @__PURE__ */ w(S, { className: "size-4" }), j("bigconsole.dataSinks.import.importing", "Importing...")]
411
+ children: [/* @__PURE__ */ w(ie, { className: "size-4" }), j("bigconsole.dataSinks.import.importing", "Importing...")]
400
412
  }),
401
- M === "complete" && /* @__PURE__ */ w(h, {
413
+ M === "complete" && /* @__PURE__ */ w(g, {
402
414
  onClick: k,
403
415
  children: j("bigconsole.dataSinks.import.done", "Done")
404
416
  })
@@ -1 +1 @@
1
- {"version":3,"file":"ImportDataSinkDialog.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/ImportDataSinkDialog.tsx"],"sourcesContent":["/**\n * ImportDataSinkDialog Component\n *\n * Modal dialog for importing a DataSink from JSON file.\n * Supports both creating new DataSinks and updating existing ones.\n */\n\nimport { type FC, memo, useState, useCallback, useEffect, useRef } from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Label } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Upload, FileJson, Check, XCircle, ArrowLeft, RefreshCw, Info } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useImportDataSink, type ImportDataSinkOptions } from '../../hooks';\nimport { useBigConsoleAnalytics } from '../../hooks/useBigConsoleAnalytics';\nimport { Section, SectionStack } from '../common';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ImportDataSinkDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess?: (dataSinkId: string, dataSinkName: string | null, originalUpdated: boolean) => void;\n}\n\ntype ImportStep = 'select' | 'preview' | 'importing' | 'complete';\n\n/**\n * Wizard steps. The dialog previously moved between three screens with no\n * indicator at all, so a user could not tell where they were.\n */\nconst WIZARD_STEPS: { id: ImportStep; label: string }[] = [\n { id: 'select', label: 'Choose file' },\n { id: 'preview', label: 'Review' },\n { id: 'complete', label: 'Done' },\n];\n\n/** Index of the wizard step currently on screen ('importing' still shows Review). */\nfunction wizardIndex(step: ImportStep): number {\n if (step === 'select') return 0;\n if (step === 'complete') return 2;\n return 1;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ImportDataSinkDialog: FC<ImportDataSinkDialogProps> = memo(function ImportDataSinkDialog({\n isOpen,\n onClose,\n onSuccess,\n}) {\n const { t } = useI18n();\n const [step, setStep] = useState<ImportStep>('select');\n const [, setSelectedFile] = useState<File | null>(null);\n const [fileContent, setFileContent] = useState<string | null>(null);\n const [nameOverride, setNameOverride] = useState('');\n const [keyOverride, setKeyOverride] = useState('');\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const {\n loading,\n error,\n validationResult,\n importResult,\n validateImport,\n importDataSink,\n extractDataSinkId,\n clearState,\n } = useImportDataSink();\n const emitBigConsoleEvent = useBigConsoleAnalytics();\n\n // Reset state when dialog opens\n useEffect(() => {\n if (isOpen) {\n setStep('select');\n setSelectedFile(null);\n setFileContent(null);\n setNameOverride('');\n setKeyOverride('');\n clearState();\n }\n }, [isOpen, clearState]);\n\n // Handle file selection\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n if (!file.name.endsWith('.json')) {\n alert(t('bigconsole.dataSinks.import.selectJsonFile', 'Please select a JSON file'));\n return;\n }\n\n setSelectedFile(file);\n\n const reader = new FileReader();\n reader.onload = async (event) => {\n const content = event.target?.result as string;\n setFileContent(content);\n\n const result = validateImport(content);\n if (result.isValid && result.dataSinkInfo) {\n setStep('preview');\n setNameOverride(result.dataSinkInfo.name || '');\n setKeyOverride(result.dataSinkInfo.key || '');\n } else {\n setStep('preview');\n }\n };\n reader.onerror = () => {\n alert(t('bigconsole.dataSinks.import.readFileError', 'Failed to read file'));\n };\n reader.readAsText(file);\n },\n [validateImport, t]\n );\n\n // Handle file drop\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n const file = e.dataTransfer.files?.[0];\n if (file) {\n const dt = new DataTransfer();\n dt.items.add(file);\n if (fileInputRef.current) {\n fileInputRef.current.files = dt.files;\n fileInputRef.current.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }, []);\n\n // Handle import\n const handleImport = useCallback(async () => {\n if (!fileContent) return;\n\n setStep('importing');\n\n const options: ImportDataSinkOptions = {\n name: nameOverride.trim() || undefined,\n key: keyOverride.trim() || undefined,\n };\n\n emitBigConsoleEvent('bigconsole.data_sink.import_clicked', { source: 'import' });\n\n const result = await importDataSink(fileContent, options);\n\n if (result?.success && result.dataSink) {\n setStep('complete');\n emitBigConsoleEvent('bigconsole.data_sink.imported', {\n dataSinkId: result.dataSink.id,\n source: 'import',\n originalUpdated: result.originalUpdated ?? false,\n });\n onSuccess?.(result.dataSink.id, result.dataSink.name, result.originalUpdated ?? false);\n } else {\n setStep('preview');\n }\n }, [emitBigConsoleEvent, fileContent, importDataSink, keyOverride, nameOverride, onSuccess]);\n\n const canClose = !loading && step !== 'importing';\n const dataSinkId = fileContent ? extractDataSinkId(fileContent) : null;\n const currentStepIndex = wizardIndex(step);\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && canClose && onClose()}>\n <DialogContent className=\"flex max-h-[85vh] flex-col sm:max-w-lg\">\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-card bg-bg-accentSubtle\">\n <Upload className=\"size-5 text-text-link\" />\n </div>\n <DialogTitle>{t('bigconsole.dataSinks.import.title', 'Import DataSink')}</DialogTitle>\n </div>\n <DialogDescription>\n {t(\n 'bigconsole.dataSinks.import.description',\n 'Upload a DataSink export file to restore it into this workspace.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n {/* Step indicator — structural strip so the wizard reads as a sequence. */}\n <ol className=\"flex flex-wrap items-center gap-x-icon-gap gap-y-1 text-xs\" aria-label=\"Import progress\">\n {WIZARD_STEPS.map((wizardStep, index) => (\n <li\n key={wizardStep.id}\n aria-current={index === currentStepIndex ? 'step' : undefined}\n className={`flex items-center gap-icon-gap ${\n index === currentStepIndex ? 'font-semibold text-text-primary' : 'text-text-muted'\n }`}\n >\n <span\n className={`inline-flex size-5 items-center justify-center rounded-pill text-[10px] ${\n index <= currentStepIndex ? 'bg-action-primary-bg text-action-primary-text' : 'bg-bg-sunken'\n }`}\n >\n {index + 1}\n </span>\n {wizardStep.label}\n {index < WIZARD_STEPS.length - 1 && (\n <span aria-hidden=\"true\" className=\"text-text-muted\">\n ›\n </span>\n )}\n </li>\n ))}\n </ol>\n\n <div className=\"min-w-0 flex-1 overflow-y-auto py-4\">\n <SectionStack>\n {/* Step 1: File Selection */}\n {step === 'select' && (\n <Section\n title=\"Choose an export file\"\n description={t(\n 'bigconsole.dataSinks.import.supportedFilesHint',\n 'Only .json files exported from BigConsole are supported'\n )}\n headingLevel={3}\n bodyClassName=\"mt-form-gap\"\n >\n <div\n onDragOver={(e) => e.preventDefault()}\n onDrop={handleDrop}\n className=\"rounded-card border-2 border-dashed border-[var(--color-border-default)] p-8 text-center hover:border-[var(--color-action-primary-bg)] motion-safe:transition-colors\"\n >\n <FileJson className=\"mx-auto mb-4 size-12 text-text-secondary\" />\n <p className=\"mb-2 text-sm\">\n {t('bigconsole.dataSinks.import.dropzoneText', 'Drag and drop a DataSink export file here')}\n </p>\n <p className=\"mb-4 text-xs text-text-secondary\">{t('bigconsole.dataSinks.import.or', 'or')}</p>\n <input ref={fileInputRef} type=\"file\" accept=\".json\" onChange={handleFileSelect} className=\"hidden\" />\n <Button onClick={() => fileInputRef.current?.click()} disabled={loading}>\n {t('bigconsole.dataSinks.import.browseFiles', 'Browse Files')}\n </Button>\n </div>\n </Section>\n )}\n\n {/* Step 2: Preview & Options */}\n {(step === 'preview' || step === 'importing') && validationResult && (\n <>\n {/* What is in the file — supporting detail. */}\n {validationResult.dataSinkInfo && (\n <Section\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={3}\n title=\"File contents\"\n description=\"What this export file describes.\"\n bodyClassName=\"space-y-2\"\n >\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.nameLabel', 'Name')}\n </span>\n <span className=\"min-w-0 truncate text-sm font-medium\">\n {validationResult.dataSinkInfo.name || t('bigconsole.dataSinks.import.unnamed', 'Unnamed')}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.keyLabel', 'Key')}\n </span>\n <span className=\"min-w-0 truncate font-mono text-xs\">{validationResult.dataSinkInfo.key}</span>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.statusLabel', 'Status')}\n </span>\n <Badge variant=\"secondary\">{validationResult.dataSinkInfo.status}</Badge>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.setupStateLabel', 'Setup State')}\n </span>\n <Badge variant=\"outline\">{validationResult.dataSinkInfo.setupState}</Badge>\n </div>\n {validationResult.dataSinkInfo.exportedFrom && (\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.sourceIdLabel', 'Source ID')}\n </span>\n <span className=\"min-w-0 max-w-[180px] truncate font-mono text-xs text-text-secondary\">\n {validationResult.dataSinkInfo.exportedFrom}\n </span>\n </div>\n )}\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.schemaVersionLabel', 'Schema Version')}\n </span>\n <span className=\"text-xs text-text-secondary\">{validationResult.dataSinkInfo.schemaVersion}</span>\n </div>\n </Section>\n )}\n\n {/* Validation Errors */}\n {validationResult.errors.length > 0 && (\n <Section\n tone=\"danger\"\n padding=\"compact\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.errorsHeading', 'Errors ({{count}})', {\n count: validationResult.errors.length,\n })}\n icon={<XCircle className=\"size-4\" />}\n >\n <ul className=\"space-y-1 text-xs text-status-error-text\">\n {validationResult.errors.map((err, idx) => (\n <li key={idx}>\n <span className=\"font-mono\">[{err.code}]</span> {err.message}\n </li>\n ))}\n </ul>\n </Section>\n )}\n\n {/* Import Options */}\n {validationResult.isValid && (\n <Section\n title={t('bigconsole.dataSinks.import.optionsHeading', 'Import Options')}\n description=\"Rename the sink or give it a different key before importing.\"\n headingLevel={3}\n bodyClassName=\"space-y-form-gap\"\n >\n <Section\n tone=\"info\"\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={4}\n icon={<Info className=\"size-4\" />}\n title={\n dataSinkId\n ? t(\n 'bigconsole.dataSinks.import.checkExistingHeading',\n 'Import will check for existing DataSink'\n )\n : t('bigconsole.dataSinks.import.newWillBeCreatedHeading', 'A new DataSink will be created')\n }\n >\n <div className=\"text-xs text-[var(--color-status-info-text)]\">\n {dataSinkId ? (\n <>\n <p>\n {t('bigconsole.dataSinks.import.ifOriginalExistsPrefix', 'If the original DataSink (ID:')}{' '}\n <code className=\"rounded-input bg-bg-surface px-1 font-mono\">\n {dataSinkId.slice(0, 8)}...\n </code>\n {t('bigconsole.dataSinks.import.ifOriginalExistsSuffix', ') exists:')}\n </p>\n <ul className=\"mt-1 list-inside list-disc space-y-0.5\">\n <li>\n {t(\n 'bigconsole.dataSinks.import.withChangesUpdate',\n 'With changes → Update the existing DataSink'\n )}\n </li>\n <li>\n {t(\n 'bigconsole.dataSinks.import.noChangesMessage',\n 'No changes → Show \"already exists\" message'\n )}\n </li>\n </ul>\n <p className=\"mt-1\">\n {t(\n 'bigconsole.dataSinks.import.ifNotExistsCreate',\n \"If original doesn't exist → Create a new DataSink\"\n )}\n </p>\n </>\n ) : (\n <p>\n {t(\n 'bigconsole.dataSinks.import.newWillBeCreatedBody',\n 'Import as a new DataSink with the specified configuration.'\n )}\n </p>\n )}\n </div>\n </Section>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-name\">\n {t('bigconsole.dataSinks.import.nameFieldLabel', 'DataSink Name')}\n </Label>\n <Input\n id=\"import-name\"\n type=\"text\"\n value={nameOverride}\n onChange={(e) => setNameOverride(e.target.value)}\n placeholder={\n validationResult.dataSinkInfo?.name ||\n t('bigconsole.dataSinks.import.namePlaceholder', 'DataSink name')\n }\n disabled={step === 'importing'}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-key\">\n {t('bigconsole.dataSinks.import.keyFieldLabel', 'DataSink Key')}\n </Label>\n <Input\n id=\"import-key\"\n type=\"text\"\n value={keyOverride}\n onChange={(e) => setKeyOverride(e.target.value)}\n placeholder={\n validationResult.dataSinkInfo?.key ||\n t('bigconsole.dataSinks.import.keyPlaceholder', 'datasink-key')\n }\n disabled={step === 'importing'}\n />\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.keyHelp',\n 'Use a unique key to avoid conflicts with existing DataSinks.'\n )}\n </p>\n </div>\n </Section>\n )}\n </>\n )}\n\n {/* Step 3: Complete */}\n {step === 'complete' && importResult?.success && (\n <>\n {/* Already Exists - No Changes */}\n {importResult.alreadyExists && (\n <Section\n tone=\"info\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.alreadyExistsTitle', 'DataSink Already Exists')}\n icon={<Info className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.alreadyExistsBody',\n 'DataSink \"{{name}}\" already exists with the same data. No changes were made.',\n { name: importResult.dataSink?.name || importResult.dataSink?.key || '' }\n )}\n </p>\n </Section>\n )}\n\n {/* Updated Existing */}\n {importResult.originalUpdated && !importResult.alreadyExists && (\n <Section\n tone=\"success\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.updatedTitle', 'DataSink Updated!')}\n icon={<RefreshCw className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.updatedBody',\n 'DataSink \"{{name}}\" has been updated with the imported data.',\n { name: importResult.dataSink?.name || importResult.dataSink?.key || '' }\n )}\n </p>\n </Section>\n )}\n\n {/* Created New */}\n {!importResult.originalUpdated && !importResult.alreadyExists && (\n <Section\n tone=\"success\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.successTitle', 'Import Successful!')}\n icon={<Check className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.successBody', 'DataSink \"{{name}}\" has been created.', {\n name: importResult.dataSink?.name || importResult.dataSink?.key || '',\n })}\n </p>\n </Section>\n )}\n </>\n )}\n\n {/* Error */}\n {error && (\n <Section tone=\"danger\" padding=\"compact\" headingLevel={3} title=\"Import failed\">\n <p className=\"text-sm text-status-error-text\">{error.message}</p>\n </Section>\n )}\n\n {importResult && !importResult.success && importResult.errorMessage && (\n <Section tone=\"danger\" padding=\"compact\" headingLevel={3} title=\"Import failed\">\n <p className=\"text-sm text-status-error-text\">{importResult.errorMessage}</p>\n </Section>\n )}\n </SectionStack>\n </div>\n\n <DialogFooter className=\"flex flex-col-reverse gap-control-gap sm:flex-row sm:justify-between\">\n {step === 'preview' ? (\n <Button\n variant=\"ghost\"\n onClick={() => {\n setStep('select');\n setSelectedFile(null);\n setFileContent(null);\n clearState();\n }}\n disabled={loading}\n >\n <ArrowLeft className=\"size-4\" />\n {t('bigconsole.dataSinks.import.back', 'Back')}\n </Button>\n ) : (\n <span aria-hidden=\"true\" className=\"hidden sm:block\" />\n )}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n {step !== 'complete' && (\n <Button variant=\"outline\" onClick={onClose} disabled={!canClose}>\n {t('bigconsole.dataSinks.import.cancel', 'Cancel')}\n </Button>\n )}\n\n {step === 'preview' && validationResult?.isValid && (\n <Button onClick={handleImport} disabled={loading}>\n <Upload className=\"size-4\" />\n {t('bigconsole.dataSinks.import.importButton', 'Import DataSink')}\n </Button>\n )}\n\n {step === 'importing' && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Spinner className=\"size-4\" />\n {t('bigconsole.dataSinks.import.importing', 'Importing...')}\n </div>\n )}\n\n {step === 'complete' && <Button onClick={onClose}>{t('bigconsole.dataSinks.import.done', 'Done')}</Button>}\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default ImportDataSinkDialog;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ImportDataSinkDialog.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/ImportDataSinkDialog.tsx"],"sourcesContent":["/**\n * ImportDataSinkDialog Component\n *\n * Modal dialog for importing a DataSink from JSON file.\n * Supports both creating new DataSinks and updating existing ones.\n */\n\nimport { type FC, memo, useState, useCallback, useEffect, useRef } from 'react';\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Label } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Upload, FileJson, Check, XCircle, ArrowLeft, RefreshCw, Info } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useImportDataSink, type ImportDataSinkOptions } from '../../hooks';\nimport { useBigConsoleAnalytics } from '../../hooks/useBigConsoleAnalytics';\nimport { Section, SectionStack } from '../common';\nimport { reportBigConsoleQuotaError } from '../../utils/quota';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ImportDataSinkDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onSuccess?: (dataSinkId: string, dataSinkName: string | null, originalUpdated: boolean) => void;\n}\n\ntype ImportStep = 'select' | 'preview' | 'importing' | 'complete';\n\n/**\n * Wizard steps. The dialog previously moved between three screens with no\n * indicator at all, so a user could not tell where they were.\n */\nconst WIZARD_STEPS: { id: ImportStep; label: string }[] = [\n { id: 'select', label: 'Choose file' },\n { id: 'preview', label: 'Review' },\n { id: 'complete', label: 'Done' },\n];\n\n/** Index of the wizard step currently on screen ('importing' still shows Review). */\nfunction wizardIndex(step: ImportStep): number {\n if (step === 'select') return 0;\n if (step === 'complete') return 2;\n return 1;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ImportDataSinkDialog: FC<ImportDataSinkDialogProps> = memo(function ImportDataSinkDialog({\n isOpen,\n onClose,\n onSuccess,\n}) {\n const { t } = useI18n();\n const [step, setStep] = useState<ImportStep>('select');\n const [, setSelectedFile] = useState<File | null>(null);\n const [fileContent, setFileContent] = useState<string | null>(null);\n const [nameOverride, setNameOverride] = useState('');\n const [keyOverride, setKeyOverride] = useState('');\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const {\n loading,\n error,\n validationResult,\n importResult,\n validateImport,\n importDataSink,\n extractDataSinkId,\n clearState,\n } = useImportDataSink();\n const emitBigConsoleEvent = useBigConsoleAnalytics();\n\n // Reset state when dialog opens\n useEffect(() => {\n if (isOpen) {\n setStep('select');\n setSelectedFile(null);\n setFileContent(null);\n setNameOverride('');\n setKeyOverride('');\n clearState();\n }\n }, [isOpen, clearState]);\n\n // Handle file selection\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n if (!file.name.endsWith('.json')) {\n alert(t('bigconsole.dataSinks.import.selectJsonFile', 'Please select a JSON file'));\n return;\n }\n\n setSelectedFile(file);\n\n const reader = new FileReader();\n reader.onload = async (event) => {\n const content = event.target?.result as string;\n setFileContent(content);\n\n const result = validateImport(content);\n if (result.isValid && result.dataSinkInfo) {\n setStep('preview');\n setNameOverride(result.dataSinkInfo.name || '');\n setKeyOverride(result.dataSinkInfo.key || '');\n } else {\n setStep('preview');\n }\n };\n reader.onerror = () => {\n alert(t('bigconsole.dataSinks.import.readFileError', 'Failed to read file'));\n };\n reader.readAsText(file);\n },\n [validateImport, t]\n );\n\n // Handle file drop\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n const file = e.dataTransfer.files?.[0];\n if (file) {\n const dt = new DataTransfer();\n dt.items.add(file);\n if (fileInputRef.current) {\n fileInputRef.current.files = dt.files;\n fileInputRef.current.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }, []);\n\n // Handle import\n const handleImport = useCallback(async () => {\n if (!fileContent) return;\n\n setStep('importing');\n\n const options: ImportDataSinkOptions = {\n name: nameOverride.trim() || undefined,\n key: keyOverride.trim() || undefined,\n };\n\n emitBigConsoleEvent('bigconsole.data_sink.import_clicked', { source: 'import' });\n\n let result: Awaited<ReturnType<typeof importDataSink>>;\n try {\n result = await importDataSink(fileContent, options);\n } catch (err) {\n // Quota refusals (e.g. \"Set up billing\" for an org without a billing\n // account, BOFF-7913) are shown by the shared quota dialog.\n if (reportBigConsoleQuotaError(err)) {\n onClose();\n return;\n }\n setStep('preview');\n return;\n }\n\n if (result?.success && result.dataSink) {\n setStep('complete');\n emitBigConsoleEvent('bigconsole.data_sink.imported', {\n dataSinkId: result.dataSink.id,\n source: 'import',\n originalUpdated: result.originalUpdated ?? false,\n });\n onSuccess?.(result.dataSink.id, result.dataSink.name, result.originalUpdated ?? false);\n } else {\n setStep('preview');\n }\n }, [emitBigConsoleEvent, fileContent, importDataSink, keyOverride, nameOverride, onClose, onSuccess]);\n\n const canClose = !loading && step !== 'importing';\n const dataSinkId = fileContent ? extractDataSinkId(fileContent) : null;\n const currentStepIndex = wizardIndex(step);\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && canClose && onClose()}>\n <DialogContent className=\"flex max-h-[85vh] flex-col sm:max-w-lg\">\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-card bg-bg-accentSubtle\">\n <Upload className=\"size-5 text-text-link\" />\n </div>\n <DialogTitle>{t('bigconsole.dataSinks.import.title', 'Import DataSink')}</DialogTitle>\n </div>\n <DialogDescription>\n {t(\n 'bigconsole.dataSinks.import.description',\n 'Upload a DataSink export file to restore it into this workspace.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n {/* Step indicator — structural strip so the wizard reads as a sequence. */}\n <ol className=\"flex flex-wrap items-center gap-x-icon-gap gap-y-1 text-xs\" aria-label=\"Import progress\">\n {WIZARD_STEPS.map((wizardStep, index) => (\n <li\n key={wizardStep.id}\n aria-current={index === currentStepIndex ? 'step' : undefined}\n className={`flex items-center gap-icon-gap ${\n index === currentStepIndex ? 'font-semibold text-text-primary' : 'text-text-muted'\n }`}\n >\n <span\n className={`inline-flex size-5 items-center justify-center rounded-pill text-[10px] ${\n index <= currentStepIndex ? 'bg-action-primary-bg text-action-primary-text' : 'bg-bg-sunken'\n }`}\n >\n {index + 1}\n </span>\n {wizardStep.label}\n {index < WIZARD_STEPS.length - 1 && (\n <span aria-hidden=\"true\" className=\"text-text-muted\">\n ›\n </span>\n )}\n </li>\n ))}\n </ol>\n\n <div className=\"min-w-0 flex-1 overflow-y-auto py-4\">\n <SectionStack>\n {/* Step 1: File Selection */}\n {step === 'select' && (\n <Section\n title=\"Choose an export file\"\n description={t(\n 'bigconsole.dataSinks.import.supportedFilesHint',\n 'Only .json files exported from BigConsole are supported'\n )}\n headingLevel={3}\n bodyClassName=\"mt-form-gap\"\n >\n <div\n onDragOver={(e) => e.preventDefault()}\n onDrop={handleDrop}\n className=\"rounded-card border-2 border-dashed border-[var(--color-border-default)] p-8 text-center hover:border-[var(--color-action-primary-bg)] motion-safe:transition-colors\"\n >\n <FileJson className=\"mx-auto mb-4 size-12 text-text-secondary\" />\n <p className=\"mb-2 text-sm\">\n {t('bigconsole.dataSinks.import.dropzoneText', 'Drag and drop a DataSink export file here')}\n </p>\n <p className=\"mb-4 text-xs text-text-secondary\">{t('bigconsole.dataSinks.import.or', 'or')}</p>\n <input ref={fileInputRef} type=\"file\" accept=\".json\" onChange={handleFileSelect} className=\"hidden\" />\n <Button onClick={() => fileInputRef.current?.click()} disabled={loading}>\n {t('bigconsole.dataSinks.import.browseFiles', 'Browse Files')}\n </Button>\n </div>\n </Section>\n )}\n\n {/* Step 2: Preview & Options */}\n {(step === 'preview' || step === 'importing') && validationResult && (\n <>\n {/* What is in the file — supporting detail. */}\n {validationResult.dataSinkInfo && (\n <Section\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={3}\n title=\"File contents\"\n description=\"What this export file describes.\"\n bodyClassName=\"space-y-2\"\n >\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.nameLabel', 'Name')}\n </span>\n <span className=\"min-w-0 truncate text-sm font-medium\">\n {validationResult.dataSinkInfo.name || t('bigconsole.dataSinks.import.unnamed', 'Unnamed')}\n </span>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.keyLabel', 'Key')}\n </span>\n <span className=\"min-w-0 truncate font-mono text-xs\">{validationResult.dataSinkInfo.key}</span>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.statusLabel', 'Status')}\n </span>\n <Badge variant=\"secondary\">{validationResult.dataSinkInfo.status}</Badge>\n </div>\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.setupStateLabel', 'Setup State')}\n </span>\n <Badge variant=\"outline\">{validationResult.dataSinkInfo.setupState}</Badge>\n </div>\n {validationResult.dataSinkInfo.exportedFrom && (\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.sourceIdLabel', 'Source ID')}\n </span>\n <span className=\"min-w-0 max-w-[180px] truncate font-mono text-xs text-text-secondary\">\n {validationResult.dataSinkInfo.exportedFrom}\n </span>\n </div>\n )}\n <div className=\"flex items-center justify-between gap-icon-gap\">\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.schemaVersionLabel', 'Schema Version')}\n </span>\n <span className=\"text-xs text-text-secondary\">{validationResult.dataSinkInfo.schemaVersion}</span>\n </div>\n </Section>\n )}\n\n {/* Validation Errors */}\n {validationResult.errors.length > 0 && (\n <Section\n tone=\"danger\"\n padding=\"compact\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.errorsHeading', 'Errors ({{count}})', {\n count: validationResult.errors.length,\n })}\n icon={<XCircle className=\"size-4\" />}\n >\n <ul className=\"space-y-1 text-xs text-status-error-text\">\n {validationResult.errors.map((err, idx) => (\n <li key={idx}>\n <span className=\"font-mono\">[{err.code}]</span> {err.message}\n </li>\n ))}\n </ul>\n </Section>\n )}\n\n {/* Import Options */}\n {validationResult.isValid && (\n <Section\n title={t('bigconsole.dataSinks.import.optionsHeading', 'Import Options')}\n description=\"Rename the sink or give it a different key before importing.\"\n headingLevel={3}\n bodyClassName=\"space-y-form-gap\"\n >\n <Section\n tone=\"info\"\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={4}\n icon={<Info className=\"size-4\" />}\n title={\n dataSinkId\n ? t(\n 'bigconsole.dataSinks.import.checkExistingHeading',\n 'Import will check for existing DataSink'\n )\n : t('bigconsole.dataSinks.import.newWillBeCreatedHeading', 'A new DataSink will be created')\n }\n >\n <div className=\"text-xs text-[var(--color-status-info-text)]\">\n {dataSinkId ? (\n <>\n <p>\n {t('bigconsole.dataSinks.import.ifOriginalExistsPrefix', 'If the original DataSink (ID:')}{' '}\n <code className=\"rounded-input bg-bg-surface px-1 font-mono\">\n {dataSinkId.slice(0, 8)}...\n </code>\n {t('bigconsole.dataSinks.import.ifOriginalExistsSuffix', ') exists:')}\n </p>\n <ul className=\"mt-1 list-inside list-disc space-y-0.5\">\n <li>\n {t(\n 'bigconsole.dataSinks.import.withChangesUpdate',\n 'With changes → Update the existing DataSink'\n )}\n </li>\n <li>\n {t(\n 'bigconsole.dataSinks.import.noChangesMessage',\n 'No changes → Show \"already exists\" message'\n )}\n </li>\n </ul>\n <p className=\"mt-1\">\n {t(\n 'bigconsole.dataSinks.import.ifNotExistsCreate',\n \"If original doesn't exist → Create a new DataSink\"\n )}\n </p>\n </>\n ) : (\n <p>\n {t(\n 'bigconsole.dataSinks.import.newWillBeCreatedBody',\n 'Import as a new DataSink with the specified configuration.'\n )}\n </p>\n )}\n </div>\n </Section>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-name\">\n {t('bigconsole.dataSinks.import.nameFieldLabel', 'DataSink Name')}\n </Label>\n <Input\n id=\"import-name\"\n type=\"text\"\n value={nameOverride}\n onChange={(e) => setNameOverride(e.target.value)}\n placeholder={\n validationResult.dataSinkInfo?.name ||\n t('bigconsole.dataSinks.import.namePlaceholder', 'DataSink name')\n }\n disabled={step === 'importing'}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"import-key\">\n {t('bigconsole.dataSinks.import.keyFieldLabel', 'DataSink Key')}\n </Label>\n <Input\n id=\"import-key\"\n type=\"text\"\n value={keyOverride}\n onChange={(e) => setKeyOverride(e.target.value)}\n placeholder={\n validationResult.dataSinkInfo?.key ||\n t('bigconsole.dataSinks.import.keyPlaceholder', 'datasink-key')\n }\n disabled={step === 'importing'}\n />\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.keyHelp',\n 'Use a unique key to avoid conflicts with existing DataSinks.'\n )}\n </p>\n </div>\n </Section>\n )}\n </>\n )}\n\n {/* Step 3: Complete */}\n {step === 'complete' && importResult?.success && (\n <>\n {/* Already Exists - No Changes */}\n {importResult.alreadyExists && (\n <Section\n tone=\"info\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.alreadyExistsTitle', 'DataSink Already Exists')}\n icon={<Info className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.alreadyExistsBody',\n 'DataSink \"{{name}}\" already exists with the same data. No changes were made.',\n { name: importResult.dataSink?.name || importResult.dataSink?.key || '' }\n )}\n </p>\n </Section>\n )}\n\n {/* Updated Existing */}\n {importResult.originalUpdated && !importResult.alreadyExists && (\n <Section\n tone=\"success\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.updatedTitle', 'DataSink Updated!')}\n icon={<RefreshCw className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'bigconsole.dataSinks.import.updatedBody',\n 'DataSink \"{{name}}\" has been updated with the imported data.',\n { name: importResult.dataSink?.name || importResult.dataSink?.key || '' }\n )}\n </p>\n </Section>\n )}\n\n {/* Created New */}\n {!importResult.originalUpdated && !importResult.alreadyExists && (\n <Section\n tone=\"success\"\n headingLevel={3}\n title={t('bigconsole.dataSinks.import.successTitle', 'Import Successful!')}\n icon={<Check className=\"h-icon-sm w-icon-sm\" />}\n >\n <p className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.import.successBody', 'DataSink \"{{name}}\" has been created.', {\n name: importResult.dataSink?.name || importResult.dataSink?.key || '',\n })}\n </p>\n </Section>\n )}\n </>\n )}\n\n {/* Error */}\n {error && (\n <Section tone=\"danger\" padding=\"compact\" headingLevel={3} title=\"Import failed\">\n <p className=\"text-sm text-status-error-text\">{error.message}</p>\n </Section>\n )}\n\n {importResult && !importResult.success && importResult.errorMessage && (\n <Section tone=\"danger\" padding=\"compact\" headingLevel={3} title=\"Import failed\">\n <p className=\"text-sm text-status-error-text\">{importResult.errorMessage}</p>\n </Section>\n )}\n </SectionStack>\n </div>\n\n <DialogFooter className=\"flex flex-col-reverse gap-control-gap sm:flex-row sm:justify-between\">\n {step === 'preview' ? (\n <Button\n variant=\"ghost\"\n onClick={() => {\n setStep('select');\n setSelectedFile(null);\n setFileContent(null);\n clearState();\n }}\n disabled={loading}\n >\n <ArrowLeft className=\"size-4\" />\n {t('bigconsole.dataSinks.import.back', 'Back')}\n </Button>\n ) : (\n <span aria-hidden=\"true\" className=\"hidden sm:block\" />\n )}\n\n <div className=\"flex flex-wrap items-center gap-2\">\n {step !== 'complete' && (\n <Button variant=\"outline\" onClick={onClose} disabled={!canClose}>\n {t('bigconsole.dataSinks.import.cancel', 'Cancel')}\n </Button>\n )}\n\n {step === 'preview' && validationResult?.isValid && (\n <Button onClick={handleImport} disabled={loading}>\n <Upload className=\"size-4\" />\n {t('bigconsole.dataSinks.import.importButton', 'Import DataSink')}\n </Button>\n )}\n\n {step === 'importing' && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <Spinner className=\"size-4\" />\n {t('bigconsole.dataSinks.import.importing', 'Importing...')}\n </div>\n )}\n\n {step === 'complete' && <Button onClick={onClose}>{t('bigconsole.dataSinks.import.done', 'Done')}</Button>}\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n});\n\nexport default ImportDataSinkDialog;\n"],"mappings":"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"}
@@ -6,11 +6,11 @@ import { DOCK_CLEARANCE as i, PreviewMeta as a, STEP_LABEL as o, formatAgo as s,
6
6
  import { ArrowUpRight as l, Braces as u, Database as d, LayoutDashboard as f, Loader2 as p, Sparkles as m, X as h } from "lucide-react";
7
7
  import { Button as g } from "@burdenoff/fe-libs/ui";
8
8
  import { jsx as _, jsxs as v } from "react/jsx-runtime";
9
- import { AssistantEntityPreview as y } from "@burdenoff/fe-libs/shared/assistant";
10
- import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
+ import { useI18n as y } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
+ import { AssistantEntityPreview as b } from "@burdenoff/fe-libs/shared/assistant";
11
11
  //#region src/bigconsole/components/preview/AiPreviewMiniPanel.tsx
12
12
  function x({ onNavigate: x }) {
13
- let { t: S } = b(), C = e(), w = n((e) => e.isRunning), T = n((e) => e.previewOpen), E = n((e) => e.hasRun), D = n((e) => e.richMounted), O = n((e) => e.steps), k = n((e) => e.entityIds), A = n((e) => e.caption), j = n((e) => e.error), M = n((e) => e.updatedAt), N = n((e) => e.openPreview), P = n((e) => e.closePreview), F = (e) => {
13
+ let { t: S } = y(), C = e(), w = n((e) => e.isRunning), T = n((e) => e.previewOpen), E = n((e) => e.hasRun), D = n((e) => e.richMounted), O = n((e) => e.steps), k = n((e) => e.entityIds), A = n((e) => e.caption), j = n((e) => e.error), M = n((e) => e.updatedAt), N = n((e) => e.openPreview), P = n((e) => e.closePreview), F = (e) => {
14
14
  x ? x(e) : typeof window < "u" && window.location.assign(e);
15
15
  };
16
16
  if (!E || D || C) return null;
@@ -71,7 +71,7 @@ function x({ onNavigate: x }) {
71
71
  children: [/* @__PURE__ */ _("h2", {
72
72
  className: "sr-only",
73
73
  children: S("bigconsole.widget.aiPreviewMini.title", "AI Preview")
74
- }), /* @__PURE__ */ _(y, {
74
+ }), /* @__PURE__ */ _(b, {
75
75
  title: S("bigconsole.widget.aiPreviewMini.title", "AI Preview"),
76
76
  steps: L,
77
77
  caption: w ? A || S("bigconsole.widget.aiPreviewMini.working", "Working…") : S("bigconsole.widget.aiPreviewMini.done", "Done"),
@@ -10,8 +10,8 @@ import { useEffect as m, useRef as h, useState as g } from "react";
10
10
  import { ArrowUpRight as _, Loader2 as v, Sparkles as y, X as b } from "lucide-react";
11
11
  import { Button as x } from "@burdenoff/fe-libs/ui";
12
12
  import { jsx as S, jsxs as C } from "react/jsx-runtime";
13
- import { AssistantEntityPreview as w } from "@burdenoff/fe-libs/shared/assistant";
14
- import { useI18n as T } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
+ import { useI18n as w } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
14
+ import { AssistantEntityPreview as T } from "@burdenoff/fe-libs/shared/assistant";
15
15
  //#region src/bigconsole/components/preview/AiPreviewPanel.tsx
16
16
  function E({ children: e }) {
17
17
  return /* @__PURE__ */ S("div", {
@@ -21,7 +21,7 @@ function E({ children: e }) {
21
21
  });
22
22
  }
23
23
  function D({ onOpen: e }) {
24
- let { t } = T();
24
+ let { t } = w();
25
25
  return /* @__PURE__ */ C(x, {
26
26
  size: "sm",
27
27
  variant: "outline",
@@ -31,7 +31,7 @@ function D({ onOpen: e }) {
31
31
  });
32
32
  }
33
33
  function O() {
34
- let { t: _ } = T(), O = t(), k = e(), A = r((e) => e.isRunning), j = r((e) => e.previewOpen), M = r((e) => e.hasRun), N = r((e) => e.steps), P = r((e) => e.entityIds), F = r((e) => e.caption), I = r((e) => e.error), L = r((e) => e.updatedAt), R = r((e) => e.openPreview), z = r((e) => e.closePreview), B = r((e) => e.setRichMounted);
34
+ let { t: _ } = w(), O = t(), k = e(), A = r((e) => e.isRunning), j = r((e) => e.previewOpen), M = r((e) => e.hasRun), N = r((e) => e.steps), P = r((e) => e.entityIds), F = r((e) => e.caption), I = r((e) => e.error), L = r((e) => e.updatedAt), R = r((e) => e.openPreview), z = r((e) => e.closePreview), B = r((e) => e.setRichMounted);
35
35
  m(() => (B(!0), () => {
36
36
  B(!1);
37
37
  }), [B]);
@@ -131,7 +131,7 @@ function O() {
131
131
  children: [/* @__PURE__ */ S("h2", {
132
132
  className: "sr-only",
133
133
  children: _("bigconsole.widget.aiPreview.title", "AI Preview")
134
- }), /* @__PURE__ */ S(w, {
134
+ }), /* @__PURE__ */ S(T, {
135
135
  title: _("bigconsole.widget.aiPreview.title", "AI Preview"),
136
136
  runKey: String(V),
137
137
  steps: G,