strapi-plugin-bulk-updater 1.2.9 → 1.2.10

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.
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import React__default, { useState, useEffect, useMemo, useRef } from "react";
3
3
  import { useFetchClient, useNotification } from "@strapi/strapi/admin";
4
4
  import { Box, Flex, Typography, Button, SingleSelect, SingleSelectOption, Checkbox, Badge, Alert, Table, Thead, Tr, Th, Tbody, Td, Loader, TextInput, ComboboxOption, Field, Combobox } from "@strapi/design-system";
5
- import { ArrowClockwise, Download, Upload, Check, Play } from "@strapi/icons";
5
+ import { ArrowClockwise, Download, Upload, Check, Eye, Play } from "@strapi/icons";
6
6
  import { V as ValidationRulesTab } from "./ValidationRulesTab-BGcqM9cN.mjs";
7
7
  function CsvManagerTab() {
8
8
  const { get, post } = useFetchClient();
@@ -1113,6 +1113,330 @@ function ProcessingDashboardModal({
1113
1113
  }
1114
1114
  );
1115
1115
  }
1116
+ const BulkUpdatePreviewModal = ({
1117
+ isOpen,
1118
+ onClose,
1119
+ onProceed,
1120
+ loading,
1121
+ previewData,
1122
+ attribute,
1123
+ targetValueDisplay
1124
+ }) => {
1125
+ const [filterTab, setFilterTab] = useState("all");
1126
+ const [searchQuery, setSearchQuery] = useState("");
1127
+ const filteredDiffs = useMemo(() => {
1128
+ if (!previewData || !previewData.diffs) return [];
1129
+ let items = previewData.diffs;
1130
+ if (filterTab !== "all") {
1131
+ items = items.filter((d) => d.status === filterTab);
1132
+ }
1133
+ if (searchQuery.trim()) {
1134
+ const q = searchQuery.toLowerCase().trim();
1135
+ items = items.filter(
1136
+ (d) => d.label.toLowerCase().includes(q) || d.documentId.toLowerCase().includes(q) || d.collectionName.toLowerCase().includes(q) || String(d.oldDisplay || "").toLowerCase().includes(q) || String(d.newDisplay || "").toLowerCase().includes(q)
1137
+ );
1138
+ }
1139
+ return items;
1140
+ }, [previewData, filterTab, searchQuery]);
1141
+ if (!isOpen) return null;
1142
+ return /* @__PURE__ */ jsx(
1143
+ "div",
1144
+ {
1145
+ style: {
1146
+ position: "fixed",
1147
+ inset: 0,
1148
+ backgroundColor: "rgba(20, 20, 30, 0.7)",
1149
+ backdropFilter: "blur(3px)",
1150
+ display: "flex",
1151
+ alignItems: "center",
1152
+ justifyContent: "center",
1153
+ zIndex: 9999,
1154
+ padding: 16,
1155
+ boxSizing: "border-box"
1156
+ },
1157
+ onClick: onClose,
1158
+ children: /* @__PURE__ */ jsxs(
1159
+ Box,
1160
+ {
1161
+ background: "neutral0",
1162
+ hasRadius: true,
1163
+ shadow: "popupShadow",
1164
+ style: {
1165
+ maxWidth: 1040,
1166
+ width: "95%",
1167
+ maxHeight: "calc(100vh - 48px)",
1168
+ display: "flex",
1169
+ flexDirection: "column",
1170
+ overflow: "hidden",
1171
+ position: "relative",
1172
+ boxShadow: "0 24px 48px rgba(0, 0, 0, 0.35), 0 0 1px rgba(0, 0, 0, 0.2)"
1173
+ },
1174
+ onClick: (e) => e.stopPropagation(),
1175
+ children: [
1176
+ /* @__PURE__ */ jsx(
1177
+ Box,
1178
+ {
1179
+ padding: 5,
1180
+ background: "neutral100",
1181
+ style: {
1182
+ borderBottom: "1px solid rgba(120, 120, 150, 0.2)",
1183
+ flexShrink: 0
1184
+ },
1185
+ children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 3, children: [
1186
+ /* @__PURE__ */ jsxs(Box, { children: [
1187
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", marginBottom: 1, children: [
1188
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", fontWeight: "bold", children: "Pre-Update Change Preview" }),
1189
+ /* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
1190
+ "Target: ",
1191
+ attribute
1192
+ ] })
1193
+ ] }),
1194
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Inspect exact before & after values across target records before applying changes to the database." })
1195
+ ] }),
1196
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
1197
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "New Value:" }),
1198
+ /* @__PURE__ */ jsx(Badge, { backgroundColor: "success100", textColor: "success700", children: targetValueDisplay || "(empty)" })
1199
+ ] })
1200
+ ] })
1201
+ }
1202
+ ),
1203
+ /* @__PURE__ */ jsx(
1204
+ Box,
1205
+ {
1206
+ padding: 5,
1207
+ style: {
1208
+ flex: "1 1 auto",
1209
+ minHeight: 0,
1210
+ overflowY: "auto",
1211
+ WebkitOverflowScrolling: "touch"
1212
+ },
1213
+ children: loading ? /* @__PURE__ */ jsx(Box, { padding: 8, style: { textAlign: "center" }, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 3, children: [
1214
+ /* @__PURE__ */ jsx(Loader, { children: "Inspecting target records from database..." }),
1215
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", fontWeight: "semiBold", children: "Inspecting Target Records..." }),
1216
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Computing proposed diffs and verifying against database schema." })
1217
+ ] }) }) : !previewData ? /* @__PURE__ */ jsx(Box, { padding: 6, style: { textAlign: "center" }, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: "No preview data available." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1218
+ /* @__PURE__ */ jsxs(Flex, { gap: 3, marginBottom: 4, wrap: "wrap", children: [
1219
+ /* @__PURE__ */ jsxs(
1220
+ Box,
1221
+ {
1222
+ padding: 3,
1223
+ background: "neutral100",
1224
+ hasRadius: true,
1225
+ style: { flex: 1, minWidth: 140, border: "1px solid rgba(120, 120, 150, 0.15)" },
1226
+ children: [
1227
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", display: "block", children: "TOTAL TARGETS" }),
1228
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", textColor: "neutral800", children: previewData.summary.total })
1229
+ ]
1230
+ }
1231
+ ),
1232
+ /* @__PURE__ */ jsxs(
1233
+ Box,
1234
+ {
1235
+ padding: 3,
1236
+ background: "success100",
1237
+ hasRadius: true,
1238
+ style: { flex: 1, minWidth: 140, border: "1px solid #b7eb8f" },
1239
+ children: [
1240
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "success700", display: "block", children: "WILL UPDATE" }),
1241
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", textColor: "success700", children: previewData.summary.willUpdate })
1242
+ ]
1243
+ }
1244
+ ),
1245
+ /* @__PURE__ */ jsxs(
1246
+ Box,
1247
+ {
1248
+ padding: 3,
1249
+ background: "neutral100",
1250
+ hasRadius: true,
1251
+ style: { flex: 1, minWidth: 140, border: "1px solid rgba(120, 120, 150, 0.15)" },
1252
+ children: [
1253
+ /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", display: "block", children: "ALREADY UP-TO-DATE" }),
1254
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", textColor: "neutral600", children: previewData.summary.unchanged })
1255
+ ]
1256
+ }
1257
+ ),
1258
+ /* @__PURE__ */ jsxs(
1259
+ Box,
1260
+ {
1261
+ padding: 3,
1262
+ background: previewData.summary.skipped > 0 ? "warning100" : "neutral100",
1263
+ hasRadius: true,
1264
+ style: { flex: 1, minWidth: 140, border: "1px solid rgba(120, 120, 150, 0.15)" },
1265
+ children: [
1266
+ /* @__PURE__ */ jsx(
1267
+ Typography,
1268
+ {
1269
+ variant: "sigma",
1270
+ textColor: previewData.summary.skipped > 0 ? "warning700" : "neutral600",
1271
+ display: "block",
1272
+ children: "WILL SKIP (NO FIELD)"
1273
+ }
1274
+ ),
1275
+ /* @__PURE__ */ jsx(
1276
+ Typography,
1277
+ {
1278
+ variant: "beta",
1279
+ fontWeight: "bold",
1280
+ textColor: previewData.summary.skipped > 0 ? "warning700" : "neutral600",
1281
+ children: previewData.summary.skipped
1282
+ }
1283
+ )
1284
+ ]
1285
+ }
1286
+ )
1287
+ ] }),
1288
+ /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 3, wrap: "wrap", gap: 3, children: [
1289
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, wrap: "wrap", children: [
1290
+ /* @__PURE__ */ jsxs(
1291
+ Button,
1292
+ {
1293
+ variant: filterTab === "all" ? "default" : "tertiary",
1294
+ size: "S",
1295
+ onClick: () => setFilterTab("all"),
1296
+ children: [
1297
+ "All (",
1298
+ previewData.summary.total,
1299
+ ")"
1300
+ ]
1301
+ }
1302
+ ),
1303
+ /* @__PURE__ */ jsxs(
1304
+ Button,
1305
+ {
1306
+ variant: filterTab === "will_update" ? "default" : "tertiary",
1307
+ size: "S",
1308
+ onClick: () => setFilterTab("will_update"),
1309
+ children: [
1310
+ "Will Update (",
1311
+ previewData.summary.willUpdate,
1312
+ ")"
1313
+ ]
1314
+ }
1315
+ ),
1316
+ /* @__PURE__ */ jsxs(
1317
+ Button,
1318
+ {
1319
+ variant: filterTab === "unchanged" ? "default" : "tertiary",
1320
+ size: "S",
1321
+ onClick: () => setFilterTab("unchanged"),
1322
+ children: [
1323
+ "Unchanged (",
1324
+ previewData.summary.unchanged,
1325
+ ")"
1326
+ ]
1327
+ }
1328
+ ),
1329
+ previewData.summary.skipped > 0 && /* @__PURE__ */ jsxs(
1330
+ Button,
1331
+ {
1332
+ variant: filterTab === "will_skip" ? "default" : "tertiary",
1333
+ size: "S",
1334
+ onClick: () => setFilterTab("will_skip"),
1335
+ children: [
1336
+ "Skipped (",
1337
+ previewData.summary.skipped,
1338
+ ")"
1339
+ ]
1340
+ }
1341
+ )
1342
+ ] }),
1343
+ /* @__PURE__ */ jsx(Box, { style: { width: 260 }, children: /* @__PURE__ */ jsx(
1344
+ TextInput,
1345
+ {
1346
+ placeholder: "Search records or values...",
1347
+ size: "S",
1348
+ value: searchQuery,
1349
+ onChange: (e) => setSearchQuery(e.target.value)
1350
+ }
1351
+ ) })
1352
+ ] }),
1353
+ /* @__PURE__ */ jsx(
1354
+ Box,
1355
+ {
1356
+ hasRadius: true,
1357
+ style: {
1358
+ border: "1px solid #eaeaef",
1359
+ maxHeight: 380,
1360
+ overflowY: "auto",
1361
+ overflowX: "auto"
1362
+ },
1363
+ children: /* @__PURE__ */ jsxs(Table, { colCount: 5, rowCount: filteredDiffs.length + 1, style: { width: "100%", minWidth: 780 }, children: [
1364
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
1365
+ /* @__PURE__ */ jsx(Th, { style: { width: 150 }, children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: "COLLECTION" }) }),
1366
+ /* @__PURE__ */ jsx(Th, { style: { minWidth: 200 }, children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: "RECORD IDENTIFIER" }) }),
1367
+ /* @__PURE__ */ jsx(Th, { style: { minWidth: 180 }, children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: "CURRENT VALUE (BEFORE)" }) }),
1368
+ /* @__PURE__ */ jsx(Th, { style: { minWidth: 180 }, children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: "NEW VALUE (AFTER)" }) }),
1369
+ /* @__PURE__ */ jsx(Th, { style: { width: 140, textAlign: "right" }, children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: "IMPACT" }) })
1370
+ ] }) }),
1371
+ /* @__PURE__ */ jsx(Tbody, { children: filteredDiffs.length === 0 ? /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: 5, style: { textAlign: "center", padding: "24px" }, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: "No records match the current filter or search criteria." }) }) }) : filteredDiffs.map((diff) => /* @__PURE__ */ jsxs(Tr, { children: [
1372
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Badge, { backgroundColor: "neutral150", textColor: "neutral700", children: diff.collectionName }) }),
1373
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Box, { children: [
1374
+ /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", display: "block", children: diff.label }),
1375
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: /* @__PURE__ */ jsx("code", { children: diff.documentId }) })
1376
+ ] }) }),
1377
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(
1378
+ Typography,
1379
+ {
1380
+ variant: "omega",
1381
+ style: {
1382
+ color: diff.hasChange ? "#666687" : "#272635",
1383
+ textDecoration: diff.hasChange ? "line-through" : "none",
1384
+ wordBreak: "break-all"
1385
+ },
1386
+ children: diff.oldDisplay || "(empty)"
1387
+ }
1388
+ ) }),
1389
+ /* @__PURE__ */ jsx(Td, { children: diff.status === "will_skip" ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "warning700", children: "— Skipped (field absent) —" }) : diff.hasChange ? /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", textColor: "success700", style: { wordBreak: "break-all" }, children: diff.newDisplay || "(empty)" }) : /* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", children: diff.newDisplay || "(already matching)" }) }),
1390
+ /* @__PURE__ */ jsxs(Td, { style: { textAlign: "right" }, children: [
1391
+ diff.status === "will_update" && /* @__PURE__ */ jsx(Badge, { backgroundColor: "success100", textColor: "success700", children: "✓ Will Update" }),
1392
+ diff.status === "unchanged" && /* @__PURE__ */ jsx(Badge, { backgroundColor: "neutral150", textColor: "neutral600", children: "= Unchanged" }),
1393
+ diff.status === "will_skip" && /* @__PURE__ */ jsx(Badge, { backgroundColor: "warning100", textColor: "warning700", children: "⚠ Will Skip" })
1394
+ ] })
1395
+ ] }, `${diff.uid}-${diff.documentId}`)) })
1396
+ ] })
1397
+ }
1398
+ )
1399
+ ] })
1400
+ }
1401
+ ),
1402
+ /* @__PURE__ */ jsx(
1403
+ Box,
1404
+ {
1405
+ padding: 4,
1406
+ background: "neutral100",
1407
+ style: {
1408
+ borderTop: "1px solid rgba(120, 120, 150, 0.2)",
1409
+ flexShrink: 0
1410
+ },
1411
+ children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
1412
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "M", onClick: onClose, children: "Close Preview" }),
1413
+ /* @__PURE__ */ jsxs(
1414
+ Button,
1415
+ {
1416
+ variant: "default",
1417
+ size: "M",
1418
+ startIcon: /* @__PURE__ */ jsx(Check, {}),
1419
+ onClick: () => {
1420
+ onClose();
1421
+ onProceed();
1422
+ },
1423
+ disabled: loading || !previewData || previewData.summary.total === 0,
1424
+ children: [
1425
+ "Proceed to Execute (",
1426
+ previewData?.summary.willUpdate || 0,
1427
+ " updates)"
1428
+ ]
1429
+ }
1430
+ )
1431
+ ] })
1432
+ }
1433
+ )
1434
+ ]
1435
+ }
1436
+ )
1437
+ }
1438
+ );
1439
+ };
1116
1440
  function getNestedValue(obj, path) {
1117
1441
  if (!obj || !path) return void 0;
1118
1442
  if (!path.includes(".")) return obj[path];
@@ -1307,6 +1631,9 @@ const BulkUpdater = () => {
1307
1631
  const [dashboardBatchId, setDashboardBatchId] = useState("");
1308
1632
  const [dashboardJob, setDashboardJob] = useState(null);
1309
1633
  const [isSubmittingBatch, setIsSubmittingBatch] = useState(false);
1634
+ const [showPreviewModal, setShowPreviewModal] = useState(false);
1635
+ const [previewLoading, setPreviewLoading] = useState(false);
1636
+ const [previewData, setPreviewData] = useState(null);
1310
1637
  const MODELS_CACHE_KEY = "strapi_bulk_updater_models_cache";
1311
1638
  const LAST_ATTR_KEY = "strapi_bulk_updater_last_attr";
1312
1639
  const getInitialAttribute = () => {
@@ -1893,6 +2220,56 @@ const BulkUpdater = () => {
1893
2220
  }
1894
2221
  setShowConfirmModal(true);
1895
2222
  };
2223
+ const handleOpenPreviewModal = async () => {
2224
+ if (!selectedAttribute) {
2225
+ toggleNotification({
2226
+ type: "warning",
2227
+ message: "Please select an attribute from the dropdown"
2228
+ });
2229
+ return;
2230
+ }
2231
+ const targets = [];
2232
+ Object.keys(selectedEntries).forEach((key) => {
2233
+ if (selectedEntries[key]) {
2234
+ const parts = key.split(KEY_SEP);
2235
+ if (parts.length === 2) {
2236
+ targets.push({ uid: parts[0], documentId: parts[1] });
2237
+ }
2238
+ }
2239
+ });
2240
+ if (targets.length === 0) {
2241
+ toggleNotification({
2242
+ type: "warning",
2243
+ message: "Please select at least one collection type or entry to preview"
2244
+ });
2245
+ return;
2246
+ }
2247
+ setShowPreviewModal(true);
2248
+ setPreviewLoading(true);
2249
+ try {
2250
+ const res = await post("/bulk-updater/preview", {
2251
+ attribute: selectedAttribute,
2252
+ value: attributeValue,
2253
+ selectedEntries: targets,
2254
+ isRegex: useRegex,
2255
+ regexPattern,
2256
+ publishOnApproval
2257
+ });
2258
+ if (res.data && res.data.success) {
2259
+ setPreviewData(res.data);
2260
+ } else {
2261
+ throw new Error(res.data?.error || "Failed to generate preview");
2262
+ }
2263
+ } catch (err) {
2264
+ toggleNotification({
2265
+ type: "danger",
2266
+ message: err.message || "Failed to fetch preview diffs"
2267
+ });
2268
+ setShowPreviewModal(false);
2269
+ } finally {
2270
+ setPreviewLoading(false);
2271
+ }
2272
+ };
1896
2273
  const executeBatchWithMode = async (executionMode, forceImmediate = false) => {
1897
2274
  const targets = [];
1898
2275
  Object.keys(selectedEntries).forEach((key) => {
@@ -2481,22 +2858,40 @@ const BulkUpdater = () => {
2481
2858
  onChange: (e) => setAttributeValue(e.target.value)
2482
2859
  }
2483
2860
  ) }),
2484
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(
2485
- Button,
2486
- {
2487
- startIcon: /* @__PURE__ */ jsx(Play, {}),
2488
- variant: "default",
2489
- size: "L",
2490
- onClick: handleOpenConfirmModal,
2491
- loading: updating,
2492
- disabled: loading || totalSelectedCount === 0,
2493
- children: [
2494
- "Update Selected (",
2495
- totalSelectedCount,
2496
- ")"
2497
- ]
2498
- }
2499
- ) })
2861
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
2862
+ /* @__PURE__ */ jsxs(
2863
+ Button,
2864
+ {
2865
+ startIcon: /* @__PURE__ */ jsx(Eye, {}),
2866
+ variant: "secondary",
2867
+ size: "L",
2868
+ onClick: handleOpenPreviewModal,
2869
+ loading: previewLoading,
2870
+ disabled: loading || totalSelectedCount === 0 || !selectedAttribute,
2871
+ children: [
2872
+ "Preview Changes (",
2873
+ totalSelectedCount,
2874
+ ")"
2875
+ ]
2876
+ }
2877
+ ),
2878
+ /* @__PURE__ */ jsxs(
2879
+ Button,
2880
+ {
2881
+ startIcon: /* @__PURE__ */ jsx(Play, {}),
2882
+ variant: "default",
2883
+ size: "L",
2884
+ onClick: handleOpenConfirmModal,
2885
+ loading: updating,
2886
+ disabled: loading || totalSelectedCount === 0 || !selectedAttribute,
2887
+ children: [
2888
+ "Update Selected (",
2889
+ totalSelectedCount,
2890
+ ")"
2891
+ ]
2892
+ }
2893
+ )
2894
+ ] })
2500
2895
  ] }),
