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