strapi-plugin-bulk-updater 1.4.2 → 1.4.6

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.
@@ -146,7 +146,7 @@ function CsvManagerTab() {
146
146
  const [collections, setCollections] = React.useState([]);
147
147
  const [loadingCollections, setLoadingCollections] = React.useState(true);
148
148
  const [selectedUid, setSelectedUid] = React.useState("");
149
- const [exportLimit, setExportLimit] = React.useState(1e3);
149
+ const [exportLimit, setExportLimit] = React.useState(0);
150
150
  const [exportOnlyViolations, setExportOnlyViolations] = React.useState(false);
151
151
  const [rules, setRules] = React.useState([]);
152
152
  const [selectedRuleId, setSelectedRuleId] = React.useState("");
@@ -154,9 +154,18 @@ function CsvManagerTab() {
154
154
  const [publishOnImport, setPublishOnImport] = React.useState(true);
155
155
  const [csvRawText, setCsvRawText] = React.useState("");
156
156
  const [fileName, setFileName] = React.useState("");
157
- const [parsedPreview, setParsedPreview] = React.useState([]);
157
+ const [allParsedRecords, setAllParsedRecords] = React.useState([]);
158
+ const [previewPage, setPreviewPage] = React.useState(1);
159
+ const [previewPageSize, setPreviewPageSize] = React.useState(10);
158
160
  const [importing, setImporting] = React.useState(false);
161
+ const [importProgress, setImportProgress] = React.useState(null);
159
162
  const [importResult, setImportResult] = React.useState(null);
163
+ const [executionWindow, setExecutionWindow] = React.useState(null);
164
+ const [preflightLoading, setPreflightLoading] = React.useState(false);
165
+ const [preflightReport, setPreflightReport] = React.useState(null);
166
+ const [showConfirmModal, setShowConfirmModal] = React.useState(false);
167
+ const [makerNotesInput, setMakerNotesInput] = React.useState("");
168
+ const [submittingBatch, setSubmittingBatch] = React.useState(false);
160
169
  React.useEffect(() => {
161
170
  fetchInitialData();
162
171
  }, []);
@@ -167,6 +176,9 @@ function CsvManagerTab() {
167
176
  get("/bulk-updater/models"),
168
177
  get("/bulk-updater/validation-rules")
169
178
  ]);
179
+ if (modelsRes.data?.executionWindow) {
180
+ setExecutionWindow(modelsRes.data.executionWindow);
181
+ }
170
182
  if (modelsRes.data?.collections) {
171
183
  setCollections(modelsRes.data.collections);
172
184
  if (modelsRes.data.collections.length > 0) {
@@ -217,7 +229,7 @@ function CsvManagerTab() {
217
229
  downloadCsvFile(csvStr, filename);
218
230
  toggleNotification({
219
231
  type: "success",
220
- message: "Collection exported to CSV successfully"
232
+ message: `Collection exported successfully (${res.data?.count ?? 0} records)`
221
233
  });
222
234
  } catch (err) {
223
235
  if (ValidationRulesTab.isAbortError(err)) return;
@@ -270,34 +282,93 @@ function CsvManagerTab() {
270
282
  if (!file) return;
271
283
  setFileName(file.name);
272
284
  setImportResult(null);
285
+ setImportProgress(null);
273
286
  const reader = new FileReader();
274
287
  reader.onload = (event) => {
275
288
  const text = event.target?.result;
276
289
  setCsvRawText(text);
277
290
  try {
278
291
  const records = parseCsv(text);
279
- setParsedPreview(records.slice(0, 10));
292
+ setAllParsedRecords(records);
293
+ setPreviewPage(1);
280
294
  } catch (err) {
281
- setParsedPreview([]);
295
+ setAllParsedRecords([]);
282
296
  }
283
297
  };
284
298
  reader.readAsText(file);
285
299
  };
286
300
  const handleExecuteImport = async () => {
287
- if (!selectedUid || !csvRawText) return;
301
+ if (!selectedUid || allParsedRecords.length === 0) return;
302
+ const totalRows = allParsedRecords.length;
303
+ const CHUNK_SIZE = 100;
304
+ const totalChunks = Math.ceil(totalRows / CHUNK_SIZE);
305
+ const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
288
306
  try {
289
307
  setImporting(true);
290
308
  setImportResult(null);
291
- const res = await post("/bulk-updater/csv/import", {
292
- uid: selectedUid,
293
- csvText: csvRawText,
294
- mode: importMode,
295
- publish: publishOnImport
309
+ let liveCreated = 0;
310
+ let liveUpdated = 0;
311
+ let liveSkipped = 0;
312
+ let liveErrors = 0;
313
+ let finalResultData = null;
314
+ setImportProgress({
315
+ currentChunk: 0,
316
+ totalChunks,
317
+ percent: 0,
318
+ processedRows: 0,
319
+ totalRows,
320
+ liveCreated: 0,
321
+ liveUpdated: 0,
322
+ liveSkipped: 0,
323
+ liveErrors: 0
296
324
  });
297
- if (res.data && res.data.success) {
298
- setImportResult(res.data);
299
- const stats = res.data.stats;
300
- let notifMsg = `CSV Import complete: ${stats.created} created, ${stats.updated} updated.`;
325
+ for (let chunkIdx = 0; chunkIdx < totalChunks; chunkIdx++) {
326
+ const startIdx = chunkIdx * CHUNK_SIZE;
327
+ const endIdx = Math.min(startIdx + CHUNK_SIZE, totalRows);
328
+ const chunkRows = allParsedRecords.slice(startIdx, endIdx);
329
+ const isFirst = chunkIdx === 0;
330
+ const isLast = chunkIdx === totalChunks - 1;
331
+ const startRowNumber = startIdx + 2;
332
+ const res = await post("/bulk-updater/csv/import-chunk", {
333
+ uid: selectedUid,
334
+ rows: chunkRows,
335
+ batchId,
336
+ isFirstChunk: isFirst,
337
+ isLastChunk: isLast,
338
+ startRowNumber,
339
+ mode: importMode,
340
+ publish: publishOnImport
341
+ });
342
+ if (!res.data || !res.data.success) {
343
+ throw new Error(res.data?.error || `Chunk ${chunkIdx + 1} failed to process`);
344
+ }
345
+ const chunkStats = res.data.chunkStats;
346
+ if (chunkStats) {
347
+ liveCreated += chunkStats.created || 0;
348
+ liveUpdated += chunkStats.updated || 0;
349
+ liveSkipped += chunkStats.skipped || 0;
350
+ liveErrors += chunkStats.errors?.length || 0;
351
+ }
352
+ const currentProgressPercent = Math.round((chunkIdx + 1) / totalChunks * 100);
353
+ setImportProgress({
354
+ currentChunk: chunkIdx + 1,
355
+ totalChunks,
356
+ percent: currentProgressPercent,
357
+ processedRows: endIdx,
358
+ totalRows,
359
+ liveCreated,
360
+ liveUpdated,
361
+ liveSkipped,
362
+ liveErrors
363
+ });
364
+ if (isLast) {
365
+ finalResultData = res.data;
366
+ }
367
+ }
368
+ if (finalResultData && finalResultData.stats) {
369
+ setImportResult(finalResultData);
370
+ const stats = finalResultData.stats;
371
+ let notifMsg = `CSV Import complete: ${stats.created} created, ${stats.updated} updated across ${stats.total} records.`;
301
372
  if (stats.newWithoutDocId && stats.newWithoutDocId > 0) {
302
373
  notifMsg += ` (${stats.newWithoutDocId} new entries created due to omitted documentId)`;
303
374
  }
@@ -305,348 +376,864 @@ function CsvManagerTab() {
305
376
  type: "success",
306
377
  message: notifMsg
307
378
  });
308
- } else {
309
- throw new Error(res.data?.error || "Import failed");
310
379
  }
311
380
  } catch (err) {
312
381
  if (ValidationRulesTab.isAbortError(err)) return;
313
382
  toggleNotification({
314
383
  type: "danger",
315
- message: err.message || "Error processing CSV import"
384
+ message: err.message || "Error processing CSV import batch"
316
385
  });
317
386
  } finally {
318
387
  setImporting(false);
319
388
  }
320
389
  };
390
+ const handleRunPreflight = async () => {
391
+ if (!selectedUid || allParsedRecords.length === 0) return;
392
+ try {
393
+ setPreflightLoading(true);
394
+ const res = await post("/bulk-updater/csv/validate-preflight", {
395
+ uid: selectedUid,
396
+ rows: allParsedRecords,
397
+ mode: importMode
398
+ });
399
+ if (res.data && res.data.success) {
400
+ setPreflightReport(res.data);
401
+ if (res.data.hasErrors) {
402
+ toggleNotification({
403
+ type: "warning",
404
+ message: `Pre-flight validation: ${res.data.totalErrorCount} error(s) and ${res.data.totalWarningCount} warning(s) detected.`
405
+ });
406
+ } else if (res.data.hasWarnings) {
407
+ toggleNotification({
408
+ type: "warning",
409
+ message: `Pre-flight validation passed with ${res.data.totalWarningCount} warning(s).`
410
+ });
411
+ } else {
412
+ toggleNotification({
413
+ type: "success",
414
+ message: `Pre-flight validation passed! All ${res.data.validRows} rows are ready for import.`
415
+ });
416
+ }
417
+ }
418
+ } catch (err) {
419
+ if (ValidationRulesTab.isAbortError(err)) return;
420
+ toggleNotification({
421
+ type: "danger",
422
+ message: err.message || "Failed running pre-flight validation"
423
+ });
424
+ } finally {
425
+ setPreflightLoading(false);
426
+ }
427
+ };
428
+ const submitBatchWithMode = async (executionMode, forceImmediate = false) => {
429
+ if (!selectedUid || allParsedRecords.length === 0) return;
430
+ if (executionMode === "immediate") {
431
+ setShowConfirmModal(false);
432
+ await handleExecuteImport();
433
+ return;
434
+ }
435
+ try {
436
+ setSubmittingBatch(true);
437
+ const res = await post("/bulk-updater/csv/submit-batch", {
438
+ uid: selectedUid,
439
+ rows: allParsedRecords,
440
+ executionMode,
441
+ makerNotes: makerNotesInput,
442
+ forceImmediate,
443
+ mode: importMode,
444
+ publish: publishOnImport
445
+ });
446
+ setShowConfirmModal(false);
447
+ if (res.data && res.data.pending) {
448
+ setMakerNotesInput("");
449
+ toggleNotification({
450
+ type: "success",
451
+ message: res.data.message || "CSV batch submitted for Checker authorization."
452
+ });
453
+ } else if (res.data && res.data.executeNow) {
454
+ await handleExecuteImport();
455
+ }
456
+ } catch (err) {
457
+ if (ValidationRulesTab.isAbortError(err)) return;
458
+ toggleNotification({
459
+ type: "danger",
460
+ message: err.message || "Failed submitting CSV batch"
461
+ });
462
+ } finally {
463
+ setSubmittingBatch(false);
464
+ }
465
+ };
321
466
  const selectedCol = collections.find((c) => c.uid === selectedUid);
322
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 6, background: "neutral0", hasRadius: true, shadow: "filterShadow", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
323
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
324
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
325
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", fontWeight: "bold", children: "CSV Export & Import Center" }),
326
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Export all records, filtered subsets, or rule violations into CSV. Correct or add records in spreadsheets and re-upload with full schema & quota enforcement." })
467
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, background: "neutral0", hasRadius: true, shadow: "filterShadow", children: [
468
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
469
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
470
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
471
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", fontWeight: "bold", children: "CSV Export & Import Center" }),
472
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Export all records (including 10,000+ datasets), filtered subsets, or rule violations into CSV. Correct or add records in spreadsheets and re-upload with high-performance chunked batch processing." })
473
+ ] }),
474
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowClockwise, {}), onClick: fetchInitialData, children: "Refresh" })
327
475
  ] }),
