@universe-platform/ui 0.1.0-beta.10 → 0.1.0-beta.11
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/dist/globals.css +142 -21
- package/dist/index.d.mts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +1319 -442
- package/dist/index.mjs +1302 -426
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -68,6 +68,7 @@ __export(src_exports, {
|
|
|
68
68
|
DatePickerCell: () => DatePickerCell,
|
|
69
69
|
LinkPickerCell: () => LinkPickerCell,
|
|
70
70
|
PASTEL_PALETTES: () => PASTEL_PALETTES,
|
|
71
|
+
RelationFilterPopover: () => RelationFilterPopover,
|
|
71
72
|
RelationPickerCell: () => RelationPickerCell,
|
|
72
73
|
TEXT_REPRESENTABLE_TYPES: () => TEXT_REPRESENTABLE_TYPES,
|
|
73
74
|
TableBlock: () => TableBlock,
|
|
@@ -224,7 +225,7 @@ var COLUMN_DEFAULT_INPUT_CONFIG = {
|
|
|
224
225
|
NUMBER: { inputType: "number", placeholder: "\u05D4\u05D6\u05DF \u05DE\u05E1\u05E4\u05E8" },
|
|
225
226
|
BOOLEAN: { inputType: "select" },
|
|
226
227
|
DATE: { inputType: "date" },
|
|
227
|
-
RELATION: { inputType: "
|
|
228
|
+
RELATION: { inputType: "select", placeholder: "\u05D1\u05D7\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05DB\u05D1\u05E8\u05D9\u05E8\u05EA \u05DE\u05D7\u05D3\u05DC" },
|
|
228
229
|
GOOGLE_DRIVE_FILE: { inputType: "text" },
|
|
229
230
|
CURRENCY: { inputType: "number", placeholder: "\u05D4\u05D6\u05DF \u05DE\u05E1\u05E4\u05E8" },
|
|
230
231
|
TIME: { inputType: "time" },
|
|
@@ -235,7 +236,7 @@ var COLUMN_DEFAULT_INPUT_CONFIG = {
|
|
|
235
236
|
};
|
|
236
237
|
|
|
237
238
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
238
|
-
var
|
|
239
|
+
var import_react14 = __toESM(require("react"));
|
|
239
240
|
|
|
240
241
|
// src/hooks/useToast.ts
|
|
241
242
|
var import_react2 = require("react");
|
|
@@ -1525,7 +1526,8 @@ function LinkPickerCell({ value, onChange, readOnly = false }) {
|
|
|
1525
1526
|
}
|
|
1526
1527
|
|
|
1527
1528
|
// src/components/TableBlock/fields/RelationPickerCell.tsx
|
|
1528
|
-
var import_react7 = require("react");
|
|
1529
|
+
var import_react7 = __toESM(require("react"));
|
|
1530
|
+
var import_react_dom = require("react-dom");
|
|
1529
1531
|
var import_lucide_react6 = require("lucide-react");
|
|
1530
1532
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1531
1533
|
function isRawObjectId(str) {
|
|
@@ -1584,6 +1586,30 @@ function resolveRelationLabel(opt, column) {
|
|
|
1584
1586
|
}
|
|
1585
1587
|
return "";
|
|
1586
1588
|
}
|
|
1589
|
+
var ITEM_HEIGHT = 35;
|
|
1590
|
+
var CONTAINER_HEIGHT = 200;
|
|
1591
|
+
var OVERSCAN = 5;
|
|
1592
|
+
var BATCH_SIZE = 50;
|
|
1593
|
+
var RelationPickerRow = import_react7.default.memo(function RelationPickerRow2({
|
|
1594
|
+
id,
|
|
1595
|
+
label,
|
|
1596
|
+
isSelected,
|
|
1597
|
+
onSelect,
|
|
1598
|
+
height
|
|
1599
|
+
}) {
|
|
1600
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1601
|
+
"div",
|
|
1602
|
+
{
|
|
1603
|
+
onClick: () => onSelect(id),
|
|
1604
|
+
style: { height: `${height}px` },
|
|
1605
|
+
className: `flex items-center justify-between px-2.5 rounded cursor-pointer text-xs transition-colors ${isSelected ? "bg-blue-50 text-blue-900 font-medium" : "hover:bg-slate-50 text-slate-700"}`,
|
|
1606
|
+
children: [
|
|
1607
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate flex-1", children: label }),
|
|
1608
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Check, { className: "w-3.5 h-3.5 text-blue-600 shrink-0 mr-1" })
|
|
1609
|
+
]
|
|
1610
|
+
}
|
|
1611
|
+
);
|
|
1612
|
+
});
|
|
1587
1613
|
function RelationPickerCell({
|
|
1588
1614
|
value,
|
|
1589
1615
|
onChange,
|
|
@@ -1592,42 +1618,147 @@ function RelationPickerCell({
|
|
|
1592
1618
|
rowId,
|
|
1593
1619
|
readOnly = false
|
|
1594
1620
|
}) {
|
|
1595
|
-
var _a;
|
|
1621
|
+
var _a, _b, _c;
|
|
1596
1622
|
const [isOpen, setIsOpen] = (0, import_react7.useState)(false);
|
|
1597
1623
|
const [searchQuery, setSearchQuery] = (0, import_react7.useState)("");
|
|
1624
|
+
const [isRemoteSearching, setIsRemoteSearching] = (0, import_react7.useState)(false);
|
|
1625
|
+
const [isLoadingMore, setIsLoadingMore] = (0, import_react7.useState)(false);
|
|
1626
|
+
const [hasMore, setHasMore] = (0, import_react7.useState)(true);
|
|
1627
|
+
const [items, setItems] = (0, import_react7.useState)([]);
|
|
1628
|
+
const [skip, setSkip] = (0, import_react7.useState)(0);
|
|
1629
|
+
const [scrollTop, setScrollTop] = (0, import_react7.useState)(0);
|
|
1598
1630
|
const containerRef = (0, import_react7.useRef)(null);
|
|
1631
|
+
const dropdownRef = (0, import_react7.useRef)(null);
|
|
1599
1632
|
const searchInputRef = (0, import_react7.useRef)(null);
|
|
1633
|
+
const listContainerRef = (0, import_react7.useRef)(null);
|
|
1634
|
+
const sentinelRef = (0, import_react7.useRef)(null);
|
|
1635
|
+
const [dropdownCoords, setDropdownCoords] = (0, import_react7.useState)(null);
|
|
1636
|
+
const updateDropdownCoords = (0, import_react7.useCallback)(() => {
|
|
1637
|
+
if (!containerRef.current) return;
|
|
1638
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
1639
|
+
const dropdownHeight = 280;
|
|
1640
|
+
const dropdownWidth = Math.max(220, Math.min(320, rect.width || 220));
|
|
1641
|
+
let right = window.innerWidth - rect.right;
|
|
1642
|
+
if (right + dropdownWidth > window.innerWidth - 10) {
|
|
1643
|
+
right = window.innerWidth - dropdownWidth - 10;
|
|
1644
|
+
}
|
|
1645
|
+
if (right < 10) {
|
|
1646
|
+
right = 10;
|
|
1647
|
+
}
|
|
1648
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
1649
|
+
let top = rect.bottom + 4;
|
|
1650
|
+
if (spaceBelow < dropdownHeight && rect.top > dropdownHeight) {
|
|
1651
|
+
top = Math.max(10, rect.top - dropdownHeight - 4);
|
|
1652
|
+
} else {
|
|
1653
|
+
top = Math.min(window.innerHeight - dropdownHeight - 10, top);
|
|
1654
|
+
}
|
|
1655
|
+
setDropdownCoords({ top, right, width: dropdownWidth });
|
|
1656
|
+
}, []);
|
|
1657
|
+
(0, import_react7.useEffect)(() => {
|
|
1658
|
+
if (!isOpen) return;
|
|
1659
|
+
updateDropdownCoords();
|
|
1660
|
+
const handleScrollOrResize = () => updateDropdownCoords();
|
|
1661
|
+
window.addEventListener("scroll", handleScrollOrResize, true);
|
|
1662
|
+
window.addEventListener("resize", handleScrollOrResize);
|
|
1663
|
+
return () => {
|
|
1664
|
+
window.removeEventListener("scroll", handleScrollOrResize, true);
|
|
1665
|
+
window.removeEventListener("resize", handleScrollOrResize);
|
|
1666
|
+
};
|
|
1667
|
+
}, [isOpen, updateDropdownCoords]);
|
|
1668
|
+
const stableLabelCacheRef = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
|
|
1669
|
+
const skipRef = (0, import_react7.useRef)(0);
|
|
1670
|
+
const isLoadingMoreRef = (0, import_react7.useRef)(false);
|
|
1600
1671
|
const allowMultiple = Boolean((_a = column.config) == null ? void 0 : _a.allowMultiple);
|
|
1672
|
+
const referencedTableId = (_b = column.config) == null ? void 0 : _b.referencedTableId;
|
|
1673
|
+
const displayField = (_c = column.config) == null ? void 0 : _c.displayField;
|
|
1601
1674
|
const selectedIds = (0, import_react7.useMemo)(() => normalizeRelationValue(value), [value]);
|
|
1602
1675
|
const isStandalone = !context || context.relationOptions === void 0;
|
|
1603
1676
|
const optionsLoaded = isStandalone || context.relationOptions[column.name] !== void 0;
|
|
1604
|
-
const
|
|
1677
|
+
const baseOptions = (0, import_react7.useMemo)(() => {
|
|
1605
1678
|
var _a2;
|
|
1606
1679
|
return ((_a2 = context == null ? void 0 : context.relationOptions) == null ? void 0 : _a2[column.name]) || [];
|
|
1607
1680
|
}, [context == null ? void 0 : context.relationOptions, column.name]);
|
|
1608
1681
|
const processedOptions = (0, import_react7.useMemo)(() => {
|
|
1609
|
-
return
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
};
|
|
1615
|
-
}).filter((opt) => opt._displayLabel && opt._displayLabel.trim() !== "" && !isRawObjectId(opt._displayLabel));
|
|
1616
|
-
}, [rawOptions, column]);
|
|
1682
|
+
return items.map((opt) => ({
|
|
1683
|
+
id: String(opt.id),
|
|
1684
|
+
_displayLabel: resolveRelationLabel(opt, column) || opt.label || ""
|
|
1685
|
+
})).filter((opt) => opt._displayLabel && opt._displayLabel.trim() !== "" && !isRawObjectId(opt._displayLabel));
|
|
1686
|
+
}, [items, column]);
|
|
1617
1687
|
const getDisplayForId = (0, import_react7.useCallback)((id) => {
|
|
1618
|
-
|
|
1619
|
-
if (
|
|
1620
|
-
|
|
1688
|
+
var _a2, _b2, _c2;
|
|
1689
|
+
if (!id) return "-";
|
|
1690
|
+
const strId = String(id).trim();
|
|
1691
|
+
if (!strId) return "-";
|
|
1692
|
+
if (stableLabelCacheRef.current.has(strId)) {
|
|
1693
|
+
const cached = stableLabelCacheRef.current.get(strId);
|
|
1694
|
+
if (cached && cached !== "-" && !isRawObjectId(cached)) {
|
|
1695
|
+
return cached;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
const dictOpt = (_c2 = (_b2 = (_a2 = context == null ? void 0 : context.relationDictionaryRef) == null ? void 0 : _a2.current) == null ? void 0 : _b2[column.name]) == null ? void 0 : _c2.get(strId);
|
|
1699
|
+
if (dictOpt) {
|
|
1700
|
+
const lbl = resolveRelationLabel(dictOpt, column) || dictOpt.label || dictOpt.name;
|
|
1701
|
+
if (lbl && !isRawObjectId(String(lbl))) {
|
|
1702
|
+
stableLabelCacheRef.current.set(strId, String(lbl));
|
|
1703
|
+
return String(lbl);
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
const foundInItems = items.find((o) => String(o.id) === strId);
|
|
1707
|
+
if (foundInItems) {
|
|
1708
|
+
const lbl = resolveRelationLabel(foundInItems, column) || foundInItems.label || foundInItems.name;
|
|
1709
|
+
if (lbl && !isRawObjectId(String(lbl))) {
|
|
1710
|
+
stableLabelCacheRef.current.set(strId, String(lbl));
|
|
1711
|
+
return String(lbl);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
const foundInBase = (baseOptions || []).find((o) => String(o.id) === strId);
|
|
1715
|
+
if (foundInBase) {
|
|
1716
|
+
const lbl = resolveRelationLabel(foundInBase, column) || foundInBase.label || foundInBase.name;
|
|
1717
|
+
if (lbl && !isRawObjectId(String(lbl))) {
|
|
1718
|
+
stableLabelCacheRef.current.set(strId, String(lbl));
|
|
1719
|
+
return String(lbl);
|
|
1720
|
+
}
|
|
1621
1721
|
}
|
|
1622
1722
|
return "-";
|
|
1623
|
-
}, [
|
|
1723
|
+
}, [items, baseOptions, column, context]);
|
|
1624
1724
|
const handleOpen = (e) => {
|
|
1625
1725
|
if (readOnly) return;
|
|
1626
1726
|
e == null ? void 0 : e.stopPropagation();
|
|
1627
|
-
|
|
1727
|
+
const nextOpen = !isOpen;
|
|
1728
|
+
if (nextOpen) {
|
|
1729
|
+
updateDropdownCoords();
|
|
1730
|
+
}
|
|
1731
|
+
setIsOpen(nextOpen);
|
|
1732
|
+
if (!nextOpen) return;
|
|
1628
1733
|
setSearchQuery("");
|
|
1629
|
-
|
|
1630
|
-
|
|
1734
|
+
setScrollTop(0);
|
|
1735
|
+
setSkip(0);
|
|
1736
|
+
skipRef.current = 0;
|
|
1737
|
+
setHasMore(true);
|
|
1738
|
+
const fetcher = (context == null ? void 0 : context.executeAction) ? (p) => context.executeAction("FETCH_RELATION", p) : (context == null ? void 0 : context.refetchRelation) ? (p) => context.refetchRelation(column.name, p) : null;
|
|
1739
|
+
if (fetcher && referencedTableId) {
|
|
1740
|
+
setIsLoadingMore(true);
|
|
1741
|
+
isLoadingMoreRef.current = true;
|
|
1742
|
+
fetcher({
|
|
1743
|
+
referencedTableId,
|
|
1744
|
+
displayField,
|
|
1745
|
+
take: BATCH_SIZE,
|
|
1746
|
+
limit: BATCH_SIZE,
|
|
1747
|
+
skip: 0
|
|
1748
|
+
}).then((res) => {
|
|
1749
|
+
const newData = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
|
|
1750
|
+
setItems(newData);
|
|
1751
|
+
setSkip(BATCH_SIZE);
|
|
1752
|
+
skipRef.current = BATCH_SIZE;
|
|
1753
|
+
if (newData.length < BATCH_SIZE) {
|
|
1754
|
+
setHasMore(false);
|
|
1755
|
+
}
|
|
1756
|
+
}).catch((err) => {
|
|
1757
|
+
console.warn("[RelationPickerCell] Initial fetch failed:", err);
|
|
1758
|
+
}).finally(() => {
|
|
1759
|
+
setIsLoadingMore(false);
|
|
1760
|
+
isLoadingMoreRef.current = false;
|
|
1761
|
+
});
|
|
1631
1762
|
}
|
|
1632
1763
|
};
|
|
1633
1764
|
(0, import_react7.useEffect)(() => {
|
|
@@ -1638,7 +1769,105 @@ function RelationPickerCell({
|
|
|
1638
1769
|
}, 50);
|
|
1639
1770
|
}
|
|
1640
1771
|
}, [isOpen]);
|
|
1641
|
-
|
|
1772
|
+
(0, import_react7.useEffect)(() => {
|
|
1773
|
+
if (!isOpen) return;
|
|
1774
|
+
const query = searchQuery.trim();
|
|
1775
|
+
const fetcher = (context == null ? void 0 : context.executeAction) ? (p) => context.executeAction("FETCH_RELATION", p) : (context == null ? void 0 : context.refetchRelation) ? (p) => context.refetchRelation(column.name, p) : null;
|
|
1776
|
+
if (!fetcher || !referencedTableId) return;
|
|
1777
|
+
setSkip(0);
|
|
1778
|
+
skipRef.current = 0;
|
|
1779
|
+
setHasMore(true);
|
|
1780
|
+
setScrollTop(0);
|
|
1781
|
+
if (listContainerRef.current) {
|
|
1782
|
+
listContainerRef.current.scrollTop = 0;
|
|
1783
|
+
}
|
|
1784
|
+
setIsRemoteSearching(true);
|
|
1785
|
+
const timer = setTimeout(() => {
|
|
1786
|
+
fetcher({
|
|
1787
|
+
referencedTableId,
|
|
1788
|
+
displayField,
|
|
1789
|
+
search: query,
|
|
1790
|
+
take: BATCH_SIZE,
|
|
1791
|
+
limit: BATCH_SIZE,
|
|
1792
|
+
skip: 0
|
|
1793
|
+
}).then((res) => {
|
|
1794
|
+
const newData = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
|
|
1795
|
+
setItems(newData);
|
|
1796
|
+
setSkip(BATCH_SIZE);
|
|
1797
|
+
skipRef.current = BATCH_SIZE;
|
|
1798
|
+
if (newData.length < BATCH_SIZE) {
|
|
1799
|
+
setHasMore(false);
|
|
1800
|
+
}
|
|
1801
|
+
}).catch((err) => {
|
|
1802
|
+
console.warn("[RelationPickerCell] Remote search failed:", err);
|
|
1803
|
+
}).finally(() => {
|
|
1804
|
+
setIsRemoteSearching(false);
|
|
1805
|
+
});
|
|
1806
|
+
}, 250);
|
|
1807
|
+
return () => clearTimeout(timer);
|
|
1808
|
+
}, [searchQuery, isOpen, referencedTableId, displayField, context, column.name]);
|
|
1809
|
+
const handleLoadMore = (0, import_react7.useCallback)(async () => {
|
|
1810
|
+
if (isLoadingMoreRef.current || !hasMore || !referencedTableId) return;
|
|
1811
|
+
const fetcher = (context == null ? void 0 : context.executeAction) ? (p) => context.executeAction("FETCH_RELATION", p) : (context == null ? void 0 : context.refetchRelation) ? (p) => context.refetchRelation(column.name, p) : null;
|
|
1812
|
+
if (!fetcher) return;
|
|
1813
|
+
isLoadingMoreRef.current = true;
|
|
1814
|
+
setIsLoadingMore(true);
|
|
1815
|
+
const currentQuery = searchQuery.trim();
|
|
1816
|
+
const currentSkip = skipRef.current;
|
|
1817
|
+
try {
|
|
1818
|
+
const res = await fetcher({
|
|
1819
|
+
referencedTableId,
|
|
1820
|
+
displayField,
|
|
1821
|
+
search: currentQuery,
|
|
1822
|
+
take: BATCH_SIZE,
|
|
1823
|
+
limit: BATCH_SIZE,
|
|
1824
|
+
skip: currentSkip
|
|
1825
|
+
});
|
|
1826
|
+
const newData = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
|
|
1827
|
+
if (newData.length < BATCH_SIZE) {
|
|
1828
|
+
setHasMore(false);
|
|
1829
|
+
}
|
|
1830
|
+
if (newData.length > 0) {
|
|
1831
|
+
setItems((prev) => {
|
|
1832
|
+
const seen = new Set(prev.map((i) => String(i.id)));
|
|
1833
|
+
const unique = newData.filter((i) => !seen.has(String(i.id)));
|
|
1834
|
+
return [...prev, ...unique];
|
|
1835
|
+
});
|
|
1836
|
+
setSkip((prev) => prev + BATCH_SIZE);
|
|
1837
|
+
skipRef.current += BATCH_SIZE;
|
|
1838
|
+
}
|
|
1839
|
+
} catch (err) {
|
|
1840
|
+
console.warn("[RelationPickerCell] Load more failed:", err);
|
|
1841
|
+
} finally {
|
|
1842
|
+
isLoadingMoreRef.current = false;
|
|
1843
|
+
setIsLoadingMore(false);
|
|
1844
|
+
}
|
|
1845
|
+
}, [hasMore, referencedTableId, searchQuery, context, column.name, displayField]);
|
|
1846
|
+
(0, import_react7.useEffect)(() => {
|
|
1847
|
+
if (!isOpen || !hasMore) return;
|
|
1848
|
+
const sentinel = sentinelRef.current;
|
|
1849
|
+
if (!sentinel) return;
|
|
1850
|
+
const observer = new IntersectionObserver(
|
|
1851
|
+
(entries) => {
|
|
1852
|
+
var _a2;
|
|
1853
|
+
if (((_a2 = entries[0]) == null ? void 0 : _a2.isIntersecting) && !isLoadingMoreRef.current) {
|
|
1854
|
+
handleLoadMore();
|
|
1855
|
+
}
|
|
1856
|
+
},
|
|
1857
|
+
{ root: listContainerRef.current, threshold: 0.1 }
|
|
1858
|
+
);
|
|
1859
|
+
observer.observe(sentinel);
|
|
1860
|
+
return () => observer.disconnect();
|
|
1861
|
+
}, [isOpen, hasMore, handleLoadMore]);
|
|
1862
|
+
const handleListScroll = (e) => {
|
|
1863
|
+
const currentScrollTop = e.currentTarget.scrollTop;
|
|
1864
|
+
setScrollTop(currentScrollTop);
|
|
1865
|
+
const { clientHeight, scrollHeight } = e.currentTarget;
|
|
1866
|
+
if (scrollHeight - (currentScrollTop + clientHeight) < 60 && hasMore && !isLoadingMoreRef.current) {
|
|
1867
|
+
handleLoadMore();
|
|
1868
|
+
}
|
|
1869
|
+
};
|
|
1870
|
+
const handleSelectOption = (0, import_react7.useCallback)((optId) => {
|
|
1642
1871
|
if (!allowMultiple) {
|
|
1643
1872
|
onChange([optId]);
|
|
1644
1873
|
setIsOpen(false);
|
|
@@ -1649,7 +1878,7 @@ function RelationPickerCell({
|
|
|
1649
1878
|
onChange([...selectedIds, optId]);
|
|
1650
1879
|
}
|
|
1651
1880
|
}
|
|
1652
|
-
};
|
|
1881
|
+
}, [allowMultiple, onChange, selectedIds]);
|
|
1653
1882
|
const handleRemove = (idToRemove) => {
|
|
1654
1883
|
onChange(selectedIds.filter((id) => id !== idToRemove));
|
|
1655
1884
|
};
|
|
@@ -1660,7 +1889,8 @@ function RelationPickerCell({
|
|
|
1660
1889
|
(0, import_react7.useEffect)(() => {
|
|
1661
1890
|
if (!isOpen) return;
|
|
1662
1891
|
function handleClickOutside(event) {
|
|
1663
|
-
|
|
1892
|
+
const target = event.target;
|
|
1893
|
+
if (containerRef.current && !containerRef.current.contains(target) && dropdownRef.current && !dropdownRef.current.contains(target)) {
|
|
1664
1894
|
setIsOpen(false);
|
|
1665
1895
|
}
|
|
1666
1896
|
}
|
|
@@ -1676,13 +1906,19 @@ function RelationPickerCell({
|
|
|
1676
1906
|
document.removeEventListener("keydown", handleKeyDown);
|
|
1677
1907
|
};
|
|
1678
1908
|
}, [isOpen]);
|
|
1679
|
-
const
|
|
1909
|
+
const displayedOptions = (0, import_react7.useMemo)(() => {
|
|
1680
1910
|
const query = searchQuery.trim().toLowerCase();
|
|
1681
1911
|
if (!query) return processedOptions;
|
|
1682
1912
|
return processedOptions.filter((opt) => {
|
|
1683
1913
|
return (opt._displayLabel || "").toLowerCase().includes(query);
|
|
1684
1914
|
});
|
|
1685
1915
|
}, [processedOptions, searchQuery]);
|
|
1916
|
+
const totalItems = displayedOptions.length;
|
|
1917
|
+
const totalHeight = totalItems * ITEM_HEIGHT;
|
|
1918
|
+
const startIndex = Math.max(0, Math.floor(scrollTop / ITEM_HEIGHT) - OVERSCAN);
|
|
1919
|
+
const endIndex = Math.min(totalItems, Math.ceil((scrollTop + CONTAINER_HEIGHT) / ITEM_HEIGHT) + OVERSCAN);
|
|
1920
|
+
const visibleOptions = displayedOptions.slice(startIndex, endIndex);
|
|
1921
|
+
const topPadding = startIndex * ITEM_HEIGHT;
|
|
1686
1922
|
if (!optionsLoaded && selectedIds.length > 0) {
|
|
1687
1923
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-2 py-1 flex items-center h-full w-full", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "inline-block w-16 h-4 bg-slate-100 animate-pulse rounded" }) });
|
|
1688
1924
|
}
|
|
@@ -1804,51 +2040,101 @@ function RelationPickerCell({
|
|
|
1804
2040
|
)
|
|
1805
2041
|
}
|
|
1806
2042
|
),
|
|
1807
|
-
isOpen &&
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
2043
|
+
isOpen && dropdownCoords && typeof document !== "undefined" && (0, import_react_dom.createPortal)(
|
|
2044
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2045
|
+
"div",
|
|
2046
|
+
{
|
|
2047
|
+
ref: dropdownRef,
|
|
2048
|
+
id: `relation-dropdown-${column.name}-${rowId || "cell"}`,
|
|
2049
|
+
dir: "rtl",
|
|
2050
|
+
style: {
|
|
2051
|
+
position: "fixed",
|
|
2052
|
+
top: `${dropdownCoords.top}px`,
|
|
2053
|
+
right: `${dropdownCoords.right}px`,
|
|
2054
|
+
width: `${dropdownCoords.width}px`,
|
|
2055
|
+
zIndex: 99999
|
|
2056
|
+
},
|
|
2057
|
+
className: "bg-white rounded-md shadow-2xl border border-slate-200 p-1 animate-in fade-in duration-100 flex flex-col",
|
|
2058
|
+
onClick: (e) => e.stopPropagation(),
|
|
2059
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
2060
|
+
children: [
|
|
2061
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative mb-1", children: [
|
|
2062
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Search, { className: "w-3.5 h-3.5 text-slate-400 absolute right-2 top-2 pointer-events-none" }),
|
|
2063
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2064
|
+
"input",
|
|
2065
|
+
{
|
|
2066
|
+
ref: searchInputRef,
|
|
2067
|
+
type: "text",
|
|
2068
|
+
placeholder: "\u05D7\u05E4\u05E9...",
|
|
2069
|
+
value: searchQuery,
|
|
2070
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
2071
|
+
onKeyDown: (e) => {
|
|
2072
|
+
if (e.key === "Escape") {
|
|
2073
|
+
e.stopPropagation();
|
|
2074
|
+
setIsOpen(false);
|
|
2075
|
+
}
|
|
2076
|
+
},
|
|
2077
|
+
className: "w-full h-7 pr-7 pl-7 bg-slate-50 border border-slate-200 rounded text-xs text-slate-800 placeholder-slate-400 focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 transition-colors"
|
|
2078
|
+
}
|
|
2079
|
+
),
|
|
2080
|
+
isRemoteSearching && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Loader2, { className: "w-3.5 h-3.5 text-blue-500 animate-spin absolute left-2 top-2 pointer-events-none" })
|
|
2081
|
+
] }),
|
|
1817
2082
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1818
|
-
"
|
|
2083
|
+
"div",
|
|
1819
2084
|
{
|
|
1820
|
-
ref:
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
2085
|
+
ref: listContainerRef,
|
|
2086
|
+
onScroll: handleListScroll,
|
|
2087
|
+
style: { maxHeight: `${CONTAINER_HEIGHT}px` },
|
|
2088
|
+
className: "overflow-y-auto relative",
|
|
2089
|
+
children: displayedOptions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2090
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { height: `${totalHeight}px`, position: "relative", width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2091
|
+
"div",
|
|
2092
|
+
{
|
|
2093
|
+
style: {
|
|
2094
|
+
position: "absolute",
|
|
2095
|
+
top: 0,
|
|
2096
|
+
left: 0,
|
|
2097
|
+
right: 0,
|
|
2098
|
+
transform: `translateY(${topPadding}px)`
|
|
2099
|
+
},
|
|
2100
|
+
children: visibleOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2101
|
+
RelationPickerRow,
|
|
2102
|
+
{
|
|
2103
|
+
id: opt.id,
|
|
2104
|
+
label: opt._displayLabel,
|
|
2105
|
+
isSelected: selectedIds.includes(opt.id),
|
|
2106
|
+
onSelect: handleSelectOption,
|
|
2107
|
+
height: ITEM_HEIGHT
|
|
2108
|
+
},
|
|
2109
|
+
opt.id
|
|
2110
|
+
))
|
|
2111
|
+
}
|
|
2112
|
+
) }),
|
|
2113
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: sentinelRef, className: "pt-1 pb-0.5 px-2 text-center", children: isLoadingMore ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-center gap-1.5 text-xs text-slate-400 py-1", children: [
|
|
2114
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Loader2, { className: "w-3 h-3 text-blue-500 animate-spin shrink-0" }),
|
|
2115
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D8\u05D5\u05E2\u05DF \u05E2\u05D5\u05D3 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA..." })
|
|
2116
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2117
|
+
"button",
|
|
2118
|
+
{
|
|
2119
|
+
type: "button",
|
|
2120
|
+
onClick: (e) => {
|
|
2121
|
+
e.stopPropagation();
|
|
2122
|
+
handleLoadMore();
|
|
2123
|
+
},
|
|
2124
|
+
className: "text-[11px] text-blue-600 hover:text-blue-700 hover:underline py-1 px-2 font-medium",
|
|
2125
|
+
children: "\u05D8\u05E2\u05DF \u05E2\u05D5\u05D3 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA..."
|
|
2126
|
+
}
|
|
2127
|
+
) })
|
|
2128
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "py-2.5 px-2 text-center text-xs text-slate-400 select-none", children: isRemoteSearching ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-center gap-1.5 py-1", children: [
|
|
2129
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Loader2, { className: "w-3 h-3 text-blue-500 animate-spin shrink-0" }),
|
|
2130
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05DE\u05D7\u05E4\u05E9 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA..." })
|
|
2131
|
+
] }) : items.length === 0 ? "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D6\u05DE\u05D9\u05E0\u05D5\u05EA" : "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA" })
|
|
1832
2132
|
}
|
|
1833
2133
|
)
|
|
1834
|
-
]
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
"div",
|
|
1839
|
-
{
|
|
1840
|
-
onClick: () => handleSelectOption(opt.id),
|
|
1841
|
-
className: `flex items-center justify-between px-2.5 py-1.5 rounded cursor-pointer text-xs transition-colors ${isSelected ? "bg-blue-50 text-blue-900 font-medium" : "hover:bg-slate-50 text-slate-700"}`,
|
|
1842
|
-
children: [
|
|
1843
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate flex-1", children: opt._displayLabel }),
|
|
1844
|
-
isSelected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Check, { className: "w-3.5 h-3.5 text-blue-600 shrink-0 mr-1" })
|
|
1845
|
-
]
|
|
1846
|
-
},
|
|
1847
|
-
opt.id
|
|
1848
|
-
);
|
|
1849
|
-
}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "py-2.5 px-2 text-center text-xs text-slate-400 select-none", children: processedOptions.length === 0 ? "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D6\u05DE\u05D9\u05E0\u05D5\u05EA" : "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA" }) })
|
|
1850
|
-
]
|
|
1851
|
-
}
|
|
2134
|
+
]
|
|
2135
|
+
}
|
|
2136
|
+
),
|
|
2137
|
+
document.body
|
|
1852
2138
|
)
|
|
1853
2139
|
]
|
|
1854
2140
|
}
|
|
@@ -2269,7 +2555,7 @@ var FORM_INPUTS = {
|
|
|
2269
2555
|
};
|
|
2270
2556
|
|
|
2271
2557
|
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
2272
|
-
var
|
|
2558
|
+
var import_react12 = require("react");
|
|
2273
2559
|
|
|
2274
2560
|
// src/utils/phone.ts
|
|
2275
2561
|
function sanitizePhoneNumber(phone) {
|
|
@@ -2427,6 +2713,7 @@ function useColumnReorder({
|
|
|
2427
2713
|
}
|
|
2428
2714
|
|
|
2429
2715
|
// src/components/TableBlock/columnTitleUtils.tsx
|
|
2716
|
+
var import_react11 = require("react");
|
|
2430
2717
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2431
2718
|
var canvas = null;
|
|
2432
2719
|
function measureTextWidth(text, font = '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif') {
|
|
@@ -2467,10 +2754,10 @@ function splitHeaderTitle(name) {
|
|
|
2467
2754
|
}
|
|
2468
2755
|
function calculateMinColumnWidth(name, isSubTable = false, colType) {
|
|
2469
2756
|
const font = isSubTable ? '600 12px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' : '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2470
|
-
const chromeWidth = isSubTable ?
|
|
2471
|
-
let baseMin = isSubTable ?
|
|
2757
|
+
const chromeWidth = isSubTable ? 24 : 26;
|
|
2758
|
+
let baseMin = isSubTable ? 30 : 36;
|
|
2472
2759
|
if ((colType == null ? void 0 : colType.toUpperCase()) === "GOOGLE_CONTACT") {
|
|
2473
|
-
baseMin = isSubTable ?
|
|
2760
|
+
baseMin = isSubTable ? 100 : 110;
|
|
2474
2761
|
}
|
|
2475
2762
|
if (!name) return baseMin;
|
|
2476
2763
|
const { isSingleWord, line1, line2 } = splitHeaderTitle(name);
|
|
@@ -2484,12 +2771,16 @@ function calculateMinColumnWidth(name, isSubTable = false, colType) {
|
|
|
2484
2771
|
return Math.max(baseMin, Math.ceil(maxLine + chromeWidth));
|
|
2485
2772
|
}
|
|
2486
2773
|
function ColumnHeaderTitle({ name, width, isSubTable = false }) {
|
|
2774
|
+
const [isMounted, setIsMounted] = (0, import_react11.useState)(false);
|
|
2775
|
+
(0, import_react11.useEffect)(() => {
|
|
2776
|
+
setIsMounted(true);
|
|
2777
|
+
}, []);
|
|
2487
2778
|
const { isSingleWord, line1, line2 } = splitHeaderTitle(name);
|
|
2488
|
-
if (isSingleWord || !line2) {
|
|
2489
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children:
|
|
2779
|
+
if (!isMounted || isSingleWord || !line2) {
|
|
2780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children: name });
|
|
2490
2781
|
}
|
|
2491
2782
|
const font = isSubTable ? '600 12px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' : '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2492
|
-
const chromeWidth = isSubTable ?
|
|
2783
|
+
const chromeWidth = isSubTable ? 24 : 26;
|
|
2493
2784
|
const fullTitleWidth = measureTextWidth(name, font) + chromeWidth;
|
|
2494
2785
|
if (width !== void 0 && width >= fullTitleWidth) {
|
|
2495
2786
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children: name });
|
|
@@ -2623,18 +2914,18 @@ function SubTableCell({
|
|
|
2623
2914
|
const isContact = colType === "GOOGLE_CONTACT";
|
|
2624
2915
|
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
2625
2916
|
const serverValue = (_b = record.data[column.name]) != null ? _b : colType === "BOOLEAN" ? false : "";
|
|
2626
|
-
const [draftValue, setDraftValue] = (0,
|
|
2627
|
-
const [isDirty, setIsDirty] = (0,
|
|
2628
|
-
const [validationError, setValidationError] = (0,
|
|
2629
|
-
const cellRef = (0,
|
|
2630
|
-
const draftRef = (0,
|
|
2631
|
-
const isDirtyRef = (0,
|
|
2632
|
-
const serverValueRef = (0,
|
|
2633
|
-
const recordIdRef = (0,
|
|
2634
|
-
const columnRef = (0,
|
|
2635
|
-
const onCommitRef = (0,
|
|
2636
|
-
const isCommittingRef = (0,
|
|
2637
|
-
const lastFailedValRef = (0,
|
|
2917
|
+
const [draftValue, setDraftValue] = (0, import_react12.useState)(serverValue);
|
|
2918
|
+
const [isDirty, setIsDirty] = (0, import_react12.useState)(false);
|
|
2919
|
+
const [validationError, setValidationError] = (0, import_react12.useState)(null);
|
|
2920
|
+
const cellRef = (0, import_react12.useRef)(null);
|
|
2921
|
+
const draftRef = (0, import_react12.useRef)(draftValue);
|
|
2922
|
+
const isDirtyRef = (0, import_react12.useRef)(isDirty);
|
|
2923
|
+
const serverValueRef = (0, import_react12.useRef)(serverValue);
|
|
2924
|
+
const recordIdRef = (0, import_react12.useRef)(record.id);
|
|
2925
|
+
const columnRef = (0, import_react12.useRef)(column);
|
|
2926
|
+
const onCommitRef = (0, import_react12.useRef)(onCommit);
|
|
2927
|
+
const isCommittingRef = (0, import_react12.useRef)(false);
|
|
2928
|
+
const lastFailedValRef = (0, import_react12.useRef)(void 0);
|
|
2638
2929
|
const { addToast } = useToast();
|
|
2639
2930
|
draftRef.current = draftValue;
|
|
2640
2931
|
isDirtyRef.current = isDirty;
|
|
@@ -2642,7 +2933,7 @@ function SubTableCell({
|
|
|
2642
2933
|
recordIdRef.current = record.id;
|
|
2643
2934
|
columnRef.current = column;
|
|
2644
2935
|
onCommitRef.current = onCommit;
|
|
2645
|
-
(0,
|
|
2936
|
+
(0, import_react12.useEffect)(() => {
|
|
2646
2937
|
if (!isDirtyRef.current) {
|
|
2647
2938
|
setDraftValue(serverValue);
|
|
2648
2939
|
draftRef.current = serverValue;
|
|
@@ -2650,7 +2941,7 @@ function SubTableCell({
|
|
|
2650
2941
|
lastFailedValRef.current = void 0;
|
|
2651
2942
|
}
|
|
2652
2943
|
}, [serverValue]);
|
|
2653
|
-
const commit = (0,
|
|
2944
|
+
const commit = (0, import_react12.useCallback)(async (valToCommit) => {
|
|
2654
2945
|
if (isCommittingRef.current) return false;
|
|
2655
2946
|
if (!isDirtyRef.current) return true;
|
|
2656
2947
|
if (valToCommit === serverValueRef.current) {
|
|
@@ -2691,7 +2982,7 @@ function SubTableCell({
|
|
|
2691
2982
|
isCommittingRef.current = false;
|
|
2692
2983
|
}
|
|
2693
2984
|
}, [addToast]);
|
|
2694
|
-
const discard = (0,
|
|
2985
|
+
const discard = (0, import_react12.useCallback)(() => {
|
|
2695
2986
|
setDraftValue(serverValueRef.current);
|
|
2696
2987
|
draftRef.current = serverValueRef.current;
|
|
2697
2988
|
setIsDirty(false);
|
|
@@ -2699,7 +2990,7 @@ function SubTableCell({
|
|
|
2699
2990
|
setValidationError(null);
|
|
2700
2991
|
lastFailedValRef.current = void 0;
|
|
2701
2992
|
}, []);
|
|
2702
|
-
(0,
|
|
2993
|
+
(0, import_react12.useEffect)(() => {
|
|
2703
2994
|
return () => {
|
|
2704
2995
|
if (isDirtyRef.current && !isCommittingRef.current) {
|
|
2705
2996
|
const val = draftRef.current;
|
|
@@ -2801,7 +3092,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2801
3092
|
var _a, _b, _c, _d, _e, _f;
|
|
2802
3093
|
const { addToast } = useToast();
|
|
2803
3094
|
const entries = Array.isArray(value) ? value : [];
|
|
2804
|
-
const [linkedRecords, setLinkedRecords] = (0,
|
|
3095
|
+
const [linkedRecords, setLinkedRecords] = (0, import_react12.useState)(() => {
|
|
2805
3096
|
const initial = [];
|
|
2806
3097
|
for (const entry of entries) {
|
|
2807
3098
|
if (entry.recordId && entry._resolvedData) {
|
|
@@ -2810,25 +3101,25 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2810
3101
|
}
|
|
2811
3102
|
return initial;
|
|
2812
3103
|
});
|
|
2813
|
-
const [targetSchema, setTargetSchema] = (0,
|
|
2814
|
-
const [isLoading, setIsLoading] = (0,
|
|
2815
|
-
const [isSearchOpen, setIsSearchOpen] = (0,
|
|
2816
|
-
const [searchQuery, setSearchQuery] = (0,
|
|
2817
|
-
const [searchResults, setSearchResults] = (0,
|
|
2818
|
-
const [isSearching, setIsSearching] = (0,
|
|
2819
|
-
const [isCreating, setIsCreating] = (0,
|
|
2820
|
-
const [newRecordData, setNewRecordData] = (0,
|
|
2821
|
-
const [conflictModalState, setConflictModalState] = (0,
|
|
3104
|
+
const [targetSchema, setTargetSchema] = (0, import_react12.useState)(null);
|
|
3105
|
+
const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
|
|
3106
|
+
const [isSearchOpen, setIsSearchOpen] = (0, import_react12.useState)(false);
|
|
3107
|
+
const [searchQuery, setSearchQuery] = (0, import_react12.useState)("");
|
|
3108
|
+
const [searchResults, setSearchResults] = (0, import_react12.useState)([]);
|
|
3109
|
+
const [isSearching, setIsSearching] = (0, import_react12.useState)(false);
|
|
3110
|
+
const [isCreating, setIsCreating] = (0, import_react12.useState)(false);
|
|
3111
|
+
const [newRecordData, setNewRecordData] = (0, import_react12.useState)({});
|
|
3112
|
+
const [conflictModalState, setConflictModalState] = (0, import_react12.useState)({
|
|
2822
3113
|
isOpen: false,
|
|
2823
3114
|
fieldName: "",
|
|
2824
3115
|
matchingRecords: []
|
|
2825
3116
|
});
|
|
2826
|
-
const searchRef = (0,
|
|
2827
|
-
const searchTimerRef = (0,
|
|
3117
|
+
const searchRef = (0, import_react12.useRef)(null);
|
|
3118
|
+
const searchTimerRef = (0, import_react12.useRef)(null);
|
|
2828
3119
|
const executeAction = context == null ? void 0 : context.executeAction;
|
|
2829
3120
|
const referencedTableId = ((_a = column.config) == null ? void 0 : _a.referencedTableId) || column.referencedTableId;
|
|
2830
|
-
const fetchedIdsRef = (0,
|
|
2831
|
-
(0,
|
|
3121
|
+
const fetchedIdsRef = (0, import_react12.useRef)(/* @__PURE__ */ new Set());
|
|
3122
|
+
(0, import_react12.useEffect)(() => {
|
|
2832
3123
|
if (entries.length > 0) {
|
|
2833
3124
|
setLinkedRecords((prev) => {
|
|
2834
3125
|
const existingIds = new Set(prev.map((r) => r.id));
|
|
@@ -2843,7 +3134,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2843
3134
|
});
|
|
2844
3135
|
}
|
|
2845
3136
|
}, [entries]);
|
|
2846
|
-
(0,
|
|
3137
|
+
(0, import_react12.useEffect)(() => {
|
|
2847
3138
|
if (!referencedTableId || !executeAction) {
|
|
2848
3139
|
setIsLoading(false);
|
|
2849
3140
|
return;
|
|
@@ -2870,7 +3161,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2870
3161
|
recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
|
|
2871
3162
|
}).finally(() => setIsLoading(false));
|
|
2872
3163
|
}, [referencedTableId, executeAction, entries, targetSchema]);
|
|
2873
|
-
(0,
|
|
3164
|
+
(0, import_react12.useEffect)(() => {
|
|
2874
3165
|
const handleClick = (e) => {
|
|
2875
3166
|
if (searchRef.current && !searchRef.current.contains(e.target)) {
|
|
2876
3167
|
setIsSearchOpen(false);
|
|
@@ -2879,7 +3170,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2879
3170
|
if (isSearchOpen) document.addEventListener("mousedown", handleClick);
|
|
2880
3171
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
2881
3172
|
}, [isSearchOpen]);
|
|
2882
|
-
const handleSearch = (0,
|
|
3173
|
+
const handleSearch = (0, import_react12.useCallback)((query) => {
|
|
2883
3174
|
setSearchQuery(query);
|
|
2884
3175
|
if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
|
|
2885
3176
|
if (!query.trim()) {
|
|
@@ -2905,16 +3196,16 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2905
3196
|
}
|
|
2906
3197
|
}, 300);
|
|
2907
3198
|
}, [executeAction, referencedTableId, entries]);
|
|
2908
|
-
const [localColumnOrder, setLocalColumnOrder] = (0,
|
|
2909
|
-
(0,
|
|
3199
|
+
const [localColumnOrder, setLocalColumnOrder] = (0, import_react12.useState)(null);
|
|
3200
|
+
(0, import_react12.useEffect)(() => {
|
|
2910
3201
|
setLocalColumnOrder(null);
|
|
2911
3202
|
}, [column.name, (_b = column.config) == null ? void 0 : _b.subTableColumnOrder]);
|
|
2912
|
-
const rawTargetColumns = (0,
|
|
3203
|
+
const rawTargetColumns = (0, import_react12.useMemo)(() => {
|
|
2913
3204
|
return ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
|
|
2914
3205
|
(c) => c.name !== "_id" && c.type !== "SUB_TABLE"
|
|
2915
3206
|
);
|
|
2916
3207
|
}, [targetSchema == null ? void 0 : targetSchema.columns]);
|
|
2917
|
-
const targetColumns = (0,
|
|
3208
|
+
const targetColumns = (0, import_react12.useMemo)(() => {
|
|
2918
3209
|
var _a2;
|
|
2919
3210
|
const activeOrder = localColumnOrder || ((_a2 = column.config) == null ? void 0 : _a2.subTableColumnOrder);
|
|
2920
3211
|
if (!activeOrder || !Array.isArray(activeOrder) || activeOrder.length === 0) {
|
|
@@ -2965,8 +3256,8 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2965
3256
|
return calculateMinColumnWidth(colName, true, col == null ? void 0 : col.type);
|
|
2966
3257
|
}
|
|
2967
3258
|
});
|
|
2968
|
-
const [relationOptions, setRelationOptions] = (0,
|
|
2969
|
-
(0,
|
|
3259
|
+
const [relationOptions, setRelationOptions] = (0, import_react12.useState)({});
|
|
3260
|
+
(0, import_react12.useEffect)(() => {
|
|
2970
3261
|
if (!executeAction || !(targetSchema == null ? void 0 : targetSchema.columns) || targetSchema.columns.length === 0) return;
|
|
2971
3262
|
const relationCols = targetSchema.columns.filter((c) => {
|
|
2972
3263
|
var _a2, _b2;
|
|
@@ -2977,7 +3268,8 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2977
3268
|
try {
|
|
2978
3269
|
const options = await executeAction("FETCH_RELATION", {
|
|
2979
3270
|
referencedTableId: (_a2 = col.config) == null ? void 0 : _a2.referencedTableId,
|
|
2980
|
-
displayField: (_b2 = col.config) == null ? void 0 : _b2.displayField
|
|
3271
|
+
displayField: (_b2 = col.config) == null ? void 0 : _b2.displayField,
|
|
3272
|
+
limit: 1e3
|
|
2981
3273
|
});
|
|
2982
3274
|
if (options && Array.isArray(options)) {
|
|
2983
3275
|
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
@@ -2987,18 +3279,35 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2987
3279
|
}
|
|
2988
3280
|
});
|
|
2989
3281
|
}, [executeAction, targetColumns]);
|
|
2990
|
-
const refetchRelation = (0,
|
|
2991
|
-
var _a2, _b2, _c2;
|
|
3282
|
+
const refetchRelation = (0, import_react12.useCallback)(async (colName, params) => {
|
|
3283
|
+
var _a2, _b2, _c2, _d2, _e2, _f2;
|
|
2992
3284
|
const col = targetColumns.find((c) => c.name === colName);
|
|
2993
|
-
if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !((_b2 = col.config) == null ? void 0 : _b2.referencedTableId) || !executeAction) return;
|
|
3285
|
+
if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !((_b2 = col.config) == null ? void 0 : _b2.referencedTableId) || !executeAction) return [];
|
|
2994
3286
|
try {
|
|
2995
|
-
const options = await executeAction("FETCH_RELATION", {
|
|
3287
|
+
const options = await executeAction("FETCH_RELATION", {
|
|
3288
|
+
referencedTableId: col.config.referencedTableId,
|
|
3289
|
+
displayField: (_c2 = col.config) == null ? void 0 : _c2.displayField,
|
|
3290
|
+
limit: (_d2 = params == null ? void 0 : params.limit) != null ? _d2 : 1e3,
|
|
3291
|
+
skip: (_e2 = params == null ? void 0 : params.skip) != null ? _e2 : 0,
|
|
3292
|
+
search: (_f2 = params == null ? void 0 : params.search) != null ? _f2 : ""
|
|
3293
|
+
});
|
|
2996
3294
|
if (options && Array.isArray(options)) {
|
|
2997
|
-
|
|
3295
|
+
if (params == null ? void 0 : params.append) {
|
|
3296
|
+
setRelationOptions((prev) => {
|
|
3297
|
+
const existing = prev[col.name] || [];
|
|
3298
|
+
const existingIds = new Set(existing.map((o) => String(o.id)));
|
|
3299
|
+
const uniqueNew = options.filter((o) => !existingIds.has(String(o.id)));
|
|
3300
|
+
return __spreadProps(__spreadValues({}, prev), { [col.name]: [...existing, ...uniqueNew] });
|
|
3301
|
+
});
|
|
3302
|
+
} else if (!(params == null ? void 0 : params.search)) {
|
|
3303
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
3304
|
+
}
|
|
3305
|
+
return options;
|
|
2998
3306
|
}
|
|
2999
3307
|
} catch (err) {
|
|
3000
3308
|
console.warn(`[SubTableViewer] Could not refetch relation options for column ${col.name}:`, err);
|
|
3001
3309
|
}
|
|
3310
|
+
return [];
|
|
3002
3311
|
}, [targetColumns, executeAction]);
|
|
3003
3312
|
const updateParentLinkage = async (updated) => {
|
|
3004
3313
|
const isNewRow = rowId.startsWith("temp_");
|
|
@@ -3131,8 +3440,8 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3131
3440
|
);
|
|
3132
3441
|
updateParentLinkage(updated);
|
|
3133
3442
|
};
|
|
3134
|
-
const isMountedRef = (0,
|
|
3135
|
-
(0,
|
|
3443
|
+
const isMountedRef = (0, import_react12.useRef)(true);
|
|
3444
|
+
(0, import_react12.useEffect)(() => {
|
|
3136
3445
|
isMountedRef.current = true;
|
|
3137
3446
|
return () => {
|
|
3138
3447
|
isMountedRef.current = false;
|
|
@@ -3219,7 +3528,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3219
3528
|
}
|
|
3220
3529
|
};
|
|
3221
3530
|
const handleRecordCellChange = handleCommitRecordCell;
|
|
3222
|
-
const handleQuietSubTableCellChange = (0,
|
|
3531
|
+
const handleQuietSubTableCellChange = (0, import_react12.useCallback)((recordId, colName, value2) => {
|
|
3223
3532
|
setLinkedRecords(
|
|
3224
3533
|
(prev) => prev.map((r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r)
|
|
3225
3534
|
);
|
|
@@ -3667,12 +3976,352 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3667
3976
|
}
|
|
3668
3977
|
|
|
3669
3978
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
3979
|
+
var import_lucide_react8 = require("lucide-react");
|
|
3980
|
+
|
|
3981
|
+
// src/components/TableBlock/RelationFilterPopover.tsx
|
|
3982
|
+
var import_react13 = require("react");
|
|
3670
3983
|
var import_lucide_react7 = require("lucide-react");
|
|
3671
3984
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
3985
|
+
function calculatePopoverCoords(rect) {
|
|
3986
|
+
if (!rect || typeof window === "undefined") return null;
|
|
3987
|
+
const popoverWidth = 260;
|
|
3988
|
+
const popoverHeight = 360;
|
|
3989
|
+
let right = window.innerWidth - rect.right;
|
|
3990
|
+
if (right + popoverWidth > window.innerWidth - 10) {
|
|
3991
|
+
right = window.innerWidth - popoverWidth - 10;
|
|
3992
|
+
}
|
|
3993
|
+
if (right < 10) {
|
|
3994
|
+
right = 10;
|
|
3995
|
+
}
|
|
3996
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
3997
|
+
let top = rect.bottom + 6;
|
|
3998
|
+
if (spaceBelow < popoverHeight && rect.top > popoverHeight) {
|
|
3999
|
+
top = Math.max(10, rect.top - popoverHeight - 6);
|
|
4000
|
+
} else {
|
|
4001
|
+
top = Math.min(window.innerHeight - popoverHeight - 10, top);
|
|
4002
|
+
}
|
|
4003
|
+
return { top, right };
|
|
4004
|
+
}
|
|
4005
|
+
function RelationFilterPopover({
|
|
4006
|
+
isOpen,
|
|
4007
|
+
onClose,
|
|
4008
|
+
column,
|
|
4009
|
+
triggerRect,
|
|
4010
|
+
options,
|
|
4011
|
+
filterValue,
|
|
4012
|
+
selectedValues,
|
|
4013
|
+
onSelectionChange,
|
|
4014
|
+
isLoading = false
|
|
4015
|
+
}) {
|
|
4016
|
+
const popoverRef = (0, import_react13.useRef)(null);
|
|
4017
|
+
const searchInputRef = (0, import_react13.useRef)(null);
|
|
4018
|
+
const selectAllRef = (0, import_react13.useRef)(null);
|
|
4019
|
+
const [searchQuery, setSearchQuery] = (0, import_react13.useState)("");
|
|
4020
|
+
const [coords, setCoords] = (0, import_react13.useState)(
|
|
4021
|
+
() => calculatePopoverCoords(triggerRect)
|
|
4022
|
+
);
|
|
4023
|
+
const [mode, setMode] = (0, import_react13.useState)("include");
|
|
4024
|
+
const [checkedSet, setCheckedSet] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
|
|
4025
|
+
const [excludedSet, setExcludedSet] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
|
|
4026
|
+
const prevIsOpenRef = (0, import_react13.useRef)(isOpen);
|
|
4027
|
+
(0, import_react13.useEffect)(() => {
|
|
4028
|
+
const justOpened = isOpen && !prevIsOpenRef.current;
|
|
4029
|
+
prevIsOpenRef.current = isOpen;
|
|
4030
|
+
if (justOpened) {
|
|
4031
|
+
const activeVal = filterValue != null ? filterValue : selectedValues;
|
|
4032
|
+
if (activeVal && typeof activeVal === "object" && !Array.isArray(activeVal) && "operator" in activeVal && activeVal.operator === "notIn") {
|
|
4033
|
+
setMode("exclude");
|
|
4034
|
+
setExcludedSet(new Set(activeVal.values || []));
|
|
4035
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
4036
|
+
} else if (Array.isArray(activeVal) && activeVal.length > 0) {
|
|
4037
|
+
setMode("include");
|
|
4038
|
+
setCheckedSet(new Set(activeVal));
|
|
4039
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4040
|
+
} else {
|
|
4041
|
+
setMode("include");
|
|
4042
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
4043
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
4046
|
+
}, [isOpen, filterValue, selectedValues]);
|
|
4047
|
+
const updatePosition = (0, import_react13.useCallback)(() => {
|
|
4048
|
+
const next = calculatePopoverCoords(triggerRect);
|
|
4049
|
+
if (next) setCoords(next);
|
|
4050
|
+
}, [triggerRect]);
|
|
4051
|
+
(0, import_react13.useEffect)(() => {
|
|
4052
|
+
if (isOpen) {
|
|
4053
|
+
updatePosition();
|
|
4054
|
+
setTimeout(() => {
|
|
4055
|
+
var _a;
|
|
4056
|
+
return (_a = searchInputRef.current) == null ? void 0 : _a.focus();
|
|
4057
|
+
}, 50);
|
|
4058
|
+
} else {
|
|
4059
|
+
setSearchQuery("");
|
|
4060
|
+
}
|
|
4061
|
+
}, [isOpen, updatePosition]);
|
|
4062
|
+
(0, import_react13.useEffect)(() => {
|
|
4063
|
+
if (!isOpen) return;
|
|
4064
|
+
const handleScrollOrResize = () => updatePosition();
|
|
4065
|
+
window.addEventListener("scroll", handleScrollOrResize, true);
|
|
4066
|
+
window.addEventListener("resize", handleScrollOrResize);
|
|
4067
|
+
return () => {
|
|
4068
|
+
window.removeEventListener("scroll", handleScrollOrResize, true);
|
|
4069
|
+
window.removeEventListener("resize", handleScrollOrResize);
|
|
4070
|
+
};
|
|
4071
|
+
}, [isOpen, updatePosition]);
|
|
4072
|
+
(0, import_react13.useEffect)(() => {
|
|
4073
|
+
if (!isOpen) return;
|
|
4074
|
+
const handleMouseDown = (e) => {
|
|
4075
|
+
if (popoverRef.current && !popoverRef.current.contains(e.target)) {
|
|
4076
|
+
onClose();
|
|
4077
|
+
}
|
|
4078
|
+
};
|
|
4079
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4080
|
+
return () => {
|
|
4081
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
4082
|
+
};
|
|
4083
|
+
}, [isOpen, onClose]);
|
|
4084
|
+
(0, import_react13.useEffect)(() => {
|
|
4085
|
+
if (!isOpen) return;
|
|
4086
|
+
const handleKeyDown = (e) => {
|
|
4087
|
+
if (e.key === "Escape") {
|
|
4088
|
+
onClose();
|
|
4089
|
+
}
|
|
4090
|
+
};
|
|
4091
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4092
|
+
return () => {
|
|
4093
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
4094
|
+
};
|
|
4095
|
+
}, [isOpen, onClose]);
|
|
4096
|
+
const filteredOptions = (0, import_react13.useMemo)(() => {
|
|
4097
|
+
if (!searchQuery.trim()) return options;
|
|
4098
|
+
const q = searchQuery.trim().toLowerCase();
|
|
4099
|
+
return options.filter((opt) => opt.label.toLowerCase().includes(q));
|
|
4100
|
+
}, [options, searchQuery]);
|
|
4101
|
+
const isOptionChecked = (0, import_react13.useCallback)(
|
|
4102
|
+
(label) => {
|
|
4103
|
+
if (mode === "exclude") {
|
|
4104
|
+
return !excludedSet.has(label);
|
|
4105
|
+
}
|
|
4106
|
+
return checkedSet.has(label);
|
|
4107
|
+
},
|
|
4108
|
+
[mode, excludedSet, checkedSet]
|
|
4109
|
+
);
|
|
4110
|
+
const allFilteredSelected = (0, import_react13.useMemo)(() => {
|
|
4111
|
+
if (filteredOptions.length === 0) return false;
|
|
4112
|
+
return filteredOptions.every((opt) => isOptionChecked(opt.label));
|
|
4113
|
+
}, [filteredOptions, isOptionChecked]);
|
|
4114
|
+
const someFilteredSelected = (0, import_react13.useMemo)(() => {
|
|
4115
|
+
return filteredOptions.some((opt) => isOptionChecked(opt.label));
|
|
4116
|
+
}, [filteredOptions, isOptionChecked]);
|
|
4117
|
+
(0, import_react13.useEffect)(() => {
|
|
4118
|
+
if (selectAllRef.current) {
|
|
4119
|
+
selectAllRef.current.indeterminate = !allFilteredSelected && someFilteredSelected;
|
|
4120
|
+
}
|
|
4121
|
+
}, [allFilteredSelected, someFilteredSelected]);
|
|
4122
|
+
const handleToggleOption = (label) => {
|
|
4123
|
+
if (mode === "exclude") {
|
|
4124
|
+
const nextExcluded = new Set(excludedSet);
|
|
4125
|
+
if (nextExcluded.has(label)) {
|
|
4126
|
+
nextExcluded.delete(label);
|
|
4127
|
+
} else {
|
|
4128
|
+
nextExcluded.add(label);
|
|
4129
|
+
}
|
|
4130
|
+
setExcludedSet(nextExcluded);
|
|
4131
|
+
if (nextExcluded.size === 0) {
|
|
4132
|
+
onSelectionChange(void 0);
|
|
4133
|
+
} else {
|
|
4134
|
+
onSelectionChange({ operator: "notIn", values: Array.from(nextExcluded) });
|
|
4135
|
+
}
|
|
4136
|
+
} else {
|
|
4137
|
+
const nextChecked = new Set(checkedSet);
|
|
4138
|
+
if (nextChecked.has(label)) {
|
|
4139
|
+
nextChecked.delete(label);
|
|
4140
|
+
} else {
|
|
4141
|
+
nextChecked.add(label);
|
|
4142
|
+
}
|
|
4143
|
+
setCheckedSet(nextChecked);
|
|
4144
|
+
if (nextChecked.size === 0) {
|
|
4145
|
+
onSelectionChange(void 0);
|
|
4146
|
+
} else if (options.length > 0 && nextChecked.size >= options.length) {
|
|
4147
|
+
setMode("exclude");
|
|
4148
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4149
|
+
onSelectionChange(void 0);
|
|
4150
|
+
} else {
|
|
4151
|
+
onSelectionChange(Array.from(nextChecked));
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
};
|
|
4155
|
+
const handleToggleSelectAll = (checked) => {
|
|
4156
|
+
if (checked) {
|
|
4157
|
+
setMode("exclude");
|
|
4158
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4159
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
4160
|
+
onSelectionChange(void 0);
|
|
4161
|
+
} else {
|
|
4162
|
+
setMode("include");
|
|
4163
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
4164
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4165
|
+
onSelectionChange(void 0);
|
|
4166
|
+
}
|
|
4167
|
+
};
|
|
4168
|
+
const handleResetFilter = () => {
|
|
4169
|
+
setMode("include");
|
|
4170
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
4171
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4172
|
+
setSearchQuery("");
|
|
4173
|
+
onSelectionChange(void 0);
|
|
4174
|
+
};
|
|
4175
|
+
if (!isOpen || !coords) return null;
|
|
4176
|
+
const selectedCount = (0, import_react13.useMemo)(() => {
|
|
4177
|
+
if (mode === "exclude") {
|
|
4178
|
+
return Math.max(0, options.length - excludedSet.size);
|
|
4179
|
+
}
|
|
4180
|
+
return checkedSet.size;
|
|
4181
|
+
}, [mode, options.length, excludedSet.size, checkedSet.size]);
|
|
4182
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4183
|
+
"div",
|
|
4184
|
+
{
|
|
4185
|
+
ref: popoverRef,
|
|
4186
|
+
dir: "rtl",
|
|
4187
|
+
style: {
|
|
4188
|
+
top: `${coords.top}px`,
|
|
4189
|
+
right: `${coords.right}px`
|
|
4190
|
+
},
|
|
4191
|
+
className: "fixed z-[99999] w-[260px] bg-white rounded-xl shadow-2xl border border-slate-200 p-2.5 text-right select-none animate-in fade-in duration-100",
|
|
4192
|
+
onClick: (e) => e.stopPropagation(),
|
|
4193
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
4194
|
+
children: [
|
|
4195
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between border-b border-slate-100 pb-2 mb-2", children: [
|
|
4196
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
4197
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-xs font-bold text-slate-700 truncate", children: [
|
|
4198
|
+
"\u05E1\u05D9\u05E0\u05D5\u05DF \u05DC\u05E4\u05D9 ",
|
|
4199
|
+
column.name
|
|
4200
|
+
] }),
|
|
4201
|
+
mode === "exclude" && excludedSet.size > 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-[10px] text-amber-600 font-semibold", children: [
|
|
4202
|
+
"(\u05D4\u05DB\u05DC \u05DC\u05DE\u05E2\u05D8 ",
|
|
4203
|
+
excludedSet.size,
|
|
4204
|
+
")"
|
|
4205
|
+
] }) : mode === "exclude" && excludedSet.size === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-[10px] text-brand font-semibold", children: "(\u05D4\u05DB\u05DC \u05E0\u05D1\u05D7\u05E8)" }) : selectedCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-[10px] text-brand font-semibold", children: [
|
|
4206
|
+
"(",
|
|
4207
|
+
selectedCount,
|
|
4208
|
+
" \u05E0\u05D1\u05D7\u05E8\u05D5)"
|
|
4209
|
+
] }) : null
|
|
4210
|
+
] }),
|
|
4211
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4212
|
+
"button",
|
|
4213
|
+
{
|
|
4214
|
+
type: "button",
|
|
4215
|
+
onClick: onClose,
|
|
4216
|
+
className: "text-slate-400 hover:text-slate-600 p-0.5 rounded hover:bg-slate-100 transition-colors cursor-pointer",
|
|
4217
|
+
title: "\u05E1\u05D2\u05D5\u05E8",
|
|
4218
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.X, { className: "w-3.5 h-3.5" })
|
|
4219
|
+
}
|
|
4220
|
+
)
|
|
4221
|
+
] }),
|
|
4222
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative mb-2", children: [
|
|
4223
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.Search, { className: "w-3.5 h-3.5 text-slate-400 absolute right-2.5 top-1/2 -translate-y-1/2 pointer-events-none" }),
|
|
4224
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4225
|
+
"input",
|
|
4226
|
+
{
|
|
4227
|
+
ref: searchInputRef,
|
|
4228
|
+
type: "text",
|
|
4229
|
+
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA...",
|
|
4230
|
+
value: searchQuery,
|
|
4231
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
4232
|
+
className: "h-7 text-xs pr-7 pl-6 w-full rounded-md border border-slate-200 bg-slate-50 focus:bg-white focus:border-brand focus:ring-1 focus:ring-brand text-slate-800 transition-all placeholder:text-slate-400"
|
|
4233
|
+
}
|
|
4234
|
+
),
|
|
4235
|
+
searchQuery && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4236
|
+
"button",
|
|
4237
|
+
{
|
|
4238
|
+
type: "button",
|
|
4239
|
+
onClick: () => setSearchQuery(""),
|
|
4240
|
+
className: "absolute left-1.5 top-1/2 -translate-y-1/2 p-0.5 text-slate-400 hover:text-slate-600 rounded",
|
|
4241
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.X, { className: "w-3 h-3" })
|
|
4242
|
+
}
|
|
4243
|
+
)
|
|
4244
|
+
] }),
|
|
4245
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between px-1.5 py-1 mb-1 rounded hover:bg-slate-50 transition-colors border-b border-slate-100 pb-1.5", children: [
|
|
4246
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-xs font-medium text-slate-700 flex-1", children: [
|
|
4247
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4248
|
+
"input",
|
|
4249
|
+
{
|
|
4250
|
+
ref: selectAllRef,
|
|
4251
|
+
type: "checkbox",
|
|
4252
|
+
checked: allFilteredSelected,
|
|
4253
|
+
onChange: (e) => handleToggleSelectAll(e.target.checked),
|
|
4254
|
+
className: "w-3.5 h-3.5 rounded border-slate-300 text-brand focus:ring-brand cursor-pointer accent-[#0d9488]"
|
|
4255
|
+
}
|
|
4256
|
+
),
|
|
4257
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u05D1\u05D7\u05E8 \u05D4\u05DB\u05DC" })
|
|
4258
|
+
] }),
|
|
4259
|
+
(mode === "exclude" || checkedSet.size > 0) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4260
|
+
"button",
|
|
4261
|
+
{
|
|
4262
|
+
type: "button",
|
|
4263
|
+
onClick: handleResetFilter,
|
|
4264
|
+
className: "text-[11px] text-blue-600 hover:text-blue-700 hover:underline flex items-center gap-1 cursor-pointer",
|
|
4265
|
+
title: "\u05E0\u05E7\u05D4 \u05E1\u05D9\u05E0\u05D5\u05DF \u05D5\u05D4\u05E6\u05D2 \u05D4\u05DB\u05DC",
|
|
4266
|
+
children: [
|
|
4267
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.RotateCcw, { className: "w-2.5 h-2.5" }),
|
|
4268
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u05E0\u05E7\u05D4" })
|
|
4269
|
+
]
|
|
4270
|
+
}
|
|
4271
|
+
)
|
|
4272
|
+
] }),
|
|
4273
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-h-[250px] overflow-y-auto space-y-0.5 custom-scrollbar pr-0.5", children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-center py-6 text-slate-400 text-xs", children: [
|
|
4274
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-4 h-4 border-2 border-brand border-t-transparent rounded-full animate-spin ml-2" }),
|
|
4275
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u05D8\u05D5\u05E2\u05DF \u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA..." })
|
|
4276
|
+
] }) : filteredOptions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "py-6 text-center text-xs text-slate-400", children: "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA" }) : filteredOptions.map((opt) => {
|
|
4277
|
+
const isChecked = isOptionChecked(opt.label);
|
|
4278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4279
|
+
"label",
|
|
4280
|
+
{
|
|
4281
|
+
className: `flex items-center gap-2 px-2 py-1 rounded cursor-pointer transition-colors text-xs ${isChecked ? "text-slate-800 font-medium bg-slate-50/60" : "text-slate-500 hover:bg-slate-50"}`,
|
|
4282
|
+
children: [
|
|
4283
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4284
|
+
"input",
|
|
4285
|
+
{
|
|
4286
|
+
type: "checkbox",
|
|
4287
|
+
checked: isChecked,
|
|
4288
|
+
onChange: () => handleToggleOption(opt.label),
|
|
4289
|
+
className: "w-3.5 h-3.5 rounded border-slate-300 text-brand focus:ring-brand cursor-pointer accent-[#0d9488]"
|
|
4290
|
+
}
|
|
4291
|
+
),
|
|
4292
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "truncate flex-1", title: opt.label, children: opt.label })
|
|
4293
|
+
]
|
|
4294
|
+
},
|
|
4295
|
+
opt.id
|
|
4296
|
+
);
|
|
4297
|
+
}) }),
|
|
4298
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "border-t border-slate-100 pt-1.5 mt-1 flex items-center justify-between text-[11px] text-slate-400 px-1", children: [
|
|
4299
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
|
|
4300
|
+
filteredOptions.length,
|
|
4301
|
+
" \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA"
|
|
4302
|
+
] }),
|
|
4303
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4304
|
+
"button",
|
|
4305
|
+
{
|
|
4306
|
+
type: "button",
|
|
4307
|
+
onClick: onClose,
|
|
4308
|
+
className: "text-slate-600 hover:text-slate-900 font-medium px-2 py-0.5 rounded hover:bg-slate-100 transition-colors cursor-pointer",
|
|
4309
|
+
children: "\u05E1\u05D2\u05D5\u05E8"
|
|
4310
|
+
}
|
|
4311
|
+
)
|
|
4312
|
+
] })
|
|
4313
|
+
]
|
|
4314
|
+
}
|
|
4315
|
+
);
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
// src/components/TableBlock/TableBlockClient.tsx
|
|
4319
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
3672
4320
|
function TableBlockClient({
|
|
3673
4321
|
data: initialRecords,
|
|
3674
4322
|
settings: schema,
|
|
3675
4323
|
executeAction,
|
|
4324
|
+
exportAction,
|
|
3676
4325
|
emitEvent,
|
|
3677
4326
|
pageState,
|
|
3678
4327
|
isLoading,
|
|
@@ -3685,6 +4334,7 @@ function TableBlockClient({
|
|
|
3685
4334
|
"data-testid": dataTestId
|
|
3686
4335
|
}) {
|
|
3687
4336
|
const { showError, addToast } = useToast();
|
|
4337
|
+
const [isExporting, setIsExporting] = (0, import_react14.useState)(false);
|
|
3688
4338
|
const tableKey = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id) || (schema == null ? void 0 : schema.name) || "default";
|
|
3689
4339
|
const { columnWidths, startResize } = useColumnResize({
|
|
3690
4340
|
storageKey: `table_widths_${tableKey}`,
|
|
@@ -3695,14 +4345,14 @@ function TableBlockClient({
|
|
|
3695
4345
|
return calculateMinColumnWidth(colName, false, col == null ? void 0 : col.type);
|
|
3696
4346
|
}
|
|
3697
4347
|
});
|
|
3698
|
-
const [isMounted, setIsMounted] = (0,
|
|
3699
|
-
const [isInitialLoading, setIsInitialLoading] = (0,
|
|
3700
|
-
const [page, setPage] = (0,
|
|
3701
|
-
const [limit, setLimit] = (0,
|
|
3702
|
-
const [totalRecords, setTotalRecords] = (0,
|
|
3703
|
-
const [totalPages, setTotalPages] = (0,
|
|
3704
|
-
const [showSummary, setShowSummary] = (0,
|
|
3705
|
-
(0,
|
|
4348
|
+
const [isMounted, setIsMounted] = (0, import_react14.useState)(false);
|
|
4349
|
+
const [isInitialLoading, setIsInitialLoading] = (0, import_react14.useState)(true);
|
|
4350
|
+
const [page, setPage] = (0, import_react14.useState)(1);
|
|
4351
|
+
const [limit, setLimit] = (0, import_react14.useState)(50);
|
|
4352
|
+
const [totalRecords, setTotalRecords] = (0, import_react14.useState)(0);
|
|
4353
|
+
const [totalPages, setTotalPages] = (0, import_react14.useState)(1);
|
|
4354
|
+
const [showSummary, setShowSummary] = (0, import_react14.useState)(false);
|
|
4355
|
+
(0, import_react14.useEffect)(() => {
|
|
3706
4356
|
if (typeof window !== "undefined") {
|
|
3707
4357
|
const savedSummary = localStorage.getItem(`table_summary_${tableKey}`);
|
|
3708
4358
|
if (savedSummary !== null) {
|
|
@@ -3751,7 +4401,7 @@ function TableBlockClient({
|
|
|
3751
4401
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
3752
4402
|
});
|
|
3753
4403
|
};
|
|
3754
|
-
const mergeColumnDefs = (0,
|
|
4404
|
+
const mergeColumnDefs = (0, import_react14.useCallback)((existingCols, incomingCols) => {
|
|
3755
4405
|
if (!incomingCols || incomingCols.length === 0) return existingCols || [];
|
|
3756
4406
|
if (!existingCols || existingCols.length === 0) return incomingCols;
|
|
3757
4407
|
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
@@ -3771,18 +4421,18 @@ function TableBlockClient({
|
|
|
3771
4421
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
3772
4422
|
});
|
|
3773
4423
|
}, []);
|
|
3774
|
-
const [localColumns, setLocalColumns] = (0,
|
|
3775
|
-
(0,
|
|
4424
|
+
const [localColumns, setLocalColumns] = (0, import_react14.useState)(() => (schema == null ? void 0 : schema.columns) || []);
|
|
4425
|
+
(0, import_react14.useEffect)(() => {
|
|
3776
4426
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
3777
4427
|
setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
|
|
3778
4428
|
}
|
|
3779
4429
|
}, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
|
|
3780
|
-
const [dirty, setDirty] = (0,
|
|
3781
|
-
const dirtyRef = (0,
|
|
3782
|
-
(0,
|
|
4430
|
+
const [dirty, setDirty] = (0, import_react14.useState)({ added: [], modified: {}, deleted: [] });
|
|
4431
|
+
const dirtyRef = (0, import_react14.useRef)(dirty);
|
|
4432
|
+
(0, import_react14.useEffect)(() => {
|
|
3783
4433
|
dirtyRef.current = dirty;
|
|
3784
4434
|
}, [dirty]);
|
|
3785
|
-
const mergeWithDirty = (0,
|
|
4435
|
+
const mergeWithDirty = (0, import_react14.useCallback)((baseRecords) => {
|
|
3786
4436
|
const { added, modified, deleted } = dirtyRef.current;
|
|
3787
4437
|
const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
|
|
3788
4438
|
const modifiedRecords = nonDeleted.map((r) => {
|
|
@@ -3795,9 +4445,9 @@ function TableBlockClient({
|
|
|
3795
4445
|
const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
|
|
3796
4446
|
return [...uniqueAdded, ...modifiedRecords];
|
|
3797
4447
|
}, []);
|
|
3798
|
-
const [data, setData] = (0,
|
|
3799
|
-
const [serverRecords, setServerRecords] = (0,
|
|
3800
|
-
(0,
|
|
4448
|
+
const [data, setData] = (0, import_react14.useState)(() => normalizeRecords(initialRecords));
|
|
4449
|
+
const [serverRecords, setServerRecords] = (0, import_react14.useState)(() => normalizeRecords(initialRecords));
|
|
4450
|
+
(0, import_react14.useEffect)(() => {
|
|
3801
4451
|
if (initialRecords) {
|
|
3802
4452
|
const norm = normalizeRecords(initialRecords);
|
|
3803
4453
|
setServerRecords(norm);
|
|
@@ -3814,25 +4464,109 @@ function TableBlockClient({
|
|
|
3814
4464
|
}
|
|
3815
4465
|
return false;
|
|
3816
4466
|
};
|
|
3817
|
-
const [baseRecordsMap, setBaseRecordsMap] = (0,
|
|
4467
|
+
const [baseRecordsMap, setBaseRecordsMap] = (0, import_react14.useState)(() => {
|
|
3818
4468
|
const map = /* @__PURE__ */ new Map();
|
|
3819
4469
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
3820
4470
|
return map;
|
|
3821
4471
|
});
|
|
3822
|
-
(0,
|
|
4472
|
+
(0, import_react14.useEffect)(() => {
|
|
3823
4473
|
if (initialRecords && initialRecords.length > 0) {
|
|
3824
4474
|
const map = /* @__PURE__ */ new Map();
|
|
3825
4475
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
3826
4476
|
setBaseRecordsMap(map);
|
|
3827
4477
|
}
|
|
3828
4478
|
}, [initialRecords]);
|
|
3829
|
-
const
|
|
4479
|
+
const [searchQuery, setSearchQuery] = (0, import_react14.useState)("");
|
|
4480
|
+
const [columnFilters, setColumnFilters] = (0, import_react14.useState)({});
|
|
4481
|
+
const [activeSearchCol, setActiveSearchCol] = (0, import_react14.useState)(null);
|
|
4482
|
+
const activeSearchRef = (0, import_react14.useRef)(null);
|
|
4483
|
+
const [activeRelationCol, setActiveRelationCol] = (0, import_react14.useState)(null);
|
|
4484
|
+
const [relationTriggerRect, setRelationTriggerRect] = (0, import_react14.useState)(null);
|
|
4485
|
+
const filterButtonRefs = (0, import_react14.useRef)({});
|
|
4486
|
+
const [relationOptions, setRelationOptions] = (0, import_react14.useState)({});
|
|
4487
|
+
const relationDictionaryRef = (0, import_react14.useRef)({});
|
|
4488
|
+
const mergeRelationOptions = (0, import_react14.useCallback)((colName, newOptions) => {
|
|
4489
|
+
if (!Array.isArray(newOptions) || newOptions.length === 0) return;
|
|
4490
|
+
if (!relationDictionaryRef.current[colName]) {
|
|
4491
|
+
relationDictionaryRef.current[colName] = /* @__PURE__ */ new Map();
|
|
4492
|
+
}
|
|
4493
|
+
const dict = relationDictionaryRef.current[colName];
|
|
4494
|
+
let hasNew = false;
|
|
4495
|
+
for (const opt of newOptions) {
|
|
4496
|
+
if (!opt) continue;
|
|
4497
|
+
const id = String(opt.id || opt._id || "");
|
|
4498
|
+
if (!id) continue;
|
|
4499
|
+
const existing = dict.get(id);
|
|
4500
|
+
if (!existing || opt.label && !existing.label) {
|
|
4501
|
+
dict.set(id, opt);
|
|
4502
|
+
hasNew = true;
|
|
4503
|
+
}
|
|
4504
|
+
}
|
|
4505
|
+
if (hasNew) {
|
|
4506
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4507
|
+
[colName]: Array.from(dict.values())
|
|
4508
|
+
}));
|
|
4509
|
+
}
|
|
4510
|
+
}, []);
|
|
4511
|
+
(0, import_react14.useEffect)(() => {
|
|
4512
|
+
if (!activeSearchCol) return;
|
|
4513
|
+
const handleMouseDown = (e) => {
|
|
4514
|
+
if (activeSearchRef.current && !activeSearchRef.current.contains(e.target)) {
|
|
4515
|
+
setActiveSearchCol(null);
|
|
4516
|
+
}
|
|
4517
|
+
};
|
|
4518
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4519
|
+
return () => {
|
|
4520
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
4521
|
+
};
|
|
4522
|
+
}, [activeSearchCol]);
|
|
4523
|
+
const filtersKey = (0, import_react14.useMemo)(() => {
|
|
4524
|
+
const active = {};
|
|
4525
|
+
Object.entries(columnFilters).forEach(([k, v]) => {
|
|
4526
|
+
if (Array.isArray(v) && v.length > 0) active[k] = v;
|
|
4527
|
+
else if (v && typeof v === "object" && "operator" in v && Array.isArray(v.values) && v.values.length > 0) active[k] = v;
|
|
4528
|
+
else if (typeof v === "string" && v.trim()) active[k] = v.trim();
|
|
4529
|
+
});
|
|
4530
|
+
return JSON.stringify(active);
|
|
4531
|
+
}, [columnFilters]);
|
|
4532
|
+
const [debouncedSearch, setDebouncedSearch] = (0, import_react14.useState)(searchQuery);
|
|
4533
|
+
(0, import_react14.useEffect)(() => {
|
|
4534
|
+
const timer = setTimeout(() => {
|
|
4535
|
+
setDebouncedSearch(searchQuery.trim());
|
|
4536
|
+
}, 300);
|
|
4537
|
+
return () => clearTimeout(timer);
|
|
4538
|
+
}, [searchQuery]);
|
|
4539
|
+
const isSearchMountedRef = (0, import_react14.useRef)(false);
|
|
4540
|
+
(0, import_react14.useEffect)(() => {
|
|
4541
|
+
if (!isSearchMountedRef.current) {
|
|
4542
|
+
isSearchMountedRef.current = true;
|
|
4543
|
+
return;
|
|
4544
|
+
}
|
|
4545
|
+
setPage(1);
|
|
4546
|
+
}, [debouncedSearch]);
|
|
4547
|
+
const [isFetching, setIsFetching] = (0, import_react14.useState)(false);
|
|
4548
|
+
const fetchRequestIdRef = (0, import_react14.useRef)(0);
|
|
4549
|
+
const fetchTableData = (0, import_react14.useCallback)((targetPage, targetLimit, targetSearch, targetFiltersKey) => {
|
|
3830
4550
|
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
3831
4551
|
if (!tableId || !executeAction) return Promise.resolve();
|
|
3832
|
-
const
|
|
3833
|
-
|
|
3834
|
-
|
|
4552
|
+
const currentRequestId = ++fetchRequestIdRef.current;
|
|
4553
|
+
setIsFetching(true);
|
|
4554
|
+
let activeFilters = {};
|
|
4555
|
+
try {
|
|
4556
|
+
activeFilters = JSON.parse(targetFiltersKey);
|
|
4557
|
+
} catch (e) {
|
|
4558
|
+
}
|
|
4559
|
+
const skip = (targetPage - 1) * targetLimit;
|
|
4560
|
+
return executeAction("FETCH_TABLE_DATA", {
|
|
4561
|
+
tableId,
|
|
4562
|
+
page: targetPage,
|
|
4563
|
+
limit: targetLimit,
|
|
4564
|
+
skip,
|
|
4565
|
+
search: targetSearch || void 0,
|
|
4566
|
+
columnFilters: Object.keys(activeFilters).length > 0 ? activeFilters : void 0
|
|
4567
|
+
}).then((res) => {
|
|
3835
4568
|
var _a;
|
|
4569
|
+
if (currentRequestId !== fetchRequestIdRef.current) return;
|
|
3836
4570
|
if (res) {
|
|
3837
4571
|
if (((_a = res.schema) == null ? void 0 : _a.columns) && res.schema.columns.length > 0) {
|
|
3838
4572
|
setLocalColumns((prev) => mergeColumnDefs(prev, res.schema.columns));
|
|
@@ -3847,37 +4581,50 @@ function TableBlockClient({
|
|
|
3847
4581
|
}
|
|
3848
4582
|
if (res.meta) {
|
|
3849
4583
|
const total = typeof res.meta.totalRecords === "number" ? res.meta.totalRecords : 0;
|
|
3850
|
-
const pages = typeof res.meta.totalPages === "number" ? res.meta.totalPages : Math.ceil(total /
|
|
4584
|
+
const pages = typeof res.meta.totalPages === "number" ? res.meta.totalPages : Math.ceil(total / targetLimit) || 1;
|
|
3851
4585
|
setTotalRecords(total);
|
|
3852
4586
|
setTotalPages(pages);
|
|
3853
|
-
if (activePage > pages && pages >= 1) {
|
|
3854
|
-
setPage(pages);
|
|
3855
|
-
}
|
|
3856
4587
|
} else if (res.records && Array.isArray(res.records)) {
|
|
3857
4588
|
setTotalRecords(res.records.length);
|
|
3858
|
-
setTotalPages(Math.ceil(res.records.length /
|
|
4589
|
+
setTotalPages(Math.ceil(res.records.length / targetLimit) || 1);
|
|
4590
|
+
}
|
|
4591
|
+
if (res.relationOptions && typeof res.relationOptions === "object") {
|
|
4592
|
+
for (const [colName, opts] of Object.entries(res.relationOptions)) {
|
|
4593
|
+
if (Array.isArray(opts)) {
|
|
4594
|
+
mergeRelationOptions(colName, opts);
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
3859
4597
|
}
|
|
3860
4598
|
}
|
|
3861
4599
|
}).catch((err) => {
|
|
3862
|
-
|
|
4600
|
+
if (currentRequestId === fetchRequestIdRef.current) {
|
|
4601
|
+
console.error("[TableBlock] Failed to fetch table data:", err);
|
|
4602
|
+
}
|
|
4603
|
+
}).finally(() => {
|
|
4604
|
+
if (currentRequestId === fetchRequestIdRef.current) {
|
|
4605
|
+
setIsFetching(false);
|
|
4606
|
+
setIsInitialLoading(false);
|
|
4607
|
+
}
|
|
3863
4608
|
});
|
|
3864
|
-
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id,
|
|
3865
|
-
(0,
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
});
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
4609
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, executeAction, mergeColumnDefs, mergeWithDirty, mergeRelationOptions]);
|
|
4610
|
+
(0, import_react14.useEffect)(() => {
|
|
4611
|
+
fetchTableData(page, limit, debouncedSearch, filtersKey);
|
|
4612
|
+
}, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
|
|
4613
|
+
const refetchTableData = (0, import_react14.useCallback)(() => {
|
|
4614
|
+
return fetchTableData(page, limit, debouncedSearch, filtersKey);
|
|
4615
|
+
}, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
|
|
4616
|
+
const handleApplyColumnFilter = (0, import_react14.useCallback)((colName, nextVal) => {
|
|
4617
|
+
setColumnFilters((prev) => {
|
|
4618
|
+
const next = __spreadValues({}, prev);
|
|
4619
|
+
if (nextVal === void 0 || Array.isArray(nextVal) && nextVal.length === 0 || typeof nextVal === "string" && !nextVal.trim() || typeof nextVal === "object" && "values" in nextVal && Array.isArray(nextVal.values) && nextVal.values.length === 0) {
|
|
4620
|
+
delete next[colName];
|
|
4621
|
+
} else {
|
|
4622
|
+
next[colName] = nextVal;
|
|
4623
|
+
}
|
|
4624
|
+
return next;
|
|
4625
|
+
});
|
|
4626
|
+
setPage(1);
|
|
4627
|
+
}, []);
|
|
3881
4628
|
const handleLimitChange = (newLimit) => {
|
|
3882
4629
|
setLimit(newLimit);
|
|
3883
4630
|
setPage(1);
|
|
@@ -3891,37 +4638,15 @@ function TableBlockClient({
|
|
|
3891
4638
|
const handleNextPage = () => {
|
|
3892
4639
|
setPage((prev) => Math.min(totalPages, prev + 1));
|
|
3893
4640
|
};
|
|
3894
|
-
(0,
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
}
|
|
3898
|
-
}, [error, showError]);
|
|
3899
|
-
const [searchQuery, setSearchQuery] = (0, import_react12.useState)("");
|
|
3900
|
-
const [columnFilters, setColumnFilters] = (0, import_react12.useState)({});
|
|
3901
|
-
const [activeSearchCol, setActiveSearchCol] = (0, import_react12.useState)(null);
|
|
3902
|
-
const activeSearchRef = (0, import_react12.useRef)(null);
|
|
3903
|
-
(0, import_react12.useEffect)(() => {
|
|
3904
|
-
if (!activeSearchCol) return;
|
|
3905
|
-
const handleMouseDown = (e) => {
|
|
3906
|
-
if (activeSearchRef.current && !activeSearchRef.current.contains(e.target)) {
|
|
3907
|
-
setActiveSearchCol(null);
|
|
3908
|
-
}
|
|
3909
|
-
};
|
|
3910
|
-
document.addEventListener("mousedown", handleMouseDown);
|
|
3911
|
-
return () => {
|
|
3912
|
-
document.removeEventListener("mousedown", handleMouseDown);
|
|
3913
|
-
};
|
|
3914
|
-
}, [activeSearchCol]);
|
|
3915
|
-
const [selectedIds, setSelectedIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
|
|
3916
|
-
const [pendingDeletions, setPendingDeletions] = (0, import_react12.useState)([]);
|
|
3917
|
-
const [isSaving, setIsSaving] = (0, import_react12.useState)(false);
|
|
4641
|
+
const [selectedIds, setSelectedIds] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
|
|
4642
|
+
const [pendingDeletions, setPendingDeletions] = (0, import_react14.useState)([]);
|
|
4643
|
+
const [isSaving, setIsSaving] = (0, import_react14.useState)(false);
|
|
3918
4644
|
const isUpdatingActive = Boolean(isUpdating || isSaving);
|
|
3919
|
-
const [isSaveSuccess, setIsSaveSuccess] = (0,
|
|
3920
|
-
const [
|
|
3921
|
-
const
|
|
3922
|
-
const
|
|
3923
|
-
|
|
3924
|
-
var _a, _b, _c;
|
|
4645
|
+
const [isSaveSuccess, setIsSaveSuccess] = (0, import_react14.useState)(false);
|
|
4646
|
+
const [expandedRowIds, setExpandedRowIds] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
|
|
4647
|
+
const schemaColsString = (0, import_react14.useMemo)(() => JSON.stringify(localColumns || []), [localColumns]);
|
|
4648
|
+
const refetchRelation = (0, import_react14.useCallback)(async (colName, params) => {
|
|
4649
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3925
4650
|
let parsedCols = [];
|
|
3926
4651
|
try {
|
|
3927
4652
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -3931,19 +4656,89 @@ function TableBlockClient({
|
|
|
3931
4656
|
var _a2;
|
|
3932
4657
|
return c.name === colName && ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION";
|
|
3933
4658
|
});
|
|
3934
|
-
if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId)) return;
|
|
4659
|
+
if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId)) return [];
|
|
3935
4660
|
try {
|
|
3936
4661
|
if (executeAction) {
|
|
3937
|
-
const
|
|
3938
|
-
|
|
3939
|
-
|
|
4662
|
+
const take = (_c = (_b = params == null ? void 0 : params.take) != null ? _b : params == null ? void 0 : params.limit) != null ? _c : 1e3;
|
|
4663
|
+
const payload = {
|
|
4664
|
+
referencedTableId: (_d = col.config) == null ? void 0 : _d.referencedTableId,
|
|
4665
|
+
displayField: (_e = col.config) == null ? void 0 : _e.displayField
|
|
4666
|
+
};
|
|
4667
|
+
if (params == null ? void 0 : params.recordIds) {
|
|
4668
|
+
payload.recordIds = params.recordIds;
|
|
4669
|
+
} else {
|
|
4670
|
+
payload.take = take;
|
|
4671
|
+
payload.limit = take;
|
|
4672
|
+
payload.skip = (_f = params == null ? void 0 : params.skip) != null ? _f : 0;
|
|
4673
|
+
payload.search = (_g = params == null ? void 0 : params.search) != null ? _g : "";
|
|
4674
|
+
}
|
|
4675
|
+
const options = await executeAction("FETCH_RELATION", payload);
|
|
4676
|
+
const list = Array.isArray(options) ? options : (options == null ? void 0 : options.data) && Array.isArray(options.data) ? options.data : [];
|
|
4677
|
+
if (list && Array.isArray(list)) {
|
|
4678
|
+
mergeRelationOptions(colName, list);
|
|
4679
|
+
return list;
|
|
3940
4680
|
}
|
|
3941
4681
|
}
|
|
3942
4682
|
} catch (err) {
|
|
3943
4683
|
console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
|
|
3944
4684
|
}
|
|
3945
|
-
|
|
3946
|
-
|
|
4685
|
+
return [];
|
|
4686
|
+
}, [schemaColsString, executeAction, mergeRelationOptions]);
|
|
4687
|
+
const requestedRelationIdsRef = (0, import_react14.useRef)({});
|
|
4688
|
+
(0, import_react14.useEffect)(() => {
|
|
4689
|
+
if (!executeAction || !data || data.length === 0) return;
|
|
4690
|
+
let parsedCols = [];
|
|
4691
|
+
try {
|
|
4692
|
+
parsedCols = JSON.parse(schemaColsString);
|
|
4693
|
+
} catch (e) {
|
|
4694
|
+
}
|
|
4695
|
+
const relationCols = parsedCols.filter(
|
|
4696
|
+
(c) => {
|
|
4697
|
+
var _a;
|
|
4698
|
+
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
|
|
4699
|
+
}
|
|
4700
|
+
);
|
|
4701
|
+
if (relationCols.length === 0) return;
|
|
4702
|
+
relationCols.forEach(async (col) => {
|
|
4703
|
+
var _a, _b;
|
|
4704
|
+
const referencedTableId = (_a = col.config) == null ? void 0 : _a.referencedTableId;
|
|
4705
|
+
if (!referencedTableId) return;
|
|
4706
|
+
const extractedIds = /* @__PURE__ */ new Set();
|
|
4707
|
+
data.forEach((row) => {
|
|
4708
|
+
if (!(row == null ? void 0 : row.data)) return;
|
|
4709
|
+
const ids = normalizeRelationValue(row.data[col.name]);
|
|
4710
|
+
ids.forEach((id) => {
|
|
4711
|
+
if (/^[0-9a-fA-F]{24}$/.test(id)) {
|
|
4712
|
+
extractedIds.add(id);
|
|
4713
|
+
}
|
|
4714
|
+
});
|
|
4715
|
+
});
|
|
4716
|
+
if (extractedIds.size === 0) return;
|
|
4717
|
+
const existingOptions = relationOptions[col.name] || [];
|
|
4718
|
+
const existingIds = new Set(existingOptions.map((o) => String(o.id)));
|
|
4719
|
+
if (!requestedRelationIdsRef.current[col.name]) {
|
|
4720
|
+
requestedRelationIdsRef.current[col.name] = /* @__PURE__ */ new Set();
|
|
4721
|
+
}
|
|
4722
|
+
const inFlight = requestedRelationIdsRef.current[col.name];
|
|
4723
|
+
const missingIds = Array.from(extractedIds).filter((id) => !existingIds.has(id) && !inFlight.has(id));
|
|
4724
|
+
if (missingIds.length === 0) return;
|
|
4725
|
+
missingIds.forEach((id) => inFlight.add(id));
|
|
4726
|
+
try {
|
|
4727
|
+
const resolved = await executeAction("FETCH_RELATION", {
|
|
4728
|
+
referencedTableId,
|
|
4729
|
+
displayField: (_b = col.config) == null ? void 0 : _b.displayField,
|
|
4730
|
+
recordIds: missingIds
|
|
4731
|
+
});
|
|
4732
|
+
const items = Array.isArray(resolved) ? resolved : (resolved == null ? void 0 : resolved.data) && Array.isArray(resolved.data) ? resolved.data : [];
|
|
4733
|
+
if (items.length > 0) {
|
|
4734
|
+
mergeRelationOptions(col.name, items);
|
|
4735
|
+
}
|
|
4736
|
+
} catch (err) {
|
|
4737
|
+
console.warn(`[TableBlock] Failed to populate relations for ${col.name}:`, err);
|
|
4738
|
+
}
|
|
4739
|
+
});
|
|
4740
|
+
}, [data, schemaColsString, executeAction, relationOptions, mergeRelationOptions]);
|
|
4741
|
+
(0, import_react14.useEffect)(() => {
|
|
3947
4742
|
let parsedCols = [];
|
|
3948
4743
|
try {
|
|
3949
4744
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -3957,7 +4752,7 @@ function TableBlockClient({
|
|
|
3957
4752
|
refetchRelation(col.name);
|
|
3958
4753
|
});
|
|
3959
4754
|
}, [schemaColsString, refetchRelation]);
|
|
3960
|
-
const normalizedColumns = (0,
|
|
4755
|
+
const normalizedColumns = (0, import_react14.useMemo)(() => {
|
|
3961
4756
|
return (localColumns || []).map((col, idx) => {
|
|
3962
4757
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
3963
4758
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
@@ -3971,17 +4766,17 @@ function TableBlockClient({
|
|
|
3971
4766
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
3972
4767
|
});
|
|
3973
4768
|
}, [localColumns]);
|
|
3974
|
-
const filteredColumns = (0,
|
|
4769
|
+
const filteredColumns = (0, import_react14.useMemo)(() => {
|
|
3975
4770
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
3976
4771
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
|
|
3977
4772
|
}, [normalizedColumns]);
|
|
3978
|
-
const customizableColumns = (0,
|
|
4773
|
+
const customizableColumns = (0, import_react14.useMemo)(() => {
|
|
3979
4774
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
3980
4775
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name));
|
|
3981
4776
|
}, [normalizedColumns]);
|
|
3982
|
-
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0,
|
|
3983
|
-
const dropdownRef = (0,
|
|
3984
|
-
(0,
|
|
4777
|
+
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0, import_react14.useState)(false);
|
|
4778
|
+
const dropdownRef = (0, import_react14.useRef)(null);
|
|
4779
|
+
(0, import_react14.useEffect)(() => {
|
|
3985
4780
|
const handleClickOutside = (e) => {
|
|
3986
4781
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
3987
4782
|
setIsColumnsDropdownOpen(false);
|
|
@@ -4224,13 +5019,13 @@ function TableBlockClient({
|
|
|
4224
5019
|
});
|
|
4225
5020
|
}
|
|
4226
5021
|
};
|
|
4227
|
-
const triggerSaveSuccess = (0,
|
|
5022
|
+
const triggerSaveSuccess = (0, import_react14.useCallback)(() => {
|
|
4228
5023
|
setIsSaveSuccess(true);
|
|
4229
5024
|
setTimeout(() => {
|
|
4230
5025
|
setIsSaveSuccess(false);
|
|
4231
5026
|
}, 2500);
|
|
4232
5027
|
}, []);
|
|
4233
|
-
const handleQuietCellChange = (0,
|
|
5028
|
+
const handleQuietCellChange = (0, import_react14.useCallback)((rowId, colName, value) => {
|
|
4234
5029
|
setData((prev) => prev.map(
|
|
4235
5030
|
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
4236
5031
|
));
|
|
@@ -4498,7 +5293,7 @@ function TableBlockClient({
|
|
|
4498
5293
|
setIsSaving(false);
|
|
4499
5294
|
}
|
|
4500
5295
|
};
|
|
4501
|
-
const getRowRelationLabels = (0,
|
|
5296
|
+
const getRowRelationLabels = (0, import_react14.useCallback)((rowVal, col) => {
|
|
4502
5297
|
const ids = normalizeRelationValue(rowVal);
|
|
4503
5298
|
if (ids.length === 0) return [];
|
|
4504
5299
|
const options = relationOptions[col.name] || [];
|
|
@@ -4506,21 +5301,38 @@ function TableBlockClient({
|
|
|
4506
5301
|
const opt = options.find((o) => o.id === id || o._id === id);
|
|
4507
5302
|
if (opt) {
|
|
4508
5303
|
const resolved = resolveRelationLabel(opt, col);
|
|
4509
|
-
if (resolved) return resolved;
|
|
4510
|
-
if (opt.label) return String(opt.label);
|
|
4511
|
-
if (opt.name) return String(opt.name);
|
|
5304
|
+
if (resolved && !isRawObjectId(resolved)) return resolved;
|
|
5305
|
+
if (opt.label && !isRawObjectId(String(opt.label))) return String(opt.label);
|
|
5306
|
+
if (opt.name && !isRawObjectId(String(opt.name))) return String(opt.name);
|
|
4512
5307
|
}
|
|
4513
5308
|
if (typeof rowVal === "object" && rowVal !== null) {
|
|
4514
|
-
if (rowVal._displayLabel) return String(rowVal._displayLabel);
|
|
4515
|
-
if (rowVal.label) return String(rowVal.label);
|
|
5309
|
+
if (rowVal._displayLabel && !isRawObjectId(String(rowVal._displayLabel))) return String(rowVal._displayLabel);
|
|
5310
|
+
if (rowVal.label && !isRawObjectId(String(rowVal.label))) return String(rowVal.label);
|
|
4516
5311
|
}
|
|
4517
|
-
return
|
|
4518
|
-
});
|
|
5312
|
+
return "";
|
|
5313
|
+
}).filter(Boolean);
|
|
4519
5314
|
}, [relationOptions]);
|
|
4520
|
-
const getUniqueRelationOptions = (0,
|
|
5315
|
+
const getUniqueRelationOptions = (0, import_react14.useCallback)((col) => {
|
|
4521
5316
|
const seenIds = /* @__PURE__ */ new Set();
|
|
5317
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
4522
5318
|
const results = [];
|
|
4523
5319
|
const options = relationOptions[col.name] || [];
|
|
5320
|
+
options.forEach((opt) => {
|
|
5321
|
+
const id = String(opt.id || opt._id || "");
|
|
5322
|
+
if (!id) return;
|
|
5323
|
+
let label = resolveRelationLabel(opt, col);
|
|
5324
|
+
if (!label) {
|
|
5325
|
+
const fallback = opt.label || opt.name || opt.title;
|
|
5326
|
+
if (fallback && typeof fallback === "string" && !isRawObjectId(fallback)) {
|
|
5327
|
+
label = fallback.trim();
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
if (label && label.trim() && !isRawObjectId(label) && !seenLabels.has(label.trim())) {
|
|
5331
|
+
seenIds.add(id);
|
|
5332
|
+
seenLabels.add(label.trim());
|
|
5333
|
+
results.push({ id, label: label.trim() });
|
|
5334
|
+
}
|
|
5335
|
+
});
|
|
4524
5336
|
data.forEach((row) => {
|
|
4525
5337
|
if (!(row == null ? void 0 : row.data)) return;
|
|
4526
5338
|
const ids = normalizeRelationValue(row.data[col.name]);
|
|
@@ -4529,58 +5341,24 @@ function TableBlockClient({
|
|
|
4529
5341
|
seenIds.add(id);
|
|
4530
5342
|
const opt = options.find((o) => o.id === id || o._id === id);
|
|
4531
5343
|
let label = opt ? resolveRelationLabel(opt, col) : "";
|
|
4532
|
-
if (!label && opt)
|
|
4533
|
-
|
|
4534
|
-
|
|
5344
|
+
if (!label && opt) {
|
|
5345
|
+
const fallback = opt.label || opt.name || opt.title;
|
|
5346
|
+
if (fallback && typeof fallback === "string" && !isRawObjectId(fallback)) {
|
|
5347
|
+
label = fallback.trim();
|
|
5348
|
+
}
|
|
5349
|
+
}
|
|
5350
|
+
if (label && label.trim() && label !== id && !isRawObjectId(label) && !seenLabels.has(label.trim())) {
|
|
5351
|
+
seenLabels.add(label.trim());
|
|
5352
|
+
results.push({ id, label: label.trim() });
|
|
5353
|
+
}
|
|
4535
5354
|
}
|
|
4536
5355
|
});
|
|
4537
5356
|
});
|
|
4538
5357
|
return results.sort((a, b) => a.label.localeCompare(b.label));
|
|
4539
5358
|
}, [data, relationOptions]);
|
|
4540
|
-
const filteredData =
|
|
4541
|
-
const hasGlobalSearch = Boolean(searchQuery && searchQuery.trim() !== "");
|
|
4542
|
-
const activeFilters = Object.entries(columnFilters).filter(([, val]) => Boolean(val && val.trim() !== ""));
|
|
4543
|
-
const hasColumnFilters = activeFilters.length > 0;
|
|
4544
|
-
if (!hasGlobalSearch && !hasColumnFilters) return data;
|
|
4545
|
-
const lowerGlobal = hasGlobalSearch ? searchQuery.trim().toLowerCase() : "";
|
|
4546
|
-
return data.filter((row) => {
|
|
4547
|
-
var _a;
|
|
4548
|
-
if (!row || !row.data) return false;
|
|
4549
|
-
if (hasGlobalSearch) {
|
|
4550
|
-
const matchesGlobal = (localColumns || []).some((col) => {
|
|
4551
|
-
var _a2;
|
|
4552
|
-
const rawVal = row.data[col.name];
|
|
4553
|
-
if (rawVal === void 0 || rawVal === null) return false;
|
|
4554
|
-
if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION") {
|
|
4555
|
-
const labels = getRowRelationLabels(rawVal, col);
|
|
4556
|
-
return labels.some((l) => l.toLowerCase().includes(lowerGlobal));
|
|
4557
|
-
}
|
|
4558
|
-
if (typeof rawVal === "object") {
|
|
4559
|
-
return JSON.stringify(rawVal).toLowerCase().includes(lowerGlobal);
|
|
4560
|
-
}
|
|
4561
|
-
return String(rawVal).toLowerCase().includes(lowerGlobal);
|
|
4562
|
-
});
|
|
4563
|
-
if (!matchesGlobal) return false;
|
|
4564
|
-
}
|
|
4565
|
-
for (const [colName, filterVal] of activeFilters) {
|
|
4566
|
-
const lowerFilter = filterVal.trim().toLowerCase();
|
|
4567
|
-
const col = (localColumns || []).find((c) => c.name === colName);
|
|
4568
|
-
const rawVal = row.data[colName];
|
|
4569
|
-
if (((_a = col == null ? void 0 : col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION") {
|
|
4570
|
-
const labels = getRowRelationLabels(rawVal, col);
|
|
4571
|
-
const matches = labels.some((l) => l.toLowerCase().includes(lowerFilter));
|
|
4572
|
-
if (!matches) return false;
|
|
4573
|
-
} else {
|
|
4574
|
-
if (rawVal === void 0 || rawVal === null) return false;
|
|
4575
|
-
const strVal = typeof rawVal === "object" ? JSON.stringify(rawVal).toLowerCase() : String(rawVal).toLowerCase();
|
|
4576
|
-
if (!strVal.includes(lowerFilter)) return false;
|
|
4577
|
-
}
|
|
4578
|
-
}
|
|
4579
|
-
return true;
|
|
4580
|
-
});
|
|
4581
|
-
}, [data, searchQuery, columnFilters, localColumns, getRowRelationLabels]);
|
|
5359
|
+
const filteredData = data;
|
|
4582
5360
|
const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
|
|
4583
|
-
const columnTotals = (0,
|
|
5361
|
+
const columnTotals = (0, import_react14.useMemo)(() => {
|
|
4584
5362
|
const totals = {};
|
|
4585
5363
|
if (!showSummary) return totals;
|
|
4586
5364
|
filteredColumns.forEach((col) => {
|
|
@@ -4598,42 +5376,120 @@ function TableBlockClient({
|
|
|
4598
5376
|
});
|
|
4599
5377
|
return totals;
|
|
4600
5378
|
}, [filteredData, filteredColumns, showSummary]);
|
|
4601
|
-
|
|
5379
|
+
const hasSelectedRows = selectedIds.size > 0;
|
|
5380
|
+
const hasActiveSearchOrFilter = Boolean(searchQuery && searchQuery.trim() !== "") || Object.values(columnFilters).some(
|
|
5381
|
+
(v) => Array.isArray(v) ? v.length > 0 : v && typeof v === "object" && "values" in v ? v.values.length > 0 : typeof v === "string" && Boolean(v.trim())
|
|
5382
|
+
);
|
|
5383
|
+
let exportButtonText = "\u05D9\u05D9\u05E6\u05D0 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD";
|
|
5384
|
+
let ExportButtonIcon = import_lucide_react8.Download;
|
|
5385
|
+
if (hasSelectedRows) {
|
|
5386
|
+
exportButtonText = `\u05D9\u05D9\u05E6\u05D0 ${selectedIds.size} \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA`;
|
|
5387
|
+
ExportButtonIcon = import_lucide_react8.Download;
|
|
5388
|
+
} else if (hasActiveSearchOrFilter) {
|
|
5389
|
+
exportButtonText = "\u05D9\u05D9\u05E6\u05D0 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E1\u05D9\u05E0\u05D5\u05DF";
|
|
5390
|
+
ExportButtonIcon = import_lucide_react8.Filter;
|
|
5391
|
+
}
|
|
5392
|
+
const handleExportCsv = async () => {
|
|
5393
|
+
if (isExporting) return;
|
|
5394
|
+
const systemFields = ["_id", "id", "createdAt", "updatedAt", "createdBy", "updatedBy", "orgId", "tableId"];
|
|
5395
|
+
const userHiddenColumns = normalizedColumns.filter((c) => c.isHidden && !systemFields.includes(c.name)).map((c) => c.name);
|
|
5396
|
+
if (userHiddenColumns.length > 0) {
|
|
5397
|
+
addToast({
|
|
5398
|
+
message: "\u05DE\u05D9\u05D9\u05E6\u05D0 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD... \u05E9\u05D9\u05DD \u05DC\u05D1: \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA \u05DE\u05D5\u05E1\u05EA\u05E8\u05D5\u05EA \u05DC\u05D0 \u05D9\u05D9\u05DB\u05DC\u05DC\u05D5 \u05D1\u05E7\u05D5\u05D1\u05E5",
|
|
5399
|
+
type: "info",
|
|
5400
|
+
duration: 3e3
|
|
5401
|
+
});
|
|
5402
|
+
} else {
|
|
5403
|
+
addToast({
|
|
5404
|
+
message: "\u05DE\u05D9\u05D9\u05E6\u05D0 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD...",
|
|
5405
|
+
type: "info",
|
|
5406
|
+
duration: 3e3
|
|
5407
|
+
});
|
|
5408
|
+
}
|
|
5409
|
+
setIsExporting(true);
|
|
5410
|
+
try {
|
|
5411
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
5412
|
+
if (!targetTableId) {
|
|
5413
|
+
showError("\u05DE\u05D6\u05D4\u05D4 \u05D4\u05D8\u05D1\u05DC\u05D4 \u05D7\u05E1\u05E8 (tableId)", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D9\u05D9\u05E6\u05D5\u05D0");
|
|
5414
|
+
return;
|
|
5415
|
+
}
|
|
5416
|
+
const payload = {
|
|
5417
|
+
tableId: targetTableId,
|
|
5418
|
+
orgId,
|
|
5419
|
+
search: searchQuery.trim() || void 0,
|
|
5420
|
+
columnFilters: Object.keys(columnFilters).length > 0 ? columnFilters : void 0,
|
|
5421
|
+
selectedRowIds: hasSelectedRows ? Array.from(selectedIds) : [],
|
|
5422
|
+
hiddenColumnIds: userHiddenColumns
|
|
5423
|
+
};
|
|
5424
|
+
let res;
|
|
5425
|
+
if (exportAction) {
|
|
5426
|
+
res = await exportAction(payload);
|
|
5427
|
+
} else if (executeAction) {
|
|
5428
|
+
res = await executeAction("EXPORT_TABLE_TO_CSV", payload);
|
|
5429
|
+
} else {
|
|
5430
|
+
throw new Error("\u05E8\u05DB\u05D9\u05D1 \u05D4\u05EA\u05E7\u05E9\u05D5\u05E8\u05EA \u05DC\u05D0 \u05D0\u05D5\u05EA\u05D7\u05DC");
|
|
5431
|
+
}
|
|
5432
|
+
const result = (res == null ? void 0 : res.data) || res;
|
|
5433
|
+
if ((result == null ? void 0 : result.success) === false) {
|
|
5434
|
+
throw new Error(result.error || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D9\u05D9\u05E6\u05D5\u05D0 \u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD");
|
|
5435
|
+
}
|
|
5436
|
+
const csvString = (result == null ? void 0 : result.csvString) || (result == null ? void 0 : result.csv);
|
|
5437
|
+
if (!csvString) {
|
|
5438
|
+
throw new Error("\u05DC\u05D0 \u05D4\u05EA\u05E7\u05D1\u05DC\u05D5 \u05E0\u05EA\u05D5\u05E0\u05D9 CSV \u05DE\u05D4\u05E9\u05E8\u05EA");
|
|
5439
|
+
}
|
|
5440
|
+
const fileName = (result == null ? void 0 : result.fileName) || `${((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name) || "table").trim()}_export.csv`;
|
|
5441
|
+
const blob = new Blob([csvString], { type: "text/csv;charset=utf-8;" });
|
|
5442
|
+
const url = URL.createObjectURL(blob);
|
|
5443
|
+
const link = document.createElement("a");
|
|
5444
|
+
link.href = url;
|
|
5445
|
+
link.setAttribute("download", fileName);
|
|
5446
|
+
document.body.appendChild(link);
|
|
5447
|
+
link.click();
|
|
5448
|
+
document.body.removeChild(link);
|
|
5449
|
+
URL.revokeObjectURL(url);
|
|
5450
|
+
} catch (err) {
|
|
5451
|
+
console.error("[TableBlock] Export to CSV failed:", err);
|
|
5452
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D9\u05D9\u05E6\u05D5\u05D0 \u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD");
|
|
5453
|
+
} finally {
|
|
5454
|
+
setIsExporting(false);
|
|
5455
|
+
}
|
|
5456
|
+
};
|
|
5457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4602
5458
|
"div",
|
|
4603
5459
|
{
|
|
4604
5460
|
id: componentId,
|
|
4605
5461
|
"data-testid": dataTestId || (componentId ? `table-block-${componentId}` : void 0),
|
|
4606
|
-
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-
|
|
5462
|
+
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs flex-1 min-h-0 overflow-hidden ${className}`,
|
|
4607
5463
|
dir: "rtl",
|
|
4608
5464
|
children: [
|
|
4609
|
-
errorMessage && /* @__PURE__ */ (0,
|
|
4610
|
-
/* @__PURE__ */ (0,
|
|
4611
|
-
/* @__PURE__ */ (0,
|
|
5465
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5466
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
5467
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: errorMessage })
|
|
4612
5468
|
] }) }),
|
|
4613
|
-
/* @__PURE__ */ (0,
|
|
4614
|
-
/* @__PURE__ */ (0,
|
|
4615
|
-
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0,
|
|
4616
|
-
/* @__PURE__ */ (0,
|
|
5469
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200 shrink-0", children: [
|
|
5470
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
5471
|
+
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: schema.title || schema.name }) }),
|
|
5472
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4617
5473
|
"button",
|
|
4618
5474
|
{
|
|
4619
5475
|
onClick: handleAddRow,
|
|
4620
5476
|
disabled: isInitialLoading || isLoading || isUpdatingActive,
|
|
4621
5477
|
className: `w-9 h-9 text-white rounded-lg shadow-xs flex items-center justify-center transition-all ${isInitialLoading || isLoading || isUpdatingActive ? "bg-emerald-950/80 text-emerald-400/60 pointer-events-none cursor-not-allowed" : "bg-emerald-600 hover:bg-emerald-700 active:bg-emerald-800 cursor-pointer"}`,
|
|
4622
5478
|
title: isInitialLoading ? "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." : "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
4623
|
-
children: /* @__PURE__ */ (0,
|
|
5479
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
|
|
4624
5480
|
}
|
|
4625
5481
|
),
|
|
4626
|
-
/* @__PURE__ */ (0,
|
|
5482
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4627
5483
|
"button",
|
|
4628
5484
|
{
|
|
4629
5485
|
onClick: handleDuplicateRow,
|
|
4630
5486
|
disabled: isInitialLoading || isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
4631
5487
|
className: "w-9 h-9 bg-blue-50 hover:bg-blue-100 border border-blue-200 text-blue-700 rounded-lg shadow-2xs flex items-center justify-center transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
|
|
4632
5488
|
title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
|
|
4633
|
-
children: /* @__PURE__ */ (0,
|
|
5489
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react8.Copy, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
4634
5490
|
}
|
|
4635
5491
|
),
|
|
4636
|
-
/* @__PURE__ */ (0,
|
|
5492
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4637
5493
|
"button",
|
|
4638
5494
|
{
|
|
4639
5495
|
onClick: handleDeleteSelected,
|
|
@@ -4641,12 +5497,12 @@ function TableBlockClient({
|
|
|
4641
5497
|
className: "w-9 h-9 bg-rose-50 hover:bg-rose-100 border border-rose-200 text-rose-700 rounded-lg shadow-2xs flex items-center justify-center relative transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
|
|
4642
5498
|
title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
|
|
4643
5499
|
children: [
|
|
4644
|
-
/* @__PURE__ */ (0,
|
|
4645
|
-
selectedIds.size > 0 && /* @__PURE__ */ (0,
|
|
5500
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
|
|
5501
|
+
selectedIds.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "absolute -top-1.5 -right-1.5 bg-rose-600 text-white min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs", children: selectedIds.size })
|
|
4646
5502
|
]
|
|
4647
5503
|
}
|
|
4648
5504
|
),
|
|
4649
|
-
/* @__PURE__ */ (0,
|
|
5505
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4650
5506
|
"button",
|
|
4651
5507
|
{
|
|
4652
5508
|
onClick: toggleSummary,
|
|
@@ -4654,13 +5510,13 @@ function TableBlockClient({
|
|
|
4654
5510
|
className: `h-9 px-3 border font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer ${showSummary ? "bg-indigo-50 border-indigo-200 text-indigo-700 hover:bg-indigo-100" : "bg-white border-slate-300 text-slate-700 hover:bg-slate-100"}`,
|
|
4655
5511
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
|
|
4656
5512
|
children: [
|
|
4657
|
-
/* @__PURE__ */ (0,
|
|
4658
|
-
/* @__PURE__ */ (0,
|
|
5513
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
|
|
5514
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
|
|
4659
5515
|
]
|
|
4660
5516
|
}
|
|
4661
5517
|
),
|
|
4662
|
-
/* @__PURE__ */ (0,
|
|
4663
|
-
/* @__PURE__ */ (0,
|
|
5518
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
|
|
5519
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4664
5520
|
"button",
|
|
4665
5521
|
{
|
|
4666
5522
|
onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
|
|
@@ -4668,16 +5524,16 @@ function TableBlockClient({
|
|
|
4668
5524
|
className: "h-9 px-3 bg-white hover:bg-slate-100 border border-slate-300 text-slate-700 font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
|
|
4669
5525
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
|
|
4670
5526
|
children: [
|
|
4671
|
-
/* @__PURE__ */ (0,
|
|
4672
|
-
/* @__PURE__ */ (0,
|
|
5527
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) }),
|
|
5528
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: `w-3.5 h-3.5 text-slate-500 transition-transform ${isColumnsDropdownOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
|
|
4673
5529
|
]
|
|
4674
5530
|
}
|
|
4675
5531
|
),
|
|
4676
|
-
isColumnsDropdownOpen && /* @__PURE__ */ (0,
|
|
4677
|
-
/* @__PURE__ */ (0,
|
|
4678
|
-
/* @__PURE__ */ (0,
|
|
4679
|
-
/* @__PURE__ */ (0,
|
|
4680
|
-
/* @__PURE__ */ (0,
|
|
5532
|
+
isColumnsDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-56 bg-white border border-slate-200 rounded-xl shadow-xl z-50 p-1.5 dir-rtl animate-in fade-in slide-in-from-top-2 duration-150", children: [
|
|
5533
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "px-2 py-1.5 text-xs font-bold text-slate-500 border-b border-slate-100 mb-1 flex items-center justify-between", children: [
|
|
5534
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
5535
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
|
|
5536
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-[10px] font-normal text-slate-400", children: [
|
|
4681
5537
|
"(",
|
|
4682
5538
|
customizableColumns.filter((c) => !c.isHidden).length,
|
|
4683
5539
|
"/",
|
|
@@ -4685,7 +5541,7 @@ function TableBlockClient({
|
|
|
4685
5541
|
")"
|
|
4686
5542
|
] })
|
|
4687
5543
|
] }),
|
|
4688
|
-
/* @__PURE__ */ (0,
|
|
5544
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4689
5545
|
"button",
|
|
4690
5546
|
{
|
|
4691
5547
|
type: "button",
|
|
@@ -4695,7 +5551,7 @@ function TableBlockClient({
|
|
|
4695
5551
|
}
|
|
4696
5552
|
)
|
|
4697
5553
|
] }),
|
|
4698
|
-
/* @__PURE__ */ (0,
|
|
5554
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
|
|
4699
5555
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
4700
5556
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
4701
5557
|
const isProtected = isRequired || isUnique;
|
|
@@ -4709,7 +5565,7 @@ function TableBlockClient({
|
|
|
4709
5565
|
protectedExplanation = "\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9 - \u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05D5\u05E8\u05D9\u05D3 \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5 \u05DE\u05D4\u05EA\u05E6\u05D5\u05D2\u05D4";
|
|
4710
5566
|
}
|
|
4711
5567
|
const badgeLabel = isRequired && isUnique ? "\u05D7\u05D5\u05D1\u05D4 + \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9" : isRequired ? "\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4" : "\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9";
|
|
4712
|
-
return /* @__PURE__ */ (0,
|
|
5568
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4713
5569
|
"div",
|
|
4714
5570
|
{
|
|
4715
5571
|
onClick: () => {
|
|
@@ -4720,8 +5576,8 @@ function TableBlockClient({
|
|
|
4720
5576
|
title: isProtected ? protectedExplanation : void 0,
|
|
4721
5577
|
className: `group flex items-center justify-between px-2.5 py-1.5 rounded-lg text-xs transition-colors select-none ${isProtected ? "opacity-75 bg-slate-50 border border-slate-100/70 cursor-not-allowed" : "hover:bg-slate-100 active:bg-slate-200 cursor-pointer"}`,
|
|
4722
5578
|
children: [
|
|
4723
|
-
/* @__PURE__ */ (0,
|
|
4724
|
-
/* @__PURE__ */ (0,
|
|
5579
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
5580
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4725
5581
|
"input",
|
|
4726
5582
|
{
|
|
4727
5583
|
type: "checkbox",
|
|
@@ -4732,16 +5588,16 @@ function TableBlockClient({
|
|
|
4732
5588
|
className: "w-3.5 h-3.5 rounded border-slate-300 text-brand focus:ring-brand/20 cursor-pointer disabled:cursor-not-allowed disabled:opacity-60"
|
|
4733
5589
|
}
|
|
4734
5590
|
),
|
|
4735
|
-
/* @__PURE__ */ (0,
|
|
5591
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
|
|
4736
5592
|
] }),
|
|
4737
|
-
isProtected && /* @__PURE__ */ (0,
|
|
5593
|
+
isProtected && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4738
5594
|
"div",
|
|
4739
5595
|
{
|
|
4740
5596
|
className: "flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-semibold bg-amber-50 text-amber-800 border border-amber-200/80 cursor-help",
|
|
4741
5597
|
title: protectedExplanation,
|
|
4742
5598
|
children: [
|
|
4743
|
-
/* @__PURE__ */ (0,
|
|
4744
|
-
/* @__PURE__ */ (0,
|
|
5599
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-3 h-3 text-amber-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "2.2", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
|
|
5600
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: badgeLabel })
|
|
4745
5601
|
]
|
|
4746
5602
|
}
|
|
4747
5603
|
)
|
|
@@ -4752,9 +5608,23 @@ function TableBlockClient({
|
|
|
4752
5608
|
}) })
|
|
4753
5609
|
] })
|
|
4754
5610
|
] }),
|
|
4755
|
-
/* @__PURE__ */ (0,
|
|
4756
|
-
|
|
4757
|
-
|
|
5611
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
5612
|
+
"button",
|
|
5613
|
+
{
|
|
5614
|
+
onClick: handleExportCsv,
|
|
5615
|
+
disabled: isLoading || isUpdatingActive || isExporting,
|
|
5616
|
+
className: `h-9 px-3 font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer border ${hasSelectedRows ? "bg-blue-50 hover:bg-blue-100 border-blue-200 text-blue-700" : hasActiveSearchOrFilter ? "bg-amber-50 hover:bg-amber-100 border-amber-200 text-amber-800" : "bg-white hover:bg-slate-100 border-slate-300 text-slate-700"}`,
|
|
5617
|
+
title: exportButtonText,
|
|
5618
|
+
"data-testid": "export-csv-button",
|
|
5619
|
+
children: [
|
|
5620
|
+
isExporting ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react8.Loader2, { className: "w-4 h-4 shrink-0 animate-spin text-slate-500" }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ExportButtonIcon, { className: "w-4 h-4 shrink-0" }),
|
|
5621
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: isExporting ? "\u05DE\u05D9\u05D9\u05E6\u05D0..." : exportButtonText })
|
|
5622
|
+
]
|
|
5623
|
+
}
|
|
5624
|
+
),
|
|
5625
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
5626
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
5627
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4758
5628
|
"input",
|
|
4759
5629
|
{
|
|
4760
5630
|
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
@@ -4764,28 +5634,28 @@ function TableBlockClient({
|
|
|
4764
5634
|
className: "w-full h-9 px-3 pr-9 text-xs border border-slate-300 rounded-lg bg-white shadow-2xs focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 text-slate-800 disabled:opacity-50"
|
|
4765
5635
|
}
|
|
4766
5636
|
),
|
|
4767
|
-
searchQuery ? /* @__PURE__ */ (0,
|
|
5637
|
+
searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4768
5638
|
"button",
|
|
4769
5639
|
{
|
|
4770
5640
|
type: "button",
|
|
4771
5641
|
onClick: () => setSearchQuery(""),
|
|
4772
5642
|
className: "absolute right-2.5 top-2.5 text-slate-400 hover:text-slate-600 transition-colors p-0.5 rounded-full hover:bg-slate-100 cursor-pointer",
|
|
4773
5643
|
title: "Clear search",
|
|
4774
|
-
children: /* @__PURE__ */ (0,
|
|
5644
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react8.X, { className: "w-3.5 h-3.5" })
|
|
4775
5645
|
}
|
|
4776
|
-
) : /* @__PURE__ */ (0,
|
|
5646
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
|
|
4777
5647
|
] })
|
|
4778
5648
|
] }),
|
|
4779
|
-
/* @__PURE__ */ (0,
|
|
4780
|
-
isUpdatingActive ? /* @__PURE__ */ (0,
|
|
4781
|
-
/* @__PURE__ */ (0,
|
|
5649
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
5650
|
+
isUpdatingActive ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-xs text-blue-600 font-semibold flex items-center gap-1.5 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-lg animate-pulse", children: [
|
|
5651
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
4782
5652
|
"\u05DE\u05E2\u05D3\u05DB\u05DF..."
|
|
4783
|
-
] }) : isSaveSuccess ? /* @__PURE__ */ (0,
|
|
4784
|
-
/* @__PURE__ */ (0,
|
|
5653
|
+
] }) : isSaveSuccess ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
|
|
5654
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
|
|
4785
5655
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
4786
|
-
] }) : hasChanges ? /* @__PURE__ */ (0,
|
|
4787
|
-
/* @__PURE__ */ (0,
|
|
4788
|
-
/* @__PURE__ */ (0,
|
|
5656
|
+
] }) : hasChanges ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-1.5 animate-in fade-in", children: [
|
|
5657
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-xs font-semibold text-amber-700", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }),
|
|
5658
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4789
5659
|
"button",
|
|
4790
5660
|
{
|
|
4791
5661
|
type: "button",
|
|
@@ -4794,30 +5664,31 @@ function TableBlockClient({
|
|
|
4794
5664
|
className: "p-1 text-amber-700 hover:text-amber-900 hover:bg-amber-100/80 active:bg-amber-200/80 rounded-md transition-colors cursor-pointer disabled:opacity-50 disabled:pointer-events-none",
|
|
4795
5665
|
title: "\u05D1\u05D8\u05DC \u05D0\u05EA \u05DB\u05DC \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5",
|
|
4796
5666
|
"aria-label": "\u05D1\u05D8\u05DC \u05D0\u05EA \u05DB\u05DC \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5",
|
|
4797
|
-
children: /* @__PURE__ */ (0,
|
|
5667
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react8.RotateCcw, { className: "w-3.5 h-3.5" })
|
|
4798
5668
|
}
|
|
4799
5669
|
)
|
|
4800
5670
|
] }) : null,
|
|
4801
|
-
/* @__PURE__ */ (0,
|
|
5671
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4802
5672
|
"button",
|
|
4803
5673
|
{
|
|
4804
5674
|
onClick: handleSave,
|
|
4805
5675
|
disabled: isUpdatingActive || isLoading || !hasChanges,
|
|
4806
5676
|
className: `h-9 px-4 text-xs font-bold rounded-lg shadow-2xs transition-all flex items-center justify-center cursor-pointer ${hasChanges && !isUpdatingActive && !isLoading ? "bg-brand hover:bg-brand-hover active:bg-[#00897b] text-white shadow-teal-500/20" : "opacity-50 grayscale bg-slate-200 text-slate-400 cursor-not-allowed"}`,
|
|
4807
|
-
children: /* @__PURE__ */ (0,
|
|
5677
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
|
|
4808
5678
|
}
|
|
4809
5679
|
)
|
|
4810
5680
|
] })
|
|
4811
5681
|
] }),
|
|
4812
|
-
/* @__PURE__ */ (0,
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
/* @__PURE__ */ (0,
|
|
5682
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `overflow-x-auto overflow-y-auto relative max-h-[calc(100vh-240px)] min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
|
|
5683
|
+
isFetching && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "absolute top-0 left-0 right-0 h-0.5 bg-blue-500/20 overflow-hidden z-30", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "w-full h-full bg-brand animate-pulse" }) }),
|
|
5684
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
|
|
5685
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
5686
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
4816
5687
|
] }),
|
|
4817
|
-
/* @__PURE__ */ (0,
|
|
4818
|
-
/* @__PURE__ */ (0,
|
|
4819
|
-
/* @__PURE__ */ (0,
|
|
4820
|
-
/* @__PURE__ */ (0,
|
|
5688
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
|
|
5689
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("thead", { className: "bg-white text-slate-700 sticky top-0 z-10 shadow-xs", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { className: "h-12 min-h-[48px]", children: [
|
|
5690
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { className: "border-b border-l border-slate-200 p-1.5 text-center shrink-0 h-12 min-h-[48px] align-middle bg-white", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-center gap-1.5", children: [
|
|
5691
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4821
5692
|
"input",
|
|
4822
5693
|
{
|
|
4823
5694
|
type: "checkbox",
|
|
@@ -4830,7 +5701,7 @@ function TableBlockClient({
|
|
|
4830
5701
|
filteredColumns.some((c) => {
|
|
4831
5702
|
var _a;
|
|
4832
5703
|
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
4833
|
-
}) && /* @__PURE__ */ (0,
|
|
5704
|
+
}) && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "w-5 h-5 shrink-0" })
|
|
4834
5705
|
] }) }),
|
|
4835
5706
|
filteredColumns.map((col) => {
|
|
4836
5707
|
var _a, _b;
|
|
@@ -4841,16 +5712,25 @@ function TableBlockClient({
|
|
|
4841
5712
|
const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
|
|
4842
5713
|
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
|
|
4843
5714
|
const isRelation = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
|
|
4844
|
-
const filterVal = columnFilters[col.name]
|
|
4845
|
-
|
|
5715
|
+
const filterVal = columnFilters[col.name];
|
|
5716
|
+
const hasActiveFilter = Array.isArray(filterVal) ? filterVal.length > 0 : filterVal && typeof filterVal === "object" && "values" in filterVal ? filterVal.values.length > 0 : Boolean(filterVal && filterVal.trim() !== "");
|
|
5717
|
+
let filterTooltip = "\u05D7\u05E4\u05E9 \u05D5\u05E1\u05E0\u05DF \u05D1\u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5";
|
|
5718
|
+
if (Array.isArray(filterVal)) {
|
|
5719
|
+
filterTooltip = `\u05DE\u05E1\u05D5\u05E0\u05DF \u05DC\u05E4\u05D9: ${filterVal.length} \u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA`;
|
|
5720
|
+
} else if (filterVal && typeof filterVal === "object" && "operator" in filterVal && filterVal.operator === "notIn") {
|
|
5721
|
+
filterTooltip = `\u05DE\u05D5\u05D7\u05E8\u05D2\u05D9\u05DD: ${filterVal.values.length} \u05E4\u05E8\u05D9\u05D8\u05D9\u05DD (\u05D4\u05DB\u05DC \u05DC\u05DE\u05E2\u05D8)`;
|
|
5722
|
+
} else if (typeof filterVal === "string" && filterVal.trim()) {
|
|
5723
|
+
filterTooltip = `\u05DE\u05E1\u05D5\u05E0\u05DF \u05DC\u05E4\u05D9: "${filterVal}" (\u05DC\u05D7\u05E5 \u05DC\u05E2\u05E8\u05D9\u05DB\u05D4)`;
|
|
5724
|
+
}
|
|
5725
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4846
5726
|
"th",
|
|
4847
5727
|
__spreadProps(__spreadValues({
|
|
4848
5728
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
4849
5729
|
title: isSearching ? void 0 : col.name
|
|
4850
5730
|
}, dragProps), {
|
|
4851
|
-
className: `relative border-b border-l border-slate-200 px-2
|
|
5731
|
+
className: `group relative border-b border-l border-slate-200 px-2 py-1 font-semibold text-slate-700 select-none transition-colors h-12 min-h-[48px] align-middle bg-white ${isSearching ? "cursor-default bg-blue-50/40" : "cursor-grab active:cursor-grabbing hover:bg-slate-100"} ${isDragging ? "opacity-40 bg-slate-200 border-dashed border-2 border-brand" : ""} ${isDragOver ? "bg-blue-50 border-r-4 border-r-brand text-brand font-bold" : ""}`,
|
|
4852
5732
|
children: [
|
|
4853
|
-
/* @__PURE__ */ (0,
|
|
5733
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4854
5734
|
"div",
|
|
4855
5735
|
{
|
|
4856
5736
|
onMouseDown: (e) => {
|
|
@@ -4862,7 +5742,7 @@ function TableBlockClient({
|
|
|
4862
5742
|
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
4863
5743
|
}
|
|
4864
5744
|
),
|
|
4865
|
-
isSearching ? /* @__PURE__ */ (0,
|
|
5745
|
+
isSearching && !isRelation ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4866
5746
|
"div",
|
|
4867
5747
|
{
|
|
4868
5748
|
ref: activeSearchRef,
|
|
@@ -4870,46 +5750,15 @@ function TableBlockClient({
|
|
|
4870
5750
|
onClick: (e) => e.stopPropagation(),
|
|
4871
5751
|
onMouseDown: (e) => e.stopPropagation(),
|
|
4872
5752
|
children: [
|
|
4873
|
-
|
|
4874
|
-
"select",
|
|
4875
|
-
{
|
|
4876
|
-
autoFocus: true,
|
|
4877
|
-
value: filterVal,
|
|
4878
|
-
onChange: (e) => {
|
|
4879
|
-
const val = e.target.value;
|
|
4880
|
-
setColumnFilters((prev) => {
|
|
4881
|
-
const next = __spreadValues({}, prev);
|
|
4882
|
-
if (val) next[col.name] = val;
|
|
4883
|
-
else delete next[col.name];
|
|
4884
|
-
return next;
|
|
4885
|
-
});
|
|
4886
|
-
},
|
|
4887
|
-
onKeyDown: (e) => {
|
|
4888
|
-
if (e.key === "Escape" || e.key === "Enter") {
|
|
4889
|
-
setActiveSearchCol(null);
|
|
4890
|
-
}
|
|
4891
|
-
},
|
|
4892
|
-
className: "h-7 text-xs px-1.5 w-full rounded border border-blue-400 bg-white text-slate-800 focus:outline-none focus:ring-1 focus:ring-blue-400 cursor-pointer truncate",
|
|
4893
|
-
children: [
|
|
4894
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", children: "\u05D4\u05DB\u05DC" }),
|
|
4895
|
-
getUniqueRelationOptions(col).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: opt.label, children: opt.label }, opt.id))
|
|
4896
|
-
]
|
|
4897
|
-
}
|
|
4898
|
-
) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
5753
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4899
5754
|
"input",
|
|
4900
5755
|
{
|
|
4901
5756
|
autoFocus: true,
|
|
4902
5757
|
type: "text",
|
|
4903
5758
|
placeholder: `\u05D7\u05E4\u05E9 \u05D1-${col.name}...`,
|
|
4904
|
-
value: filterVal,
|
|
5759
|
+
value: typeof filterVal === "string" ? filterVal : "",
|
|
4905
5760
|
onChange: (e) => {
|
|
4906
|
-
|
|
4907
|
-
setColumnFilters((prev) => {
|
|
4908
|
-
const next = __spreadValues({}, prev);
|
|
4909
|
-
if (val) next[col.name] = val;
|
|
4910
|
-
else delete next[col.name];
|
|
4911
|
-
return next;
|
|
4912
|
-
});
|
|
5761
|
+
handleApplyColumnFilter(col.name, e.target.value);
|
|
4913
5762
|
},
|
|
4914
5763
|
onKeyDown: (e) => {
|
|
4915
5764
|
if (e.key === "Escape" || e.key === "Enter") {
|
|
@@ -4919,7 +5768,7 @@ function TableBlockClient({
|
|
|
4919
5768
|
className: "h-7 text-xs px-2 w-full rounded border border-blue-400 bg-white text-slate-800 focus:outline-none focus:ring-1 focus:ring-blue-400"
|
|
4920
5769
|
}
|
|
4921
5770
|
) }),
|
|
4922
|
-
/* @__PURE__ */ (0,
|
|
5771
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4923
5772
|
"button",
|
|
4924
5773
|
{
|
|
4925
5774
|
type: "button",
|
|
@@ -4929,59 +5778,62 @@ function TableBlockClient({
|
|
|
4929
5778
|
},
|
|
4930
5779
|
onClick: (e) => {
|
|
4931
5780
|
e.stopPropagation();
|
|
4932
|
-
|
|
4933
|
-
const next = __spreadValues({}, prev);
|
|
4934
|
-
delete next[col.name];
|
|
4935
|
-
return next;
|
|
4936
|
-
});
|
|
5781
|
+
handleApplyColumnFilter(col.name, void 0);
|
|
4937
5782
|
setActiveSearchCol(null);
|
|
4938
5783
|
},
|
|
4939
5784
|
className: "p-1 text-slate-400 hover:text-slate-700 hover:bg-slate-200/70 rounded transition-colors cursor-pointer shrink-0",
|
|
4940
5785
|
title: "\u05E0\u05E7\u05D4 \u05D5\u05E1\u05D2\u05D5\u05E8 \u05D7\u05D9\u05E4\u05D5\u05E9",
|
|
4941
|
-
children: /* @__PURE__ */ (0,
|
|
5786
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react8.X, { className: "w-3.5 h-3.5" })
|
|
4942
5787
|
}
|
|
4943
5788
|
)
|
|
4944
5789
|
]
|
|
4945
5790
|
}
|
|
4946
|
-
) : /* @__PURE__ */ (0,
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
5791
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col items-center justify-center w-full h-full min-w-0 select-none py-0.5", title: col.name, children: [
|
|
5792
|
+
((_b = col.type) == null ? void 0 : _b.toUpperCase()) !== "SUB_TABLE" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5793
|
+
"button",
|
|
5794
|
+
{
|
|
5795
|
+
ref: (el) => {
|
|
5796
|
+
filterButtonRefs.current[col.name] = el;
|
|
5797
|
+
},
|
|
5798
|
+
type: "button",
|
|
5799
|
+
onClick: (e) => {
|
|
5800
|
+
e.stopPropagation();
|
|
5801
|
+
e.preventDefault();
|
|
5802
|
+
if (isRelation) {
|
|
5803
|
+
if (activeRelationCol === col.name) {
|
|
5804
|
+
setActiveRelationCol(null);
|
|
5805
|
+
setRelationTriggerRect(null);
|
|
5806
|
+
} else {
|
|
5807
|
+
const btn = filterButtonRefs.current[col.name];
|
|
5808
|
+
if (btn) {
|
|
5809
|
+
setRelationTriggerRect(btn.getBoundingClientRect());
|
|
5810
|
+
}
|
|
5811
|
+
setActiveRelationCol(col.name);
|
|
5812
|
+
if (!relationOptions[col.name] || relationOptions[col.name].length < 100) {
|
|
5813
|
+
refetchRelation(col.name, { take: 1e3 });
|
|
5814
|
+
}
|
|
5815
|
+
}
|
|
5816
|
+
} else {
|
|
4956
5817
|
setActiveSearchCol(col.name);
|
|
4957
|
-
}
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
}
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
{
|
|
4966
|
-
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
4967
|
-
fill: "none",
|
|
4968
|
-
viewBox: "0 0 24 24",
|
|
4969
|
-
stroke: "currentColor",
|
|
4970
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
|
|
4971
|
-
}
|
|
4972
|
-
)
|
|
4973
|
-
] })
|
|
5818
|
+
}
|
|
5819
|
+
},
|
|
5820
|
+
className: `p-0.5 rounded transition-colors cursor-pointer mb-0.5 shrink-0 ${hasActiveFilter ? "opacity-100 text-blue-600 bg-blue-100 hover:bg-blue-200" : activeRelationCol === col.name ? "opacity-100 text-blue-600 bg-blue-100" : "opacity-0 group-hover:opacity-100 text-slate-400 hover:text-slate-600 hover:bg-slate-200/60"}`,
|
|
5821
|
+
title: filterTooltip,
|
|
5822
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react8.Filter, { className: "w-3 h-3" })
|
|
5823
|
+
}
|
|
5824
|
+
),
|
|
5825
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ColumnHeaderTitle, { name: col.name, width: currentWidth, isSubTable: false })
|
|
4974
5826
|
] })
|
|
4975
5827
|
]
|
|
4976
5828
|
}),
|
|
4977
5829
|
col.name
|
|
4978
5830
|
);
|
|
4979
5831
|
}),
|
|
4980
|
-
/* @__PURE__ */ (0,
|
|
5832
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none h-12 min-h-[48px] bg-white" })
|
|
4981
5833
|
] }) }),
|
|
4982
|
-
/* @__PURE__ */ (0,
|
|
4983
|
-
/* @__PURE__ */ (0,
|
|
4984
|
-
/* @__PURE__ */ (0,
|
|
5834
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { className: `bg-white transition-opacity duration-150 ${isFetching ? "opacity-50 pointer-events-none" : "opacity-100"}`, children: (isStateEmpty || filteredData.length === 0) && !isLoading && !isFetching ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
5835
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
|
|
5836
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
4985
5837
|
] }) }) }) : filteredData.map((row) => {
|
|
4986
5838
|
const hasSubTableCols = filteredColumns.some((c) => {
|
|
4987
5839
|
var _a;
|
|
@@ -4992,10 +5844,10 @@ function TableBlockClient({
|
|
|
4992
5844
|
var _a;
|
|
4993
5845
|
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
4994
5846
|
});
|
|
4995
|
-
return /* @__PURE__ */ (0,
|
|
4996
|
-
/* @__PURE__ */ (0,
|
|
4997
|
-
/* @__PURE__ */ (0,
|
|
4998
|
-
/* @__PURE__ */ (0,
|
|
5847
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react14.default.Fragment, { children: [
|
|
5848
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
|
|
5849
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-center gap-1.5", children: [
|
|
5850
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4999
5851
|
"input",
|
|
5000
5852
|
{
|
|
5001
5853
|
type: "checkbox",
|
|
@@ -5005,7 +5857,7 @@ function TableBlockClient({
|
|
|
5005
5857
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
5006
5858
|
}
|
|
5007
5859
|
),
|
|
5008
|
-
hasSubTableCols && /* @__PURE__ */ (0,
|
|
5860
|
+
hasSubTableCols && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5009
5861
|
"button",
|
|
5010
5862
|
{
|
|
5011
5863
|
type: "button",
|
|
@@ -5017,7 +5869,7 @@ function TableBlockClient({
|
|
|
5017
5869
|
}),
|
|
5018
5870
|
className: "w-5 h-5 rounded-full bg-slate-500 hover:bg-slate-600 text-white flex items-center justify-center transition-colors cursor-pointer shrink-0 shadow-sm",
|
|
5019
5871
|
title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
|
|
5020
|
-
children: /* @__PURE__ */ (0,
|
|
5872
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: `w-3 h-3 transition-transform duration-150 ${isExpanded ? "rotate-90" : "rotate-180"}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", d: "M9 5l7 7-7 7" }) })
|
|
5021
5873
|
}
|
|
5022
5874
|
)
|
|
5023
5875
|
] }) }),
|
|
@@ -5035,12 +5887,12 @@ function TableBlockClient({
|
|
|
5035
5887
|
}
|
|
5036
5888
|
}
|
|
5037
5889
|
if (value === void 0) value = null;
|
|
5038
|
-
return /* @__PURE__ */ (0,
|
|
5890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5039
5891
|
"td",
|
|
5040
5892
|
{
|
|
5041
5893
|
className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
|
|
5042
5894
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
5043
|
-
children: /* @__PURE__ */ (0,
|
|
5895
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5044
5896
|
InputComponent,
|
|
5045
5897
|
{
|
|
5046
5898
|
value,
|
|
@@ -5052,6 +5904,7 @@ function TableBlockClient({
|
|
|
5052
5904
|
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
5053
5905
|
onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
|
|
5054
5906
|
relationOptions,
|
|
5907
|
+
relationDictionaryRef,
|
|
5055
5908
|
refetchRelation,
|
|
5056
5909
|
executeAction,
|
|
5057
5910
|
emitEvent,
|
|
@@ -5068,9 +5921,9 @@ function TableBlockClient({
|
|
|
5068
5921
|
col.name
|
|
5069
5922
|
);
|
|
5070
5923
|
}),
|
|
5071
|
-
/* @__PURE__ */ (0,
|
|
5924
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
5072
5925
|
] }),
|
|
5073
|
-
isExpanded && /* @__PURE__ */ (0,
|
|
5926
|
+
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5074
5927
|
ExpandedSubTables,
|
|
5075
5928
|
{
|
|
5076
5929
|
rowId: row.id,
|
|
@@ -5092,8 +5945,8 @@ function TableBlockClient({
|
|
|
5092
5945
|
)
|
|
5093
5946
|
] }, row.id);
|
|
5094
5947
|
}) }),
|
|
5095
|
-
showSummary && filteredData.length > 0 && /* @__PURE__ */ (0,
|
|
5096
|
-
/* @__PURE__ */ (0,
|
|
5948
|
+
showSummary && filteredData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tfoot", { className: "bg-slate-50 border-t-2 border-slate-300 sticky bottom-0 z-10 shadow-[0_-2px_4px_rgba(0,0,0,0.02)]", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
|
|
5949
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center font-bold text-slate-600 text-xs", children: '\u05E1\u05D4"\u05DB' }),
|
|
5097
5950
|
filteredColumns.map((col) => {
|
|
5098
5951
|
var _a, _b;
|
|
5099
5952
|
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
@@ -5107,16 +5960,16 @@ function TableBlockClient({
|
|
|
5107
5960
|
displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
|
|
5108
5961
|
}
|
|
5109
5962
|
}
|
|
5110
|
-
return /* @__PURE__ */ (0,
|
|
5963
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-l border-slate-200 p-2 text-sm font-semibold text-slate-700 bg-slate-50 relative", children: isNumeric && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "truncate", children: displayVal }) }) }, col.name);
|
|
5111
5964
|
}),
|
|
5112
|
-
/* @__PURE__ */ (0,
|
|
5965
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
|
|
5113
5966
|
] }) })
|
|
5114
5967
|
] })
|
|
5115
5968
|
] }),
|
|
5116
|
-
/* @__PURE__ */ (0,
|
|
5117
|
-
/* @__PURE__ */ (0,
|
|
5118
|
-
/* @__PURE__ */ (0,
|
|
5119
|
-
/* @__PURE__ */ (0,
|
|
5969
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 bg-slate-50 border-t border-slate-200 text-xs text-slate-600 rounded-b-xl shrink-0", children: [
|
|
5970
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5971
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
|
|
5972
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
5120
5973
|
"select",
|
|
5121
5974
|
{
|
|
5122
5975
|
value: limit,
|
|
@@ -5124,27 +5977,27 @@ function TableBlockClient({
|
|
|
5124
5977
|
disabled: isLoading || isUpdatingActive,
|
|
5125
5978
|
className: "bg-white border border-slate-300 rounded-lg px-2.5 py-1 text-slate-700 font-semibold shadow-2xs cursor-pointer focus:outline-none focus:ring-2 focus:ring-brand disabled:opacity-50",
|
|
5126
5979
|
children: [
|
|
5127
|
-
/* @__PURE__ */ (0,
|
|
5128
|
-
/* @__PURE__ */ (0,
|
|
5129
|
-
/* @__PURE__ */ (0,
|
|
5980
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: 20, children: "20" }),
|
|
5981
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: 50, children: "50" }),
|
|
5982
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: 100, children: "100" })
|
|
5130
5983
|
]
|
|
5131
5984
|
}
|
|
5132
5985
|
)
|
|
5133
5986
|
] }),
|
|
5134
|
-
/* @__PURE__ */ (0,
|
|
5135
|
-
/* @__PURE__ */ (0,
|
|
5987
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
5988
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "font-medium text-slate-600", children: [
|
|
5136
5989
|
"\u05E2\u05DE\u05D5\u05D3 ",
|
|
5137
|
-
/* @__PURE__ */ (0,
|
|
5990
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("strong", { className: "text-slate-900", children: page }),
|
|
5138
5991
|
" \u05DE\u05EA\u05D5\u05DA ",
|
|
5139
|
-
/* @__PURE__ */ (0,
|
|
5140
|
-
totalRecords > 0 && /* @__PURE__ */ (0,
|
|
5992
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("strong", { className: "text-slate-900", children: totalPages || 1 }),
|
|
5993
|
+
totalRecords > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-slate-500 font-normal", children: [
|
|
5141
5994
|
" (",
|
|
5142
5995
|
totalRecords,
|
|
5143
5996
|
' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
|
|
5144
5997
|
] })
|
|
5145
5998
|
] }),
|
|
5146
|
-
/* @__PURE__ */ (0,
|
|
5147
|
-
/* @__PURE__ */ (0,
|
|
5999
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
6000
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5148
6001
|
"button",
|
|
5149
6002
|
{
|
|
5150
6003
|
onClick: handlePrevPage,
|
|
@@ -5154,7 +6007,7 @@ function TableBlockClient({
|
|
|
5154
6007
|
children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
|
|
5155
6008
|
}
|
|
5156
6009
|
),
|
|
5157
|
-
/* @__PURE__ */ (0,
|
|
6010
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5158
6011
|
"button",
|
|
5159
6012
|
{
|
|
5160
6013
|
onClick: handleNextPage,
|
|
@@ -5166,7 +6019,30 @@ function TableBlockClient({
|
|
|
5166
6019
|
)
|
|
5167
6020
|
] })
|
|
5168
6021
|
] })
|
|
5169
|
-
] })
|
|
6022
|
+
] }),
|
|
6023
|
+
activeRelationCol && (() => {
|
|
6024
|
+
const activeColDef = filteredColumns.find((c) => c.name === activeRelationCol);
|
|
6025
|
+
if (!activeColDef) return null;
|
|
6026
|
+
const rawSelected = columnFilters[activeRelationCol];
|
|
6027
|
+
const currentSelected = typeof rawSelected === "object" && rawSelected !== null ? rawSelected : void 0;
|
|
6028
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6029
|
+
RelationFilterPopover,
|
|
6030
|
+
{
|
|
6031
|
+
isOpen: Boolean(activeRelationCol),
|
|
6032
|
+
onClose: () => {
|
|
6033
|
+
setActiveRelationCol(null);
|
|
6034
|
+
setRelationTriggerRect(null);
|
|
6035
|
+
},
|
|
6036
|
+
column: activeColDef,
|
|
6037
|
+
triggerRect: relationTriggerRect,
|
|
6038
|
+
options: getUniqueRelationOptions(activeColDef),
|
|
6039
|
+
filterValue: currentSelected,
|
|
6040
|
+
onSelectionChange: (newSelected) => {
|
|
6041
|
+
handleApplyColumnFilter(activeRelationCol, newSelected);
|
|
6042
|
+
}
|
|
6043
|
+
}
|
|
6044
|
+
);
|
|
6045
|
+
})()
|
|
5170
6046
|
]
|
|
5171
6047
|
}
|
|
5172
6048
|
);
|
|
@@ -5180,11 +6056,11 @@ function ExpandedSubTables({
|
|
|
5180
6056
|
context
|
|
5181
6057
|
}) {
|
|
5182
6058
|
var _a;
|
|
5183
|
-
const [activeTab, setActiveTab] = (0,
|
|
6059
|
+
const [activeTab, setActiveTab] = (0, import_react14.useState)((_a = subTableColumns[0]) == null ? void 0 : _a.name);
|
|
5184
6060
|
if (subTableColumns.length === 0) return null;
|
|
5185
6061
|
if (subTableColumns.length === 1) {
|
|
5186
6062
|
const stCol = subTableColumns[0];
|
|
5187
|
-
return /* @__PURE__ */ (0,
|
|
6063
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5188
6064
|
SubTableViewer,
|
|
5189
6065
|
{
|
|
5190
6066
|
rowId,
|
|
@@ -5196,8 +6072,8 @@ function ExpandedSubTables({
|
|
|
5196
6072
|
) }) });
|
|
5197
6073
|
}
|
|
5198
6074
|
const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
|
|
5199
|
-
return /* @__PURE__ */ (0,
|
|
5200
|
-
/* @__PURE__ */ (0,
|
|
6075
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50 overflow-hidden", children: [
|
|
6076
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex border-b border-slate-200 bg-slate-100/50 px-2 pt-2 gap-1 overflow-hidden", children: subTableColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5201
6077
|
"button",
|
|
5202
6078
|
{
|
|
5203
6079
|
type: "button",
|
|
@@ -5207,7 +6083,7 @@ function ExpandedSubTables({
|
|
|
5207
6083
|
},
|
|
5208
6084
|
col.name
|
|
5209
6085
|
)) }),
|
|
5210
|
-
/* @__PURE__ */ (0,
|
|
6086
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
5211
6087
|
SubTableViewer,
|
|
5212
6088
|
{
|
|
5213
6089
|
rowId,
|
|
@@ -5222,9 +6098,9 @@ function ExpandedSubTables({
|
|
|
5222
6098
|
}
|
|
5223
6099
|
|
|
5224
6100
|
// src/components/TableBlock/TableBlock.tsx
|
|
5225
|
-
var
|
|
6101
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
5226
6102
|
function TableBlock(props) {
|
|
5227
|
-
return /* @__PURE__ */ (0,
|
|
6103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableBlockClient, __spreadValues({}, props));
|
|
5228
6104
|
}
|
|
5229
6105
|
|
|
5230
6106
|
// src/registry.ts
|
|
@@ -5241,6 +6117,7 @@ var UNIVERSE_COMPONENTS = {
|
|
|
5241
6117
|
DatePickerCell,
|
|
5242
6118
|
LinkPickerCell,
|
|
5243
6119
|
PASTEL_PALETTES,
|
|
6120
|
+
RelationFilterPopover,
|
|
5244
6121
|
RelationPickerCell,
|
|
5245
6122
|
TEXT_REPRESENTABLE_TYPES,
|
|
5246
6123
|
TableBlock,
|