strapi-plugin-bulk-updater 1.5.7 → 1.5.9
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-KtGgE0LO.js → BulkUpdater-C0uR_ORS.js} +186 -98
- package/dist/_chunks/BulkUpdater-C0uR_ORS.js.map +1 -0
- package/dist/_chunks/{BulkUpdater-Ci_Uojtf.mjs → BulkUpdater-RWXTJOa6.mjs} +186 -98
- package/dist/_chunks/BulkUpdater-RWXTJOa6.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +364 -348
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +364 -348
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/_chunks/BulkUpdater-Ci_Uojtf.mjs.map +0 -1
- package/dist/_chunks/BulkUpdater-KtGgE0LO.js.map +0 -1
|
@@ -136,12 +136,99 @@ function extractDocId(row) {
|
|
|
136
136
|
}
|
|
137
137
|
return "";
|
|
138
138
|
}
|
|
139
|
+
function getEntryLifecycleStatus(entry, col, pendingBatches = []) {
|
|
140
|
+
const isPendingApproval = pendingBatches.some((b) => {
|
|
141
|
+
if (b.status !== "pending_approval") return false;
|
|
142
|
+
const targets = b.payload?.selectedEntries || [];
|
|
143
|
+
return targets.some((t) => entry.documentId && t.documentId === entry.documentId || String(t.documentId) === String(entry.id));
|
|
144
|
+
});
|
|
145
|
+
if (isPendingApproval) {
|
|
146
|
+
return {
|
|
147
|
+
status: "pending_review",
|
|
148
|
+
label: "Pending Review",
|
|
149
|
+
badgeColor: "warning100",
|
|
150
|
+
textColor: "warning700"
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (col && col.draftAndPublish === false) {
|
|
154
|
+
return {
|
|
155
|
+
status: "published",
|
|
156
|
+
label: "Published",
|
|
157
|
+
badgeColor: "success100",
|
|
158
|
+
textColor: "success700"
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
if (entry.status === "modified") {
|
|
162
|
+
return {
|
|
163
|
+
status: "modified",
|
|
164
|
+
label: "Modified",
|
|
165
|
+
badgeColor: "primary100",
|
|
166
|
+
textColor: "primary700"
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
if (entry.status === "draft") {
|
|
170
|
+
return {
|
|
171
|
+
status: "draft",
|
|
172
|
+
label: "Draft",
|
|
173
|
+
badgeColor: "neutral150",
|
|
174
|
+
textColor: "neutral700"
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if (entry.status === "published") {
|
|
178
|
+
return {
|
|
179
|
+
status: "published",
|
|
180
|
+
label: "Published",
|
|
181
|
+
badgeColor: "success100",
|
|
182
|
+
textColor: "success700"
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (entry.status === "unknown") {
|
|
186
|
+
return {
|
|
187
|
+
status: "unknown",
|
|
188
|
+
label: "Unknown",
|
|
189
|
+
badgeColor: "neutral200",
|
|
190
|
+
textColor: "neutral600"
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (!entry.documentId && !entry.id && !entry.slug) {
|
|
194
|
+
return {
|
|
195
|
+
status: "unknown",
|
|
196
|
+
label: "Unknown",
|
|
197
|
+
badgeColor: "neutral200",
|
|
198
|
+
textColor: "neutral600"
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
if (entry.publishedAt) {
|
|
202
|
+
if (entry.updatedAt && new Date(entry.updatedAt).getTime() > new Date(entry.publishedAt).getTime()) {
|
|
203
|
+
return {
|
|
204
|
+
status: "modified",
|
|
205
|
+
label: "Modified",
|
|
206
|
+
badgeColor: "primary100",
|
|
207
|
+
textColor: "primary700"
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
status: "published",
|
|
212
|
+
label: "Published",
|
|
213
|
+
badgeColor: "success100",
|
|
214
|
+
textColor: "success700"
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
status: "draft",
|
|
219
|
+
label: "Draft",
|
|
220
|
+
badgeColor: "neutral150",
|
|
221
|
+
textColor: "neutral700"
|
|
222
|
+
};
|
|
223
|
+
}
|
|
139
224
|
function CsvManagerTab() {
|
|
140
225
|
const { get, post } = useFetchClient();
|
|
141
226
|
const { toggleNotification } = useNotification();
|
|
142
227
|
const [collections, setCollections] = useState([]);
|
|
143
228
|
const [loadingCollections, setLoadingCollections] = useState(true);
|
|
144
229
|
const [selectedUid, setSelectedUid] = useState("");
|
|
230
|
+
const [collectionEntries, setCollectionEntries] = useState([]);
|
|
231
|
+
const [pendingBatches, setPendingBatches] = useState([]);
|
|
145
232
|
const [exportLimit, setExportLimit] = useState(0);
|
|
146
233
|
const [exportOnlyViolations, setExportOnlyViolations] = useState(false);
|
|
147
234
|
const [rules, setRules] = useState([]);
|
|
@@ -170,17 +257,25 @@ function CsvManagerTab() {
|
|
|
170
257
|
const fetchInitialData = async () => {
|
|
171
258
|
try {
|
|
172
259
|
setLoadingCollections(true);
|
|
173
|
-
const [modelsRes, rulesRes] = await Promise.all([
|
|
260
|
+
const [modelsRes, rulesRes, batchesRes] = await Promise.all([
|
|
174
261
|
get("/bulk-updater/models"),
|
|
175
|
-
get("/bulk-updater/validation-rules")
|
|
262
|
+
get("/bulk-updater/validation-rules"),
|
|
263
|
+
get("/bulk-updater/pending-batches").catch(() => ({ data: { batches: [] } }))
|
|
176
264
|
]);
|
|
177
265
|
if (modelsRes.data?.executionWindow) {
|
|
178
266
|
setExecutionWindow(modelsRes.data.executionWindow);
|
|
179
267
|
}
|
|
268
|
+
if (batchesRes.data?.batches) {
|
|
269
|
+
setPendingBatches(batchesRes.data.batches);
|
|
270
|
+
}
|
|
271
|
+
let loadedCollections = [];
|
|
180
272
|
if (modelsRes.data?.collections) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
273
|
+
loadedCollections = modelsRes.data.collections;
|
|
274
|
+
setCollections(loadedCollections);
|
|
275
|
+
if (loadedCollections.length > 0) {
|
|
276
|
+
const firstUid = loadedCollections[0].uid;
|
|
277
|
+
setSelectedUid(firstUid);
|
|
278
|
+
fetchAndEnrichEntries(firstUid, loadedCollections, batchesRes.data?.batches || []);
|
|
184
279
|
}
|
|
185
280
|
}
|
|
186
281
|
if (rulesRes.data?.rules) {
|
|
@@ -199,6 +294,67 @@ function CsvManagerTab() {
|
|
|
199
294
|
setLoadingCollections(false);
|
|
200
295
|
}
|
|
201
296
|
};
|
|
297
|
+
const fetchAndEnrichEntries = async (colUid, cols = collections, batches = pendingBatches) => {
|
|
298
|
+
if (!colUid) return [];
|
|
299
|
+
try {
|
|
300
|
+
const res = await get(`/bulk-updater/collections/${colUid}/entries?page=1&pageSize=500`);
|
|
301
|
+
if (res.data && (res.data.success || res.data.entries !== void 0)) {
|
|
302
|
+
const fetchedEntries = res.data.entries || [];
|
|
303
|
+
const col = (cols || []).find((c) => c.uid === colUid) || null;
|
|
304
|
+
const enrichedEntries = fetchedEntries.map((entry) => {
|
|
305
|
+
if (!entry.status) {
|
|
306
|
+
const lifecycle = getEntryLifecycleStatus(entry, col, batches);
|
|
307
|
+
return {
|
|
308
|
+
...entry,
|
|
309
|
+
status: lifecycle.status,
|
|
310
|
+
publishedAt: entry.publishedAt ?? (lifecycle.status === "published" ? entry.updatedAt || null : null)
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
return entry;
|
|
314
|
+
});
|
|
315
|
+
setCollectionEntries(enrichedEntries);
|
|
316
|
+
return enrichedEntries;
|
|
317
|
+
}
|
|
318
|
+
} catch (err) {
|
|
319
|
+
if (isAbortError(err)) return [];
|
|
320
|
+
}
|
|
321
|
+
return [];
|
|
322
|
+
};
|
|
323
|
+
const enrichCsvRowsWithLifecycle = (rows, knownEntries = collectionEntries) => {
|
|
324
|
+
if (!rows || rows.length === 0) return rows;
|
|
325
|
+
const entryByDocId = /* @__PURE__ */ new Map();
|
|
326
|
+
for (const e of knownEntries) {
|
|
327
|
+
if (e.documentId) entryByDocId.set(String(e.documentId), e);
|
|
328
|
+
if (e.id) entryByDocId.set(String(e.id), e);
|
|
329
|
+
}
|
|
330
|
+
return rows.map((row) => {
|
|
331
|
+
const docId = extractDocId(row);
|
|
332
|
+
const matched = docId ? entryByDocId.get(docId) : void 0;
|
|
333
|
+
const existingStatus = row.status || row.Status;
|
|
334
|
+
const existingPubAt = row.publishedAt || row.published_at;
|
|
335
|
+
let status = existingStatus;
|
|
336
|
+
let publishedAt = existingPubAt;
|
|
337
|
+
if (!status && matched?.status) {
|
|
338
|
+
status = matched.status;
|
|
339
|
+
}
|
|
340
|
+
if (!publishedAt && matched?.publishedAt) {
|
|
341
|
+
publishedAt = matched.publishedAt;
|
|
342
|
+
}
|
|
343
|
+
if (status || publishedAt) {
|
|
344
|
+
return {
|
|
345
|
+
...row,
|
|
346
|
+
...status ? { status } : {},
|
|
347
|
+
...publishedAt ? { publishedAt } : {}
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
return row;
|
|
351
|
+
});
|
|
352
|
+
};
|
|
353
|
+
useEffect(() => {
|
|
354
|
+
if (selectedUid) {
|
|
355
|
+
fetchAndEnrichEntries(selectedUid);
|
|
356
|
+
}
|
|
357
|
+
}, [selectedUid]);
|
|
202
358
|
const handleDownloadTemplate = async () => {
|
|
203
359
|
if (!selectedUid) return;
|
|
204
360
|
try {
|
|
@@ -221,6 +377,7 @@ function CsvManagerTab() {
|
|
|
221
377
|
const handleExportCollection = async () => {
|
|
222
378
|
if (!selectedUid) return;
|
|
223
379
|
try {
|
|
380
|
+
await fetchAndEnrichEntries(selectedUid);
|
|
224
381
|
const res = await get(`/bulk-updater/csv/export/${selectedUid}?limit=${exportLimit}`);
|
|
225
382
|
const csvStr = res.data?.csvContent || (typeof res.data === "string" ? res.data : "");
|
|
226
383
|
const filename = res.data?.filename || `${selectedUid.split(".").pop()}_export.csv`;
|
|
@@ -287,7 +444,8 @@ function CsvManagerTab() {
|
|
|
287
444
|
setCsvRawText(text);
|
|
288
445
|
try {
|
|
289
446
|
const records = parseCsv(text);
|
|
290
|
-
|
|
447
|
+
const enriched = enrichCsvRowsWithLifecycle(records, collectionEntries);
|
|
448
|
+
setAllParsedRecords(enriched);
|
|
291
449
|
setPreviewPage(1);
|
|
292
450
|
} catch (err) {
|
|
293
451
|
setAllParsedRecords([]);
|
|
@@ -297,7 +455,12 @@ function CsvManagerTab() {
|
|
|
297
455
|
};
|
|
298
456
|
const handleExecuteImport = async () => {
|
|
299
457
|
if (!selectedUid || allParsedRecords.length === 0) return;
|
|
300
|
-
|
|
458
|
+
let currentEntries = collectionEntries;
|
|
459
|
+
if (currentEntries.length === 0) {
|
|
460
|
+
currentEntries = await fetchAndEnrichEntries(selectedUid);
|
|
461
|
+
}
|
|
462
|
+
const enrichedRecords = enrichCsvRowsWithLifecycle(allParsedRecords, currentEntries);
|
|
463
|
+
const totalRows = enrichedRecords.length;
|
|
301
464
|
const CHUNK_SIZE = 100;
|
|
302
465
|
const totalChunks = Math.ceil(totalRows / CHUNK_SIZE);
|
|
303
466
|
const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
|
|
@@ -323,7 +486,7 @@ function CsvManagerTab() {
|
|
|
323
486
|
for (let chunkIdx = 0; chunkIdx < totalChunks; chunkIdx++) {
|
|
324
487
|
const startIdx = chunkIdx * CHUNK_SIZE;
|
|
325
488
|
const endIdx = Math.min(startIdx + CHUNK_SIZE, totalRows);
|
|
326
|
-
const chunkRows =
|
|
489
|
+
const chunkRows = enrichedRecords.slice(startIdx, endIdx);
|
|
327
490
|
const isFirst = chunkIdx === 0;
|
|
328
491
|
const isLast = chunkIdx === totalChunks - 1;
|
|
329
492
|
const startRowNumber = startIdx + 2;
|
|
@@ -391,9 +554,14 @@ function CsvManagerTab() {
|
|
|
391
554
|
if (!selectedUid || allParsedRecords.length === 0) return;
|
|
392
555
|
try {
|
|
393
556
|
setPreflightLoading(true);
|
|
557
|
+
let currentEntries = collectionEntries;
|
|
558
|
+
if (currentEntries.length === 0) {
|
|
559
|
+
currentEntries = await fetchAndEnrichEntries(selectedUid);
|
|
560
|
+
}
|
|
561
|
+
const enrichedRecords = enrichCsvRowsWithLifecycle(allParsedRecords, currentEntries);
|
|
394
562
|
const res = await post("/bulk-updater/csv/validate-preflight", {
|
|
395
563
|
uid: selectedUid,
|
|
396
|
-
rows:
|
|
564
|
+
rows: enrichedRecords,
|
|
397
565
|
mode: importMode
|
|
398
566
|
});
|
|
399
567
|
if (res.data && res.data.success) {
|
|
@@ -434,9 +602,14 @@ function CsvManagerTab() {
|
|
|
434
602
|
}
|
|
435
603
|
try {
|
|
436
604
|
setSubmittingBatch(true);
|
|
605
|
+
let currentEntries = collectionEntries;
|
|
606
|
+
if (currentEntries.length === 0) {
|
|
607
|
+
currentEntries = await fetchAndEnrichEntries(selectedUid);
|
|
608
|
+
}
|
|
609
|
+
const enrichedRecords = enrichCsvRowsWithLifecycle(allParsedRecords, currentEntries);
|
|
437
610
|
const res = await post("/bulk-updater/csv/submit-batch", {
|
|
438
611
|
uid: selectedUid,
|
|
439
|
-
rows:
|
|
612
|
+
rows: enrichedRecords,
|
|
440
613
|
executionMode,
|
|
441
614
|
makerNotes: makerNotesInput,
|
|
442
615
|
forceImmediate,
|
|
@@ -2853,91 +3026,6 @@ const CheckerReviewModal = ({
|
|
|
2853
3026
|
}
|
|
2854
3027
|
);
|
|
2855
3028
|
};
|
|
2856
|
-
function getEntryLifecycleStatus(entry, col, pendingBatches = []) {
|
|
2857
|
-
const isPendingApproval = pendingBatches.some((b) => {
|
|
2858
|
-
if (b.status !== "pending_approval") return false;
|
|
2859
|
-
const targets = b.payload?.selectedEntries || [];
|
|
2860
|
-
return targets.some((t) => entry.documentId && t.documentId === entry.documentId || String(t.documentId) === String(entry.id));
|
|
2861
|
-
});
|
|
2862
|
-
if (isPendingApproval) {
|
|
2863
|
-
return {
|
|
2864
|
-
status: "pending_review",
|
|
2865
|
-
label: "Pending Review",
|
|
2866
|
-
badgeColor: "warning100",
|
|
2867
|
-
textColor: "warning700"
|
|
2868
|
-
};
|
|
2869
|
-
}
|
|
2870
|
-
if (col && col.draftAndPublish === false) {
|
|
2871
|
-
return {
|
|
2872
|
-
status: "published",
|
|
2873
|
-
label: "Published",
|
|
2874
|
-
badgeColor: "success100",
|
|
2875
|
-
textColor: "success700"
|
|
2876
|
-
};
|
|
2877
|
-
}
|
|
2878
|
-
if (entry.status === "modified") {
|
|
2879
|
-
return {
|
|
2880
|
-
status: "modified",
|
|
2881
|
-
label: "Modified",
|
|
2882
|
-
badgeColor: "primary100",
|
|
2883
|
-
textColor: "primary700"
|
|
2884
|
-
};
|
|
2885
|
-
}
|
|
2886
|
-
if (entry.status === "draft") {
|
|
2887
|
-
return {
|
|
2888
|
-
status: "draft",
|
|
2889
|
-
label: "Draft",
|
|
2890
|
-
badgeColor: "neutral150",
|
|
2891
|
-
textColor: "neutral700"
|
|
2892
|
-
};
|
|
2893
|
-
}
|
|
2894
|
-
if (entry.status === "published") {
|
|
2895
|
-
return {
|
|
2896
|
-
status: "published",
|
|
2897
|
-
label: "Published",
|
|
2898
|
-
badgeColor: "success100",
|
|
2899
|
-
textColor: "success700"
|
|
2900
|
-
};
|
|
2901
|
-
}
|
|
2902
|
-
if (entry.status === "unknown") {
|
|
2903
|
-
return {
|
|
2904
|
-
status: "unknown",
|
|
2905
|
-
label: "Unknown",
|
|
2906
|
-
badgeColor: "neutral200",
|
|
2907
|
-
textColor: "neutral600"
|
|
2908
|
-
};
|
|
2909
|
-
}
|
|
2910
|
-
if (!entry.documentId && !entry.id && !entry.slug) {
|
|
2911
|
-
return {
|
|
2912
|
-
status: "unknown",
|
|
2913
|
-
label: "Unknown",
|
|
2914
|
-
badgeColor: "neutral200",
|
|
2915
|
-
textColor: "neutral600"
|
|
2916
|
-
};
|
|
2917
|
-
}
|
|
2918
|
-
if (entry.publishedAt) {
|
|
2919
|
-
if (entry.updatedAt && new Date(entry.updatedAt).getTime() > new Date(entry.publishedAt).getTime()) {
|
|
2920
|
-
return {
|
|
2921
|
-
status: "modified",
|
|
2922
|
-
label: "Modified",
|
|
2923
|
-
badgeColor: "primary100",
|
|
2924
|
-
textColor: "primary700"
|
|
2925
|
-
};
|
|
2926
|
-
}
|
|
2927
|
-
return {
|
|
2928
|
-
status: "published",
|
|
2929
|
-
label: "Published",
|
|
2930
|
-
badgeColor: "success100",
|
|
2931
|
-
textColor: "success700"
|
|
2932
|
-
};
|
|
2933
|
-
}
|
|
2934
|
-
return {
|
|
2935
|
-
status: "draft",
|
|
2936
|
-
label: "Draft",
|
|
2937
|
-
badgeColor: "neutral150",
|
|
2938
|
-
textColor: "neutral700"
|
|
2939
|
-
};
|
|
2940
|
-
}
|
|
2941
3029
|
function parseDynamicZonePath(path) {
|
|
2942
3030
|
if (!path) return { cleanPath: "", rootKey: "", subPath: "" };
|
|
2943
3031
|
const bracketMatch = path.match(/^([^.[]+)\[([^\]]+)\]\.(.+)$/);
|
|
@@ -4461,8 +4549,8 @@ const BulkUpdater = () => {
|
|
|
4461
4549
|
const cachedEntry = colPage?.entries?.find((e) => e.documentId === docId);
|
|
4462
4550
|
if (cachedEntry) {
|
|
4463
4551
|
if (cachedEntry.status) targetObj.status = cachedEntry.status;
|
|
4464
|
-
if (cachedEntry.strapi_stage) targetObj.strapi_stage = cachedEntry.strapi_stage;
|
|
4465
4552
|
if (cachedEntry.publishedAt) targetObj.publishedAt = cachedEntry.publishedAt;
|
|
4553
|
+
if (cachedEntry.locale) targetObj.locale = cachedEntry.locale;
|
|
4466
4554
|
}
|
|
4467
4555
|
targets.push(targetObj);
|
|
4468
4556
|
}
|
|
@@ -4519,8 +4607,8 @@ const BulkUpdater = () => {
|
|
|
4519
4607
|
const cachedEntry = colPage?.entries?.find((e) => e.documentId === docId);
|
|
4520
4608
|
if (cachedEntry) {
|
|
4521
4609
|
if (cachedEntry.status) targetObj.status = cachedEntry.status;
|
|
4522
|
-
if (cachedEntry.strapi_stage) targetObj.strapi_stage = cachedEntry.strapi_stage;
|
|
4523
4610
|
if (cachedEntry.publishedAt) targetObj.publishedAt = cachedEntry.publishedAt;
|
|
4611
|
+
if (cachedEntry.locale) targetObj.locale = cachedEntry.locale;
|
|
4524
4612
|
}
|
|
4525
4613
|
targets.push(targetObj);
|
|
4526
4614
|
}
|
|
@@ -7533,4 +7621,4 @@ export {
|
|
|
7533
7621
|
getSortOptionsForCollection,
|
|
7534
7622
|
parseDynamicZonePath
|
|
7535
7623
|
};
|
|
7536
|
-
//# sourceMappingURL=BulkUpdater-
|
|
7624
|
+
//# sourceMappingURL=BulkUpdater-RWXTJOa6.mjs.map
|