2501
2896
  /* @__PURE__ */ jsx(Box, { marginTop: 4, padding: 4, background: "neutral100", hasRadius: true, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 3, children: [
2502
2897
  /* @__PURE__ */ jsx(Flex, { gap: 2, alignItems: "center", children: /* @__PURE__ */ jsx(
@@ -3673,6 +4068,22 @@ const BulkUpdater = () => {
3673
4068
  children: publishOnApproval ? "Publish Immediately" : "Keep as Draft"
3674
4069
  }
3675
4070
  )
4071
+ ] }),
4072
+ /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginTop: 2, paddingTop: 2, style: { borderTop: "1px solid #eaeaef" }, children: [
4073
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Need to inspect before & after values?" }),
4074
+ /* @__PURE__ */ jsx(
4075
+ Button,
4076
+ {
4077
+ variant: "secondary",
4078
+ size: "S",
4079
+ startIcon: /* @__PURE__ */ jsx(Eye, {}),
4080
+ onClick: () => {
4081
+ setShowConfirmModal(false);
4082
+ handleOpenPreviewModal();
4083
+ },
4084
+ children: "Open Change Preview"
4085
+ }
4086
+ )
3676
4087
  ] })
3677
4088
  ] })
3678
4089
  ] }),
@@ -3809,6 +4220,21 @@ const BulkUpdater = () => {
3809
4220
  )
