strapi-plugin-bulk-updater 1.4.9 → 1.5.0

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.
@@ -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("safe");
170
- const [unreviewedConsent, setUnreviewedConsent] = React.useState(false);
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.SingleSelect,
487
+ designSystem.Combobox,
488
488
  {
489
- value: selectedUid,
490
- onChange: (val) => {
491
- setSelectedUid(val);
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
- disabled: loadingCollections,
496
- placeholder: "Select a collection...",
497
- children: collections.map((col) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelectOption, { value: col.uid, children: [
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) => setPublishOnImport(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
- setPublishStrategy("safe");
862
- setUnreviewedConsent(false);
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 && (preflightReport?.lifecycleStats?.unreviewedCount ?? 0) > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
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 CONSENT" }),
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 === "safe" ? "2px solid #4945ff" : "1px solid #eaeaef",
1203
- backgroundColor: publishStrategy === "safe" ? "#f0f0ff" : "#ffffff",
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("safe");
1208
- setUnreviewedConsent(false);
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-safe",
1239
+ id: "csv-strategy-all",
1216
1240
  name: "csvPublishStrategy",
1217
- checked: publishStrategy === "safe",
1241
+ checked: publishStrategy === "all",
1218
1242
  onChange: () => {
1219
- setPublishStrategy("safe");
1220
- setUnreviewedConsent(false);
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: "🛡️ Safe Publishing (Recommended)" }),
1227
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
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 === "all" ? "2px solid #d02b20" : "1px solid #eaeaef",
1247
- backgroundColor: publishStrategy === "all" ? "#fff5f5" : "#ffffff",
1262
+ border: publishStrategy === "safe" ? "2px solid #4945ff" : "1px solid #eaeaef",
1263
+ backgroundColor: publishStrategy === "safe" ? "#f0f0ff" : "#ffffff",
1248
1264
  cursor: "pointer"
1249
1265
  },
1250
- onClick: () => setPublishStrategy("all"),
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-all",
1275
+ id: "csv-strategy-safe",
1257
1276
  name: "csvPublishStrategy",
1258
- checked: publishStrategy === "all",
1259
- onChange: () => setPublishStrategy("all"),
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", textColor: "danger700", display: "block", children: "⚠️ Publish All Imported Records (Includes Unreviewed Drafts)" }),
1265
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
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");
@@ -3755,7 +4254,7 @@ const BulkUpdater = () => {
3755
4254
  return val.some((item) => typeof item === "object" ? testEntityObject(item) : testString(item));
3756
4255
  }
3757
4256
  if (typeof val === "object" && val !== null) {
3758
- if (testEntityObject(val)) return true;
4257
+ return testEntityObject(val);
3759
4258
  }
3760
4259
  return testString(displayStr);
3761
4260
  };
@@ -4348,6 +4847,7 @@ const BulkUpdater = () => {
4348
4847
  type: "success",
4349
4848
  message: res.data.message || `Batch ${batchId} approved and executed successfully!`
4350
4849
  });
4850
+ setInspectingPendingBatch(null);
4351
4851
  await fetchPendingBatches();
4352
4852
  await fetchAuditHistory();
4353
4853
  await fetchModels();
@@ -4366,8 +4866,8 @@ const BulkUpdater = () => {
4366
4866
  setApprovingBatchId(null);
4367
4867
  }
4368
4868
  };
