strapi-plugin-bulk-updater 1.1.0 → 1.2.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 +7 -1
- package/dist/_chunks/{BulkUpdater-BSZP0U18.mjs → BulkUpdater-BDszahRM.mjs} +145 -87
- package/dist/_chunks/BulkUpdater-BDszahRM.mjs.map +1 -0
- package/dist/_chunks/{BulkUpdater-BRcMQGP3.js → BulkUpdater-DCrCPKSe.js} +143 -85
- package/dist/_chunks/BulkUpdater-DCrCPKSe.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +319 -63
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +319 -63
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/_chunks/BulkUpdater-BRcMQGP3.js.map +0 -1
- package/dist/_chunks/BulkUpdater-BSZP0U18.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -54,7 +54,13 @@ Strapi allows editing entries individually or applying bulk actions within a sin
|
|
|
54
54
|
- **Tier 2 (Strapi Enterprise Bridge)**: Bridges events directly to native Strapi Enterprise Audit Logs (`admin::audit-logs`).
|
|
55
55
|
- **Tier 3 (Custom Declarative Schema)**: Custom collection types and declarative column mappings.
|
|
56
56
|
- **Deterministic Rollback**: Restores exact prior values and relationship links using Strapi v5 Document Service.
|
|
57
|
-
-
|
|
57
|
+
- 🧩 **Deep Nested Component Support**:
|
|
58
|
+
- Full dot-notation introspection (e.g. `metaFields.metaDescription`, `defaultSeo.metaTitle`) in attribute dropdown and table views.
|
|
59
|
+
- Non-destructive deep merging preserves sibling component properties during bulk updates and rollbacks.
|
|
60
|
+
- ⚡ **Server-Side Filter & Full-Text Search Pushdown**:
|
|
61
|
+
- Pushes text searches and attribute filters (`equals`, `contains`, `empty`, `starts_with`) directly to the database.
|
|
62
|
+
- Automatically hides non-matching records and pre-selects matching rows with real-time match counters.
|
|
63
|
+
- Scalable server-side pagination up to 500 records per page with a one-click "Load all entries" button.
|
|
58
64
|
- 🌓 **Adaptive Light & Dark Theme Design**: Built with native `@strapi/design-system` tokens with high-contrast text and sticky viewport-constrained modals.
|
|
59
65
|
- ⚡ **Zero-Infra Strapi Cloud Ready**: In-memory caching, pod-level high-watermark ETags, zero external Redis/SQL requirements.
|
|
60
66
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import React__default, { useState, useEffect } from "react";
|
|
2
|
+
import React__default, { useState, useEffect, useRef } from "react";
|
|
3
3
|
import { useFetchClient, useNotification } from "@strapi/strapi/admin";
|
|
4
4
|
import { Box, Flex, Typography, Button, SingleSelect, SingleSelectOption, Checkbox, Badge, Table, Thead, Tr, Th, Tbody, Td, Alert, TextInput } from "@strapi/design-system";
|
|
5
5
|
import { ArrowClockwise, Download, Upload, Check, Play } from "@strapi/icons";
|
|
@@ -418,6 +418,11 @@ function CsvManagerTab() {
|
|
|
418
418
|
] })
|
|
419
419
|
] }) });
|
|
420
420
|
}
|
|
421
|
+
function getNestedValue(obj, path) {
|
|
422
|
+
if (!obj || !path) return void 0;
|
|
423
|
+
if (!path.includes(".")) return obj[path];
|
|
424
|
+
return path.split(".").reduce((acc, part) => acc && typeof acc === "object" ? acc[part] : void 0, obj);
|
|
425
|
+
}
|
|
421
426
|
function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
422
427
|
const cols = [
|
|
423
428
|
{
|
|
@@ -438,7 +443,7 @@ function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
|
438
443
|
if (attr === "name" || attr === "title" || attr === selectedAttribute) {
|
|
439
444
|
return;
|
|
440
445
|
}
|
|
441
|
-
const formattedLabel = attr.charAt(0).toUpperCase() + attr.slice(1);
|
|
446
|
+
const formattedLabel = attr.includes(".") ? attr.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ") : attr.charAt(0).toUpperCase() + attr.slice(1);
|
|
442
447
|
cols.push({
|
|
443
448
|
key: `attr_${attr}`,
|
|
444
449
|
label: formattedLabel,
|
|
@@ -524,7 +529,7 @@ function renderCellContent(colDef, entry, col, selectedAttribute, isMatch, hasAt
|
|
|
524
529
|
] });
|
|
525
530
|
}
|
|
526
531
|
case "target_attr": {
|
|
527
|
-
const val = entry
|
|
532
|
+
const val = getNestedValue(entry, selectedAttribute);
|
|
528
533
|
const displayStr = formatDisplayValue(val);
|
|
529
534
|
const isUnset = displayStr === "(empty / not set)" || displayStr === "(empty / unlinked)";
|
|
530
535
|
return /* @__PURE__ */ jsx(
|
|
@@ -554,7 +559,7 @@ function renderCellContent(colDef, entry, col, selectedAttribute, isMatch, hasAt
|
|
|
554
559
|
}
|
|
555
560
|
default: {
|
|
556
561
|
const attrName = colDef.key.replace("attr_", "");
|
|
557
|
-
const rawVal = entry
|
|
562
|
+
const rawVal = getNestedValue(entry, attrName);
|
|
558
563
|
const displayStr = formatDisplayValue(rawVal);
|
|
559
564
|
return /* @__PURE__ */ jsx(
|
|
560
565
|
Typography,
|
|
@@ -628,7 +633,8 @@ const BulkUpdater = () => {
|
|
|
628
633
|
const [regexPattern, setRegexPattern] = useState("");
|
|
629
634
|
const [filterOperator, setFilterOperator] = useState("none");
|
|
630
635
|
const [filterQuery, setFilterQuery] = useState("");
|
|
631
|
-
const [
|
|
636
|
+
const [entrySearch, setEntrySearch] = useState("");
|
|
637
|
+
const isFilterActive = filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
632
638
|
const [lastResults, setLastResults] = useState(null);
|
|
633
639
|
const [updateSummary, setUpdateSummary] = useState(null);
|
|
634
640
|
const [collectionPages, setCollectionPages] = useState({});
|
|
@@ -724,12 +730,15 @@ const BulkUpdater = () => {
|
|
|
724
730
|
setLoading(false);
|
|
725
731
|
}
|
|
726
732
|
};
|
|
727
|
-
const loadCollectionPage = async (colUid, targetPage, customPageSize, customSortField, customSortOrder) => {
|
|
733
|
+
const loadCollectionPage = async (colUid, targetPage, customPageSize, customSortField, customSortOrder, overrideFilterOp, overrideFilterQuery, overrideEntrySearch, autoSelectReturned = true) => {
|
|
728
734
|
const currentPageState = collectionPages[colUid];
|
|
729
735
|
const size = customPageSize || currentPageState?.pageSize || defaultPageSize;
|
|
730
736
|
const currentSort = collectionSorts[colUid] || { field: "createdAt", order: "desc" };
|
|
731
737
|
const sortField = customSortField !== void 0 ? customSortField : currentSort.field;
|
|
732
738
|
const sortOrder = customSortOrder !== void 0 ? customSortOrder : currentSort.order;
|
|
739
|
+
const op = overrideFilterOp !== void 0 ? overrideFilterOp : filterOperator;
|
|
740
|
+
const q = overrideFilterQuery !== void 0 ? overrideFilterQuery : filterQuery;
|
|
741
|
+
const s = overrideEntrySearch !== void 0 ? overrideEntrySearch : entrySearch;
|
|
733
742
|
setCollectionPages((prev) => ({
|
|
734
743
|
...prev,
|
|
735
744
|
[colUid]: {
|
|
@@ -743,16 +752,20 @@ const BulkUpdater = () => {
|
|
|
743
752
|
pageSize: String(size)
|
|
744
753
|
});
|
|
745
754
|
if (selectedAttribute) params.set("attribute", selectedAttribute);
|
|
746
|
-
if (
|
|
747
|
-
params.set("filterOperator",
|
|
748
|
-
if (
|
|
755
|
+
if (op && op !== "none") {
|
|
756
|
+
params.set("filterOperator", op);
|
|
757
|
+
if (q) params.set("filterQuery", q);
|
|
758
|
+
}
|
|
759
|
+
if (s && s.trim()) {
|
|
760
|
+
params.set("search", s.trim());
|
|
749
761
|
}
|
|
750
762
|
if (sortField) {
|
|
751
763
|
params.set("sortField", sortField);
|
|
752
764
|
params.set("sortOrder", sortOrder);
|
|
753
765
|
}
|
|
754
766
|
const res = await get(`/bulk-updater/collections/${colUid}/entries?${params.toString()}`);
|
|
755
|
-
if (res.data && res.data.success) {
|
|
767
|
+
if (res.data && (res.data.success || res.data.entries !== void 0)) {
|
|
768
|
+
const fetchedEntries = res.data.entries || [];
|
|
756
769
|
setCollectionPages((prev) => ({
|
|
757
770
|
...prev,
|
|
758
771
|
[colUid]: {
|
|
@@ -760,10 +773,20 @@ const BulkUpdater = () => {
|
|
|
760
773
|
pageSize: res.data.pagination.pageSize,
|
|
761
774
|
total: res.data.pagination.total,
|
|
762
775
|
pageCount: res.data.pagination.pageCount,
|
|
763
|
-
entries:
|
|
776
|
+
entries: fetchedEntries,
|
|
764
777
|
loading: false
|
|
765
778
|
}
|
|
766
779
|
}));
|
|
780
|
+
const isFilterActiveNow = op !== "none" && (["empty", "not_empty"].includes(op) || Boolean(q.trim())) || Boolean(s.trim());
|
|
781
|
+
if (isFilterActiveNow && autoSelectReturned) {
|
|
782
|
+
setSelectedEntries((prev) => {
|
|
783
|
+
const next = { ...prev };
|
|
784
|
+
fetchedEntries.forEach((e) => {
|
|
785
|
+
next[`${colUid}${KEY_SEP}${e.documentId}`] = true;
|
|
786
|
+
});
|
|
787
|
+
return next;
|
|
788
|
+
});
|
|
789
|
+
}
|
|
767
790
|
}
|
|
768
791
|
} catch (err) {
|
|
769
792
|
toggleNotification({
|
|
@@ -827,6 +850,35 @@ const BulkUpdater = () => {
|
|
|
827
850
|
fetchPendingBatches();
|
|
828
851
|
}
|
|
829
852
|
}, [activeTab]);
|
|
853
|
+
const isInitialFilterMount = useRef(true);
|
|
854
|
+
useEffect(() => {
|
|
855
|
+
if (isInitialFilterMount.current) {
|
|
856
|
+
isInitialFilterMount.current = false;
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
const timer = setTimeout(() => {
|
|
860
|
+
if (collections.length > 0) {
|
|
861
|
+
const isFilterActiveNow = filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
862
|
+
if (isFilterActiveNow) {
|
|
863
|
+
setSelectedEntries({});
|
|
864
|
+
}
|
|
865
|
+
collections.forEach((col) => {
|
|
866
|
+
loadCollectionPage(
|
|
867
|
+
col.uid,
|
|
868
|
+
1,
|
|
869
|
+
void 0,
|
|
870
|
+
void 0,
|
|
871
|
+
void 0,
|
|
872
|
+
filterOperator,
|
|
873
|
+
filterQuery,
|
|
874
|
+
entrySearch,
|
|
875
|
+
true
|
|
876
|
+
);
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
}, 350);
|
|
880
|
+
return () => clearTimeout(timer);
|
|
881
|
+
}, [filterOperator, filterQuery, entrySearch]);
|
|
830
882
|
const KEY_SEP = "@@@";
|
|
831
883
|
const handleAttributeChange = (newAttr) => {
|
|
832
884
|
if (newAttr !== selectedAttribute) {
|
|
@@ -834,7 +886,7 @@ const BulkUpdater = () => {
|
|
|
834
886
|
setSelectedEntries({});
|
|
835
887
|
setFilterOperator("none");
|
|
836
888
|
setFilterQuery("");
|
|
837
|
-
|
|
889
|
+
setEntrySearch("");
|
|
838
890
|
setSelectedRelationDocId("");
|
|
839
891
|
setAttributeValue("");
|
|
840
892
|
if (relationsMeta[newAttr]) {
|
|
@@ -851,7 +903,7 @@ const BulkUpdater = () => {
|
|
|
851
903
|
(c) => visibleTypeUids[c.uid] !== false && (!collectionSearch.trim() || c.displayName.toLowerCase().includes(collectionSearch.toLowerCase().trim()) || c.uid.toLowerCase().includes(collectionSearch.toLowerCase().trim()))
|
|
852
904
|
);
|
|
853
905
|
const handleGlobalPageSizeChange = (newSize) => {
|
|
854
|
-
const capped = Math.min(
|
|
906
|
+
const capped = Math.min(500, Math.max(1, newSize));
|
|
855
907
|
setDefaultPageSize(capped);
|
|
856
908
|
collections.forEach((col) => {
|
|
857
909
|
if (!col.isSingleType) {
|
|
@@ -860,7 +912,7 @@ const BulkUpdater = () => {
|
|
|
860
912
|
});
|
|
861
913
|
};
|
|
862
914
|
const handleCollectionPageSizeChange = (colUid, newSize) => {
|
|
863
|
-
const capped = Math.min(
|
|
915
|
+
const capped = Math.min(500, Math.max(1, newSize));
|
|
864
916
|
loadCollectionPage(colUid, 1, capped);
|
|
865
917
|
};
|
|
866
918
|
const handleCollectionSortChange = (colUid, field, order) => {
|
|
@@ -884,7 +936,7 @@ const BulkUpdater = () => {
|
|
|
884
936
|
};
|
|
885
937
|
const entryMatchesFilter = (entry, attr) => {
|
|
886
938
|
if (filterOperator === "none") return true;
|
|
887
|
-
const val = entry
|
|
939
|
+
const val = getNestedValue(entry, attr);
|
|
888
940
|
const displayStr = formatDisplayValue(val);
|
|
889
941
|
const isValEmpty = val === void 0 || val === null || displayStr.trim() === "" || displayStr.trim().toLowerCase() === "(not set)" || displayStr.trim().toLowerCase() === "(empty / not set)" || displayStr.trim().toLowerCase() === "(empty / unlinked)";
|
|
890
942
|
switch (filterOperator) {
|
|
@@ -904,64 +956,48 @@ const BulkUpdater = () => {
|
|
|
904
956
|
};
|
|
905
957
|
const getVisibleEntries = (col) => {
|
|
906
958
|
const pageState = collectionPages[col.uid];
|
|
907
|
-
|
|
908
|
-
if (!hideNonMatching || filterOperator === "none") {
|
|
909
|
-
return entries;
|
|
910
|
-
}
|
|
911
|
-
return entries.filter((e) => entryMatchesFilter(e, selectedAttribute));
|
|
959
|
+
return pageState ? pageState.entries : col.entries || [];
|
|
912
960
|
};
|
|
913
961
|
const matchingEntriesCount = React__default.useMemo(() => {
|
|
914
|
-
if (
|
|
962
|
+
if (!isFilterActive) return 0;
|
|
915
963
|
let count = 0;
|
|
916
964
|
filteredCollections.forEach((col) => {
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
entries.forEach((entry) => {
|
|
921
|
-
if (entryMatchesFilter(entry, selectedAttribute)) {
|
|
922
|
-
count++;
|
|
923
|
-
}
|
|
924
|
-
});
|
|
965
|
+
const pageState = collectionPages[col.uid];
|
|
966
|
+
if (pageState) {
|
|
967
|
+
count += pageState.total;
|
|
925
968
|
}
|
|
926
969
|
});
|
|
927
970
|
return count;
|
|
928
|
-
}, [filteredCollections, collectionPages,
|
|
971
|
+
}, [filteredCollections, collectionPages, isFilterActive]);
|
|
929
972
|
const selectAllMatching = () => {
|
|
930
973
|
const updated = { ...selectedEntries };
|
|
931
974
|
filteredCollections.forEach((col) => {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
updated[`${col.uid}${KEY_SEP}${e.documentId}`] = true;
|
|
938
|
-
}
|
|
939
|
-
});
|
|
940
|
-
}
|
|
975
|
+
const pageState = collectionPages[col.uid];
|
|
976
|
+
const entries = pageState ? pageState.entries : col.entries || [];
|
|
977
|
+
entries.forEach((e) => {
|
|
978
|
+
updated[`${col.uid}${KEY_SEP}${e.documentId}`] = true;
|
|
979
|
+
});
|
|
941
980
|
});
|
|
942
981
|
setSelectedEntries(updated);
|
|
943
982
|
};
|
|
944
983
|
const deselectAllMatching = () => {
|
|
945
984
|
const updated = { ...selectedEntries };
|
|
946
985
|
filteredCollections.forEach((col) => {
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
delete updated[`${col.uid}${KEY_SEP}${e.documentId}`];
|
|
953
|
-
}
|
|
954
|
-
});
|
|
955
|
-
}
|
|
986
|
+
const pageState = collectionPages[col.uid];
|
|
987
|
+
const entries = pageState ? pageState.entries : col.entries || [];
|
|
988
|
+
entries.forEach((e) => {
|
|
989
|
+
delete updated[`${col.uid}${KEY_SEP}${e.documentId}`];
|
|
990
|
+
});
|
|
956
991
|
});
|
|
957
992
|
setSelectedEntries(updated);
|
|
958
993
|
};
|
|
959
994
|
const clearFilter = () => {
|
|
960
995
|
setFilterOperator("none");
|
|
961
996
|
setFilterQuery("");
|
|
962
|
-
|
|
997
|
+
setEntrySearch("");
|
|
998
|
+
setSelectedEntries({});
|
|
963
999
|
collections.forEach((col) => {
|
|
964
|
-
loadCollectionPage(col.uid, 1);
|
|
1000
|
+
loadCollectionPage(col.uid, 1, void 0, void 0, void 0, "none", "", "", false);
|
|
965
1001
|
});
|
|
966
1002
|
};
|
|
967
1003
|
const isCollectionFullySelected = (col) => {
|
|
@@ -1083,6 +1119,7 @@ const BulkUpdater = () => {
|
|
|
1083
1119
|
message: `Bulk update complete! Batch ID: ${res.data.batchId}. Updated: ${res.data.updatedCount}, Skipped: ${res.data.skippedCount}`
|
|
1084
1120
|
});
|
|
1085
1121
|
await fetchModels();
|
|
1122
|
+
await fetchAuditHistory();
|
|
1086
1123
|
}
|
|
1087
1124
|
} else {
|
|
1088
1125
|
toggleNotification({
|
|
@@ -1369,7 +1406,7 @@ const BulkUpdater = () => {
|
|
|
1369
1406
|
/* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral700", children: [
|
|
1370
1407
|
/* @__PURE__ */ jsx("code", { children: latestActiveBatch.batchId }),
|
|
1371
1408
|
" (",
|
|
1372
|
-
latestActiveBatch.
|
|
1409
|
+
latestActiveBatch.updatedCount,
|
|
1373
1410
|
" entries updated by ",
|
|
1374
1411
|
latestActiveBatch.userEmail,
|
|
1375
1412
|
")"
|
|
@@ -1596,24 +1633,25 @@ const BulkUpdater = () => {
|
|
|
1596
1633
|
children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
|
1597
1634
|
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 2, children: [
|
|
1598
1635
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
1599
|
-
/* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", children: "
|
|
1600
|
-
|
|
1636
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "bold", children: "Search & Filter Targets:" }),
|
|
1637
|
+
isFilterActive && /* @__PURE__ */ jsxs(Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
1601
1638
|
matchingEntriesCount,
|
|
1602
1639
|
" matching ",
|
|
1603
|
-
matchingEntriesCount === 1 ? "entry" : "entries"
|
|
1640
|
+
matchingEntriesCount === 1 ? "entry" : "entries",
|
|
1641
|
+
" found in database"
|
|
1604
1642
|
] })
|
|
1605
1643
|
] }),
|
|
1606
|
-
|
|
1644
|
+
isFilterActive && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "S", onClick: clearFilter, children: "Clear Search & Filter" })
|
|
1607
1645
|
] }),
|
|
1608
1646
|
/* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "flex-end", wrap: "wrap", children: [
|
|
1609
|
-
/* @__PURE__ */ jsx(Box, { style: { width:
|
|
1647
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 220, minWidth: 180 }, children: /* @__PURE__ */ jsxs(
|
|
1610
1648
|
SingleSelect,
|
|
1611
1649
|
{
|
|
1612
1650
|
label: `Filter condition for "${selectedAttribute}"`,
|
|
1613
1651
|
value: filterOperator,
|
|
1614
1652
|
onChange: (val) => setFilterOperator(String(val)),
|
|
1615
1653
|
children: [
|
|
1616
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "none", children: "Show All (No Filter)" }),
|
|
1654
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "none", children: "Show All (No Attribute Filter)" }),
|
|
1617
1655
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "empty", children: "Is Empty or Null" }),
|
|
1618
1656
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "not_empty", children: "Is Not Empty" }),
|
|
1619
1657
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "equals", children: "Equals Exact Text" }),
|
|
@@ -1622,28 +1660,33 @@ const BulkUpdater = () => {
|
|
|
1622
1660
|
]
|
|
1623
1661
|
}
|
|
1624
1662
|
) }),
|
|
1625
|
-
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth:
|
|
1663
|
+
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsx(
|
|
1626
1664
|
TextInput,
|
|
1627
1665
|
{
|
|
1628
|
-
label:
|
|
1666
|
+
label: `Value for "${selectedAttribute}"`,
|
|
1629
1667
|
placeholder: "Type value to match...",
|
|
1630
1668
|
value: filterQuery,
|
|
1631
1669
|
onChange: (e) => setFilterQuery(e.target.value)
|
|
1632
1670
|
}
|
|
1633
1671
|
) }),
|
|
1634
|
-
|
|
1635
|
-
|
|
1672
|
+
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsx(
|
|
1673
|
+
TextInput,
|
|
1674
|
+
{
|
|
1675
|
+
label: "Full-text Entry Search",
|
|
1676
|
+
placeholder: "Search title, name, or text across records...",
|
|
1677
|
+
value: entrySearch,
|
|
1678
|
+
onChange: (e) => setEntrySearch(e.target.value)
|
|
1679
|
+
}
|
|
1680
|
+
) }),
|
|
1681
|
+
isFilterActive && /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
1682
|
+
/* @__PURE__ */ jsx(
|
|
1636
1683
|
Button,
|
|
1637
1684
|
{
|
|
1638
1685
|
variant: "default",
|
|
1639
1686
|
size: "S",
|
|
1640
1687
|
onClick: selectAllMatching,
|
|
1641
1688
|
disabled: matchingEntriesCount === 0,
|
|
1642
|
-
children:
|
|
1643
|
-
"Select Matching (",
|
|
1644
|
-
matchingEntriesCount,
|
|
1645
|
-
")"
|
|
1646
|
-
]
|
|
1689
|
+
children: "Select All Loaded"
|
|
1647
1690
|
}
|
|
1648
1691
|
),
|
|
1649
1692
|
/* @__PURE__ */ jsx(
|
|
@@ -1653,19 +1696,12 @@ const BulkUpdater = () => {
|
|
|
1653
1696
|
size: "S",
|
|
1654
1697
|
onClick: deselectAllMatching,
|
|
1655
1698
|
disabled: matchingEntriesCount === 0,
|
|
1656
|
-
children: "Deselect
|
|
1699
|
+
children: "Deselect All Loaded"
|
|
1657
1700
|
}
|
|
1658
1701
|
)
|
|
1659
1702
|
] })
|
|
1660
1703
|
] }),
|
|
1661
|
-
|
|
1662
|
-
Checkbox,
|
|
1663
|
-
{
|
|
1664
|
-
checked: hideNonMatching,
|
|
1665
|
-
onCheckedChange: (checked) => setHideNonMatching(Boolean(checked)),
|
|
1666
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral700", children: "Only display matching entries in tables (hide non-matching)" })
|
|
1667
|
-
}
|
|
1668
|
-
) })
|
|
1704
|
+
isFilterActive && /* @__PURE__ */ jsx(Flex, { gap: 2, alignItems: "center", marginTop: 1, children: /* @__PURE__ */ jsx(Badge, { backgroundColor: "success100", textColor: "success700", size: "S", children: "✓ Filter active: Showing only matching entries. All returned matching records are pre-selected." }) })
|
|
1669
1705
|
] })
|
|
1670
1706
|
}
|
|
1671
1707
|
),
|
|
@@ -1759,8 +1795,8 @@ const BulkUpdater = () => {
|
|
|
1759
1795
|
}
|
|
1760
1796
|
) }),
|
|
1761
1797
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", style: { marginLeft: "auto" }, children: [
|
|
1762
|
-
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Default page size (max
|
|
1763
|
-
/* @__PURE__ */ jsx(Box, { style: { width:
|
|
1798
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Default page size (max 500):" }),
|
|
1799
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 130 }, children: /* @__PURE__ */ jsxs(
|
|
1764
1800
|
SingleSelect,
|
|
1765
1801
|
{
|
|
1766
1802
|
size: "S",
|
|
@@ -1771,7 +1807,9 @@ const BulkUpdater = () => {
|
|
|
1771
1807
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "10", children: "10 / page" }),
|
|
1772
1808
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "25", children: "25 / page" }),
|
|
1773
1809
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "50", children: "50 / page" }),
|
|
1774
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "100", children: "100 / page" })
|
|
1810
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "100", children: "100 / page" }),
|
|
1811
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "250", children: "250 / page" }),
|
|
1812
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "500", children: "500 / page" })
|
|
1775
1813
|
]
|
|
1776
1814
|
}
|
|
1777
1815
|
) })
|
|
@@ -1786,7 +1824,7 @@ const BulkUpdater = () => {
|
|
|
1786
1824
|
const pageSize = pageState ? pageState.pageSize : defaultPageSize;
|
|
1787
1825
|
const hasAttr = col.attributes.includes(selectedAttribute);
|
|
1788
1826
|
const visibleEntries = getVisibleEntries(col);
|
|
1789
|
-
|
|
1827
|
+
entries.filter((e) => entryMatchesFilter(e, selectedAttribute)).length;
|
|
1790
1828
|
const isFullySelected = isCollectionFullySelected(col);
|
|
1791
1829
|
const isPartiallySelected = isCollectionPartiallySelected(col);
|
|
1792
1830
|
const currentSort = collectionSorts[col.uid] || { field: "createdAt", order: "desc" };
|
|
@@ -1895,6 +1933,9 @@ const BulkUpdater = () => {
|
|
|
1895
1933
|
params.set("filterOperator", filterOperator);
|
|
1896
1934
|
if (filterQuery) params.set("filterQuery", filterQuery);
|
|
1897
1935
|
}
|
|
1936
|
+
if (entrySearch && entrySearch.trim()) {
|
|
1937
|
+
params.set("search", entrySearch.trim());
|
|
1938
|
+
}
|
|
1898
1939
|
const res = await get(`/bulk-updater/csv/export/${col.uid}?${params.toString()}`);
|
|
1899
1940
|
const csvStr = res.data?.csvContent || (typeof res.data === "string" ? res.data : "");
|
|
1900
1941
|
if (!csvStr) {
|
|
@@ -1927,7 +1968,7 @@ const BulkUpdater = () => {
|
|
|
1927
1968
|
children: "Export CSV"
|
|
1928
1969
|
}
|
|
1929
1970
|
),
|
|
1930
|
-
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: col.isSingleType ? "1 single entry" :
|
|
1971
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: col.isSingleType ? "1 single entry" : isFilterActive ? `${totalEntries} matching entries in DB` : `${totalEntries} entries` })
|
|
1931
1972
|
] })
|
|
1932
1973
|
] }),
|
|
1933
1974
|
openColumnPickerUid === col.uid && /* @__PURE__ */ jsx(
|
|
@@ -1997,7 +2038,7 @@ const BulkUpdater = () => {
|
|
|
1997
2038
|
/* @__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) => {
|
|
1998
2039
|
const key = `${col.uid}${KEY_SEP}${entry.documentId}`;
|
|
1999
2040
|
const isSelected = Boolean(selectedEntries[key]);
|
|
2000
|
-
const isMatch =
|
|
2041
|
+
const isMatch = isFilterActive;
|
|
2001
2042
|
return /* @__PURE__ */ jsx(
|
|
2002
2043
|
Tr,
|
|
2003
2044
|
{
|
|
@@ -2029,11 +2070,12 @@ const BulkUpdater = () => {
|
|
|
2029
2070
|
Math.min(page * pageSize, totalEntries),
|
|
2030
2071
|
" of ",
|
|
2031
2072
|
totalEntries,
|
|
2032
|
-
"
|
|
2073
|
+
" ",
|
|
2074
|
+
isFilterActive ? "matching entries" : "entries"
|
|
2033
2075
|
] }),
|
|
2034
2076
|
/* @__PURE__ */ jsxs(Flex, { gap: 1, alignItems: "center", children: [
|
|
2035
2077
|
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "Show:" }),
|
|
2036
|
-
/* @__PURE__ */ jsx(Box, { style: { width:
|
|
2078
|
+
/* @__PURE__ */ jsx(Box, { style: { width: 85 }, children: /* @__PURE__ */ jsxs(
|
|
2037
2079
|
SingleSelect,
|
|
2038
2080
|
{
|
|
2039
2081
|
size: "S",
|
|
@@ -2044,12 +2086,27 @@ const BulkUpdater = () => {
|
|
|
2044
2086
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "10", children: "10" }),
|
|
2045
2087
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "25", children: "25" }),
|
|
2046
2088
|
/* @__PURE__ */ jsx(SingleSelectOption, { value: "50", children: "50" }),
|
|
2047
|
-
/* @__PURE__ */ jsx(SingleSelectOption, { value: "100", children: "100" })
|
|
2089
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "100", children: "100" }),
|
|
2090
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "250", children: "250" }),
|
|
2091
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "500", children: "500" })
|
|
2048
2092
|
]
|
|
2049
2093
|
}
|
|
2050
2094
|
) }),
|
|
2051
2095
|
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: "per page" })
|
|
2052
|
-
] })
|
|
2096
|
+
] }),
|
|
2097
|
+
totalEntries > visibleEntries.length && /* @__PURE__ */ jsxs(
|
|
2098
|
+
Button,
|
|
2099
|
+
{
|
|
2100
|
+
variant: "tertiary",
|
|
2101
|
+
size: "S",
|
|
2102
|
+
onClick: () => handleCollectionPageSizeChange(col.uid, Math.min(totalEntries, 500)),
|
|
2103
|
+
children: [
|
|
2104
|
+
"Load all ",
|
|
2105
|
+
totalEntries,
|
|
2106
|
+
" entries"
|
|
2107
|
+
]
|
|
2108
|
+
}
|
|
2109
|
+
)
|
|
2053
2110
|
] }),
|
|
2054
2111
|
pageCount > 1 && /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
2055
2112
|
/* @__PURE__ */ jsx(
|
|
@@ -2707,6 +2764,7 @@ const BulkUpdater = () => {
|
|
|
2707
2764
|
export {
|
|
2708
2765
|
BulkUpdater as default,
|
|
2709
2766
|
formatDisplayValue,
|
|
2710
|
-
getAvailableColumnsForCollection
|
|
2767
|
+
getAvailableColumnsForCollection,
|
|
2768
|
+
getNestedValue
|
|
2711
2769
|
};
|
|
2712
|
-
//# sourceMappingURL=BulkUpdater-
|
|
2770
|
+
//# sourceMappingURL=BulkUpdater-BDszahRM.mjs.map
|