strapi-plugin-bulk-updater 1.3.10 → 1.4.2
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-J21ZgJWx.mjs → BulkUpdater-D4v5fP-1.mjs} +603 -420
- package/dist/_chunks/BulkUpdater-D4v5fP-1.mjs.map +1 -0
- package/dist/_chunks/{BulkUpdater-DRHQBZZV.js → BulkUpdater-L2FdlJfh.js} +602 -419
- package/dist/_chunks/BulkUpdater-L2FdlJfh.js.map +1 -0
- package/dist/_chunks/{SettingsPage-BDObdCIY.mjs → SettingsPage-D2qYhqpF.mjs} +2 -2
- package/dist/_chunks/{SettingsPage-BDObdCIY.mjs.map → SettingsPage-D2qYhqpF.mjs.map} +1 -1
- package/dist/_chunks/{SettingsPage-M-HQ8Jtr.js → SettingsPage-Dv2DRplw.js} +2 -2
- package/dist/_chunks/{SettingsPage-M-HQ8Jtr.js.map → SettingsPage-Dv2DRplw.js.map} +1 -1
- package/dist/_chunks/{ValidationRulesTab-DuvL-K4F.js → ValidationRulesTab-BTm3QXxM.js} +11 -1
- package/dist/_chunks/ValidationRulesTab-BTm3QXxM.js.map +1 -0
- package/dist/_chunks/{ValidationRulesTab-VeRr-vxa.mjs → ValidationRulesTab-BtOCWK8E.mjs} +12 -2
- package/dist/_chunks/ValidationRulesTab-BtOCWK8E.mjs.map +1 -0
- package/dist/admin/index.js +98 -4
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +98 -4
- package/dist/admin/index.mjs.map +1 -1
- package/dist/server/index.js +803 -29893
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +803 -29883
- package/dist/server/index.mjs.map +1 -1
- package/package.json +2 -1
- package/dist/_chunks/BulkUpdater-DRHQBZZV.js.map +0 -1
- package/dist/_chunks/BulkUpdater-J21ZgJWx.mjs.map +0 -1
- package/dist/_chunks/ValidationRulesTab-DuvL-K4F.js.map +0 -1
- package/dist/_chunks/ValidationRulesTab-VeRr-vxa.mjs.map +0 -1
|
@@ -2,8 +2,8 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
|
2
2
|
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, Badge, Checkbox, Alert, Table, Thead, Tr, Th, Tbody, Td, Loader, TextInput, ComboboxOption, Field, Combobox } from "@strapi/design-system";
|
|
5
|
-
import { ArrowClockwise, Download, Upload, Check, Eye, Play
|
|
6
|
-
import { V as ValidationRulesTab } from "./ValidationRulesTab-
|
|
5
|
+
import { ArrowClockwise, Download, Upload, Check, Cog, Eye, Play } from "@strapi/icons";
|
|
6
|
+
import { i as isAbortError, V as ValidationRulesTab } from "./ValidationRulesTab-BtOCWK8E.mjs";
|
|
7
7
|
function parseCsvRows(csvText) {
|
|
8
8
|
if (!csvText) return [];
|
|
9
9
|
let text = csvText;
|
|
@@ -91,6 +91,51 @@ function parseCsv(csvText) {
|
|
|
91
91
|
}
|
|
92
92
|
return records;
|
|
93
93
|
}
|
|
94
|
+
const LIFECYCLE_STATUS_WORDS = /* @__PURE__ */ new Set([
|
|
95
|
+
"pending review",
|
|
96
|
+
"pending_review",
|
|
97
|
+
"pending approval",
|
|
98
|
+
"pending_approval",
|
|
99
|
+
"approved",
|
|
100
|
+
"rejected",
|
|
101
|
+
"draft",
|
|
102
|
+
"published",
|
|
103
|
+
"modified",
|
|
104
|
+
"supported",
|
|
105
|
+
"ignored"
|
|
106
|
+
]);
|
|
107
|
+
function isValidDocId(val) {
|
|
108
|
+
if (!val || typeof val !== "string") return false;
|
|
109
|
+
const trimmed = val.trim();
|
|
110
|
+
if (!trimmed) return false;
|
|
111
|
+
if (LIFECYCLE_STATUS_WORDS.has(trimmed.toLowerCase())) return false;
|
|
112
|
+
if (/\s/.test(trimmed)) return false;
|
|
113
|
+
return /^[a-zA-Z0-9_-]+$/.test(trimmed);
|
|
114
|
+
}
|
|
115
|
+
function extractDocId(row) {
|
|
116
|
+
if (!row || typeof row !== "object") return "";
|
|
117
|
+
const candidates = [
|
|
118
|
+
row.documentId,
|
|
119
|
+
row.document_id,
|
|
120
|
+
row["Document ID"],
|
|
121
|
+
row["Document Id"],
|
|
122
|
+
row["document_id"],
|
|
123
|
+
row.docId,
|
|
124
|
+
row["docId"],
|
|
125
|
+
row.id,
|
|
126
|
+
row.ID,
|
|
127
|
+
row.Id
|
|
128
|
+
];
|
|
129
|
+
for (const c of candidates) {
|
|
130
|
+
if (c !== void 0 && c !== null) {
|
|
131
|
+
const str = String(c).trim();
|
|
132
|
+
if (isValidDocId(str)) {
|
|
133
|
+
return str;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return "";
|
|
138
|
+
}
|
|
94
139
|
function CsvManagerTab() {
|
|
95
140
|
const { get, post } = useFetchClient();
|
|
96
141
|
const { toggleNotification } = useNotification();
|
|
@@ -131,6 +176,7 @@ function CsvManagerTab() {
|
|
|
131
176
|
}
|
|
132
177
|
}
|
|
133
178
|
} catch (err) {
|
|
179
|
+
if (isAbortError(err)) return;
|
|
134
180
|
toggleNotification({
|
|
135
181
|
type: "danger",
|
|
136
182
|
message: err.message || "Failed loading collections for CSV Manager"
|
|
@@ -151,6 +197,7 @@ function CsvManagerTab() {
|
|
|
151
197
|
message: "CSV Template downloaded successfully"
|
|
152
198
|
});
|
|
153
199
|
} catch (err) {
|
|
200
|
+
if (isAbortError(err)) return;
|
|
154
201
|
toggleNotification({
|
|
155
202
|
type: "danger",
|
|
156
203
|
message: err.message || "Failed downloading CSV template"
|
|
@@ -169,6 +216,7 @@ function CsvManagerTab() {
|
|
|
169
216
|
message: "Collection exported to CSV successfully"
|
|
170
217
|
});
|
|
171
218
|
} catch (err) {
|
|
219
|
+
if (isAbortError(err)) return;
|
|
172
220
|
toggleNotification({
|
|
173
221
|
type: "danger",
|
|
174
222
|
message: err.message || "Failed exporting collection to CSV"
|
|
@@ -187,6 +235,7 @@ function CsvManagerTab() {
|
|
|
187
235
|
message: "Rule violations exported to CSV successfully"
|
|
188
236
|
});
|
|
189
237
|
} catch (err) {
|
|
238
|
+
if (isAbortError(err)) return;
|
|
190
239
|
toggleNotification({
|
|
191
240
|
type: "danger",
|
|
192
241
|
message: err.message || "Failed exporting violations to CSV"
|
|
@@ -256,6 +305,7 @@ function CsvManagerTab() {
|
|
|
256
305
|
throw new Error(res.data?.error || "Import failed");
|
|
257
306
|
}
|
|
258
307
|
} catch (err) {
|
|
308
|
+
if (isAbortError(err)) return;
|
|
259
309
|
toggleNotification({
|
|
260
310
|
type: "danger",
|
|
261
311
|
message: err.message || "Error processing CSV import"
|
|
@@ -409,7 +459,7 @@ function CsvManagerTab() {
|
|
|
409
459
|
),
|
|
410
460
|
parsedPreview.length > 0 && (() => {
|
|
411
461
|
const missingDocIdCount = parsedPreview.filter(
|
|
412
|
-
(row) => !(row
|
|
462
|
+
(row) => !extractDocId(row)
|
|
413
463
|
).length;
|
|
414
464
|
const headers = Object.keys(parsedPreview[0]);
|
|
415
465
|
return /* @__PURE__ */ jsxs(Box, { marginTop: 4, background: "neutral0", padding: 4, hasRadius: true, children: [
|
|
@@ -454,7 +504,7 @@ function CsvManagerTab() {
|
|
|
454
504
|
headers.map((h) => /* @__PURE__ */ jsx(Th, { style: { minWidth: 160 }, children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: h }) }, h))
|
|
455
505
|
] }) }),
|
|
456
506
|
/* @__PURE__ */ jsx(Tbody, { children: parsedPreview.map((row, rIdx) => {
|
|
457
|
-
const hasDocId = !!(row
|
|
507
|
+
const hasDocId = !!extractDocId(row);
|
|
458
508
|
return /* @__PURE__ */ jsxs(Tr, { children: [
|
|
459
509
|
/* @__PURE__ */ jsx(Td, { children: hasDocId ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "primary100", textColor: "primary700", children: "🔄 Match / Update" }) : /* @__PURE__ */ jsx(Badge, { backgroundColor: "warning100", textColor: "warning700", children: "➕ New Entry" }) }),
|
|
460
510
|
headers.map((h) => /* @__PURE__ */ jsx(Td, { style: { verticalAlign: "top", maxWidth: 300 }, children: (h === "documentId" || h === "id") && !row[h]?.trim() ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "warning700", fontWeight: "bold", children: "(Auto-generate ID)" }) : /* @__PURE__ */ jsx(
|
|
@@ -540,12 +590,53 @@ function CsvManagerTab() {
|
|
|
540
590
|
importResult.stats.errors.length,
|
|
541
591
|
"):"
|
|
542
592
|
] }),
|
|
543
|
-
/* @__PURE__ */ jsx("ul", { style: { margin: "4px 0 0 16px", padding: 0 }, children: importResult.stats.errors.slice(0,
|
|
593
|
+
/* @__PURE__ */ jsx("ul", { style: { margin: "4px 0 0 16px", padding: 0 }, children: importResult.stats.errors.slice(0, 10).map((err, idx) => /* @__PURE__ */ jsx("li", { style: { marginBottom: "2px" }, children: /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "danger600", children: [
|
|
544
594
|
"Row ",
|
|
545
595
|
err.row,
|
|
546
596
|
": ",
|
|
547
597
|
err.error
|
|
548
|
-
] }) }, idx)) })
|
|
598
|
+
] }) }, idx)) }),
|
|
599
|
+
importResult.stats.errors.length > 10 && /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", style: { display: "block", marginTop: 4, fontStyle: "italic" }, children: [
|
|
600
|
+
"...and ",
|
|
601
|
+
importResult.stats.errors.length - 10,
|
|
602
|
+
" more error",
|
|
603
|
+
importResult.stats.errors.length - 10 > 1 ? "s" : ""
|
|
604
|
+
] })
|
|
605
|
+
] }),
|
|
606
|
+
importResult.stats.diffs && importResult.stats.diffs.length > 0 && /* @__PURE__ */ jsxs(Box, { marginTop: 3, padding: 3, background: "neutral0", hasRadius: true, style: { border: "1px solid #dcdce4" }, children: [
|
|
607
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "sigma", textColor: "neutral800", fontWeight: "bold", display: "block", marginBottom: 2, children: [
|
|
608
|
+
"CHANGES APPLIED (",
|
|
609
|
+
importResult.stats.diffs.length,
|
|
610
|
+
"):"
|
|
611
|
+
] }),
|
|
612
|
+
/* @__PURE__ */ jsx(Box, { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxs(Table, { colCount: 4, rowCount: importResult.stats.diffs.length + 1, children: [
|
|
613
|
+
/* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
|
|
614
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Entry / Document" }) }),
|
|
615
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Attribute" }) }),
|
|
616
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Previous Value" }) }),
|
|
617
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Applied Value" }) })
|
|
618
|
+
] }) }),
|
|
619
|
+
/* @__PURE__ */ jsx(Tbody, { children: importResult.stats.diffs.slice(0, 10).map((d, idx) => {
|
|
620
|
+
const oldDisplay = d.oldValue !== null && d.oldValue !== void 0 ? typeof d.oldValue === "object" ? JSON.stringify(d.oldValue) : String(d.oldValue) : "(empty)";
|
|
621
|
+
const newDisplay = d.newValue !== null && d.newValue !== void 0 ? typeof d.newValue === "object" ? JSON.stringify(d.newValue) : String(d.newValue) : "(empty)";
|
|
622
|
+
return /* @__PURE__ */ jsxs(Tr, { children: [
|
|
623
|
+
/* @__PURE__ */ jsxs(Td, { children: [
|
|
624
|
+
/* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: d.label || d.documentId }),
|
|
625
|
+
d.documentId && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", display: "block", children: d.documentId })
|
|
626
|
+
] }),
|
|
627
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: d.attribute || "field" }) }),
|
|
628
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: oldDisplay }) }),
|
|
629
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "semiBold", children: newDisplay }) })
|
|
630
|
+
] }, idx);
|
|
631
|
+
}) })
|
|
632
|
+
] }) }),
|
|
633
|
+
importResult.stats.diffs.length > 10 && /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", style: { display: "block", marginTop: 6, fontStyle: "italic" }, children: [
|
|
634
|
+
"...and ",
|
|
635
|
+
importResult.stats.diffs.length - 10,
|
|
636
|
+
" more change",
|
|
637
|
+
importResult.stats.diffs.length - 10 > 1 ? "s" : "",
|
|
638
|
+
" recorded in Audit Trail & Version History."
|
|
639
|
+
] })
|
|
549
640
|
] })
|
|
550
641
|
]
|
|
551
642
|
}
|
|
@@ -1566,13 +1657,15 @@ function getAvailableColumnsForCollection(col, selectedAttribute, searchAttribut
|
|
|
1566
1657
|
defaultVisible: true
|
|
1567
1658
|
});
|
|
1568
1659
|
}
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1660
|
+
if (selectedAttribute && selectedAttribute.trim()) {
|
|
1661
|
+
const targetLabel = searchAttribute && searchAttribute !== selectedAttribute ? `Update Target: "${selectedAttribute}"` : `Current "${selectedAttribute}"`;
|
|
1662
|
+
cols.push({
|
|
1663
|
+
key: "target_attr",
|
|
1664
|
+
label: targetLabel,
|
|
1665
|
+
sortable: !col.isSingleType && col.attributes.includes(selectedAttribute),
|
|
1666
|
+
defaultVisible: true
|
|
1667
|
+
});
|
|
1668
|
+
}
|
|
1576
1669
|
cols.push({
|
|
1577
1670
|
key: "status",
|
|
1578
1671
|
label: "Status",
|
|
@@ -1629,7 +1722,68 @@ function formatDisplayValue(val) {
|
|
|
1629
1722
|
}
|
|
1630
1723
|
return String(val);
|
|
1631
1724
|
}
|
|
1632
|
-
function
|
|
1725
|
+
function getEntryLifecycleStatus(entry, col, pendingBatches = []) {
|
|
1726
|
+
const isPendingApproval = pendingBatches.some((b) => {
|
|
1727
|
+
if (b.status !== "pending_approval") return false;
|
|
1728
|
+
const targets = b.payload?.selectedEntries || [];
|
|
1729
|
+
return targets.some((t) => t.documentId === entry.documentId || String(t.documentId) === String(entry.id));
|
|
1730
|
+
});
|
|
1731
|
+
if (isPendingApproval) {
|
|
1732
|
+
return {
|
|
1733
|
+
status: "pending_review",
|
|
1734
|
+
label: "Pending Review",
|
|
1735
|
+
badgeColor: "warning100",
|
|
1736
|
+
textColor: "warning700"
|
|
1737
|
+
};
|
|
1738
|
+
}
|
|
1739
|
+
if (entry.status === "modified") {
|
|
1740
|
+
return {
|
|
1741
|
+
status: "modified",
|
|
1742
|
+
label: "Modified",
|
|
1743
|
+
badgeColor: "primary100",
|
|
1744
|
+
textColor: "primary700"
|
|
1745
|
+
};
|
|
1746
|
+
}
|
|
1747
|
+
if (entry.status === "draft") {
|
|
1748
|
+
return {
|
|
1749
|
+
status: "draft",
|
|
1750
|
+
label: "Draft",
|
|
1751
|
+
badgeColor: "neutral150",
|
|
1752
|
+
textColor: "neutral700"
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
if (entry.status === "published") {
|
|
1756
|
+
return {
|
|
1757
|
+
status: "published",
|
|
1758
|
+
label: "Published",
|
|
1759
|
+
badgeColor: "success100",
|
|
1760
|
+
textColor: "success700"
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
if (col && col.draftAndPublish === false) {
|
|
1764
|
+
return {
|
|
1765
|
+
status: "published",
|
|
1766
|
+
label: "Published",
|
|
1767
|
+
badgeColor: "success100",
|
|
1768
|
+
textColor: "success700"
|
|
1769
|
+
};
|
|
1770
|
+
}
|
|
1771
|
+
if (entry.publishedAt) {
|
|
1772
|
+
return {
|
|
1773
|
+
status: "published",
|
|
1774
|
+
label: "Published",
|
|
1775
|
+
badgeColor: "success100",
|
|
1776
|
+
textColor: "success700"
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1779
|
+
return {
|
|
1780
|
+
status: "draft",
|
|
1781
|
+
label: "Draft",
|
|
1782
|
+
badgeColor: "neutral150",
|
|
1783
|
+
textColor: "neutral700"
|
|
1784
|
+
};
|
|
1785
|
+
}
|
|
1786
|
+
function renderCellContent(colDef, entry, col, selectedAttribute, searchAttribute, isMatch, hasAttr, isSelected, onToggleSelect, pendingBatches = []) {
|
|
1633
1787
|
switch (colDef.key) {
|
|
1634
1788
|
case "select":
|
|
1635
1789
|
return /* @__PURE__ */ jsx(
|
|
@@ -1688,11 +1842,12 @@ function renderCellContent(colDef, entry, col, selectedAttribute, searchAttribut
|
|
|
1688
1842
|
);
|
|
1689
1843
|
}
|
|
1690
1844
|
case "status": {
|
|
1691
|
-
if (!hasAttr) {
|
|
1845
|
+
if (selectedAttribute && !hasAttr) {
|
|
1692
1846
|
return /* @__PURE__ */ jsx(Badge, { backgroundColor: "neutral200", textColor: "neutral600", children: "Ignored" });
|
|
1693
1847
|
}
|
|
1848
|
+
const lifecycle = getEntryLifecycleStatus(entry, col, pendingBatches);
|
|
1694
1849
|
return /* @__PURE__ */ jsxs(Flex, { gap: 1, alignItems: "center", children: [
|
|
1695
|
-
/* @__PURE__ */ jsx(Badge, { backgroundColor:
|
|
1850
|
+
/* @__PURE__ */ jsx(Badge, { backgroundColor: lifecycle.badgeColor, textColor: lifecycle.textColor, children: lifecycle.label }),
|
|
1696
1851
|
isMatch && /* @__PURE__ */ jsx(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: "Matches Filter" })
|
|
1697
1852
|
] });
|
|
1698
1853
|
}
|
|
@@ -1776,7 +1931,7 @@ const BulkUpdater = () => {
|
|
|
1776
1931
|
if (stored) return stored;
|
|
1777
1932
|
} catch {
|
|
1778
1933
|
}
|
|
1779
|
-
return "
|
|
1934
|
+
return "";
|
|
1780
1935
|
};
|
|
1781
1936
|
const [selectedAttribute, setSelectedAttribute] = useState(getInitialAttribute);
|
|
1782
1937
|
const [attributeValue, setAttributeValue] = useState("");
|
|
@@ -1828,7 +1983,8 @@ const BulkUpdater = () => {
|
|
|
1828
1983
|
const [filterOperator, setFilterOperator] = useState("none");
|
|
1829
1984
|
const [filterQuery, setFilterQuery] = useState("");
|
|
1830
1985
|
const [entrySearch, setEntrySearch] = useState("");
|
|
1831
|
-
const
|
|
1986
|
+
const [statusFilter, setStatusFilter] = useState("all");
|
|
1987
|
+
const isFilterActive = Boolean(searchAttribute && searchAttribute !== selectedAttribute) || filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim()) || Boolean(statusFilter !== "all") || Boolean(useRegex && regexPattern.trim());
|
|
1832
1988
|
const [lastResults, setLastResults] = useState(null);
|
|
1833
1989
|
const [updateSummary, setUpdateSummary] = useState(null);
|
|
1834
1990
|
const [collectionPages, setCollectionPages] = useState({});
|
|
@@ -1934,7 +2090,7 @@ const BulkUpdater = () => {
|
|
|
1934
2090
|
storedAttr = localStorage.getItem(LAST_ATTR_KEY);
|
|
1935
2091
|
} catch {
|
|
1936
2092
|
}
|
|
1937
|
-
const resolvedAttr = storedAttr && activeAttrs.includes(storedAttr) ? storedAttr : selectedAttribute && activeAttrs.includes(selectedAttribute) ? selectedAttribute :
|
|
2093
|
+
const resolvedAttr = storedAttr && activeAttrs.includes(storedAttr) ? storedAttr : selectedAttribute && activeAttrs.includes(selectedAttribute) ? selectedAttribute : "";
|
|
1938
2094
|
setSelectedAttribute(resolvedAttr);
|
|
1939
2095
|
if (resolvedAttr && data.relationsMeta && data.relationsMeta[resolvedAttr]) {
|
|
1940
2096
|
fetchRelationOptions(data.relationsMeta[resolvedAttr].targetUid);
|
|
@@ -1965,8 +2121,7 @@ const BulkUpdater = () => {
|
|
|
1965
2121
|
}
|
|
1966
2122
|
}
|
|
1967
2123
|
} catch (err) {
|
|
1968
|
-
|
|
1969
|
-
if (!isAborted) {
|
|
2124
|
+
if (!isAbortError(err)) {
|
|
1970
2125
|
toggleNotification({
|
|
1971
2126
|
type: "danger",
|
|
1972
2127
|
message: err?.message || "Failed to load collections data"
|
|
@@ -2043,8 +2198,7 @@ const BulkUpdater = () => {
|
|
|
2043
2198
|
}
|
|
2044
2199
|
}
|
|
2045
2200
|
} catch (err) {
|
|
2046
|
-
|
|
2047
|
-
if (!isAborted) {
|
|
2201
|
+
if (!isAbortError(err)) {
|
|
2048
2202
|
toggleNotification({
|
|
2049
2203
|
type: "danger",
|
|
2050
2204
|
message: `Failed to load entries for ${colUid}: ${err?.message || "Network error"}`
|
|
@@ -2073,8 +2227,7 @@ const BulkUpdater = () => {
|
|
|
2073
2227
|
}
|
|
2074
2228
|
}
|
|
2075
2229
|
} catch (err) {
|
|
2076
|
-
|
|
2077
|
-
if (!isAborted) {
|
|
2230
|
+
if (!isAbortError(err)) {
|
|
2078
2231
|
toggleNotification({
|
|
2079
2232
|
type: "danger",
|
|
2080
2233
|
message: err?.message || "Failed to fetch audit history."
|
|
@@ -2156,18 +2309,14 @@ const BulkUpdater = () => {
|
|
|
2156
2309
|
const targetCol = collections.find((c) => c.uid === newUid);
|
|
2157
2310
|
const colAttrs = targetCol?.attributes || [];
|
|
2158
2311
|
setAttributes(colAttrs);
|
|
2159
|
-
if (!colAttrs.includes(selectedAttribute)) {
|
|
2160
|
-
|
|
2161
|
-
setSelectedAttribute(newAttr);
|
|
2312
|
+
if (selectedAttribute && !colAttrs.includes(selectedAttribute)) {
|
|
2313
|
+
setSelectedAttribute("");
|
|
2162
2314
|
try {
|
|
2163
|
-
localStorage.
|
|
2315
|
+
localStorage.removeItem(LAST_ATTR_KEY);
|
|
2164
2316
|
} catch {
|
|
2165
2317
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
} else {
|
|
2169
|
-
setSelectedRelationDocId("");
|
|
2170
|
-
}
|
|
2318
|
+
setSelectedRelationDocId("");
|
|
2319
|
+
setAttributeValue("");
|
|
2171
2320
|
}
|
|
2172
2321
|
loadCollectionPage(newUid, 1, void 0, void 0, void 0, filterOperator, filterQuery, entrySearch, true, "");
|
|
2173
2322
|
};
|
|
@@ -2182,10 +2331,6 @@ const BulkUpdater = () => {
|
|
|
2182
2331
|
}
|
|
2183
2332
|
} catch {
|
|
2184
2333
|
}
|
|
2185
|
-
setSelectedEntries({});
|
|
2186
|
-
setFilterOperator("none");
|
|
2187
|
-
setFilterQuery("");
|
|
2188
|
-
setEntrySearch("");
|
|
2189
2334
|
setSelectedRelationDocId("");
|
|
2190
2335
|
setAttributeValue("");
|
|
2191
2336
|
if (newAttr && relationsMeta[newAttr]) {
|
|
@@ -2193,9 +2338,6 @@ const BulkUpdater = () => {
|
|
|
2193
2338
|
} else {
|
|
2194
2339
|
setRelationOptions([]);
|
|
2195
2340
|
}
|
|
2196
|
-
if (newAttr && selectedCollectionUid) {
|
|
2197
|
-
loadCollectionPage(selectedCollectionUid, 1);
|
|
2198
|
-
}
|
|
2199
2341
|
}
|
|
2200
2342
|
};
|
|
2201
2343
|
const filteredCollections = useMemo(() => {
|
|
@@ -2211,10 +2353,10 @@ const BulkUpdater = () => {
|
|
|
2211
2353
|
return availableColAttributes.filter((attr) => getAttrDepth(attr) <= componentDepth);
|
|
2212
2354
|
}, [availableColAttributes, componentDepth, attributesMeta]);
|
|
2213
2355
|
const filteredAttributes = useMemo(() => {
|
|
2214
|
-
|
|
2356
|
+
const q = attributeSearch.toLowerCase().trim();
|
|
2357
|
+
if (!q || q === (selectedAttribute || "").toLowerCase().trim()) {
|
|
2215
2358
|
return depthFilteredAttributes;
|
|
2216
2359
|
}
|
|
2217
|
-
const q = attributeSearch.toLowerCase().trim();
|
|
2218
2360
|
const cleanQ = q.replace(/[^a-z0-9]/g, "");
|
|
2219
2361
|
return depthFilteredAttributes.filter((attr) => {
|
|
2220
2362
|
const lower = attr.toLowerCase();
|
|
@@ -2223,12 +2365,12 @@ const BulkUpdater = () => {
|
|
|
2223
2365
|
const relTarget = (rel?.targetDisplayName || "").toLowerCase();
|
|
2224
2366
|
return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
|
|
2225
2367
|
});
|
|
2226
|
-
}, [depthFilteredAttributes, attributeSearch, relationsMeta]);
|
|
2368
|
+
}, [depthFilteredAttributes, attributeSearch, selectedAttribute, relationsMeta]);
|
|
2227
2369
|
const filteredSearchAttributes = useMemo(() => {
|
|
2228
|
-
|
|
2370
|
+
const q = searchAttributeSearch.toLowerCase().trim();
|
|
2371
|
+
if (!q || q === (searchAttribute || "").toLowerCase().trim()) {
|
|
2229
2372
|
return depthFilteredAttributes;
|
|
2230
2373
|
}
|
|
2231
|
-
const q = searchAttributeSearch.toLowerCase().trim();
|
|
2232
2374
|
const cleanQ = q.replace(/[^a-z0-9]/g, "");
|
|
2233
2375
|
return depthFilteredAttributes.filter((attr) => {
|
|
2234
2376
|
const lower = attr.toLowerCase();
|
|
@@ -2237,7 +2379,7 @@ const BulkUpdater = () => {
|
|
|
2237
2379
|
const relTarget = (rel?.targetDisplayName || "").toLowerCase();
|
|
2238
2380
|
return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
|
|
2239
2381
|
});
|
|
2240
|
-
}, [depthFilteredAttributes, searchAttributeSearch, relationsMeta]);
|
|
2382
|
+
}, [depthFilteredAttributes, searchAttributeSearch, searchAttribute, relationsMeta]);
|
|
2241
2383
|
const memoizedComboboxOptions = useMemo(() => {
|
|
2242
2384
|
if (filteredAttributes.length === 0) {
|
|
2243
2385
|
return /* @__PURE__ */ jsx(ComboboxOption, { value: "__none__", disabled: true, textValue: "No matching attributes found", children: /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
@@ -2373,24 +2515,25 @@ const BulkUpdater = () => {
|
|
|
2373
2515
|
};
|
|
2374
2516
|
const getVisibleEntries = (col) => {
|
|
2375
2517
|
const pageState = collectionPages[col.uid];
|
|
2376
|
-
|
|
2518
|
+
const raw = pageState ? pageState.entries : col.entries || [];
|
|
2519
|
+
if (statusFilter === "all") return raw;
|
|
2520
|
+
return raw.filter((entry) => {
|
|
2521
|
+
const lifecycle = getEntryLifecycleStatus(entry, col, pendingBatches);
|
|
2522
|
+
return lifecycle.status === statusFilter;
|
|
2523
|
+
});
|
|
2377
2524
|
};
|
|
2378
2525
|
const matchingEntriesCount = React__default.useMemo(() => {
|
|
2379
2526
|
if (!isFilterActive) return 0;
|
|
2380
2527
|
let count = 0;
|
|
2381
2528
|
filteredCollections.forEach((col) => {
|
|
2382
|
-
|
|
2383
|
-
if (pageState) {
|
|
2384
|
-
count += pageState.total;
|
|
2385
|
-
}
|
|
2529
|
+
count += getVisibleEntries(col).length;
|
|
2386
2530
|
});
|
|
2387
2531
|
return count;
|
|
2388
|
-
}, [filteredCollections, collectionPages, isFilterActive]);
|
|
2532
|
+
}, [filteredCollections, collectionPages, isFilterActive, statusFilter, pendingBatches]);
|
|
2389
2533
|
const selectAllMatching = () => {
|
|
2390
2534
|
const updated = { ...selectedEntries };
|
|
2391
2535
|
filteredCollections.forEach((col) => {
|
|
2392
|
-
const
|
|
2393
|
-
const entries = pageState ? pageState.entries : col.entries || [];
|
|
2536
|
+
const entries = getVisibleEntries(col);
|
|
2394
2537
|
entries.forEach((e) => {
|
|
2395
2538
|
updated[`${col.uid}${KEY_SEP}${e.documentId}`] = true;
|
|
2396
2539
|
});
|
|
@@ -2400,8 +2543,7 @@ const BulkUpdater = () => {
|
|
|
2400
2543
|
const deselectAllMatching = () => {
|
|
2401
2544
|
const updated = { ...selectedEntries };
|
|
2402
2545
|
filteredCollections.forEach((col) => {
|
|
2403
|
-
const
|
|
2404
|
-
const entries = pageState ? pageState.entries : col.entries || [];
|
|
2546
|
+
const entries = getVisibleEntries(col);
|
|
2405
2547
|
entries.forEach((e) => {
|
|
2406
2548
|
delete updated[`${col.uid}${KEY_SEP}${e.documentId}`];
|
|
2407
2549
|
});
|
|
@@ -2414,6 +2556,7 @@ const BulkUpdater = () => {
|
|
|
2414
2556
|
setFilterOperator("none");
|
|
2415
2557
|
setFilterQuery("");
|
|
2416
2558
|
setEntrySearch("");
|
|
2559
|
+
setStatusFilter("all");
|
|
2417
2560
|
setRegexPattern("");
|
|
2418
2561
|
setSelectedEntries({});
|
|
2419
2562
|
collections.forEach((col) => {
|
|
@@ -2534,10 +2677,12 @@ const BulkUpdater = () => {
|
|
|
2534
2677
|
throw new Error(res.data?.error || "Failed to generate preview");
|
|
2535
2678
|
}
|
|
2536
2679
|
} catch (err) {
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2680
|
+
if (!isAbortError(err)) {
|
|
2681
|
+
toggleNotification({
|
|
2682
|
+
type: "danger",
|
|
2683
|
+
message: err.message || "Failed to fetch preview diffs"
|
|
2684
|
+
});
|
|
2685
|
+
}
|
|
2541
2686
|
setShowPreviewModal(false);
|
|
2542
2687
|
} finally {
|
|
2543
2688
|
setPreviewLoading(false);
|
|
@@ -3270,349 +3415,128 @@ const BulkUpdater = () => {
|
|
|
3270
3415
|
marginBottom: 6,
|
|
3271
3416
|
style: { width: "100%", maxWidth: "100%", minWidth: 0, boxSizing: "border-box" },
|
|
3272
3417
|
children: [
|
|
3273
|
-
/* @__PURE__ */
|
|
3274
|
-
/* @__PURE__ */
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3418
|
+
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, wrap: "wrap", gap: 3, children: [
|
|
3419
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
3420
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", fontWeight: "semiBold", children: "1. Search & Filter Targets" }),
|
|
3421
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
3422
|
+
"Search, filter, and select entries within ",
|
|
3423
|
+
selectedCol ? selectedCol.displayName : "the selected collection",
|
|
3424
|
+
" before updating."
|
|
3425
|
+
] })
|
|
3426
|
+
] }),
|
|
3427
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
3428
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "S", onClick: selectAll, children: "Select All" }),
|
|
3429
|
+
/* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "S", onClick: deselectAll, children: "Deselect All" })
|
|
3430
|
+
] })
|
|
3431
|
+
] }),
|
|
3432
|
+
/* @__PURE__ */ jsx(
|
|
3433
|
+
Box,
|
|
3434
|
+
{
|
|
3435
|
+
padding: 4,
|
|
3436
|
+
background: "neutral100",
|
|
3437
|
+
hasRadius: true,
|
|
3438
|
+
marginBottom: 5,
|
|
3439
|
+
style: { width: "100%", maxWidth: "100%", boxSizing: "border-box" },
|
|
3440
|
+
children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
|
3441
|
+
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 2, children: [
|
|
3442
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3443
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", children: "Search & Filter Targets:" }),
|
|
3444
|
+
isFilterActive && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
3445
|
+
matchingEntriesCount,
|
|
3446
|
+
" matching ",
|
|
3447
|
+
matchingEntriesCount === 1 ? "entry" : "entries",
|
|
3448
|
+
" found in database"
|
|
3449
|
+
] }),
|
|
3450
|
+
searchAttribute && searchAttribute !== selectedAttribute && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: [
|
|
3451
|
+
"Searching by: ",
|
|
3452
|
+
searchAttribute,
|
|
3453
|
+
" → Target to update: ",
|
|
3454
|
+
selectedAttribute
|
|
3455
|
+
] })
|
|
3456
|
+
] }),
|
|
3457
|
+
isFilterActive && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "S", onClick: clearFilter, children: "Clear Search & Filter" })
|
|
3458
|
+
] }),
|
|
3459
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "flex-end", wrap: "wrap", children: [
|
|
3460
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 280, minWidth: 230 }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
3461
|
+
/* @__PURE__ */ jsx(Field.Label, { children: "Search Attribute" }),
|
|
3462
|
+
/* @__PURE__ */ jsx(
|
|
3463
|
+
Combobox,
|
|
3464
|
+
{
|
|
3465
|
+
autocomplete: "none",
|
|
3466
|
+
placeholder: searchAttribute || `Same as Update (${selectedAttribute || "None"})`,
|
|
3467
|
+
value: searchAttribute || "__default__",
|
|
3468
|
+
clearLabel: "Reset search attribute",
|
|
3469
|
+
onClear: () => {
|
|
3470
|
+
handleSearchAttributeChange("");
|
|
3471
|
+
setSearchAttributeSearch("");
|
|
3472
|
+
},
|
|
3473
|
+
onInputChange: (e) => {
|
|
3474
|
+
setSearchAttributeSearch(e.target.value);
|
|
3475
|
+
},
|
|
3476
|
+
onOpenChange: (isOpen) => {
|
|
3477
|
+
if (!isOpen) {
|
|
3478
|
+
setSearchAttributeSearch("");
|
|
3479
|
+
}
|
|
3480
|
+
},
|
|
3481
|
+
onChange: (val) => {
|
|
3482
|
+
if (val && typeof val === "string" && val !== "__none__") {
|
|
3483
|
+
handleSearchAttributeChange(val);
|
|
3484
|
+
setSearchAttributeSearch("");
|
|
3485
|
+
}
|
|
3486
|
+
},
|
|
3487
|
+
children: memoizedSearchComboboxOptions
|
|
3488
|
+
},
|
|
3489
|
+
`search-attr-${selectedCollectionUid}`
|
|
3490
|
+
)
|
|
3491
|
+
] }) }),
|
|
3492
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 200, minWidth: 170 }, children: /* @__PURE__ */ jsxs(
|
|
3493
|
+
SingleSelect,
|
|
3494
|
+
{
|
|
3495
|
+
label: effectiveSearchAttribute ? `Condition for "${effectiveSearchAttribute}"` : "Filter condition",
|
|
3496
|
+
value: filterOperator,
|
|
3497
|
+
onChange: (val) => setFilterOperator(String(val)),
|
|
3498
|
+
children: [
|
|
3499
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "none", children: "Show All (No Value Filter)" }),
|
|
3500
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "empty", children: "Is Empty or Null" }),
|
|
3501
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "not_empty", children: "Is Not Empty" }),
|
|
3502
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "equals", children: "Equals Exact Text" }),
|
|
3503
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "contains", children: "Contains Substring" }),
|
|
3504
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "starts_with", children: "Starts With" })
|
|
3505
|
+
]
|
|
3297
3506
|
}
|
|
3298
|
-
},
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3507
|
+
) }),
|
|
3508
|
+
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
3509
|
+
TextInput,
|
|
3510
|
+
{
|
|
3511
|
+
label: effectiveSearchAttribute ? `Value for "${effectiveSearchAttribute}"` : "Value to match",
|
|
3512
|
+
placeholder: "Type value to match...",
|
|
3513
|
+
value: filterQuery,
|
|
3514
|
+
onChange: (e) => setFilterQuery(e.target.value)
|
|
3305
3515
|
}
|
|
3306
|
-
},
|
|
3307
|
-
children:
|
|
3308
|
-
|
|
3309
|
-
`update-attr-${selectedCollectionUid}-${selectedAttribute}`
|
|
3310
|
-
)
|
|
3311
|
-
] }) }),
|
|
3312
|
-
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 340 }, children: relationsMeta[selectedAttribute] ? /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, style: { width: "100%" }, children: [
|
|
3313
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3314
|
-
/* @__PURE__ */ jsxs(Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral700", children: [
|
|
3315
|
-
"Target ",
|
|
3316
|
-
relationsMeta[selectedAttribute].targetDisplayName,
|
|
3317
|
-
" Relation:"
|
|
3318
|
-
] }),
|
|
3319
|
-
/* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: [
|
|
3320
|
-
relationsMeta[selectedAttribute].relationType,
|
|
3321
|
-
" → ",
|
|
3322
|
-
relationsMeta[selectedAttribute].targetDisplayName
|
|
3323
|
-
] }),
|
|
3324
|
-
relationsMeta[selectedAttribute].isMulti && /* @__PURE__ */ jsx(Badge, { backgroundColor: "primary100", textColor: "primary700", children: "Multi-Relation" })
|
|
3325
|
-
] }),
|
|
3326
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", style: { width: "100%" }, children: [
|
|
3327
|
-
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
3328
|
-
/* @__PURE__ */ jsx(Field.Label, { children: `Choose ${relationsMeta[selectedAttribute].targetDisplayName}` }),
|
|
3329
|
-
/* @__PURE__ */ jsxs(
|
|
3330
|
-
Combobox,
|
|
3516
|
+
) }),
|
|
3517
|
+
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
3518
|
+
TextInput,
|
|
3331
3519
|
{
|
|
3332
|
-
|
|
3333
|
-
placeholder:
|
|
3334
|
-
value:
|
|
3335
|
-
onChange: (
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
},
|
|
3520
|
+
label: "Full-text Entry Search",
|
|
3521
|
+
placeholder: "Search title, name, or text across records...",
|
|
3522
|
+
value: entrySearch,
|
|
3523
|
+
onChange: (e) => setEntrySearch(e.target.value)
|
|
3524
|
+
}
|
|
3525
|
+
) }),
|
|
3526
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 190, minWidth: 160 }, children: /* @__PURE__ */ jsxs(
|
|
3527
|
+
SingleSelect,
|
|
3528
|
+
{
|
|
3529
|
+
label: "Lifecycle Status",
|
|
3530
|
+
value: statusFilter,
|
|
3531
|
+
onChange: (val) => setStatusFilter(String(val)),
|
|
3345
3532
|
children: [
|
|
3346
|
-
/* @__PURE__ */ jsx(
|
|
3347
|
-
|
|
3533
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "all", children: "All Statuses" }),
|
|
3534
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "pending_review", children: "Pending Review (Due)" }),
|
|
3535
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "draft", children: "Draft" }),
|
|
3536
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "published", children: "Published" }),
|
|
3537
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "modified", children: "Modified" })
|
|
3348
3538
|
]
|
|
3349
3539
|
}
|
|
3350
|
-
)
|
|
3351
|
-
] }) }),
|
|
3352
|
-
relationsMeta[selectedAttribute].isMulti && /* @__PURE__ */ jsx(Box, { style: { width: 170 }, children: /* @__PURE__ */ jsxs(
|
|
3353
|
-
SingleSelect,
|
|
3354
|
-
{
|
|
3355
|
-
label: "Action Mode",
|
|
3356
|
-
value: relationMode,
|
|
3357
|
-
onChange: (val) => {
|
|
3358
|
-
const m = String(val);
|
|
3359
|
-
setRelationMode(m);
|
|
3360
|
-
if (selectedRelationDocId) {
|
|
3361
|
-
if (selectedRelationDocId === "__clear__" || m === "clear") {
|
|
3362
|
-
setAttributeValue(JSON.stringify({ mode: "clear", label: "(clear relation)" }));
|
|
3363
|
-
} else {
|
|
3364
|
-
const opt = relationOptions.find((o) => o.documentId === selectedRelationDocId);
|
|
3365
|
-
setAttributeValue(JSON.stringify({ mode: m, documentIds: [selectedRelationDocId], label: opt?.label || selectedRelationDocId }));
|
|
3366
|
-
}
|
|
3367
|
-
}
|
|
3368
|
-
},
|
|
3369
|
-
children: [
|
|
3370
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "set", children: "Set / Overwrite" }),
|
|
3371
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "connect", children: "Add / Connect" }),
|
|
3372
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "disconnect", children: "Remove / Disconnect" }),
|
|
3373
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "clear", children: "Clear All" })
|
|
3374
|
-
]
|
|
3375
|
-
}
|
|
3376
|
-
) })
|
|
3377
|
-
] })
|
|
3378
|
-
] }) : /* @__PURE__ */ jsx(
|
|
3379
|
-
TextInput,
|
|
3380
|
-
{
|
|
3381
|
-
label: useRegex ? "Replacement Value" : "New Attribute Value",
|
|
3382
|
-
name: "attributeValue",
|
|
3383
|
-
placeholder: useRegex ? "Replace matched pattern with..." : "Enter the value to apply...",
|
|
3384
|
-
value: attributeValue,
|
|
3385
|
-
onChange: (e) => setAttributeValue(e.target.value)
|
|
3386
|
-
}
|
|
3387
|
-
) }),
|
|
3388
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3389
|
-
/* @__PURE__ */ jsxs(
|
|
3390
|
-
Button,
|
|
3391
|
-
{
|
|
3392
|
-
startIcon: /* @__PURE__ */ jsx(Eye, {}),
|
|
3393
|
-
variant: "secondary",
|
|
3394
|
-
size: "L",
|
|
3395
|
-
onClick: handleOpenPreviewModal,
|
|
3396
|
-
loading: previewLoading,
|
|
3397
|
-
disabled: loading || totalSelectedCount === 0 || !selectedAttribute,
|
|
3398
|
-
children: [
|
|
3399
|
-
"Preview Changes (",
|
|
3400
|
-
totalSelectedCount,
|
|
3401
|
-
")"
|
|
3402
|
-
]
|
|
3403
|
-
}
|
|
3404
|
-
),
|
|
3405
|
-
/* @__PURE__ */ jsxs(
|
|
3406
|
-
Button,
|
|
3407
|
-
{
|
|
3408
|
-
startIcon: /* @__PURE__ */ jsx(Play, {}),
|
|
3409
|
-
variant: "default",
|
|
3410
|
-
size: "L",
|
|
3411
|
-
onClick: handleOpenConfirmModal,
|
|
3412
|
-
loading: updating,
|
|
3413
|
-
disabled: loading || totalSelectedCount === 0 || !selectedAttribute,
|
|
3414
|
-
children: [
|
|
3415
|
-
"Update Selected (",
|
|
3416
|
-
totalSelectedCount,
|
|
3417
|
-
")"
|
|
3418
|
-
]
|
|
3419
|
-
}
|
|
3420
|
-
),
|
|
3421
|
-
/* @__PURE__ */ jsxs(
|
|
3422
|
-
Button,
|
|
3423
|
-
{
|
|
3424
|
-
startIcon: /* @__PURE__ */ jsx(Check, {}),
|
|
3425
|
-
variant: "success-light",
|
|
3426
|
-
size: "L",
|
|
3427
|
-
onClick: handleOpenPublishModal,
|
|
3428
|
-
loading: publishing,
|
|
3429
|
-
disabled: loading || totalSelectedCount === 0,
|
|
3430
|
-
title: "Directly publish selected draft records across collections",
|
|
3431
|
-
children: [
|
|
3432
|
-
"Publish Selected (",
|
|
3433
|
-
totalSelectedCount,
|
|
3434
|
-
")"
|
|
3435
|
-
]
|
|
3436
|
-
}
|
|
3437
|
-
),
|
|
3438
|
-
/* @__PURE__ */ jsxs(
|
|
3439
|
-
Button,
|
|
3440
|
-
{
|
|
3441
|
-
startIcon: /* @__PURE__ */ jsx(Download, {}),
|
|
3442
|
-
variant: "tertiary",
|
|
3443
|
-
size: "L",
|
|
3444
|
-
onClick: handleBulkExportSelected,
|
|
3445
|
-
loading: bulkExporting,
|
|
3446
|
-
disabled: loading || totalSelectedCount === 0,
|
|
3447
|
-
title: "Export selected entries to Excel-compatible CSV with full nested component support",
|
|
3448
|
-
children: [
|
|
3449
|
-
"Export Selected (",
|
|
3450
|
-
totalSelectedCount,
|
|
3451
|
-
")"
|
|
3452
|
-
]
|
|
3453
|
-
}
|
|
3454
|
-
)
|
|
3455
|
-
] })
|
|
3456
|
-
] }),
|
|
3457
|
-
/* @__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: [
|
|
3458
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
3459
|
-
/* @__PURE__ */ jsx(
|
|
3460
|
-
Checkbox,
|
|
3461
|
-
{
|
|
3462
|
-
checked: publishOnApproval,
|
|
3463
|
-
onCheckedChange: (checked) => setPublishOnApproval(Boolean(checked)),
|
|
3464
|
-
children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: "Auto-Publish after Update" })
|
|
3465
|
-
}
|
|
3466
|
-
),
|
|
3467
|
-
/* @__PURE__ */ jsx(
|
|
3468
|
-
Badge,
|
|
3469
|
-
{
|
|
3470
|
-
backgroundColor: publishOnApproval ? "success100" : "warning100",
|
|
3471
|
-
textColor: publishOnApproval ? "success700" : "warning700",
|
|
3472
|
-
children: publishOnApproval ? "✓ LIVE PUBLISH" : "DRAFT ONLY"
|
|
3473
|
-
}
|
|
3474
|
-
)
|
|
3475
|
-
] }),
|
|
3476
|
-
/* @__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." })
|
|
3477
|
-
] }) }),
|
|
3478
|
-
selectedCol && selectedAttribute && /* @__PURE__ */ jsx(Box, { marginTop: 4, padding: 3, background: "neutral100", hasRadius: true, style: { border: "1px solid #eaeaef" }, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 3, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3479
|
-
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "Target Selection:" }),
|
|
3480
|
-
/* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
3481
|
-
"Collection: ",
|
|
3482
|
-
selectedCol.displayName
|
|
3483
|
-
] }),
|
|
3484
|
-
/* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: [
|
|
3485
|
-
"Attribute: ",
|
|
3486
|
-
selectedAttribute,
|
|
3487
|
-
" ",
|
|
3488
|
-
attributesMeta[selectedAttribute]?.type ? `(${attributesMeta[selectedAttribute].type})` : ""
|
|
3489
|
-
] }),
|
|
3490
|
-
attributesMeta[selectedAttribute]?.depth ? /* @__PURE__ */ jsxs(Badge, { backgroundColor: "neutral200", textColor: "neutral700", children: [
|
|
3491
|
-
"Nesting Level: L",
|
|
3492
|
-
attributesMeta[selectedAttribute].depth
|
|
3493
|
-
] }) : null,
|
|
3494
|
-
selectedCol.draftAndPublish ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "success100", textColor: "success700", children: "Draft & Publish Enabled" }) : /* @__PURE__ */ jsx(Badge, { backgroundColor: "warning100", textColor: "warning700", children: "Direct Publish Only" })
|
|
3495
|
-
] }) }) })
|
|
3496
|
-
]
|
|
3497
|
-
}
|
|
3498
|
-
),
|
|
3499
|
-
/* @__PURE__ */ jsxs(
|
|
3500
|
-
Box,
|
|
3501
|
-
{
|
|
3502
|
-
padding: 6,
|
|
3503
|
-
background: "neutral0",
|
|
3504
|
-
shadow: "filterShadow",
|
|
3505
|
-
hasRadius: true,
|
|
3506
|
-
marginBottom: 6,
|
|
3507
|
-
style: { width: "100%", maxWidth: "100%", minWidth: 0, boxSizing: "border-box" },
|
|
3508
|
-
children: [
|
|
3509
|
-
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, wrap: "wrap", gap: 3, children: [
|
|
3510
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
3511
|
-
/* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", fontWeight: "semiBold", children: "2. Select Targets" }),
|
|
3512
|
-
/* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
3513
|
-
"Search and select entries to apply the update to within ",
|
|
3514
|
-
selectedCol ? selectedCol.displayName : "the selected collection",
|
|
3515
|
-
"."
|
|
3516
|
-
] })
|
|
3517
|
-
] }),
|
|
3518
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
3519
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "S", onClick: selectAll, children: "Select All" }),
|
|
3520
|
-
/* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "S", onClick: deselectAll, children: "Deselect All" })
|
|
3521
|
-
] })
|
|
3522
|
-
] }),
|
|
3523
|
-
/* @__PURE__ */ jsx(
|
|
3524
|
-
Box,
|
|
3525
|
-
{
|
|
3526
|
-
padding: 4,
|
|
3527
|
-
background: "neutral100",
|
|
3528
|
-
hasRadius: true,
|
|
3529
|
-
marginBottom: 5,
|
|
3530
|
-
style: { width: "100%", maxWidth: "100%", boxSizing: "border-box" },
|
|
3531
|
-
children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
|
3532
|
-
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 2, children: [
|
|
3533
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3534
|
-
/* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", children: "Search & Filter Targets:" }),
|
|
3535
|
-
isFilterActive && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
3536
|
-
matchingEntriesCount,
|
|
3537
|
-
" matching ",
|
|
3538
|
-
matchingEntriesCount === 1 ? "entry" : "entries",
|
|
3539
|
-
" found in database"
|
|
3540
|
-
] }),
|
|
3541
|
-
searchAttribute && searchAttribute !== selectedAttribute && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: [
|
|
3542
|
-
"Searching by: ",
|
|
3543
|
-
searchAttribute,
|
|
3544
|
-
" → Target to update: ",
|
|
3545
|
-
selectedAttribute
|
|
3546
|
-
] })
|
|
3547
|
-
] }),
|
|
3548
|
-
isFilterActive && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "S", onClick: clearFilter, children: "Clear Search & Filter" })
|
|
3549
|
-
] }),
|
|
3550
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "flex-end", wrap: "wrap", children: [
|
|
3551
|
-
/* @__PURE__ */ jsx(Box, { style: { width: 280, minWidth: 230 }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
3552
|
-
/* @__PURE__ */ jsx(Field.Label, { children: "Search Attribute" }),
|
|
3553
|
-
/* @__PURE__ */ jsx(
|
|
3554
|
-
Combobox,
|
|
3555
|
-
{
|
|
3556
|
-
autocomplete: "none",
|
|
3557
|
-
placeholder: searchAttribute || `Same as Update (${selectedAttribute || "None"})`,
|
|
3558
|
-
value: searchAttribute || "__default__",
|
|
3559
|
-
clearLabel: "Reset search attribute",
|
|
3560
|
-
onClear: () => {
|
|
3561
|
-
handleSearchAttributeChange("");
|
|
3562
|
-
setSearchAttributeSearch("");
|
|
3563
|
-
},
|
|
3564
|
-
onInputChange: (e) => {
|
|
3565
|
-
setSearchAttributeSearch(e.target.value);
|
|
3566
|
-
},
|
|
3567
|
-
onOpenChange: (isOpen) => {
|
|
3568
|
-
if (!isOpen) {
|
|
3569
|
-
setSearchAttributeSearch("");
|
|
3570
|
-
}
|
|
3571
|
-
},
|
|
3572
|
-
onChange: (val) => {
|
|
3573
|
-
if (val && typeof val === "string" && val !== "__none__") {
|
|
3574
|
-
handleSearchAttributeChange(val);
|
|
3575
|
-
setSearchAttributeSearch("");
|
|
3576
|
-
}
|
|
3577
|
-
},
|
|
3578
|
-
children: memoizedSearchComboboxOptions
|
|
3579
|
-
},
|
|
3580
|
-
`search-attr-${selectedCollectionUid}-${searchAttribute}`
|
|
3581
|
-
)
|
|
3582
|
-
] }) }),
|
|
3583
|
-
/* @__PURE__ */ jsx(Box, { style: { width: 200, minWidth: 170 }, children: /* @__PURE__ */ jsxs(
|
|
3584
|
-
SingleSelect,
|
|
3585
|
-
{
|
|
3586
|
-
label: effectiveSearchAttribute ? `Condition for "${effectiveSearchAttribute}"` : "Filter condition",
|
|
3587
|
-
value: filterOperator,
|
|
3588
|
-
onChange: (val) => setFilterOperator(String(val)),
|
|
3589
|
-
children: [
|
|
3590
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "none", children: "Show All (No Value Filter)" }),
|
|
3591
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "empty", children: "Is Empty or Null" }),
|
|
3592
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "not_empty", children: "Is Not Empty" }),
|
|
3593
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "equals", children: "Equals Exact Text" }),
|
|
3594
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "contains", children: "Contains Substring" }),
|
|
3595
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "starts_with", children: "Starts With" })
|
|
3596
|
-
]
|
|
3597
|
-
}
|
|
3598
|
-
) }),
|
|
3599
|
-
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
3600
|
-
TextInput,
|
|
3601
|
-
{
|
|
3602
|
-
label: effectiveSearchAttribute ? `Value for "${effectiveSearchAttribute}"` : "Value to match",
|
|
3603
|
-
placeholder: "Type value to match...",
|
|
3604
|
-
value: filterQuery,
|
|
3605
|
-
onChange: (e) => setFilterQuery(e.target.value)
|
|
3606
|
-
}
|
|
3607
|
-
) }),
|
|
3608
|
-
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
3609
|
-
TextInput,
|
|
3610
|
-
{
|
|
3611
|
-
label: "Full-text Entry Search",
|
|
3612
|
-
placeholder: "Search title, name, or text across records...",
|
|
3613
|
-
value: entrySearch,
|
|
3614
|
-
onChange: (e) => setEntrySearch(e.target.value)
|
|
3615
|
-
}
|
|
3616
3540
|
) }),
|
|
3617
3541
|
isFilterActive && /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
3618
3542
|
/* @__PURE__ */ jsx(
|
|
@@ -4016,7 +3940,8 @@ const BulkUpdater = () => {
|
|
|
4016
3940
|
isMatch,
|
|
4017
3941
|
hasAttr,
|
|
4018
3942
|
isSelected,
|
|
4019
|
-
() => toggleEntry(col.uid, entry.documentId)
|
|
3943
|
+
() => toggleEntry(col.uid, entry.documentId),
|
|
3944
|
+
pendingBatches
|
|
4020
3945
|
) }, colDef.key))
|
|
4021
3946
|
},
|
|
4022
3947
|
key
|
|
@@ -4107,6 +4032,242 @@ const BulkUpdater = () => {
|
|
|
4107
4032
|
]
|
|
4108
4033
|
}
|
|
4109
4034
|
),
|
|
4035
|
+
/* @__PURE__ */ jsxs(
|
|
4036
|
+
Box,
|
|
4037
|
+
{
|
|
4038
|
+
padding: 6,
|
|
4039
|
+
background: "neutral0",
|
|
4040
|
+
shadow: "filterShadow",
|
|
4041
|
+
hasRadius: true,
|
|
4042
|
+
marginBottom: 6,
|
|
4043
|
+
style: { width: "100%", maxWidth: "100%", minWidth: 0, boxSizing: "border-box" },
|
|
4044
|
+
children: [
|
|
4045
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, wrap: "wrap", gap: 3, children: /* @__PURE__ */ jsxs(Box, { children: [
|
|
4046
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", fontWeight: "semiBold", children: "2. Configure Attribute Update" }),
|
|
4047
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Select the target attribute to update and configure the replacement value for your selected entries." })
|
|
4048
|
+
] }) }),
|
|
4049
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "flex-end", wrap: "wrap", children: [
|
|
4050
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 280, minWidth: 230 }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
4051
|
+
/* @__PURE__ */ jsx(Field.Label, { children: "Attribute to Update" }),
|
|
4052
|
+
/* @__PURE__ */ jsx(
|
|
4053
|
+
Combobox,
|
|
4054
|
+
{
|
|
4055
|
+
autocomplete: "none",
|
|
4056
|
+
placeholder: "Search attribute by name or relation...",
|
|
4057
|
+
value: selectedAttribute || void 0,
|
|
4058
|
+
clearLabel: "Clear attribute selection",
|
|
4059
|
+
onClear: () => {
|
|
4060
|
+
handleAttributeChange("");
|
|
4061
|
+
setAttributeSearch("");
|
|
4062
|
+
},
|
|
4063
|
+
onInputChange: (e) => {
|
|
4064
|
+
setAttributeSearch(e.target.value);
|
|
4065
|
+
},
|
|
4066
|
+
onOpenChange: (isOpen) => {
|
|
4067
|
+
if (!isOpen) {
|
|
4068
|
+
setAttributeSearch("");
|
|
4069
|
+
}
|
|
4070
|
+
},
|
|
4071
|
+
loading: loading && attributes.length === 0,
|
|
4072
|
+
loadingMessage: "Discovering schema attributes...",
|
|
4073
|
+
onChange: (val) => {
|
|
4074
|
+
if (val && typeof val === "string" && val !== "__none__") {
|
|
4075
|
+
handleAttributeChange(val);
|
|
4076
|
+
setAttributeSearch("");
|
|
4077
|
+
}
|
|
4078
|
+
},
|
|
4079
|
+
children: memoizedComboboxOptions
|
|
4080
|
+
},
|
|
4081
|
+
`update-attr-${selectedCollectionUid}`
|
|
4082
|
+
)
|
|
4083
|
+
] }) }),
|
|
4084
|
+
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 340 }, children: relationsMeta[selectedAttribute] ? /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, style: { width: "100%" }, children: [
|
|
4085
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
4086
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral700", children: [
|
|
4087
|
+
"Target ",
|
|
4088
|
+
relationsMeta[selectedAttribute].targetDisplayName,
|
|
4089
|
+
" Relation:"
|
|
4090
|
+
] }),
|
|
4091
|
+
/* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: [
|
|
4092
|
+
relationsMeta[selectedAttribute].relationType,
|
|
4093
|
+
" → ",
|
|
4094
|
+
relationsMeta[selectedAttribute].targetDisplayName
|
|
4095
|
+
] }),
|
|
4096
|
+
relationsMeta[selectedAttribute].isMulti && /* @__PURE__ */ jsx(Badge, { backgroundColor: "primary100", textColor: "primary700", children: "Multi-Relation" })
|
|
4097
|
+
] }),
|
|
4098
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", style: { width: "100%" }, children: [
|
|
4099
|
+
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
4100
|
+
/* @__PURE__ */ jsx(Field.Label, { children: `Choose ${relationsMeta[selectedAttribute].targetDisplayName}` }),
|
|
4101
|
+
/* @__PURE__ */ jsxs(
|
|
4102
|
+
Combobox,
|
|
4103
|
+
{
|
|
4104
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
4105
|
+
placeholder: relationOptionsLoading ? "Loading entities..." : `Search & pick ${relationsMeta[selectedAttribute].targetDisplayName}...`,
|
|
4106
|
+
value: selectedRelationDocId,
|
|
4107
|
+
onChange: (val) => {
|
|
4108
|
+
const docId = val ? String(val) : "";
|
|
4109
|
+
setSelectedRelationDocId(docId);
|
|
4110
|
+
if (docId === "__clear__") {
|
|
4111
|
+
setAttributeValue(JSON.stringify({ mode: "clear", label: "(clear relation)" }));
|
|
4112
|
+
} else {
|
|
4113
|
+
const opt = relationOptions.find((o) => o.documentId === docId);
|
|
4114
|
+
setAttributeValue(JSON.stringify({ mode: relationMode, documentIds: [docId], label: opt?.label || docId }));
|
|
4115
|
+
}
|
|
4116
|
+
},
|
|
4117
|
+
children: [
|
|
4118
|
+
/* @__PURE__ */ jsx(ComboboxOption, { value: "__clear__", textValue: "Clear / Unlink Relation", children: "-- Clear / Unlink Relation --" }),
|
|
4119
|
+
relationOptions.map((opt) => /* @__PURE__ */ jsx(ComboboxOption, { value: opt.documentId, textValue: opt.label, children: opt.label }, opt.documentId))
|
|
4120
|
+
]
|
|
4121
|
+
}
|
|
4122
|
+
)
|
|
4123
|
+
] }) }),
|
|
4124
|
+
relationsMeta[selectedAttribute].isMulti && /* @__PURE__ */ jsx(Box, { style: { width: 170 }, children: /* @__PURE__ */ jsxs(
|
|
4125
|
+
SingleSelect,
|
|
4126
|
+
{
|
|
4127
|
+
label: "Action Mode",
|
|
4128
|
+
value: relationMode,
|
|
4129
|
+
onChange: (val) => {
|
|
4130
|
+
const m = String(val);
|
|
4131
|
+
setRelationMode(m);
|
|
4132
|
+
if (selectedRelationDocId) {
|
|
4133
|
+
if (selectedRelationDocId === "__clear__" || m === "clear") {
|
|
4134
|
+
setAttributeValue(JSON.stringify({ mode: "clear", label: "(clear relation)" }));
|
|
4135
|
+
} else {
|
|
4136
|
+
const opt = relationOptions.find((o) => o.documentId === selectedRelationDocId);
|
|
4137
|
+
setAttributeValue(JSON.stringify({ mode: m, documentIds: [selectedRelationDocId], label: opt?.label || selectedRelationDocId }));
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
},
|
|
4141
|
+
children: [
|
|
4142
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "set", children: "Set / Overwrite" }),
|
|
4143
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "connect", children: "Add / Connect" }),
|
|
4144
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "disconnect", children: "Remove / Disconnect" }),
|
|
4145
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "clear", children: "Clear All" })
|
|
4146
|
+
]
|
|
4147
|
+
}
|
|
4148
|
+
) })
|
|
4149
|
+
] })
|
|
4150
|
+
] }) : /* @__PURE__ */ jsx(
|
|
4151
|
+
TextInput,
|
|
4152
|
+
{
|
|
4153
|
+
label: useRegex ? "Replacement Value" : "New Attribute Value",
|
|
4154
|
+
name: "attributeValue",
|
|
4155
|
+
placeholder: useRegex ? "Replace matched pattern with..." : "Enter the value to apply...",
|
|
4156
|
+
value: attributeValue,
|
|
4157
|
+
onChange: (e) => setAttributeValue(e.target.value)
|
|
4158
|
+
}
|
|
4159
|
+
) }),
|
|
4160
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
4161
|
+
/* @__PURE__ */ jsxs(
|
|
4162
|
+
Button,
|
|
4163
|
+
{
|
|
4164
|
+
startIcon: /* @__PURE__ */ jsx(Eye, {}),
|
|
4165
|
+
variant: "secondary",
|
|
4166
|
+
size: "L",
|
|
4167
|
+
onClick: handleOpenPreviewModal,
|
|
4168
|
+
loading: previewLoading,
|
|
4169
|
+
disabled: loading || totalSelectedCount === 0 || !selectedAttribute || !selectedAttribute.trim(),
|
|
4170
|
+
children: [
|
|
4171
|
+
"Preview Changes (",
|
|
4172
|
+
totalSelectedCount,
|
|
4173
|
+
")"
|
|
4174
|
+
]
|
|
4175
|
+
}
|
|
4176
|
+
),
|
|
4177
|
+
/* @__PURE__ */ jsxs(
|
|
4178
|
+
Button,
|
|
4179
|
+
{
|
|
4180
|
+
startIcon: /* @__PURE__ */ jsx(Play, {}),
|
|
4181
|
+
variant: "default",
|
|
4182
|
+
size: "L",
|
|
4183
|
+
onClick: handleOpenConfirmModal,
|
|
4184
|
+
loading: updating,
|
|
4185
|
+
disabled: loading || totalSelectedCount === 0 || !selectedAttribute || !selectedAttribute.trim(),
|
|
4186
|
+
children: [
|
|
4187
|
+
"Update Selected (",
|
|
4188
|
+
totalSelectedCount,
|
|
4189
|
+
")"
|
|
4190
|
+
]
|
|
4191
|
+
}
|
|
4192
|
+
),
|
|
4193
|
+
/* @__PURE__ */ jsxs(
|
|
4194
|
+
Button,
|
|
4195
|
+
{
|
|
4196
|
+
startIcon: /* @__PURE__ */ jsx(Check, {}),
|
|
4197
|
+
variant: "success-light",
|
|
4198
|
+
size: "L",
|
|
4199
|
+
onClick: handleOpenPublishModal,
|
|
4200
|
+
loading: publishing,
|
|
4201
|
+
disabled: loading || totalSelectedCount === 0,
|
|
4202
|
+
title: "Directly publish selected draft records across collections",
|
|
4203
|
+
children: [
|
|
4204
|
+
"Publish Selected (",
|
|
4205
|
+
totalSelectedCount,
|
|
4206
|
+
")"
|
|
4207
|
+
]
|
|
4208
|
+
}
|
|
4209
|
+
),
|
|
4210
|
+
/* @__PURE__ */ jsxs(
|
|
4211
|
+
Button,
|
|
4212
|
+
{
|
|
4213
|
+
startIcon: /* @__PURE__ */ jsx(Download, {}),
|
|
4214
|
+
variant: "tertiary",
|
|
4215
|
+
size: "L",
|
|
4216
|
+
onClick: handleBulkExportSelected,
|
|
4217
|
+
loading: bulkExporting,
|
|
4218
|
+
disabled: loading || totalSelectedCount === 0,
|
|
4219
|
+
title: "Export selected entries to Excel-compatible CSV with full nested component support",
|
|
4220
|
+
children: [
|
|
4221
|
+
"Export Selected (",
|
|
4222
|
+
totalSelectedCount,
|
|
4223
|
+
")"
|
|
4224
|
+
]
|
|
4225
|
+
}
|
|
4226
|
+
)
|
|
4227
|
+
] })
|
|
4228
|
+
] }),
|
|
4229
|
+
/* @__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: [
|
|
4230
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
4231
|
+
/* @__PURE__ */ jsx(
|
|
4232
|
+
Checkbox,
|
|
4233
|
+
{
|
|
4234
|
+
checked: publishOnApproval,
|
|
4235
|
+
onCheckedChange: (checked) => setPublishOnApproval(Boolean(checked)),
|
|
4236
|
+
children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: "Auto-Publish after Update" })
|
|
4237
|
+
}
|
|
4238
|
+
),
|
|
4239
|
+
/* @__PURE__ */ jsx(
|
|
4240
|
+
Badge,
|
|
4241
|
+
{
|
|
4242
|
+
backgroundColor: publishOnApproval ? "success100" : "warning100",
|
|
4243
|
+
textColor: publishOnApproval ? "success700" : "warning700",
|
|
4244
|
+
children: publishOnApproval ? "✓ LIVE PUBLISH" : "DRAFT ONLY"
|
|
4245
|
+
}
|
|
4246
|
+
)
|
|
4247
|
+
] }),
|
|
4248
|
+
/* @__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." })
|
|
4249
|
+
] }) }),
|
|
4250
|
+
selectedCol && selectedAttribute && /* @__PURE__ */ jsx(Box, { marginTop: 4, padding: 3, background: "neutral100", hasRadius: true, style: { border: "1px solid #eaeaef" }, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 3, children: /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
4251
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: "Target Selection:" }),
|
|
4252
|
+
/* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
4253
|
+
"Collection: ",
|
|
4254
|
+
selectedCol.displayName
|
|
4255
|
+
] }),
|
|
4256
|
+
/* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: [
|
|
4257
|
+
"Attribute: ",
|
|
4258
|
+
selectedAttribute,
|
|
4259
|
+
" ",
|
|
4260
|
+
attributesMeta[selectedAttribute]?.type ? `(${attributesMeta[selectedAttribute].type})` : ""
|
|
4261
|
+
] }),
|
|
4262
|
+
attributesMeta[selectedAttribute]?.depth ? /* @__PURE__ */ jsxs(Badge, { backgroundColor: "neutral200", textColor: "neutral700", children: [
|
|
4263
|
+
"Nesting Level: L",
|
|
4264
|
+
attributesMeta[selectedAttribute].depth
|
|
4265
|
+
] }) : null,
|
|
4266
|
+
selectedCol.draftAndPublish ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "success100", textColor: "success700", children: "Draft & Publish Enabled" }) : /* @__PURE__ */ jsx(Badge, { backgroundColor: "warning100", textColor: "warning700", children: "Direct Publish Only" })
|
|
4267
|
+
] }) }) })
|
|
4268
|
+
]
|
|
4269
|
+
}
|
|
4270
|
+
),
|
|
4110
4271
|
updateSummary && /* @__PURE__ */ jsxs(
|
|
4111
4272
|
Box,
|
|
4112
4273
|
{
|
|
@@ -4371,25 +4532,44 @@ const BulkUpdater = () => {
|
|
|
4371
4532
|
/* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: rec.userName }),
|
|
4372
4533
|
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", display: "block", style: { wordBreak: "break-all" }, children: rec.userEmail })
|
|
4373
4534
|
] }),
|
|
4374
|
-
/* @__PURE__ */ jsx(Td, { style: { minWidth:
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
formatDisplayValue(rec.value),
|
|
4389
|
-
"”"
|
|
4390
|
-
]
|
|
4535
|
+
/* @__PURE__ */ jsx(Td, { style: { minWidth: 200 }, children: (() => {
|
|
4536
|
+
const isCsv = rec.attribute === "CSV_IMPORT" || rec.attribute?.startsWith("CSV");
|
|
4537
|
+
let attrText = rec.attribute;
|
|
4538
|
+
let valText = formatDisplayValue(rec.value);
|
|
4539
|
+
if (rec.attribute === "CSV_IMPORT" && rec.diffs && rec.diffs.length > 0) {
|
|
4540
|
+
const colName = rec.diffs[0]?.collectionName || "Collection";
|
|
4541
|
+
const attrs = Array.from(new Set(rec.diffs.map((d) => d.attribute).filter(Boolean))).join(", ");
|
|
4542
|
+
attrText = `CSV [${colName}]: ${attrs || "fields"}`;
|
|
4543
|
+
if (rec.value.startsWith("Mode:") && rec.diffs.length === 1) {
|
|
4544
|
+
const d = rec.diffs[0];
|
|
4545
|
+
valText = `"${d.label || d.documentId}": ${d.attribute || "field"} → "${formatDisplayValue(d.newValue)}"`;
|
|
4546
|
+
} else if (rec.value.startsWith("Mode:")) {
|
|
4547
|
+
valText = `${rec.diffs.length} attribute${rec.diffs.length > 1 ? "s" : ""} updated in ${colName}`;
|
|
4548
|
+
}
|
|
4391
4549
|
}
|
|
4392
|
-
|
|
4550
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
4551
|
+
isCsv && /* @__PURE__ */ jsx(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: "CSV IMPORT" }),
|
|
4552
|
+
/* @__PURE__ */ jsxs(
|
|
4553
|
+
Typography,
|
|
4554
|
+
{
|
|
4555
|
+
style: {
|
|
4556
|
+
display: "inline-block",
|
|
4557
|
+
maxWidth: "100%",
|
|
4558
|
+
overflow: "hidden",
|
|
4559
|
+
textOverflow: "ellipsis",
|
|
4560
|
+
whiteSpace: "nowrap"
|
|
4561
|
+
},
|
|
4562
|
+
title: `${attrText} → "${valText}"`,
|
|
4563
|
+
children: [
|
|
4564
|
+
/* @__PURE__ */ jsx("strong", { children: attrText.replace(/^CSV\s*\[?([^\]]+)\]?:\s*/, "$1: ") }),
|
|
4565
|
+
" → “",
|
|
4566
|
+
valText,
|
|
4567
|
+
"”"
|
|
4568
|
+
]
|
|
4569
|
+
}
|
|
4570
|
+
)
|
|
4571
|
+
] });
|
|
4572
|
+
})() }),
|
|
4393
4573
|
/* @__PURE__ */ jsxs(Td, { style: { minWidth: 90, whiteSpace: "nowrap" }, children: [
|
|
4394
4574
|
/* @__PURE__ */ jsxs(Badge, { backgroundColor: "success100", textColor: "success700", children: [
|
|
4395
4575
|
rec.updatedCount,
|
|
@@ -4462,18 +4642,20 @@ const BulkUpdater = () => {
|
|
|
4462
4642
|
rec.batchId,
|
|
4463
4643
|
":"
|
|
4464
4644
|
] }),
|
|
4465
|
-
/* @__PURE__ */ jsxs(Table, { colCount:
|
|
4645
|
+
/* @__PURE__ */ jsxs(Table, { colCount: 5, rowCount: rec.diffs.length + 1, children: [
|
|
4466
4646
|
/* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
|
|
4467
4647
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Collection" }) }),
|
|
4468
4648
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Document / Entry" }) }),
|
|
4649
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Attribute" }) }),
|
|
4469
4650
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Previous Value" }) }),
|
|
4470
4651
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Applied Value" }) })
|
|
4471
4652
|
] }) }),
|
|
4472
4653
|
/* @__PURE__ */ jsx(Tbody, { children: rec.diffs.map((d, dIdx) => /* @__PURE__ */ jsxs(Tr, { children: [
|
|
4473
4654
|
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: d.collectionName }) }),
|
|
4474
4655
|
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: d.label }) }),
|
|
4656
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: d.attribute || "field" }) }),
|
|
4475
4657
|
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: formatDisplayValue(d.oldValue) }) }),
|
|
4476
|
-
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "success600", children: formatDisplayValue(d.newValue) }) })
|
|
4658
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "semiBold", children: formatDisplayValue(d.newValue) }) })
|
|
4477
4659
|
] }, dIdx)) })
|
|
4478
4660
|
] })
|
|
4479
4661
|
]
|
|
@@ -4986,6 +5168,7 @@ export {
|
|
|
4986
5168
|
BulkUpdater as default,
|
|
4987
5169
|
formatDisplayValue,
|
|
4988
5170
|
getAvailableColumnsForCollection,
|
|
5171
|
+
getEntryLifecycleStatus,
|
|
4989
5172
|
getNestedValue
|
|
4990
5173
|
};
|
|
4991
|
-
//# sourceMappingURL=BulkUpdater-
|
|
5174
|
+
//# sourceMappingURL=BulkUpdater-D4v5fP-1.mjs.map
|