4369
- const handleRejectBatch = async (batchId) => {
4370
- const reason = window.prompt("Enter reason for rejection:", "Does not meet release criteria") || "Rejected by Checker";
4869
+ const handleRejectBatch = async (batchId, customReason) => {
4870
+ const reason = customReason || window.prompt("Enter reason for rejection:", "Does not meet release criteria") || "Rejected by Checker";
4371
4871
  try {
4372
4872
  setRejectingBatchId(batchId);
4373
4873
  const res = await post(`/bulk-updater/batches/${batchId}/reject`, { reason });
@@ -4376,6 +4876,7 @@ const BulkUpdater = () => {
4376
4876
  type: "info",
4377
4877
  message: `Batch ${batchId} rejected: ${reason}`
4378
4878
  });
4879
+ setInspectingPendingBatch(null);
4379
4880
  await fetchPendingBatches();
4380
4881
  } else {
4381
4882
  toggleNotification({
@@ -4392,6 +4893,40 @@ const BulkUpdater = () => {
4392
4893
  setRejectingBatchId(null);
4393
4894
  }
4394
4895
  };
4896
+ const handleExportPendingBatch = async (batchId) => {
4897
+ try {
4898
+ setExportingPendingBatchId(batchId);
4899
+ const res = await get(`/bulk-updater/batches/${batchId}/diffs/export`);
4900
+ if (res.data && res.data.success && res.data.csvContent) {
4901
+ const safeContent = res.data.csvContent.startsWith("\uFEFF") ? res.data.csvContent : "\uFEFF" + res.data.csvContent;
4902
+ const blob = new Blob([safeContent], { type: "text/csv;charset=utf-8;" });
4903
+ const url = URL.createObjectURL(blob);
4904
+ const link = document.createElement("a");
4905
+ link.href = url;
4906
+ link.setAttribute("download", res.data.filename || `batch_${batchId}_review.csv`);
4907
+ document.body.appendChild(link);
4908
+ link.click();
4909
+ document.body.removeChild(link);
4910
+ URL.revokeObjectURL(url);
4911
+ toggleNotification({
4912
+ type: "success",
4913
+ message: `Exported ${res.data.count || ""} batch diffs to CSV.`
4914
+ });
4915
+ } else {
4916
+ toggleNotification({
4917
+ type: "danger",
4918
+ message: "Failed to export batch diffs to CSV."
4919
+ });
4920
+ }
4921
+ } catch (err) {
4922
+ toggleNotification({
4923
+ type: "danger",
4924
+ message: err.message || "Error exporting batch diffs."
4925
+ });
4926
+ } finally {
4927
+ setExportingPendingBatchId(null);
4928
+ }
4929
+ };
4395
4930
  const handleExecuteNow = async (batchId) => {
4396
4931
  try {
4397
4932
  setExecutingNowBatchId(batchId);
@@ -4685,9 +5220,14 @@ const BulkUpdater = () => {
4685
5220
  /* @__PURE__ */ jsxRuntime.jsx(
4686
5221
  designSystem.Combobox,
4687
5222
  {
4688
- autocomplete: "none",
4689
- placeholder: "Select Collection Type...",
5223
+ autocomplete: { type: "list", filter: "contains" },
5224
+ placeholder: "Search Collection Type...",
4690
5225
  value: selectedCollectionUid || void 0,
5226
+ clearLabel: "Clear collection selection",
5227
+ onClear: () => handleCollectionChange(""),
5228
+ onFocus: (e) => {
5229
+ e.target.select();
5230
+ },
4691
5231
  onChange: (val) => {
4692
5232
  if (val && typeof val === "string") {
4693
5233
  handleCollectionChange(val);
@@ -4783,7 +5323,7 @@ const BulkUpdater = () => {
4783
5323
  /* @__PURE__ */ jsxRuntime.jsx(
4784
5324
  designSystem.Combobox,
4785
5325
  {
4786
- autocomplete: "none",
5326
+ autocomplete: { type: "list", filter: "contains" },
4787
5327
  placeholder: searchAttribute || `Same as Update (${selectedAttribute || "None"})`,
4788
5328
  value: searchAttribute || "__default__",
4789
5329
  clearLabel: "Reset search attribute",
@@ -4791,6 +5331,9 @@ const BulkUpdater = () => {
4791
5331
  handleSearchAttributeChange("");
4792
5332
  setSearchAttributeSearch("");
4793
5333
  },
5334
+ onFocus: (e) => {
5335
+ e.target.select();
5336
+ },
4794
5337
  onInputChange: (e) => {
4795
5338
  setSearchAttributeSearch(e.target.value);
4796
5339
  },
@@ -5580,7 +6123,7 @@ const BulkUpdater = () => {
5580
6123
  /* @__PURE__ */ jsxRuntime.jsx(
5581
6124
  designSystem.Combobox,
5582
6125
  {
5583
- autocomplete: "none",
6126
+ autocomplete: { type: "list", filter: "contains" },
5584
6127
  placeholder: "Search attribute by name or relation...",
5585
6128
  value: selectedAttribute || void 0,
5586
6129
  clearLabel: "Clear attribute selection",
@@ -5588,6 +6131,9 @@ const BulkUpdater = () => {
5588
6131
  handleAttributeChange("");
5589
6132
  setAttributeSearch("");
5590
6133
  },
6134
+ onFocus: (e) => {
6135
+ e.target.select();
6136
+ },
5591
6137
  onInputChange: (e) => {
5592
6138
  setAttributeSearch(e.target.value);
5593
6139
  },
@@ -6009,6 +6555,27 @@ const BulkUpdater = () => {
6009
6555
  ] })
6010
6556
  ] }) }),
6011
6557
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { style: { textAlign: "right" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, justifyContent: "flex-end", children: [
6558
+ /* @__PURE__ */ jsxRuntime.jsx(
6559
+ designSystem.Button,
6560
+ {
6561
+ size: "S",
6562
+ variant: "secondary",
6563
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Eye, {}),
6564
+ onClick: () => setInspectingPendingBatch(batch),
6565
+ children: "Review Changes"
6566
+ }
6567
+ ),
6568
+ /* @__PURE__ */ jsxRuntime.jsx(
6569
+ designSystem.Button,
6570
+ {
6571
+ size: "S",
6572
+ variant: "tertiary",
6573
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
6574
+ onClick: () => handleExportPendingBatch(batch.id),
6575
+ loading: exportingPendingBatchId === batch.id,
6576
+ children: "Export CSV"
6577
+ }
6578
+ ),
6012
6579
  batch.status === "pending_approval" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6013
6580
  /* @__PURE__ */ jsxRuntime.jsx(
6014
6581
  designSystem.Button,
@@ -6925,6 +7492,18 @@ const BulkUpdater = () => {
6925
7492
  initialJob: dashboardJob,
6926
7493
  isSubmitting: isSubmittingBatch
6927
7494
  }
7495
+ ),
7496
+ /* @__PURE__ */ jsxRuntime.jsx(
7497
+ CheckerReviewModal,
7498
+ {
7499
+ isOpen: Boolean(inspectingPendingBatch),
7500
+ onClose: () => setInspectingPendingBatch(null),
7501
+ batch: inspectingPendingBatch,
7502
+ onApprove: handleApproveBatch,
7503
+ onReject: handleRejectBatch,
7504
+ approving: Boolean(inspectingPendingBatch && approvingBatchId === inspectingPendingBatch.id),
7505
+ rejecting: Boolean(inspectingPendingBatch && rejectingBatchId === inspectingPendingBatch.id)
7506
+ }
6928
7507
  )
6929
7508
  ]
6930
7509
  }
@@ -6941,4 +7520,4 @@ exports.getNestedValue = getNestedValue;
6941
7520
  exports.getPropertyValue = getPropertyValue;
6942
7521
  exports.getSortOptionsForCollection = getSortOptionsForCollection;
6943
7522
  exports.parseDynamicZonePath = parseDynamicZonePath;
6944
- //# sourceMappingURL=BulkUpdater-C0uPoso2.js.map
7523
+ //# sourceMappingURL=BulkUpdater-CSmtXjbM.js.map