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.
@@ -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-BoqhoTjo.js");
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 blob = new Blob([content], { type: "text/csv;charset=utf-8;" });
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 blob = new Blob([content], { type: mimeType });
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 blob = new Blob([csvStr], { type: "text/csv;charset=utf-8;" });
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-DS6gm_qd.js.map
4747
+ //# sourceMappingURL=BulkUpdater-CWJYmuGU.js.map