328
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowClockwise, {}), onClick: fetchInitialData, children: "Refresh" })
329
- ] }),
330
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, background: "neutral100", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, alignItems: "flex-end", children: [
331
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
332
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", marginBottom: 2, children: "Target Collection Type" }),
476
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, background: "neutral100", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, alignItems: "flex-end", children: [
477
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
478
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", marginBottom: 2, children: "Target Collection Type" }),
479
+ /* @__PURE__ */ jsxRuntime.jsx(
480
+ designSystem.SingleSelect,
481
+ {
482
+ value: selectedUid,
483
+ onChange: (val) => {
484
+ setSelectedUid(val);
485
+ setImportResult(null);
486
+ setImportProgress(null);
487
+ },
488
+ disabled: loadingCollections,
489
+ placeholder: "Select a collection...",
490
+ children: collections.map((col) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: col.uid, children: [
491
+ col.displayName,
492
+ " (",
493
+ col.totalEntries ?? 0,
494
+ " records)"
495
+ ] }, col.uid))
496
+ }
497
+ )
498
+ ] }),
333
499
  /* @__PURE__ */ jsxRuntime.jsx(
334
- designSystem.SingleSelect,
335
- {
336
- value: selectedUid,
337
- onChange: (val) => {
338
- setSelectedUid(val);
339
- setImportResult(null);
340
- },
341
- disabled: loadingCollections,
342
- placeholder: "Select a collection...",
343
- children: collections.map((col) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: col.uid, children: [
344
- col.displayName,
345
- " (",
346
- col.totalEntries ?? 0,
347
- " records)"
348
- ] }, col.uid))
349
- }
350
- )
351
- ] }),
352
- /* @__PURE__ */ jsxRuntime.jsx(
353
- designSystem.Button,
354
- {
355
- variant: "tertiary",
356
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
357
- onClick: handleDownloadTemplate,
358
- disabled: !selectedUid,
359
- children: "Download Sample CSV Template"
360
- }
361
- )
362
- ] }) }),
363
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 5, background: "neutral100", hasRadius: true, children: [
364
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h3", fontWeight: "bold", marginBottom: 2, children: "1. Export Data to CSV" }),
365
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", marginBottom: 4, children: "Extract entire collections or pinpoint records violating validation quotas." }),
366
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, wrap: "wrap", alignItems: "center", marginTop: 3, children: [
367
- /* @__PURE__ */ jsxRuntime.jsxs(
368
500
  designSystem.Button,
369
501
  {
370
- variant: "default",
502
+ variant: "tertiary",
371
503
  startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
372
- onClick: handleExportCollection,
504
+ onClick: handleDownloadTemplate,
373
505
  disabled: !selectedUid,
374
- children: [
375
- "Export All ",
376
- selectedCol?.displayName || "Collection",
377
- " Records (.csv)"
378
- ]
506
+ children: "Download Sample CSV Template"
379
507
  }
380
- ),
381
- rules.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", style: { marginLeft: "auto" }, children: [
382
- /* @__PURE__ */ jsxRuntime.jsx(
508
+ )
509
+ ] }) }),
510
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 5, background: "neutral100", hasRadius: true, children: [
511
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h3", fontWeight: "bold", marginBottom: 2, children: "1. Export Data to CSV" }),
512
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", marginBottom: 4, children: "Extract entire collections without artificial limits (streams 10,000+ records in paged chunks) or pinpoint records violating validation quotas." }),
513
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, wrap: "wrap", alignItems: "center", marginTop: 3, children: [
514
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 220 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
383
515
  designSystem.SingleSelect,
384
516
  {
385
- value: selectedRuleId,
386
- onChange: (val) => setSelectedRuleId(val),
387
- placeholder: "Select Quota Rule...",
388
- children: rules.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: r.id, children: [
389
- "Rule: ",
390
- r.name
391
- ] }, r.id))
517
+ value: String(exportLimit),
518
+ onChange: (val) => setExportLimit(Number(val)),
519
+ placeholder: "Export Limit",
520
+ children: [
521
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "0", children: "All Records (No Limit)" }),
522
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "10000", children: "Up to 10,000 Records" }),
523
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "5000", children: "Up to 5,000 Records" }),
524
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "1000", children: "Up to 1,000 Records" })
525
+ ]
392
526
  }
393
- ),
394
- /* @__PURE__ */ jsxRuntime.jsx(
527
+ ) }),
528
+ /* @__PURE__ */ jsxRuntime.jsxs(
395
529
  designSystem.Button,
396
530
  {
397
- variant: "danger-light",
531
+ variant: "default",
398
532
  startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
399
- onClick: handleExportViolations,
400
- disabled: !selectedRuleId,
401
- children: "Export Violators CSV"
533
+ onClick: handleExportCollection,
534
+ disabled: !selectedUid,
535
+ children: [
536
+ "Export ",
537
+ exportLimit === 0 ? "All" : `${exportLimit}`,
538
+ " ",
539
+ selectedCol?.displayName || "Collection",
540
+ " Records (.csv)"
541
+ ]
402
542
  }
403
- )
404
- ] })
405
- ] })
406
- ] }),
407
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 5, background: "neutral100", hasRadius: true, children: [
408
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h3", fontWeight: "bold", marginBottom: 2, children: "2. Import & Batch Override CSV" }),
409
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", marginBottom: 4, children: "Upload an updated CSV file to bulk update existing records or insert new records." }),
410
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, wrap: "wrap", gap: 4, children: [
411
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
412
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", marginBottom: 1, display: "block", children: "Operation Mode" }),
413
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
414
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: "⚡ Smart Auto-Detect" }),
415
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
416
- "Automatically updates matching records by ",
417
- /* @__PURE__ */ jsxRuntime.jsx("code", { children: "documentId" }),
418
- " and creates new entries when ID is omitted."
419
- ] })
543
+ ),
544
+ rules.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", style: { marginLeft: "auto" }, children: [
545
+ /* @__PURE__ */ jsxRuntime.jsx(
546
+ designSystem.SingleSelect,
547
+ {
548
+ value: selectedRuleId,
549
+ onChange: (val) => setSelectedRuleId(val),
550
+ placeholder: "Select Quota Rule...",
551
+ children: rules.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: r.id, children: [
552
+ "Rule: ",
553
+ r.name
554
+ ] }, r.id))
555
+ }
556
+ ),
557
+ /* @__PURE__ */ jsxRuntime.jsx(
558
+ designSystem.Button,
559
+ {
560
+ variant: "danger-light",
561
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
562
+ onClick: handleExportViolations,
563
+ disabled: !selectedRuleId,
564
+ children: "Export Violators CSV"
565
+ }
566
+ )
420
567
  ] })
421
- ] }),
422
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
423
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", marginBottom: 1, display: "block", children: "Publish Options" }),
424
- /* @__PURE__ */ jsxRuntime.jsx(
425
- designSystem.Checkbox,
426
- {
427
- checked: publishOnImport,
428
- onValueChange: (val) => setPublishOnImport(val),
429
- children: "Auto-publish on import"
430
- }
431
- )
432
568
  ] })
433
569
  ] }),
434
- /* @__PURE__ */ jsxRuntime.jsxs(
435
- designSystem.Box,
436
- {
437
- padding: 6,
438
- background: "neutral0",
439
- hasRadius: true,
440
- style: {
441
- border: "2px dashed #dcdce4",
442
- textAlign: "center",
443
- cursor: "pointer"
444
- },
445
- children: [
570
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 5, background: "neutral100", hasRadius: true, children: [
571
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h3", fontWeight: "bold", marginBottom: 2, children: "2. Import & Batch Override CSV" }),
572
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", marginBottom: 4, children: "Upload an updated CSV file (supports 10,000+ records via chunked streaming) to bulk update existing records or insert new records." }),
573
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, wrap: "wrap", gap: 4, children: [
574
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
575
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", marginBottom: 1, display: "block", children: "Operation Mode" }),
576
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
577
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: "⚡ Smart Auto-Detect" }),
578
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
579
+ "Automatically updates matching records by ",
580
+ /* @__PURE__ */ jsxRuntime.jsx("code", { children: "documentId" }),
581
+ " and creates new entries when ID is omitted."
582
+ ] })
583
+ ] })
584
+ ] }),
585
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
586
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", marginBottom: 1, display: "block", children: "Publish Options" }),
446
587
  /* @__PURE__ */ jsxRuntime.jsx(
447
- "input",
588
+ designSystem.Checkbox,
448
589
  {
449
- type: "file",
450
- accept: ".csv",
451
- id: "csv-file-input",
452
- style: { display: "none" },
453
- onChange: handleFileUpload
590
+ checked: publishOnImport,
591
+ onValueChange: (val) => setPublishOnImport(val),
592
+ children: "Auto-publish on import"
454
593
  }
455
- ),
456
- /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: "csv-file-input", style: { cursor: "pointer", display: "block" }, children: [
457
- /* @__PURE__ */ jsxRuntime.jsx(icons.Upload, { style: { width: 32, height: 32, margin: "0 auto 8px", color: "#4945ff" } }),
458
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", display: "block", children: fileName ? `Selected: ${fileName}` : "Click here or drag a .csv file to upload" }),
459
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "UTF-8 encoded CSV matching collection schema headers" })
460
- ] })
461
- ]
462
- }
463
- ),
464
- parsedPreview.length > 0 && (() => {
465
- const missingDocIdCount = parsedPreview.filter(
466
- (row) => !extractDocId(row)
467
- ).length;
468
- const headers = Object.keys(parsedPreview[0]);
469
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 4, background: "neutral0", padding: 4, hasRadius: true, children: [
470
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 3, children: [
471
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
472
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "neutral700", children: [
473
- "FILE PREVIEW (FIRST ",
474
- parsedPreview.length,
475
- " ROWS)"
594
+ )
595
+ ] })
596
+ ] }),
597
+ /* @__PURE__ */ jsxRuntime.jsxs(
598
+ designSystem.Box,
599
+ {
600
+ padding: 6,
601
+ background: "neutral0",
602
+ hasRadius: true,
603
+ style: {
604
+ border: "2px dashed #dcdce4",
605
+ textAlign: "center",
606
+ cursor: "pointer"
607
+ },
608
+ children: [
609
+ /* @__PURE__ */ jsxRuntime.jsx(
610
+ "input",
611
+ {
612
+ type: "file",
613
+ accept: ".csv",
614
+ id: "csv-file-input",
615
+ style: { display: "none" },
616
+ onChange: handleFileUpload
617
+ }
618
+ ),
619
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: "csv-file-input", style: { cursor: "pointer", display: "block" }, children: [
620
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Upload, { style: { width: 32, height: 32, margin: "0 auto 8px", color: "#4945ff" } }),
621
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", display: "block", children: fileName ? `Selected: ${fileName}` : "Click here or drag a .csv file to upload" }),
622
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "UTF-8 encoded CSV matching collection schema headers" })
623
+ ] })
624
+ ]
625
+ }
626
+ ),
627
+ allParsedRecords.length > 0 && (() => {
628
+ const totalRows = allParsedRecords.length;
629
+ const missingDocIdCount = allParsedRecords.filter((row) => !extractDocId(row)).length;
630
+ const updateCount = totalRows - missingDocIdCount;
631
+ const headers = Object.keys(allParsedRecords[0]);
632
+ const totalPages = Math.ceil(totalRows / previewPageSize) || 1;
633
+ const safePage = Math.min(Math.max(1, previewPage), totalPages);
634
+ const startIndex = (safePage - 1) * previewPageSize;
635
+ const endIndex = Math.min(startIndex + previewPageSize, totalRows);
636
+ const displayedRows = allParsedRecords.slice(startIndex, endIndex);
637
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 4, background: "neutral0", padding: 4, hasRadius: true, children: [
638
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 3, wrap: "wrap", gap: 2, children: [
639
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
640
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "neutral700", children: [
641
+ "FILE PREVIEW — ",
642
+ totalRows.toLocaleString(),
643
+ " RECORDS DETECTED IN CSV"
644
+ ] }),
645
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral500", display: "block", children: [
646
+ totalRows.toLocaleString(),
647
+ " total row",
648
+ totalRows > 1 ? "s" : "",
649
+ " •",
650
+ " ",
651
+ updateCount > 0 ? `${updateCount.toLocaleString()} updates` : "",
652
+ updateCount > 0 && missingDocIdCount > 0 ? ", " : "",
653
+ missingDocIdCount > 0 ? `${missingDocIdCount.toLocaleString()} new entries (missing documentId)` : ""
654
+ ] })
476
655
  ] }),
