strapi-plugin-bulk-updater 1.2.13 → 1.3.1
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 +250 -125
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +250 -125
- 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
package/README.md
CHANGED
|
@@ -31,9 +31,14 @@ Strapi allows editing entries individually or applying bulk actions within a sin
|
|
|
31
31
|
## ✨ Features at a Glance
|
|
32
32
|
|
|
33
33
|
- 🔍 **Dynamic Cross-Collection Discovery**: Introspects all registered content types and attributes in your Strapi v5 instance.
|
|
34
|
+
- 🎯 **Separate Search vs Update Attributes**: Search and filter by one attribute, relation, or nested component in Section 2, while targeting a distinct attribute to update in Section 1. Side-by-side table columns display both searched and target values simultaneously.
|
|
35
|
+
- 🌲 **Configurable Component Nesting Depth (Levels 1–5)**: User-controlled depth exploration in the UI (`L1` to `L5`), persistent across sessions. Fully supports recursive component schema introspection, deep population, query filtering, and safe leaf mutation preserving sibling component properties.
|
|
36
|
+
- 🚀 **Direct Bulk Publishing & Auto-Publish Toggle**: Directly publish draft records in bulk across multiple collections without editing values, plus an auto-publish toggle that instantly publishes updated documents for draft-enabled content types.
|
|
37
|
+
- 📑 **Excel-Safe Bulk CSV Export**: RFC-4180 compliant CSV export with UTF-8 BOM and CRLF line breaks for seamless opening in Microsoft Excel and Numbers, with full recursive nested component support.
|
|
38
|
+
- 🔍 **Interactive Pre-Update Change Preview**: Inspect real-time before-and-after diffs with impact classification (`Will Update`, `Unchanged`, `Will Skip`) prior to executing batch updates.
|
|
34
39
|
- 🔎 **Searchable Combobox Attribute & Entity Picker**:
|
|
35
40
|
- Instant fuzzy and substring search across all scalar fields, relations, and nested component paths.
|
|
36
|
-
- Interactive visual badges for relation targets (`relation ➔ Target`) and
|
|
41
|
+
- Interactive visual badges for relation targets (`relation ➔ Target`) and component nesting levels (`L1 component`, `L2 component`).
|
|
37
42
|
- 🔗 **Full Relational Field Support**:
|
|
38
43
|
- Supports `manyToOne`, `oneToOne`, `oneToMany`, and `manyToMany` relations.
|
|
39
44
|
- Interactive searchable target entity dropdown populated directly from target collection records.
|
|
@@ -57,9 +62,6 @@ Strapi allows editing entries individually or applying bulk actions within a sin
|
|
|
57
62
|
- **Convention Auto-Discovery**: Seamlessly detects and mirrors custom app collections (`api::audit-log.audit-log`).
|
|
58
63
|
- **Strapi Enterprise Bridge**: Bridges events directly to native Strapi Enterprise Audit Logs (`admin::audit-logs`).
|
|
59
64
|
- **Deterministic Rollback**: Restores exact prior values and relationship links using Strapi v5 Document Service.
|
|
60
|
-
- 🧩 **Deep Nested Component Support**:
|
|
61
|
-
- Full dot-notation introspection (e.g. `metaFields.metaDescription`, `defaultSeo.metaTitle`) in attribute dropdown and table views.
|
|
62
|
-
- Non-destructive deep merging preserves sibling component properties during bulk updates and rollbacks.
|
|
63
65
|
- ⚡ **Server-Side Filter & Full-Text Search Pushdown**:
|
|
64
66
|
- Pushes text searches and attribute filters (`equals`, `contains`, `empty`, `starts_with`) directly to the database.
|
|
65
67
|
- Automatically hides non-matching records and pre-selects matching rows with real-time match counters.
|
|
@@ -246,6 +248,10 @@ All routes are mounted under `/bulk-updater` and protected by Strapi Admin authe
|
|
|
246
248
|
| `DELETE` | `/bulk-updater/validation-rules/:id` | Deletes a validation rule. |
|
|
247
249
|
| `POST` | `/bulk-updater/validation-rules/:id/toggle` | Toggles rule active status. |
|
|
248
250
|
| `POST` | `/bulk-updater/validation-rules/:id/scan` | Scans all existing records in target content types for violations. |
|
|
251
|
+
| `POST` | `/bulk-updater/preview` | Generates a dry-run diff preview across target entries before update. |
|
|
252
|
+
| `POST` | `/bulk-updater/publish` | Bulk publishes selected draft entries across multiple collections. |
|
|
253
|
+
| `POST` | `/bulk-updater/export-selected` | Exports selected entries across collections to Excel-compatible CSV. |
|
|
254
|
+
| `GET` | `/bulk-updater/collections/:uid/entries` | Paginated and filtered collection entries with search attribute pushdown. |
|
|
249
255
|
| `GET` | `/bulk-updater/csv/template/:uid` | Generates a blank CSV template with content type headers. |
|
|
250
256
|
| `GET` | `/bulk-updater/csv/export/:uid` | Exports all records for a collection type as CSV. |
|
|
251
257
|
| `GET` | `/bulk-updater/csv/export-violations/:ruleId` | Exports only records violating the specified rule as CSV. |
|
|
@@ -1458,7 +1458,7 @@ function getNestedValue(obj, path) {
|
|
|
1458
1458
|
if (!path.includes(".")) return obj[path];
|
|
1459
1459
|
return path.split(".").reduce((acc, part) => acc && typeof acc === "object" ? acc[part] : void 0, obj);
|
|
1460
1460
|
}
|
|
1461
|
-
function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
1461
|
+
function getAvailableColumnsForCollection(col, selectedAttribute, searchAttribute) {
|
|
1462
1462
|
const cols = [
|
|
1463
1463
|
{
|
|
1464
1464
|
key: "select",
|
|
@@ -1475,7 +1475,7 @@ function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
|
1475
1475
|
];
|
|
1476
1476
|
const candidateAttrs = col.attributes || [];
|
|
1477
1477
|
candidateAttrs.forEach((attr) => {
|
|
1478
|
-
if (attr === "name" || attr === "title" || attr === selectedAttribute) {
|
|
1478
|
+
if (attr === "name" || attr === "title" || attr === selectedAttribute || searchAttribute && attr === searchAttribute) {
|
|
1479
1479
|
return;
|
|
1480
1480
|
}
|
|
1481
1481
|
const formattedLabel = attr.includes(".") ? attr.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ") : attr.charAt(0).toUpperCase() + attr.slice(1);
|
|
@@ -1486,9 +1486,19 @@ function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
|
1486
1486
|
defaultVisible: ["department", "email", "location"].includes(attr)
|
|
1487
1487
|
});
|
|
1488
1488
|
});
|
|
1489
|
+
if (searchAttribute && searchAttribute !== selectedAttribute) {
|
|
1490
|
+
const formattedSearchLabel = searchAttribute.includes(".") ? searchAttribute.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ") : searchAttribute;
|
|
1491
|
+
cols.push({
|
|
1492
|
+
key: "search_attr",
|
|
1493
|
+
label: `Search: "${formattedSearchLabel}"`,
|
|
1494
|
+
sortable: !col.isSingleType && col.attributes.includes(searchAttribute),
|
|
1495
|
+
defaultVisible: true
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
const targetLabel = searchAttribute && searchAttribute !== selectedAttribute ? `Update Target: "${selectedAttribute}"` : `Current "${selectedAttribute}"`;
|
|
1489
1499
|
cols.push({
|
|
1490
1500
|
key: "target_attr",
|
|
1491
|
-
label:
|
|
1501
|
+
label: targetLabel,
|
|
1492
1502
|
sortable: !col.isSingleType && col.attributes.includes(selectedAttribute),
|
|
1493
1503
|
defaultVisible: true
|
|
1494
1504
|
});
|
|
@@ -1500,17 +1510,19 @@ function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
|
1500
1510
|
});
|
|
1501
1511
|
return cols;
|
|
1502
1512
|
}
|
|
1503
|
-
function renderHeaderCell(colDef, col, currentSort, selectedAttribute, onSort) {
|
|
1513
|
+
function renderHeaderCell(colDef, col, currentSort, selectedAttribute, searchAttribute, onSort) {
|
|
1504
1514
|
if (colDef.key === "select") {
|
|
1505
1515
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { style: { width: 48 }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Select" }) }, "select");
|
|
1506
1516
|
}
|
|
1507
|
-
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_", "");
|
|
1517
|
+
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_", "");
|
|
1508
1518
|
const sortArrow = isCurrentSorted ? currentSort.order === "asc" ? "▲" : "▼" : "⇅";
|
|
1509
1519
|
const handleClick = () => {
|
|
1510
1520
|
if (!colDef.sortable) return;
|
|
1511
1521
|
if (colDef.key === "identifier") {
|
|
1512
1522
|
const field = col.attributes.includes("name") ? "name" : col.attributes.includes("title") ? "title" : "createdAt";
|
|
1513
1523
|
onSort(col.uid, field);
|
|
1524
|
+
} else if (colDef.key === "search_attr") {
|
|
1525
|
+
onSort(col.uid, searchAttribute);
|
|
1514
1526
|
} else if (colDef.key === "target_attr") {
|
|
1515
1527
|
onSort(col.uid, selectedAttribute);
|
|
1516
1528
|
} else if (colDef.key.startsWith("attr_")) {
|
|
@@ -1546,7 +1558,7 @@ function formatDisplayValue(val) {
|
|
|
1546
1558
|
}
|
|
1547
1559
|
return String(val);
|
|
1548
1560
|
}
|
|
1549
|
-
function renderCellContent(colDef, entry, col, selectedAttribute, isMatch, hasAttr, isSelected, onToggleSelect) {
|
|
1561
|
+
function renderCellContent(colDef, entry, col, selectedAttribute, searchAttribute, isMatch, hasAttr, isSelected, onToggleSelect) {
|
|
1550
1562
|
switch (colDef.key) {
|
|
1551
1563
|
case "select":
|
|
1552
1564
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1563,6 +1575,27 @@ function renderCellContent(colDef, entry, col, selectedAttribute, isMatch, hasAt
|
|
|
1563
1575
|
entry.email && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", display: "block", children: entry.email })
|
|
1564
1576
|
] });
|
|
1565
1577
|
}
|
|
1578
|
+
case "search_attr": {
|
|
1579
|
+
const val = getNestedValue(entry, searchAttribute);
|
|
1580
|
+
const displayStr = formatDisplayValue(val);
|
|
1581
|
+
const isUnset = displayStr === "(empty / not set)" || displayStr === "(empty / unlinked)";
|
|
1582
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1583
|
+
designSystem.Typography,
|
|
1584
|
+
{
|
|
1585
|
+
textColor: isUnset ? "neutral500" : "primary700",
|
|
1586
|
+
fontWeight: "semiBold",
|
|
1587
|
+
style: {
|
|
1588
|
+
fontStyle: isUnset ? "italic" : "normal",
|
|
1589
|
+
display: "inline-block",
|
|
1590
|
+
maxWidth: 260,
|
|
1591
|
+
overflow: "hidden",
|
|
1592
|
+
textOverflow: "ellipsis",
|
|
1593
|
+
whiteSpace: "nowrap"
|
|
1594
|
+
},
|
|
1595
|
+
children: displayStr
|
|
1596
|
+
}
|
|
1597
|
+
);
|
|
1598
|
+
}
|
|
1566
1599
|
case "target_attr": {
|
|
1567
1600
|
const val = getNestedValue(entry, selectedAttribute);
|
|
1568
1601
|
const displayStr = formatDisplayValue(val);
|
|
@@ -1687,10 +1720,34 @@ const BulkUpdater = () => {
|
|
|
1687
1720
|
};
|
|
1688
1721
|
const [useRegex, setUseRegex] = React.useState(false);
|
|
1689
1722
|
const [regexPattern, setRegexPattern] = React.useState("");
|
|
1723
|
+
const DEPTH_STORAGE_KEY = "strapi_bulk_updater_component_depth";
|
|
1724
|
+
const [componentDepth, setComponentDepth] = React.useState(() => {
|
|
1725
|
+
try {
|
|
1726
|
+
const stored = localStorage.getItem(DEPTH_STORAGE_KEY);
|
|
1727
|
+
if (stored) {
|
|
1728
|
+
const val = Number(stored);
|
|
1729
|
+
if (val >= 1 && val <= 5) return val;
|
|
1730
|
+
}
|
|
1731
|
+
} catch {
|
|
1732
|
+
}
|
|
1733
|
+
return 3;
|
|
1734
|
+
});
|
|
1735
|
+
const handleComponentDepthChange = (depth) => {
|
|
1736
|
+
const capped = Math.min(5, Math.max(1, depth));
|
|
1737
|
+
setComponentDepth(capped);
|
|
1738
|
+
try {
|
|
1739
|
+
localStorage.setItem(DEPTH_STORAGE_KEY, String(capped));
|
|
1740
|
+
} catch {
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1743
|
+
const [searchAttribute, setSearchAttribute] = React.useState("");
|
|
1744
|
+
const [searchAttributeInput, setSearchAttributeInput] = React.useState("");
|
|
1745
|
+
const [attributesMeta, setAttributesMeta] = React.useState({});
|
|
1746
|
+
const effectiveSearchAttribute = searchAttribute || selectedAttribute;
|
|
1690
1747
|
const [filterOperator, setFilterOperator] = React.useState("none");
|
|
1691
1748
|
const [filterQuery, setFilterQuery] = React.useState("");
|
|
1692
1749
|
const [entrySearch, setEntrySearch] = React.useState("");
|
|
1693
|
-
const isFilterActive = filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
1750
|
+
const isFilterActive = Boolean(searchAttribute && searchAttribute !== selectedAttribute) || filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
1694
1751
|
const [lastResults, setLastResults] = React.useState(null);
|
|
1695
1752
|
const [updateSummary, setUpdateSummary] = React.useState(null);
|
|
1696
1753
|
const [collectionPages, setCollectionPages] = React.useState({});
|
|
@@ -1770,6 +1827,9 @@ const BulkUpdater = () => {
|
|
|
1770
1827
|
if (data.relationsMeta) {
|
|
1771
1828
|
setRelationsMeta(data.relationsMeta);
|
|
1772
1829
|
}
|
|
1830
|
+
if (data.attributesMeta) {
|
|
1831
|
+
setAttributesMeta(data.attributesMeta);
|
|
1832
|
+
}
|
|
1773
1833
|
let storedAttr = null;
|
|
1774
1834
|
try {
|
|
1775
1835
|
storedAttr = localStorage.getItem(LAST_ATTR_KEY);
|
|
@@ -1817,7 +1877,7 @@ const BulkUpdater = () => {
|
|
|
1817
1877
|
setLoading(false);
|
|
1818
1878
|
}
|
|
1819
1879
|
};
|
|
1820
|
-
const loadCollectionPage = async (colUid, targetPage, customPageSize, customSortField, customSortOrder, overrideFilterOp, overrideFilterQuery, overrideEntrySearch, autoSelectReturned = true) => {
|
|
1880
|
+
const loadCollectionPage = async (colUid, targetPage, customPageSize, customSortField, customSortOrder, overrideFilterOp, overrideFilterQuery, overrideEntrySearch, autoSelectReturned = true, overrideSearchAttr) => {
|
|
1821
1881
|
const currentPageState = collectionPages[colUid];
|
|
1822
1882
|
const size = customPageSize || currentPageState?.pageSize || defaultPageSize;
|
|
1823
1883
|
const currentSort = collectionSorts[colUid] || { field: "createdAt", order: "desc" };
|
|
@@ -1826,6 +1886,7 @@ const BulkUpdater = () => {
|
|
|
1826
1886
|
const op = overrideFilterOp !== void 0 ? overrideFilterOp : filterOperator;
|
|
1827
1887
|
const q = overrideFilterQuery !== void 0 ? overrideFilterQuery : filterQuery;
|
|
1828
1888
|
const s = overrideEntrySearch !== void 0 ? overrideEntrySearch : entrySearch;
|
|
1889
|
+
const searchAttr = overrideSearchAttr !== void 0 ? overrideSearchAttr : searchAttribute;
|
|
1829
1890
|
setCollectionPages((prev) => ({
|
|
1830
1891
|
...prev,
|
|
1831
1892
|
[colUid]: {
|
|
@@ -1839,6 +1900,9 @@ const BulkUpdater = () => {
|
|
|
1839
1900
|
pageSize: String(size)
|
|
1840
1901
|
});
|
|
1841
1902
|
if (selectedAttribute) params.set("attribute", selectedAttribute);
|
|
1903
|
+
if (searchAttr && searchAttr !== selectedAttribute) {
|
|
1904
|
+
params.set("searchAttribute", searchAttr);
|
|
1905
|
+
}
|
|
1842
1906
|
if (op && op !== "none") {
|
|
1843
1907
|
params.set("filterOperator", op);
|
|
1844
1908
|
if (q) params.set("filterQuery", q);
|
|
@@ -1868,7 +1932,7 @@ const BulkUpdater = () => {
|
|
|
1868
1932
|
loading: false
|
|
1869
1933
|
}
|
|
1870
1934
|
}));
|
|
1871
|
-
const isFilterActiveNow = op !== "none" && (["empty", "not_empty"].includes(op) || Boolean(q.trim())) || Boolean(s.trim());
|
|
1935
|
+
const isFilterActiveNow = Boolean(searchAttr && searchAttr !== selectedAttribute) || op !== "none" && (["empty", "not_empty"].includes(op) || Boolean(q.trim())) || Boolean(s.trim());
|
|
1872
1936
|
if (isFilterActiveNow && autoSelectReturned) {
|
|
1873
1937
|
setSelectedEntries((prev) => {
|
|
1874
1938
|
const next = { ...prev };
|
|
@@ -1955,13 +2019,14 @@ const BulkUpdater = () => {
|
|
|
1955
2019
|
}
|
|
1956
2020
|
const timer = setTimeout(() => {
|
|
1957
2021
|
if (collections.length > 0) {
|
|
1958
|
-
const isFilterActiveNow = filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
2022
|
+
const isFilterActiveNow = Boolean(searchAttribute && searchAttribute !== selectedAttribute) || filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
1959
2023
|
if (isFilterActiveNow) {
|
|
1960
2024
|
setSelectedEntries({});
|
|
1961
2025
|
}
|
|
2026
|
+
const targetSearchAttr = searchAttribute || selectedAttribute;
|
|
1962
2027
|
const targetCols = collections.filter((col) => {
|
|
1963
2028
|
if (visibleTypeUids[col.uid] === false) return false;
|
|
1964
|
-
if (filterOperator !== "none" && !col.attributes.includes(
|
|
2029
|
+
if (filterOperator !== "none" && targetSearchAttr && !col.attributes.includes(targetSearchAttr)) return false;
|
|
1965
2030
|
return true;
|
|
1966
2031
|
});
|
|
1967
2032
|
targetCols.forEach((col) => {
|
|
@@ -1974,13 +2039,14 @@ const BulkUpdater = () => {
|
|
|
1974
2039
|
filterOperator,
|
|
1975
2040
|
filterQuery,
|
|
1976
2041
|
entrySearch,
|
|
1977
|
-
true
|
|
2042
|
+
true,
|
|
2043
|
+
searchAttribute
|
|
1978
2044
|
);
|
|
1979
2045
|
});
|
|
1980
2046
|
}
|
|
1981
2047
|
}, 350);
|
|
1982
2048
|
return () => clearTimeout(timer);
|
|
1983
|
-
}, [filterOperator, filterQuery, entrySearch]);
|
|
2049
|
+
}, [searchAttribute, filterOperator, filterQuery, entrySearch]);
|
|
1984
2050
|
const KEY_SEP = "@@@";
|
|
1985
2051
|
const handleAttributeChange = (newAttr) => {
|
|
1986
2052
|
if (newAttr !== selectedAttribute) {
|
|
@@ -2049,39 +2115,119 @@ const BulkUpdater = () => {
|
|
|
2049
2115
|
setVisibleTypeUids(newVis);
|
|
2050
2116
|
};
|
|
2051
2117
|
const [attributeSearch, setAttributeSearch] = React.useState("");
|
|
2118
|
+
const [searchAttributeSearch, setSearchAttributeSearch] = React.useState("");
|
|
2119
|
+
const getAttrDepth = (attr) => attributesMeta[attr]?.depth ?? (attr.includes(".") ? attr.split(".").length - 1 : 0);
|
|
2120
|
+
const depthFilteredAttributes = React.useMemo(() => {
|
|
2121
|
+
return attributes.filter((attr) => getAttrDepth(attr) <= componentDepth);
|
|
2122
|
+
}, [attributes, componentDepth, attributesMeta]);
|
|
2052
2123
|
const filteredAttributes = React.useMemo(() => {
|
|
2053
2124
|
if (!attributeSearch.trim()) {
|
|
2054
|
-
return
|
|
2125
|
+
return depthFilteredAttributes;
|
|
2055
2126
|
}
|
|
2056
2127
|
const q = attributeSearch.toLowerCase().trim();
|
|
2057
2128
|
const cleanQ = q.replace(/[^a-z0-9]/g, "");
|
|
2058
|
-
return
|
|
2129
|
+
return depthFilteredAttributes.filter((attr) => {
|
|
2059
2130
|
const lower = attr.toLowerCase();
|
|
2060
2131
|
const cleanLower = lower.replace(/[^a-z0-9]/g, "");
|
|
2061
2132
|
const rel = relationsMeta[attr];
|
|
2062
2133
|
const relTarget = (rel?.targetDisplayName || "").toLowerCase();
|
|
2063
2134
|
return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
|
|
2064
2135
|
});
|
|
2065
|
-
}, [
|
|
2136
|
+
}, [depthFilteredAttributes, attributeSearch, relationsMeta]);
|
|
2137
|
+
const filteredSearchAttributes = React.useMemo(() => {
|
|
2138
|
+
if (!searchAttributeSearch.trim()) {
|
|
2139
|
+
return depthFilteredAttributes;
|
|
2140
|
+
}
|
|
2141
|
+
const q = searchAttributeSearch.toLowerCase().trim();
|
|
2142
|
+
const cleanQ = q.replace(/[^a-z0-9]/g, "");
|
|
2143
|
+
return depthFilteredAttributes.filter((attr) => {
|
|
2144
|
+
const lower = attr.toLowerCase();
|
|
2145
|
+
const cleanLower = lower.replace(/[^a-z0-9]/g, "");
|
|
2146
|
+
const rel = relationsMeta[attr];
|
|
2147
|
+
const relTarget = (rel?.targetDisplayName || "").toLowerCase();
|
|
2148
|
+
return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
|
|
2149
|
+
});
|
|
2150
|
+
}, [depthFilteredAttributes, searchAttributeSearch, relationsMeta]);
|
|
2066
2151
|
const memoizedComboboxOptions = React.useMemo(() => {
|
|
2067
2152
|
if (filteredAttributes.length === 0) {
|
|
2068
2153
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: "__none__", disabled: true, textValue: "No matching attributes found", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
2069
2154
|
'No matching attributes found for "',
|
|
2070
2155
|
attributeSearch,
|
|
2071
|
-
'"'
|
|
2156
|
+
'" (Depth L',
|
|
2157
|
+
componentDepth,
|
|
2158
|
+
")"
|
|
2072
2159
|
] }) });
|
|
2073
2160
|
}
|
|
2074
2161
|
return filteredAttributes.map((attr) => {
|
|
2075
2162
|
const rel = relationsMeta[attr];
|
|
2163
|
+
const depth = getAttrDepth(attr);
|
|
2076
2164
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: attr, textValue: attr, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
2077
2165
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: attr === selectedAttribute ? "bold" : "regular", children: attr }),
|
|
2078
2166
|
rel ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", size: "S", children: [
|
|
2079
2167
|
"relation ➔ ",
|
|
2080
2168
|
rel.targetDisplayName
|
|
2081
|
-
] }) :
|
|
2169
|
+
] }) : depth > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: depth === 1 ? "neutral150" : depth === 2 ? "primary100" : "secondary100", textColor: depth === 1 ? "neutral700" : depth === 2 ? "primary700" : "secondary700", size: "S", children: [
|
|
2170
|
+
"L",
|
|
2171
|
+
depth,
|
|
2172
|
+
" component"
|
|
2173
|
+
] }) : null
|
|
2082
2174
|
] }) }, attr);
|
|
2083
2175
|
});
|
|
2084
|
-
}, [filteredAttributes, relationsMeta, selectedAttribute, attributeSearch]);
|
|
2176
|
+
}, [filteredAttributes, relationsMeta, selectedAttribute, attributeSearch, componentDepth, attributesMeta]);
|
|
2177
|
+
const memoizedSearchComboboxOptions = React.useMemo(() => {
|
|
2178
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2179
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2180
|
+
designSystem.ComboboxOption,
|
|
2181
|
+
{
|
|
2182
|
+
value: "__default__",
|
|
2183
|
+
textValue: `Same as Update Attribute (${selectedAttribute || "None"})`,
|
|
2184
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
2185
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", fontStyle: "italic", textColor: "neutral600", children: [
|
|
2186
|
+
"-- Same as Update Attribute (",
|
|
2187
|
+
selectedAttribute || "None",
|
|
2188
|
+
") --"
|
|
2189
|
+
] }),
|
|
2190
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "neutral150", textColor: "neutral600", size: "S", children: "Default" })
|
|
2191
|
+
] })
|
|
2192
|
+
}
|
|
2193
|
+
),
|
|
2194
|
+
filteredSearchAttributes.map((attr) => {
|
|
2195
|
+
const rel = relationsMeta[attr];
|
|
2196
|
+
const depth = getAttrDepth(attr);
|
|
2197
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: attr, textValue: attr, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
2198
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: attr === searchAttribute ? "bold" : "regular", children: attr }),
|
|
2199
|
+
rel ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", size: "S", children: [
|
|
2200
|
+
"relation ➔ ",
|
|
2201
|
+
rel.targetDisplayName
|
|
2202
|
+
] }) : depth > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: depth === 1 ? "neutral150" : depth === 2 ? "primary100" : "secondary100", textColor: depth === 1 ? "neutral700" : depth === 2 ? "primary700" : "secondary700", size: "S", children: [
|
|
2203
|
+
"L",
|
|
2204
|
+
depth,
|
|
2205
|
+
" component"
|
|
2206
|
+
] }) : null
|
|
2207
|
+
] }) }, `search_${attr}`);
|
|
2208
|
+
})
|
|
2209
|
+
] });
|
|
2210
|
+
}, [filteredSearchAttributes, relationsMeta, searchAttribute, selectedAttribute, componentDepth, attributesMeta]);
|
|
2211
|
+
const handleSearchAttributeChange = (newAttr) => {
|
|
2212
|
+
const finalAttr = newAttr === "__default__" ? "" : newAttr;
|
|
2213
|
+
setSearchAttribute(finalAttr);
|
|
2214
|
+
if (collections.length > 0) {
|
|
2215
|
+
collections.forEach((col) => {
|
|
2216
|
+
loadCollectionPage(
|
|
2217
|
+
col.uid,
|
|
2218
|
+
1,
|
|
2219
|
+
void 0,
|
|
2220
|
+
void 0,
|
|
2221
|
+
void 0,
|
|
2222
|
+
filterOperator,
|
|
2223
|
+
filterQuery,
|
|
2224
|
+
entrySearch,
|
|
2225
|
+
true,
|
|
2226
|
+
finalAttr
|
|
2227
|
+
);
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
};
|
|
2085
2231
|
const handleGlobalPageSizeChange = (newSize) => {
|
|
2086
2232
|
const capped = Math.min(500, Math.max(1, newSize));
|
|
2087
2233
|
setDefaultPageSize(capped);
|
|
@@ -2172,12 +2318,14 @@ const BulkUpdater = () => {
|
|
|
2172
2318
|
setSelectedEntries(updated);
|
|
2173
2319
|
};
|
|
2174
2320
|
const clearFilter = () => {
|
|
2321
|
+
setSearchAttribute("");
|
|
2322
|
+
setSearchAttributeSearch("");
|
|
2175
2323
|
setFilterOperator("none");
|
|
2176
2324
|
setFilterQuery("");
|
|
2177
2325
|
setEntrySearch("");
|
|
2178
2326
|
setSelectedEntries({});
|
|
2179
2327
|
collections.forEach((col) => {
|
|
2180
|
-
loadCollectionPage(col.uid, 1, void 0, void 0, void 0, "none", "", "", false);
|
|
2328
|
+
loadCollectionPage(col.uid, 1, void 0, void 0, void 0, "none", "", "", false, "");
|
|
2181
2329
|
});
|
|
2182
2330
|
};
|
|
2183
2331
|
const isCollectionFullySelected = (col) => {
|
|
@@ -2973,7 +3121,29 @@ const BulkUpdater = () => {
|
|
|
2973
3121
|
marginBottom: 6,
|
|
2974
3122
|
style: { width: "100%", maxWidth: "100%", minWidth: 0, boxSizing: "border-box" },
|
|
2975
3123
|
children: [
|
|
2976
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3124
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", marginBottom: 4, wrap: "wrap", gap: 3, children: [
|
|
3125
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
3126
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h2", fontWeight: "semiBold", children: "1. Configure Attribute Update" }),
|
|
3127
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Select the target attribute to update across collections." })
|
|
3128
|
+
] }),
|
|
3129
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3130
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral700", fontWeight: "bold", children: "Component Nesting Depth:" }),
|
|
3131
|
+
[1, 2, 3, 4, 5].map((lvl) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3132
|
+
designSystem.Button,
|
|
3133
|
+
{
|
|
3134
|
+
variant: componentDepth === lvl ? "default" : "tertiary",
|
|
3135
|
+
size: "S",
|
|
3136
|
+
onClick: () => handleComponentDepthChange(lvl),
|
|
3137
|
+
title: `Discover nested component attributes up to Level ${lvl}`,
|
|
3138
|
+
children: [
|
|
3139
|
+
"Level ",
|
|
3140
|
+
lvl
|
|
3141
|
+
]
|
|
3142
|
+
},
|
|
3143
|
+
`depth_cfg_${lvl}`
|
|
3144
|
+
))
|
|
3145
|
+
] })
|
|
3146
|
+
] }),
|
|
2977
3147
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, alignItems: "flex-end", wrap: "wrap", children: [
|
|
2978
3148
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { minWidth: 280, flex: 1, maxWidth: 440 }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { children: [
|
|
2979
3149
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Attribute to Update" }),
|
|
@@ -3304,26 +3474,83 @@ const BulkUpdater = () => {
|
|
|
3304
3474
|
style: { width: "100%", maxWidth: "100%", boxSizing: "border-box" },
|
|
3305
3475
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, children: [
|
|
3306
3476
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 2, children: [
|
|
3307
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
3477
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3308
3478
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: "Search & Filter Targets:" }),
|
|
3309
3479
|
isFilterActive && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
3310
3480
|
matchingEntriesCount,
|
|
3311
3481
|
" matching ",
|
|
3312
3482
|
matchingEntriesCount === 1 ? "entry" : "entries",
|
|
3313
3483
|
" found in database"
|
|
3484
|
+
] }),
|
|
3485
|
+
searchAttribute && searchAttribute !== selectedAttribute && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: [
|
|
3486
|
+
"Searching by: ",
|
|
3487
|
+
searchAttribute,
|
|
3488
|
+
" → Target to update: ",
|
|
3489
|
+
selectedAttribute
|
|
3314
3490
|
] })
|
|
3315
3491
|
] }),
|
|
3316
|
-
|
|
3492
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
3493
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, alignItems: "center", children: [
|
|
3494
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Depth:" }),
|
|
3495
|
+
[1, 2, 3, 4, 5].map((lvl) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3496
|
+
designSystem.Button,
|
|
3497
|
+
{
|
|
3498
|
+
variant: componentDepth === lvl ? "default" : "tertiary",
|
|
3499
|
+
size: "S",
|
|
3500
|
+
onClick: () => handleComponentDepthChange(lvl),
|
|
3501
|
+
title: `Show component attributes up to Level ${lvl}`,
|
|
3502
|
+
style: { minWidth: 26, padding: "2px 6px" },
|
|
3503
|
+
children: [
|
|
3504
|
+
"L",
|
|
3505
|
+
lvl
|
|
3506
|
+
]
|
|
3507
|
+
},
|
|
3508
|
+
`s2_depth_${lvl}`
|
|
3509
|
+
))
|
|
3510
|
+
] }),
|
|
3511
|
+
isFilterActive && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "ghost", size: "S", onClick: clearFilter, children: "Clear Search & Filter" })
|
|
3512
|
+
] })
|
|
3317
3513
|
] }),
|
|
3318
3514
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "flex-end", wrap: "wrap", children: [
|
|
3319
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width:
|
|
3515
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 280, minWidth: 230 }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { children: [
|
|
3516
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Search Attribute" }),
|
|
3517
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3518
|
+
designSystem.Combobox,
|
|
3519
|
+
{
|
|
3520
|
+
autocomplete: "none",
|
|
3521
|
+
placeholder: searchAttribute || `Same as Update (${selectedAttribute || "None"})`,
|
|
3522
|
+
value: searchAttribute || "__default__",
|
|
3523
|
+
clearLabel: "Reset search attribute",
|
|
3524
|
+
onClear: () => {
|
|
3525
|
+
handleSearchAttributeChange("");
|
|
3526
|
+
setSearchAttributeSearch("");
|
|
3527
|
+
},
|
|
3528
|
+
onInputChange: (e) => {
|
|
3529
|
+
setSearchAttributeSearch(e.target.value);
|
|
3530
|
+
},
|
|
3531
|
+
onOpenChange: (isOpen) => {
|
|
3532
|
+
if (!isOpen) {
|
|
3533
|
+
setSearchAttributeSearch("");
|
|
3534
|
+
}
|
|
3535
|
+
},
|
|
3536
|
+
onChange: (val) => {
|
|
3537
|
+
if (val && typeof val === "string" && val !== "__none__") {
|
|
3538
|
+
handleSearchAttributeChange(val);
|
|
3539
|
+
setSearchAttributeSearch("");
|
|
3540
|
+
}
|
|
3541
|
+
},
|
|
3542
|
+
children: memoizedSearchComboboxOptions
|
|
3543
|
+
}
|
|
3544
|
+
)
|
|
3545
|
+
] }) }),
|
|
3546
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 200, minWidth: 170 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3320
3547
|
designSystem.SingleSelect,
|
|
3321
3548
|
{
|
|
3322
|
-
label:
|
|
3549
|
+
label: effectiveSearchAttribute ? `Condition for "${effectiveSearchAttribute}"` : "Filter condition",
|
|
3323
3550
|
value: filterOperator,
|
|
3324
3551
|
onChange: (val) => setFilterOperator(String(val)),
|
|
3325
3552
|
children: [
|
|
3326
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "none", children: "Show All (No
|
|
3553
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "none", children: "Show All (No Value Filter)" }),
|
|
3327
3554
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "empty", children: "Is Empty or Null" }),
|
|
3328
3555
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "not_empty", children: "Is Not Empty" }),
|
|
3329
3556
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "equals", children: "Equals Exact Text" }),
|
|
@@ -3332,16 +3559,16 @@ const BulkUpdater = () => {
|
|
|
3332
3559
|
]
|
|
3333
3560
|
}
|
|
3334
3561
|
) }),
|
|
3335
|
-
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth:
|
|
3562
|
+
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3336
3563
|
designSystem.TextInput,
|
|
3337
3564
|
{
|
|
3338
|
-
label:
|
|
3565
|
+
label: effectiveSearchAttribute ? `Value for "${effectiveSearchAttribute}"` : "Value to match",
|
|
3339
3566
|
placeholder: "Type value to match...",
|
|
3340
3567
|
value: filterQuery,
|
|
3341
3568
|
onChange: (e) => setFilterQuery(e.target.value)
|
|
3342
3569
|
}
|
|
3343
3570
|
) }),
|
|
3344
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth:
|
|
3571
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3345
3572
|
designSystem.TextInput,
|
|
3346
3573
|
{
|
|
3347
3574
|
label: "Full-text Entry Search",
|
|
@@ -3539,11 +3766,11 @@ const BulkUpdater = () => {
|
|
|
3539
3766
|
const pageSize = pageState ? pageState.pageSize : defaultPageSize;
|
|
3540
3767
|
const hasAttr = selectedAttribute ? col.attributes.includes(selectedAttribute) : false;
|
|
3541
3768
|
const visibleEntries = getVisibleEntries(col);
|
|
3542
|
-
selectedAttribute ? entries.filter((e) => entryMatchesFilter(e,
|
|
3769
|
+
selectedAttribute ? entries.filter((e) => entryMatchesFilter(e, effectiveSearchAttribute)).length : 0;
|
|
3543
3770
|
const isFullySelected = isCollectionFullySelected(col);
|
|
3544
3771
|
const isPartiallySelected = isCollectionPartiallySelected(col);
|
|
3545
3772
|
const currentSort = collectionSorts[col.uid] || { field: "createdAt", order: "desc" };
|
|
3546
|
-
const availableColumns = getAvailableColumnsForCollection(col, selectedAttribute);
|
|
3773
|
+
const availableColumns = getAvailableColumnsForCollection(col, selectedAttribute, searchAttribute);
|
|
3547
3774
|
const savedColKeys = collectionColumnVisibility[col.uid];
|
|
3548
3775
|
const activeColumns = savedColKeys ? availableColumns.filter((c) => c.isPermanent || savedColKeys.includes(c.key)) : availableColumns.filter((c) => c.defaultVisible);
|
|
3549
3776
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3753,7 +3980,7 @@ const BulkUpdater = () => {
|
|
|
3753
3980
|
),
|
|
3754
3981
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { className: "bulk-updater-table-container", style: { width: "100%", maxWidth: "100%", minWidth: 0, overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: activeColumns.length, rowCount: visibleEntries.length + 1, style: { width: "100%" }, children: [
|
|
3755
3982
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: activeColumns.map(
|
|
3756
|
-
(colDef) => renderHeaderCell(colDef, col, currentSort, selectedAttribute, handleHeaderSortClick)
|
|
3983
|
+
(colDef) => renderHeaderCell(colDef, col, currentSort, selectedAttribute, searchAttribute, handleHeaderSortClick)
|
|
3757
3984
|
) }) }),
|
|
3758
3985
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: visibleEntries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: activeColumns.length, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, style: { textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "No entries in this content type match the active filter criteria." }) }) }) }) : visibleEntries.map((entry) => {
|
|
3759
3986
|
const key = `${col.uid}${KEY_SEP}${entry.documentId}`;
|
|
@@ -3771,6 +3998,7 @@ const BulkUpdater = () => {
|
|
|
3771
3998
|
entry,
|
|
3772
3999
|
col,
|
|
3773
4000
|
selectedAttribute,
|
|
4001
|
+
searchAttribute,
|
|
3774
4002
|
isMatch,
|
|
3775
4003
|
hasAttr,
|
|
3776
4004
|
isSelected,
|
|
@@ -4744,4 +4972,4 @@ exports.default = BulkUpdater;
|
|
|
4744
4972
|
exports.formatDisplayValue = formatDisplayValue;
|
|
4745
4973
|
exports.getAvailableColumnsForCollection = getAvailableColumnsForCollection;
|
|
4746
4974
|
exports.getNestedValue = getNestedValue;
|
|
4747
|
-
//# sourceMappingURL=BulkUpdater-
|
|
4975
|
+
//# sourceMappingURL=BulkUpdater-CRvwX326.js.map
|