strapi-plugin-bulk-updater 1.2.13 → 1.3.0
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/README.md +10 -4
- package/dist/_chunks/{BulkUpdater-CWJYmuGU.js → BulkUpdater-CRvwX326.js} +261 -33
- package/dist/_chunks/BulkUpdater-CRvwX326.js.map +1 -0
- package/dist/_chunks/{BulkUpdater-Cfig2f7d.mjs → BulkUpdater-DowSmA56.mjs} +261 -33
- package/dist/_chunks/BulkUpdater-DowSmA56.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +187 -92
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +187 -92
- package/dist/server/index.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/_chunks/BulkUpdater-CWJYmuGU.js.map +0 -1
- package/dist/_chunks/BulkUpdater-Cfig2f7d.mjs.map +0 -1
|
@@ -1454,7 +1454,7 @@ function getNestedValue(obj, path) {
|
|
|
1454
1454
|
if (!path.includes(".")) return obj[path];
|
|
1455
1455
|
return path.split(".").reduce((acc, part) => acc && typeof acc === "object" ? acc[part] : void 0, obj);
|
|
1456
1456
|
}
|
|
1457
|
-
function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
1457
|
+
function getAvailableColumnsForCollection(col, selectedAttribute, searchAttribute) {
|
|
1458
1458
|
const cols = [
|
|
1459
1459
|
{
|
|
1460
1460
|
key: "select",
|
|
@@ -1471,7 +1471,7 @@ function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
|
1471
1471
|
];
|
|
1472
1472
|
const candidateAttrs = col.attributes || [];
|
|
1473
1473
|
candidateAttrs.forEach((attr) => {
|
|
1474
|
-
if (attr === "name" || attr === "title" || attr === selectedAttribute) {
|
|
1474
|
+
if (attr === "name" || attr === "title" || attr === selectedAttribute || searchAttribute && attr === searchAttribute) {
|
|
1475
1475
|
return;
|
|
1476
1476
|
}
|
|
1477
1477
|
const formattedLabel = attr.includes(".") ? attr.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ") : attr.charAt(0).toUpperCase() + attr.slice(1);
|
|
@@ -1482,9 +1482,19 @@ function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
|
1482
1482
|
defaultVisible: ["department", "email", "location"].includes(attr)
|
|
1483
1483
|
});
|
|
1484
1484
|
});
|
|
1485
|
+
if (searchAttribute && searchAttribute !== selectedAttribute) {
|
|
1486
|
+
const formattedSearchLabel = searchAttribute.includes(".") ? searchAttribute.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ") : searchAttribute;
|
|
1487
|
+
cols.push({
|
|
1488
|
+
key: "search_attr",
|
|
1489
|
+
label: `Search: "${formattedSearchLabel}"`,
|
|
1490
|
+
sortable: !col.isSingleType && col.attributes.includes(searchAttribute),
|
|
1491
|
+
defaultVisible: true
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
const targetLabel = searchAttribute && searchAttribute !== selectedAttribute ? `Update Target: "${selectedAttribute}"` : `Current "${selectedAttribute}"`;
|
|
1485
1495
|
cols.push({
|
|
1486
1496
|
key: "target_attr",
|
|
1487
|
-
label:
|
|
1497
|
+
label: targetLabel,
|
|
1488
1498
|
sortable: !col.isSingleType && col.attributes.includes(selectedAttribute),
|
|
1489
1499
|
defaultVisible: true
|
|
1490
1500
|
});
|
|
@@ -1496,17 +1506,19 @@ function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
|
1496
1506
|
});
|
|
1497
1507
|
return cols;
|
|
1498
1508
|
}
|
|
1499
|
-
function renderHeaderCell(colDef, col, currentSort, selectedAttribute, onSort) {
|
|
1509
|
+
function renderHeaderCell(colDef, col, currentSort, selectedAttribute, searchAttribute, onSort) {
|
|
1500
1510
|
if (colDef.key === "select") {
|
|
1501
1511
|
return /* @__PURE__ */ jsx(Th, { style: { width: 48 }, children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: "Select" }) }, "select");
|
|
1502
1512
|
}
|
|
1503
|
-
const isCurrentSorted = colDef.key === "identifier" && (currentSort.field === "name" || currentSort.field === "title") || colDef.key === "target_attr" && currentSort.field === selectedAttribute || colDef.key.startsWith("attr_") && currentSort.field === colDef.key.replace("attr_", "");
|
|
1513
|
+
const isCurrentSorted = colDef.key === "identifier" && (currentSort.field === "name" || currentSort.field === "title") || colDef.key === "search_attr" && currentSort.field === searchAttribute || colDef.key === "target_attr" && currentSort.field === selectedAttribute || colDef.key.startsWith("attr_") && currentSort.field === colDef.key.replace("attr_", "");
|
|
1504
1514
|
const sortArrow = isCurrentSorted ? currentSort.order === "asc" ? "▲" : "▼" : "⇅";
|
|
1505
1515
|
const handleClick = () => {
|
|
1506
1516
|
if (!colDef.sortable) return;
|
|
1507
1517
|
if (colDef.key === "identifier") {
|
|
1508
1518
|
const field = col.attributes.includes("name") ? "name" : col.attributes.includes("title") ? "title" : "createdAt";
|
|
1509
1519
|
onSort(col.uid, field);
|
|
1520
|
+
} else if (colDef.key === "search_attr") {
|
|
1521
|
+
onSort(col.uid, searchAttribute);
|
|
1510
1522
|
} else if (colDef.key === "target_attr") {
|
|
1511
1523
|
onSort(col.uid, selectedAttribute);
|
|
1512
1524
|
} else if (colDef.key.startsWith("attr_")) {
|
|
@@ -1542,7 +1554,7 @@ function formatDisplayValue(val) {
|
|
|
1542
1554
|
}
|
|
1543
1555
|
return String(val);
|
|
1544
1556
|
}
|
|
1545
|
-
function renderCellContent(colDef, entry, col, selectedAttribute, isMatch, hasAttr, isSelected, onToggleSelect) {
|
|
1557
|
+
function renderCellContent(colDef, entry, col, selectedAttribute, searchAttribute, isMatch, hasAttr, isSelected, onToggleSelect) {
|
|
1546
1558
|
switch (colDef.key) {
|
|
1547
1559
|
case "select":
|
|
1548
1560
|
return /* @__PURE__ */ jsx(
|
|
@@ -1559,6 +1571,27 @@ function renderCellContent(colDef, entry, col, selectedAttribute, isMatch, hasAt
|
|
|
1559
1571
|
entry.email && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", display: "block", children: entry.email })
|
|
1560
1572
|
] });
|
|
1561
1573
|
}
|
|
1574
|
+
case "search_attr": {
|
|
1575
|
+
const val = getNestedValue(entry, searchAttribute);
|
|
1576
|
+
const displayStr = formatDisplayValue(val);
|
|
1577
|
+
const isUnset = displayStr === "(empty / not set)" || displayStr === "(empty / unlinked)";
|
|
1578
|
+
return /* @__PURE__ */ jsx(
|
|
1579
|
+
Typography,
|
|
1580
|
+
{
|
|
1581
|
+
textColor: isUnset ? "neutral500" : "primary700",
|
|
1582
|
+
fontWeight: "semiBold",
|
|
1583
|
+
style: {
|
|
1584
|
+
fontStyle: isUnset ? "italic" : "normal",
|
|
1585
|
+
display: "inline-block",
|
|
1586
|
+
maxWidth: 260,
|
|
1587
|
+
overflow: "hidden",
|
|
1588
|
+
textOverflow: "ellipsis",
|
|
1589
|
+
whiteSpace: "nowrap"
|
|
1590
|
+
},
|
|
1591
|
+
children: displayStr
|
|
1592
|
+
}
|
|
1593
|
+
);
|
|
1594
|
+
}
|
|
1562
1595
|
case "target_attr": {
|
|
1563
1596
|
const val = getNestedValue(entry, selectedAttribute);
|
|
1564
1597
|
const displayStr = formatDisplayValue(val);
|
|
@@ -1683,10 +1716,34 @@ const BulkUpdater = () => {
|
|
|
1683
1716
|
};
|
|
1684
1717
|
const [useRegex, setUseRegex] = useState(false);
|
|
1685
1718
|
const [regexPattern, setRegexPattern] = useState("");
|
|
1719
|
+
const DEPTH_STORAGE_KEY = "strapi_bulk_updater_component_depth";
|
|
1720
|
+
const [componentDepth, setComponentDepth] = useState(() => {
|
|
1721
|
+
try {
|
|
1722
|
+
const stored = localStorage.getItem(DEPTH_STORAGE_KEY);
|
|
1723
|
+
if (stored) {
|
|
1724
|
+
const val = Number(stored);
|
|
1725
|
+
if (val >= 1 && val <= 5) return val;
|
|
1726
|
+
}
|
|
1727
|
+
} catch {
|
|
1728
|
+
}
|
|
1729
|
+
return 3;
|
|
1730
|
+
});
|
|
1731
|
+
const handleComponentDepthChange = (depth) => {
|
|
1732
|
+
const capped = Math.min(5, Math.max(1, depth));
|
|
1733
|
+
setComponentDepth(capped);
|
|
1734
|
+
try {
|
|
1735
|
+
localStorage.setItem(DEPTH_STORAGE_KEY, String(capped));
|
|
1736
|
+
} catch {
|
|
1737
|
+
}
|
|
1738
|
+
};
|
|
1739
|
+
const [searchAttribute, setSearchAttribute] = useState("");
|
|
1740
|
+
const [searchAttributeInput, setSearchAttributeInput] = useState("");
|
|
1741
|
+
const [attributesMeta, setAttributesMeta] = useState({});
|
|
1742
|
+
const effectiveSearchAttribute = searchAttribute || selectedAttribute;
|
|
1686
1743
|
const [filterOperator, setFilterOperator] = useState("none");
|
|
1687
1744
|
const [filterQuery, setFilterQuery] = useState("");
|
|
1688
1745
|
const [entrySearch, setEntrySearch] = useState("");
|
|
1689
|
-
const isFilterActive = filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
1746
|
+
const isFilterActive = Boolean(searchAttribute && searchAttribute !== selectedAttribute) || filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
1690
1747
|
const [lastResults, setLastResults] = useState(null);
|
|
1691
1748
|
const [updateSummary, setUpdateSummary] = useState(null);
|
|
1692
1749
|
const [collectionPages, setCollectionPages] = useState({});
|
|
@@ -1766,6 +1823,9 @@ const BulkUpdater = () => {
|
|
|
1766
1823
|
if (data.relationsMeta) {
|
|
1767
1824
|
setRelationsMeta(data.relationsMeta);
|
|
1768
1825
|
}
|
|
1826
|
+
if (data.attributesMeta) {
|
|
1827
|
+
setAttributesMeta(data.attributesMeta);
|
|
1828
|
+
}
|
|
1769
1829
|
let storedAttr = null;
|
|
1770
1830
|
try {
|
|
1771
1831
|
storedAttr = localStorage.getItem(LAST_ATTR_KEY);
|
|
@@ -1813,7 +1873,7 @@ const BulkUpdater = () => {
|
|
|
1813
1873
|
setLoading(false);
|
|
1814
1874
|
}
|
|
1815
1875
|
};
|
|
1816
|
-
const loadCollectionPage = async (colUid, targetPage, customPageSize, customSortField, customSortOrder, overrideFilterOp, overrideFilterQuery, overrideEntrySearch, autoSelectReturned = true) => {
|
|
1876
|
+
const loadCollectionPage = async (colUid, targetPage, customPageSize, customSortField, customSortOrder, overrideFilterOp, overrideFilterQuery, overrideEntrySearch, autoSelectReturned = true, overrideSearchAttr) => {
|
|
1817
1877
|
const currentPageState = collectionPages[colUid];
|
|
1818
1878
|
const size = customPageSize || currentPageState?.pageSize || defaultPageSize;
|
|
1819
1879
|
const currentSort = collectionSorts[colUid] || { field: "createdAt", order: "desc" };
|
|
@@ -1822,6 +1882,7 @@ const BulkUpdater = () => {
|
|
|
1822
1882
|
const op = overrideFilterOp !== void 0 ? overrideFilterOp : filterOperator;
|
|
1823
1883
|
const q = overrideFilterQuery !== void 0 ? overrideFilterQuery : filterQuery;
|
|
1824
1884
|
const s = overrideEntrySearch !== void 0 ? overrideEntrySearch : entrySearch;
|
|
1885
|
+
const searchAttr = overrideSearchAttr !== void 0 ? overrideSearchAttr : searchAttribute;
|
|
1825
1886
|
setCollectionPages((prev) => ({
|
|
1826
1887
|
...prev,
|
|
1827
1888
|
[colUid]: {
|
|
@@ -1835,6 +1896,9 @@ const BulkUpdater = () => {
|
|
|
1835
1896
|
pageSize: String(size)
|
|
1836
1897
|
});
|
|
1837
1898
|
if (selectedAttribute) params.set("attribute", selectedAttribute);
|
|
1899
|
+
if (searchAttr && searchAttr !== selectedAttribute) {
|
|
1900
|
+
params.set("searchAttribute", searchAttr);
|
|
1901
|
+
}
|
|
1838
1902
|
if (op && op !== "none") {
|
|
1839
1903
|
params.set("filterOperator", op);
|
|
1840
1904
|
if (q) params.set("filterQuery", q);
|
|
@@ -1864,7 +1928,7 @@ const BulkUpdater = () => {
|
|
|
1864
1928
|
loading: false
|
|
1865
1929
|
}
|
|
1866
1930
|
}));
|
|
1867
|
-
const isFilterActiveNow = op !== "none" && (["empty", "not_empty"].includes(op) || Boolean(q.trim())) || Boolean(s.trim());
|
|
1931
|
+
const isFilterActiveNow = Boolean(searchAttr && searchAttr !== selectedAttribute) || op !== "none" && (["empty", "not_empty"].includes(op) || Boolean(q.trim())) || Boolean(s.trim());
|
|
1868
1932
|
if (isFilterActiveNow && autoSelectReturned) {
|
|
1869
1933
|
setSelectedEntries((prev) => {
|
|
1870
1934
|
const next = { ...prev };
|
|
@@ -1951,13 +2015,14 @@ const BulkUpdater = () => {
|
|
|
1951
2015
|
}
|
|
1952
2016
|
const timer = setTimeout(() => {
|
|
1953
2017
|
if (collections.length > 0) {
|
|
1954
|
-
const isFilterActiveNow = filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
2018
|
+
const isFilterActiveNow = Boolean(searchAttribute && searchAttribute !== selectedAttribute) || filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
1955
2019
|
if (isFilterActiveNow) {
|
|
1956
2020
|
setSelectedEntries({});
|
|
1957
2021
|
}
|
|
2022
|
+
const targetSearchAttr = searchAttribute || selectedAttribute;
|
|
1958
2023
|
const targetCols = collections.filter((col) => {
|
|
1959
2024
|
if (visibleTypeUids[col.uid] === false) return false;
|
|
1960
|
-
if (filterOperator !== "none" && !col.attributes.includes(
|
|
2025
|
+
if (filterOperator !== "none" && targetSearchAttr && !col.attributes.includes(targetSearchAttr)) return false;
|
|
1961
2026
|
return true;
|
|
1962
2027
|
});
|
|
1963
2028
|
targetCols.forEach((col) => {
|
|
@@ -1970,13 +2035,14 @@ const BulkUpdater = () => {
|
|
|
1970
2035
|
filterOperator,
|
|
1971
2036
|
filterQuery,
|
|
1972
2037
|
entrySearch,
|
|
1973
|
-
true
|
|
2038
|
+
true,
|
|
2039
|
+
searchAttribute
|
|
1974
2040
|
);
|
|
1975
2041
|
});
|
|
1976
2042
|
}
|
|
1977
2043
|
}, 350);
|
|
1978
2044
|
return () => clearTimeout(timer);
|
|
1979
|
-
}, [filterOperator, filterQuery, entrySearch]);
|
|
2045
|
+
}, [searchAttribute, filterOperator, filterQuery, entrySearch]);
|
|
1980
2046
|
const KEY_SEP = "@@@";
|
|
1981
2047
|
const handleAttributeChange = (newAttr) => {
|
|
1982
2048
|
if (newAttr !== selectedAttribute) {
|
|
@@ -2045,39 +2111,119 @@ const BulkUpdater = () => {
|
|
|
2045
2111
|
setVisibleTypeUids(newVis);
|
|
2046
2112
|
};
|
|
2047
2113
|
const [attributeSearch, setAttributeSearch] = useState("");
|
|
2114
|
+
const [searchAttributeSearch, setSearchAttributeSearch] = useState("");
|
|
2115
|
+
const getAttrDepth = (attr) => attributesMeta[attr]?.depth ?? (attr.includes(".") ? attr.split(".").length - 1 : 0);
|
|
2116
|
+
const depthFilteredAttributes = useMemo(() => {
|
|
2117
|
+
return attributes.filter((attr) => getAttrDepth(attr) <= componentDepth);
|
|
2118
|
+
}, [attributes, componentDepth, attributesMeta]);
|
|
2048
2119
|
const filteredAttributes = useMemo(() => {
|
|
2049
2120
|
if (!attributeSearch.trim()) {
|
|
2050
|
-
return
|
|
2121
|
+
return depthFilteredAttributes;
|
|
2051
2122
|
}
|
|
2052
2123
|
const q = attributeSearch.toLowerCase().trim();
|
|
2053
2124
|
const cleanQ = q.replace(/[^a-z0-9]/g, "");
|
|
2054
|
-
return
|
|
2125
|
+
return depthFilteredAttributes.filter((attr) => {
|
|
2055
2126
|
const lower = attr.toLowerCase();
|
|
2056
2127
|
const cleanLower = lower.replace(/[^a-z0-9]/g, "");
|
|
2057
2128
|
const rel = relationsMeta[attr];
|
|
2058
2129
|
const relTarget = (rel?.targetDisplayName || "").toLowerCase();
|
|
2059
2130
|
return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
|
|
2060
2131
|
});
|
|
2061
|
-
}, [
|
|
2132
|
+
}, [depthFilteredAttributes, attributeSearch, relationsMeta]);
|
|
2133
|
+
const filteredSearchAttributes = useMemo(() => {
|
|
2134
|
+
if (!searchAttributeSearch.trim()) {
|
|
2135
|
+
return depthFilteredAttributes;
|
|
2136
|
+
}
|
|
2137
|
+
const q = searchAttributeSearch.toLowerCase().trim();
|
|
2138
|
+
const cleanQ = q.replace(/[^a-z0-9]/g, "");
|
|
2139
|
+
return depthFilteredAttributes.filter((attr) => {
|
|
2140
|
+
const lower = attr.toLowerCase();
|
|
2141
|
+
const cleanLower = lower.replace(/[^a-z0-9]/g, "");
|
|
2142
|
+
const rel = relationsMeta[attr];
|
|
2143
|
+
const relTarget = (rel?.targetDisplayName || "").toLowerCase();
|
|
2144
|
+
return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
|
|
2145
|
+
});
|
|
2146
|
+
}, [depthFilteredAttributes, searchAttributeSearch, relationsMeta]);
|
|
2062
2147
|
const memoizedComboboxOptions = useMemo(() => {
|
|
2063
2148
|
if (filteredAttributes.length === 0) {
|
|
2064
2149
|
return /* @__PURE__ */ jsx(ComboboxOption, { value: "__none__", disabled: true, textValue: "No matching attributes found", children: /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
2065
2150
|
'No matching attributes found for "',
|
|
2066
2151
|
attributeSearch,
|
|
2067
|
-
'"'
|
|
2152
|
+
'" (Depth L',
|
|
2153
|
+
componentDepth,
|
|
2154
|
+
")"
|
|
2068
2155
|
] }) });
|
|
2069
2156
|
}
|
|
2070
2157
|
return filteredAttributes.map((attr) => {
|
|
2071
2158
|
const rel = relationsMeta[attr];
|
|
2159
|
+
const depth = getAttrDepth(attr);
|
|
2072
2160
|
return /* @__PURE__ */ jsx(ComboboxOption, { value: attr, textValue: attr, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
2073
2161
|
/* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: attr === selectedAttribute ? "bold" : "regular", children: attr }),
|
|
2074
2162
|
rel ? /* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", size: "S", children: [
|
|
2075
2163
|
"relation ➔ ",
|
|
2076
2164
|
rel.targetDisplayName
|
|
2077
|
-
] }) :
|
|
2165
|
+
] }) : depth > 0 ? /* @__PURE__ */ jsxs(Badge, { backgroundColor: depth === 1 ? "neutral150" : depth === 2 ? "primary100" : "secondary100", textColor: depth === 1 ? "neutral700" : depth === 2 ? "primary700" : "secondary700", size: "S", children: [
|
|
2166
|
+
"L",
|
|
2167
|
+
depth,
|
|
2168
|
+
" component"
|
|
2169
|
+
] }) : null
|
|
2078
2170
|
] }) }, attr);
|
|
2079
2171
|
});
|
|
2080
|
-
}, [filteredAttributes, relationsMeta, selectedAttribute, attributeSearch]);
|
|
2172
|
+
}, [filteredAttributes, relationsMeta, selectedAttribute, attributeSearch, componentDepth, attributesMeta]);
|
|
2173
|
+
const memoizedSearchComboboxOptions = useMemo(() => {
|
|
2174
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2175
|
+
/* @__PURE__ */ jsx(
|
|
2176
|
+
ComboboxOption,
|
|
2177
|
+
{
|
|
2178
|
+
value: "__default__",
|
|
2179
|
+
textValue: `Same as Update Attribute (${selectedAttribute || "None"})`,
|
|
2180
|
+
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
2181
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "omega", fontStyle: "italic", textColor: "neutral600", children: [
|
|
2182
|
+
"-- Same as Update Attribute (",
|
|
2183
|
+
selectedAttribute || "None",
|
|
2184
|
+
") --"
|
|
2185
|
+
] }),
|
|
2186
|
+
/* @__PURE__ */ jsx(Badge, { backgroundColor: "neutral150", textColor: "neutral600", size: "S", children: "Default" })
|
|
2187
|
+
] })
|
|
2188
|
+
}
|
|
2189
|
+
),
|
|
2190
|
+
filteredSearchAttributes.map((attr) => {
|
|
2191
|
+
const rel = relationsMeta[attr];
|
|
2192
|
+
const depth = getAttrDepth(attr);
|
|
2193
|
+
return /* @__PURE__ */ jsx(ComboboxOption, { value: attr, textValue: attr, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
2194
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: attr === searchAttribute ? "bold" : "regular", children: attr }),
|
|
2195
|
+
rel ? /* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", size: "S", children: [
|
|
2196
|
+
"relation ➔ ",
|
|
2197
|
+
rel.targetDisplayName
|
|
2198
|
+
] }) : depth > 0 ? /* @__PURE__ */ jsxs(Badge, { backgroundColor: depth === 1 ? "neutral150" : depth === 2 ? "primary100" : "secondary100", textColor: depth === 1 ? "neutral700" : depth === 2 ? "primary700" : "secondary700", size: "S", children: [
|
|
2199
|
+
"L",
|
|
2200
|
+
depth,
|
|
2201
|
+
" component"
|
|
2202
|
+
] }) : null
|
|
2203
|
+
] }) }, `search_${attr}`);
|
|
2204
|
+
})
|
|
2205
|
+
] });
|
|
2206
|
+
}, [filteredSearchAttributes, relationsMeta, searchAttribute, selectedAttribute, componentDepth, attributesMeta]);
|
|
2207
|
+
const handleSearchAttributeChange = (newAttr) => {
|
|
2208
|
+
const finalAttr = newAttr === "__default__" ? "" : newAttr;
|
|
2209
|
+
setSearchAttribute(finalAttr);
|
|
2210
|
+
if (collections.length > 0) {
|
|
2211
|
+
collections.forEach((col) => {
|
|
2212
|
+
loadCollectionPage(
|
|
2213
|
+
col.uid,
|
|
2214
|
+
1,
|
|
2215
|
+
void 0,
|
|
2216
|
+
void 0,
|
|
2217
|
+
void 0,
|
|
2218
|
+
filterOperator,
|
|
2219
|
+
filterQuery,
|
|
2220
|
+
entrySearch,
|
|
2221
|
+
true,
|
|
2222
|
+
finalAttr
|
|
2223
|
+
);
|
|
2224
|
+
});
|
|
2225
|
+
}
|
|
2226
|
+
};
|
|
2081
2227
|
const handleGlobalPageSizeChange = (newSize) => {
|
|
2082
2228
|
const capped = Math.min(500, Math.max(1, newSize));
|
|
2083
2229
|
setDefaultPageSize(capped);
|
|
@@ -2168,12 +2314,14 @@ const BulkUpdater = () => {
|
|
|
2168
2314
|
setSelectedEntries(updated);
|
|
2169
2315
|
};
|
|
2170
2316
|
const clearFilter = () => {
|
|
2317
|
+
setSearchAttribute("");
|
|
2318
|
+
setSearchAttributeSearch("");
|
|
2171
2319
|
setFilterOperator("none");
|
|
2172
2320
|
setFilterQuery("");
|
|
2173
2321
|
setEntrySearch("");
|
|
2174
2322
|
setSelectedEntries({});
|
|
2175
2323
|
collections.forEach((col) => {
|
|
2176
|
-
loadCollectionPage(col.uid, 1, void 0, void 0, void 0, "none", "", "", false);
|
|
2324
|
+
loadCollectionPage(col.uid, 1, void 0, void 0, void 0, "none", "", "", false, "");
|
|
2177
2325
|
});
|
|
2178
2326
|
};
|
|
2179
2327
|
const isCollectionFullySelected = (col) => {
|
|
@@ -2969,7 +3117,29 @@ const BulkUpdater = () => {
|
|
|
2969
3117
|
marginBottom: 6,
|
|
2970
3118
|
style: { width: "100%", maxWidth: "100%", minWidth: 0, boxSizing: "border-box" },
|
|
2971
3119
|
children: [
|
|
2972
|
-
/* @__PURE__ */
|
|
3120
|
+
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, wrap: "wrap", gap: 3, children: [
|
|
3121
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
3122
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", fontWeight: "semiBold", children: "1. Configure Attribute Update" }),
|
|
3123
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Select the target attribute to update across collections." })
|
|
3124
|
+
] }),
|
|
3125
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3126
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral700", fontWeight: "bold", children: "Component Nesting Depth:" }),
|
|
3127
|
+
[1, 2, 3, 4, 5].map((lvl) => /* @__PURE__ */ jsxs(
|
|
3128
|
+
Button,
|
|
3129
|
+
{
|
|
3130
|
+
variant: componentDepth === lvl ? "default" : "tertiary",
|
|
3131
|
+
size: "S",
|
|
3132
|
+
onClick: () => handleComponentDepthChange(lvl),
|
|
3133
|
+
title: `Discover nested component attributes up to Level ${lvl}`,
|
|
3134
|
+
children: [
|
|
3135
|
+
"Level ",
|
|
3136
|
+
lvl
|
|
3137
|
+
]
|
|
3138
|
+
},
|
|
3139
|
+
`depth_cfg_${lvl}`
|
|
3140
|
+
))
|
|
3141
|
+
] })
|
|
3142
|
+
] }),
|
|
2973
3143
|
/* @__PURE__ */ jsxs(Flex, { gap: 4, alignItems: "flex-end", wrap: "wrap", children: [
|
|
2974
3144
|
/* @__PURE__ */ jsx(Box, { style: { minWidth: 280, flex: 1, maxWidth: 440 }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
2975
3145
|
/* @__PURE__ */ jsx(Field.Label, { children: "Attribute to Update" }),
|
|
@@ -3300,26 +3470,83 @@ const BulkUpdater = () => {
|
|
|
3300
3470
|
style: { width: "100%", maxWidth: "100%", boxSizing: "border-box" },
|
|
3301
3471
|
children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
|
3302
3472
|
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 2, children: [
|
|
3303
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
3473
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3304
3474
|
/* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", children: "Search & Filter Targets:" }),
|
|
3305
3475
|
isFilterActive && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
3306
3476
|
matchingEntriesCount,
|
|
3307
3477
|
" matching ",
|
|
3308
3478
|
matchingEntriesCount === 1 ? "entry" : "entries",
|
|
3309
3479
|
" found in database"
|
|
3480
|
+
] }),
|
|
3481
|
+
searchAttribute && searchAttribute !== selectedAttribute && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: [
|
|
3482
|
+
"Searching by: ",
|
|
3483
|
+
searchAttribute,
|
|
3484
|
+
" → Target to update: ",
|
|
3485
|
+
selectedAttribute
|
|
3310
3486
|
] })
|
|
3311
3487
|
] }),
|
|
3312
|
-
|
|
3488
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3489
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 1, alignItems: "center", children: [
|
|
3490
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Depth:" }),
|
|
3491
|
+
[1, 2, 3, 4, 5].map((lvl) => /* @__PURE__ */ jsxs(
|
|
3492
|
+
Button,
|
|
3493
|
+
{
|
|
3494
|
+
variant: componentDepth === lvl ? "default" : "tertiary",
|
|
3495
|
+
size: "S",
|
|
3496
|
+
onClick: () => handleComponentDepthChange(lvl),
|
|
3497
|
+
title: `Show component attributes up to Level ${lvl}`,
|
|
3498
|
+
style: { minWidth: 26, padding: "2px 6px" },
|
|
3499
|
+
children: [
|
|
3500
|
+
"L",
|
|
3501
|
+
lvl
|
|
3502
|
+
]
|
|
3503
|
+
},
|
|
3504
|
+
`s2_depth_${lvl}`
|
|
3505
|
+
))
|
|
3506
|
+
] }),
|
|
3507
|
+
isFilterActive && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "S", onClick: clearFilter, children: "Clear Search & Filter" })
|
|
3508
|
+
] })
|
|
3313
3509
|
] }),
|
|
3314
3510
|
/* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "flex-end", wrap: "wrap", children: [
|
|
3315
|
-
/* @__PURE__ */ jsx(Box, { style: { width:
|
|
3511
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 280, minWidth: 230 }, children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
3512
|
+
/* @__PURE__ */ jsx(Field.Label, { children: "Search Attribute" }),
|
|
3513
|
+
/* @__PURE__ */ jsx(
|
|
3514
|
+
Combobox,
|
|
3515
|
+
{
|
|
3516
|
+
autocomplete: "none",
|
|
3517
|
+
placeholder: searchAttribute || `Same as Update (${selectedAttribute || "None"})`,
|
|
3518
|
+
value: searchAttribute || "__default__",
|
|
3519
|
+
clearLabel: "Reset search attribute",
|
|
3520
|
+
onClear: () => {
|
|
3521
|
+
handleSearchAttributeChange("");
|
|
3522
|
+
setSearchAttributeSearch("");
|
|
3523
|
+
},
|
|
3524
|
+
onInputChange: (e) => {
|
|
3525
|
+
setSearchAttributeSearch(e.target.value);
|
|
3526
|
+
},
|
|
3527
|
+
onOpenChange: (isOpen) => {
|
|
3528
|
+
if (!isOpen) {
|
|
3529
|
+
setSearchAttributeSearch("");
|
|
3530
|
+
}
|
|
3531
|
+
},
|
|
3532
|
+
onChange: (val) => {
|
|
3533
|
+
if (val && typeof val === "string" && val !== "__none__") {
|
|
3534
|
+
handleSearchAttributeChange(val);
|
|
3535
|
+
setSearchAttributeSearch("");
|
|
3536
|
+
}
|
|
3537
|
+
},
|
|
3538
|
+
children: memoizedSearchComboboxOptions
|
|
3539
|
+
}
|
|
3540
|
+
)
|
|
3541
|
+
] }) }),
|
|
3542
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 200, minWidth: 170 }, children: /* @__PURE__ */ jsxs(
|
|
3316
3543
|
SingleSelect,
|
|
3317
3544
|
{
|
|
3318
|
-
label:
|
|
3545
|
+
label: effectiveSearchAttribute ? `Condition for "${effectiveSearchAttribute}"` : "Filter condition",
|
|
3319
3546
|
value: filterOperator,
|
|
3320
3547
|
onChange: (val) => setFilterOperator(String(val)),
|
|
3321
3548
|
children: [
|
|
3322
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "none", children: "Show All (No
|
|
3549
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "none", children: "Show All (No Value Filter)" }),
|
|
3323
3550
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "empty", children: "Is Empty or Null" }),
|
|
3324
3551
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "not_empty", children: "Is Not Empty" }),
|
|
3325
3552
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "equals", children: "Equals Exact Text" }),
|
|
@@ -3328,16 +3555,16 @@ const BulkUpdater = () => {
|
|
|
3328
3555
|
]
|
|
3329
3556
|
}
|
|
3330
3557
|
) }),
|
|
3331
|
-
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth:
|
|
3558
|
+
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
3332
3559
|
TextInput,
|
|
3333
3560
|
{
|
|
3334
|
-
label:
|
|
3561
|
+
label: effectiveSearchAttribute ? `Value for "${effectiveSearchAttribute}"` : "Value to match",
|
|
3335
3562
|
placeholder: "Type value to match...",
|
|
3336
3563
|
value: filterQuery,
|
|
3337
3564
|
onChange: (e) => setFilterQuery(e.target.value)
|
|
3338
3565
|
}
|
|
3339
3566
|
) }),
|
|
3340
|
-
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth:
|
|
3567
|
+
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 180 }, children: /* @__PURE__ */ jsx(
|
|
3341
3568
|
TextInput,
|
|
3342
3569
|
{
|
|
3343
3570
|
label: "Full-text Entry Search",
|
|
@@ -3535,11 +3762,11 @@ const BulkUpdater = () => {
|
|
|
3535
3762
|
const pageSize = pageState ? pageState.pageSize : defaultPageSize;
|
|
3536
3763
|
const hasAttr = selectedAttribute ? col.attributes.includes(selectedAttribute) : false;
|
|
3537
3764
|
const visibleEntries = getVisibleEntries(col);
|
|
3538
|
-
selectedAttribute ? entries.filter((e) => entryMatchesFilter(e,
|
|
3765
|
+
selectedAttribute ? entries.filter((e) => entryMatchesFilter(e, effectiveSearchAttribute)).length : 0;
|
|
3539
3766
|
const isFullySelected = isCollectionFullySelected(col);
|
|
3540
3767
|
const isPartiallySelected = isCollectionPartiallySelected(col);
|
|
3541
3768
|
const currentSort = collectionSorts[col.uid] || { field: "createdAt", order: "desc" };
|
|
3542
|
-
const availableColumns = getAvailableColumnsForCollection(col, selectedAttribute);
|
|
3769
|
+
const availableColumns = getAvailableColumnsForCollection(col, selectedAttribute, searchAttribute);
|
|
3543
3770
|
const savedColKeys = collectionColumnVisibility[col.uid];
|
|
3544
3771
|
const activeColumns = savedColKeys ? availableColumns.filter((c) => c.isPermanent || savedColKeys.includes(c.key)) : availableColumns.filter((c) => c.defaultVisible);
|
|
3545
3772
|
return /* @__PURE__ */ jsxs(
|
|
@@ -3749,7 +3976,7 @@ const BulkUpdater = () => {
|
|
|
3749
3976
|
),
|
|
3750
3977
|
/* @__PURE__ */ jsx(Box, { className: "bulk-updater-table-container", style: { width: "100%", maxWidth: "100%", minWidth: 0, overflowX: "auto" }, children: /* @__PURE__ */ jsxs(Table, { colCount: activeColumns.length, rowCount: visibleEntries.length + 1, style: { width: "100%" }, children: [
|
|
3751
3978
|
/* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsx(Tr, { children: activeColumns.map(
|
|
3752
|
-
(colDef) => renderHeaderCell(colDef, col, currentSort, selectedAttribute, handleHeaderSortClick)
|
|
3979
|
+
(colDef) => renderHeaderCell(colDef, col, currentSort, selectedAttribute, searchAttribute, handleHeaderSortClick)
|
|
3753
3980
|
) }) }),
|
|
3754
3981
|
/* @__PURE__ */ jsx(Tbody, { children: visibleEntries.length === 0 ? /* @__PURE__ */ jsx(Tr, { children: /* @__PURE__ */ jsx(Td, { colSpan: activeColumns.length, children: /* @__PURE__ */ jsx(Box, { padding: 4, style: { textAlign: "center" }, children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: "No entries in this content type match the active filter criteria." }) }) }) }) : visibleEntries.map((entry) => {
|
|
3755
3982
|
const key = `${col.uid}${KEY_SEP}${entry.documentId}`;
|
|
@@ -3767,6 +3994,7 @@ const BulkUpdater = () => {
|
|
|
3767
3994
|
entry,
|
|
3768
3995
|
col,
|
|
3769
3996
|
selectedAttribute,
|
|
3997
|
+
searchAttribute,
|
|
3770
3998
|
isMatch,
|
|
3771
3999
|
hasAttr,
|
|
3772
4000
|
isSelected,
|
|
@@ -4742,4 +4970,4 @@ export {
|
|
|
4742
4970
|
getAvailableColumnsForCollection,
|
|
4743
4971
|
getNestedValue
|
|
4744
4972
|
};
|
|
4745
|
-
//# sourceMappingURL=BulkUpdater-
|
|
4973
|
+
//# sourceMappingURL=BulkUpdater-DowSmA56.mjs.map
|