477
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral500", display: "block", children: [
478
- parsedPreview.length,
479
- " previewed row",
480
- parsedPreview.length > 1 ? "s" : "",
481
- " •",
482
- " ",
483
- missingDocIdCount > 0 ? `${missingDocIdCount} row${missingDocIdCount > 1 ? "s" : ""} missing documentId (will be created as new entries)` : "All previewed rows contain document IDs"
656
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
657
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
658
+ "🔄 ",
659
+ updateCount.toLocaleString(),
660
+ " Updates"
661
+ ] }),
662
+ missingDocIdCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "warning100", textColor: "warning700", children: [
663
+ "➕ ",
664
+ missingDocIdCount.toLocaleString(),
665
+ " New (No ID)"
666
+ ] })
484
667
  ] })
485
668
  ] }),
486
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: missingDocIdCount > 0 ? "warning100" : "success100", textColor: missingDocIdCount > 0 ? "warning700" : "success700", children: missingDocIdCount > 0 ? `${missingDocIdCount} New (No ID)` : "Ready to Import" })
487
- ] }),
488
- missingDocIdCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginBottom: 3, children: /* @__PURE__ */ jsxRuntime.jsx(
489
- designSystem.Alert,
490
- {
491
- variant: "default",
492
- title: "Smart Auto-Detect Active",
493
- children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", children: [
494
- missingDocIdCount,
495
- " row",
496
- missingDocIdCount > 1 ? "s have" : " has",
497
- " no ",
498
- /* @__PURE__ */ jsxRuntime.jsx("code", { children: "documentId" }),
499
- ".",
500
- " ",
501
- "Because no documentId is provided, the engine will automatically treat them as new entries and generate new database IDs for them."
502
- ] })
503
- }
504
- ) }),
505
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { overflowX: "auto", maxWidth: "100%", border: "1px solid #e0e0e0", borderRadius: 4 }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: headers.length + 1, rowCount: parsedPreview.length + 1, children: [
506
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
507
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { width: 150, minWidth: 150 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Detected Action" }) }),
508
- headers.map((h) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { minWidth: 160 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: h }) }, h))
669
+ preflightReport && /* @__PURE__ */ jsxRuntime.jsx(
670
+ designSystem.Box,
671
+ {
672
+ marginBottom: 3,
673
+ padding: 4,
674
+ background: preflightReport.hasErrors ? "danger100" : preflightReport.hasWarnings ? "warning100" : "success100",
675
+ hasRadius: true,
676
+ style: { border: `1px solid ${preflightReport.hasErrors ? "#d9534f" : preflightReport.hasWarnings ? "#f0ad4e" : "#5cb85c"}` },
677
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
678
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 2, children: [
679
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: preflightReport.hasErrors ? "danger700" : preflightReport.hasWarnings ? "warning700" : "success700", children: preflightReport.hasErrors ? `⚠️ Pre-Flight Check: ${preflightReport.totalErrorCount} error(s) detected` : preflightReport.hasWarnings ? `⚡ Pre-Flight Check: ${preflightReport.validRows} valid rows with ${preflightReport.totalWarningCount} warning(s)` : `✅ Pre-Flight Check Passed: All ${preflightReport.validRows} rows are ready for import` }),
680
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
681
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", children: [
682
+ "✓ ",
683
+ preflightReport.validRows,
684
+ " Valid Rows"
685
+ ] }),
686
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
687
+ "🔄 ",
688
+ preflightReport.estimatedUpdates,
689
+ " Updates"
690
+ ] }),
691
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "warning100", textColor: "warning700", children: [
692
+ "➕ ",
693
+ preflightReport.estimatedCreates,
694
+ " New"
695
+ ] })
696
+ ] })
697
+ ] }),
698
+ preflightReport.hasErrors && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 2, background: "neutral0", padding: 3, hasRadius: true, style: { maxHeight: 160, overflowY: "auto" }, children: [
699
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "danger700", display: "block", marginBottom: 1, children: [
700
+ "Validation Errors (",
701
+ preflightReport.totalErrorCount,
702
+ "):"
703
+ ] }),
704
+ preflightReport.errors.map((e, idx) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "danger700", display: "block", children: [
705
+ "• Row ",
706
+ e.row,
707
+ ": ",
708
+ e.error
709
+ ] }, idx))
710
+ ] }),
711
+ preflightReport.hasWarnings && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 2, background: "neutral0", padding: 3, hasRadius: true, style: { maxHeight: 140, overflowY: "auto" }, children: [
712
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "warning700", display: "block", marginBottom: 1, children: [
713
+ "Warnings (",
714
+ preflightReport.totalWarningCount,
715
+ "):"
716
+ ] }),
717
+ preflightReport.warnings.map((w, idx) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "warning700", display: "block", children: [
718
+ "• Row ",
719
+ w.row,
720
+ ": ",
721
+ w.warning
722
+ ] }, idx))
723
+ ] })
724
+ ] })
725
+ }
726
+ ),
727
+ missingDocIdCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginBottom: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "default", title: "Smart Auto-Detect Active", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", children: [
728
+ missingDocIdCount.toLocaleString(),
729
+ " row",
730
+ missingDocIdCount > 1 ? "s have" : " has",
731
+ " no ",
732
+ /* @__PURE__ */ jsxRuntime.jsx("code", { children: "documentId" }),
733
+ ".",
734
+ " ",
735
+ "Because no documentId is provided, the engine will automatically treat them as new entries and generate new database IDs for them."
736
+ ] }) }) }),
737
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { overflowX: "auto", maxWidth: "100%", border: "1px solid #e0e0e0", borderRadius: 4 }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: headers.length + 1, rowCount: displayedRows.length + 1, children: [
738
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
739
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { width: 150, minWidth: 150 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Detected Action" }) }),
740
+ headers.map((h) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { minWidth: 160 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: h }) }, h))
741
+ ] }) }),
742
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: displayedRows.map((row, rIdx) => {
743
+ const hasDocId = !!extractDocId(row);
744
+ const actualRowIndex = startIndex + rIdx + 1;
745
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
746
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 1, children: [
747
+ hasDocId ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: "🔄 Update" }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "warning100", textColor: "warning700", children: "➕ New Entry" }),
748
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: [
749
+ "Row #",
750
+ actualRowIndex
751
+ ] })
752
+ ] }) }),
753
+ headers.map((h) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { style: { verticalAlign: "top", maxWidth: 300 }, children: (h === "documentId" || h === "id") && !row[h]?.trim() ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "warning700", fontWeight: "bold", children: "(Auto-generate ID)" }) : /* @__PURE__ */ jsxRuntime.jsx(
754
+ designSystem.Typography,
755
+ {
756
+ variant: "omega",
757
+ style: {
758
+ display: "-webkit-box",
759
+ WebkitLineClamp: 3,
760
+ WebkitBoxOrient: "vertical",
761
+ overflow: "hidden",
762
+ textOverflow: "ellipsis",
763
+ whiteSpace: "pre-wrap",
764
+ wordBreak: "break-word",
765
+ maxHeight: 65
766
+ },
767
+ title: row[h] || "",
768
+ children: row[h] || "-"
769
+ }
770
+ ) }, h))
771
+ ] }, rIdx);
772
+ }) })
509
773
  ] }) }),
510
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: parsedPreview.map((row, rIdx) => {
511
- const hasDocId = !!extractDocId(row);
512
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
513
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: hasDocId ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: "🔄 Match / Update" }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "warning100", textColor: "warning700", children: "➕ New Entry" }) }),
514
- headers.map((h) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { style: { verticalAlign: "top", maxWidth: 300 }, children: (h === "documentId" || h === "id") && !row[h]?.trim() ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "warning700", fontWeight: "bold", children: "(Auto-generate ID)" }) : /* @__PURE__ */ jsxRuntime.jsx(
515
- designSystem.Typography,
774
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginTop: 3, wrap: "wrap", gap: 3, children: [
775
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
776
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Rows per page:" }),
777
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 80 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
778
+ designSystem.SingleSelect,
516
779
  {
517
- variant: "omega",
518
- style: {
519
- display: "-webkit-box",
520
- WebkitLineClamp: 3,
521
- WebkitBoxOrient: "vertical",
522
- overflow: "hidden",
523
- textOverflow: "ellipsis",
524
- whiteSpace: "pre-wrap",
525
- wordBreak: "break-word",
526
- maxHeight: 65
780
+ value: String(previewPageSize),
781
+ onChange: (val) => {
782
+ setPreviewPageSize(Number(val));
783
+ setPreviewPage(1);
527
784
  },
528
- title: row[h] || "",
529
- children: row[h] || "-"
785
+ children: [
786
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "10", children: "10" }),
787
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "25", children: "25" }),
788
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "50", children: "50" }),
789
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "100", children: "100" })
790
+ ]
530
791
  }
