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.
@@ -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
- setCollections(modelsRes.data.collections);
186
- if (modelsRes.data.collections.length > 0) {
187
- setSelectedUid(modelsRes.data.collections[0].uid);
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
- setAllParsedRecords(records);
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
- const totalRows = allParsedRecords.length;
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 = allParsedRecords.slice(startIdx, endIdx);
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: allParsedRecords,
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: allParsedRecords,
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-ezjrkUaf.js.map
7626
+ //# sourceMappingURL=BulkUpdater-C0uR_ORS.js.map