strapi-plugin-bulk-updater 1.4.10 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/_chunks/{BulkUpdater-CHdA0546.mjs → BulkUpdater-BiSkkAHF.mjs} +673 -147
- package/dist/_chunks/BulkUpdater-BiSkkAHF.mjs.map +1 -0
- package/dist/_chunks/{BulkUpdater-C0uPoso2.js → BulkUpdater-JZW74XM4.js} +672 -146
- package/dist/_chunks/BulkUpdater-JZW74XM4.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +687 -231
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +687 -231
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/_chunks/BulkUpdater-C0uPoso2.js.map +0 -1
- package/dist/_chunks/BulkUpdater-CHdA0546.mjs.map +0 -1
|
@@ -166,8 +166,8 @@ function CsvManagerTab() {
|
|
|
166
166
|
const [showConfirmModal, setShowConfirmModal] = React.useState(false);
|
|
167
167
|
const [makerNotesInput, setMakerNotesInput] = React.useState("");
|
|
168
168
|
const [submittingBatch, setSubmittingBatch] = React.useState(false);
|
|
169
|
-
const [publishStrategy, setPublishStrategy] = React.useState("
|
|
170
|
-
const [unreviewedConsent, setUnreviewedConsent] = React.useState(
|
|
169
|
+
const [publishStrategy, setPublishStrategy] = React.useState("all");
|
|
170
|
+
const [unreviewedConsent, setUnreviewedConsent] = React.useState(true);
|
|
171
171
|
React.useEffect(() => {
|
|
172
172
|
fetchInitialData();
|
|
173
173
|
}, []);
|
|
@@ -484,23 +484,36 @@ function CsvManagerTab() {
|
|
|
484
484
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
|
|
485
485
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", marginBottom: 2, children: "Target Collection Type" }),
|
|
486
486
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
487
|
-
designSystem.
|
|
487
|
+
designSystem.Combobox,
|
|
488
488
|
{
|
|
489
|
-
value: selectedUid,
|
|
490
|
-
|
|
491
|
-
|
|
489
|
+
value: selectedUid || void 0,
|
|
490
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
491
|
+
placeholder: "Search & select a collection...",
|
|
492
|
+
disabled: loadingCollections,
|
|
493
|
+
clearLabel: "Clear collection selection",
|
|
494
|
+
onClear: () => {
|
|
495
|
+
setSelectedUid("");
|
|
492
496
|
setImportResult(null);
|
|
493
497
|
setImportProgress(null);
|
|
494
498
|
},
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
499
|
+
onFocus: (e) => {
|
|
500
|
+
e.target.select();
|
|
501
|
+
},
|
|
502
|
+
onChange: (val) => {
|
|
503
|
+
if (val && typeof val === "string") {
|
|
504
|
+
setSelectedUid(val);
|
|
505
|
+
setImportResult(null);
|
|
506
|
+
setImportProgress(null);
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
children: collections.map((col) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ComboboxOption, { value: col.uid, textValue: `${col.displayName} (${col.uid})`, children: [
|
|
498
510
|
col.displayName,
|
|
499
511
|
" (",
|
|
500
512
|
col.totalEntries ?? 0,
|
|
501
513
|
" records)"
|
|
502
514
|
] }, col.uid))
|
|
503
|
-
}
|
|
515
|
+
},
|
|
516
|
+
`csv-col-${selectedUid}`
|
|
504
517
|
)
|
|
505
518
|
] }),
|
|
506
519
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -595,7 +608,13 @@ function CsvManagerTab() {
|
|
|
595
608
|
designSystem.Checkbox,
|
|
596
609
|
{
|
|
597
610
|
checked: publishOnImport,
|
|
598
|
-
onValueChange: (val) =>
|
|
611
|
+
onValueChange: (val) => {
|
|
612
|
+
setPublishOnImport(val);
|
|
613
|
+
if (val) {
|
|
614
|
+
setPublishStrategy("all");
|
|
615
|
+
setUnreviewedConsent(true);
|
|
616
|
+
}
|
|
617
|
+
},
|
|
599
618
|
children: "Auto-publish on import"
|
|
600
619
|
}
|
|
601
620
|
)
|
|
@@ -858,8 +877,13 @@ function CsvManagerTab() {
|
|
|
858
877
|
size: "L",
|
|
859
878
|
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
|
|
860
879
|
onClick: () => {
|
|
861
|
-
|
|
862
|
-
|
|
880
|
+
if (publishOnImport) {
|
|
881
|
+
setPublishStrategy("all");
|
|
882
|
+
setUnreviewedConsent(true);
|
|
883
|
+
} else {
|
|
884
|
+
setPublishStrategy("safe");
|
|
885
|
+
setUnreviewedConsent(false);
|
|
886
|
+
}
|
|
863
887
|
setShowConfirmModal(true);
|
|
864
888
|
},
|
|
865
889
|
loading: importing || submittingBatch,
|
|
@@ -1182,7 +1206,7 @@ function CsvManagerTab() {
|
|
|
1182
1206
|
] })
|
|
1183
1207
|
}
|
|
1184
1208
|
),
|
|
1185
|
-
publishOnImport &&
|
|
1209
|
+
publishOnImport && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1186
1210
|
designSystem.Box,
|
|
1187
1211
|
{
|
|
1188
1212
|
padding: 4,
|
|
@@ -1191,7 +1215,7 @@ function CsvManagerTab() {
|
|
|
1191
1215
|
marginBottom: 4,
|
|
1192
1216
|
style: { border: "1px solid #d9d8ff" },
|
|
1193
1217
|
children: [
|
|
1194
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", marginBottom: 3, display: "block", children: "PUBLISHING STRATEGY & GOVERNANCE
|
|
1218
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", marginBottom: 3, display: "block", children: "PUBLISHING STRATEGY & GOVERNANCE" }),
|
|
1195
1219
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, children: [
|
|
1196
1220
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1197
1221
|
designSystem.Box,
|
|
@@ -1199,40 +1223,32 @@ function CsvManagerTab() {
|
|
|
1199
1223
|
padding: 3,
|
|
1200
1224
|
hasRadius: true,
|
|
1201
1225
|
style: {
|
|
1202
|
-
border: publishStrategy === "
|
|
1203
|
-
backgroundColor: publishStrategy === "
|
|
1226
|
+
border: publishStrategy === "all" ? "2px solid #4945ff" : "1px solid #eaeaef",
|
|
1227
|
+
backgroundColor: publishStrategy === "all" ? "#f0f0ff" : "#ffffff",
|
|
1204
1228
|
cursor: "pointer"
|
|
1205
1229
|
},
|
|
1206
1230
|
onClick: () => {
|
|
1207
|
-
setPublishStrategy("
|
|
1208
|
-
setUnreviewedConsent(
|
|
1231
|
+
setPublishStrategy("all");
|
|
1232
|
+
setUnreviewedConsent(true);
|
|
1209
1233
|
},
|
|
1210
1234
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "flex-start", children: [
|
|
1211
1235
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1212
1236
|
"input",
|
|
1213
1237
|
{
|
|
1214
1238
|
type: "radio",
|
|
1215
|
-
id: "csv-strategy-
|
|
1239
|
+
id: "csv-strategy-all",
|
|
1216
1240
|
name: "csvPublishStrategy",
|
|
1217
|
-
checked: publishStrategy === "
|
|
1241
|
+
checked: publishStrategy === "all",
|
|
1218
1242
|
onChange: () => {
|
|
1219
|
-
setPublishStrategy("
|
|
1220
|
-
setUnreviewedConsent(
|
|
1243
|
+
setPublishStrategy("all");
|
|
1244
|
+
setUnreviewedConsent(true);
|
|
1221
1245
|
},
|
|
1222
1246
|
style: { marginTop: 3 }
|
|
1223
1247
|
}
|
|
1224
1248
|
),
|
|
1225
1249
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
1226
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", display: "block", children: "
|
|
1227
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1228
|
-
"Only publish records that are already approved & live (",
|
|
1229
|
-
preflightReport?.lifecycleStats?.published ?? 0,
|
|
1230
|
-
" record",
|
|
1231
|
-
(preflightReport?.lifecycleStats?.published ?? 0) === 1 ? "" : "s",
|
|
1232
|
-
"). The ",
|
|
1233
|
-
preflightReport?.lifecycleStats?.unreviewedCount ?? 0,
|
|
1234
|
-
" unreviewed or draft record(s) will receive the CSV update in Draft mode without publishing unreviewed draft revisions to visitors."
|
|
1235
|
-
] })
|
|
1250
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "primary700", display: "block", children: "🚀 Publish All Imported Records Live (Immediate)" }),
|
|
1251
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Publish all affected records live to production immediately upon import execution." })
|
|
1236
1252
|
] })
|
|
1237
1253
|
] })
|
|
1238
1254
|
}
|
|
@@ -1243,56 +1259,32 @@ function CsvManagerTab() {
|
|
|
1243
1259
|
padding: 3,
|
|
1244
1260
|
hasRadius: true,
|
|
1245
1261
|
style: {
|
|
1246
|
-
border: publishStrategy === "
|
|
1247
|
-
backgroundColor: publishStrategy === "
|
|
1262
|
+
border: publishStrategy === "safe" ? "2px solid #4945ff" : "1px solid #eaeaef",
|
|
1263
|
+
backgroundColor: publishStrategy === "safe" ? "#f0f0ff" : "#ffffff",
|
|
1248
1264
|
cursor: "pointer"
|
|
1249
1265
|
},
|
|
1250
|
-
onClick: () =>
|
|
1266
|
+
onClick: () => {
|
|
1267
|
+
setPublishStrategy("safe");
|
|
1268
|
+
setUnreviewedConsent(false);
|
|
1269
|
+
},
|
|
1251
1270
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "flex-start", children: [
|
|
1252
1271
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1253
1272
|
"input",
|
|
1254
1273
|
{
|
|
1255
1274
|
type: "radio",
|
|
1256
|
-
id: "csv-strategy-
|
|
1275
|
+
id: "csv-strategy-safe",
|
|
1257
1276
|
name: "csvPublishStrategy",
|
|
1258
|
-
checked: publishStrategy === "
|
|
1259
|
-
onChange: () =>
|
|
1277
|
+
checked: publishStrategy === "safe",
|
|
1278
|
+
onChange: () => {
|
|
1279
|
+
setPublishStrategy("safe");
|
|
1280
|
+
setUnreviewedConsent(false);
|
|
1281
|
+
},
|
|
1260
1282
|
style: { marginTop: 3 }
|
|
1261
1283
|
}
|
|
1262
1284
|
),
|
|
1263
1285
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
1264
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold",
|
|
1265
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1266
|
-
"Publish all affected records live to production immediately, pushing all pending unreviewed draft edits in the ",
|
|
1267
|
-
preflightReport?.lifecycleStats?.unreviewedCount ?? 0,
|
|
1268
|
-
" draft/modified record(s) live."
|
|
1269
|
-
] })
|
|
1270
|
-
] })
|
|
1271
|
-
] })
|
|
1272
|
-
}
|
|
1273
|
-
),
|
|
1274
|
-
publishStrategy === "all" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1275
|
-
designSystem.Box,
|
|
1276
|
-
{
|
|
1277
|
-
padding: 3,
|
|
1278
|
-
background: "danger100",
|
|
1279
|
-
hasRadius: true,
|
|
1280
|
-
style: { border: "1px solid #f5c0b8" },
|
|
1281
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "flex-start", children: [
|
|
1282
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1283
|
-
designSystem.Checkbox,
|
|
1284
|
-
{
|
|
1285
|
-
checked: unreviewedConsent,
|
|
1286
|
-
onValueChange: (checked) => setUnreviewedConsent(Boolean(checked))
|
|
1287
|
-
}
|
|
1288
|
-
),
|
|
1289
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { cursor: "pointer" }, onClick: () => setUnreviewedConsent(!unreviewedConsent), children: [
|
|
1290
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "danger700", display: "block", children: "Mandatory Risk Consent Required" }),
|
|
1291
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "danger700", children: [
|
|
1292
|
-
"I understand and explicitly consent that ",
|
|
1293
|
-
preflightReport?.lifecycleStats?.unreviewedCount ?? 0,
|
|
1294
|
-
" record(s) with unreviewed draft revisions or saved draft states will be published live to production visitors."
|
|
1295
|
-
] })
|
|
1286
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", display: "block", children: "🛡️ Safe Publishing (Only Publish Pre-Approved Live Records)" }),
|
|
1287
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Only publish records that are already approved & live. Any unreviewed or draft records will receive the CSV update in Draft mode without publishing to visitors." })
|
|
1296
1288
|
] })
|
|
1297
1289
|
] })
|
|
1298
1290
|
}
|
|
@@ -2360,6 +2352,511 @@ const BulkUpdatePreviewModal = ({
|
|
|
2360
2352
|
}
|
|
2361
2353
|
);
|
|
2362
2354
|
};
|
|
2355
|
+
const CheckerReviewModal = ({
|
|
2356
|
+
isOpen,
|
|
2357
|
+
onClose,
|
|
2358
|
+
batch,
|
|
2359
|
+
onApprove,
|
|
2360
|
+
onReject,
|
|
2361
|
+
approving,
|
|
2362
|
+
rejecting
|
|
2363
|
+
}) => {
|
|
2364
|
+
const { get } = admin.useFetchClient();
|
|
2365
|
+
const { toggleNotification } = admin.useNotification();
|
|
2366
|
+
const [loading, setLoading] = React.useState(false);
|
|
2367
|
+
const [error, setError] = React.useState(null);
|
|
2368
|
+
const [diffs, setDiffs] = React.useState([]);
|
|
2369
|
+
const [summary, setSummary] = React.useState({
|
|
2370
|
+
total: 0,
|
|
2371
|
+
willUpdate: 0,
|
|
2372
|
+
willCreate: 0,
|
|
2373
|
+
unchanged: 0,
|
|
2374
|
+
skipped: 0
|
|
2375
|
+
});
|
|
2376
|
+
const [filterTab, setFilterTab] = React.useState("all");
|
|
2377
|
+
const [searchQuery, setSearchQuery] = React.useState("");
|
|
2378
|
+
const [isExporting, setIsExporting] = React.useState(false);
|
|
2379
|
+
const [showRejectInput, setShowRejectInput] = React.useState(false);
|
|
2380
|
+
const [rejectionReason, setRejectionReason] = React.useState("");
|
|
2381
|
+
const fetchBatchDiffs = async () => {
|
|
2382
|
+
if (!batch || !batch.id) return;
|
|
2383
|
+
try {
|
|
2384
|
+
setLoading(true);
|
|
2385
|
+
setError(null);
|
|
2386
|
+
const res = await get(`/bulk-updater/batches/${batch.id}/diffs`);
|
|
2387
|
+
if (res.data && res.data.success) {
|
|
2388
|
+
setDiffs(res.data.diffs || []);
|
|
2389
|
+
setSummary({
|
|
2390
|
+
total: res.data.summary?.total ?? res.data.diffs?.length ?? 0,
|
|
2391
|
+
willUpdate: res.data.summary?.willUpdate ?? 0,
|
|
2392
|
+
willCreate: res.data.summary?.willCreate ?? 0,
|
|
2393
|
+
unchanged: res.data.summary?.unchanged ?? 0,
|
|
2394
|
+
skipped: res.data.summary?.skipped ?? 0
|
|
2395
|
+
});
|
|
2396
|
+
} else {
|
|
2397
|
+
setError(res.data?.error || "Failed to inspect pending batch changes.");
|
|
2398
|
+
}
|
|
2399
|
+
} catch (err) {
|
|
2400
|
+
setError(err.message || "An error occurred while fetching batch diffs.");
|
|
2401
|
+
} finally {
|
|
2402
|
+
setLoading(false);
|
|
2403
|
+
}
|
|
2404
|
+
};
|
|
2405
|
+
React.useEffect(() => {
|
|
2406
|
+
if (isOpen && batch) {
|
|
2407
|
+
setShowRejectInput(false);
|
|
2408
|
+
setRejectionReason("");
|
|
2409
|
+
setFilterTab("all");
|
|
2410
|
+
setSearchQuery("");
|
|
2411
|
+
fetchBatchDiffs();
|
|
2412
|
+
}
|
|
2413
|
+
}, [isOpen, batch?.id]);
|
|
2414
|
+
const handleExportCsv = async () => {
|
|
2415
|
+
if (!batch || !batch.id) return;
|
|
2416
|
+
try {
|
|
2417
|
+
setIsExporting(true);
|
|
2418
|
+
const res = await get(`/bulk-updater/batches/${batch.id}/diffs/export`);
|
|
2419
|
+
if (res.data && res.data.success && res.data.csvContent) {
|
|
2420
|
+
const safeContent = res.data.csvContent.startsWith("\uFEFF") ? res.data.csvContent : "\uFEFF" + res.data.csvContent;
|
|
2421
|
+
const blob = new Blob([safeContent], { type: "text/csv;charset=utf-8;" });
|
|
2422
|
+
const url = URL.createObjectURL(blob);
|
|
2423
|
+
const link = document.createElement("a");
|
|
2424
|
+
link.href = url;
|
|
2425
|
+
link.setAttribute("download", res.data.filename || `batch_${batch.id}_review.csv`);
|
|
2426
|
+
document.body.appendChild(link);
|
|
2427
|
+
link.click();
|
|
2428
|
+
document.body.removeChild(link);
|
|
2429
|
+
URL.revokeObjectURL(url);
|
|
2430
|
+
toggleNotification({
|
|
2431
|
+
type: "success",
|
|
2432
|
+
message: `Exported ${res.data.count || diffs.length} batch changes to audit CSV.`
|
|
2433
|
+
});
|
|
2434
|
+
} else {
|
|
2435
|
+
toggleNotification({
|
|
2436
|
+
type: "danger",
|
|
2437
|
+
message: "Failed to generate review CSV export."
|
|
2438
|
+
});
|
|
2439
|
+
}
|
|
2440
|
+
} catch (err) {
|
|
2441
|
+
toggleNotification({
|
|
2442
|
+
type: "danger",
|
|
2443
|
+
message: err.message || "Error downloading review CSV."
|
|
2444
|
+
});
|
|
2445
|
+
} finally {
|
|
2446
|
+
setIsExporting(false);
|
|
2447
|
+
}
|
|
2448
|
+
};
|
|
2449
|
+
const filteredDiffs = React.useMemo(() => {
|
|
2450
|
+
let items = diffs;
|
|
2451
|
+
if (filterTab === "changes") {
|
|
2452
|
+
items = items.filter((d) => d.hasChange || d.status === "will_create");
|
|
2453
|
+
} else if (filterTab === "will_update") {
|
|
2454
|
+
items = items.filter((d) => d.status === "will_update");
|
|
2455
|
+
} else if (filterTab === "will_create") {
|
|
2456
|
+
items = items.filter((d) => d.status === "will_create");
|
|
2457
|
+
} else if (filterTab === "unchanged") {
|
|
2458
|
+
items = items.filter((d) => d.status === "unchanged");
|
|
2459
|
+
} else if (filterTab === "will_skip") {
|
|
2460
|
+
items = items.filter((d) => d.status === "will_skip");
|
|
2461
|
+
}
|
|
2462
|
+
if (searchQuery.trim()) {
|
|
2463
|
+
const q = searchQuery.toLowerCase().trim();
|
|
2464
|
+
items = items.filter(
|
|
2465
|
+
(d) => d.label?.toLowerCase().includes(q) || d.documentId?.toLowerCase().includes(q) || d.collectionName?.toLowerCase().includes(q) || d.attribute?.toLowerCase().includes(q) || String(d.oldDisplay || "").toLowerCase().includes(q) || String(d.newDisplay || "").toLowerCase().includes(q)
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2468
|
+
return items;
|
|
2469
|
+
}, [diffs, filterTab, searchQuery]);
|
|
2470
|
+
if (!isOpen || !batch) return null;
|
|
2471
|
+
const totalChanges = (summary.willUpdate || 0) + (summary.willCreate || 0);
|
|
2472
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2473
|
+
"div",
|
|
2474
|
+
{
|
|
2475
|
+
style: {
|
|
2476
|
+
position: "fixed",
|
|
2477
|
+
inset: 0,
|
|
2478
|
+
backgroundColor: "rgba(20, 20, 30, 0.75)",
|
|
2479
|
+
backdropFilter: "blur(4px)",
|
|
2480
|
+
display: "flex",
|
|
2481
|
+
alignItems: "center",
|
|
2482
|
+
justifyContent: "center",
|
|
2483
|
+
zIndex: 9999,
|
|
2484
|
+
padding: 16,
|
|
2485
|
+
boxSizing: "border-box"
|
|
2486
|
+
},
|
|
2487
|
+
onClick: onClose,
|
|
2488
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2489
|
+
designSystem.Box,
|
|
2490
|
+
{
|
|
2491
|
+
background: "neutral0",
|
|
2492
|
+
hasRadius: true,
|
|
2493
|
+
shadow: "popupShadow",
|
|
2494
|
+
style: {
|
|
2495
|
+
maxWidth: 1160,
|
|
2496
|
+
width: "96%",
|
|
2497
|
+
maxHeight: "calc(100vh - 40px)",
|
|
2498
|
+
display: "flex",
|
|
2499
|
+
flexDirection: "column",
|
|
2500
|
+
overflow: "hidden",
|
|
2501
|
+
position: "relative",
|
|
2502
|
+
boxShadow: "0 24px 50px rgba(0, 0, 0, 0.4), 0 0 1px rgba(0, 0, 0, 0.25)"
|
|
2503
|
+
},
|
|
2504
|
+
onClick: (e) => e.stopPropagation(),
|
|
2505
|
+
children: [
|
|
2506
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2507
|
+
designSystem.Box,
|
|
2508
|
+
{
|
|
2509
|
+
padding: 5,
|
|
2510
|
+
background: "neutral100",
|
|
2511
|
+
style: {
|
|
2512
|
+
borderBottom: "1px solid rgba(120, 120, 150, 0.2)",
|
|
2513
|
+
flexShrink: 0
|
|
2514
|
+
},
|
|
2515
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "flex-start", wrap: "wrap", gap: 3, children: [
|
|
2516
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
2517
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", marginBottom: 1, children: [
|
|
2518
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", children: "Checker Approval: Bulk Change Inspection" }),
|
|
2519
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: batch.id }),
|
|
2520
|
+
(batch.payload?.action === "csv_import" || batch.id?.startsWith("csv_")) && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: "📊 CSV IMPORT" }),
|
|
2521
|
+
batch.payload?.action === "publish" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", children: "🚀 BULK PUBLISH" })
|
|
2522
|
+
] }),
|
|
2523
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
2524
|
+
"Submitted by ",
|
|
2525
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: batch.createdBy?.email || "admin" }),
|
|
2526
|
+
" on ",
|
|
2527
|
+
new Date(batch.createdAt).toLocaleString()
|
|
2528
|
+
] }),
|
|
2529
|
+
batch.makerNotes && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, padding: 2, background: "neutral150", hasRadius: true, style: { borderLeft: "3px solid #4945ff" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral700", children: [
|
|
2530
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Maker Notes:" }),
|
|
2531
|
+
" ",
|
|
2532
|
+
batch.makerNotes
|
|
2533
|
+
] }) })
|
|
2534
|
+
] }),
|
|
2535
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
2536
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2537
|
+
designSystem.Button,
|
|
2538
|
+
{
|
|
2539
|
+
variant: "tertiary",
|
|
2540
|
+
size: "S",
|
|
2541
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
|
|
2542
|
+
onClick: handleExportCsv,
|
|
2543
|
+
loading: isExporting,
|
|
2544
|
+
children: "Export Audit CSV"
|
|
2545
|
+
}
|
|
2546
|
+
),
|
|
2547
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2548
|
+
designSystem.Button,
|
|
2549
|
+
{
|
|
2550
|
+
variant: "tertiary",
|
|
2551
|
+
size: "S",
|
|
2552
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowClockwise, {}),
|
|
2553
|
+
onClick: fetchBatchDiffs,
|
|
2554
|
+
loading,
|
|
2555
|
+
children: "Refresh"
|
|
2556
|
+
}
|
|
2557
|
+
)
|
|
2558
|
+
] })
|
|
2559
|
+
] })
|
|
2560
|
+
}
|
|
2561
|
+
),
|
|
2562
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2563
|
+
designSystem.Box,
|
|
2564
|
+
{
|
|
2565
|
+
padding: 5,
|
|
2566
|
+
style: {
|
|
2567
|
+
flex: "1 1 auto",
|
|
2568
|
+
minHeight: 0,
|
|
2569
|
+
overflowY: "auto",
|
|
2570
|
+
WebkitOverflowScrolling: "touch"
|
|
2571
|
+
},
|
|
2572
|
+
children: [
|
|
2573
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, style: { textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", gap: 3, children: [
|
|
2574
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { children: "Inspecting target records from database..." }),
|
|
2575
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "semiBold", children: "Generating Itemized Diffs..." }),
|
|
2576
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Comparing proposed values against current database records." })
|
|
2577
|
+
] }) }) : error ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, style: { textAlign: "center" }, children: [
|
|
2578
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", textColor: "danger700", fontWeight: "bold", children: "Failed to load change diffs" }),
|
|
2579
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral700", display: "block", marginTop: 1, children: error })
|
|
2580
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2581
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, marginBottom: 4, wrap: "wrap", children: [
|
|
2582
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2583
|
+
designSystem.Box,
|
|
2584
|
+
{
|
|
2585
|
+
padding: 3,
|
|
2586
|
+
background: "neutral100",
|
|
2587
|
+
hasRadius: true,
|
|
2588
|
+
style: { flex: 1, minWidth: 130, border: "1px solid rgba(120, 120, 150, 0.15)" },
|
|
2589
|
+
children: [
|
|
2590
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", display: "block", children: "TOTAL TARGETS" }),
|
|
2591
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", fontWeight: "bold", textColor: "neutral800", children: summary.total })
|
|
2592
|
+
]
|
|
2593
|
+
}
|
|
2594
|
+
),
|
|
2595
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2596
|
+
designSystem.Box,
|
|
2597
|
+
{
|
|
2598
|
+
padding: 3,
|
|
2599
|
+
background: "warning100",
|
|
2600
|
+
hasRadius: true,
|
|
2601
|
+
style: { flex: 1, minWidth: 130, border: "1px solid #ffd591" },
|
|
2602
|
+
children: [
|
|
2603
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "warning700", display: "block", children: "WILL UPDATE" }),
|
|
2604
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", fontWeight: "bold", textColor: "warning700", children: summary.willUpdate })
|
|
2605
|
+
]
|
|
2606
|
+
}
|
|
2607
|
+
),
|
|
2608
|
+
(summary.willCreate ?? 0) > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2609
|
+
designSystem.Box,
|
|
2610
|
+
{
|
|
2611
|
+
padding: 3,
|
|
2612
|
+
background: "success100",
|
|
2613
|
+
hasRadius: true,
|
|
2614
|
+
style: { flex: 1, minWidth: 130, border: "1px solid #b7eb8f" },
|
|
2615
|
+
children: [
|
|
2616
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "success700", display: "block", children: "WILL CREATE (NEW)" }),
|
|
2617
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", fontWeight: "bold", textColor: "success700", children: summary.willCreate })
|
|
2618
|
+
]
|
|
2619
|
+
}
|
|
2620
|
+
),
|
|
2621
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2622
|
+
designSystem.Box,
|
|
2623
|
+
{
|
|
2624
|
+
padding: 3,
|
|
2625
|
+
background: "neutral100",
|
|
2626
|
+
hasRadius: true,
|
|
2627
|
+
style: { flex: 1, minWidth: 130, border: "1px solid rgba(120, 120, 150, 0.15)" },
|
|
2628
|
+
children: [
|
|
2629
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", display: "block", children: "UNCHANGED" }),
|
|
2630
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", fontWeight: "bold", textColor: "neutral600", children: summary.unchanged })
|
|
2631
|
+
]
|
|
2632
|
+
}
|
|
2633
|
+
),
|
|
2634
|
+
summary.skipped > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2635
|
+
designSystem.Box,
|
|
2636
|
+
{
|
|
2637
|
+
padding: 3,
|
|
2638
|
+
background: "danger100",
|
|
2639
|
+
hasRadius: true,
|
|
2640
|
+
style: { flex: 1, minWidth: 130, border: "1px solid #ffa39e" },
|
|
2641
|
+
children: [
|
|
2642
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "danger700", display: "block", children: "SKIPPED / ERRORS" }),
|
|
2643
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", fontWeight: "bold", textColor: "danger700", children: summary.skipped })
|
|
2644
|
+
]
|
|
2645
|
+
}
|
|
2646
|
+
)
|
|
2647
|
+
] }),
|
|
2648
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 3, wrap: "wrap", gap: 3, children: [
|
|
2649
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, wrap: "wrap", children: [
|
|
2650
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2651
|
+
designSystem.Button,
|
|
2652
|
+
{
|
|
2653
|
+
variant: filterTab === "all" ? "default" : "tertiary",
|
|
2654
|
+
size: "S",
|
|
2655
|
+
onClick: () => setFilterTab("all"),
|
|
2656
|
+
children: [
|
|
2657
|
+
"All Items (",
|
|
2658
|
+
diffs.length,
|
|
2659
|
+
")"
|
|
2660
|
+
]
|
|
2661
|
+
}
|
|
2662
|
+
),
|
|
2663
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2664
|
+
designSystem.Button,
|
|
2665
|
+
{
|
|
2666
|
+
variant: filterTab === "changes" ? "default" : "tertiary",
|
|
2667
|
+
size: "S",
|
|
2668
|
+
onClick: () => setFilterTab("changes"),
|
|
2669
|
+
children: [
|
|
2670
|
+
"Changes Only (",
|
|
2671
|
+
totalChanges,
|
|
2672
|
+
")"
|
|
2673
|
+
]
|
|
2674
|
+
}
|
|
2675
|
+
),
|
|
2676
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2677
|
+
designSystem.Button,
|
|
2678
|
+
{
|
|
2679
|
+
variant: filterTab === "will_update" ? "default" : "tertiary",
|
|
2680
|
+
size: "S",
|
|
2681
|
+
onClick: () => setFilterTab("will_update"),
|
|
2682
|
+
children: [
|
|
2683
|
+
"Updates (",
|
|
2684
|
+
summary.willUpdate,
|
|
2685
|
+
")"
|
|
2686
|
+
]
|
|
2687
|
+
}
|
|
2688
|
+
),
|
|
2689
|
+
(summary.willCreate ?? 0) > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2690
|
+
designSystem.Button,
|
|
2691
|
+
{
|
|
2692
|
+
variant: filterTab === "will_create" ? "default" : "tertiary",
|
|
2693
|
+
size: "S",
|
|
2694
|
+
onClick: () => setFilterTab("will_create"),
|
|
2695
|
+
children: [
|
|
2696
|
+
"Creates (",
|
|
2697
|
+
summary.willCreate,
|
|
2698
|
+
")"
|
|
2699
|
+
]
|
|
2700
|
+
}
|
|
2701
|
+
),
|
|
2702
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2703
|
+
designSystem.Button,
|
|
2704
|
+
{
|
|
2705
|
+
variant: filterTab === "unchanged" ? "default" : "tertiary",
|
|
2706
|
+
size: "S",
|
|
2707
|
+
onClick: () => setFilterTab("unchanged"),
|
|
2708
|
+
children: [
|
|
2709
|
+
"Unchanged (",
|
|
2710
|
+
summary.unchanged,
|
|
2711
|
+
")"
|
|
2712
|
+
]
|
|
2713
|
+
}
|
|
2714
|
+
),
|
|
2715
|
+
summary.skipped > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2716
|
+
designSystem.Button,
|
|
2717
|
+
{
|
|
2718
|
+
variant: filterTab === "will_skip" ? "default" : "tertiary",
|
|
2719
|
+
size: "S",
|
|
2720
|
+
onClick: () => setFilterTab("will_skip"),
|
|
2721
|
+
children: [
|
|
2722
|
+
"Skipped (",
|
|
2723
|
+
summary.skipped,
|
|
2724
|
+
")"
|
|
2725
|
+
]
|
|
2726
|
+
}
|
|
2727
|
+
)
|
|
2728
|
+
] }),
|
|
2729
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 260 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2730
|
+
designSystem.TextInput,
|
|
2731
|
+
{
|
|
2732
|
+
placeholder: "Search records or values...",
|
|
2733
|
+
size: "S",
|
|
2734
|
+
value: searchQuery,
|
|
2735
|
+
onChange: (e) => setSearchQuery(e.target.value)
|
|
2736
|
+
}
|
|
2737
|
+
) })
|
|
2738
|
+
] }),
|
|
2739
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2740
|
+
designSystem.Box,
|
|
2741
|
+
{
|
|
2742
|
+
hasRadius: true,
|
|
2743
|
+
style: {
|
|
2744
|
+
border: "1px solid #eaeaef",
|
|
2745
|
+
maxHeight: 380,
|
|
2746
|
+
overflowY: "auto",
|
|
2747
|
+
overflowX: "auto"
|
|
2748
|
+
},
|
|
2749
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: 6, rowCount: filteredDiffs.length + 1, style: { width: "100%", minWidth: 880 }, children: [
|
|
2750
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
2751
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { width: 140 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: "COLLECTION" }) }),
|
|
2752
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: "RECORD IDENTIFIER" }) }),
|
|
2753
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { minWidth: 140 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: "ATTRIBUTE" }) }),
|
|
2754
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: "CURRENT VALUE (BEFORE)" }) }),
|
|
2755
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: "PROPOSED VALUE (AFTER)" }) }),
|
|
2756
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { width: 130, textAlign: "right" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: "IMPACT" }) })
|
|
2757
|
+
] }) }),
|
|
2758
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: filteredDiffs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: 6, style: { textAlign: "center", padding: "24px" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: "No records match the current filter or search criteria." }) }) }) : filteredDiffs.map((diff, idx) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
2759
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "neutral150", textColor: "neutral700", children: diff.collectionName }) }),
|
|
2760
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
2761
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", display: "block", children: diff.label }),
|
|
2762
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: diff.documentId }) })
|
|
2763
|
+
] }) }),
|
|
2764
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", children: diff.attribute }) }),
|
|
2765
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2766
|
+
designSystem.Typography,
|
|
2767
|
+
{
|
|
2768
|
+
variant: "omega",
|
|
2769
|
+
style: {
|
|
2770
|
+
color: diff.hasChange ? "#9254de" : "#272635",
|
|
2771
|
+
textDecoration: diff.hasChange ? "line-through" : "none",
|
|
2772
|
+
wordBreak: "break-all"
|
|
2773
|
+
},
|
|
2774
|
+
children: diff.oldDisplay || "(empty)"
|
|
2775
|
+
}
|
|
2776
|
+
) }),
|
|
2777
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: diff.status === "will_create" ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "success700", style: { wordBreak: "break-all" }, children: diff.newDisplay || "(new value)" }) : diff.status === "will_skip" ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "warning700", children: "— Skipped —" }) : diff.hasChange ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "success700", style: { wordBreak: "break-all" }, children: diff.newDisplay || "(empty)" }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: diff.newDisplay || "(matching)" }) }),
|
|
2778
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Td, { style: { textAlign: "right" }, children: [
|
|
2779
|
+
diff.status === "will_create" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", children: "+ Will Create" }),
|
|
2780
|
+
diff.status === "will_update" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "warning100", textColor: "warning700", children: "✎ Will Update" }),
|
|
2781
|
+
diff.status === "unchanged" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "neutral150", textColor: "neutral600", children: "= Unchanged" }),
|
|
2782
|
+
diff.status === "will_skip" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "danger100", textColor: "danger700", children: "⚠ Will Skip" })
|
|
2783
|
+
] })
|
|
2784
|
+
] }, `${diff.uid}-${diff.documentId}-${diff.attribute}-${idx}`)) })
|
|
2785
|
+
] })
|
|
2786
|
+
}
|
|
2787
|
+
)
|
|
2788
|
+
] }),
|
|
2789
|
+
showRejectInput && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { marginTop: 4, padding: 4, background: "danger100", hasRadius: true, style: { border: "1px solid #ffa39e" }, children: [
|
|
2790
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", textColor: "danger700", marginBottom: 2, children: "Reject Batch" }),
|
|
2791
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "danger700", marginBottom: 2, display: "block", children: "Please provide a rejection note explaining why this batch was declined. The Maker will see this message." }),
|
|
2792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2793
|
+
designSystem.TextInput,
|
|
2794
|
+
{
|
|
2795
|
+
placeholder: "Reason for rejection (e.g., incorrect localized prices in CSV rows 4-8)...",
|
|
2796
|
+
value: rejectionReason,
|
|
2797
|
+
onChange: (e) => setRejectionReason(e.target.value),
|
|
2798
|
+
style: { marginBottom: 12 }
|
|
2799
|
+
}
|
|
2800
|
+
),
|
|
2801
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, justifyContent: "flex-end", children: [
|
|
2802
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", size: "S", onClick: () => setShowRejectInput(false), children: "Cancel" }),
|
|
2803
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2804
|
+
designSystem.Button,
|
|
2805
|
+
{
|
|
2806
|
+
variant: "danger",
|
|
2807
|
+
size: "S",
|
|
2808
|
+
loading: rejecting,
|
|
2809
|
+
onClick: () => onReject(batch.id, rejectionReason || "Declined by Checker"),
|
|
2810
|
+
children: "Confirm Rejection"
|
|
2811
|
+
}
|
|
2812
|
+
)
|
|
2813
|
+
] })
|
|
2814
|
+
] })
|
|
2815
|
+
]
|
|
2816
|
+
}
|
|
2817
|
+
),
|
|
2818
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2819
|
+
designSystem.Box,
|
|
2820
|
+
{
|
|
2821
|
+
padding: 4,
|
|
2822
|
+
background: "neutral100",
|
|
2823
|
+
style: {
|
|
2824
|
+
borderTop: "1px solid rgba(120, 120, 150, 0.2)",
|
|
2825
|
+
flexShrink: 0
|
|
2826
|
+
},
|
|
2827
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 3, children: [
|
|
2828
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", onClick: onClose, disabled: approving || rejecting, children: "Close Preview" }),
|
|
2829
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, children: [
|
|
2830
|
+
!showRejectInput && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2831
|
+
designSystem.Button,
|
|
2832
|
+
{
|
|
2833
|
+
variant: "danger-light",
|
|
2834
|
+
onClick: () => setShowRejectInput(true),
|
|
2835
|
+
disabled: approving || rejecting,
|
|
2836
|
+
children: "Reject Batch"
|
|
2837
|
+
}
|
|
2838
|
+
),
|
|
2839
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2840
|
+
designSystem.Button,
|
|
2841
|
+
{
|
|
2842
|
+
variant: "success",
|
|
2843
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
|
|
2844
|
+
onClick: () => onApprove(batch.id),
|
|
2845
|
+
loading: approving,
|
|
2846
|
+
disabled: rejecting,
|
|
2847
|
+
children: "Approve & Execute Batch"
|
|
2848
|
+
}
|
|
2849
|
+
)
|
|
2850
|
+
] })
|
|
2851
|
+
] })
|
|
2852
|
+
}
|
|
2853
|
+
)
|
|
2854
|
+
]
|
|
2855
|
+
}
|
|
2856
|
+
)
|
|
2857
|
+
}
|
|
2858
|
+
);
|
|
2859
|
+
};
|
|
2363
2860
|
function parseDynamicZonePath(path) {
|
|
2364
2861
|
if (!path) return { cleanPath: "", rootKey: "", subPath: "" };
|
|
2365
2862
|
const bracketMatch = path.match(/^([^.[]+)\[([^\]]+)\]\.(.+)$/);
|
|
@@ -3060,6 +3557,8 @@ const BulkUpdater = () => {
|
|
|
3060
3557
|
const [pendingBatchesLoading, setPendingBatchesLoading] = React.useState(false);
|
|
3061
3558
|
const [approvingBatchId, setApprovingBatchId] = React.useState(null);
|
|
3062
3559
|
const [rejectingBatchId, setRejectingBatchId] = React.useState(null);
|
|
3560
|
+
const [inspectingPendingBatch, setInspectingPendingBatch] = React.useState(null);
|
|
3561
|
+
const [exportingPendingBatchId, setExportingPendingBatchId] = React.useState(null);
|
|
3063
3562
|
const [makerNotesInput, setMakerNotesInput] = React.useState("");
|
|
3064
3563
|
const [publishOnApproval, setPublishOnApproval] = React.useState(true);
|
|
3065
3564
|
const [publishStrategy, setPublishStrategy] = React.useState("safe");
|
|
@@ -3532,8 +4031,6 @@ const BulkUpdater = () => {
|
|
|
3532
4031
|
const filteredCollections = React.useMemo(() => {
|
|
3533
4032
|
return selectedCol ? [selectedCol] : [];
|
|
3534
4033
|
}, [selectedCol]);
|
|
3535
|
-
const [attributeSearch, setAttributeSearch] = React.useState("");
|
|
3536
|
-
const [searchAttributeSearch, setSearchAttributeSearch] = React.useState("");
|
|
3537
4034
|
const getAttrDepth = (attr) => attributesMeta[attr]?.depth ?? (attr.includes(".") ? attr.split(".").length - 1 : 0);
|
|
3538
4035
|
const availableColAttributes = React.useMemo(() => {
|
|
3539
4036
|
return selectedCol?.attributes || attributes || [];
|
|
@@ -3541,48 +4038,20 @@ const BulkUpdater = () => {
|
|
|
3541
4038
|
const depthFilteredAttributes = React.useMemo(() => {
|
|
3542
4039
|
return availableColAttributes.filter((attr) => getAttrDepth(attr) <= componentDepth);
|
|
3543
4040
|
}, [availableColAttributes, componentDepth, attributesMeta]);
|
|
3544
|
-
const filteredAttributes = React.useMemo(() => {
|
|
3545
|
-
const q = attributeSearch.toLowerCase().trim();
|
|
3546
|
-
if (!q || q === (selectedAttribute || "").toLowerCase().trim()) {
|
|
3547
|
-
return depthFilteredAttributes;
|
|
3548
|
-
}
|
|
3549
|
-
const cleanQ = q.replace(/[^a-z0-9]/g, "");
|
|
3550
|
-
return depthFilteredAttributes.filter((attr) => {
|
|
3551
|
-
const lower = attr.toLowerCase();
|
|
3552
|
-
const cleanLower = lower.replace(/[^a-z0-9]/g, "");
|
|
3553
|
-
const rel = relationsMeta[attr];
|
|
3554
|
-
const relTarget = (rel?.targetDisplayName || "").toLowerCase();
|
|
3555
|
-
return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
|
|
3556
|
-
});
|
|
3557
|
-
}, [depthFilteredAttributes, attributeSearch, selectedAttribute, relationsMeta]);
|
|
3558
|
-
const filteredSearchAttributes = React.useMemo(() => {
|
|
3559
|
-
const q = searchAttributeSearch.toLowerCase().trim();
|
|
3560
|
-
if (!q || q === (searchAttribute || "").toLowerCase().trim()) {
|
|
3561
|
-
return depthFilteredAttributes;
|
|
3562
|
-
}
|
|
3563
|
-
const cleanQ = q.replace(/[^a-z0-9]/g, "");
|
|
3564
|
-
return depthFilteredAttributes.filter((attr) => {
|
|
3565
|
-
const lower = attr.toLowerCase();
|
|
3566
|
-
const cleanLower = lower.replace(/[^a-z0-9]/g, "");
|
|
3567
|
-
const rel = relationsMeta[attr];
|
|
3568
|
-
const relTarget = (rel?.targetDisplayName || "").toLowerCase();
|
|
3569
|
-
return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
|
|
3570
|
-
});
|
|
3571
|
-
}, [depthFilteredAttributes, searchAttributeSearch, searchAttribute, relationsMeta]);
|
|
3572
4041
|
const memoizedComboboxOptions = React.useMemo(() => {
|
|
3573
|
-
if (
|
|
3574
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: "__none__", disabled: true, textValue: "No
|
|
3575
|
-
|
|
3576
|
-
attributeSearch,
|
|
3577
|
-
'" (Depth L',
|
|
4042
|
+
if (depthFilteredAttributes.length === 0) {
|
|
4043
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: "__none__", disabled: true, textValue: "No attributes available", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
4044
|
+
"No attributes available for this collection type (Depth L",
|
|
3578
4045
|
componentDepth,
|
|
3579
4046
|
")"
|
|
3580
4047
|
] }) });
|
|
3581
4048
|
}
|
|
3582
|
-
return
|
|
4049
|
+
return depthFilteredAttributes.map((attr) => {
|
|
3583
4050
|
const rel = relationsMeta[attr];
|
|
3584
4051
|
const depth = getAttrDepth(attr);
|
|
3585
|
-
|
|
4052
|
+
const badgeText = rel ? `relation ${rel.targetDisplayName}` : depth > 0 ? `L${depth} component` : "";
|
|
4053
|
+
const textValue = badgeText ? `${attr} ${badgeText}` : attr;
|
|
4054
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: attr, textValue, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
3586
4055
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: attr === selectedAttribute ? "bold" : "regular", children: attr }),
|
|
3587
4056
|
rel ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", size: "S", children: [
|
|
3588
4057
|
"relation ➔ ",
|
|
@@ -3594,14 +4063,14 @@ const BulkUpdater = () => {
|
|
|
3594
4063
|
] }) : null
|
|
3595
4064
|
] }) }, attr);
|
|
3596
4065
|
});
|
|
3597
|
-
}, [
|
|
4066
|
+
}, [depthFilteredAttributes, relationsMeta, selectedAttribute, componentDepth, attributesMeta]);
|
|
3598
4067
|
const memoizedSearchComboboxOptions = React.useMemo(() => {
|
|
3599
4068
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3600
4069
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3601
4070
|
designSystem.ComboboxOption,
|
|
3602
4071
|
{
|
|
3603
4072
|
value: "__default__",
|
|
3604
|
-
textValue: `Same as Update Attribute (${selectedAttribute || "None"})`,
|
|
4073
|
+
textValue: `Same as Update Attribute (${selectedAttribute || "None"}) default`,
|
|
3605
4074
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
3606
4075
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", fontStyle: "italic", textColor: "neutral600", children: [
|
|
3607
4076
|
"-- Same as Update Attribute (",
|
|
@@ -3612,10 +4081,12 @@ const BulkUpdater = () => {
|
|
|
3612
4081
|
] })
|
|
3613
4082
|
}
|
|
3614
4083
|
),
|
|
3615
|
-
|
|
4084
|
+
depthFilteredAttributes.map((attr) => {
|
|
3616
4085
|
const rel = relationsMeta[attr];
|
|
3617
4086
|
const depth = getAttrDepth(attr);
|
|
3618
|
-
|
|
4087
|
+
const badgeText = rel ? `relation ${rel.targetDisplayName}` : depth > 0 ? `L${depth} component` : "";
|
|
4088
|
+
const textValue = badgeText ? `${attr} ${badgeText}` : attr;
|
|
4089
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: attr, textValue, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
3619
4090
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: attr === searchAttribute ? "bold" : "regular", children: attr }),
|
|
3620
4091
|
rel ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", size: "S", children: [
|
|
3621
4092
|
"relation ➔ ",
|
|
@@ -3628,7 +4099,7 @@ const BulkUpdater = () => {
|
|
|
3628
4099
|
] }) }, `search_${attr}`);
|
|
3629
4100
|
})
|
|
3630
4101
|
] });
|
|
3631
|
-
}, [
|
|
4102
|
+
}, [depthFilteredAttributes, relationsMeta, searchAttribute, selectedAttribute, componentDepth, attributesMeta]);
|
|
3632
4103
|
const handleSearchAttributeChange = (newAttr) => {
|
|
3633
4104
|
const finalAttr = newAttr === "__default__" ? "" : newAttr;
|
|
3634
4105
|
setSearchAttribute(finalAttr);
|
|
@@ -3755,7 +4226,7 @@ const BulkUpdater = () => {
|
|
|
3755
4226
|
return val.some((item) => typeof item === "object" ? testEntityObject(item) : testString(item));
|
|
3756
4227
|
}
|
|
3757
4228
|
if (typeof val === "object" && val !== null) {
|
|
3758
|
-
|
|
4229
|
+
return testEntityObject(val);
|
|
3759
4230
|
}
|
|
3760
4231
|
return testString(displayStr);
|
|
3761
4232
|
};
|
|
@@ -3803,7 +4274,6 @@ const BulkUpdater = () => {
|
|
|
3803
4274
|
};
|
|
3804
4275
|
const clearFilter = () => {
|
|
3805
4276
|
setSearchAttribute("");
|
|
3806
|
-
setSearchAttributeSearch("");
|
|
3807
4277
|
setFilterOperator("none");
|
|
3808
4278
|
setFilterQuery("");
|
|
3809
4279
|
setEntrySearch("");
|
|
@@ -4348,6 +4818,7 @@ const BulkUpdater = () => {
|
|
|
4348
4818
|
type: "success",
|
|
4349
4819
|
message: res.data.message || `Batch ${batchId} approved and executed successfully!`
|
|
4350
4820
|
});
|
|
4821
|
+
setInspectingPendingBatch(null);
|
|
4351
4822
|
await fetchPendingBatches();
|
|
4352
4823
|
await fetchAuditHistory();
|
|
4353
4824
|
await fetchModels();
|
|
@@ -4366,8 +4837,8 @@ const BulkUpdater = () => {
|
|
|
4366
4837
|
setApprovingBatchId(null);
|
|
4367
4838
|
}
|
|
4368
4839
|
};
|
|
4369
|
-
const handleRejectBatch = async (batchId) => {
|
|
4370
|
-
const reason = window.prompt("Enter reason for rejection:", "Does not meet release criteria") || "Rejected by Checker";
|
|
4840
|
+
const handleRejectBatch = async (batchId, customReason) => {
|
|
4841
|
+
const reason = customReason || window.prompt("Enter reason for rejection:", "Does not meet release criteria") || "Rejected by Checker";
|
|
4371
4842
|
try {
|
|
4372
4843
|
setRejectingBatchId(batchId);
|
|
4373
4844
|
const res = await post(`/bulk-updater/batches/${batchId}/reject`, { reason });
|
|
@@ -4376,6 +4847,7 @@ const BulkUpdater = () => {
|
|
|
4376
4847
|
type: "info",
|
|
4377
4848
|
message: `Batch ${batchId} rejected: ${reason}`
|
|
4378
4849
|
});
|
|
4850
|
+
setInspectingPendingBatch(null);
|
|
4379
4851
|
await fetchPendingBatches();
|
|
4380
4852
|
} else {
|
|
4381
4853
|
toggleNotification({
|
|
@@ -4392,6 +4864,40 @@ const BulkUpdater = () => {
|
|
|
4392
4864
|
setRejectingBatchId(null);
|
|
4393
4865
|
}
|
|
4394
4866
|
};
|
|
4867
|
+
const handleExportPendingBatch = async (batchId) => {
|
|
4868
|
+
try {
|
|
4869
|
+
setExportingPendingBatchId(batchId);
|
|
4870
|
+
const res = await get(`/bulk-updater/batches/${batchId}/diffs/export`);
|
|
4871
|
+
if (res.data && res.data.success && res.data.csvContent) {
|
|
4872
|
+
const safeContent = res.data.csvContent.startsWith("\uFEFF") ? res.data.csvContent : "\uFEFF" + res.data.csvContent;
|
|
4873
|
+
const blob = new Blob([safeContent], { type: "text/csv;charset=utf-8;" });
|
|
4874
|
+
const url = URL.createObjectURL(blob);
|
|
4875
|
+
const link = document.createElement("a");
|
|
4876
|
+
link.href = url;
|
|
4877
|
+
link.setAttribute("download", res.data.filename || `batch_${batchId}_review.csv`);
|
|
4878
|
+
document.body.appendChild(link);
|
|
4879
|
+
link.click();
|
|
4880
|
+
document.body.removeChild(link);
|
|
4881
|
+
URL.revokeObjectURL(url);
|
|
4882
|
+
toggleNotification({
|
|
4883
|
+
type: "success",
|
|
4884
|
+
message: `Exported ${res.data.count || ""} batch diffs to CSV.`
|
|
4885
|
+
});
|
|
4886
|
+
} else {
|
|
4887
|
+
toggleNotification({
|
|
4888
|
+
type: "danger",
|
|
4889
|
+
message: "Failed to export batch diffs to CSV."
|
|
4890
|
+
});
|
|
4891
|
+
}
|
|
4892
|
+
} catch (err) {
|
|
4893
|
+
toggleNotification({
|
|
4894
|
+
type: "danger",
|
|
4895
|
+
message: err.message || "Error exporting batch diffs."
|
|
4896
|
+
});
|
|
4897
|
+
} finally {
|
|
4898
|
+
setExportingPendingBatchId(null);
|
|
4899
|
+
}
|
|
4900
|
+
};
|
|
4395
4901
|
const handleExecuteNow = async (batchId) => {
|
|
4396
4902
|
try {
|
|
4397
4903
|
setExecutingNowBatchId(batchId);
|
|
@@ -4685,9 +5191,14 @@ const BulkUpdater = () => {
|
|
|
4685
5191
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4686
5192
|
designSystem.Combobox,
|
|
4687
5193
|
{
|
|
4688
|
-
autocomplete: "
|
|
4689
|
-
placeholder: "
|
|
5194
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
5195
|
+
placeholder: "Search Collection Type...",
|
|
4690
5196
|
value: selectedCollectionUid || void 0,
|
|
5197
|
+
clearLabel: "Clear collection selection",
|
|
5198
|
+
onClear: () => handleCollectionChange(""),
|
|
5199
|
+
onFocus: (e) => {
|
|
5200
|
+
e.target.select();
|
|
5201
|
+
},
|
|
4691
5202
|
onChange: (val) => {
|
|
4692
5203
|
if (val && typeof val === "string") {
|
|
4693
5204
|
handleCollectionChange(val);
|
|
@@ -4783,26 +5294,17 @@ const BulkUpdater = () => {
|
|
|
4783
5294
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4784
5295
|
designSystem.Combobox,
|
|
4785
5296
|
{
|
|
4786
|
-
autocomplete: "
|
|
5297
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
4787
5298
|
placeholder: searchAttribute || `Same as Update (${selectedAttribute || "None"})`,
|
|
4788
5299
|
value: searchAttribute || "__default__",
|
|
4789
5300
|
clearLabel: "Reset search attribute",
|
|
4790
|
-
onClear: () =>
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
},
|
|
4794
|
-
onInputChange: (e) => {
|
|
4795
|
-
setSearchAttributeSearch(e.target.value);
|
|
4796
|
-
},
|
|
4797
|
-
onOpenChange: (isOpen) => {
|
|
4798
|
-
if (!isOpen) {
|
|
4799
|
-
setSearchAttributeSearch("");
|
|
4800
|
-
}
|
|
5301
|
+
onClear: () => handleSearchAttributeChange(""),
|
|
5302
|
+
onFocus: (e) => {
|
|
5303
|
+
e.target.select();
|
|
4801
5304
|
},
|
|
4802
5305
|
onChange: (val) => {
|
|
4803
5306
|
if (val && typeof val === "string" && val !== "__none__") {
|
|
4804
5307
|
handleSearchAttributeChange(val);
|
|
4805
|
-
setSearchAttributeSearch("");
|
|
4806
5308
|
}
|
|
4807
5309
|
},
|
|
4808
5310
|
children: memoizedSearchComboboxOptions
|
|
@@ -5580,28 +6082,19 @@ const BulkUpdater = () => {
|
|
|
5580
6082
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5581
6083
|
designSystem.Combobox,
|
|
5582
6084
|
{
|
|
5583
|
-
autocomplete: "
|
|
6085
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
5584
6086
|
placeholder: "Search attribute by name or relation...",
|
|
5585
6087
|
value: selectedAttribute || void 0,
|
|
5586
6088
|
clearLabel: "Clear attribute selection",
|
|
5587
|
-
onClear: () =>
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
},
|
|
5591
|
-
onInputChange: (e) => {
|
|
5592
|
-
setAttributeSearch(e.target.value);
|
|
5593
|
-
},
|
|
5594
|
-
onOpenChange: (isOpen) => {
|
|
5595
|
-
if (!isOpen) {
|
|
5596
|
-
setAttributeSearch("");
|
|
5597
|
-
}
|
|
6089
|
+
onClear: () => handleAttributeChange(""),
|
|
6090
|
+
onFocus: (e) => {
|
|
6091
|
+
e.target.select();
|
|
5598
6092
|
},
|
|
5599
6093
|
loading: loading && attributes.length === 0,
|
|
5600
6094
|
loadingMessage: "Discovering schema attributes...",
|
|
5601
6095
|
onChange: (val) => {
|
|
5602
6096
|
if (val && typeof val === "string" && val !== "__none__") {
|
|
5603
6097
|
handleAttributeChange(val);
|
|
5604
|
-
setAttributeSearch("");
|
|
5605
6098
|
}
|
|
5606
6099
|
},
|
|
5607
6100
|
children: memoizedComboboxOptions
|
|
@@ -6009,6 +6502,27 @@ const BulkUpdater = () => {
|
|
|
6009
6502
|
] })
|
|
6010
6503
|
] }) }),
|
|
6011
6504
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { style: { textAlign: "right" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, justifyContent: "flex-end", children: [
|
|
6505
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6506
|
+
designSystem.Button,
|
|
6507
|
+
{
|
|
6508
|
+
size: "S",
|
|
6509
|
+
variant: "secondary",
|
|
6510
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Eye, {}),
|
|
6511
|
+
onClick: () => setInspectingPendingBatch(batch),
|
|
6512
|
+
children: "Review Changes"
|
|
6513
|
+
}
|
|
6514
|
+
),
|
|
6515
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6516
|
+
designSystem.Button,
|
|
6517
|
+
{
|
|
6518
|
+
size: "S",
|
|
6519
|
+
variant: "tertiary",
|
|
6520
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
|
|
6521
|
+
onClick: () => handleExportPendingBatch(batch.id),
|
|
6522
|
+
loading: exportingPendingBatchId === batch.id,
|
|
6523
|
+
children: "Export CSV"
|
|
6524
|
+
}
|
|
6525
|
+
),
|
|
6012
6526
|
batch.status === "pending_approval" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6013
6527
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6014
6528
|
designSystem.Button,
|
|
@@ -6925,6 +7439,18 @@ const BulkUpdater = () => {
|
|
|
6925
7439
|
initialJob: dashboardJob,
|
|
6926
7440
|
isSubmitting: isSubmittingBatch
|
|
6927
7441
|
}
|
|
7442
|
+
),
|
|
7443
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7444
|
+
CheckerReviewModal,
|
|
7445
|
+
{
|
|
7446
|
+
isOpen: Boolean(inspectingPendingBatch),
|
|
7447
|
+
onClose: () => setInspectingPendingBatch(null),
|
|
7448
|
+
batch: inspectingPendingBatch,
|
|
7449
|
+
onApprove: handleApproveBatch,
|
|
7450
|
+
onReject: handleRejectBatch,
|
|
7451
|
+
approving: Boolean(inspectingPendingBatch && approvingBatchId === inspectingPendingBatch.id),
|
|
7452
|
+
rejecting: Boolean(inspectingPendingBatch && rejectingBatchId === inspectingPendingBatch.id)
|
|
7453
|
+
}
|
|
6928
7454
|
)
|
|
6929
7455
|
]
|
|
6930
7456
|
}
|
|
@@ -6941,4 +7467,4 @@ exports.getNestedValue = getNestedValue;
|
|
|
6941
7467
|
exports.getPropertyValue = getPropertyValue;
|
|
6942
7468
|
exports.getSortOptionsForCollection = getSortOptionsForCollection;
|
|
6943
7469
|
exports.parseDynamicZonePath = parseDynamicZonePath;
|
|
6944
|
-
//# sourceMappingURL=BulkUpdater-
|
|
7470
|
+
//# sourceMappingURL=BulkUpdater-JZW74XM4.js.map
|