531
- ) }, h))
532
- ] }, rIdx);
533
- }) })
534
- ] }) }),
535
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
536
- designSystem.Button,
792
+ ) }),
793
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
794
+ "Showing ",
795
+ startIndex + 1,
796
+ "–",
797
+ endIndex,
798
+ " of ",
799
+ totalRows.toLocaleString(),
800
+ " rows"
801
+ ] })
802
+ ] }),
803
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
804
+ /* @__PURE__ */ jsxRuntime.jsx(
805
+ designSystem.Button,
806
+ {
807
+ variant: "tertiary",
808
+ size: "S",
809
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronLeft, {}),
810
+ disabled: safePage <= 1 || importing,
811
+ onClick: () => setPreviewPage((p) => Math.max(1, p - 1)),
812
+ children: "Prev"
813
+ }
814
+ ),
815
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral700", children: [
816
+ "Page ",
817
+ safePage,
818
+ " of ",
819
+ totalPages
820
+ ] }),
821
+ /* @__PURE__ */ jsxRuntime.jsx(
822
+ designSystem.Button,
823
+ {
824
+ variant: "tertiary",
825
+ size: "S",
826
+ endIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronRight, {}),
827
+ disabled: safePage >= totalPages || importing,
828
+ onClick: () => setPreviewPage((p) => Math.min(totalPages, p + 1)),
829
+ children: "Next"
830
+ }
831
+ )
832
+ ] })
833
+ ] }),
834
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginTop: 4, wrap: "wrap", gap: 3, children: [
835
+ /* @__PURE__ */ jsxRuntime.jsx(
836
+ designSystem.Button,
837
+ {
838
+ variant: "secondary",
839
+ size: "L",
840
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Eye, {}),
841
+ onClick: handleRunPreflight,
842
+ loading: preflightLoading,
843
+ disabled: importing,
844
+ children: "Run Pre-Flight Dry Run"
845
+ }
846
+ ),
847
+ /* @__PURE__ */ jsxRuntime.jsxs(
848
+ designSystem.Button,
849
+ {
850
+ variant: "default",
851
+ size: "L",
852
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
853
+ onClick: () => setShowConfirmModal(true),
854
+ loading: importing || submittingBatch,
855
+ children: [
856
+ "Review & Import (",
857
+ totalRows.toLocaleString(),
858
+ " Records)..."
859
+ ]
860
+ }
861
+ )
862
+ ] })
863
+ ] });
864
+ })(),
865
+ importProgress && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 4, padding: 4, background: "neutral0", hasRadius: true, style: { border: "1px solid #4945ff" }, children: [
866
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 2, children: [
867
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", textColor: "primary700", children: importing ? `Processing Batch Chunk ${importProgress.currentChunk} of ${importProgress.totalChunks} (${importProgress.percent}%)` : "Batch Import Complete" }),
868
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral700", children: [
869
+ importProgress.processedRows.toLocaleString(),
870
+ " / ",
871
+ importProgress.totalRows.toLocaleString(),
872
+ " rows processed"
873
+ ] })
874
+ ] }),
875
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: "100%", height: 10, background: "#e0e0e0", borderRadius: 5, overflow: "hidden", marginBottom: 12 }, children: /* @__PURE__ */ jsxRuntime.jsx(
876
+ designSystem.Box,
537
877
  {
538
- variant: "default",
539
- size: "L",
540
- startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
541
- onClick: handleExecuteImport,
542
- loading: importing,
543
- children: "Execute Smart Import (Auto-Detect)"
878
+ style: {
879
+ width: `${importProgress.percent}%`,
880
+ height: "100%",
881
+ background: importProgress.percent === 100 ? "#2f6846" : "#4945ff",
882
+ transition: "width 0.2s ease-in-out"
883
+ }
544
884
  }
545
- ) })
546
- ] });
547
- })(),
548
- importResult && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
549
- designSystem.Alert,
550
- {
551
- variant: importResult.stats.errors.length > 0 ? "warning" : "success",
552
- title: "CSV Import Results",
553
- children: [
554
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", display: "block", marginBottom: 1, children: [
555
- "Successfully processed: ",
556
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
557
- importResult.stats.created,
558
- " created"
559
- ] }),
560
- importResult.stats.newWithoutDocId > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
561
- " (",
562
- importResult.stats.newWithoutDocId,
563
- " created as new entries because documentId was omitted)"
564
- ] }),
565
- ", ",
566
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
567
- importResult.stats.updated,
568
- " updated"
569
- ] }),
570
- ",",
571
- " ",
572
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
573
- importResult.stats.skipped,
574
- " skipped"
575
- ] }),
576
- " out of ",
577
- importResult.stats.total,
578
- " total rows."
885
+ ) }),
886
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, wrap: "wrap", alignItems: "center", children: [
887
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", children: [
888
+ "Created: ",
889
+ importProgress.liveCreated.toLocaleString()
579
890
  ] }),
580
- importResult.stats.newWithoutDocId > 0 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, padding: 2, background: "neutral100", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral700", children: [
581
- "ℹ️ ",
582
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Note on new entries:" }),
583
- " ",
584
- importResult.stats.newWithoutDocId,
585
- " row",
586
- importResult.stats.newWithoutDocId > 1 ? "s" : "",
587
- " had no ",
588
- /* @__PURE__ */ jsxRuntime.jsx("code", { children: "documentId" }),
589
- " specified in the CSV. The engine generated brand-new database entries with assigned document IDs. If you export this collection now, you will see their generated document IDs."
590
- ] }) }),
591
- importResult.stats.errors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 2, children: [
592
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "danger700", fontWeight: "bold", children: [
593
- "Errors encountered (",
594
- importResult.stats.errors.length,
595
- "):"
596
- ] }),
597
- /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: "4px 0 0 16px", padding: 0 }, children: importResult.stats.errors.slice(0, 10).map((err, idx) => /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginBottom: "2px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "danger600", children: [
598
- "Row ",
599
- err.row,
600
- ": ",
601
- err.error
602
- ] }) }, idx)) }),
603
- importResult.stats.errors.length > 10 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { display: "block", marginTop: 4, fontStyle: "italic" }, children: [
604
- "...and ",
605
- importResult.stats.errors.length - 10,
606
- " more error",
607
- importResult.stats.errors.length - 10 > 1 ? "s" : ""
608
- ] })
891
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
892
+ "Updated: ",
893
+ importProgress.liveUpdated.toLocaleString()
894
+ ] }),
895
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "neutral150", textColor: "neutral700", children: [
896
+ "Skipped: ",
897
+ importProgress.liveSkipped.toLocaleString()
609
898
  ] }),
610
- importResult.stats.diffs && importResult.stats.diffs.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 3, padding: 3, background: "neutral0", hasRadius: true, style: { border: "1px solid #dcdce4" }, children: [
611
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "neutral800", fontWeight: "bold", display: "block", marginBottom: 2, children: [
612
- "CHANGES APPLIED (",
613
- importResult.stats.diffs.length,
614
- "):"
899
+ importProgress.liveErrors > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "danger100", textColor: "danger700", children: [
900
+ "Errors: ",
901
+ importProgress.liveErrors.toLocaleString()
902
+ ] })
903
+ ] })
904
+ ] }),
905
+ importResult && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
906
+ designSystem.Alert,
907
+ {
908
+ variant: importResult.stats.errors.length > 0 ? "warning" : "success",
909
+ title: "CSV Import Results",
910
+ children: [
911
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", display: "block", marginBottom: 1, children: [
912
+ "Successfully processed: ",
913
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
914
+ importResult.stats.created.toLocaleString(),
915
+ " created"
916
+ ] }),
917
+ importResult.stats.newWithoutDocId > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
918
+ " (",
919
+ importResult.stats.newWithoutDocId.toLocaleString(),
920
+ " created as new entries because documentId was omitted)"
921
+ ] }),
922
+ ", ",
923
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
924
+ importResult.stats.updated.toLocaleString(),
925
+ " updated"
926
+ ] }),
927
+ ",",
928
+ " ",
929
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
930
+ importResult.stats.skipped.toLocaleString(),
931
+ " skipped"
932
+ ] }),
933
+ " out of ",
934
+ importResult.stats.total.toLocaleString(),
935
+ " total rows."
615
936
  ] }),
616
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: 4, rowCount: importResult.stats.diffs.length + 1, children: [
617
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
618
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Entry / Document" }) }),
619
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Attribute" }) }),
620
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Previous Value" }) }),
621
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Applied Value" }) })
622
- ] }) }),
623
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: importResult.stats.diffs.slice(0, 10).map((d, idx) => {
624
- const oldDisplay = d.oldValue !== null && d.oldValue !== void 0 ? typeof d.oldValue === "object" ? JSON.stringify(d.oldValue) : String(d.oldValue) : "(empty)";
625
- const newDisplay = d.newValue !== null && d.newValue !== void 0 ? typeof d.newValue === "object" ? JSON.stringify(d.newValue) : String(d.newValue) : "(empty)";
626
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
627
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Td, { children: [
628
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", children: d.label || d.documentId }),
629
- d.documentId && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", display: "block", children: d.documentId })
630
- ] }),
631
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: d.attribute || "field" }) }),
632
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", children: oldDisplay }) }),
633
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "semiBold", children: newDisplay }) })
634
- ] }, idx);
635
- }) })
937
+ importResult.stats.newWithoutDocId > 0 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, padding: 2, background: "neutral100", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral700", children: [
938
+ "ℹ️ ",
939
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Note on new entries:" }),
940
+ " ",
941
+ importResult.stats.newWithoutDocId,
942
+ " row",
943
+ importResult.stats.newWithoutDocId > 1 ? "s" : "",
944
+ " had no ",
945
+ /* @__PURE__ */ jsxRuntime.jsx("code", { children: "documentId" }),
946
+ " specified in the CSV. The engine generated brand-new database entries with assigned document IDs. If you export this collection now, you will see their generated document IDs."
636
947
  ] }) }),
637
- importResult.stats.diffs.length > 10 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { display: "block", marginTop: 6, fontStyle: "italic" }, children: [
638
- "...and ",
639
- importResult.stats.diffs.length - 10,
640
- " more change",
641
- importResult.stats.diffs.length - 10 > 1 ? "s" : "",
642
- " recorded in Audit Trail & Version History."
948
+ importResult.stats.errors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 2, children: [
949
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "danger700", fontWeight: "bold", children: [
950
+ "Errors encountered (",
951
+ importResult.stats.errors.length,
952
+ "):"
953
+ ] }),
954
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: "4px 0 0 16px", padding: 0 }, children: importResult.stats.errors.slice(0, 10).map((err, idx) => /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginBottom: "2px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "danger600", children: [
955
+ "Row ",
956
+ err.row,
957
+ ": ",
958
+ err.error
959
+ ] }) }, idx)) }),
960
+ importResult.stats.errors.length > 10 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { display: "block", marginTop: 4, fontStyle: "italic" }, children: [
961
+ "...and ",
962
+ importResult.stats.errors.length - 10,
963
+ " more error",
964
+ importResult.stats.errors.length - 10 > 1 ? "s" : ""
965
+ ] })
966
+ ] }),
967
+ importResult.stats.diffs && importResult.stats.diffs.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 3, padding: 3, background: "neutral0", hasRadius: true, style: { border: "1px solid #dcdce4" }, children: [
968
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "neutral800", fontWeight: "bold", display: "block", marginBottom: 2, children: [
969
+ "CHANGES APPLIED (",
970
+ importResult.stats.diffs.length.toLocaleString(),
971
+ "):"
972
+ ] }),
973
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: 4, rowCount: importResult.stats.diffs.length + 1, children: [
974
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
975
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Entry / Document" }) }),
976
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Attribute" }) }),
977
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Previous Value" }) }),
978
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Applied Value" }) })
979
+ ] }) }),
980
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: importResult.stats.diffs.slice(0, 10).map((d, idx) => {
981
+ const oldDisplay = d.oldValue !== null && d.oldValue !== void 0 ? typeof d.oldValue === "object" ? JSON.stringify(d.oldValue) : String(d.oldValue) : "(empty)";
982
+ const newDisplay = d.newValue !== null && d.newValue !== void 0 ? typeof d.newValue === "object" ? JSON.stringify(d.newValue) : String(d.newValue) : "(empty)";
983
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
984
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Td, { children: [
985
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", children: d.label || d.documentId }),
986
+ d.documentId && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", display: "block", children: d.documentId })
987
+ ] }),
988
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: d.attribute || "field" }) }),
989
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", children: oldDisplay }) }),
990
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "semiBold", children: newDisplay }) })
991
+ ] }, idx);
992
+ }) })
993
+ ] }) }),
994
+ importResult.stats.diffs.length > 10 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { display: "block", marginTop: 6, fontStyle: "italic" }, children: [
995
+ "...and ",
996
+ importResult.stats.diffs.length - 10,
997
+ " more change",
998
+ importResult.stats.diffs.length - 10 > 1 ? "s" : "",
999
+ " recorded in Audit Trail & Version History."
1000
+ ] })
643
1001
  ] })
