strapi-plugin-bulk-updater 1.2.11 → 1.2.13
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-DS6gm_qd.js → BulkUpdater-CWJYmuGU.js} +484 -10
- package/dist/_chunks/BulkUpdater-CWJYmuGU.js.map +1 -0
- package/dist/_chunks/{BulkUpdater-B_COVQmo.mjs → BulkUpdater-Cfig2f7d.mjs} +484 -10
- package/dist/_chunks/BulkUpdater-Cfig2f7d.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-BRGTrW9H.js → SettingsPage-BAvuOb7V.js} +2 -2
- package/dist/_chunks/{SettingsPage-BRGTrW9H.js.map → SettingsPage-BAvuOb7V.js.map} +1 -1
- package/dist/_chunks/{SettingsPage-ieu-Out8.mjs → SettingsPage-BWo4l6Gd.mjs} +2 -2
- package/dist/_chunks/{SettingsPage-ieu-Out8.mjs.map → SettingsPage-BWo4l6Gd.mjs.map} +1 -1
- package/dist/_chunks/{ValidationRulesTab-BoqhoTjo.js → ValidationRulesTab-BLZWPGrZ.js} +3 -2
- package/dist/_chunks/{ValidationRulesTab-BoqhoTjo.js.map → ValidationRulesTab-BLZWPGrZ.js.map} +1 -1
- package/dist/_chunks/{ValidationRulesTab-BGcqM9cN.mjs → ValidationRulesTab-Dt53h-Ke.mjs} +3 -2
- package/dist/_chunks/{ValidationRulesTab-BGcqM9cN.mjs.map → ValidationRulesTab-Dt53h-Ke.mjs.map} +1 -1
- package/dist/admin/index.js +2 -2
- package/dist/admin/index.mjs +2 -2
- package/dist/server/index.js +670 -81
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +670 -81
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/_chunks/BulkUpdater-B_COVQmo.mjs.map +0 -1
- package/dist/_chunks/BulkUpdater-DS6gm_qd.js.map +0 -1
|
@@ -5,7 +5,7 @@ const React = require("react");
|
|
|
5
5
|
const admin = require("@strapi/strapi/admin");
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
|
7
7
|
const icons = require("@strapi/icons");
|
|
8
|
-
const ValidationRulesTab = require("./ValidationRulesTab-
|
|
8
|
+
const ValidationRulesTab = require("./ValidationRulesTab-BLZWPGrZ.js");
|
|
9
9
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
10
10
|
const React__default = /* @__PURE__ */ _interopDefault(React);
|
|
11
11
|
function CsvManagerTab() {
|
|
@@ -118,7 +118,8 @@ function CsvManagerTab() {
|
|
|
118
118
|
});
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
|
-
const
|
|
121
|
+
const safeContent = content.startsWith("\uFEFF") ? content : "\uFEFF" + content;
|
|
122
|
+
const blob = new Blob([safeContent], { type: "text/csv;charset=utf-8;" });
|
|
122
123
|
const url = URL.createObjectURL(blob);
|
|
123
124
|
const link = document.createElement("a");
|
|
124
125
|
link.href = url;
|
|
@@ -507,7 +508,9 @@ function formatVal(v) {
|
|
|
507
508
|
return String(v);
|
|
508
509
|
}
|
|
509
510
|
function downloadFile(content, filename, mimeType = "text/csv;charset=utf-8;") {
|
|
510
|
-
const
|
|
511
|
+
const isCsv = mimeType.includes("csv") || filename.endsWith(".csv");
|
|
512
|
+
const safeContent = isCsv && !content.startsWith("\uFEFF") ? "\uFEFF" + content : content;
|
|
513
|
+
const blob = new Blob([safeContent], { type: mimeType });
|
|
511
514
|
const url = URL.createObjectURL(blob);
|
|
512
515
|
const a = document.createElement("a");
|
|
513
516
|
a.href = url;
|
|
@@ -629,7 +632,7 @@ function ProcessingDashboardModal({
|
|
|
629
632
|
].join(",")
|
|
630
633
|
)
|
|
631
634
|
];
|
|
632
|
-
downloadFile(csvRows.join("\n"), `bulk_update_report_${targetId}.csv`);
|
|
635
|
+
downloadFile(csvRows.join("\r\n") + "\r\n", `bulk_update_report_${targetId}.csv`);
|
|
633
636
|
toggleNotification({
|
|
634
637
|
type: "success",
|
|
635
638
|
message: "Execution report downloaded successfully"
|
|
@@ -1124,7 +1127,8 @@ const BulkUpdatePreviewModal = ({
|
|
|
1124
1127
|
loading,
|
|
1125
1128
|
previewData,
|
|
1126
1129
|
attribute,
|
|
1127
|
-
targetValueDisplay
|
|
1130
|
+
targetValueDisplay,
|
|
1131
|
+
publishOnApproval = true
|
|
1128
1132
|
}) => {
|
|
1129
1133
|
const [filterTab, setFilterTab] = React.useState("all");
|
|
1130
1134
|
const [searchQuery, setSearchQuery] = React.useState("");
|
|
@@ -1197,9 +1201,17 @@ const BulkUpdatePreviewModal = ({
|
|
|
1197
1201
|
] }),
|
|
1198
1202
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Inspect exact before & after values across target records before applying changes to the database." })
|
|
1199
1203
|
] }),
|
|
1200
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
1204
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
1201
1205
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "New Value:" }),
|
|
1202
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", children: targetValueDisplay || "(empty)" })
|
|
1206
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", children: targetValueDisplay || "(empty)" }),
|
|
1207
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1208
|
+
designSystem.Badge,
|
|
1209
|
+
{
|
|
1210
|
+
backgroundColor: publishOnApproval !== false ? "success100" : "warning100",
|
|
1211
|
+
textColor: publishOnApproval !== false ? "success700" : "warning700",
|
|
1212
|
+
children: publishOnApproval !== false ? "✓ LIVE PUBLISH" : "DRAFT ONLY"
|
|
1213
|
+
}
|
|
1214
|
+
)
|
|
1203
1215
|
] })
|
|
1204
1216
|
] })
|
|
1205
1217
|
}
|
|
@@ -1638,6 +1650,10 @@ const BulkUpdater = () => {
|
|
|
1638
1650
|
const [showPreviewModal, setShowPreviewModal] = React.useState(false);
|
|
1639
1651
|
const [previewLoading, setPreviewLoading] = React.useState(false);
|
|
1640
1652
|
const [previewData, setPreviewData] = React.useState(null);
|
|
1653
|
+
const [showPublishConfirmModal, setShowPublishConfirmModal] = React.useState(false);
|
|
1654
|
+
const [publishing, setPublishing] = React.useState(false);
|
|
1655
|
+
const [publishMakerNotesInput, setPublishMakerNotesInput] = React.useState("");
|
|
1656
|
+
const [bulkExporting, setBulkExporting] = React.useState(false);
|
|
1641
1657
|
const MODELS_CACHE_KEY = "strapi_bulk_updater_models_cache";
|
|
1642
1658
|
const LAST_ATTR_KEY = "strapi_bulk_updater_last_attr";
|
|
1643
1659
|
const getInitialAttribute = () => {
|
|
@@ -2423,6 +2439,199 @@ const BulkUpdater = () => {
|
|
|
2423
2439
|
setMakerNotesInput("");
|
|
2424
2440
|
}
|
|
2425
2441
|
};
|
|
2442
|
+
const handleBulkExportSelected = async () => {
|
|
2443
|
+
const targets = [];
|
|
2444
|
+
Object.keys(selectedEntries).forEach((key) => {
|
|
2445
|
+
if (selectedEntries[key]) {
|
|
2446
|
+
const parts = key.split(KEY_SEP);
|
|
2447
|
+
if (parts.length === 2) {
|
|
2448
|
+
targets.push({ uid: parts[0], documentId: parts[1] });
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
});
|
|
2452
|
+
if (targets.length === 0) {
|
|
2453
|
+
toggleNotification({
|
|
2454
|
+
type: "warning",
|
|
2455
|
+
message: "Please select at least one entry to export"
|
|
2456
|
+
});
|
|
2457
|
+
return;
|
|
2458
|
+
}
|
|
2459
|
+
try {
|
|
2460
|
+
setBulkExporting(true);
|
|
2461
|
+
const res = await post("/bulk-updater/csv/export-bulk", { selectedEntries: targets });
|
|
2462
|
+
const csvStr = res.data?.csvContent || (typeof res.data === "string" ? res.data : "");
|
|
2463
|
+
if (!csvStr) {
|
|
2464
|
+
toggleNotification({
|
|
2465
|
+
type: "warning",
|
|
2466
|
+
message: "No CSV content returned for selected entries"
|
|
2467
|
+
});
|
|
2468
|
+
return;
|
|
2469
|
+
}
|
|
2470
|
+
const safeContent = csvStr.startsWith("\uFEFF") ? csvStr : "\uFEFF" + csvStr;
|
|
2471
|
+
const blob = new Blob([safeContent], { type: "text/csv;charset=utf-8;" });
|
|
2472
|
+
const url = URL.createObjectURL(blob);
|
|
2473
|
+
const link = document.createElement("a");
|
|
2474
|
+
link.href = url;
|
|
2475
|
+
link.setAttribute("download", res.data?.filename || `bulk_export_selected_${targets.length}.csv`);
|
|
2476
|
+
document.body.appendChild(link);
|
|
2477
|
+
link.click();
|
|
2478
|
+
document.body.removeChild(link);
|
|
2479
|
+
URL.revokeObjectURL(url);
|
|
2480
|
+
toggleNotification({
|
|
2481
|
+
type: "success",
|
|
2482
|
+
message: `Successfully exported ${res.data?.count || targets.length} selected records to Excel CSV`
|
|
2483
|
+
});
|
|
2484
|
+
} catch (e) {
|
|
2485
|
+
toggleNotification({
|
|
2486
|
+
type: "danger",
|
|
2487
|
+
message: e.message || "Failed exporting selected records to CSV"
|
|
2488
|
+
});
|
|
2489
|
+
} finally {
|
|
2490
|
+
setBulkExporting(false);
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2493
|
+
const handleOpenPublishModal = () => {
|
|
2494
|
+
const totalSelected = Object.values(selectedEntries).filter(Boolean).length;
|
|
2495
|
+
if (totalSelected === 0) {
|
|
2496
|
+
toggleNotification({
|
|
2497
|
+
type: "warning",
|
|
2498
|
+
message: "Please select at least one collection type or entry to publish"
|
|
2499
|
+
});
|
|
2500
|
+
return;
|
|
2501
|
+
}
|
|
2502
|
+
setShowPublishConfirmModal(true);
|
|
2503
|
+
};
|
|
2504
|
+
const executeBatchPublish = async (executionMode, forceImmediate = false) => {
|
|
2505
|
+
const targets = [];
|
|
2506
|
+
Object.keys(selectedEntries).forEach((key) => {
|
|
2507
|
+
if (selectedEntries[key]) {
|
|
2508
|
+
const parts = key.split(KEY_SEP);
|
|
2509
|
+
if (parts.length === 2) {
|
|
2510
|
+
targets.push({ uid: parts[0], documentId: parts[1] });
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
});
|
|
2514
|
+
try {
|
|
2515
|
+
setPublishing(true);
|
|
2516
|
+
setShowPublishConfirmModal(false);
|
|
2517
|
+
setShowProcessingDashboard(true);
|
|
2518
|
+
setIsSubmittingBatch(true);
|
|
2519
|
+
setLastResults(null);
|
|
2520
|
+
const tempBatchId = `batch_pub_${Date.now()}`;
|
|
2521
|
+
setDashboardBatchId(tempBatchId);
|
|
2522
|
+
setDashboardJob({
|
|
2523
|
+
id: tempBatchId,
|
|
2524
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2525
|
+
status: "processing",
|
|
2526
|
+
executionMode,
|
|
2527
|
+
attribute: "(publish)",
|
|
2528
|
+
value: "published",
|
|
2529
|
+
totalTargets: targets.length,
|
|
2530
|
+
processedCount: 0,
|
|
2531
|
+
updatedCount: 0,
|
|
2532
|
+
skippedCount: 0,
|
|
2533
|
+
failedCount: 0,
|
|
2534
|
+
isLive: true,
|
|
2535
|
+
publishOnApproval: true,
|
|
2536
|
+
results: []
|
|
2537
|
+
});
|
|
2538
|
+
const payload = {
|
|
2539
|
+
selectedEntries: targets,
|
|
2540
|
+
executionMode,
|
|
2541
|
+
makerNotes: publishMakerNotesInput,
|
|
2542
|
+
forceImmediate
|
|
2543
|
+
};
|
|
2544
|
+
const res = await post("/bulk-updater/batch-publish", payload);
|
|
2545
|
+
setIsSubmittingBatch(false);
|
|
2546
|
+
if (res.data && res.data.success) {
|
|
2547
|
+
setSelectedEntries({});
|
|
2548
|
+
const finalBatchId = res.data.batchId;
|
|
2549
|
+
setDashboardBatchId(finalBatchId);
|
|
2550
|
+
if (res.data.pending) {
|
|
2551
|
+
setDashboardJob({
|
|
2552
|
+
id: finalBatchId,
|
|
2553
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2554
|
+
status: res.data.status || "pending_approval",
|
|
2555
|
+
executionMode,
|
|
2556
|
+
scheduledFor: res.data.scheduledFor,
|
|
2557
|
+
attribute: "(publish)",
|
|
2558
|
+
value: "published",
|
|
2559
|
+
totalTargets: targets.length,
|
|
2560
|
+
processedCount: 0,
|
|
2561
|
+
updatedCount: 0,
|
|
2562
|
+
skippedCount: 0,
|
|
2563
|
+
failedCount: 0,
|
|
2564
|
+
isLive: true,
|
|
2565
|
+
publishOnApproval: true,
|
|
2566
|
+
makerNotes: publishMakerNotesInput,
|
|
2567
|
+
policyMessage: res.data.message,
|
|
2568
|
+
results: []
|
|
2569
|
+
});
|
|
2570
|
+
toggleNotification({
|
|
2571
|
+
type: "success",
|
|
2572
|
+
message: res.data.message || "Publish batch submitted successfully."
|
|
2573
|
+
});
|
|
2574
|
+
await fetchPendingBatches();
|
|
2575
|
+
} else {
|
|
2576
|
+
setLastResults(res.data.results || []);
|
|
2577
|
+
setUpdateSummary({
|
|
2578
|
+
updatedCount: res.data.publishedCount || 0,
|
|
2579
|
+
skippedCount: res.data.skippedCount || 0,
|
|
2580
|
+
batchId: res.data.batchId
|
|
2581
|
+
});
|
|
2582
|
+
setDashboardJob({
|
|
2583
|
+
id: finalBatchId,
|
|
2584
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2585
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2586
|
+
status: res.data.status || "successful",
|
|
2587
|
+
executionMode: "immediate",
|
|
2588
|
+
attribute: "(publish)",
|
|
2589
|
+
value: "published",
|
|
2590
|
+
totalTargets: res.data.totalTargets || targets.length,
|
|
2591
|
+
processedCount: res.data.results?.length || targets.length,
|
|
2592
|
+
updatedCount: res.data.publishedCount || 0,
|
|
2593
|
+
skippedCount: res.data.skippedCount || 0,
|
|
2594
|
+
failedCount: res.data.failedCount || 0,
|
|
2595
|
+
isLive: true,
|
|
2596
|
+
publishOnApproval: true,
|
|
2597
|
+
results: res.data.results || []
|
|
2598
|
+
});
|
|
2599
|
+
toggleNotification({
|
|
2600
|
+
type: "success",
|
|
2601
|
+
message: `Bulk publish complete! Batch ID: ${res.data.batchId}. Published: ${res.data.publishedCount}, Skipped: ${res.data.skippedCount}`
|
|
2602
|
+
});
|
|
2603
|
+
await fetchModels();
|
|
2604
|
+
await fetchAuditHistory();
|
|
2605
|
+
}
|
|
2606
|
+
} else {
|
|
2607
|
+
setIsSubmittingBatch(false);
|
|
2608
|
+
setDashboardJob((prev) => ({
|
|
2609
|
+
...prev,
|
|
2610
|
+
status: "failed",
|
|
2611
|
+
error: res.data?.error || "Batch publish encountered an error"
|
|
2612
|
+
}));
|
|
2613
|
+
toggleNotification({
|
|
2614
|
+
type: "danger",
|
|
2615
|
+
message: res.data?.error || "Batch publish encountered an error"
|
|
2616
|
+
});
|
|
2617
|
+
}
|
|
2618
|
+
} catch (err) {
|
|
2619
|
+
setIsSubmittingBatch(false);
|
|
2620
|
+
const errMsg = err.response?.data?.error || err.message || "Batch publish failed";
|
|
2621
|
+
setDashboardJob((prev) => ({
|
|
2622
|
+
...prev,
|
|
2623
|
+
status: "failed",
|
|
2624
|
+
error: errMsg
|
|
2625
|
+
}));
|
|
2626
|
+
toggleNotification({
|
|
2627
|
+
type: "danger",
|
|
2628
|
+
message: errMsg
|
|
2629
|
+
});
|
|
2630
|
+
} finally {
|
|
2631
|
+
setPublishing(false);
|
|
2632
|
+
setPublishMakerNotesInput("");
|
|
2633
|
+
}
|
|
2634
|
+
};
|
|
2426
2635
|
const handleApproveBatch = async (batchId) => {
|
|
2427
2636
|
try {
|
|
2428
2637
|
setApprovingBatchId(batchId);
|
|
@@ -2907,9 +3116,64 @@ const BulkUpdater = () => {
|
|
|
2907
3116
|
")"
|
|
2908
3117
|
]
|
|
2909
3118
|
}
|
|
3119
|
+
),
|
|
3120
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3121
|
+
designSystem.Button,
|
|
3122
|
+
{
|
|
3123
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
|
|
3124
|
+
variant: "success-light",
|
|
3125
|
+
size: "L",
|
|
3126
|
+
onClick: handleOpenPublishModal,
|
|
3127
|
+
loading: publishing,
|
|
3128
|
+
disabled: loading || totalSelectedCount === 0,
|
|
3129
|
+
title: "Directly publish selected draft records across collections",
|
|
3130
|
+
children: [
|
|
3131
|
+
"Publish Selected (",
|
|
3132
|
+
totalSelectedCount,
|
|
3133
|
+
")"
|
|
3134
|
+
]
|
|
3135
|
+
}
|
|
3136
|
+
),
|
|
3137
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3138
|
+
designSystem.Button,
|
|
3139
|
+
{
|
|
3140
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
|
|
3141
|
+
variant: "tertiary",
|
|
3142
|
+
size: "L",
|
|
3143
|
+
onClick: handleBulkExportSelected,
|
|
3144
|
+
loading: bulkExporting,
|
|
3145
|
+
disabled: loading || totalSelectedCount === 0,
|
|
3146
|
+
title: "Export selected entries to Excel-compatible CSV with full nested component support",
|
|
3147
|
+
children: [
|
|
3148
|
+
"Export Selected (",
|
|
3149
|
+
totalSelectedCount,
|
|
3150
|
+
")"
|
|
3151
|
+
]
|
|
3152
|
+
}
|
|
2910
3153
|
)
|
|
2911
3154
|
] })
|
|
2912
3155
|
] }),
|
|
3156
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 4, padding: 4, background: "neutral100", hasRadius: true, style: { border: "1px solid #eaeaef" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 3, children: [
|
|
3157
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
3158
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3159
|
+
designSystem.Checkbox,
|
|
3160
|
+
{
|
|
3161
|
+
checked: publishOnApproval,
|
|
3162
|
+
onCheckedChange: (checked) => setPublishOnApproval(Boolean(checked)),
|
|
3163
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: "Auto-Publish after Update" })
|
|
3164
|
+
}
|
|
3165
|
+
),
|
|
3166
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3167
|
+
designSystem.Badge,
|
|
3168
|
+
{
|
|
3169
|
+
backgroundColor: publishOnApproval ? "success100" : "warning100",
|
|
3170
|
+
textColor: publishOnApproval ? "success700" : "warning700",
|
|
3171
|
+
children: publishOnApproval ? "✓ LIVE PUBLISH" : "DRAFT ONLY"
|
|
3172
|
+
}
|
|
3173
|
+
)
|
|
3174
|
+
] }),
|
|
3175
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: publishOnApproval ? "When enabled, entries will be published live immediately upon batch execution for draft-enabled content types." : "When disabled, entries will be saved as draft versions without publishing to live visitors." })
|
|
3176
|
+
] }) }),
|
|
2913
3177
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 4, padding: 4, background: "neutral100", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 3, children: [
|
|
2914
3178
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, alignItems: "center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2915
3179
|
designSystem.Checkbox,
|
|
@@ -3387,6 +3651,10 @@ const BulkUpdater = () => {
|
|
|
3387
3651
|
if (entrySearch && entrySearch.trim()) {
|
|
3388
3652
|
params.set("search", entrySearch.trim());
|
|
3389
3653
|
}
|
|
3654
|
+
const colSelectedDocIds = col.entries.filter((e) => selectedEntries[`${col.uid}${KEY_SEP}${e.documentId}`]).map((e) => e.documentId);
|
|
3655
|
+
if (colSelectedDocIds.length > 0) {
|
|
3656
|
+
params.set("documentIds", colSelectedDocIds.join(","));
|
|
3657
|
+
}
|
|
3390
3658
|
const res = await get(`/bulk-updater/csv/export/${col.uid}?${params.toString()}`);
|
|
3391
3659
|
const csvStr = res.data?.csvContent || (typeof res.data === "string" ? res.data : "");
|
|
3392
3660
|
if (!csvStr) {
|
|
@@ -3396,7 +3664,8 @@ const BulkUpdater = () => {
|
|
|
3396
3664
|
});
|
|
3397
3665
|
return;
|
|
3398
3666
|
}
|
|
3399
|
-
const
|
|
3667
|
+
const safeContent = csvStr.startsWith("\uFEFF") ? csvStr : "\uFEFF" + csvStr;
|
|
3668
|
+
const blob = new Blob([safeContent], { type: "text/csv;charset=utf-8;" });
|
|
3400
3669
|
const url = URL.createObjectURL(blob);
|
|
3401
3670
|
const link = document.createElement("a");
|
|
3402
3671
|
link.href = url;
|
|
@@ -3407,7 +3676,7 @@ const BulkUpdater = () => {
|
|
|
3407
3676
|
URL.revokeObjectURL(url);
|
|
3408
3677
|
toggleNotification({
|
|
3409
3678
|
type: "success",
|
|
3410
|
-
message: `Exported ${col.displayName} entries to CSV`
|
|
3679
|
+
message: `Exported ${res.data?.count ?? (colSelectedDocIds.length || col.entries.length)} ${col.displayName} entries to Excel CSV`
|
|
3411
3680
|
});
|
|
3412
3681
|
} catch (e) {
|
|
3413
3682
|
toggleNotification({
|
|
@@ -4237,6 +4506,210 @@ const BulkUpdater = () => {
|
|
|
4237
4506
|
)
|
|
4238
4507
|
}
|
|
4239
4508
|
),
|
|
4509
|
+
showPublishConfirmModal && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4510
|
+
"div",
|
|
4511
|
+
{
|
|
4512
|
+
style: {
|
|
4513
|
+
position: "fixed",
|
|
4514
|
+
top: 0,
|
|
4515
|
+
left: 0,
|
|
4516
|
+
right: 0,
|
|
4517
|
+
bottom: 0,
|
|
4518
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
4519
|
+
display: "flex",
|
|
4520
|
+
alignItems: "center",
|
|
4521
|
+
justifyContent: "center",
|
|
4522
|
+
zIndex: 100
|
|
4523
|
+
},
|
|
4524
|
+
onClick: () => setShowPublishConfirmModal(false),
|
|
4525
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4526
|
+
designSystem.Box,
|
|
4527
|
+
{
|
|
4528
|
+
background: "neutral0",
|
|
4529
|
+
hasRadius: true,
|
|
4530
|
+
style: {
|
|
4531
|
+
width: "90%",
|
|
4532
|
+
maxWidth: 620,
|
|
4533
|
+
maxHeight: "90vh",
|
|
4534
|
+
display: "flex",
|
|
4535
|
+
flexDirection: "column",
|
|
4536
|
+
boxShadow: "0 10px 40px rgba(0, 0, 0, 0.25)",
|
|
4537
|
+
overflow: "hidden"
|
|
4538
|
+
},
|
|
4539
|
+
onClick: (e) => e.stopPropagation(),
|
|
4540
|
+
children: [
|
|
4541
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4542
|
+
designSystem.Box,
|
|
4543
|
+
{
|
|
4544
|
+
padding: 5,
|
|
4545
|
+
background: "neutral100",
|
|
4546
|
+
style: {
|
|
4547
|
+
borderBottom: "1px solid rgba(120, 120, 150, 0.2)",
|
|
4548
|
+
flexShrink: 0
|
|
4549
|
+
},
|
|
4550
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
|
|
4551
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
4552
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", fontWeight: "bold", children: "Confirm Bulk Publish" }),
|
|
4553
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Publish selected draft records live to visitors across content types" }) })
|
|
4554
|
+
] }),
|
|
4555
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", children: [
|
|
4556
|
+
totalSelectedCount,
|
|
4557
|
+
" Selected"
|
|
4558
|
+
] })
|
|
4559
|
+
] })
|
|
4560
|
+
}
|
|
4561
|
+
),
|
|
4562
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4563
|
+
designSystem.Box,
|
|
4564
|
+
{
|
|
4565
|
+
padding: 5,
|
|
4566
|
+
style: {
|
|
4567
|
+
overflowY: "auto",
|
|
4568
|
+
flexGrow: 1,
|
|
4569
|
+
display: "flex",
|
|
4570
|
+
flexDirection: "column",
|
|
4571
|
+
gap: 16
|
|
4572
|
+
},
|
|
4573
|
+
children: [
|
|
4574
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral100", hasRadius: true, style: { border: "1px solid #eaeaef" }, children: [
|
|
4575
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: "Collection Breakdown:" }),
|
|
4576
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, children: collections.filter(
|
|
4577
|
+
(col) => col.entries.some((entry) => selectedEntries[`${col.uid}${KEY_SEP}${entry.documentId}`])
|
|
4578
|
+
).map((col) => {
|
|
4579
|
+
const count = col.entries.filter(
|
|
4580
|
+
(entry) => selectedEntries[`${col.uid}${KEY_SEP}${entry.documentId}`]
|
|
4581
|
+
).length;
|
|
4582
|
+
const hasDraftAndPublish = col.draftAndPublish !== false;
|
|
4583
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4584
|
+
designSystem.Flex,
|
|
4585
|
+
{
|
|
4586
|
+
justifyContent: "space-between",
|
|
4587
|
+
alignItems: "center",
|
|
4588
|
+
paddingTop: 2,
|
|
4589
|
+
paddingBottom: 2,
|
|
4590
|
+
style: { borderBottom: "1px dashed #eaeaef" },
|
|
4591
|
+
children: [
|
|
4592
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", children: [
|
|
4593
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: col.displayName }),
|
|
4594
|
+
" (",
|
|
4595
|
+
col.uid,
|
|
4596
|
+
")"
|
|
4597
|
+
] }),
|
|
4598
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
4599
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "neutral150", textColor: "neutral700", children: [
|
|
4600
|
+
count,
|
|
4601
|
+
" ",
|
|
4602
|
+
count === 1 ? "entry" : "entries"
|
|
4603
|
+
] }),
|
|
4604
|
+
hasDraftAndPublish ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", children: "✓ Draft & Publish Enabled" }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "warning100", textColor: "warning700", children: "⚠️ Skipped (Drafts Disabled)" })
|
|
4605
|
+
] })
|
|
4606
|
+
]
|
|
4607
|
+
},
|
|
4608
|
+
col.uid
|
|
4609
|
+
);
|
|
4610
|
+
}) })
|
|
4611
|
+
] }),
|
|
4612
|
+
executionWindow?.isBusinessHours && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4613
|
+
designSystem.Box,
|
|
4614
|
+
{
|
|
4615
|
+
padding: 4,
|
|
4616
|
+
background: "warning100",
|
|
4617
|
+
hasRadius: true,
|
|
4618
|
+
style: { border: "1px solid #f5c0b8" },
|
|
4619
|
+
children: [
|
|
4620
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "warning700", children: "⚠️ Business Hours Active:" }),
|
|
4621
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "warning700", style: { display: "block", marginTop: 4 }, children: [
|
|
4622
|
+
"It is currently business peak hours (",
|
|
4623
|
+
executionWindow.currentTime,
|
|
4624
|
+
"). To prevent API latency spikes, publish requests should be queued for off-peak hours (",
|
|
4625
|
+
executionWindow.offPeakStartTime,
|
|
4626
|
+
") or submitted for governance review."
|
|
4627
|
+
] })
|
|
4628
|
+
]
|
|
4629
|
+
}
|
|
4630
|
+
),
|
|
4631
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
4632
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", children: "Governance Notes / Reason (Optional):" }),
|
|
4633
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4634
|
+
designSystem.TextInput,
|
|
4635
|
+
{
|
|
4636
|
+
name: "publishMakerNotes",
|
|
4637
|
+
placeholder: "e.g. Publishing Q3 catalog release updates",
|
|
4638
|
+
value: publishMakerNotesInput,
|
|
4639
|
+
onChange: (e) => setPublishMakerNotesInput(e.target.value)
|
|
4640
|
+
}
|
|
4641
|
+
) })
|
|
4642
|
+
] })
|
|
4643
|
+
]
|
|
4644
|
+
}
|
|
4645
|
+
),
|
|
4646
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4647
|
+
designSystem.Box,
|
|
4648
|
+
{
|
|
4649
|
+
padding: 4,
|
|
4650
|
+
background: "neutral100",
|
|
4651
|
+
style: {
|
|
4652
|
+
borderTop: "1px solid rgba(120, 120, 150, 0.2)",
|
|
4653
|
+
flexShrink: 0,
|
|
4654
|
+
boxShadow: "0 -4px 16px rgba(0, 0, 0, 0.08)"
|
|
4655
|
+
},
|
|
4656
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", gap: 3, style: { width: "100%" }, children: [
|
|
4657
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", size: "M", onClick: () => setShowPublishConfirmModal(false), children: "Cancel" }),
|
|
4658
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, wrap: "wrap", justifyContent: "flex-end", alignItems: "center", children: [
|
|
4659
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4660
|
+
designSystem.Button,
|
|
4661
|
+
{
|
|
4662
|
+
variant: executionWindow?.isBusinessHours ? "default" : "secondary",
|
|
4663
|
+
size: "M",
|
|
4664
|
+
onClick: () => executeBatchPublish("maker_checker"),
|
|
4665
|
+
loading: publishing,
|
|
4666
|
+
children: "Submit for Checker Approval"
|
|
4667
|
+
}
|
|
4668
|
+
),
|
|
4669
|
+
executionWindow?.isBusinessHours ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4670
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4671
|
+
designSystem.Button,
|
|
4672
|
+
{
|
|
4673
|
+
variant: "secondary",
|
|
4674
|
+
size: "M",
|
|
4675
|
+
onClick: () => executeBatchPublish("queue_offpeak"),
|
|
4676
|
+
loading: publishing,
|
|
4677
|
+
children: [
|
|
4678
|
+
"Queue for Off-Peak (",
|
|
4679
|
+
executionWindow?.offPeakStartTime || "18:00",
|
|
4680
|
+
")"
|
|
4681
|
+
]
|
|
4682
|
+
}
|
|
4683
|
+
),
|
|
4684
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4685
|
+
designSystem.Button,
|
|
4686
|
+
{
|
|
4687
|
+
variant: "danger-light",
|
|
4688
|
+
size: "S",
|
|
4689
|
+
onClick: () => executeBatchPublish("immediate", true),
|
|
4690
|
+
loading: publishing,
|
|
4691
|
+
children: "Force Publish Now"
|
|
4692
|
+
}
|
|
4693
|
+
)
|
|
4694
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4695
|
+
designSystem.Button,
|
|
4696
|
+
{
|
|
4697
|
+
variant: "default",
|
|
4698
|
+
size: "M",
|
|
4699
|
+
onClick: () => executeBatchPublish("immediate"),
|
|
4700
|
+
loading: publishing,
|
|
4701
|
+
children: "Confirm & Publish Now"
|
|
4702
|
+
}
|
|
4703
|
+
)
|
|
4704
|
+
] })
|
|
4705
|
+
] })
|
|
4706
|
+
}
|
|
4707
|
+
)
|
|
4708
|
+
]
|
|
4709
|
+
}
|
|
4710
|
+
)
|
|
4711
|
+
}
|
|
4712
|
+
),
|
|
4240
4713
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4241
4714
|
BulkUpdatePreviewModal,
|
|
4242
4715
|
{
|
|
@@ -4249,6 +4722,7 @@ const BulkUpdater = () => {
|
|
|
4249
4722
|
loading: previewLoading,
|
|
4250
4723
|
previewData,
|
|
4251
4724
|
attribute: selectedAttribute,
|
|
4725
|
+
publishOnApproval,
|
|
4252
4726
|
targetValueDisplay: relationsMeta[selectedAttribute] ? selectedRelationDocId === "__clear__" ? "Clear / Unlink Relation" : relationOptions.find((o) => o.documentId === selectedRelationDocId)?.label || selectedRelationDocId || "(none)" : useRegex ? `Replace /${regexPattern}/g with "${attributeValue}"` : attributeValue
|
|
4253
4727
|
}
|
|
4254
4728
|
),
|
|
@@ -4270,4 +4744,4 @@ exports.default = BulkUpdater;
|
|
|
4270
4744
|
exports.formatDisplayValue = formatDisplayValue;
|
|
4271
4745
|
exports.getAvailableColumnsForCollection = getAvailableColumnsForCollection;
|
|
4272
4746
|
exports.getNestedValue = getNestedValue;
|
|
4273
|
-
//# sourceMappingURL=BulkUpdater-
|
|
4747
|
+
//# sourceMappingURL=BulkUpdater-CWJYmuGU.js.map
|