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