644
- ] })
645
- ]
646
- }
647
- ) })
648
- ] })
649
- ] }) });
1002
+ ]
1003
+ }
1004
+ ) })
1005
+ ] })
1006
+ ] }),
1007
+ showConfirmModal && /* @__PURE__ */ jsxRuntime.jsx(
1008
+ "div",
1009
+ {
1010
+ style: {
1011
+ position: "fixed",
1012
+ inset: 0,
1013
+ backgroundColor: "rgba(20, 20, 30, 0.65)",
1014
+ backdropFilter: "blur(2px)",
1015
+ display: "flex",
1016
+ alignItems: "center",
1017
+ justifyContent: "center",
1018
+ zIndex: 9999,
1019
+ padding: 16,
1020
+ boxSizing: "border-box",
1021
+ overflowY: "auto"
1022
+ },
1023
+ onClick: () => setShowConfirmModal(false),
1024
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1025
+ designSystem.Box,
1026
+ {
1027
+ background: "neutral0",
1028
+ hasRadius: true,
1029
+ shadow: "popupShadow",
1030
+ style: {
1031
+ maxWidth: 680,
1032
+ width: "100%",
1033
+ maxHeight: "calc(100vh - 48px)",
1034
+ display: "flex",
1035
+ flexDirection: "column",
1036
+ overflow: "hidden",
1037
+ position: "relative",
1038
+ boxShadow: "0 24px 48px rgba(0, 0, 0, 0.32), 0 0 1px rgba(0, 0, 0, 0.2)"
1039
+ },
1040
+ onClick: (e) => e.stopPropagation(),
1041
+ children: [
1042
+ /* @__PURE__ */ jsxRuntime.jsx(
1043
+ designSystem.Box,
1044
+ {
1045
+ padding: 5,
1046
+ background: "neutral100",
1047
+ style: {
1048
+ borderBottom: "1px solid rgba(120, 120, 150, 0.2)",
1049
+ flexShrink: 0
1050
+ },
1051
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
1052
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", children: "Confirm CSV Bulk Import" }),
1053
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", display: "block", children: "Review import target, record actions, publishing mode, and execution window policies before proceeding." })
1054
+ ] }) })
1055
+ }
1056
+ ),
1057
+ /* @__PURE__ */ jsxRuntime.jsxs(
1058
+ designSystem.Box,
1059
+ {
1060
+ padding: 5,
1061
+ style: {
1062
+ flex: "1 1 auto",
1063
+ minHeight: 0,
1064
+ overflowY: "auto",
1065
+ WebkitOverflowScrolling: "touch"
1066
+ },
1067
+ children: [
1068
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral100", hasRadius: true, marginBottom: 4, children: [
1069
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", marginBottom: 2, display: "block", children: "IMPORT DETAILS" }),
1070
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
1071
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
1072
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", children: "Target Collection:" }),
1073
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: selectedCol?.displayName || selectedUid })
1074
+ ] }),
1075
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
1076
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", children: "Total Detected Records:" }),
1077
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "bold", textColor: "primary600", children: [
1078
+ allParsedRecords.length.toLocaleString(),
1079
+ " records"
1080
+ ] })
1081
+ ] }),
1082
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
1083
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", children: "Action Breakdown:" }),
1084
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
1085
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
1086
+ "🔄 ",
1087
+ allParsedRecords.filter((r) => !!extractDocId(r)).length.toLocaleString(),
1088
+ " Updates"
1089
+ ] }),
1090
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "warning100", textColor: "warning700", children: [
1091
+ "➕ ",
1092
+ allParsedRecords.filter((r) => !extractDocId(r)).length.toLocaleString(),
1093
+ " New (No ID)"
1094
+ ] })
1095
+ ] })
1096
+ ] }),
1097
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
1098
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", children: "Import Mode:" }),
1099
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "neutral200", textColor: "neutral800", children: importMode === "update" ? "Update Only (Exact Document IDs)" : importMode === "create_or_override" ? "Create or Override" : "Smart Auto-Detect" })
1100
+ ] }),
1101
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
1102
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", children: "Publishing Mode:" }),
1103
+ /* @__PURE__ */ jsxRuntime.jsx(
1104
+ designSystem.Badge,
1105
+ {
1106
+ backgroundColor: publishOnImport ? "success100" : "warning100",
1107
+ textColor: publishOnImport ? "success700" : "warning700",
1108
+ children: publishOnImport ? "Publish Immediately" : "Keep as Draft"
1109
+ }
1110
+ )
1111
+ ] }),
1112
+ preflightReport && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginTop: 2, paddingTop: 2, style: { borderTop: "1px solid #eaeaef" }, children: [
1113
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Pre-Flight Status:" }),
1114
+ /* @__PURE__ */ jsxRuntime.jsx(
1115
+ designSystem.Typography,
1116
+ {
1117
+ variant: "pi",
1118
+ fontWeight: "bold",
1119
+ textColor: preflightReport.hasErrors ? "danger700" : preflightReport.hasWarnings ? "warning700" : "success700",
1120
+ children: preflightReport.hasErrors ? `⚠️ ${preflightReport.totalErrorCount} errors found` : preflightReport.hasWarnings ? `⚡ Passed with ${preflightReport.totalWarningCount} warnings` : "✅ 100% Passed"
1121
+ }
1122
+ )
1123
+ ] })
1124
+ ] })
1125
+ ] }),
1126
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, hasRadius: true, marginBottom: 4, background: executionWindow?.isBusinessHours ? "warning100" : "success100", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 1, children: [
1127
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, alignItems: "center", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: executionWindow?.isBusinessHours ? "warning700" : "success700", children: executionWindow?.isBusinessHours ? "⏰ Peak Business Hours Restriction Active" : "✅ Server Off-Peak Window Active" }) }),
1128
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: executionWindow?.isBusinessHours ? "warning700" : "success700", children: executionWindow?.policyMessage || (executionWindow?.isBusinessHours ? "Server policy restricts bulk operations during peak business hours (09:00 - 18:00). Direct execution is paused to preserve API throughput." : "Currently outside peak business hours. Direct execution is permitted.") })
1129
+ ] }) }),
1130
+ /* @__PURE__ */ jsxRuntime.jsx(
1131
+ designSystem.Box,
1132
+ {
1133
+ padding: 4,
1134
+ background: "neutral100",
1135
+ hasRadius: true,
1136
+ marginBottom: 4,
1137
+ style: { border: "1px solid rgba(120, 120, 150, 0.15)" },
1138
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "flex-start", children: [
1139
+ /* @__PURE__ */ jsxRuntime.jsx(
1140
+ designSystem.Checkbox,
1141
+ {
1142
+ checked: publishOnImport,
1143
+ onValueChange: (val) => setPublishOnImport(Boolean(val))
1144
+ }
1145
+ ),
1146
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { cursor: "pointer" }, onClick: () => setPublishOnImport(!publishOnImport), children: [
1147
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", display: "block", children: "Publish immediately upon checker approval / execution" }),
1148
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "When checked (default), content types with Draft & Publish enabled will have their updated documents published immediately upon execution. When unchecked, changes remain in Draft for further editorial review." })
1149
+ ] })
1150
+ ] })
1151
+ }
1152
+ ),
1153
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
1154
+ designSystem.TextInput,
1155
+ {
1156
+ label: "Change Request / Release Notes (Optional)",
1157
+ name: "makerNotes",
1158
+ placeholder: "e.g. REL-5040: Bulk updating catalog attributes via CSV",
1159
+ value: makerNotesInput,
1160
+ onChange: (e) => setMakerNotesInput(e.target.value)
1161
+ }
1162
+ ) })
1163
+ ]
1164
+ }
1165
+ ),
1166
+ /* @__PURE__ */ jsxRuntime.jsx(
1167
+ designSystem.Box,
1168
+ {
1169
+ padding: 4,
1170
+ background: "neutral100",
1171
+ style: {
1172
+ borderTop: "1px solid rgba(120, 120, 150, 0.2)",
1173
+ flexShrink: 0,
1174
+ position: "sticky",
1175
+ bottom: 0,
1176
+ zIndex: 20,
1177
+ boxShadow: "0 -4px 16px rgba(0, 0, 0, 0.08)"
1178
+ },
1179
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", gap: 3, style: { width: "100%" }, children: [
1180
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", size: "M", onClick: () => setShowConfirmModal(false), children: "Cancel" }),
1181
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, wrap: "wrap", justifyContent: "flex-end", alignItems: "center", children: [
1182
+ /* @__PURE__ */ jsxRuntime.jsx(
1183
+ designSystem.Button,
1184
+ {
1185
+ variant: executionWindow?.isBusinessHours ? "default" : "secondary",
1186
+ size: "M",
1187
+ onClick: () => submitBatchWithMode("maker_checker"),
1188
+ loading: submittingBatch,
1189
+ children: "Submit for Checker Approval"
1190
+ }
1191
+ ),
1192
+ executionWindow?.isBusinessHours ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1193
+ /* @__PURE__ */ jsxRuntime.jsxs(
1194
+ designSystem.Button,
1195
+ {
1196
+ variant: "secondary",
1197
+ size: "M",
1198
+ onClick: () => submitBatchWithMode("queue_offpeak"),
1199
+ loading: submittingBatch,
1200
+ children: [
1201
+ "Queue for Off-Peak (",
1202
+ executionWindow?.offPeakStartTime || "18:00",
1203
+ ")"
1204
+ ]
1205
+ }
1206
+ ),
1207
+ /* @__PURE__ */ jsxRuntime.jsx(
1208
+ designSystem.Button,
1209
+ {
1210
+ variant: "danger-light",
1211
+ size: "S",
1212
+ onClick: () => submitBatchWithMode("immediate", true),
1213
+ loading: importing,
1214
+ children: "Force Run Now"
1215
+ }
1216
+ )
1217
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
1218
+ designSystem.Button,
1219
+ {
1220
+ variant: "default",
1221
+ size: "M",
1222
+ onClick: () => submitBatchWithMode("immediate"),
1223
+ loading: importing,
1224
+ children: "Confirm & Execute Now"
1225
+ }
1226
+ )
1227
+ ] })
1228
+ ] })
1229
+ }
1230
+ )
1231
+ ]
1232
+ }
1233
+ )
1234
+ }
1235
+ )
1236
+ ] });
650
1237
  }
651
1238
  function formatVal(v) {
652
1239
  if (v === null || v === void 0) return "(empty)";
@@ -1603,9 +2190,75 @@ const BulkUpdatePreviewModal = ({
1603
2190
  }
1604
2191
  );
1605
2192
  };