3810
4221
  }
3811
4222
  ),
4223
+ /* @__PURE__ */ jsx(
4224
+ BulkUpdatePreviewModal,
4225
+ {
4226
+ isOpen: showPreviewModal,
4227
+ onClose: () => setShowPreviewModal(false),
4228
+ onProceed: () => {
4229
+ setShowPreviewModal(false);
4230
+ handleOpenConfirmModal();
4231
+ },
4232
+ loading: previewLoading,
4233
+ previewData,
4234
+ attribute: selectedAttribute,
4235
+ targetValueDisplay: relationsMeta[selectedAttribute] ? selectedRelationDocId === "__clear__" ? "Clear / Unlink Relation" : relationOptions.find((o) => o.documentId === selectedRelationDocId)?.label || selectedRelationDocId || "(none)" : useRegex ? `Replace /${regexPattern}/g with "${attributeValue}"` : attributeValue
4236
+ }
4237
+ ),
3812
4238
  /* @__PURE__ */ jsx(
3813
4239
  ProcessingDashboardModal,
3814
4240
  {
@@ -3829,4 +4255,4 @@ export {
3829
4255
  getAvailableColumnsForCollection,
3830
4256
  getNestedValue
3831
4257
  };
3832
- //# sourceMappingURL=BulkUpdater-NpSxrH3b.mjs.map
4258
+ //# sourceMappingURL=BulkUpdater-Cg9utqzm.mjs.map