strapi-plugin-bulk-updater 1.2.8 → 1.2.9

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.
@@ -1428,7 +1428,7 @@ const BulkUpdater = () => {
1428
1428
  storedAttr = localStorage.getItem(LAST_ATTR_KEY);
1429
1429
  } catch {
1430
1430
  }
1431
- const resolvedAttr = storedAttr && attrs.includes(storedAttr) ? storedAttr : attrs.includes(selectedAttribute) ? selectedAttribute : attrs[0] || "metaDescription";
1431
+ const resolvedAttr = storedAttr && attrs.includes(storedAttr) ? storedAttr : selectedAttribute && attrs.includes(selectedAttribute) ? selectedAttribute : "";
1432
1432
  setSelectedAttribute(resolvedAttr);
1433
1433
  if (resolvedAttr && data.relationsMeta && data.relationsMeta[resolvedAttr]) {
1434
1434
  fetchRelationOptions(data.relationsMeta[resolvedAttr].targetUid);
@@ -1626,7 +1626,11 @@ const BulkUpdater = () => {
1626
1626
  if (newAttr !== selectedAttribute) {
1627
1627
  setSelectedAttribute(newAttr);
1628
1628
  try {
1629
- localStorage.setItem(LAST_ATTR_KEY, newAttr);
1629
+ if (newAttr) {
1630
+ localStorage.setItem(LAST_ATTR_KEY, newAttr);
1631
+ } else {
1632
+ localStorage.removeItem(LAST_ATTR_KEY);
1633
+ }
1630
1634
  } catch {
1631
1635
  }
1632
1636
  setSelectedEntries({});
@@ -1635,17 +1639,19 @@ const BulkUpdater = () => {
1635
1639
  setEntrySearch("");
1636
1640
  setSelectedRelationDocId("");
1637
1641
  setAttributeValue("");
1638
- if (relationsMeta[newAttr]) {
1642
+ if (newAttr && relationsMeta[newAttr]) {
1639
1643
  fetchRelationOptions(relationsMeta[newAttr].targetUid);
1640
1644
  } else {
1641
1645
  setRelationOptions([]);
1642
1646
  }
1643
- const collectionsToLoad = collections.filter(
1644
- (col) => visibleTypeUids[col.uid] !== false && col.attributes.includes(newAttr) && (!collectionPages[col.uid]?.entries || collectionPages[col.uid].entries.length === 0)
1645
- );
1646
- collectionsToLoad.forEach((col) => {
1647
- loadCollectionPage(col.uid, 1);
1648
- });
1647
+ if (newAttr) {
1648
+ const collectionsToLoad = collections.filter(
1649
+ (col) => visibleTypeUids[col.uid] !== false && col.attributes.includes(newAttr) && (!collectionPages[col.uid]?.entries || collectionPages[col.uid].entries.length === 0)
1650
+ );
1651
+ collectionsToLoad.forEach((col) => {
1652
+ loadCollectionPage(col.uid, 1);
1653
+ });
1654
+ }
1649
1655
  }
1650
1656
  };
1651
1657
  const filteredCollections = collections.filter(
@@ -1682,8 +1688,30 @@ const BulkUpdater = () => {
1682
1688
  });
1683
1689
  setVisibleTypeUids(newVis);
1684
1690
  };
1691
+ const [attributeSearch, setAttributeSearch] = useState("");
1692
+ const filteredAttributes = useMemo(() => {
1693
+ if (!attributeSearch.trim()) {
1694
+ return attributes;
1695
+ }
1696
+ const q = attributeSearch.toLowerCase().trim();
1697
+ const cleanQ = q.replace(/[^a-z0-9]/g, "");
1698
+ return attributes.filter((attr) => {
1699
+ const lower = attr.toLowerCase();
1700
+ const cleanLower = lower.replace(/[^a-z0-9]/g, "");
1701
+ const rel = relationsMeta[attr];
1702
+ const relTarget = (rel?.targetDisplayName || "").toLowerCase();
1703
+ return lower.includes(q) || cleanLower.includes(cleanQ) || relTarget.includes(q);
1704
+ });
1705
+ }, [attributes, attributeSearch, relationsMeta]);
1685
1706
  const memoizedComboboxOptions = useMemo(() => {
1686
- return attributes.map((attr) => {
1707
+ if (filteredAttributes.length === 0) {
1708
+ return /* @__PURE__ */ jsx(ComboboxOption, { value: "__none__", disabled: true, textValue: "No matching attributes found", children: /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
1709
+ 'No matching attributes found for "',
1710
+ attributeSearch,
1711
+ '"'
1712
+ ] }) });
1713
+ }
1714
+ return filteredAttributes.map((attr) => {
1687
1715
  const rel = relationsMeta[attr];
1688
1716
  return /* @__PURE__ */ jsx(ComboboxOption, { value: attr, textValue: attr, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", width: "100%", gap: 2, children: [
1689
1717
  /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: attr === selectedAttribute ? "bold" : "regular", children: attr }),
@@ -1693,7 +1721,7 @@ const BulkUpdater = () => {
1693
1721
  ] }) : attr.includes(".") ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "neutral150", textColor: "neutral700", size: "S", children: "component" }) : null
1694
1722
  ] }) }, attr);
1695
1723
  });