2193
+ function parseDynamicZonePath(path) {
2194
+ if (!path) return { cleanPath: "", rootKey: "", subPath: "" };
2195
+ const bracketMatch = path.match(/^([^.[]+)\[([^\]]+)\]\.(.+)$/);
2196
+ if (bracketMatch) {
2197
+ const rootKey = bracketMatch[1];
2198
+ const selector = bracketMatch[2];
2199
+ const subPath = bracketMatch[3];
2200
+ const cleanPath = `${rootKey}.${subPath}`;
2201
+ if (/^\d+$/.test(selector)) {
2202
+ return { cleanPath, rootKey, subPath, targetIndex: parseInt(selector, 10) };
2203
+ }
2204
+ return { cleanPath, rootKey, subPath, targetComponentUid: selector };
2205
+ }
2206
+ const parts = path.split(".");
2207
+ return {
2208
+ cleanPath: path,
2209
+ rootKey: parts[0] || "",
2210
+ subPath: parts.slice(1).join(".")
2211
+ };
2212
+ }
2213
+ function formatComponentName(compUid) {
2214
+ if (!compUid) return "Component";
2215
+ const name = compUid.includes(".") ? compUid.split(".")[1] : compUid;
2216
+ return name.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
2217
+ }
2218
+ function getAllNestedValues(obj, path, availableAttributes) {
2219
+ if (!obj || !path) return [];
2220
+ const parsed = parseDynamicZonePath(path);
2221
+ const parts = parsed.cleanPath.split(".");
2222
+ const [head, ...tail] = parts;
2223
+ const rootTarget = obj[head];
2224
+ if (Array.isArray(rootTarget)) {
2225
+ const results = [];
2226
+ rootTarget.forEach((item, idx) => {
2227
+ if (!item || typeof item !== "object") return;
2228
+ if (parsed.targetIndex !== void 0 && idx !== parsed.targetIndex) return;
2229
+ if (parsed.targetComponentUid && item.__component !== parsed.targetComponentUid) return;
2230
+ const subPath = tail.join(".");
2231
+ const scopedPath = item.__component ? `${head}[${item.__component}].${subPath}` : "";
2232
+ const isSupported = availableAttributes ? availableAttributes.includes(scopedPath) : false;
2233
+ const subVal = tail.length > 0 ? getNestedValue(item, subPath) : item;
2234
+ if (subVal !== void 0 || isSupported) {
2235
+ results.push({
2236
+ index: idx,
2237
+ componentUid: item.__component,
2238
+ componentName: formatComponentName(item.__component),
2239
+ value: subVal !== void 0 ? subVal : null,
2240
+ path: `${head}[#${idx}${item.__component ? ` ${formatComponentName(item.__component)}` : ""}].${subPath}`
2241
+ });
2242
+ }
2243
+ });
2244
+ return results;
2245
+ }
2246
+ const singleVal = getNestedValue(obj, parsed.cleanPath);
2247
+ if (singleVal !== void 0) {
2248
+ return [
2249
+ {
2250
+ index: 0,
2251
+ value: singleVal,
2252
+ path: parsed.cleanPath
2253
+ }
2254
+ ];
2255
+ }
2256
+ return [];
2257
+ }
1606
2258
  function getNestedValue(obj, path) {
1607
2259
  if (!obj || !path) return void 0;
1608
- const parts = path.split(".");
2260
+ const parsed = parseDynamicZonePath(path);
2261
+ const parts = parsed.cleanPath.split(".");
1609
2262
  function extract(current, remainingParts) {
1610
2263
  if (current === void 0 || current === null) return void 0;
1611
2264
  if (remainingParts.length === 0) return current;
@@ -1614,7 +2267,10 @@ function getNestedValue(obj, path) {
1614
2267
  if (/^\d+$/.test(head)) {
1615
2268
  return extract(current[parseInt(head, 10)], tail);
1616
2269
  }
1617
- for (const item of current) {
2270
+ for (let idx = 0; idx < current.length; idx++) {
2271
+ const item = current[idx];
2272
+ if (parsed.targetIndex !== void 0 && idx !== parsed.targetIndex) continue;
2273
+ if (parsed.targetComponentUid && item?.__component !== parsed.targetComponentUid) continue;
1618
2274
  const found = extract(item?.[head], tail);
1619
2275
  if (found !== void 0 && found !== null) return found;
1620
2276
  }
@@ -1644,7 +2300,18 @@ function getAvailableColumnsForCollection(col, selectedAttribute, searchAttribut
1644
2300
  if (attr === "name" || attr === "title" || attr === selectedAttribute || searchAttribute && attr === searchAttribute) {
1645
2301
  return;
1646
2302
  }
1647
- const formattedLabel = attr.includes(".") ? attr.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ") : attr.charAt(0).toUpperCase() + attr.slice(1);
2303
+ let formattedLabel = attr;
2304
+ const bracketMatch = attr.match(/^([^.[]+)\[([^\]]+)\]\.(.+)$/);
2305
+ if (bracketMatch) {
2306
+ const root = bracketMatch[1].charAt(0).toUpperCase() + bracketMatch[1].slice(1);
2307
+ const comp = formatComponentName(bracketMatch[2]);
2308
+ const sub = bracketMatch[3].split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ");
2309
+ formattedLabel = `${root} [${comp}] > ${sub}`;
2310
+ } else if (attr.includes(".")) {
2311
+ formattedLabel = attr.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ");
2312
+ } else {
2313
+ formattedLabel = attr.charAt(0).toUpperCase() + attr.slice(1);
2314
+ }
1648
2315
  cols.push({
1649
2316
  key: `attr_${attr}`,
1650
2317
  label: formattedLabel,
@@ -1653,7 +2320,16 @@ function getAvailableColumnsForCollection(col, selectedAttribute, searchAttribut
1653
2320
  });
1654
2321
  });
1655
2322
  if (searchAttribute && searchAttribute !== selectedAttribute) {
1656
- const formattedSearchLabel = searchAttribute.includes(".") ? searchAttribute.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ") : searchAttribute;
2323
+ let formattedSearchLabel = searchAttribute;
2324
+ const bracketMatch = searchAttribute.match(/^([^.[]+)\[([^\]]+)\]\.(.+)$/);
2325
+ if (bracketMatch) {
2326
+ const root = bracketMatch[1].charAt(0).toUpperCase() + bracketMatch[1].slice(1);
2327
+ const comp = formatComponentName(bracketMatch[2]);
2328
+ const sub = bracketMatch[3].split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ");
2329
+ formattedSearchLabel = `${root} [${comp}] > ${sub}`;
2330
+ } else if (searchAttribute.includes(".")) {
2331
+ formattedSearchLabel = searchAttribute.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ");
2332
+ }
1657
2333
  cols.push({
1658
2334
  key: "search_attr",
1659
2335
  label: `Search: "${formattedSearchLabel}"`,
@@ -1662,7 +2338,17 @@ function getAvailableColumnsForCollection(col, selectedAttribute, searchAttribut
1662
2338
  });
1663
2339
  }
1664
2340
  if (selectedAttribute && selectedAttribute.trim()) {
1665
- const targetLabel = searchAttribute && searchAttribute !== selectedAttribute ? `Update Target: "${selectedAttribute}"` : `Current "${selectedAttribute}"`;
2341
+ let formattedTargetLabel = selectedAttribute;
2342
+ const bracketMatch = selectedAttribute.match(/^([^.[]+)\[([^\]]+)\]\.(.+)$/);
2343
+ if (bracketMatch) {
2344
+ const root = bracketMatch[1].charAt(0).toUpperCase() + bracketMatch[1].slice(1);
2345
+ const comp = formatComponentName(bracketMatch[2]);
2346
+ const sub = bracketMatch[3].split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ");
2347
+ formattedTargetLabel = `${root} [${comp}] > ${sub}`;
2348
+ } else if (selectedAttribute.includes(".")) {
2349
+ formattedTargetLabel = selectedAttribute.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ");
2350
+ }
2351
+ const targetLabel = searchAttribute && searchAttribute !== selectedAttribute ? `Update Target: "${formattedTargetLabel}"` : `Current "${formattedTargetLabel}"`;
1666
2352
  cols.push({
1667
2353
  key: "target_attr",
1668
2354
  label: targetLabel,
@@ -1787,7 +2473,7 @@ function getEntryLifecycleStatus(entry, col, pendingBatches = []) {
1787
2473
  textColor: "neutral700"
1788
2474
  };
1789
2475
  }
1790
- function renderCellContent(colDef, entry, col, selectedAttribute, searchAttribute, isMatch, hasAttr, isSelected, onToggleSelect, pendingBatches = []) {
2476
+ function renderCellContent(colDef, entry, col, selectedAttribute, searchAttribute, isMatch, hasAttr, isSelected, onToggleSelect, pendingBatches = [], isDzExpanded = false, onToggleExpandDz, filterQuery = "") {
1791
2477
  switch (colDef.key) {
1792
2478
  case "select":
1793
2479
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -1799,51 +2485,162 @@ function renderCellContent(colDef, entry, col, selectedAttribute, searchAttribut
1799
2485
  );
1800
2486
  case "identifier": {
1801
2487
  const mainText = entry.name || entry.title || `Entry #${entry.id || entry.documentId}`;
2488
+ const dzField = Object.keys(entry).find(
2489
+ (k) => Array.isArray(entry[k]) && entry[k].length > 0 && entry[k].some((item) => item && item.__component)
2490
+ );
2491
+ const dzItemsCount = dzField ? entry[dzField].length : 0;
1802
2492
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
1803
2493
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", children: mainText }),
1804
- entry.email && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", display: "block", children: entry.email })
2494
+ entry.email && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", display: "block", children: entry.email }),
2495
+ dzItemsCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(
2496
+ designSystem.Button,
2497
+ {
2498
+ variant: "ghost",
2499
+ size: "S",
2500
+ onClick: onToggleExpandDz,
2501
+ style: {
2502
+ padding: "2px 6px",
2503
+ height: "auto",
2504
+ fontSize: "0.72rem",
2505
+ color: isDzExpanded ? "#4945ff" : "#666687",
2506
+ backgroundColor: isDzExpanded ? "rgba(73, 69, 255, 0.08)" : "rgba(0, 0, 0, 0.04)",
2507
+ borderRadius: 4
2508
+ },
2509
+ children: isDzExpanded ? `▲ Hide ${dzField} (${dzItemsCount} blocks)` : `▼ View ${dzField} (${dzItemsCount} blocks)`
2510
+ }
2511
+ ) })
1805
2512
  ] });
1806
2513
  }
1807
2514
  case "search_attr": {
1808
- const val = getNestedValue(entry, searchAttribute);
1809
- const displayStr = formatDisplayValue(val);
1810
- const isUnset = displayStr === "(empty / not set)" || displayStr === "(empty / unlinked)";
1811
- return /* @__PURE__ */ jsxRuntime.jsx(
1812
- designSystem.Typography,
1813
- {
1814
- textColor: isUnset ? "neutral500" : "primary700",
1815
- fontWeight: "semiBold",
1816
- style: {
1817
- fontStyle: isUnset ? "italic" : "normal",
1818
- display: "inline-block",
1819
- maxWidth: 260,
1820
- overflow: "hidden",
1821
- textOverflow: "ellipsis",
1822
- whiteSpace: "nowrap"
2515
+ const matches = getAllNestedValues(entry, searchAttribute, col?.attributes);
2516
+ if (matches.length === 0) {
2517
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral500", style: { fontStyle: "italic" }, children: "(empty / not set)" });
2518
+ }
2519
+ if (matches.length === 1 && !matches[0].componentUid) {
2520
+ const displayStr = formatDisplayValue(matches[0].value);
2521
+ const isUnset = displayStr === "(empty / not set)" || displayStr === "(empty / unlinked)";
2522
+ return /* @__PURE__ */ jsxRuntime.jsx(
2523
+ designSystem.Typography,
2524
+ {
2525
+ textColor: isUnset ? "neutral500" : "primary700",
2526
+ fontWeight: "semiBold",
2527
+ style: {
2528
+ fontStyle: isUnset ? "italic" : "normal",
2529
+ display: "inline-block",
2530
+ maxWidth: 260,
2531
+ overflow: "hidden",
2532
+ textOverflow: "ellipsis",
2533
+ whiteSpace: "nowrap"
2534
+ },
2535
+ children: displayStr
2536
+ }
2537
+ );
2538
+ }
2539
+ const qLower = (filterQuery || "").trim().toLowerCase();
2540
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", gap: 1, alignItems: "flex-start", style: { maxWidth: 320 }, children: matches.map((m) => {
2541
+ const displayStr = formatDisplayValue(m.value);
2542
+ const isMatchItem = qLower && displayStr.toLowerCase().includes(qLower);
2543
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2544
+ designSystem.Flex,
2545
+ {
2546
+ gap: 1,
2547
+ alignItems: "center",
2548
+ style: {
2549
+ backgroundColor: isMatchItem ? "rgba(46, 213, 115, 0.15)" : "rgba(0, 0, 0, 0.03)",
2550
+ padding: "2px 6px",
2551
+ borderRadius: 4,
2552
+ border: isMatchItem ? "1px solid #2ed573" : "1px solid transparent"
2553
+ },
2554
+ children: [
2555
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { size: "S", backgroundColor: isMatchItem ? "success100" : "primary100", textColor: isMatchItem ? "success700" : "primary700", children: [
2556
+ "#",
2557
+ m.index,
2558
+ " ",
2559
+ m.componentName
2560
+ ] }),
2561
+ /* @__PURE__ */ jsxRuntime.jsx(
2562
+ designSystem.Typography,
2563
+ {
2564
+ variant: "pi",
2565
+ fontWeight: isMatchItem ? "bold" : "normal",
2566
+ textColor: isMatchItem ? "success700" : "neutral800",
2567
+ style: {
2568
+ maxWidth: 200,
2569
+ overflow: "hidden",
2570
+ textOverflow: "ellipsis",
2571
+ whiteSpace: "nowrap"
2572
+ },
2573
+ children: displayStr
2574
+ }
2575
+ )
2576
+ ]
1823
2577
  },
1824
- children: displayStr
1825
- }
1826
- );
2578
+ m.index
2579
+ );
2580
+ }) });
1827
2581
  }
