strapi-plugin-bulk-updater 1.5.8 → 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-ezjrkUaf.js → BulkUpdater-C0uR_ORS.js} +184 -96
- package/dist/_chunks/BulkUpdater-C0uR_ORS.js.map +1 -0
- package/dist/_chunks/{BulkUpdater-B58N9HHk.mjs → BulkUpdater-RWXTJOa6.mjs} +184 -96
- 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 +68 -26
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +68 -26
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/_chunks/BulkUpdater-B58N9HHk.mjs.map +0 -1
- package/dist/_chunks/BulkUpdater-ezjrkUaf.js.map +0 -1
|
@@ -140,12 +140,99 @@ function extractDocId(row) {
|
|
|
140
140
|
}
|
|
141
141
|
return "";
|
|
142
142
|
}
|
|
143
|
+
function getEntryLifecycleStatus(entry, col, pendingBatches = []) {
|
|
144
|
+
const isPendingApproval = pendingBatches.some((b) => {
|
|
145
|
+
if (b.status !== "pending_approval") return false;
|
|
146
|
+
const targets = b.payload?.selectedEntries || [];
|
|
147
|
+
return targets.some((t) => entry.documentId && t.documentId === entry.documentId || String(t.documentId) === String(entry.id));
|
|
148
|
+
});
|
|
149
|
+
if (isPendingApproval) {
|
|
150
|
+
return {
|
|
151
|
+
status: "pending_review",
|
|
152
|
+
label: "Pending Review",
|
|
153
|
+
badgeColor: "warning100",
|
|
154
|
+
textColor: "warning700"
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (col && col.draftAndPublish === false) {
|
|
158
|
+
return {
|
|
159
|
+
status: "published",
|
|
160
|
+
label: "Published",
|
|
161
|
+
badgeColor: "success100",
|
|
162
|
+
textColor: "success700"
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (entry.status === "modified") {
|
|
166
|
+
return {
|
|
167
|
+
status: "modified",
|
|
168
|
+
label: "Modified",
|
|
169
|
+
badgeColor: "primary100",
|
|
170
|
+
textColor: "primary700"
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (entry.status === "draft") {
|
|
174
|
+
return {
|
|
175
|
+
status: "draft",
|
|
176
|
+
label: "Draft",
|
|
177
|
+
badgeColor: "neutral150",
|
|
178
|
+
textColor: "neutral700"
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (entry.status === "published") {
|
|
182
|
+
return {
|
|
183
|
+
status: "published",
|
|
184
|
+
label: "Published",
|
|
185
|
+
badgeColor: "success100",
|
|
186
|
+
textColor: "success700"
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
if (entry.status === "unknown") {
|
|
190
|
+
return {
|
|
191
|
+
status: "unknown",
|
|
192
|
+
label: "Unknown",
|
|
193
|
+
badgeColor: "neutral200",
|
|
194
|
+
textColor: "neutral600"
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
if (!entry.documentId && !entry.id && !entry.slug) {
|
|
198
|
+
return {
|
|
199
|
+
status: "unknown",
|
|
200
|
+
label: "Unknown",
|
|
201
|
+
badgeColor: "neutral200",
|
|
202
|
+
textColor: "neutral600"
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
if (entry.publishedAt) {
|
|
206
|
+
if (entry.updatedAt && new Date(entry.updatedAt).getTime() > new Date(entry.publishedAt).getTime()) {
|
|
207
|
+
return {
|
|
208
|
+
status: "modified",
|
|
209
|
+
label: "Modified",
|
|
210
|
+
badgeColor: "primary100",
|
|
211
|
+
textColor: "primary700"
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
status: "published",
|
|
216
|
+
label: "Published",
|
|
217
|
+
badgeColor: "success100",
|
|
218
|
+
textColor: "success700"
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
status: "draft",
|
|
223
|
+
label: "Draft",
|
|
224
|
+
badgeColor: "neutral150",
|
|
225
|
+
textColor: "neutral700"
|
|
226
|
+
};
|
|
227
|
+
}
|
|
143
228
|
function CsvManagerTab() {
|
|
144
229
|
const { get, post } = admin.useFetchClient();
|
|
145
230
|
const { toggleNotification } = admin.useNotification();
|
|
146
231
|
const [collections, setCollections] = React.useState([]);
|
|
147
232
|
const [loadingCollections, setLoadingCollections] = React.useState(true);
|
|
148
233
|
const [selectedUid, setSelectedUid] = React.useState("");
|
|
234
|
+
const [collectionEntries, setCollectionEntries] = React.useState([]);
|
|
235
|
+
const [pendingBatches, setPendingBatches] = React.useState([]);
|
|
149
236
|
const [exportLimit, setExportLimit] = React.useState(0);
|
|
150
237
|
const [exportOnlyViolations, setExportOnlyViolations] = React.useState(false);
|
|
151
238
|
const [rules, setRules] = React.useState([]);
|
|
@@ -174,17 +261,25 @@ function CsvManagerTab() {
|
|
|
174
261
|
const fetchInitialData = async () => {
|
|
175
262
|
try {
|
|
176
263
|
setLoadingCollections(true);
|
|
177
|
-
const [modelsRes, rulesRes] = await Promise.all([
|
|
264
|
+
const [modelsRes, rulesRes, batchesRes] = await Promise.all([
|
|
178
265
|
get("/bulk-updater/models"),
|
|
179
|
-
get("/bulk-updater/validation-rules")
|
|
266
|
+
get("/bulk-updater/validation-rules"),
|
|
267
|
+
get("/bulk-updater/pending-batches").catch(() => ({ data: { batches: [] } }))
|
|
180
268
|
]);
|
|
181
269
|
if (modelsRes.data?.executionWindow) {
|
|
182
270
|
setExecutionWindow(modelsRes.data.executionWindow);
|
|
183
271
|
}
|
|
272
|
+
if (batchesRes.data?.batches) {
|
|
273
|
+
setPendingBatches(batchesRes.data.batches);
|
|
274
|
+
}
|
|
275
|
+
let loadedCollections = [];
|
|
184
276
|
if (modelsRes.data?.collections) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
277
|
+
loadedCollections = modelsRes.data.collections;
|
|
278
|
+
setCollections(loadedCollections);
|
|
279
|
+
if (loadedCollections.length > 0) {
|
|
280
|
+
const firstUid = loadedCollections[0].uid;
|
|
281
|
+
setSelectedUid(firstUid);
|
|
282
|
+
fetchAndEnrichEntries(firstUid, loadedCollections, batchesRes.data?.batches || []);
|
|
188
283
|
}
|
|
189
284
|
}
|
|
190
285
|
if (rulesRes.data?.rules) {
|
|
@@ -203,6 +298,67 @@ function CsvManagerTab() {
|
|
|
203
298
|
setLoadingCollections(false);
|
|
204
299
|
}
|
|
205
300
|
};
|
|
301
|
+
const fetchAndEnrichEntries = async (colUid, cols = collections, batches = pendingBatches) => {
|
|
302
|
+
if (!colUid) return [];
|
|
303
|
+
try {
|
|
304
|
+
const res = await get(`/bulk-updater/collections/${colUid}/entries?page=1&pageSize=500`);
|
|
305
|
+
if (res.data && (res.data.success || res.data.entries !== void 0)) {
|
|
306
|
+
const fetchedEntries = res.data.entries || [];
|
|
307
|
+
const col = (cols || []).find((c) => c.uid === colUid) || null;
|
|
308
|
+
const enrichedEntries = fetchedEntries.map((entry) => {
|
|
309
|
+
if (!entry.status) {
|
|
310
|
+
const lifecycle = getEntryLifecycleStatus(entry, col, batches);
|
|
311
|
+
return {
|
|
312
|
+
...entry,
|
|
313
|
+
status: lifecycle.status,
|
|
314
|
+
publishedAt: entry.publishedAt ?? (lifecycle.status === "published" ? entry.updatedAt || null : null)
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
return entry;
|
|
318
|
+
});
|
|
319
|
+
setCollectionEntries(enrichedEntries);
|
|
320
|
+
return enrichedEntries;
|
|
321
|
+
}
|
|
322
|
+
} catch (err) {
|
|
323
|
+
if (ValidationRulesTab.isAbortError(err)) return [];
|
|
324
|
+
}
|
|
325
|
+
return [];
|
|
326
|
+
};
|
|
327
|
+
const enrichCsvRowsWithLifecycle = (rows, knownEntries = collectionEntries) => {
|
|
328
|
+
if (!rows || rows.length === 0) return rows;
|
|
329
|
+
const entryByDocId = /* @__PURE__ */ new Map();
|
|
330
|
+
for (const e of knownEntries) {
|
|
331
|
+
if (e.documentId) entryByDocId.set(String(e.documentId), e);
|
|
332
|
+
if (e.id) entryByDocId.set(String(e.id), e);
|
|
333
|
+
}
|
|
334
|
+
return rows.map((row) => {
|
|
335
|
+
const docId = extractDocId(row);
|
|
336
|
+
const matched = docId ? entryByDocId.get(docId) : void 0;
|
|
337
|
+
const existingStatus = row.status || row.Status;
|
|
338
|
+
const existingPubAt = row.publishedAt || row.published_at;
|
|
339
|
+
let status = existingStatus;
|
|
340
|
+
let publishedAt = existingPubAt;
|
|
341
|
+
if (!status && matched?.status) {
|
|
342
|
+
status = matched.status;
|
|
343
|
+
}
|
|
344
|
+
if (!publishedAt && matched?.publishedAt) {
|
|
345
|
+
publishedAt = matched.publishedAt;
|
|
346
|
+
}
|
|
347
|
+
if (status || publishedAt) {
|
|
348
|
+
return {
|
|
349
|
+
...row,
|
|
350
|
+
...status ? { status } : {},
|
|
351
|
+
...publishedAt ? { publishedAt } : {}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
return row;
|
|
355
|
+
});
|
|
356
|
+
};
|
|
357
|
+
React.useEffect(() => {
|
|
358
|
+
if (selectedUid) {
|
|
359
|
+
fetchAndEnrichEntries(selectedUid);
|
|
360
|
+
}
|
|
361
|
+
}, [selectedUid]);
|
|
206
362
|
const handleDownloadTemplate = async () => {
|
|
207
363
|
if (!selectedUid) return;
|
|
208
364
|
try {
|
|
@@ -225,6 +381,7 @@ function CsvManagerTab() {
|
|
|
225
381
|
const handleExportCollection = async () => {
|
|
226
382
|
if (!selectedUid) return;
|
|
227
383
|
try {
|
|
384
|
+
await fetchAndEnrichEntries(selectedUid);
|
|
228
385
|
const res = await get(`/bulk-updater/csv/export/${selectedUid}?limit=${exportLimit}`);
|
|
229
386
|
const csvStr = res.data?.csvContent || (typeof res.data === "string" ? res.data : "");
|
|
230
387
|
const filename = res.data?.filename || `${selectedUid.split(".").pop()}_export.csv`;
|
|
@@ -291,7 +448,8 @@ function CsvManagerTab() {
|
|
|
291
448
|
setCsvRawText(text);
|
|
292
449
|
try {
|
|
293
450
|
const records = parseCsv(text);
|
|
294
|
-
|
|
451
|
+
const enriched = enrichCsvRowsWithLifecycle(records, collectionEntries);
|
|
452
|
+
setAllParsedRecords(enriched);
|
|
295
453
|
setPreviewPage(1);
|
|
296
454
|
} catch (err) {
|
|
297
455
|
setAllParsedRecords([]);
|
|
@@ -301,7 +459,12 @@ function CsvManagerTab() {
|
|
|
301
459
|
};
|
|
302
460
|
const handleExecuteImport = async () => {
|
|
303
461
|
if (!selectedUid || allParsedRecords.length === 0) return;
|
|
304
|
-
|
|
462
|
+
let currentEntries = collectionEntries;
|
|
463
|
+
if (currentEntries.length === 0) {
|
|
464
|
+
currentEntries = await fetchAndEnrichEntries(selectedUid);
|
|
465
|
+
}
|
|
466
|
+
const enrichedRecords = enrichCsvRowsWithLifecycle(allParsedRecords, currentEntries);
|
|
467
|
+
const totalRows = enrichedRecords.length;
|
|
305
468
|
const CHUNK_SIZE = 100;
|
|
306
469
|
const totalChunks = Math.ceil(totalRows / CHUNK_SIZE);
|
|
307
470
|
const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
|
|
@@ -327,7 +490,7 @@ function CsvManagerTab() {
|
|
|
327
490
|
for (let chunkIdx = 0; chunkIdx < totalChunks; chunkIdx++) {
|
|
328
491
|
const startIdx = chunkIdx * CHUNK_SIZE;
|
|
329
492
|
const endIdx = Math.min(startIdx + CHUNK_SIZE, totalRows);
|
|
330
|
-
const chunkRows =
|
|
493
|
+
const chunkRows = enrichedRecords.slice(startIdx, endIdx);
|
|
331
494
|
const isFirst = chunkIdx === 0;
|
|
332
495
|
const isLast = chunkIdx === totalChunks - 1;
|
|
333
496
|
const startRowNumber = startIdx + 2;
|
|
@@ -395,9 +558,14 @@ function CsvManagerTab() {
|
|
|
395
558
|
if (!selectedUid || allParsedRecords.length === 0) return;
|
|
396
559
|
try {
|
|
397
560
|
setPreflightLoading(true);
|
|
561
|
+
let currentEntries = collectionEntries;
|
|
562
|
+
if (currentEntries.length === 0) {
|
|
563
|
+
currentEntries = await fetchAndEnrichEntries(selectedUid);
|
|
564
|
+
}
|
|
565
|
+
const enrichedRecords = enrichCsvRowsWithLifecycle(allParsedRecords, currentEntries);
|
|
398
566
|
const res = await post("/bulk-updater/csv/validate-preflight", {
|
|
399
567
|
uid: selectedUid,
|
|
400
|
-
rows:
|
|
568
|
+
rows: enrichedRecords,
|
|
401
569
|
mode: importMode
|
|
402
570
|
});
|
|
403
571
|
if (res.data && res.data.success) {
|
|
@@ -438,9 +606,14 @@ function CsvManagerTab() {
|
|
|
438
606
|
}
|
|
439
607
|
try {
|
|
440
608
|
setSubmittingBatch(true);
|
|
609
|
+
let currentEntries = collectionEntries;
|
|
610
|
+
if (currentEntries.length === 0) {
|
|
611
|
+
currentEntries = await fetchAndEnrichEntries(selectedUid);
|
|
612
|
+
}
|
|
613
|
+
const enrichedRecords = enrichCsvRowsWithLifecycle(allParsedRecords, currentEntries);
|
|
441
614
|
const res = await post("/bulk-updater/csv/submit-batch", {
|
|
442
615
|
uid: selectedUid,
|
|
443
|
-
rows:
|
|
616
|
+
rows: enrichedRecords,
|
|
444
617
|
executionMode,
|
|
445
618
|
makerNotes: makerNotesInput,
|
|
446
619
|
forceImmediate,
|
|
@@ -2857,91 +3030,6 @@ const CheckerReviewModal = ({
|
|
|
2857
3030
|
}
|
|
2858
3031
|
);
|
|
2859
3032
|
};
|
|
2860
|
-
function getEntryLifecycleStatus(entry, col, pendingBatches = []) {
|
|
2861
|
-
const isPendingApproval = pendingBatches.some((b) => {
|
|
2862
|
-
if (b.status !== "pending_approval") return false;
|
|
2863
|
-
const targets = b.payload?.selectedEntries || [];
|
|
2864
|
-
return targets.some((t) => entry.documentId && t.documentId === entry.documentId || String(t.documentId) === String(entry.id));
|
|
2865
|
-
});
|
|
2866
|
-
if (isPendingApproval) {
|
|
2867
|
-
return {
|
|
2868
|
-
status: "pending_review",
|
|
2869
|
-
label: "Pending Review",
|
|
2870
|
-
badgeColor: "warning100",
|
|
2871
|
-
textColor: "warning700"
|
|
2872
|
-
};
|
|
2873
|
-
}
|
|
2874
|
-
if (col && col.draftAndPublish === false) {
|
|
2875
|
-
return {
|
|
2876
|
-
status: "published",
|
|
2877
|
-
label: "Published",
|
|
2878
|
-
badgeColor: "success100",
|
|
2879
|
-
textColor: "success700"
|
|
2880
|
-
};
|
|
2881
|
-
}
|
|
2882
|
-
if (entry.status === "modified") {
|
|
2883
|
-
return {
|
|
2884
|
-
status: "modified",
|
|
2885
|
-
label: "Modified",
|
|
2886
|
-
badgeColor: "primary100",
|
|
2887
|
-
textColor: "primary700"
|
|
2888
|
-
};
|
|
2889
|
-
}
|
|
2890
|
-
if (entry.status === "draft") {
|
|
2891
|
-
return {
|
|
2892
|
-
status: "draft",
|
|
2893
|
-
label: "Draft",
|
|
2894
|
-
badgeColor: "neutral150",
|
|
2895
|
-
textColor: "neutral700"
|
|
2896
|
-
};
|
|
2897
|
-
}
|
|
2898
|
-
if (entry.status === "published") {
|
|
2899
|
-
return {
|
|
2900
|
-
status: "published",
|
|
2901
|
-
label: "Published",
|
|
2902
|
-
badgeColor: "success100",
|
|
2903
|
-
textColor: "success700"
|
|
2904
|
-
};
|
|
2905
|
-
}
|
|
2906
|
-
if (entry.status === "unknown") {
|
|
2907
|
-
return {
|
|
2908
|
-
status: "unknown",
|
|
2909
|
-
label: "Unknown",
|
|
2910
|
-
badgeColor: "neutral200",
|
|
2911
|
-
textColor: "neutral600"
|
|
2912
|
-
};
|
|
2913
|
-
}
|
|
2914
|
-
if (!entry.documentId && !entry.id && !entry.slug) {
|
|
2915
|
-
return {
|
|
2916
|
-
status: "unknown",
|
|
2917
|
-
label: "Unknown",
|
|
2918
|
-
badgeColor: "neutral200",
|
|
2919
|
-
textColor: "neutral600"
|
|
2920
|
-
};
|
|
2921
|
-
}
|
|
2922
|
-
if (entry.publishedAt) {
|
|
2923
|
-
if (entry.updatedAt && new Date(entry.updatedAt).getTime() > new Date(entry.publishedAt).getTime()) {
|
|
2924
|
-
return {
|
|
2925
|
-
status: "modified",
|
|
2926
|
-
label: "Modified",
|
|
2927
|
-
badgeColor: "primary100",
|
|
2928
|
-
textColor: "primary700"
|
|
2929
|
-
};
|
|
2930
|
-
}
|
|
2931
|
-
return {
|
|
2932
|
-
status: "published",
|
|
2933
|
-
label: "Published",
|
|
2934
|
-
badgeColor: "success100",
|
|
2935
|
-
textColor: "success700"
|
|
2936
|
-
};
|
|
2937
|
-
}
|
|
2938
|
-
return {
|
|
2939
|
-
status: "draft",
|
|
2940
|
-
label: "Draft",
|
|
2941
|
-
badgeColor: "neutral150",
|
|
2942
|
-
textColor: "neutral700"
|
|
2943
|
-
};
|
|
2944
|
-
}
|
|
2945
3033
|
function parseDynamicZonePath(path) {
|
|
2946
3034
|
if (!path) return { cleanPath: "", rootKey: "", subPath: "" };
|
|
2947
3035
|
const bracketMatch = path.match(/^([^.[]+)\[([^\]]+)\]\.(.+)$/);
|
|
@@ -7535,4 +7623,4 @@ exports.getNestedValue = getNestedValue;
|
|
|
7535
7623
|
exports.getPropertyValue = getPropertyValue;
|
|
7536
7624
|
exports.getSortOptionsForCollection = getSortOptionsForCollection;
|
|
7537
7625
|
exports.parseDynamicZonePath = parseDynamicZonePath;
|
|
7538
|
-
//# sourceMappingURL=BulkUpdater-
|
|
7626
|
+
//# sourceMappingURL=BulkUpdater-C0uR_ORS.js.map
|