1696
- }, [attributes, relationsMeta, selectedAttribute]);
1724
+ }, [filteredAttributes, relationsMeta, selectedAttribute, attributeSearch]);
1697
1725
  const handleGlobalPageSizeChange = (newSize) => {
1698
1726
  const capped = Math.min(500, Math.max(1, newSize));
1699
1727
  setDefaultPageSize(capped);
@@ -2349,15 +2377,28 @@ const BulkUpdater = () => {
2349
2377
  /* @__PURE__ */ jsx(
2350
2378
  Combobox,
2351
2379
  {
2352
- autocomplete: { type: "list", filter: "contains" },
2380
+ autocomplete: "none",
2353
2381
  placeholder: "Search attribute by name or relation...",
2354
- value: selectedAttribute,
2355
- textValue: selectedAttribute,
2382
+ value: selectedAttribute || void 0,
2383
+ clearLabel: "Clear attribute selection",
2384
+ onClear: () => {
2385
+ handleAttributeChange("");
2386
+ setAttributeSearch("");
2387
+ },
2388
+ onInputChange: (e) => {
2389
+ setAttributeSearch(e.target.value);
2390
+ },
2391
+ onOpenChange: (isOpen) => {
2392
+ if (!isOpen) {
2393
+ setAttributeSearch("");
2394
+ }
2395
+ },
2356
2396
  loading: loading && attributes.length === 0,
2357
2397
  loadingMessage: "Discovering schema attributes...",
2358
2398
  onChange: (val) => {
2359
- if (val && typeof val === "string") {
2399
+ if (val && typeof val === "string" && val !== "__none__") {
2360
2400
  handleAttributeChange(val);
2401
+ setAttributeSearch("");
2361
2402
  }
2362
2403
  },
2363
2404
  children: memoizedComboboxOptions
@@ -2602,7 +2643,7 @@ const BulkUpdater = () => {
2602
2643
  /* @__PURE__ */ jsx(Box, { style: { width: 220, minWidth: 180 }, children: /* @__PURE__ */ jsxs(
2603
2644
  SingleSelect,
2604
2645
  {
2605
- label: `Filter condition for "${selectedAttribute}"`,
2646
+ label: selectedAttribute ? `Filter condition for "${selectedAttribute}"` : "Filter condition",
2606
2647
  value: filterOperator,
2607
2648
  onChange: (val) => setFilterOperator(String(val)),
2608
2649
  children: [
@@ -2618,7 +2659,7 @@ const BulkUpdater = () => {
2618
2659
  (filterOperator === "equals" || filterOperator === "contains" || filterOperator === "starts_with") && /* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ jsx(
2619
2660
  TextInput,
2620
2661
  {
2621
- label: `Value for "${selectedAttribute}"`,
2662
+ label: selectedAttribute ? `Value for "${selectedAttribute}"` : "Value to match",
2622
2663
  placeholder: "Type value to match...",
2623
2664
  value: filterQuery,
2624
2665
  onChange: (e) => setFilterQuery(e.target.value)
@@ -2746,7 +2787,7 @@ const BulkUpdater = () => {
2746
2787
  (col) => !typeVisibilitySearch.trim() || col.displayName.toLowerCase().includes(typeVisibilitySearch.toLowerCase().trim()) || col.uid.toLowerCase().includes(typeVisibilitySearch.toLowerCase().trim())
2747
2788
  ).map((col) => {
2748
2789
  const isVisible = visibleTypeUids[col.uid] !== false;
2749
- const hasAttr = col.attributes.includes(selectedAttribute);
2790
+ const hasAttr = selectedAttribute ? col.attributes.includes(selectedAttribute) : false;
2750
2791
  return /* @__PURE__ */ jsx(
2751
2792
  Box,
2752
2793
  {
@@ -2820,9 +2861,9 @@ const BulkUpdater = () => {
2820
2861
  const page = pageState ? pageState.page : 1;
2821
2862
  const pageCount = pageState ? pageState.pageCount : 1;
2822
2863
  const pageSize = pageState ? pageState.pageSize : defaultPageSize;
2823
- const hasAttr = col.attributes.includes(selectedAttribute);
2864
+ const hasAttr = selectedAttribute ? col.attributes.includes(selectedAttribute) : false;
2824
2865
  const visibleEntries = getVisibleEntries(col);
2825
- entries.filter((e) => entryMatchesFilter(e, selectedAttribute)).length;
2866
+ selectedAttribute ? entries.filter((e) => entryMatchesFilter(e, selectedAttribute)).length : 0;
2826
2867
  const isFullySelected = isCollectionFullySelected(col);
2827
2868
  const isPartiallySelected = isCollectionPartiallySelected(col);
2828
2869
  const currentSort = collectionSorts[col.uid] || { field: "createdAt", order: "desc" };
@@ -2856,14 +2897,14 @@ const BulkUpdater = () => {
2856
2897
  ] })
2857
2898
  }
2858
2899
  ),
2859
- col.isSingleType ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: "Single Type" }) : /* @__PURE__ */ jsx(
2900
+ col.isSingleType ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: "Single Type" }) : selectedAttribute ? /* @__PURE__ */ jsx(
2860
2901
  Badge,
2861
2902
  {
2862
2903
  backgroundColor: hasAttr ? "success100" : "warning100",
2863
2904
  textColor: hasAttr ? "success700" : "warning700",
2864
2905
  children: hasAttr ? `Schema has "${selectedAttribute}"` : `Schema lacks "${selectedAttribute}" (will skip)`
2865
2906
  }
2866
- )
2907
+ ) : null
2867
2908
  ] }),
2868
2909
  /* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
2869
2910
  !col.isSingleType && /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
@@ -3788,4 +3829,4 @@ export {
3788
3829
  getAvailableColumnsForCollection,
3789
3830
  getNestedValue
3790
3831
  };
3791
- //# sourceMappingURL=BulkUpdater-DR8Z9z95.mjs.map
3832
+ //# sourceMappingURL=BulkUpdater-NpSxrH3b.mjs.map