1828
2582
  case "target_attr": {
1829
- const val = getNestedValue(entry, selectedAttribute);
1830
- const displayStr = formatDisplayValue(val);
1831
- const isUnset = displayStr === "(empty / not set)" || displayStr === "(empty / unlinked)";
1832
- return /* @__PURE__ */ jsxRuntime.jsx(
1833
- designSystem.Typography,
1834
- {
1835
- textColor: isUnset ? "neutral500" : "neutral800",
1836
- style: {
1837
- fontStyle: isUnset ? "italic" : "normal",
1838
- display: "inline-block",
1839
- maxWidth: 260,
1840
- overflow: "hidden",
1841
- textOverflow: "ellipsis",
1842
- whiteSpace: "nowrap"
2583
+ const matches = getAllNestedValues(entry, selectedAttribute, col?.attributes);
2584
+ if (matches.length === 0) {
2585
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral500", style: { fontStyle: "italic" }, children: "(empty / not set)" });
2586
+ }
2587
+ if (matches.length === 1 && !matches[0].componentUid) {
2588
+ const displayStr = formatDisplayValue(matches[0].value);
2589
+ const isUnset = displayStr === "(empty / not set)" || displayStr === "(empty / unlinked)";
2590
+ return /* @__PURE__ */ jsxRuntime.jsx(
2591
+ designSystem.Typography,
2592
+ {
2593
+ textColor: isUnset ? "neutral500" : "neutral800",
2594
+ style: {
2595
+ fontStyle: isUnset ? "italic" : "normal",
2596
+ display: "inline-block",
2597
+ maxWidth: 260,
2598
+ overflow: "hidden",
2599
+ textOverflow: "ellipsis",
2600
+ whiteSpace: "nowrap"
2601
+ },
2602
+ children: displayStr
2603
+ }
2604
+ );
2605
+ }
2606
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", gap: 1, alignItems: "flex-start", style: { maxWidth: 320 }, children: matches.map((m) => {
2607
+ const displayStr = formatDisplayValue(m.value);
2608
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2609
+ designSystem.Flex,
2610
+ {
2611
+ gap: 1,
2612
+ alignItems: "center",
2613
+ style: {
2614
+ backgroundColor: "rgba(0, 0, 0, 0.03)",
2615
+ padding: "2px 6px",
2616
+ borderRadius: 4
2617
+ },
2618
+ children: [
2619
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { size: "S", backgroundColor: "neutral200", textColor: "neutral800", children: [
2620
+ "#",
2621
+ m.index,
2622
+ " ",
2623
+ m.componentName
2624
+ ] }),
2625
+ /* @__PURE__ */ jsxRuntime.jsx(
2626
+ designSystem.Typography,
2627
+ {
2628
+ variant: "pi",
2629
+ textColor: "neutral800",
2630
+ style: {
2631
+ maxWidth: 200,
2632
+ overflow: "hidden",
2633
+ textOverflow: "ellipsis",
2634
+ whiteSpace: "nowrap"
2635
+ },
2636
+ children: displayStr
2637
+ }
2638
+ )
2639
+ ]
1843
2640
  },
1844
- children: displayStr
1845
- }
1846
- );
2641
+ m.index
2642
+ );
2643
+ }) });
1847
2644
  }
