strapi-plugin-bulk-updater 1.1.0 → 1.2.3
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 +15 -6
- package/dist/_chunks/{BulkUpdater-BSZP0U18.mjs → BulkUpdater-BYtO2SHc.mjs} +199 -127
- package/dist/_chunks/BulkUpdater-BYtO2SHc.mjs.map +1 -0
- package/dist/_chunks/{BulkUpdater-BRcMQGP3.js → BulkUpdater-BdRJhVFh.js} +196 -124
- package/dist/_chunks/BulkUpdater-BdRJhVFh.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +524 -88
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +524 -88
- 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
|
@@ -422,6 +422,11 @@ function CsvManagerTab() {
|
|
|
422
422
|
] })
|
|
423
423
|
] }) });
|
|
424
424
|
}
|
|
425
|
+
function getNestedValue(obj, path) {
|
|
426
|
+
if (!obj || !path) return void 0;
|
|
427
|
+
if (!path.includes(".")) return obj[path];
|
|
428
|
+
return path.split(".").reduce((acc, part) => acc && typeof acc === "object" ? acc[part] : void 0, obj);
|
|
429
|
+
}
|
|
425
430
|
function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
426
431
|
const cols = [
|
|
427
432
|
{
|
|
@@ -442,7 +447,7 @@ function getAvailableColumnsForCollection(col, selectedAttribute) {
|
|
|
442
447
|
if (attr === "name" || attr === "title" || attr === selectedAttribute) {
|
|
443
448
|
return;
|
|
444
449
|
}
|
|
445
|
-
const formattedLabel = attr.charAt(0).toUpperCase() + attr.slice(1);
|
|
450
|
+
const formattedLabel = attr.includes(".") ? attr.split(".").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" > ") : attr.charAt(0).toUpperCase() + attr.slice(1);
|
|
446
451
|
cols.push({
|
|
447
452
|
key: `attr_${attr}`,
|
|
448
453
|
label: formattedLabel,
|
|
@@ -528,7 +533,7 @@ function renderCellContent(colDef, entry, col, selectedAttribute, isMatch, hasAt
|
|
|
528
533
|
] });
|
|
529
534
|
}
|
|
530
535
|
case "target_attr": {
|
|
531
|
-
const val = entry
|
|
536
|
+
const val = getNestedValue(entry, selectedAttribute);
|
|
532
537
|
const displayStr = formatDisplayValue(val);
|
|
533
538
|
const isUnset = displayStr === "(empty / not set)" || displayStr === "(empty / unlinked)";
|
|
534
539
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -558,7 +563,7 @@ function renderCellContent(colDef, entry, col, selectedAttribute, isMatch, hasAt
|
|
|
558
563
|
}
|
|
559
564
|
default: {
|
|
560
565
|
const attrName = colDef.key.replace("attr_", "");
|
|
561
|
-
const rawVal = entry
|
|
566
|
+
const rawVal = getNestedValue(entry, attrName);
|
|
562
567
|
const displayStr = formatDisplayValue(rawVal);
|
|
563
568
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
564
569
|
designSystem.Typography,
|
|
@@ -632,7 +637,8 @@ const BulkUpdater = () => {
|
|
|
632
637
|
const [regexPattern, setRegexPattern] = React.useState("");
|
|
633
638
|
const [filterOperator, setFilterOperator] = React.useState("none");
|
|
634
639
|
const [filterQuery, setFilterQuery] = React.useState("");
|
|
635
|
-
const [
|
|
640
|
+
const [entrySearch, setEntrySearch] = React.useState("");
|
|
641
|
+
const isFilterActive = filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
636
642
|
const [lastResults, setLastResults] = React.useState(null);
|
|
637
643
|
const [updateSummary, setUpdateSummary] = React.useState(null);
|
|
638
644
|
const [collectionPages, setCollectionPages] = React.useState({});
|
|
@@ -728,12 +734,15 @@ const BulkUpdater = () => {
|
|
|
728
734
|
setLoading(false);
|
|
729
735
|
}
|
|
730
736
|
};
|
|
731
|
-
const loadCollectionPage = async (colUid, targetPage, customPageSize, customSortField, customSortOrder) => {
|
|
737
|
+
const loadCollectionPage = async (colUid, targetPage, customPageSize, customSortField, customSortOrder, overrideFilterOp, overrideFilterQuery, overrideEntrySearch, autoSelectReturned = true) => {
|
|
732
738
|
const currentPageState = collectionPages[colUid];
|
|
733
739
|
const size = customPageSize || currentPageState?.pageSize || defaultPageSize;
|
|
734
740
|
const currentSort = collectionSorts[colUid] || { field: "createdAt", order: "desc" };
|
|
735
741
|
const sortField = customSortField !== void 0 ? customSortField : currentSort.field;
|
|
736
742
|
const sortOrder = customSortOrder !== void 0 ? customSortOrder : currentSort.order;
|
|
743
|
+
const op = overrideFilterOp !== void 0 ? overrideFilterOp : filterOperator;
|
|
744
|
+
const q = overrideFilterQuery !== void 0 ? overrideFilterQuery : filterQuery;
|
|
745
|
+
const s = overrideEntrySearch !== void 0 ? overrideEntrySearch : entrySearch;
|
|
737
746
|
setCollectionPages((prev) => ({
|
|
738
747
|
...prev,
|
|
739
748
|
[colUid]: {
|
|
@@ -747,16 +756,20 @@ const BulkUpdater = () => {
|
|
|
747
756
|
pageSize: String(size)
|
|
748
757
|
});
|
|
749
758
|
if (selectedAttribute) params.set("attribute", selectedAttribute);
|
|
750
|
-
if (
|
|
751
|
-
params.set("filterOperator",
|
|
752
|
-
if (
|
|
759
|
+
if (op && op !== "none") {
|
|
760
|
+
params.set("filterOperator", op);
|
|
761
|
+
if (q) params.set("filterQuery", q);
|
|
762
|
+
}
|
|
763
|
+
if (s && s.trim()) {
|
|
764
|
+
params.set("search", s.trim());
|
|
753
765
|
}
|
|
754
766
|
if (sortField) {
|
|
755
767
|
params.set("sortField", sortField);
|
|
756
768
|
params.set("sortOrder", sortOrder);
|
|
757
769
|
}
|
|
758
770
|
const res = await get(`/bulk-updater/collections/${colUid}/entries?${params.toString()}`);
|
|
759
|
-
if (res.data && res.data.success) {
|
|
771
|
+
if (res.data && (res.data.success || res.data.entries !== void 0)) {
|
|
772
|
+
const fetchedEntries = res.data.entries || [];
|
|
760
773
|
setCollectionPages((prev) => ({
|
|
761
774
|
...prev,
|
|
762
775
|
[colUid]: {
|
|
@@ -764,10 +777,20 @@ const BulkUpdater = () => {
|
|
|
764
777
|
pageSize: res.data.pagination.pageSize,
|
|
765
778
|
total: res.data.pagination.total,
|
|
766
779
|
pageCount: res.data.pagination.pageCount,
|
|
767
|
-
entries:
|
|
780
|
+
entries: fetchedEntries,
|
|
768
781
|
loading: false
|
|
769
782
|
}
|
|
770
783
|
}));
|
|
784
|
+
const isFilterActiveNow = op !== "none" && (["empty", "not_empty"].includes(op) || Boolean(q.trim())) || Boolean(s.trim());
|
|
785
|
+
if (isFilterActiveNow && autoSelectReturned) {
|
|
786
|
+
setSelectedEntries((prev) => {
|
|
787
|
+
const next = { ...prev };
|
|
788
|
+
fetchedEntries.forEach((e) => {
|
|
789
|
+
next[`${colUid}${KEY_SEP}${e.documentId}`] = true;
|
|
790
|
+
});
|
|
791
|
+
return next;
|
|
792
|
+
});
|
|
793
|
+
}
|
|
771
794
|
}
|
|
772
795
|
} catch (err) {
|
|
773
796
|
toggleNotification({
|
|
@@ -831,6 +854,35 @@ const BulkUpdater = () => {
|
|
|
831
854
|
fetchPendingBatches();
|
|
832
855
|
}
|
|
833
856
|
}, [activeTab]);
|
|
857
|
+
const isInitialFilterMount = React.useRef(true);
|
|
858
|
+
React.useEffect(() => {
|
|
859
|
+
if (isInitialFilterMount.current) {
|
|
860
|
+
isInitialFilterMount.current = false;
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
const timer = setTimeout(() => {
|
|
864
|
+
if (collections.length > 0) {
|
|
865
|
+
const isFilterActiveNow = filterOperator !== "none" && (["empty", "not_empty"].includes(filterOperator) || Boolean(filterQuery.trim())) || Boolean(entrySearch.trim());
|
|
866
|
+
if (isFilterActiveNow) {
|
|
867
|
+
setSelectedEntries({});
|
|
868
|
+
}
|
|
869
|
+
collections.forEach((col) => {
|
|
870
|
+
loadCollectionPage(
|
|
871
|
+
col.uid,
|
|
872
|
+
1,
|
|
873
|
+
void 0,
|
|
874
|
+
void 0,
|
|
875
|
+
void 0,
|
|
876
|
+
filterOperator,
|
|
877
|
+
filterQuery,
|
|
878
|
+
entrySearch,
|
|
879
|
+
true
|
|
880
|
+
);
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
}, 350);
|
|
884
|
+
return () => clearTimeout(timer);
|
|
885
|
+
}, [filterOperator, filterQuery, entrySearch]);
|
|
834
886
|
const KEY_SEP = "@@@";
|
|
835
887
|
const handleAttributeChange = (newAttr) => {
|
|
836
888
|
if (newAttr !== selectedAttribute) {
|
|
@@ -838,7 +890,7 @@ const BulkUpdater = () => {
|
|
|
838
890
|
setSelectedEntries({});
|
|
839
891
|
setFilterOperator("none");
|
|
840
892
|
setFilterQuery("");
|
|
841
|
-
|
|
893
|
+
setEntrySearch("");
|
|
842
894
|
setSelectedRelationDocId("");
|
|
843
895
|
setAttributeValue("");
|
|
844
896
|
if (relationsMeta[newAttr]) {
|
|
@@ -855,7 +907,7 @@ const BulkUpdater = () => {
|
|
|
855
907
|
(c) => visibleTypeUids[c.uid] !== false && (!collectionSearch.trim() || c.displayName.toLowerCase().includes(collectionSearch.toLowerCase().trim()) || c.uid.toLowerCase().includes(collectionSearch.toLowerCase().trim()))
|
|
856
908
|
);
|
|
857
909
|
const handleGlobalPageSizeChange = (newSize) => {
|
|
858
|
-
const capped = Math.min(
|
|
910
|
+
const capped = Math.min(500, Math.max(1, newSize));
|
|
859
911
|
setDefaultPageSize(capped);
|
|
860
912
|
collections.forEach((col) => {
|
|
861
913
|
if (!col.isSingleType) {
|
|
@@ -864,7 +916,7 @@ const BulkUpdater = () => {
|
|
|
864
916
|
});
|
|
865
917
|
};
|
|
866
918
|
const handleCollectionPageSizeChange = (colUid, newSize) => {
|
|
867
|
-
const capped = Math.min(
|
|
919
|
+
const capped = Math.min(500, Math.max(1, newSize));
|
|
868
920
|
loadCollectionPage(colUid, 1, capped);
|
|
869
921
|
};
|
|
870
922
|
const handleCollectionSortChange = (colUid, field, order) => {
|
|
@@ -888,7 +940,7 @@ const BulkUpdater = () => {
|
|
|
888
940
|
};
|
|
889
941
|
const entryMatchesFilter = (entry, attr) => {
|
|
890
942
|
if (filterOperator === "none") return true;
|
|
891
|
-
const val = entry
|
|
943
|
+
const val = getNestedValue(entry, attr);
|
|
892
944
|
const displayStr = formatDisplayValue(val);
|
|
893
945
|
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)";
|
|
894
946
|
switch (filterOperator) {
|
|
@@ -908,64 +960,48 @@ const BulkUpdater = () => {
|
|
|
908
960
|
};
|
|
909
961
|
const getVisibleEntries = (col) => {
|
|
910
962
|
const pageState = collectionPages[col.uid];
|
|
911
|
-
|
|
912
|
-
if (!hideNonMatching || filterOperator === "none") {
|
|
913
|
-
return entries;
|
|
914
|
-
}
|
|
915
|
-
return entries.filter((e) => entryMatchesFilter(e, selectedAttribute));
|
|
963
|
+
return pageState ? pageState.entries : col.entries || [];
|
|
916
964
|
};
|
|
917
965
|
const matchingEntriesCount = React__default.default.useMemo(() => {
|
|
918
|
-
if (
|
|
966
|
+
if (!isFilterActive) return 0;
|
|
919
967
|
let count = 0;
|
|
920
968
|
filteredCollections.forEach((col) => {
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
entries.forEach((entry) => {
|
|
925
|
-
if (entryMatchesFilter(entry, selectedAttribute)) {
|
|
926
|
-
count++;
|
|
927
|
-
}
|
|
928
|
-
});
|
|
969
|
+
const pageState = collectionPages[col.uid];
|
|
970
|
+
if (pageState) {
|
|
971
|
+
count += pageState.total;
|
|
929
972
|
}
|
|
930
973
|
});
|
|
931
974
|
return count;
|
|
932
|
-
}, [filteredCollections, collectionPages,
|
|
975
|
+
}, [filteredCollections, collectionPages, isFilterActive]);
|
|
933
976
|
const selectAllMatching = () => {
|
|
934
977
|
const updated = { ...selectedEntries };
|
|
935
978
|
filteredCollections.forEach((col) => {
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
updated[`${col.uid}${KEY_SEP}${e.documentId}`] = true;
|
|
942
|
-
}
|
|
943
|
-
});
|
|
944
|
-
}
|
|
979
|
+
const pageState = collectionPages[col.uid];
|
|
980
|
+
const entries = pageState ? pageState.entries : col.entries || [];
|
|
981
|
+
entries.forEach((e) => {
|
|
982
|
+
updated[`${col.uid}${KEY_SEP}${e.documentId}`] = true;
|
|
983
|
+
});
|
|
945
984
|
});
|
|
946
985
|
setSelectedEntries(updated);
|
|
947
986
|
};
|
|
948
987
|
const deselectAllMatching = () => {
|
|
949
988
|
const updated = { ...selectedEntries };
|
|
950
989
|
filteredCollections.forEach((col) => {
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
delete updated[`${col.uid}${KEY_SEP}${e.documentId}`];
|
|
957
|
-
}
|
|
958
|
-
});
|
|
959
|
-
}
|
|
990
|
+
const pageState = collectionPages[col.uid];
|
|
991
|
+
const entries = pageState ? pageState.entries : col.entries || [];
|
|
992
|
+
entries.forEach((e) => {
|
|
993
|
+
delete updated[`${col.uid}${KEY_SEP}${e.documentId}`];
|
|
994
|
+
});
|
|
960
995
|
});
|
|
961
996
|
setSelectedEntries(updated);
|
|
962
997
|
};
|
|
963
998
|
const clearFilter = () => {
|
|
964
999
|
setFilterOperator("none");
|
|
965
1000
|
setFilterQuery("");
|
|
966
|
-
|
|
1001
|
+
setEntrySearch("");
|
|
1002
|
+
setSelectedEntries({});
|
|
967
1003
|
collections.forEach((col) => {
|
|
968
|
-
loadCollectionPage(col.uid, 1);
|
|
1004
|
+
loadCollectionPage(col.uid, 1, void 0, void 0, void 0, "none", "", "", false);
|
|
969
1005
|
});
|
|
970
1006
|
};
|
|
971
1007
|
const isCollectionFullySelected = (col) => {
|
|
@@ -1087,6 +1123,7 @@ const BulkUpdater = () => {
|
|
|
1087
1123
|
message: `Bulk update complete! Batch ID: ${res.data.batchId}. Updated: ${res.data.updatedCount}, Skipped: ${res.data.skippedCount}`
|
|
1088
1124
|
});
|
|
1089
1125
|
await fetchModels();
|
|
1126
|
+
await fetchAuditHistory();
|
|
1090
1127
|
}
|
|
1091
1128
|
} else {
|
|
1092
1129
|
toggleNotification({
|
|
@@ -1373,7 +1410,7 @@ const BulkUpdater = () => {
|
|
|
1373
1410
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral700", children: [
|
|
1374
1411
|
/* @__PURE__ */ jsxRuntime.jsx("code", { children: latestActiveBatch.batchId }),
|
|
1375
1412
|
" (",
|
|
1376
|
-
latestActiveBatch.
|
|
1413
|
+
latestActiveBatch.updatedCount,
|
|
1377
1414
|
" entries updated by ",
|
|
1378
1415
|
latestActiveBatch.userEmail,
|
|
1379
1416
|
")"
|
|
@@ -1417,23 +1454,34 @@ const BulkUpdater = () => {
|
|
|
1417
1454
|
children: [
|
|
1418
1455
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h2", marginBottom: 4, fontWeight: "semiBold", children: "1. Configure Attribute Update" }),
|
|
1419
1456
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, alignItems: "flex-end", wrap: "wrap", children: [
|
|
1420
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { minWidth:
|
|
1421
|
-
designSystem.
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1457
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { minWidth: 280, flex: 1, maxWidth: 440 }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { children: [
|
|
1458
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Attribute to Update" }),
|
|
1459
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1460
|
+
designSystem.Combobox,
|
|
1461
|
+
{
|
|
1462
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
1463
|
+
placeholder: "Search attribute by name or relation...",
|
|
1464
|
+
value: selectedAttribute,
|
|
1465
|
+
onChange: (val) => {
|
|
1466
|
+
if (val && typeof val === "string") {
|
|
1467
|
+
handleAttributeChange(val);
|
|
1468
|
+
}
|
|
1469
|
+
},
|
|
1470
|
+
children: attributes.map((attr) => {
|
|
1471
|
+
const rel = relationsMeta[attr];
|
|
1472
|
+
const cleanParts = attr.includes(".") ? attr.split(".").join(" ") : "";
|
|
1473
|
+
const labelText = `${attr} ${cleanParts} ${rel ? `relation ${rel.targetDisplayName}` : ""}`.trim();
|
|
1474
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: attr, textValue: labelText, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
|
|
1475
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: attr === selectedAttribute ? "bold" : "regular", children: attr }),
|
|
1476
|
+
rel ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "secondary100", textColor: "secondary700", size: "S", children: [
|
|
1477
|
+
"relation ➔ ",
|
|
1478
|
+
rel.targetDisplayName
|
|
1479
|
+
] }) : attr.includes(".") ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "neutral150", textColor: "neutral700", size: "S", children: "component" }) : null
|
|
1480
|
+
] }) }, attr);
|
|
1481
|
+
})
|
|
1482
|
+
}
|
|
1483
|
+
)
|
|
1484
|
+
] }) }),
|
|
1437
1485
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: 340 }, children: relationsMeta[selectedAttribute] ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 1, style: { width: "100%" }, children: [
|
|
1438
1486
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
1439
1487
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral700", children: [
|
|
@@ -1449,28 +1497,31 @@ const BulkUpdater = () => {
|
|
|
1449
1497
|
relationsMeta[selectedAttribute].isMulti && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: "Multi-Relation" })
|
|
1450
1498
|
] }),
|
|
1451
1499
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", style: { width: "100%" }, children: [
|
|
1452
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1453
|
-
designSystem.
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1500
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { children: [
|
|
1501
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: `Choose ${relationsMeta[selectedAttribute].targetDisplayName}` }),
|
|
1502
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1503
|
+
designSystem.Combobox,
|
|
1504
|
+
{
|
|
1505
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
1506
|
+
placeholder: relationOptionsLoading ? "Loading entities..." : `Search & pick ${relationsMeta[selectedAttribute].targetDisplayName}...`,
|
|
1507
|
+
value: selectedRelationDocId,
|
|
1508
|
+
onChange: (val) => {
|
|
1509
|
+
const docId = val ? String(val) : "";
|
|
1510
|
+
setSelectedRelationDocId(docId);
|
|
1511
|
+
if (docId === "__clear__") {
|
|
1512
|
+
setAttributeValue(JSON.stringify({ mode: "clear", label: "(clear relation)" }));
|
|
1513
|
+
} else {
|
|
1514
|
+
const opt = relationOptions.find((o) => o.documentId === docId);
|
|
1515
|
+
setAttributeValue(JSON.stringify({ mode: relationMode, documentIds: [docId], label: opt?.label || docId }));
|
|
1516
|
+
}
|
|
1517
|
+
},
|
|
1518
|
+
children: [
|
|
1519
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: "__clear__", textValue: "Clear / Unlink Relation", children: "-- Clear / Unlink Relation --" }),
|
|
1520
|
+
relationOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: opt.documentId, textValue: opt.label, children: opt.label }, opt.documentId))
|
|
1521
|
+
]
|
|
1522
|
+
}
|
|
1523
|
+
)
|
|
1524
|
+
] }) }),
|
|
1474
1525
|
relationsMeta[selectedAttribute].isMulti && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 170 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1475
1526
|
designSystem.SingleSelect,
|
|
1476
1527
|
{
|
|
@@ -1600,24 +1651,25 @@ const BulkUpdater = () => {
|
|
|
1600
1651
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, children: [
|
|
1601
1652
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", wrap: "wrap", gap: 2, children: [
|
|
1602
1653
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
1603
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: "
|
|
1604
|
-
|
|
1654
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: "Search & Filter Targets:" }),
|
|
1655
|
+
isFilterActive && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: "primary100", textColor: "primary700", children: [
|
|
1605
1656
|
matchingEntriesCount,
|
|
1606
1657
|
" matching ",
|
|
1607
|
-
matchingEntriesCount === 1 ? "entry" : "entries"
|
|
1658
|
+
matchingEntriesCount === 1 ? "entry" : "entries",
|
|
1659
|
+
" found in database"
|
|
1608
1660
|
] })
|
|
1609
1661
|
] }),
|
|
1610
|
-
|
|
1662
|
+
isFilterActive && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "ghost", size: "S", onClick: clearFilter, children: "Clear Search & Filter" })
|
|
1611
1663
|
] }),
|
|
1612
1664
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "flex-end", wrap: "wrap", children: [
|
|
1613
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width:
|
|
1665
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 220, minWidth: 180 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1614
1666
|
designSystem.SingleSelect,
|
|
1615
1667
|
{
|
|
1616
1668
|
label: `Filter condition for "${selectedAttribute}"`,
|
|
1617
1669
|
value: filterOperator,
|
|
1618
1670
|
onChange: (val) => setFilterOperator(String(val)),
|
|
1619
1671
|
children: [
|
|
1620
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "none", children: "Show All (No Filter)" }),
|
|
1672
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "none", children: "Show All (No Attribute Filter)" }),
|
|
1621
1673
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "empty", children: "Is Empty or Null" }),
|
|
1622
1674
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "not_empty", children: "Is Not Empty" }),
|
|
1623
1675
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "equals", children: "Equals Exact Text" }),
|
|
@@ -1626,28 +1678,33 @@ const BulkUpdater = () => {
|
|
|
1626
1678
|
]
|
|
1627
1679
|
}
|
|
1628
1680
|
) }),
|
|
1629
|
-
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth:
|
|
1681
|
+
(filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1630
1682
|
designSystem.TextInput,
|
|
1631
1683
|
{
|
|
1632
|
-
label:
|
|
1684
|
+
label: `Value for "${selectedAttribute}"`,
|
|
1633
1685
|
placeholder: "Type value to match...",
|
|
1634
1686
|
value: filterQuery,
|
|
1635
1687
|
onChange: (e) => setFilterQuery(e.target.value)
|
|
1636
1688
|
}
|
|
1637
1689
|
) }),
|
|
1638
|
-
|
|
1639
|
-
|
|
1690
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1691
|
+
designSystem.TextInput,
|
|
1692
|
+
{
|
|
1693
|
+
label: "Full-text Entry Search",
|
|
1694
|
+
placeholder: "Search title, name, or text across records...",
|
|
1695
|
+
value: entrySearch,
|
|
1696
|
+
onChange: (e) => setEntrySearch(e.target.value)
|
|
1697
|
+
}
|
|
1698
|
+
) }),
|
|
1699
|
+
isFilterActive && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
1700
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1640
1701
|
designSystem.Button,
|
|
1641
1702
|
{
|
|
1642
1703
|
variant: "default",
|
|
1643
1704
|
size: "S",
|
|
1644
1705
|
onClick: selectAllMatching,
|
|
1645
1706
|
disabled: matchingEntriesCount === 0,
|
|
1646
|
-
children:
|
|
1647
|
-
"Select Matching (",
|
|
1648
|
-
matchingEntriesCount,
|
|
1649
|
-
")"
|
|
1650
|
-
]
|
|
1707
|
+
children: "Select All Loaded"
|
|
1651
1708
|
}
|
|
1652
1709
|
),
|
|
1653
1710
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1657,19 +1714,12 @@ const BulkUpdater = () => {
|
|
|
1657
1714
|
size: "S",
|
|
1658
1715
|
onClick: deselectAllMatching,
|
|
1659
1716
|
disabled: matchingEntriesCount === 0,
|
|
1660
|
-
children: "Deselect
|
|
1717
|
+
children: "Deselect All Loaded"
|
|
1661
1718
|
}
|
|
1662
1719
|
)
|
|
1663
1720
|
] })
|
|
1664
1721
|
] }),
|
|
1665
|
-
|
|
1666
|
-
designSystem.Checkbox,
|
|
1667
|
-
{
|
|
1668
|
-
checked: hideNonMatching,
|
|
1669
|
-
onCheckedChange: (checked) => setHideNonMatching(Boolean(checked)),
|
|
1670
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral700", children: "Only display matching entries in tables (hide non-matching)" })
|
|
1671
|
-
}
|
|
1672
|
-
) })
|
|
1722
|
+
isFilterActive && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, alignItems: "center", marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { backgroundColor: "success100", textColor: "success700", size: "S", children: "✓ Filter active: Showing only matching entries. All returned matching records are pre-selected." }) })
|
|
1673
1723
|
] })
|
|
1674
1724
|
}
|
|
1675
1725
|
),
|
|
@@ -1763,8 +1813,8 @@ const BulkUpdater = () => {
|
|
|
1763
1813
|
}
|
|
1764
1814
|
) }),
|
|
1765
1815
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", style: { marginLeft: "auto" }, children: [
|
|
1766
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Default page size (max
|
|
1767
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width:
|
|
1816
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Default page size (max 500):" }),
|
|
1817
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 130 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1768
1818
|
designSystem.SingleSelect,
|
|
1769
1819
|
{
|
|
1770
1820
|
size: "S",
|
|
@@ -1775,7 +1825,9 @@ const BulkUpdater = () => {
|
|
|
1775
1825
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "10", children: "10 / page" }),
|
|
1776
1826
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "25", children: "25 / page" }),
|
|
1777
1827
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "50", children: "50 / page" }),
|
|
1778
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "100", children: "100 / page" })
|
|
1828
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "100", children: "100 / page" }),
|
|
1829
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "250", children: "250 / page" }),
|
|
1830
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "500", children: "500 / page" })
|
|
1779
1831
|
]
|
|
1780
1832
|
}
|
|
1781
1833
|
) })
|
|
@@ -1790,7 +1842,7 @@ const BulkUpdater = () => {
|
|
|
1790
1842
|
const pageSize = pageState ? pageState.pageSize : defaultPageSize;
|
|
1791
1843
|
const hasAttr = col.attributes.includes(selectedAttribute);
|
|
1792
1844
|
const visibleEntries = getVisibleEntries(col);
|
|
1793
|
-
|
|
1845
|
+
entries.filter((e) => entryMatchesFilter(e, selectedAttribute)).length;
|
|
1794
1846
|
const isFullySelected = isCollectionFullySelected(col);
|
|
1795
1847
|
const isPartiallySelected = isCollectionPartiallySelected(col);
|
|
1796
1848
|
const currentSort = collectionSorts[col.uid] || { field: "createdAt", order: "desc" };
|
|
@@ -1899,6 +1951,9 @@ const BulkUpdater = () => {
|
|
|
1899
1951
|
params.set("filterOperator", filterOperator);
|
|
1900
1952
|
if (filterQuery) params.set("filterQuery", filterQuery);
|
|
1901
1953
|
}
|
|
1954
|
+
if (entrySearch && entrySearch.trim()) {
|
|
1955
|
+
params.set("search", entrySearch.trim());
|
|
1956
|
+
}
|
|
1902
1957
|
const res = await get(`/bulk-updater/csv/export/${col.uid}?${params.toString()}`);
|
|
1903
1958
|
const csvStr = res.data?.csvContent || (typeof res.data === "string" ? res.data : "");
|
|
1904
1959
|
if (!csvStr) {
|
|
@@ -1931,7 +1986,7 @@ const BulkUpdater = () => {
|
|
|
1931
1986
|
children: "Export CSV"
|
|
1932
1987
|
}
|
|
1933
1988
|
),
|
|
1934
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: col.isSingleType ? "1 single entry" :
|
|
1989
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: col.isSingleType ? "1 single entry" : isFilterActive ? `${totalEntries} matching entries in DB` : `${totalEntries} entries` })
|
|
1935
1990
|
] })
|
|
1936
1991
|
] }),
|
|
1937
1992
|
openColumnPickerUid === col.uid && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2001,7 +2056,7 @@ const BulkUpdater = () => {
|
|
|
2001
2056
|
/* @__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) => {
|
|
2002
2057
|
const key = `${col.uid}${KEY_SEP}${entry.documentId}`;
|
|
2003
2058
|
const isSelected = Boolean(selectedEntries[key]);
|
|
2004
|
-
const isMatch =
|
|
2059
|
+
const isMatch = isFilterActive;
|
|
2005
2060
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2006
2061
|
designSystem.Tr,
|
|
2007
2062
|
{
|
|
@@ -2033,11 +2088,12 @@ const BulkUpdater = () => {
|
|
|
2033
2088
|
Math.min(page * pageSize, totalEntries),
|
|
2034
2089
|
" of ",
|
|
2035
2090
|
totalEntries,
|
|
2036
|
-
"
|
|
2091
|
+
" ",
|
|
2092
|
+
isFilterActive ? "matching entries" : "entries"
|
|
2037
2093
|
] }),
|
|
2038
2094
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, alignItems: "center", children: [
|
|
2039
2095
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: "Show:" }),
|
|
2040
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width:
|
|
2096
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 85 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2041
2097
|
designSystem.SingleSelect,
|
|
2042
2098
|
{
|
|
2043
2099
|
size: "S",
|
|
@@ -2048,12 +2104,27 @@ const BulkUpdater = () => {
|
|
|
2048
2104
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "10", children: "10" }),
|
|
2049
2105
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "25", children: "25" }),
|
|
2050
2106
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "50", children: "50" }),
|
|
2051
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "100", children: "100" })
|
|
2107
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "100", children: "100" }),
|
|
2108
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "250", children: "250" }),
|
|
2109
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "500", children: "500" })
|
|
2052
2110
|
]
|
|
2053
2111
|
}
|
|
2054
2112
|
) }),
|
|
2055
2113
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "per page" })
|
|
2056
|
-
] })
|
|
2114
|
+
] }),
|
|
2115
|
+
totalEntries > visibleEntries.length && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2116
|
+
designSystem.Button,
|
|
2117
|
+
{
|
|
2118
|
+
variant: "tertiary",
|
|
2119
|
+
size: "S",
|
|
2120
|
+
onClick: () => handleCollectionPageSizeChange(col.uid, Math.min(totalEntries, 500)),
|
|
2121
|
+
children: [
|
|
2122
|
+
"Load all ",
|
|
2123
|
+
totalEntries,
|
|
2124
|
+
" entries"
|
|
2125
|
+
]
|
|
2126
|
+
}
|
|
2127
|
+
)
|
|
2057
2128
|
] }),
|
|
2058
2129
|
pageCount > 1 && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
2059
2130
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2711,4 +2782,5 @@ const BulkUpdater = () => {
|
|
|
2711
2782
|
exports.default = BulkUpdater;
|
|
2712
2783
|
exports.formatDisplayValue = formatDisplayValue;
|
|
2713
2784
|
exports.getAvailableColumnsForCollection = getAvailableColumnsForCollection;
|
|
2714
|
-
|
|
2785
|
+
exports.getNestedValue = getNestedValue;
|
|
2786
|
+
//# sourceMappingURL=BulkUpdater-BdRJhVFh.js.map
|