strapi-plugin-bulk-updater 1.2.9 → 1.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{BulkUpdater-NpSxrH3b.mjs → BulkUpdater-B_COVQmo.mjs} +473 -34
- package/dist/_chunks/BulkUpdater-B_COVQmo.mjs.map +1 -0
- package/dist/_chunks/{BulkUpdater-Q4rX3L5w.js → BulkUpdater-DS6gm_qd.js} +472 -33
- package/dist/_chunks/BulkUpdater-DS6gm_qd.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +270 -12
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +270 -12
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/_chunks/BulkUpdater-NpSxrH3b.mjs.map +0 -1
- package/dist/_chunks/BulkUpdater-Q4rX3L5w.js.map +0 -1
|
@@ -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 = () => {
|
|
@@ -1459,10 +1786,13 @@ const BulkUpdater = () => {
|
|
|
1459
1786
|
}
|
|
1460
1787
|
}
|
|
1461
1788
|
} catch (err) {
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1789
|
+
const isAborted = err?.name === "AbortError" || err?.name === "CanceledError" || err?.code === "ERR_CANCELED" || err?.message?.includes("aborted") || err?.message?.includes("canceled");
|
|
1790
|
+
if (!isAborted) {
|
|
1791
|
+
toggleNotification({
|
|
1792
|
+
type: "danger",
|
|
1793
|
+
message: err?.message || "Failed to load collections data"
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1466
1796
|
} finally {
|
|
1467
1797
|
setLoading(false);
|
|
1468
1798
|
}
|
|
@@ -1503,13 +1833,17 @@ const BulkUpdater = () => {
|
|
|
1503
1833
|
const res = await get(`/bulk-updater/collections/${colUid}/entries?${params.toString()}`);
|
|
1504
1834
|
if (res.data && (res.data.success || res.data.entries !== void 0)) {
|
|
1505
1835
|
const fetchedEntries = res.data.entries || [];
|
|
1836
|
+
const pageNum = res.data.pagination?.page ?? targetPage ?? 1;
|
|
1837
|
+
const pageSizeNum = res.data.pagination?.pageSize ?? size ?? defaultPageSize;
|
|
1838
|
+
const totalNum = res.data.pagination?.total !== void 0 ? res.data.pagination.total : fetchedEntries.length;
|
|
1839
|
+
const pageCountNum = res.data.pagination?.pageCount ?? Math.max(1, Math.ceil(totalNum / pageSizeNum));
|
|
1506
1840
|
setCollectionPages((prev) => ({
|
|
1507
1841
|
...prev,
|
|
1508
1842
|
[colUid]: {
|
|
1509
|
-
page:
|
|
1510
|
-
pageSize:
|
|
1511
|
-
total:
|
|
1512
|
-
pageCount:
|
|
1843
|
+
page: pageNum,
|
|
1844
|
+
pageSize: pageSizeNum,
|
|
1845
|
+
total: totalNum,
|
|
1846
|
+
pageCount: pageCountNum,
|
|
1513
1847
|
entries: fetchedEntries,
|
|
1514
1848
|
loading: false
|
|
1515
1849
|
}
|
|
@@ -1526,10 +1860,13 @@ const BulkUpdater = () => {
|
|
|
1526
1860
|
}
|
|
1527
1861
|
}
|
|
1528
1862
|
} catch (err) {
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1863
|
+
const isAborted = err?.name === "AbortError" || err?.name === "CanceledError" || err?.code === "ERR_CANCELED" || err?.message?.includes("aborted") || err?.message?.includes("canceled");
|
|
1864
|
+
if (!isAborted) {
|
|
1865
|
+
toggleNotification({
|
|
1866
|
+
type: "danger",
|
|
1867
|
+
message: `Failed to load entries for ${colUid}: ${err?.message || "Network error"}`
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1533
1870
|
setCollectionPages((prev) => ({
|
|
1534
1871
|
...prev,
|
|
1535
1872
|
[colUid]: {
|
|
@@ -1553,10 +1890,13 @@ const BulkUpdater = () => {
|
|
|
1553
1890
|
}
|
|
1554
1891
|
}
|
|
1555
1892
|
} catch (err) {
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1893
|
+
const isAborted = err?.name === "AbortError" || err?.name === "CanceledError" || err?.code === "ERR_CANCELED" || err?.message?.includes("aborted") || err?.message?.includes("canceled");
|
|
1894
|
+
if (!isAborted) {
|
|
1895
|
+
toggleNotification({
|
|
1896
|
+
type: "danger",
|
|
1897
|
+
message: err?.message || "Failed to fetch audit history."
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1560
1900
|
} finally {
|
|
1561
1901
|
setAuditLoading(false);
|
|
1562
1902
|
}
|
|
@@ -1893,6 +2233,56 @@ const BulkUpdater = () => {
|
|
|
1893
2233
|
}
|
|
1894
2234
|
setShowConfirmModal(true);
|
|
1895
2235
|
};
|
|
2236
|
+
const handleOpenPreviewModal = async () => {
|
|
2237
|
+
if (!selectedAttribute) {
|
|
2238
|
+
toggleNotification({
|
|
2239
|
+
type: "warning",
|
|
2240
|
+
message: "Please select an attribute from the dropdown"
|
|
2241
|
+
});
|
|
2242
|
+
return;
|
|
2243
|
+
}
|
|
2244
|
+
const targets = [];
|
|
2245
|
+
Object.keys(selectedEntries).forEach((key) => {
|
|
2246
|
+
if (selectedEntries[key]) {
|
|
2247
|
+
const parts = key.split(KEY_SEP);
|
|
2248
|
+
if (parts.length === 2) {
|
|
2249
|
+
targets.push({ uid: parts[0], documentId: parts[1] });
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
});
|
|
2253
|
+
if (targets.length === 0) {
|
|
2254
|
+
toggleNotification({
|
|
2255
|
+
type: "warning",
|
|
2256
|
+
message: "Please select at least one collection type or entry to preview"
|
|
2257
|
+
});
|
|
2258
|
+
return;
|
|
2259
|
+
}
|
|
2260
|
+
setShowPreviewModal(true);
|
|
2261
|
+
setPreviewLoading(true);
|
|
2262
|
+
try {
|
|
2263
|
+
const res = await post("/bulk-updater/preview", {
|
|
2264
|
+
attribute: selectedAttribute,
|
|
2265
|
+
value: attributeValue,
|
|
2266
|
+
selectedEntries: targets,
|
|
2267
|
+
isRegex: useRegex,
|
|
2268
|
+
regexPattern,
|
|
2269
|
+
publishOnApproval
|
|
2270
|
+
});
|
|
2271
|
+
if (res.data && res.data.success) {
|
|
2272
|
+
setPreviewData(res.data);
|
|
2273
|
+
} else {
|
|
2274
|
+
throw new Error(res.data?.error || "Failed to generate preview");
|
|
2275
|
+
}
|
|
2276
|
+
} catch (err) {
|
|
2277
|
+
toggleNotification({
|
|
2278
|
+
type: "danger",
|
|
2279
|
+
message: err.message || "Failed to fetch preview diffs"
|
|
2280
|
+
});
|
|
2281
|
+
setShowPreviewModal(false);
|
|
2282
|
+
} finally {
|
|
2283
|
+
setPreviewLoading(false);
|
|
2284
|
+
}
|
|
2285
|
+
};
|
|
1896
2286
|
const executeBatchWithMode = async (executionMode, forceImmediate = false) => {
|
|
1897
2287
|
const targets = [];
|
|
1898
2288
|
Object.keys(selectedEntries).forEach((key) => {
|
|
@@ -2481,22 +2871,40 @@ const BulkUpdater = () => {
|
|
|
2481
2871
|
onChange: (e) => setAttributeValue(e.target.value)
|
|
2482
2872
|
}
|
|
2483
2873
|
) }),
|
|
2484
|
-
/* @__PURE__ */
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2874
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
2875
|
+
/* @__PURE__ */ jsxs(
|
|
2876
|
+
Button,
|
|
2877
|
+
{
|
|
2878
|
+
startIcon: /* @__PURE__ */ jsx(Eye, {}),
|
|
2879
|
+
variant: "secondary",
|
|
2880
|
+
size: "L",
|
|
2881
|
+
onClick: handleOpenPreviewModal,
|
|
2882
|
+
loading: previewLoading,
|
|
2883
|
+
disabled: loading || totalSelectedCount === 0 || !selectedAttribute,
|
|
2884
|
+
children: [
|
|
2885
|
+
"Preview Changes (",
|
|
2886
|
+
totalSelectedCount,
|
|
2887
|
+
")"
|
|
2888
|
+
]
|
|
2889
|
+
}
|
|
2890
|
+
),
|
|
2891
|
+
/* @__PURE__ */ jsxs(
|
|
2892
|
+
Button,
|
|
2893
|
+
{
|
|
2894
|
+
startIcon: /* @__PURE__ */ jsx(Play, {}),
|
|
2895
|
+
variant: "default",
|
|
2896
|
+
size: "L",
|
|
2897
|
+
onClick: handleOpenConfirmModal,
|
|
2898
|
+
loading: updating,
|
|
2899
|
+
disabled: loading || totalSelectedCount === 0 || !selectedAttribute,
|
|
2900
|
+
children: [
|
|
2901
|
+
"Update Selected (",
|
|
2902
|
+
totalSelectedCount,
|
|
2903
|
+
")"
|
|
2904
|
+
]
|
|
2905
|
+
}
|
|
2906
|
+
)
|
|
2907
|
+
] })
|
|
2500
2908
|
] }),
|
|
2501
2909
|
/* @__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
2910
|
/* @__PURE__ */ jsx(Flex, { gap: 2, alignItems: "center", children: /* @__PURE__ */ jsx(
|
|
@@ -3673,6 +4081,22 @@ const BulkUpdater = () => {
|
|
|
3673
4081
|
children: publishOnApproval ? "Publish Immediately" : "Keep as Draft"
|
|
3674
4082
|
}
|
|
3675
4083
|
)
|
|
4084
|
+
] }),
|
|
4085
|
+
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginTop: 2, paddingTop: 2, style: { borderTop: "1px solid #eaeaef" }, children: [
|
|
4086
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Need to inspect before & after values?" }),
|
|
4087
|
+
/* @__PURE__ */ jsx(
|
|
4088
|
+
Button,
|
|
4089
|
+
{
|
|
4090
|
+
variant: "secondary",
|
|
4091
|
+
size: "S",
|
|
4092
|
+
startIcon: /* @__PURE__ */ jsx(Eye, {}),
|
|
4093
|
+
onClick: () => {
|
|
4094
|
+
setShowConfirmModal(false);
|
|
4095
|
+
handleOpenPreviewModal();
|
|
4096
|
+
},
|
|
4097
|
+
children: "Open Change Preview"
|
|
4098
|
+
}
|
|
4099
|
+
)
|
|
3676
4100
|
] })
|
|
3677
4101
|
] })
|
|
3678
4102
|
] }),
|
|
@@ -3809,6 +4233,21 @@ const BulkUpdater = () => {
|
|
|
3809
4233
|
)
|
|
3810
4234
|
}
|
|
3811
4235
|
),
|
|
4236
|
+
/* @__PURE__ */ jsx(
|
|
4237
|
+
BulkUpdatePreviewModal,
|
|
4238
|
+
{
|
|
4239
|
+
isOpen: showPreviewModal,
|
|
4240
|
+
onClose: () => setShowPreviewModal(false),
|
|
4241
|
+
onProceed: () => {
|
|
4242
|
+
setShowPreviewModal(false);
|
|
4243
|
+
handleOpenConfirmModal();
|
|
4244
|
+
},
|
|
4245
|
+
loading: previewLoading,
|
|
4246
|
+
previewData,
|
|
4247
|
+
attribute: selectedAttribute,
|
|
4248
|
+
targetValueDisplay: relationsMeta[selectedAttribute] ? selectedRelationDocId === "__clear__" ? "Clear / Unlink Relation" : relationOptions.find((o) => o.documentId === selectedRelationDocId)?.label || selectedRelationDocId || "(none)" : useRegex ? `Replace /${regexPattern}/g with "${attributeValue}"` : attributeValue
|
|
4249
|
+
}
|
|
4250
|
+
),
|
|
3812
4251
|
/* @__PURE__ */ jsx(
|
|
3813
4252
|
ProcessingDashboardModal,
|
|
3814
4253
|
{
|
|
@@ -3829,4 +4268,4 @@ export {
|
|
|
3829
4268
|
getAvailableColumnsForCollection,
|
|
3830
4269
|
getNestedValue
|
|
3831
4270
|
};
|
|
3832
|
-
//# sourceMappingURL=BulkUpdater-
|
|
4271
|
+
//# sourceMappingURL=BulkUpdater-B_COVQmo.mjs.map
|