1848
2645
  case "status": {
1849
2646
  if (selectedAttribute && !hasAttr) {
@@ -1940,6 +2737,8 @@ const BulkUpdater = () => {
1940
2737
  const [selectedAttribute, setSelectedAttribute] = React.useState(getInitialAttribute);
1941
2738
  const [attributeValue, setAttributeValue] = React.useState("");
1942
2739
  const [selectedEntries, setSelectedEntries] = React.useState({});
2740
+ const [expandedDzEntries, setExpandedDzEntries] = React.useState({});
2741
+ const [selectedDzBlocks, setSelectedDzBlocks] = React.useState({});
1943
2742
  const [relationsMeta, setRelationsMeta] = React.useState({});
1944
2743
  const [relationOptions, setRelationOptions] = React.useState([]);
1945
2744
  const [relationOptionsLoading, setRelationOptionsLoading] = React.useState(false);
@@ -2482,40 +3281,78 @@ const BulkUpdater = () => {
2482
3281
  };
2483
3282
  const toggleEntry = (uid, documentId) => {
2484
3283
  const key = `${uid}${KEY_SEP}${documentId}`;
3284
+ const nextVal = !selectedEntries[key];
2485
3285
  setSelectedEntries((prev) => ({
2486
3286
  ...prev,
2487
- [key]: !prev[key]
3287
+ [key]: nextVal
2488
3288
  }));
3289
+ if (!nextVal) {
3290
+ setSelectedDzBlocks((prev) => {
3291
+ const copy = { ...prev };
3292
+ delete copy[key];
3293
+ return copy;
3294
+ });
3295
+ }
3296
+ };
3297
+ const toggleDzBlock = (uid, documentId, blockIndex, allApplicableIndexes) => {
3298
+ const key = `${uid}${KEY_SEP}${documentId}`;
3299
+ setSelectedDzBlocks((prev) => {
3300
+ const currentSelected = prev[key] !== void 0 ? prev[key] : [...allApplicableIndexes];
3301
+ let nextSelected;
3302
+ if (currentSelected.includes(blockIndex)) {
3303
+ nextSelected = currentSelected.filter((idx) => idx !== blockIndex);
3304
+ } else {
3305
+ nextSelected = [...currentSelected, blockIndex];
3306
+ }
3307
+ if (nextSelected.length > 0) {
3308
+ setSelectedEntries((e) => ({ ...e, [key]: true }));
3309
+ } else {
3310
+ setSelectedEntries((e) => ({ ...e, [key]: false }));
3311
+ }
3312
+ return {
3313
+ ...prev,
3314
+ [key]: nextSelected
3315
+ };
3316
+ });
2489
3317
  };
2490
3318
  const entryMatchesFilter = (entry, attr) => {
3319
+ const matches = getAllNestedValues(entry, attr);
2491
3320
  if (useRegex && regexPattern.trim()) {
2492
3321
  try {
2493
3322
  const regex = new RegExp(regexPattern, "i");
2494
- const targetSearchVal = formatDisplayValue(getNestedValue(entry, attr));
2495
- if (!regex.test(targetSearchVal)) {
3323
+ const anyRegexMatch = matches.some((m) => regex.test(formatDisplayValue(m.value)));
3324
+ if (!anyRegexMatch) {
2496
3325
  return false;
2497
3326
  }
2498
3327
  } catch {
2499
3328
  }
2500
3329
  }
2501
3330
  if (filterOperator === "none") return true;
2502
- const val = getNestedValue(entry, attr);
2503
- const displayStr = formatDisplayValue(val);
2504
- const isValEmpty = val === void 0 || val === null || displayStr.trim() === "" || displayStr.trim().toLowerCase() === "(not set)" || displayStr.trim().toLowerCase() === "(empty / not set)" || displayStr.trim().toLowerCase() === "(empty / unlinked)";
2505
- switch (filterOperator) {
2506
- case "empty":
2507
- return isValEmpty;
2508
- case "not_empty":
2509
- return !isValEmpty;
2510
- case "equals":
2511
- return !isValEmpty && displayStr.trim().toLowerCase() === filterQuery.trim().toLowerCase();
2512
- case "contains":
2513
- return !isValEmpty && displayStr.toLowerCase().includes(filterQuery.trim().toLowerCase());
2514
- case "starts_with":
2515
- return !isValEmpty && displayStr.trim().toLowerCase().startsWith(filterQuery.trim().toLowerCase());
2516
- default:
2517
- return true;
3331
+ if (matches.length === 0) {
3332
+ return filterOperator === "empty";
2518
3333
  }
3334
+ const checkMatch = (val) => {
3335
+ const displayStr = formatDisplayValue(val);
3336
+ const isValEmpty = val === void 0 || val === null || displayStr.trim() === "" || displayStr.trim().toLowerCase() === "(not set)" || displayStr.trim().toLowerCase() === "(empty / not set)" || displayStr.trim().toLowerCase() === "(empty / unlinked)";
3337
+ switch (filterOperator) {
3338
+ case "empty":
3339
+ return isValEmpty;
3340
+ case "not_empty":
3341
+ return !isValEmpty;
3342
+ case "equals":
3343
+ return !isValEmpty && displayStr.trim().toLowerCase() === filterQuery.trim().toLowerCase();
3344
+ case "contains":
3345
+ return !isValEmpty && displayStr.toLowerCase().includes(filterQuery.trim().toLowerCase());
3346
+ case "starts_with":
3347
+ return !isValEmpty && displayStr.trim().toLowerCase().startsWith(filterQuery.trim().toLowerCase());
3348
+ default:
3349
+ return true;
3350
+ }
3351
+ };
3352
+ if (filterOperator === "empty") {
3353
+ return matches.every((m) => checkMatch(m.value));
3354
+ }
3355
+ return matches.some((m) => checkMatch(m.value));
2519
3356
  };
2520
3357
  const getVisibleEntries = (col) => {
2521
3358
  const pageState = collectionPages[col.uid];
@@ -2653,7 +3490,11 @@ const BulkUpdater = () => {
2653
3490
  if (selectedEntries[key]) {
2654
3491
  const parts = key.split(KEY_SEP);
2655
3492
  if (parts.length === 2) {
2656
- targets.push({ uid: parts[0], documentId: parts[1] });
3493
+ const targetObj = { uid: parts[0], documentId: parts[1] };
3494
+ if (selectedDzBlocks[key] && selectedDzBlocks[key].length > 0) {
3495
+ targetObj.dynamicZoneIndexes = selectedDzBlocks[key];
3496
+ }
3497
+ targets.push(targetObj);
2657
3498
  }
2658
3499
  }
2659
3500
  });
@@ -2698,7 +3539,11 @@ const BulkUpdater = () => {
2698
3539
  if (selectedEntries[key]) {
2699
3540
  const parts = key.split(KEY_SEP);
2700
3541
  if (parts.length === 2) {
2701
- targets.push({ uid: parts[0], documentId: parts[1] });
3542
+ const targetObj = { uid: parts[0], documentId: parts[1] };
3543
+ if (selectedDzBlocks[key] && selectedDzBlocks[key].length > 0) {
3544
+ targetObj.dynamicZoneIndexes = selectedDzBlocks[key];
3545
+ }
3546
+ targets.push(targetObj);
2702
3547
  }
2703
3548
  }
2704
3549
  });
@@ -2741,6 +3586,7 @@ const BulkUpdater = () => {
2741
3586
  setIsSubmittingBatch(false);
2742
3587
  if (res.data && res.data.success) {
2743
3588
  setSelectedEntries({});
3589
+ setSelectedDzBlocks({});
2744
3590
  const finalBatchId = res.data.batchId;
2745
3591
  setDashboardBatchId(finalBatchId);
2746
3592
  if (res.data.pending) {
@@ -2798,6 +3644,20 @@ const BulkUpdater = () => {
2798
3644
  });
2799
3645
  await fetchModels();
2800
3646
  await fetchAuditHistory();
3647
+ if (selectedCollectionUid) {
3648
+ loadCollectionPage(
3649
+ selectedCollectionUid,
3650
+ collectionPages[selectedCollectionUid]?.page || 1,
3651
+ void 0,
3652
+ void 0,
3653
+ void 0,
3654
+ filterOperator,
3655
+ filterQuery,
3656
+ entrySearch,
3657
+ false,
3658
+ searchAttribute
3659
+ );
3660
+ }
2801
3661
  }
2802
3662
  } else {
2803
3663
  setIsSubmittingBatch(false);
@@ -3928,28 +4788,128 @@ const BulkUpdater = () => {
3928
4788
  const key = `${col.uid}${KEY_SEP}${entry.documentId}`;
3929
4789
  const isSelected = Boolean(selectedEntries[key]);
3930
4790
  const isMatch = isFilterActive;
3931
- return /* @__PURE__ */ jsxRuntime.jsx(
3932
- designSystem.Tr,
3933
- {
3934
- style: {
3935
- backgroundColor: isSelected ? "rgba(73, 69, 255, 0.14)" : isMatch ? "rgba(46, 213, 115, 0.08)" : void 0,
3936
- boxShadow: isSelected ? "inset 3px 0 0 0 #4945ff" : isMatch ? "inset 3px 0 0 0 #2ed573" : void 0
3937
- },
3938
- children: activeColumns.map((colDef) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: renderCellContent(
3939
- colDef,
3940
- entry,
3941
- col,
3942
- selectedAttribute,
3943
- searchAttribute,
3944
- isMatch,
3945
- hasAttr,
3946
- isSelected,
3947
- () => toggleEntry(col.uid, entry.documentId),
3948
- pendingBatches
3949
- ) }, colDef.key))
3950
- },
3951
- key
4791
+ const isDzExpanded = Boolean(expandedDzEntries[key]);
4792
+ const onToggleExpandDz = () => setExpandedDzEntries((prev) => ({
4793
+ ...prev,
4794
+ [key]: !prev[key]
4795
+ }));
4796
+ const dzFields = Object.keys(entry).filter(
4797
+ (k) => Array.isArray(entry[k]) && entry[k].length > 0 && entry[k].some((item) => item && item.__component)
3952
4798
  );
4799
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
4800
+ /* @__PURE__ */ jsxRuntime.jsx(
4801
+ designSystem.Tr,
4802
+ {
4803
+ style: {
4804
+ backgroundColor: isSelected ? "rgba(73, 69, 255, 0.14)" : isMatch ? "rgba(46, 213, 115, 0.08)" : void 0,
4805
+ boxShadow: isSelected ? "inset 3px 0 0 0 #4945ff" : isMatch ? "inset 3px 0 0 0 #2ed573" : void 0
4806
+ },
4807
+ children: activeColumns.map((colDef) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: renderCellContent(
4808
+ colDef,
4809
+ entry,
4810
+ col,
4811
+ selectedAttribute,
4812
+ searchAttribute,
4813
+ isMatch,
4814
+ hasAttr,
4815
+ isSelected,
4816
+ () => toggleEntry(col.uid, entry.documentId),
4817
+ pendingBatches,
4818
+ isDzExpanded,
4819
+ onToggleExpandDz,
4820
+ filterQuery
4821
+ ) }, colDef.key))
4822
+ }
4823
+ ),
4824
+ isDzExpanded && dzFields.map((dzKey) => {
4825
+ const blocks = entry[dzKey] || [];
4826
+ const targetParsed = parseDynamicZonePath(selectedAttribute);
4827
+ const isBlockApplicable = (blockItem) => {
4828
+ if (!targetParsed.subPath) return true;
4829
+ const scopedPath = `${dzKey}[${blockItem?.__component}].${targetParsed.subPath}`;
4830
+ const componentSupports = (col?.attributes || attributes || []).includes(scopedPath);
4831
+ return componentSupports || getNestedValue(blockItem, targetParsed.subPath) !== void 0;
4832
+ };
4833
+ const allApplicableIndexes = blocks.map((_, i) => i).filter((i) => isBlockApplicable(blocks[i]));
4834
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: activeColumns.length, style: { padding: "12px 16px", backgroundColor: "rgba(73, 69, 255, 0.02)", borderBottom: "2px solid rgba(73, 69, 255, 0.15)" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
4835
+ designSystem.Box,
4836
+ {
4837
+ padding: 3,
4838
+ background: "neutral0",
4839
+ hasRadius: true,
4840
+ style: { border: "1px solid rgba(73, 69, 255, 0.25)", boxShadow: "0 2px 8px rgba(0,0,0,0.05)" },
4841
+ children: [
4842
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 2, children: [
4843
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
4844
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", textColor: "primary700", children: [
4845
+ 'DYNAMIC ZONE: "',
4846
+ dzKey,
4847
+ '" (',
4848
+ blocks.length,
4849
+ " blocks)"
4850
+ ] }),
4851
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: "Selective Block Targeting" })
4852
+ ] }),
4853
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "Selectively choose which blocks to update for this entry" })
4854
+ ] }),
4855
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: 5, rowCount: blocks.length + 1, style: { width: "100%", background: "#fff" }, children: [
4856
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
4857
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { width: 64 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Update?" }) }),
4858
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { width: 60 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Pos" }) }),
4859
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { width: 220 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Component" }) }),
4860
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", children: [
4861
+ "Target Field Value (",
4862
+ selectedAttribute || "selected",
4863
+ ")"
4864
+ ] }) }),
4865
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Block Summary" }) })
4866
+ ] }) }),
4867
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: blocks.map((block, bIdx) => {
4868
+ const compUid = block.__component;
4869
+ const compLabel = formatComponentName(compUid);
4870
+ const scopedPath = `${dzKey}[${compUid}].${targetParsed.subPath}`;
4871
+ const componentSupports = (col?.attributes || attributes || []).includes(scopedPath);
4872
+ const blockVal = targetParsed.subPath ? getNestedValue(block, targetParsed.subPath) : void 0;
4873
+ const hasTargetAttr = componentSupports || blockVal !== void 0;
4874
+ const isBlockChecked = hasTargetAttr && isSelected && (selectedDzBlocks[key] !== void 0 ? selectedDzBlocks[key].includes(bIdx) : true);
4875
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4876
+ designSystem.Tr,
4877
+ {
4878
+ style: {
4879
+ backgroundColor: isBlockChecked ? "rgba(73, 69, 255, 0.08)" : void 0
4880
+ },
4881
+ children: [
4882
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(
4883
+ designSystem.Checkbox,
4884
+ {
4885
+ checked: isBlockChecked,
4886
+ disabled: !hasTargetAttr,
4887
+ onCheckedChange: () => {
4888
+ toggleDzBlock(col.uid, entry.documentId, bIdx, allApplicableIndexes);
4889
+ }
4890
+ }
4891
+ ) }),
4892
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: [
4893
+ "#",
4894
+ bIdx
4895
+ ] }) }),
4896
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Td, { children: [
4897
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "neutral150", textColor: "neutral800", children: compLabel }),
4898
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", display: "block", style: { fontSize: "0.68rem", marginTop: 2 }, children: compUid })
4899
+ ] }),
4900
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: hasTargetAttr ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", textColor: "primary700", children: formatDisplayValue(blockVal) }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "neutral100", textColor: "neutral500", children: "Does not contain attribute" }) }),
4901
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { maxWidth: 300, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: block.title || block.name || block.heading || block.body || Object.keys(block).filter((k) => !k.startsWith("_") && k !== "id").slice(0, 3).map((k) => `${k}: ${formatDisplayValue(block[k])}`).join(", ") || "-" }) })
4902
+ ]
4903
+ },
4904
+ bIdx
4905
+ );
4906
+ }) })
4907
+ ] })
4908
+ ]
4909
+ }
4910
+ ) }) }, `${key}-dz-${dzKey}`);
4911
+ })
4912
+ ] }, key);
3953
4913
  }) })
3954
4914
  ] }) }),
3955
4915
  !col.isSingleType && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginTop: 4, wrap: "wrap", gap: 3, children: [
@@ -4427,6 +5387,7 @@ const BulkUpdater = () => {
4427
5387
  '"'
4428
5388
  ] }),
4429
5389
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, alignItems: "center", marginTop: 1, children: [
5390
+ (batch.payload?.action === "csv_import" || batch.id?.startsWith("csv_")) && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: "📊 CSV IMPORT" }),
4430
5391
  /* @__PURE__ */ jsxRuntime.jsx(
4431
5392
  designSystem.Badge,
4432
5393
  {
@@ -5169,8 +6130,11 @@ const BulkUpdater = () => {
5169
6130
  );
5170
6131
  };
5171
6132
  exports.default = BulkUpdater;
6133
+ exports.formatComponentName = formatComponentName;
5172
6134
  exports.formatDisplayValue = formatDisplayValue;
6135
+ exports.getAllNestedValues = getAllNestedValues;
5173
6136
  exports.getAvailableColumnsForCollection = getAvailableColumnsForCollection;
5174
6137
  exports.getEntryLifecycleStatus = getEntryLifecycleStatus;
5175
6138
  exports.getNestedValue = getNestedValue;
5176
- //# sourceMappingURL=BulkUpdater-L2FdlJfh.js.map
6139
+ exports.parseDynamicZonePath = parseDynamicZonePath;
6140
+ //# sourceMappingURL=BulkUpdater-DtBH2c0-.js.map