@universe-platform/ui 0.1.0-beta.10 → 0.1.0-beta.12
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 +1545 -583
- package/dist/index.mjs +1532 -571
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -159,7 +159,7 @@ var COLUMN_DEFAULT_INPUT_CONFIG = {
|
|
|
159
159
|
NUMBER: { inputType: "number", placeholder: "\u05D4\u05D6\u05DF \u05DE\u05E1\u05E4\u05E8" },
|
|
160
160
|
BOOLEAN: { inputType: "select" },
|
|
161
161
|
DATE: { inputType: "date" },
|
|
162
|
-
RELATION: { inputType: "
|
|
162
|
+
RELATION: { inputType: "select", placeholder: "\u05D1\u05D7\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05DB\u05D1\u05E8\u05D9\u05E8\u05EA \u05DE\u05D7\u05D3\u05DC" },
|
|
163
163
|
GOOGLE_DRIVE_FILE: { inputType: "text" },
|
|
164
164
|
CURRENCY: { inputType: "number", placeholder: "\u05D4\u05D6\u05DF \u05DE\u05E1\u05E4\u05E8" },
|
|
165
165
|
TIME: { inputType: "time" },
|
|
@@ -170,7 +170,7 @@ var COLUMN_DEFAULT_INPUT_CONFIG = {
|
|
|
170
170
|
};
|
|
171
171
|
|
|
172
172
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
173
|
-
import
|
|
173
|
+
import React11, { useState as useState12, useMemo as useMemo6, useEffect as useEffect10, useCallback as useCallback10, useRef as useRef8 } from "react";
|
|
174
174
|
|
|
175
175
|
// src/hooks/useToast.ts
|
|
176
176
|
import { useContext as useContext2 } from "react";
|
|
@@ -1460,9 +1460,10 @@ function LinkPickerCell({ value, onChange, readOnly = false }) {
|
|
|
1460
1460
|
}
|
|
1461
1461
|
|
|
1462
1462
|
// src/components/TableBlock/fields/RelationPickerCell.tsx
|
|
1463
|
-
import { useState as useState6, useRef as useRef5, useEffect as useEffect5, useCallback as useCallback5, useMemo as useMemo3 } from "react";
|
|
1464
|
-
import {
|
|
1465
|
-
import {
|
|
1463
|
+
import React6, { useState as useState6, useRef as useRef5, useEffect as useEffect5, useCallback as useCallback5, useMemo as useMemo3 } from "react";
|
|
1464
|
+
import { createPortal } from "react-dom";
|
|
1465
|
+
import { X as X6, Search, Check as Check3, ChevronDown, Loader2 } from "lucide-react";
|
|
1466
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1466
1467
|
function isRawObjectId(str) {
|
|
1467
1468
|
if (typeof str !== "string") return false;
|
|
1468
1469
|
const trimmed = str.trim();
|
|
@@ -1519,6 +1520,30 @@ function resolveRelationLabel(opt, column) {
|
|
|
1519
1520
|
}
|
|
1520
1521
|
return "";
|
|
1521
1522
|
}
|
|
1523
|
+
var ITEM_HEIGHT = 35;
|
|
1524
|
+
var CONTAINER_HEIGHT = 200;
|
|
1525
|
+
var OVERSCAN = 5;
|
|
1526
|
+
var BATCH_SIZE = 50;
|
|
1527
|
+
var RelationPickerRow = React6.memo(function RelationPickerRow2({
|
|
1528
|
+
id,
|
|
1529
|
+
label,
|
|
1530
|
+
isSelected,
|
|
1531
|
+
onSelect,
|
|
1532
|
+
height
|
|
1533
|
+
}) {
|
|
1534
|
+
return /* @__PURE__ */ jsxs6(
|
|
1535
|
+
"div",
|
|
1536
|
+
{
|
|
1537
|
+
onClick: () => onSelect(id),
|
|
1538
|
+
style: { height: `${height}px` },
|
|
1539
|
+
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"}`,
|
|
1540
|
+
children: [
|
|
1541
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate flex-1", children: label }),
|
|
1542
|
+
isSelected && /* @__PURE__ */ jsx6(Check3, { className: "w-3.5 h-3.5 text-blue-600 shrink-0 mr-1" })
|
|
1543
|
+
]
|
|
1544
|
+
}
|
|
1545
|
+
);
|
|
1546
|
+
});
|
|
1522
1547
|
function RelationPickerCell({
|
|
1523
1548
|
value,
|
|
1524
1549
|
onChange,
|
|
@@ -1527,42 +1552,147 @@ function RelationPickerCell({
|
|
|
1527
1552
|
rowId,
|
|
1528
1553
|
readOnly = false
|
|
1529
1554
|
}) {
|
|
1530
|
-
var _a;
|
|
1555
|
+
var _a, _b, _c;
|
|
1531
1556
|
const [isOpen, setIsOpen] = useState6(false);
|
|
1532
1557
|
const [searchQuery, setSearchQuery] = useState6("");
|
|
1558
|
+
const [isRemoteSearching, setIsRemoteSearching] = useState6(false);
|
|
1559
|
+
const [isLoadingMore, setIsLoadingMore] = useState6(false);
|
|
1560
|
+
const [hasMore, setHasMore] = useState6(true);
|
|
1561
|
+
const [items, setItems] = useState6([]);
|
|
1562
|
+
const [skip, setSkip] = useState6(0);
|
|
1563
|
+
const [scrollTop, setScrollTop] = useState6(0);
|
|
1533
1564
|
const containerRef = useRef5(null);
|
|
1565
|
+
const dropdownRef = useRef5(null);
|
|
1534
1566
|
const searchInputRef = useRef5(null);
|
|
1567
|
+
const listContainerRef = useRef5(null);
|
|
1568
|
+
const sentinelRef = useRef5(null);
|
|
1569
|
+
const [dropdownCoords, setDropdownCoords] = useState6(null);
|
|
1570
|
+
const updateDropdownCoords = useCallback5(() => {
|
|
1571
|
+
if (!containerRef.current) return;
|
|
1572
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
1573
|
+
const dropdownHeight = 280;
|
|
1574
|
+
const dropdownWidth = Math.max(220, Math.min(320, rect.width || 220));
|
|
1575
|
+
let right = window.innerWidth - rect.right;
|
|
1576
|
+
if (right + dropdownWidth > window.innerWidth - 10) {
|
|
1577
|
+
right = window.innerWidth - dropdownWidth - 10;
|
|
1578
|
+
}
|
|
1579
|
+
if (right < 10) {
|
|
1580
|
+
right = 10;
|
|
1581
|
+
}
|
|
1582
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
1583
|
+
let top = rect.bottom + 4;
|
|
1584
|
+
if (spaceBelow < dropdownHeight && rect.top > dropdownHeight) {
|
|
1585
|
+
top = Math.max(10, rect.top - dropdownHeight - 4);
|
|
1586
|
+
} else {
|
|
1587
|
+
top = Math.min(window.innerHeight - dropdownHeight - 10, top);
|
|
1588
|
+
}
|
|
1589
|
+
setDropdownCoords({ top, right, width: dropdownWidth });
|
|
1590
|
+
}, []);
|
|
1591
|
+
useEffect5(() => {
|
|
1592
|
+
if (!isOpen) return;
|
|
1593
|
+
updateDropdownCoords();
|
|
1594
|
+
const handleScrollOrResize = () => updateDropdownCoords();
|
|
1595
|
+
window.addEventListener("scroll", handleScrollOrResize, true);
|
|
1596
|
+
window.addEventListener("resize", handleScrollOrResize);
|
|
1597
|
+
return () => {
|
|
1598
|
+
window.removeEventListener("scroll", handleScrollOrResize, true);
|
|
1599
|
+
window.removeEventListener("resize", handleScrollOrResize);
|
|
1600
|
+
};
|
|
1601
|
+
}, [isOpen, updateDropdownCoords]);
|
|
1602
|
+
const stableLabelCacheRef = useRef5(/* @__PURE__ */ new Map());
|
|
1603
|
+
const skipRef = useRef5(0);
|
|
1604
|
+
const isLoadingMoreRef = useRef5(false);
|
|
1535
1605
|
const allowMultiple = Boolean((_a = column.config) == null ? void 0 : _a.allowMultiple);
|
|
1606
|
+
const referencedTableId = (_b = column.config) == null ? void 0 : _b.referencedTableId;
|
|
1607
|
+
const displayField = (_c = column.config) == null ? void 0 : _c.displayField;
|
|
1536
1608
|
const selectedIds = useMemo3(() => normalizeRelationValue(value), [value]);
|
|
1537
1609
|
const isStandalone = !context || context.relationOptions === void 0;
|
|
1538
1610
|
const optionsLoaded = isStandalone || context.relationOptions[column.name] !== void 0;
|
|
1539
|
-
const
|
|
1611
|
+
const baseOptions = useMemo3(() => {
|
|
1540
1612
|
var _a2;
|
|
1541
1613
|
return ((_a2 = context == null ? void 0 : context.relationOptions) == null ? void 0 : _a2[column.name]) || [];
|
|
1542
1614
|
}, [context == null ? void 0 : context.relationOptions, column.name]);
|
|
1543
1615
|
const processedOptions = useMemo3(() => {
|
|
1544
|
-
return
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
};
|
|
1550
|
-
}).filter((opt) => opt._displayLabel && opt._displayLabel.trim() !== "" && !isRawObjectId(opt._displayLabel));
|
|
1551
|
-
}, [rawOptions, column]);
|
|
1616
|
+
return items.map((opt) => ({
|
|
1617
|
+
id: String(opt.id),
|
|
1618
|
+
_displayLabel: resolveRelationLabel(opt, column) || opt.label || ""
|
|
1619
|
+
})).filter((opt) => opt._displayLabel && opt._displayLabel.trim() !== "" && !isRawObjectId(opt._displayLabel));
|
|
1620
|
+
}, [items, column]);
|
|
1552
1621
|
const getDisplayForId = useCallback5((id) => {
|
|
1553
|
-
|
|
1554
|
-
if (
|
|
1555
|
-
|
|
1622
|
+
var _a2, _b2, _c2;
|
|
1623
|
+
if (!id) return "-";
|
|
1624
|
+
const strId = String(id).trim();
|
|
1625
|
+
if (!strId) return "-";
|
|
1626
|
+
if (stableLabelCacheRef.current.has(strId)) {
|
|
1627
|
+
const cached = stableLabelCacheRef.current.get(strId);
|
|
1628
|
+
if (cached && cached !== "-" && !isRawObjectId(cached)) {
|
|
1629
|
+
return cached;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
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);
|
|
1633
|
+
if (dictOpt) {
|
|
1634
|
+
const lbl = resolveRelationLabel(dictOpt, column) || dictOpt.label || dictOpt.name;
|
|
1635
|
+
if (lbl && !isRawObjectId(String(lbl))) {
|
|
1636
|
+
stableLabelCacheRef.current.set(strId, String(lbl));
|
|
1637
|
+
return String(lbl);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
const foundInItems = items.find((o) => String(o.id) === strId);
|
|
1641
|
+
if (foundInItems) {
|
|
1642
|
+
const lbl = resolveRelationLabel(foundInItems, column) || foundInItems.label || foundInItems.name;
|
|
1643
|
+
if (lbl && !isRawObjectId(String(lbl))) {
|
|
1644
|
+
stableLabelCacheRef.current.set(strId, String(lbl));
|
|
1645
|
+
return String(lbl);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
const foundInBase = (baseOptions || []).find((o) => String(o.id) === strId);
|
|
1649
|
+
if (foundInBase) {
|
|
1650
|
+
const lbl = resolveRelationLabel(foundInBase, column) || foundInBase.label || foundInBase.name;
|
|
1651
|
+
if (lbl && !isRawObjectId(String(lbl))) {
|
|
1652
|
+
stableLabelCacheRef.current.set(strId, String(lbl));
|
|
1653
|
+
return String(lbl);
|
|
1654
|
+
}
|
|
1556
1655
|
}
|
|
1557
1656
|
return "-";
|
|
1558
|
-
}, [
|
|
1657
|
+
}, [items, baseOptions, column, context]);
|
|
1559
1658
|
const handleOpen = (e) => {
|
|
1560
1659
|
if (readOnly) return;
|
|
1561
1660
|
e == null ? void 0 : e.stopPropagation();
|
|
1562
|
-
|
|
1661
|
+
const nextOpen = !isOpen;
|
|
1662
|
+
if (nextOpen) {
|
|
1663
|
+
updateDropdownCoords();
|
|
1664
|
+
}
|
|
1665
|
+
setIsOpen(nextOpen);
|
|
1666
|
+
if (!nextOpen) return;
|
|
1563
1667
|
setSearchQuery("");
|
|
1564
|
-
|
|
1565
|
-
|
|
1668
|
+
setScrollTop(0);
|
|
1669
|
+
setSkip(0);
|
|
1670
|
+
skipRef.current = 0;
|
|
1671
|
+
setHasMore(true);
|
|
1672
|
+
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;
|
|
1673
|
+
if (fetcher && referencedTableId) {
|
|
1674
|
+
setIsLoadingMore(true);
|
|
1675
|
+
isLoadingMoreRef.current = true;
|
|
1676
|
+
fetcher({
|
|
1677
|
+
referencedTableId,
|
|
1678
|
+
displayField,
|
|
1679
|
+
take: BATCH_SIZE,
|
|
1680
|
+
limit: BATCH_SIZE,
|
|
1681
|
+
skip: 0
|
|
1682
|
+
}).then((res) => {
|
|
1683
|
+
const newData = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
|
|
1684
|
+
setItems(newData);
|
|
1685
|
+
setSkip(BATCH_SIZE);
|
|
1686
|
+
skipRef.current = BATCH_SIZE;
|
|
1687
|
+
if (newData.length < BATCH_SIZE) {
|
|
1688
|
+
setHasMore(false);
|
|
1689
|
+
}
|
|
1690
|
+
}).catch((err) => {
|
|
1691
|
+
console.warn("[RelationPickerCell] Initial fetch failed:", err);
|
|
1692
|
+
}).finally(() => {
|
|
1693
|
+
setIsLoadingMore(false);
|
|
1694
|
+
isLoadingMoreRef.current = false;
|
|
1695
|
+
});
|
|
1566
1696
|
}
|
|
1567
1697
|
};
|
|
1568
1698
|
useEffect5(() => {
|
|
@@ -1573,7 +1703,105 @@ function RelationPickerCell({
|
|
|
1573
1703
|
}, 50);
|
|
1574
1704
|
}
|
|
1575
1705
|
}, [isOpen]);
|
|
1576
|
-
|
|
1706
|
+
useEffect5(() => {
|
|
1707
|
+
if (!isOpen) return;
|
|
1708
|
+
const query = searchQuery.trim();
|
|
1709
|
+
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;
|
|
1710
|
+
if (!fetcher || !referencedTableId) return;
|
|
1711
|
+
setSkip(0);
|
|
1712
|
+
skipRef.current = 0;
|
|
1713
|
+
setHasMore(true);
|
|
1714
|
+
setScrollTop(0);
|
|
1715
|
+
if (listContainerRef.current) {
|
|
1716
|
+
listContainerRef.current.scrollTop = 0;
|
|
1717
|
+
}
|
|
1718
|
+
setIsRemoteSearching(true);
|
|
1719
|
+
const timer = setTimeout(() => {
|
|
1720
|
+
fetcher({
|
|
1721
|
+
referencedTableId,
|
|
1722
|
+
displayField,
|
|
1723
|
+
search: query,
|
|
1724
|
+
take: BATCH_SIZE,
|
|
1725
|
+
limit: BATCH_SIZE,
|
|
1726
|
+
skip: 0
|
|
1727
|
+
}).then((res) => {
|
|
1728
|
+
const newData = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
|
|
1729
|
+
setItems(newData);
|
|
1730
|
+
setSkip(BATCH_SIZE);
|
|
1731
|
+
skipRef.current = BATCH_SIZE;
|
|
1732
|
+
if (newData.length < BATCH_SIZE) {
|
|
1733
|
+
setHasMore(false);
|
|
1734
|
+
}
|
|
1735
|
+
}).catch((err) => {
|
|
1736
|
+
console.warn("[RelationPickerCell] Remote search failed:", err);
|
|
1737
|
+
}).finally(() => {
|
|
1738
|
+
setIsRemoteSearching(false);
|
|
1739
|
+
});
|
|
1740
|
+
}, 250);
|
|
1741
|
+
return () => clearTimeout(timer);
|
|
1742
|
+
}, [searchQuery, isOpen, referencedTableId, displayField, context, column.name]);
|
|
1743
|
+
const handleLoadMore = useCallback5(async () => {
|
|
1744
|
+
if (isLoadingMoreRef.current || !hasMore || !referencedTableId) return;
|
|
1745
|
+
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;
|
|
1746
|
+
if (!fetcher) return;
|
|
1747
|
+
isLoadingMoreRef.current = true;
|
|
1748
|
+
setIsLoadingMore(true);
|
|
1749
|
+
const currentQuery = searchQuery.trim();
|
|
1750
|
+
const currentSkip = skipRef.current;
|
|
1751
|
+
try {
|
|
1752
|
+
const res = await fetcher({
|
|
1753
|
+
referencedTableId,
|
|
1754
|
+
displayField,
|
|
1755
|
+
search: currentQuery,
|
|
1756
|
+
take: BATCH_SIZE,
|
|
1757
|
+
limit: BATCH_SIZE,
|
|
1758
|
+
skip: currentSkip
|
|
1759
|
+
});
|
|
1760
|
+
const newData = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
|
|
1761
|
+
if (newData.length < BATCH_SIZE) {
|
|
1762
|
+
setHasMore(false);
|
|
1763
|
+
}
|
|
1764
|
+
if (newData.length > 0) {
|
|
1765
|
+
setItems((prev) => {
|
|
1766
|
+
const seen = new Set(prev.map((i) => String(i.id)));
|
|
1767
|
+
const unique = newData.filter((i) => !seen.has(String(i.id)));
|
|
1768
|
+
return [...prev, ...unique];
|
|
1769
|
+
});
|
|
1770
|
+
setSkip((prev) => prev + BATCH_SIZE);
|
|
1771
|
+
skipRef.current += BATCH_SIZE;
|
|
1772
|
+
}
|
|
1773
|
+
} catch (err) {
|
|
1774
|
+
console.warn("[RelationPickerCell] Load more failed:", err);
|
|
1775
|
+
} finally {
|
|
1776
|
+
isLoadingMoreRef.current = false;
|
|
1777
|
+
setIsLoadingMore(false);
|
|
1778
|
+
}
|
|
1779
|
+
}, [hasMore, referencedTableId, searchQuery, context, column.name, displayField]);
|
|
1780
|
+
useEffect5(() => {
|
|
1781
|
+
if (!isOpen || !hasMore) return;
|
|
1782
|
+
const sentinel = sentinelRef.current;
|
|
1783
|
+
if (!sentinel) return;
|
|
1784
|
+
const observer = new IntersectionObserver(
|
|
1785
|
+
(entries) => {
|
|
1786
|
+
var _a2;
|
|
1787
|
+
if (((_a2 = entries[0]) == null ? void 0 : _a2.isIntersecting) && !isLoadingMoreRef.current) {
|
|
1788
|
+
handleLoadMore();
|
|
1789
|
+
}
|
|
1790
|
+
},
|
|
1791
|
+
{ root: listContainerRef.current, threshold: 0.1 }
|
|
1792
|
+
);
|
|
1793
|
+
observer.observe(sentinel);
|
|
1794
|
+
return () => observer.disconnect();
|
|
1795
|
+
}, [isOpen, hasMore, handleLoadMore]);
|
|
1796
|
+
const handleListScroll = (e) => {
|
|
1797
|
+
const currentScrollTop = e.currentTarget.scrollTop;
|
|
1798
|
+
setScrollTop(currentScrollTop);
|
|
1799
|
+
const { clientHeight, scrollHeight } = e.currentTarget;
|
|
1800
|
+
if (scrollHeight - (currentScrollTop + clientHeight) < 60 && hasMore && !isLoadingMoreRef.current) {
|
|
1801
|
+
handleLoadMore();
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1804
|
+
const handleSelectOption = useCallback5((optId) => {
|
|
1577
1805
|
if (!allowMultiple) {
|
|
1578
1806
|
onChange([optId]);
|
|
1579
1807
|
setIsOpen(false);
|
|
@@ -1584,7 +1812,7 @@ function RelationPickerCell({
|
|
|
1584
1812
|
onChange([...selectedIds, optId]);
|
|
1585
1813
|
}
|
|
1586
1814
|
}
|
|
1587
|
-
};
|
|
1815
|
+
}, [allowMultiple, onChange, selectedIds]);
|
|
1588
1816
|
const handleRemove = (idToRemove) => {
|
|
1589
1817
|
onChange(selectedIds.filter((id) => id !== idToRemove));
|
|
1590
1818
|
};
|
|
@@ -1595,7 +1823,8 @@ function RelationPickerCell({
|
|
|
1595
1823
|
useEffect5(() => {
|
|
1596
1824
|
if (!isOpen) return;
|
|
1597
1825
|
function handleClickOutside(event) {
|
|
1598
|
-
|
|
1826
|
+
const target = event.target;
|
|
1827
|
+
if (containerRef.current && !containerRef.current.contains(target) && dropdownRef.current && !dropdownRef.current.contains(target)) {
|
|
1599
1828
|
setIsOpen(false);
|
|
1600
1829
|
}
|
|
1601
1830
|
}
|
|
@@ -1611,13 +1840,19 @@ function RelationPickerCell({
|
|
|
1611
1840
|
document.removeEventListener("keydown", handleKeyDown);
|
|
1612
1841
|
};
|
|
1613
1842
|
}, [isOpen]);
|
|
1614
|
-
const
|
|
1843
|
+
const displayedOptions = useMemo3(() => {
|
|
1615
1844
|
const query = searchQuery.trim().toLowerCase();
|
|
1616
1845
|
if (!query) return processedOptions;
|
|
1617
1846
|
return processedOptions.filter((opt) => {
|
|
1618
1847
|
return (opt._displayLabel || "").toLowerCase().includes(query);
|
|
1619
1848
|
});
|
|
1620
1849
|
}, [processedOptions, searchQuery]);
|
|
1850
|
+
const totalItems = displayedOptions.length;
|
|
1851
|
+
const totalHeight = totalItems * ITEM_HEIGHT;
|
|
1852
|
+
const startIndex = Math.max(0, Math.floor(scrollTop / ITEM_HEIGHT) - OVERSCAN);
|
|
1853
|
+
const endIndex = Math.min(totalItems, Math.ceil((scrollTop + CONTAINER_HEIGHT) / ITEM_HEIGHT) + OVERSCAN);
|
|
1854
|
+
const visibleOptions = displayedOptions.slice(startIndex, endIndex);
|
|
1855
|
+
const topPadding = startIndex * ITEM_HEIGHT;
|
|
1621
1856
|
if (!optionsLoaded && selectedIds.length > 0) {
|
|
1622
1857
|
return /* @__PURE__ */ jsx6("div", { className: "px-2 py-1 flex items-center h-full w-full", children: /* @__PURE__ */ jsx6("span", { className: "inline-block w-16 h-4 bg-slate-100 animate-pulse rounded" }) });
|
|
1623
1858
|
}
|
|
@@ -1739,51 +1974,101 @@ function RelationPickerCell({
|
|
|
1739
1974
|
)
|
|
1740
1975
|
}
|
|
1741
1976
|
),
|
|
1742
|
-
isOpen &&
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1977
|
+
isOpen && dropdownCoords && typeof document !== "undefined" && createPortal(
|
|
1978
|
+
/* @__PURE__ */ jsxs6(
|
|
1979
|
+
"div",
|
|
1980
|
+
{
|
|
1981
|
+
ref: dropdownRef,
|
|
1982
|
+
id: `relation-dropdown-${column.name}-${rowId || "cell"}`,
|
|
1983
|
+
dir: "rtl",
|
|
1984
|
+
style: {
|
|
1985
|
+
position: "fixed",
|
|
1986
|
+
top: `${dropdownCoords.top}px`,
|
|
1987
|
+
right: `${dropdownCoords.right}px`,
|
|
1988
|
+
width: `${dropdownCoords.width}px`,
|
|
1989
|
+
zIndex: 99999
|
|
1990
|
+
},
|
|
1991
|
+
className: "bg-white rounded-md shadow-2xl border border-slate-200 p-1 animate-in fade-in duration-100 flex flex-col",
|
|
1992
|
+
onClick: (e) => e.stopPropagation(),
|
|
1993
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
1994
|
+
children: [
|
|
1995
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative mb-1", children: [
|
|
1996
|
+
/* @__PURE__ */ jsx6(Search, { className: "w-3.5 h-3.5 text-slate-400 absolute right-2 top-2 pointer-events-none" }),
|
|
1997
|
+
/* @__PURE__ */ jsx6(
|
|
1998
|
+
"input",
|
|
1999
|
+
{
|
|
2000
|
+
ref: searchInputRef,
|
|
2001
|
+
type: "text",
|
|
2002
|
+
placeholder: "\u05D7\u05E4\u05E9...",
|
|
2003
|
+
value: searchQuery,
|
|
2004
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
2005
|
+
onKeyDown: (e) => {
|
|
2006
|
+
if (e.key === "Escape") {
|
|
2007
|
+
e.stopPropagation();
|
|
2008
|
+
setIsOpen(false);
|
|
2009
|
+
}
|
|
2010
|
+
},
|
|
2011
|
+
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"
|
|
2012
|
+
}
|
|
2013
|
+
),
|
|
2014
|
+
isRemoteSearching && /* @__PURE__ */ jsx6(Loader2, { className: "w-3.5 h-3.5 text-blue-500 animate-spin absolute left-2 top-2 pointer-events-none" })
|
|
2015
|
+
] }),
|
|
1752
2016
|
/* @__PURE__ */ jsx6(
|
|
1753
|
-
"
|
|
2017
|
+
"div",
|
|
1754
2018
|
{
|
|
1755
|
-
ref:
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
2019
|
+
ref: listContainerRef,
|
|
2020
|
+
onScroll: handleListScroll,
|
|
2021
|
+
style: { maxHeight: `${CONTAINER_HEIGHT}px` },
|
|
2022
|
+
className: "overflow-y-auto relative",
|
|
2023
|
+
children: displayedOptions.length > 0 ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
2024
|
+
/* @__PURE__ */ jsx6("div", { style: { height: `${totalHeight}px`, position: "relative", width: "100%" }, children: /* @__PURE__ */ jsx6(
|
|
2025
|
+
"div",
|
|
2026
|
+
{
|
|
2027
|
+
style: {
|
|
2028
|
+
position: "absolute",
|
|
2029
|
+
top: 0,
|
|
2030
|
+
left: 0,
|
|
2031
|
+
right: 0,
|
|
2032
|
+
transform: `translateY(${topPadding}px)`
|
|
2033
|
+
},
|
|
2034
|
+
children: visibleOptions.map((opt) => /* @__PURE__ */ jsx6(
|
|
2035
|
+
RelationPickerRow,
|
|
2036
|
+
{
|
|
2037
|
+
id: opt.id,
|
|
2038
|
+
label: opt._displayLabel,
|
|
2039
|
+
isSelected: selectedIds.includes(opt.id),
|
|
2040
|
+
onSelect: handleSelectOption,
|
|
2041
|
+
height: ITEM_HEIGHT
|
|
2042
|
+
},
|
|
2043
|
+
opt.id
|
|
2044
|
+
))
|
|
2045
|
+
}
|
|
2046
|
+
) }),
|
|
2047
|
+
hasMore && /* @__PURE__ */ jsx6("div", { ref: sentinelRef, className: "pt-1 pb-0.5 px-2 text-center", children: isLoadingMore ? /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-center gap-1.5 text-xs text-slate-400 py-1", children: [
|
|
2048
|
+
/* @__PURE__ */ jsx6(Loader2, { className: "w-3 h-3 text-blue-500 animate-spin shrink-0" }),
|
|
2049
|
+
/* @__PURE__ */ jsx6("span", { children: "\u05D8\u05D5\u05E2\u05DF \u05E2\u05D5\u05D3 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA..." })
|
|
2050
|
+
] }) : /* @__PURE__ */ jsx6(
|
|
2051
|
+
"button",
|
|
2052
|
+
{
|
|
2053
|
+
type: "button",
|
|
2054
|
+
onClick: (e) => {
|
|
2055
|
+
e.stopPropagation();
|
|
2056
|
+
handleLoadMore();
|
|
2057
|
+
},
|
|
2058
|
+
className: "text-[11px] text-blue-600 hover:text-blue-700 hover:underline py-1 px-2 font-medium",
|
|
2059
|
+
children: "\u05D8\u05E2\u05DF \u05E2\u05D5\u05D3 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA..."
|
|
2060
|
+
}
|
|
2061
|
+
) })
|
|
2062
|
+
] }) : /* @__PURE__ */ jsx6("div", { className: "py-2.5 px-2 text-center text-xs text-slate-400 select-none", children: isRemoteSearching ? /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-center gap-1.5 py-1", children: [
|
|
2063
|
+
/* @__PURE__ */ jsx6(Loader2, { className: "w-3 h-3 text-blue-500 animate-spin shrink-0" }),
|
|
2064
|
+
/* @__PURE__ */ jsx6("span", { children: "\u05DE\u05D7\u05E4\u05E9 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA..." })
|
|
2065
|
+
] }) : 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" })
|
|
1767
2066
|
}
|
|
1768
2067
|
)
|
|
1769
|
-
]
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
"div",
|
|
1774
|
-
{
|
|
1775
|
-
onClick: () => handleSelectOption(opt.id),
|
|
1776
|
-
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"}`,
|
|
1777
|
-
children: [
|
|
1778
|
-
/* @__PURE__ */ jsx6("span", { className: "truncate flex-1", children: opt._displayLabel }),
|
|
1779
|
-
isSelected && /* @__PURE__ */ jsx6(Check3, { className: "w-3.5 h-3.5 text-blue-600 shrink-0 mr-1" })
|
|
1780
|
-
]
|
|
1781
|
-
},
|
|
1782
|
-
opt.id
|
|
1783
|
-
);
|
|
1784
|
-
}) : /* @__PURE__ */ jsx6("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" }) })
|
|
1785
|
-
]
|
|
1786
|
-
}
|
|
2068
|
+
]
|
|
2069
|
+
}
|
|
2070
|
+
),
|
|
2071
|
+
document.body
|
|
1787
2072
|
)
|
|
1788
2073
|
]
|
|
1789
2074
|
}
|
|
@@ -2204,7 +2489,7 @@ var FORM_INPUTS = {
|
|
|
2204
2489
|
};
|
|
2205
2490
|
|
|
2206
2491
|
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
2207
|
-
import { useState as
|
|
2492
|
+
import { useState as useState10, useEffect as useEffect8, useRef as useRef6, useCallback as useCallback8, useMemo as useMemo4 } from "react";
|
|
2208
2493
|
|
|
2209
2494
|
// src/utils/phone.ts
|
|
2210
2495
|
function sanitizePhoneNumber(phone) {
|
|
@@ -2362,6 +2647,7 @@ function useColumnReorder({
|
|
|
2362
2647
|
}
|
|
2363
2648
|
|
|
2364
2649
|
// src/components/TableBlock/columnTitleUtils.tsx
|
|
2650
|
+
import { useState as useState9, useEffect as useEffect7 } from "react";
|
|
2365
2651
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2366
2652
|
var canvas = null;
|
|
2367
2653
|
function measureTextWidth(text, font = '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif') {
|
|
@@ -2402,10 +2688,10 @@ function splitHeaderTitle(name) {
|
|
|
2402
2688
|
}
|
|
2403
2689
|
function calculateMinColumnWidth(name, isSubTable = false, colType) {
|
|
2404
2690
|
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';
|
|
2405
|
-
const chromeWidth = isSubTable ?
|
|
2406
|
-
let baseMin = isSubTable ?
|
|
2691
|
+
const chromeWidth = isSubTable ? 24 : 26;
|
|
2692
|
+
let baseMin = isSubTable ? 30 : 36;
|
|
2407
2693
|
if ((colType == null ? void 0 : colType.toUpperCase()) === "GOOGLE_CONTACT") {
|
|
2408
|
-
baseMin = isSubTable ?
|
|
2694
|
+
baseMin = isSubTable ? 100 : 110;
|
|
2409
2695
|
}
|
|
2410
2696
|
if (!name) return baseMin;
|
|
2411
2697
|
const { isSingleWord, line1, line2 } = splitHeaderTitle(name);
|
|
@@ -2419,12 +2705,16 @@ function calculateMinColumnWidth(name, isSubTable = false, colType) {
|
|
|
2419
2705
|
return Math.max(baseMin, Math.ceil(maxLine + chromeWidth));
|
|
2420
2706
|
}
|
|
2421
2707
|
function ColumnHeaderTitle({ name, width, isSubTable = false }) {
|
|
2708
|
+
const [isMounted, setIsMounted] = useState9(false);
|
|
2709
|
+
useEffect7(() => {
|
|
2710
|
+
setIsMounted(true);
|
|
2711
|
+
}, []);
|
|
2422
2712
|
const { isSingleWord, line1, line2 } = splitHeaderTitle(name);
|
|
2423
|
-
if (isSingleWord || !line2) {
|
|
2424
|
-
return /* @__PURE__ */ jsx8("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children:
|
|
2713
|
+
if (!isMounted || isSingleWord || !line2) {
|
|
2714
|
+
return /* @__PURE__ */ jsx8("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children: name });
|
|
2425
2715
|
}
|
|
2426
2716
|
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';
|
|
2427
|
-
const chromeWidth = isSubTable ?
|
|
2717
|
+
const chromeWidth = isSubTable ? 24 : 26;
|
|
2428
2718
|
const fullTitleWidth = measureTextWidth(name, font) + chromeWidth;
|
|
2429
2719
|
if (width !== void 0 && width >= fullTitleWidth) {
|
|
2430
2720
|
return /* @__PURE__ */ jsx8("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children: name });
|
|
@@ -2558,9 +2848,9 @@ function SubTableCell({
|
|
|
2558
2848
|
const isContact = colType === "GOOGLE_CONTACT";
|
|
2559
2849
|
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
2560
2850
|
const serverValue = (_b = record.data[column.name]) != null ? _b : colType === "BOOLEAN" ? false : "";
|
|
2561
|
-
const [draftValue, setDraftValue] =
|
|
2562
|
-
const [isDirty, setIsDirty] =
|
|
2563
|
-
const [validationError, setValidationError] =
|
|
2851
|
+
const [draftValue, setDraftValue] = useState10(serverValue);
|
|
2852
|
+
const [isDirty, setIsDirty] = useState10(false);
|
|
2853
|
+
const [validationError, setValidationError] = useState10(null);
|
|
2564
2854
|
const cellRef = useRef6(null);
|
|
2565
2855
|
const draftRef = useRef6(draftValue);
|
|
2566
2856
|
const isDirtyRef = useRef6(isDirty);
|
|
@@ -2577,7 +2867,7 @@ function SubTableCell({
|
|
|
2577
2867
|
recordIdRef.current = record.id;
|
|
2578
2868
|
columnRef.current = column;
|
|
2579
2869
|
onCommitRef.current = onCommit;
|
|
2580
|
-
|
|
2870
|
+
useEffect8(() => {
|
|
2581
2871
|
if (!isDirtyRef.current) {
|
|
2582
2872
|
setDraftValue(serverValue);
|
|
2583
2873
|
draftRef.current = serverValue;
|
|
@@ -2634,7 +2924,7 @@ function SubTableCell({
|
|
|
2634
2924
|
setValidationError(null);
|
|
2635
2925
|
lastFailedValRef.current = void 0;
|
|
2636
2926
|
}, []);
|
|
2637
|
-
|
|
2927
|
+
useEffect8(() => {
|
|
2638
2928
|
return () => {
|
|
2639
2929
|
if (isDirtyRef.current && !isCommittingRef.current) {
|
|
2640
2930
|
const val = draftRef.current;
|
|
@@ -2736,7 +3026,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2736
3026
|
var _a, _b, _c, _d, _e, _f;
|
|
2737
3027
|
const { addToast } = useToast();
|
|
2738
3028
|
const entries = Array.isArray(value) ? value : [];
|
|
2739
|
-
const [linkedRecords, setLinkedRecords] =
|
|
3029
|
+
const [linkedRecords, setLinkedRecords] = useState10(() => {
|
|
2740
3030
|
const initial = [];
|
|
2741
3031
|
for (const entry of entries) {
|
|
2742
3032
|
if (entry.recordId && entry._resolvedData) {
|
|
@@ -2745,15 +3035,15 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2745
3035
|
}
|
|
2746
3036
|
return initial;
|
|
2747
3037
|
});
|
|
2748
|
-
const [targetSchema, setTargetSchema] =
|
|
2749
|
-
const [isLoading, setIsLoading] =
|
|
2750
|
-
const [isSearchOpen, setIsSearchOpen] =
|
|
2751
|
-
const [searchQuery, setSearchQuery] =
|
|
2752
|
-
const [searchResults, setSearchResults] =
|
|
2753
|
-
const [isSearching, setIsSearching] =
|
|
2754
|
-
const [isCreating, setIsCreating] =
|
|
2755
|
-
const [newRecordData, setNewRecordData] =
|
|
2756
|
-
const [conflictModalState, setConflictModalState] =
|
|
3038
|
+
const [targetSchema, setTargetSchema] = useState10(null);
|
|
3039
|
+
const [isLoading, setIsLoading] = useState10(true);
|
|
3040
|
+
const [isSearchOpen, setIsSearchOpen] = useState10(false);
|
|
3041
|
+
const [searchQuery, setSearchQuery] = useState10("");
|
|
3042
|
+
const [searchResults, setSearchResults] = useState10([]);
|
|
3043
|
+
const [isSearching, setIsSearching] = useState10(false);
|
|
3044
|
+
const [isCreating, setIsCreating] = useState10(false);
|
|
3045
|
+
const [newRecordData, setNewRecordData] = useState10({});
|
|
3046
|
+
const [conflictModalState, setConflictModalState] = useState10({
|
|
2757
3047
|
isOpen: false,
|
|
2758
3048
|
fieldName: "",
|
|
2759
3049
|
matchingRecords: []
|
|
@@ -2763,7 +3053,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2763
3053
|
const executeAction = context == null ? void 0 : context.executeAction;
|
|
2764
3054
|
const referencedTableId = ((_a = column.config) == null ? void 0 : _a.referencedTableId) || column.referencedTableId;
|
|
2765
3055
|
const fetchedIdsRef = useRef6(/* @__PURE__ */ new Set());
|
|
2766
|
-
|
|
3056
|
+
useEffect8(() => {
|
|
2767
3057
|
if (entries.length > 0) {
|
|
2768
3058
|
setLinkedRecords((prev) => {
|
|
2769
3059
|
const existingIds = new Set(prev.map((r) => r.id));
|
|
@@ -2778,7 +3068,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2778
3068
|
});
|
|
2779
3069
|
}
|
|
2780
3070
|
}, [entries]);
|
|
2781
|
-
|
|
3071
|
+
useEffect8(() => {
|
|
2782
3072
|
if (!referencedTableId || !executeAction) {
|
|
2783
3073
|
setIsLoading(false);
|
|
2784
3074
|
return;
|
|
@@ -2805,7 +3095,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2805
3095
|
recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
|
|
2806
3096
|
}).finally(() => setIsLoading(false));
|
|
2807
3097
|
}, [referencedTableId, executeAction, entries, targetSchema]);
|
|
2808
|
-
|
|
3098
|
+
useEffect8(() => {
|
|
2809
3099
|
const handleClick = (e) => {
|
|
2810
3100
|
if (searchRef.current && !searchRef.current.contains(e.target)) {
|
|
2811
3101
|
setIsSearchOpen(false);
|
|
@@ -2840,8 +3130,8 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2840
3130
|
}
|
|
2841
3131
|
}, 300);
|
|
2842
3132
|
}, [executeAction, referencedTableId, entries]);
|
|
2843
|
-
const [localColumnOrder, setLocalColumnOrder] =
|
|
2844
|
-
|
|
3133
|
+
const [localColumnOrder, setLocalColumnOrder] = useState10(null);
|
|
3134
|
+
useEffect8(() => {
|
|
2845
3135
|
setLocalColumnOrder(null);
|
|
2846
3136
|
}, [column.name, (_b = column.config) == null ? void 0 : _b.subTableColumnOrder]);
|
|
2847
3137
|
const rawTargetColumns = useMemo4(() => {
|
|
@@ -2900,8 +3190,8 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2900
3190
|
return calculateMinColumnWidth(colName, true, col == null ? void 0 : col.type);
|
|
2901
3191
|
}
|
|
2902
3192
|
});
|
|
2903
|
-
const [relationOptions, setRelationOptions] =
|
|
2904
|
-
|
|
3193
|
+
const [relationOptions, setRelationOptions] = useState10({});
|
|
3194
|
+
useEffect8(() => {
|
|
2905
3195
|
if (!executeAction || !(targetSchema == null ? void 0 : targetSchema.columns) || targetSchema.columns.length === 0) return;
|
|
2906
3196
|
const relationCols = targetSchema.columns.filter((c) => {
|
|
2907
3197
|
var _a2, _b2;
|
|
@@ -2912,7 +3202,8 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2912
3202
|
try {
|
|
2913
3203
|
const options = await executeAction("FETCH_RELATION", {
|
|
2914
3204
|
referencedTableId: (_a2 = col.config) == null ? void 0 : _a2.referencedTableId,
|
|
2915
|
-
displayField: (_b2 = col.config) == null ? void 0 : _b2.displayField
|
|
3205
|
+
displayField: (_b2 = col.config) == null ? void 0 : _b2.displayField,
|
|
3206
|
+
limit: 1e3
|
|
2916
3207
|
});
|
|
2917
3208
|
if (options && Array.isArray(options)) {
|
|
2918
3209
|
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
@@ -2922,18 +3213,35 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
2922
3213
|
}
|
|
2923
3214
|
});
|
|
2924
3215
|
}, [executeAction, targetColumns]);
|
|
2925
|
-
const refetchRelation = useCallback8(async (colName) => {
|
|
2926
|
-
var _a2, _b2, _c2;
|
|
3216
|
+
const refetchRelation = useCallback8(async (colName, params) => {
|
|
3217
|
+
var _a2, _b2, _c2, _d2, _e2, _f2;
|
|
2927
3218
|
const col = targetColumns.find((c) => c.name === colName);
|
|
2928
|
-
if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !((_b2 = col.config) == null ? void 0 : _b2.referencedTableId) || !executeAction) return;
|
|
3219
|
+
if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !((_b2 = col.config) == null ? void 0 : _b2.referencedTableId) || !executeAction) return [];
|
|
2929
3220
|
try {
|
|
2930
|
-
const options = await executeAction("FETCH_RELATION", {
|
|
3221
|
+
const options = await executeAction("FETCH_RELATION", {
|
|
3222
|
+
referencedTableId: col.config.referencedTableId,
|
|
3223
|
+
displayField: (_c2 = col.config) == null ? void 0 : _c2.displayField,
|
|
3224
|
+
limit: (_d2 = params == null ? void 0 : params.limit) != null ? _d2 : 1e3,
|
|
3225
|
+
skip: (_e2 = params == null ? void 0 : params.skip) != null ? _e2 : 0,
|
|
3226
|
+
search: (_f2 = params == null ? void 0 : params.search) != null ? _f2 : ""
|
|
3227
|
+
});
|
|
2931
3228
|
if (options && Array.isArray(options)) {
|
|
2932
|
-
|
|
3229
|
+
if (params == null ? void 0 : params.append) {
|
|
3230
|
+
setRelationOptions((prev) => {
|
|
3231
|
+
const existing = prev[col.name] || [];
|
|
3232
|
+
const existingIds = new Set(existing.map((o) => String(o.id)));
|
|
3233
|
+
const uniqueNew = options.filter((o) => !existingIds.has(String(o.id)));
|
|
3234
|
+
return __spreadProps(__spreadValues({}, prev), { [col.name]: [...existing, ...uniqueNew] });
|
|
3235
|
+
});
|
|
3236
|
+
} else if (!(params == null ? void 0 : params.search)) {
|
|
3237
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
3238
|
+
}
|
|
3239
|
+
return options;
|
|
2933
3240
|
}
|
|
2934
3241
|
} catch (err) {
|
|
2935
3242
|
console.warn(`[SubTableViewer] Could not refetch relation options for column ${col.name}:`, err);
|
|
2936
3243
|
}
|
|
3244
|
+
return [];
|
|
2937
3245
|
}, [targetColumns, executeAction]);
|
|
2938
3246
|
const updateParentLinkage = async (updated) => {
|
|
2939
3247
|
const isNewRow = rowId.startsWith("temp_");
|
|
@@ -3067,7 +3375,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3067
3375
|
updateParentLinkage(updated);
|
|
3068
3376
|
};
|
|
3069
3377
|
const isMountedRef = useRef6(true);
|
|
3070
|
-
|
|
3378
|
+
useEffect8(() => {
|
|
3071
3379
|
isMountedRef.current = true;
|
|
3072
3380
|
return () => {
|
|
3073
3381
|
isMountedRef.current = false;
|
|
@@ -3602,12 +3910,352 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3602
3910
|
}
|
|
3603
3911
|
|
|
3604
3912
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
3605
|
-
import { X as
|
|
3913
|
+
import { X as X8, Copy as Copy2, RotateCcw as RotateCcw2, Download, Filter, Loader2 as Loader22 } from "lucide-react";
|
|
3914
|
+
|
|
3915
|
+
// src/components/TableBlock/RelationFilterPopover.tsx
|
|
3916
|
+
import { useState as useState11, useEffect as useEffect9, useRef as useRef7, useMemo as useMemo5, useCallback as useCallback9 } from "react";
|
|
3917
|
+
import { Search as Search2, X as X7, RotateCcw } from "lucide-react";
|
|
3606
3918
|
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3919
|
+
function calculatePopoverCoords(rect) {
|
|
3920
|
+
if (!rect || typeof window === "undefined") return null;
|
|
3921
|
+
const popoverWidth = 260;
|
|
3922
|
+
const popoverHeight = 360;
|
|
3923
|
+
let right = window.innerWidth - rect.right;
|
|
3924
|
+
if (right + popoverWidth > window.innerWidth - 10) {
|
|
3925
|
+
right = window.innerWidth - popoverWidth - 10;
|
|
3926
|
+
}
|
|
3927
|
+
if (right < 10) {
|
|
3928
|
+
right = 10;
|
|
3929
|
+
}
|
|
3930
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
3931
|
+
let top = rect.bottom + 6;
|
|
3932
|
+
if (spaceBelow < popoverHeight && rect.top > popoverHeight) {
|
|
3933
|
+
top = Math.max(10, rect.top - popoverHeight - 6);
|
|
3934
|
+
} else {
|
|
3935
|
+
top = Math.min(window.innerHeight - popoverHeight - 10, top);
|
|
3936
|
+
}
|
|
3937
|
+
return { top, right };
|
|
3938
|
+
}
|
|
3939
|
+
function RelationFilterPopover({
|
|
3940
|
+
isOpen,
|
|
3941
|
+
onClose,
|
|
3942
|
+
column,
|
|
3943
|
+
triggerRect,
|
|
3944
|
+
options,
|
|
3945
|
+
filterValue,
|
|
3946
|
+
selectedValues,
|
|
3947
|
+
onSelectionChange,
|
|
3948
|
+
isLoading = false
|
|
3949
|
+
}) {
|
|
3950
|
+
const popoverRef = useRef7(null);
|
|
3951
|
+
const searchInputRef = useRef7(null);
|
|
3952
|
+
const selectAllRef = useRef7(null);
|
|
3953
|
+
const [searchQuery, setSearchQuery] = useState11("");
|
|
3954
|
+
const [coords, setCoords] = useState11(
|
|
3955
|
+
() => calculatePopoverCoords(triggerRect)
|
|
3956
|
+
);
|
|
3957
|
+
const [mode, setMode] = useState11("include");
|
|
3958
|
+
const [checkedSet, setCheckedSet] = useState11(/* @__PURE__ */ new Set());
|
|
3959
|
+
const [excludedSet, setExcludedSet] = useState11(/* @__PURE__ */ new Set());
|
|
3960
|
+
const prevIsOpenRef = useRef7(isOpen);
|
|
3961
|
+
useEffect9(() => {
|
|
3962
|
+
const justOpened = isOpen && !prevIsOpenRef.current;
|
|
3963
|
+
prevIsOpenRef.current = isOpen;
|
|
3964
|
+
if (justOpened) {
|
|
3965
|
+
const activeVal = filterValue != null ? filterValue : selectedValues;
|
|
3966
|
+
if (activeVal && typeof activeVal === "object" && !Array.isArray(activeVal) && "operator" in activeVal && activeVal.operator === "notIn") {
|
|
3967
|
+
setMode("exclude");
|
|
3968
|
+
setExcludedSet(new Set(activeVal.values || []));
|
|
3969
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
3970
|
+
} else if (Array.isArray(activeVal) && activeVal.length > 0) {
|
|
3971
|
+
setMode("include");
|
|
3972
|
+
setCheckedSet(new Set(activeVal));
|
|
3973
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
3974
|
+
} else {
|
|
3975
|
+
setMode("include");
|
|
3976
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
3977
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3980
|
+
}, [isOpen, filterValue, selectedValues]);
|
|
3981
|
+
const updatePosition = useCallback9(() => {
|
|
3982
|
+
const next = calculatePopoverCoords(triggerRect);
|
|
3983
|
+
if (next) setCoords(next);
|
|
3984
|
+
}, [triggerRect]);
|
|
3985
|
+
useEffect9(() => {
|
|
3986
|
+
if (isOpen) {
|
|
3987
|
+
updatePosition();
|
|
3988
|
+
setTimeout(() => {
|
|
3989
|
+
var _a;
|
|
3990
|
+
return (_a = searchInputRef.current) == null ? void 0 : _a.focus();
|
|
3991
|
+
}, 50);
|
|
3992
|
+
} else {
|
|
3993
|
+
setSearchQuery("");
|
|
3994
|
+
}
|
|
3995
|
+
}, [isOpen, updatePosition]);
|
|
3996
|
+
useEffect9(() => {
|
|
3997
|
+
if (!isOpen) return;
|
|
3998
|
+
const handleScrollOrResize = () => updatePosition();
|
|
3999
|
+
window.addEventListener("scroll", handleScrollOrResize, true);
|
|
4000
|
+
window.addEventListener("resize", handleScrollOrResize);
|
|
4001
|
+
return () => {
|
|
4002
|
+
window.removeEventListener("scroll", handleScrollOrResize, true);
|
|
4003
|
+
window.removeEventListener("resize", handleScrollOrResize);
|
|
4004
|
+
};
|
|
4005
|
+
}, [isOpen, updatePosition]);
|
|
4006
|
+
useEffect9(() => {
|
|
4007
|
+
if (!isOpen) return;
|
|
4008
|
+
const handleMouseDown = (e) => {
|
|
4009
|
+
if (popoverRef.current && !popoverRef.current.contains(e.target)) {
|
|
4010
|
+
onClose();
|
|
4011
|
+
}
|
|
4012
|
+
};
|
|
4013
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4014
|
+
return () => {
|
|
4015
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
4016
|
+
};
|
|
4017
|
+
}, [isOpen, onClose]);
|
|
4018
|
+
useEffect9(() => {
|
|
4019
|
+
if (!isOpen) return;
|
|
4020
|
+
const handleKeyDown = (e) => {
|
|
4021
|
+
if (e.key === "Escape") {
|
|
4022
|
+
onClose();
|
|
4023
|
+
}
|
|
4024
|
+
};
|
|
4025
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4026
|
+
return () => {
|
|
4027
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
4028
|
+
};
|
|
4029
|
+
}, [isOpen, onClose]);
|
|
4030
|
+
const filteredOptions = useMemo5(() => {
|
|
4031
|
+
if (!searchQuery.trim()) return options;
|
|
4032
|
+
const q = searchQuery.trim().toLowerCase();
|
|
4033
|
+
return options.filter((opt) => opt.label.toLowerCase().includes(q));
|
|
4034
|
+
}, [options, searchQuery]);
|
|
4035
|
+
const isOptionChecked = useCallback9(
|
|
4036
|
+
(label) => {
|
|
4037
|
+
if (mode === "exclude") {
|
|
4038
|
+
return !excludedSet.has(label);
|
|
4039
|
+
}
|
|
4040
|
+
return checkedSet.has(label);
|
|
4041
|
+
},
|
|
4042
|
+
[mode, excludedSet, checkedSet]
|
|
4043
|
+
);
|
|
4044
|
+
const allFilteredSelected = useMemo5(() => {
|
|
4045
|
+
if (filteredOptions.length === 0) return false;
|
|
4046
|
+
return filteredOptions.every((opt) => isOptionChecked(opt.label));
|
|
4047
|
+
}, [filteredOptions, isOptionChecked]);
|
|
4048
|
+
const someFilteredSelected = useMemo5(() => {
|
|
4049
|
+
return filteredOptions.some((opt) => isOptionChecked(opt.label));
|
|
4050
|
+
}, [filteredOptions, isOptionChecked]);
|
|
4051
|
+
useEffect9(() => {
|
|
4052
|
+
if (selectAllRef.current) {
|
|
4053
|
+
selectAllRef.current.indeterminate = !allFilteredSelected && someFilteredSelected;
|
|
4054
|
+
}
|
|
4055
|
+
}, [allFilteredSelected, someFilteredSelected]);
|
|
4056
|
+
const handleToggleOption = (label) => {
|
|
4057
|
+
if (mode === "exclude") {
|
|
4058
|
+
const nextExcluded = new Set(excludedSet);
|
|
4059
|
+
if (nextExcluded.has(label)) {
|
|
4060
|
+
nextExcluded.delete(label);
|
|
4061
|
+
} else {
|
|
4062
|
+
nextExcluded.add(label);
|
|
4063
|
+
}
|
|
4064
|
+
setExcludedSet(nextExcluded);
|
|
4065
|
+
if (nextExcluded.size === 0) {
|
|
4066
|
+
onSelectionChange(void 0);
|
|
4067
|
+
} else {
|
|
4068
|
+
onSelectionChange({ operator: "notIn", values: Array.from(nextExcluded) });
|
|
4069
|
+
}
|
|
4070
|
+
} else {
|
|
4071
|
+
const nextChecked = new Set(checkedSet);
|
|
4072
|
+
if (nextChecked.has(label)) {
|
|
4073
|
+
nextChecked.delete(label);
|
|
4074
|
+
} else {
|
|
4075
|
+
nextChecked.add(label);
|
|
4076
|
+
}
|
|
4077
|
+
setCheckedSet(nextChecked);
|
|
4078
|
+
if (nextChecked.size === 0) {
|
|
4079
|
+
onSelectionChange(void 0);
|
|
4080
|
+
} else if (options.length > 0 && nextChecked.size >= options.length) {
|
|
4081
|
+
setMode("exclude");
|
|
4082
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4083
|
+
onSelectionChange(void 0);
|
|
4084
|
+
} else {
|
|
4085
|
+
onSelectionChange(Array.from(nextChecked));
|
|
4086
|
+
}
|
|
4087
|
+
}
|
|
4088
|
+
};
|
|
4089
|
+
const handleToggleSelectAll = (checked) => {
|
|
4090
|
+
if (checked) {
|
|
4091
|
+
setMode("exclude");
|
|
4092
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4093
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
4094
|
+
onSelectionChange(void 0);
|
|
4095
|
+
} else {
|
|
4096
|
+
setMode("include");
|
|
4097
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
4098
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4099
|
+
onSelectionChange(void 0);
|
|
4100
|
+
}
|
|
4101
|
+
};
|
|
4102
|
+
const handleResetFilter = () => {
|
|
4103
|
+
setMode("include");
|
|
4104
|
+
setCheckedSet(/* @__PURE__ */ new Set());
|
|
4105
|
+
setExcludedSet(/* @__PURE__ */ new Set());
|
|
4106
|
+
setSearchQuery("");
|
|
4107
|
+
onSelectionChange(void 0);
|
|
4108
|
+
};
|
|
4109
|
+
if (!isOpen || !coords) return null;
|
|
4110
|
+
const selectedCount = useMemo5(() => {
|
|
4111
|
+
if (mode === "exclude") {
|
|
4112
|
+
return Math.max(0, options.length - excludedSet.size);
|
|
4113
|
+
}
|
|
4114
|
+
return checkedSet.size;
|
|
4115
|
+
}, [mode, options.length, excludedSet.size, checkedSet.size]);
|
|
4116
|
+
return /* @__PURE__ */ jsxs10(
|
|
4117
|
+
"div",
|
|
4118
|
+
{
|
|
4119
|
+
ref: popoverRef,
|
|
4120
|
+
dir: "rtl",
|
|
4121
|
+
style: {
|
|
4122
|
+
top: `${coords.top}px`,
|
|
4123
|
+
right: `${coords.right}px`
|
|
4124
|
+
},
|
|
4125
|
+
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",
|
|
4126
|
+
onClick: (e) => e.stopPropagation(),
|
|
4127
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
4128
|
+
children: [
|
|
4129
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between border-b border-slate-100 pb-2 mb-2", children: [
|
|
4130
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
4131
|
+
/* @__PURE__ */ jsxs10("span", { className: "text-xs font-bold text-slate-700 truncate", children: [
|
|
4132
|
+
"\u05E1\u05D9\u05E0\u05D5\u05DF \u05DC\u05E4\u05D9 ",
|
|
4133
|
+
column.name
|
|
4134
|
+
] }),
|
|
4135
|
+
mode === "exclude" && excludedSet.size > 0 ? /* @__PURE__ */ jsxs10("span", { className: "text-[10px] text-amber-600 font-semibold", children: [
|
|
4136
|
+
"(\u05D4\u05DB\u05DC \u05DC\u05DE\u05E2\u05D8 ",
|
|
4137
|
+
excludedSet.size,
|
|
4138
|
+
")"
|
|
4139
|
+
] }) : mode === "exclude" && excludedSet.size === 0 ? /* @__PURE__ */ jsx10("span", { className: "text-[10px] text-brand font-semibold", children: "(\u05D4\u05DB\u05DC \u05E0\u05D1\u05D7\u05E8)" }) : selectedCount > 0 ? /* @__PURE__ */ jsxs10("span", { className: "text-[10px] text-brand font-semibold", children: [
|
|
4140
|
+
"(",
|
|
4141
|
+
selectedCount,
|
|
4142
|
+
" \u05E0\u05D1\u05D7\u05E8\u05D5)"
|
|
4143
|
+
] }) : null
|
|
4144
|
+
] }),
|
|
4145
|
+
/* @__PURE__ */ jsx10(
|
|
4146
|
+
"button",
|
|
4147
|
+
{
|
|
4148
|
+
type: "button",
|
|
4149
|
+
onClick: onClose,
|
|
4150
|
+
className: "text-slate-400 hover:text-slate-600 p-0.5 rounded hover:bg-slate-100 transition-colors cursor-pointer",
|
|
4151
|
+
title: "\u05E1\u05D2\u05D5\u05E8",
|
|
4152
|
+
children: /* @__PURE__ */ jsx10(X7, { className: "w-3.5 h-3.5" })
|
|
4153
|
+
}
|
|
4154
|
+
)
|
|
4155
|
+
] }),
|
|
4156
|
+
/* @__PURE__ */ jsxs10("div", { className: "relative mb-2", children: [
|
|
4157
|
+
/* @__PURE__ */ jsx10(Search2, { className: "w-3.5 h-3.5 text-slate-400 absolute right-2.5 top-1/2 -translate-y-1/2 pointer-events-none" }),
|
|
4158
|
+
/* @__PURE__ */ jsx10(
|
|
4159
|
+
"input",
|
|
4160
|
+
{
|
|
4161
|
+
ref: searchInputRef,
|
|
4162
|
+
type: "text",
|
|
4163
|
+
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA...",
|
|
4164
|
+
value: searchQuery,
|
|
4165
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
4166
|
+
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"
|
|
4167
|
+
}
|
|
4168
|
+
),
|
|
4169
|
+
searchQuery && /* @__PURE__ */ jsx10(
|
|
4170
|
+
"button",
|
|
4171
|
+
{
|
|
4172
|
+
type: "button",
|
|
4173
|
+
onClick: () => setSearchQuery(""),
|
|
4174
|
+
className: "absolute left-1.5 top-1/2 -translate-y-1/2 p-0.5 text-slate-400 hover:text-slate-600 rounded",
|
|
4175
|
+
children: /* @__PURE__ */ jsx10(X7, { className: "w-3 h-3" })
|
|
4176
|
+
}
|
|
4177
|
+
)
|
|
4178
|
+
] }),
|
|
4179
|
+
/* @__PURE__ */ jsxs10("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: [
|
|
4180
|
+
/* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-2 cursor-pointer text-xs font-medium text-slate-700 flex-1", children: [
|
|
4181
|
+
/* @__PURE__ */ jsx10(
|
|
4182
|
+
"input",
|
|
4183
|
+
{
|
|
4184
|
+
ref: selectAllRef,
|
|
4185
|
+
type: "checkbox",
|
|
4186
|
+
checked: allFilteredSelected,
|
|
4187
|
+
onChange: (e) => handleToggleSelectAll(e.target.checked),
|
|
4188
|
+
className: "w-3.5 h-3.5 rounded border-slate-300 text-brand focus:ring-brand cursor-pointer accent-[#0d9488]"
|
|
4189
|
+
}
|
|
4190
|
+
),
|
|
4191
|
+
/* @__PURE__ */ jsx10("span", { children: "\u05D1\u05D7\u05E8 \u05D4\u05DB\u05DC" })
|
|
4192
|
+
] }),
|
|
4193
|
+
(mode === "exclude" || checkedSet.size > 0) && /* @__PURE__ */ jsxs10(
|
|
4194
|
+
"button",
|
|
4195
|
+
{
|
|
4196
|
+
type: "button",
|
|
4197
|
+
onClick: handleResetFilter,
|
|
4198
|
+
className: "text-[11px] text-blue-600 hover:text-blue-700 hover:underline flex items-center gap-1 cursor-pointer",
|
|
4199
|
+
title: "\u05E0\u05E7\u05D4 \u05E1\u05D9\u05E0\u05D5\u05DF \u05D5\u05D4\u05E6\u05D2 \u05D4\u05DB\u05DC",
|
|
4200
|
+
children: [
|
|
4201
|
+
/* @__PURE__ */ jsx10(RotateCcw, { className: "w-2.5 h-2.5" }),
|
|
4202
|
+
/* @__PURE__ */ jsx10("span", { children: "\u05E0\u05E7\u05D4" })
|
|
4203
|
+
]
|
|
4204
|
+
}
|
|
4205
|
+
)
|
|
4206
|
+
] }),
|
|
4207
|
+
/* @__PURE__ */ jsx10("div", { className: "max-h-[250px] overflow-y-auto space-y-0.5 custom-scrollbar pr-0.5", children: isLoading ? /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-center py-6 text-slate-400 text-xs", children: [
|
|
4208
|
+
/* @__PURE__ */ jsx10("div", { className: "w-4 h-4 border-2 border-brand border-t-transparent rounded-full animate-spin ml-2" }),
|
|
4209
|
+
/* @__PURE__ */ jsx10("span", { children: "\u05D8\u05D5\u05E2\u05DF \u05D0\u05E4\u05E9\u05E8\u05D5\u05D9\u05D5\u05EA..." })
|
|
4210
|
+
] }) : filteredOptions.length === 0 ? /* @__PURE__ */ jsx10("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) => {
|
|
4211
|
+
const isChecked = isOptionChecked(opt.label);
|
|
4212
|
+
return /* @__PURE__ */ jsxs10(
|
|
4213
|
+
"label",
|
|
4214
|
+
{
|
|
4215
|
+
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"}`,
|
|
4216
|
+
children: [
|
|
4217
|
+
/* @__PURE__ */ jsx10(
|
|
4218
|
+
"input",
|
|
4219
|
+
{
|
|
4220
|
+
type: "checkbox",
|
|
4221
|
+
checked: isChecked,
|
|
4222
|
+
onChange: () => handleToggleOption(opt.label),
|
|
4223
|
+
className: "w-3.5 h-3.5 rounded border-slate-300 text-brand focus:ring-brand cursor-pointer accent-[#0d9488]"
|
|
4224
|
+
}
|
|
4225
|
+
),
|
|
4226
|
+
/* @__PURE__ */ jsx10("span", { className: "truncate flex-1", title: opt.label, children: opt.label })
|
|
4227
|
+
]
|
|
4228
|
+
},
|
|
4229
|
+
opt.id
|
|
4230
|
+
);
|
|
4231
|
+
}) }),
|
|
4232
|
+
/* @__PURE__ */ jsxs10("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: [
|
|
4233
|
+
/* @__PURE__ */ jsxs10("span", { children: [
|
|
4234
|
+
filteredOptions.length,
|
|
4235
|
+
" \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA"
|
|
4236
|
+
] }),
|
|
4237
|
+
/* @__PURE__ */ jsx10(
|
|
4238
|
+
"button",
|
|
4239
|
+
{
|
|
4240
|
+
type: "button",
|
|
4241
|
+
onClick: onClose,
|
|
4242
|
+
className: "text-slate-600 hover:text-slate-900 font-medium px-2 py-0.5 rounded hover:bg-slate-100 transition-colors cursor-pointer",
|
|
4243
|
+
children: "\u05E1\u05D2\u05D5\u05E8"
|
|
4244
|
+
}
|
|
4245
|
+
)
|
|
4246
|
+
] })
|
|
4247
|
+
]
|
|
4248
|
+
}
|
|
4249
|
+
);
|
|
4250
|
+
}
|
|
4251
|
+
|
|
4252
|
+
// src/components/TableBlock/TableBlockClient.tsx
|
|
4253
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3607
4254
|
function TableBlockClient({
|
|
3608
4255
|
data: initialRecords,
|
|
3609
4256
|
settings: schema,
|
|
3610
4257
|
executeAction,
|
|
4258
|
+
exportAction,
|
|
3611
4259
|
emitEvent,
|
|
3612
4260
|
pageState,
|
|
3613
4261
|
isLoading,
|
|
@@ -3620,6 +4268,7 @@ function TableBlockClient({
|
|
|
3620
4268
|
"data-testid": dataTestId
|
|
3621
4269
|
}) {
|
|
3622
4270
|
const { showError, addToast } = useToast();
|
|
4271
|
+
const [isExporting, setIsExporting] = useState12(false);
|
|
3623
4272
|
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";
|
|
3624
4273
|
const { columnWidths, startResize } = useColumnResize({
|
|
3625
4274
|
storageKey: `table_widths_${tableKey}`,
|
|
@@ -3630,14 +4279,18 @@ function TableBlockClient({
|
|
|
3630
4279
|
return calculateMinColumnWidth(colName, false, col == null ? void 0 : col.type);
|
|
3631
4280
|
}
|
|
3632
4281
|
});
|
|
3633
|
-
const
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
const [
|
|
3638
|
-
const [
|
|
3639
|
-
const [
|
|
3640
|
-
|
|
4282
|
+
const executeActionRef = useRef8(executeAction);
|
|
4283
|
+
useEffect10(() => {
|
|
4284
|
+
executeActionRef.current = executeAction;
|
|
4285
|
+
}, [executeAction]);
|
|
4286
|
+
const [isMounted, setIsMounted] = useState12(false);
|
|
4287
|
+
const [isInitialLoading, setIsInitialLoading] = useState12(true);
|
|
4288
|
+
const [page, setPage] = useState12(1);
|
|
4289
|
+
const [limit, setLimit] = useState12(50);
|
|
4290
|
+
const [totalRecords, setTotalRecords] = useState12(0);
|
|
4291
|
+
const [totalPages, setTotalPages] = useState12(1);
|
|
4292
|
+
const [showSummary, setShowSummary] = useState12(false);
|
|
4293
|
+
useEffect10(() => {
|
|
3641
4294
|
if (typeof window !== "undefined") {
|
|
3642
4295
|
const savedSummary = localStorage.getItem(`table_summary_${tableKey}`);
|
|
3643
4296
|
if (savedSummary !== null) {
|
|
@@ -3686,7 +4339,7 @@ function TableBlockClient({
|
|
|
3686
4339
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
3687
4340
|
});
|
|
3688
4341
|
};
|
|
3689
|
-
const mergeColumnDefs =
|
|
4342
|
+
const mergeColumnDefs = useCallback10((existingCols, incomingCols) => {
|
|
3690
4343
|
if (!incomingCols || incomingCols.length === 0) return existingCols || [];
|
|
3691
4344
|
if (!existingCols || existingCols.length === 0) return incomingCols;
|
|
3692
4345
|
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
@@ -3706,18 +4359,18 @@ function TableBlockClient({
|
|
|
3706
4359
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
3707
4360
|
});
|
|
3708
4361
|
}, []);
|
|
3709
|
-
const [localColumns, setLocalColumns] =
|
|
3710
|
-
|
|
4362
|
+
const [localColumns, setLocalColumns] = useState12(() => (schema == null ? void 0 : schema.columns) || []);
|
|
4363
|
+
useEffect10(() => {
|
|
3711
4364
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
3712
4365
|
setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
|
|
3713
4366
|
}
|
|
3714
4367
|
}, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
|
|
3715
|
-
const [dirty, setDirty] =
|
|
3716
|
-
const dirtyRef =
|
|
3717
|
-
|
|
4368
|
+
const [dirty, setDirty] = useState12({ added: [], modified: {}, deleted: [] });
|
|
4369
|
+
const dirtyRef = useRef8(dirty);
|
|
4370
|
+
useEffect10(() => {
|
|
3718
4371
|
dirtyRef.current = dirty;
|
|
3719
4372
|
}, [dirty]);
|
|
3720
|
-
const mergeWithDirty =
|
|
4373
|
+
const mergeWithDirty = useCallback10((baseRecords) => {
|
|
3721
4374
|
const { added, modified, deleted } = dirtyRef.current;
|
|
3722
4375
|
const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
|
|
3723
4376
|
const modifiedRecords = nonDeleted.map((r) => {
|
|
@@ -3730,9 +4383,10 @@ function TableBlockClient({
|
|
|
3730
4383
|
const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
|
|
3731
4384
|
return [...uniqueAdded, ...modifiedRecords];
|
|
3732
4385
|
}, []);
|
|
3733
|
-
const [data, setData] =
|
|
3734
|
-
const [serverRecords, setServerRecords] =
|
|
3735
|
-
|
|
4386
|
+
const [data, setData] = useState12(() => normalizeRecords(initialRecords));
|
|
4387
|
+
const [serverRecords, setServerRecords] = useState12(() => normalizeRecords(initialRecords));
|
|
4388
|
+
const filteredData = data;
|
|
4389
|
+
useEffect10(() => {
|
|
3736
4390
|
if (initialRecords) {
|
|
3737
4391
|
const norm = normalizeRecords(initialRecords);
|
|
3738
4392
|
setServerRecords(norm);
|
|
@@ -3749,31 +4403,118 @@ function TableBlockClient({
|
|
|
3749
4403
|
}
|
|
3750
4404
|
return false;
|
|
3751
4405
|
};
|
|
3752
|
-
const [baseRecordsMap, setBaseRecordsMap] =
|
|
4406
|
+
const [baseRecordsMap, setBaseRecordsMap] = useState12(() => {
|
|
3753
4407
|
const map = /* @__PURE__ */ new Map();
|
|
3754
4408
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
3755
4409
|
return map;
|
|
3756
4410
|
});
|
|
3757
|
-
|
|
4411
|
+
useEffect10(() => {
|
|
3758
4412
|
if (initialRecords && initialRecords.length > 0) {
|
|
3759
4413
|
const map = /* @__PURE__ */ new Map();
|
|
3760
4414
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
3761
4415
|
setBaseRecordsMap(map);
|
|
3762
4416
|
}
|
|
3763
4417
|
}, [initialRecords]);
|
|
3764
|
-
const
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
4418
|
+
const [searchQuery, setSearchQuery] = useState12("");
|
|
4419
|
+
const [columnFilters, setColumnFilters] = useState12({});
|
|
4420
|
+
const [activeSearchCol, setActiveSearchCol] = useState12(null);
|
|
4421
|
+
const activeSearchRef = useRef8(null);
|
|
4422
|
+
const [activeRelationCol, setActiveRelationCol] = useState12(null);
|
|
4423
|
+
const [relationTriggerRect, setRelationTriggerRect] = useState12(null);
|
|
4424
|
+
const filterButtonRefs = useRef8({});
|
|
4425
|
+
const [relationOptions, setRelationOptions] = useState12({});
|
|
4426
|
+
const [relationFilterOptions, setRelationFilterOptions] = useState12({});
|
|
4427
|
+
const [loadingFilterCol, setLoadingFilterCol] = useState12(null);
|
|
4428
|
+
const relationDictionaryRef = useRef8({});
|
|
4429
|
+
const mergeRelationOptions = useCallback10((colName, newOptions) => {
|
|
4430
|
+
if (!Array.isArray(newOptions) || newOptions.length === 0) return;
|
|
4431
|
+
if (!relationDictionaryRef.current[colName]) {
|
|
4432
|
+
relationDictionaryRef.current[colName] = /* @__PURE__ */ new Map();
|
|
4433
|
+
}
|
|
4434
|
+
const dict = relationDictionaryRef.current[colName];
|
|
4435
|
+
let hasNew = false;
|
|
4436
|
+
for (const opt of newOptions) {
|
|
4437
|
+
if (!opt) continue;
|
|
4438
|
+
const id = String(opt.id || opt._id || "");
|
|
4439
|
+
if (!id) continue;
|
|
4440
|
+
const existing = dict.get(id);
|
|
4441
|
+
if (!existing || opt.label && !existing.label) {
|
|
4442
|
+
dict.set(id, opt);
|
|
4443
|
+
hasNew = true;
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4446
|
+
if (hasNew) {
|
|
4447
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4448
|
+
[colName]: Array.from(dict.values())
|
|
4449
|
+
}));
|
|
4450
|
+
}
|
|
4451
|
+
}, []);
|
|
4452
|
+
useEffect10(() => {
|
|
4453
|
+
if (!activeSearchCol) return;
|
|
4454
|
+
const handleMouseDown = (e) => {
|
|
4455
|
+
if (activeSearchRef.current && !activeSearchRef.current.contains(e.target)) {
|
|
4456
|
+
setActiveSearchCol(null);
|
|
4457
|
+
}
|
|
4458
|
+
};
|
|
4459
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4460
|
+
return () => {
|
|
4461
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
4462
|
+
};
|
|
4463
|
+
}, [activeSearchCol]);
|
|
4464
|
+
const filtersKey = useMemo6(() => {
|
|
4465
|
+
const active = {};
|
|
4466
|
+
Object.entries(columnFilters).forEach(([k, v]) => {
|
|
4467
|
+
if (Array.isArray(v) && v.length > 0) active[k] = v;
|
|
4468
|
+
else if (v && typeof v === "object" && "operator" in v && Array.isArray(v.values) && v.values.length > 0) active[k] = v;
|
|
4469
|
+
else if (typeof v === "string" && v.trim()) active[k] = v.trim();
|
|
4470
|
+
});
|
|
4471
|
+
return JSON.stringify(active);
|
|
4472
|
+
}, [columnFilters]);
|
|
4473
|
+
const [debouncedSearch, setDebouncedSearch] = useState12(searchQuery);
|
|
4474
|
+
useEffect10(() => {
|
|
4475
|
+
const timer = setTimeout(() => {
|
|
4476
|
+
setDebouncedSearch(searchQuery.trim());
|
|
4477
|
+
}, 300);
|
|
4478
|
+
return () => clearTimeout(timer);
|
|
4479
|
+
}, [searchQuery]);
|
|
4480
|
+
const isSearchMountedRef = useRef8(false);
|
|
4481
|
+
useEffect10(() => {
|
|
4482
|
+
if (!isSearchMountedRef.current) {
|
|
4483
|
+
isSearchMountedRef.current = true;
|
|
4484
|
+
return;
|
|
4485
|
+
}
|
|
4486
|
+
setPage(1);
|
|
4487
|
+
}, [debouncedSearch]);
|
|
4488
|
+
const [isFetching, setIsFetching] = useState12(false);
|
|
4489
|
+
const fetchRequestIdRef = useRef8(0);
|
|
4490
|
+
const fetchTableData = useCallback10((targetPage, targetLimit, targetSearch, targetFiltersKey) => {
|
|
4491
|
+
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
4492
|
+
const action = executeActionRef.current;
|
|
4493
|
+
if (!tableId || !action) return Promise.resolve();
|
|
4494
|
+
const currentRequestId = ++fetchRequestIdRef.current;
|
|
4495
|
+
setIsFetching(true);
|
|
4496
|
+
let activeFilters = {};
|
|
4497
|
+
try {
|
|
4498
|
+
activeFilters = JSON.parse(targetFiltersKey);
|
|
4499
|
+
} catch (e) {
|
|
4500
|
+
}
|
|
4501
|
+
const skip = (targetPage - 1) * targetLimit;
|
|
4502
|
+
return action("FETCH_TABLE_DATA", {
|
|
4503
|
+
tableId,
|
|
4504
|
+
page: targetPage,
|
|
4505
|
+
limit: targetLimit,
|
|
4506
|
+
skip,
|
|
4507
|
+
search: targetSearch || void 0,
|
|
4508
|
+
columnFilters: Object.keys(activeFilters).length > 0 ? activeFilters : void 0
|
|
4509
|
+
}).then((res) => {
|
|
4510
|
+
var _a;
|
|
4511
|
+
if (currentRequestId !== fetchRequestIdRef.current) return;
|
|
4512
|
+
if (res) {
|
|
4513
|
+
if (((_a = res.schema) == null ? void 0 : _a.columns) && res.schema.columns.length > 0) {
|
|
4514
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, res.schema.columns));
|
|
4515
|
+
}
|
|
4516
|
+
if (res.records && Array.isArray(res.records)) {
|
|
4517
|
+
const norm = normalizeRecords(res.records);
|
|
3777
4518
|
const map = /* @__PURE__ */ new Map();
|
|
3778
4519
|
norm.forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
3779
4520
|
setBaseRecordsMap(map);
|
|
@@ -3782,37 +4523,50 @@ function TableBlockClient({
|
|
|
3782
4523
|
}
|
|
3783
4524
|
if (res.meta) {
|
|
3784
4525
|
const total = typeof res.meta.totalRecords === "number" ? res.meta.totalRecords : 0;
|
|
3785
|
-
const pages = typeof res.meta.totalPages === "number" ? res.meta.totalPages : Math.ceil(total /
|
|
4526
|
+
const pages = typeof res.meta.totalPages === "number" ? res.meta.totalPages : Math.ceil(total / targetLimit) || 1;
|
|
3786
4527
|
setTotalRecords(total);
|
|
3787
4528
|
setTotalPages(pages);
|
|
3788
|
-
if (activePage > pages && pages >= 1) {
|
|
3789
|
-
setPage(pages);
|
|
3790
|
-
}
|
|
3791
4529
|
} else if (res.records && Array.isArray(res.records)) {
|
|
3792
4530
|
setTotalRecords(res.records.length);
|
|
3793
|
-
setTotalPages(Math.ceil(res.records.length /
|
|
4531
|
+
setTotalPages(Math.ceil(res.records.length / targetLimit) || 1);
|
|
4532
|
+
}
|
|
4533
|
+
if (res.relationOptions && typeof res.relationOptions === "object") {
|
|
4534
|
+
for (const [colName, opts] of Object.entries(res.relationOptions)) {
|
|
4535
|
+
if (Array.isArray(opts)) {
|
|
4536
|
+
mergeRelationOptions(colName, opts);
|
|
4537
|
+
}
|
|
4538
|
+
}
|
|
3794
4539
|
}
|
|
3795
4540
|
}
|
|
3796
4541
|
}).catch((err) => {
|
|
3797
|
-
|
|
4542
|
+
if (currentRequestId === fetchRequestIdRef.current) {
|
|
4543
|
+
console.error("[TableBlock] Failed to fetch table data:", err);
|
|
4544
|
+
}
|
|
4545
|
+
}).finally(() => {
|
|
4546
|
+
if (currentRequestId === fetchRequestIdRef.current) {
|
|
4547
|
+
setIsFetching(false);
|
|
4548
|
+
setIsInitialLoading(false);
|
|
4549
|
+
}
|
|
3798
4550
|
});
|
|
3799
|
-
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id,
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
});
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
4551
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, mergeColumnDefs, mergeWithDirty, mergeRelationOptions]);
|
|
4552
|
+
useEffect10(() => {
|
|
4553
|
+
fetchTableData(page, limit, debouncedSearch, filtersKey);
|
|
4554
|
+
}, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
|
|
4555
|
+
const refetchTableData = useCallback10(() => {
|
|
4556
|
+
return fetchTableData(page, limit, debouncedSearch, filtersKey);
|
|
4557
|
+
}, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
|
|
4558
|
+
const handleApplyColumnFilter = useCallback10((colName, nextVal) => {
|
|
4559
|
+
setColumnFilters((prev) => {
|
|
4560
|
+
const next = __spreadValues({}, prev);
|
|
4561
|
+
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) {
|
|
4562
|
+
delete next[colName];
|
|
4563
|
+
} else {
|
|
4564
|
+
next[colName] = nextVal;
|
|
4565
|
+
}
|
|
4566
|
+
return next;
|
|
4567
|
+
});
|
|
4568
|
+
setPage(1);
|
|
4569
|
+
}, []);
|
|
3816
4570
|
const handleLimitChange = (newLimit) => {
|
|
3817
4571
|
setLimit(newLimit);
|
|
3818
4572
|
setPage(1);
|
|
@@ -3826,37 +4580,15 @@ function TableBlockClient({
|
|
|
3826
4580
|
const handleNextPage = () => {
|
|
3827
4581
|
setPage((prev) => Math.min(totalPages, prev + 1));
|
|
3828
4582
|
};
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
}
|
|
3833
|
-
}, [error, showError]);
|
|
3834
|
-
const [searchQuery, setSearchQuery] = useState10("");
|
|
3835
|
-
const [columnFilters, setColumnFilters] = useState10({});
|
|
3836
|
-
const [activeSearchCol, setActiveSearchCol] = useState10(null);
|
|
3837
|
-
const activeSearchRef = useRef7(null);
|
|
3838
|
-
useEffect8(() => {
|
|
3839
|
-
if (!activeSearchCol) return;
|
|
3840
|
-
const handleMouseDown = (e) => {
|
|
3841
|
-
if (activeSearchRef.current && !activeSearchRef.current.contains(e.target)) {
|
|
3842
|
-
setActiveSearchCol(null);
|
|
3843
|
-
}
|
|
3844
|
-
};
|
|
3845
|
-
document.addEventListener("mousedown", handleMouseDown);
|
|
3846
|
-
return () => {
|
|
3847
|
-
document.removeEventListener("mousedown", handleMouseDown);
|
|
3848
|
-
};
|
|
3849
|
-
}, [activeSearchCol]);
|
|
3850
|
-
const [selectedIds, setSelectedIds] = useState10(/* @__PURE__ */ new Set());
|
|
3851
|
-
const [pendingDeletions, setPendingDeletions] = useState10([]);
|
|
3852
|
-
const [isSaving, setIsSaving] = useState10(false);
|
|
4583
|
+
const [selectedIds, setSelectedIds] = useState12(/* @__PURE__ */ new Set());
|
|
4584
|
+
const [pendingDeletions, setPendingDeletions] = useState12([]);
|
|
4585
|
+
const [isSaving, setIsSaving] = useState12(false);
|
|
3853
4586
|
const isUpdatingActive = Boolean(isUpdating || isSaving);
|
|
3854
|
-
const [isSaveSuccess, setIsSaveSuccess] =
|
|
3855
|
-
const [
|
|
3856
|
-
const
|
|
3857
|
-
const
|
|
3858
|
-
|
|
3859
|
-
var _a, _b, _c;
|
|
4587
|
+
const [isSaveSuccess, setIsSaveSuccess] = useState12(false);
|
|
4588
|
+
const [expandedRowIds, setExpandedRowIds] = useState12(/* @__PURE__ */ new Set());
|
|
4589
|
+
const schemaColsString = useMemo6(() => JSON.stringify(localColumns || []), [localColumns]);
|
|
4590
|
+
const refetchRelation = useCallback10(async (colName, params) => {
|
|
4591
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3860
4592
|
let parsedCols = [];
|
|
3861
4593
|
try {
|
|
3862
4594
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -3866,19 +4598,125 @@ function TableBlockClient({
|
|
|
3866
4598
|
var _a2;
|
|
3867
4599
|
return c.name === colName && ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION";
|
|
3868
4600
|
});
|
|
3869
|
-
if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId)) return;
|
|
4601
|
+
if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId)) return [];
|
|
3870
4602
|
try {
|
|
3871
4603
|
if (executeAction) {
|
|
3872
|
-
const
|
|
3873
|
-
|
|
3874
|
-
|
|
4604
|
+
const take = (_c = (_b = params == null ? void 0 : params.take) != null ? _b : params == null ? void 0 : params.limit) != null ? _c : 1e3;
|
|
4605
|
+
const payload = {
|
|
4606
|
+
referencedTableId: (_d = col.config) == null ? void 0 : _d.referencedTableId,
|
|
4607
|
+
displayField: (_e = col.config) == null ? void 0 : _e.displayField
|
|
4608
|
+
};
|
|
4609
|
+
if (params == null ? void 0 : params.recordIds) {
|
|
4610
|
+
payload.recordIds = params.recordIds;
|
|
4611
|
+
} else {
|
|
4612
|
+
payload.take = take;
|
|
4613
|
+
payload.limit = take;
|
|
4614
|
+
payload.skip = (_f = params == null ? void 0 : params.skip) != null ? _f : 0;
|
|
4615
|
+
payload.search = (_g = params == null ? void 0 : params.search) != null ? _g : "";
|
|
4616
|
+
}
|
|
4617
|
+
const options = await executeAction("FETCH_RELATION", payload);
|
|
4618
|
+
const list = Array.isArray(options) ? options : (options == null ? void 0 : options.data) && Array.isArray(options.data) ? options.data : [];
|
|
4619
|
+
if (list && Array.isArray(list)) {
|
|
4620
|
+
mergeRelationOptions(colName, list);
|
|
4621
|
+
return list;
|
|
3875
4622
|
}
|
|
3876
4623
|
}
|
|
3877
4624
|
} catch (err) {
|
|
3878
4625
|
console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
|
|
3879
4626
|
}
|
|
3880
|
-
|
|
3881
|
-
|
|
4627
|
+
return [];
|
|
4628
|
+
}, [schemaColsString, executeAction, mergeRelationOptions]);
|
|
4629
|
+
const fetchRelationFilterOptions = useCallback10(async (colName) => {
|
|
4630
|
+
var _a;
|
|
4631
|
+
let parsedCols = [];
|
|
4632
|
+
try {
|
|
4633
|
+
parsedCols = JSON.parse(schemaColsString);
|
|
4634
|
+
} catch (e) {
|
|
4635
|
+
}
|
|
4636
|
+
const col = parsedCols.find((c) => {
|
|
4637
|
+
var _a2;
|
|
4638
|
+
return c.name === colName && ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION";
|
|
4639
|
+
});
|
|
4640
|
+
if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId) || !executeAction) return;
|
|
4641
|
+
const currentTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
4642
|
+
setLoadingFilterCol(colName);
|
|
4643
|
+
try {
|
|
4644
|
+
const res = await executeAction("FETCH_RELATION", {
|
|
4645
|
+
referencedTableId: col.config.referencedTableId,
|
|
4646
|
+
currentTableId,
|
|
4647
|
+
columnName: colName,
|
|
4648
|
+
isFilter: true,
|
|
4649
|
+
displayField: col.config.displayField,
|
|
4650
|
+
take: 1e3
|
|
4651
|
+
});
|
|
4652
|
+
const list = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
|
|
4653
|
+
setRelationFilterOptions((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4654
|
+
[colName]: list
|
|
4655
|
+
}));
|
|
4656
|
+
if (list.length > 0) {
|
|
4657
|
+
mergeRelationOptions(colName, list);
|
|
4658
|
+
}
|
|
4659
|
+
} catch (err) {
|
|
4660
|
+
console.warn(`[TableBlock] Failed to fetch distinct relation filter options for ${colName}:`, err);
|
|
4661
|
+
} finally {
|
|
4662
|
+
setLoadingFilterCol(null);
|
|
4663
|
+
}
|
|
4664
|
+
}, [schemaColsString, schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, executeAction, mergeRelationOptions]);
|
|
4665
|
+
const requestedRelationIdsRef = useRef8({});
|
|
4666
|
+
useEffect10(() => {
|
|
4667
|
+
if (!executeAction || !data || data.length === 0) return;
|
|
4668
|
+
let parsedCols = [];
|
|
4669
|
+
try {
|
|
4670
|
+
parsedCols = JSON.parse(schemaColsString);
|
|
4671
|
+
} catch (e) {
|
|
4672
|
+
}
|
|
4673
|
+
const relationCols = parsedCols.filter(
|
|
4674
|
+
(c) => {
|
|
4675
|
+
var _a;
|
|
4676
|
+
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
|
|
4677
|
+
}
|
|
4678
|
+
);
|
|
4679
|
+
if (relationCols.length === 0) return;
|
|
4680
|
+
relationCols.forEach(async (col) => {
|
|
4681
|
+
var _a, _b;
|
|
4682
|
+
const referencedTableId = (_a = col.config) == null ? void 0 : _a.referencedTableId;
|
|
4683
|
+
if (!referencedTableId) return;
|
|
4684
|
+
const extractedIds = /* @__PURE__ */ new Set();
|
|
4685
|
+
data.forEach((row) => {
|
|
4686
|
+
if (!(row == null ? void 0 : row.data)) return;
|
|
4687
|
+
const ids = normalizeRelationValue(row.data[col.name]);
|
|
4688
|
+
ids.forEach((id) => {
|
|
4689
|
+
if (/^[0-9a-fA-F]{24}$/.test(id)) {
|
|
4690
|
+
extractedIds.add(id);
|
|
4691
|
+
}
|
|
4692
|
+
});
|
|
4693
|
+
});
|
|
4694
|
+
if (extractedIds.size === 0) return;
|
|
4695
|
+
const existingOptions = relationOptions[col.name] || [];
|
|
4696
|
+
const existingIds = new Set(existingOptions.map((o) => String(o.id)));
|
|
4697
|
+
if (!requestedRelationIdsRef.current[col.name]) {
|
|
4698
|
+
requestedRelationIdsRef.current[col.name] = /* @__PURE__ */ new Set();
|
|
4699
|
+
}
|
|
4700
|
+
const inFlight = requestedRelationIdsRef.current[col.name];
|
|
4701
|
+
const missingIds = Array.from(extractedIds).filter((id) => !existingIds.has(id) && !inFlight.has(id));
|
|
4702
|
+
if (missingIds.length === 0) return;
|
|
4703
|
+
missingIds.forEach((id) => inFlight.add(id));
|
|
4704
|
+
try {
|
|
4705
|
+
const resolved = await executeAction("FETCH_RELATION", {
|
|
4706
|
+
referencedTableId,
|
|
4707
|
+
displayField: (_b = col.config) == null ? void 0 : _b.displayField,
|
|
4708
|
+
recordIds: missingIds
|
|
4709
|
+
});
|
|
4710
|
+
const items = Array.isArray(resolved) ? resolved : (resolved == null ? void 0 : resolved.data) && Array.isArray(resolved.data) ? resolved.data : [];
|
|
4711
|
+
if (items.length > 0) {
|
|
4712
|
+
mergeRelationOptions(col.name, items);
|
|
4713
|
+
}
|
|
4714
|
+
} catch (err) {
|
|
4715
|
+
console.warn(`[TableBlock] Failed to populate relations for ${col.name}:`, err);
|
|
4716
|
+
}
|
|
4717
|
+
});
|
|
4718
|
+
}, [data, schemaColsString, executeAction, relationOptions, mergeRelationOptions]);
|
|
4719
|
+
useEffect10(() => {
|
|
3882
4720
|
let parsedCols = [];
|
|
3883
4721
|
try {
|
|
3884
4722
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -3892,7 +4730,7 @@ function TableBlockClient({
|
|
|
3892
4730
|
refetchRelation(col.name);
|
|
3893
4731
|
});
|
|
3894
4732
|
}, [schemaColsString, refetchRelation]);
|
|
3895
|
-
const normalizedColumns =
|
|
4733
|
+
const normalizedColumns = useMemo6(() => {
|
|
3896
4734
|
return (localColumns || []).map((col, idx) => {
|
|
3897
4735
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
3898
4736
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
@@ -3906,17 +4744,17 @@ function TableBlockClient({
|
|
|
3906
4744
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
3907
4745
|
});
|
|
3908
4746
|
}, [localColumns]);
|
|
3909
|
-
const filteredColumns =
|
|
4747
|
+
const filteredColumns = useMemo6(() => {
|
|
3910
4748
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
3911
4749
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
|
|
3912
4750
|
}, [normalizedColumns]);
|
|
3913
|
-
const customizableColumns =
|
|
4751
|
+
const customizableColumns = useMemo6(() => {
|
|
3914
4752
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
3915
4753
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name));
|
|
3916
4754
|
}, [normalizedColumns]);
|
|
3917
|
-
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] =
|
|
3918
|
-
const dropdownRef =
|
|
3919
|
-
|
|
4755
|
+
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState12(false);
|
|
4756
|
+
const dropdownRef = useRef8(null);
|
|
4757
|
+
useEffect10(() => {
|
|
3920
4758
|
const handleClickOutside = (e) => {
|
|
3921
4759
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
3922
4760
|
setIsColumnsDropdownOpen(false);
|
|
@@ -4126,46 +4964,45 @@ function TableBlockClient({
|
|
|
4126
4964
|
setData((prev) => [newRow, ...prev]);
|
|
4127
4965
|
setDirty((prev) => __spreadProps(__spreadValues({}, prev), { added: [newRow, ...prev.added] }));
|
|
4128
4966
|
};
|
|
4129
|
-
const handleCellChange = (rowId, colName, value) => {
|
|
4967
|
+
const handleCellChange = useCallback10((rowId, colName, value) => {
|
|
4130
4968
|
setData((prev) => prev.map(
|
|
4131
4969
|
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
4132
4970
|
));
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
added: prev.added.map(
|
|
4137
|
-
(r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
|
|
4138
|
-
)
|
|
4139
|
-
}));
|
|
4140
|
-
} else {
|
|
4141
|
-
const origData = baseRecordsMap.get(rowId) || {};
|
|
4142
|
-
const origValue = origData[colName];
|
|
4143
|
-
setDirty((prev) => {
|
|
4144
|
-
const currentMods = __spreadValues({}, prev.modified[rowId] || {});
|
|
4145
|
-
if (isEqualValues(value, origValue)) {
|
|
4146
|
-
delete currentMods[colName];
|
|
4147
|
-
} else {
|
|
4148
|
-
currentMods[colName] = value;
|
|
4149
|
-
}
|
|
4150
|
-
const nextModified = __spreadValues({}, prev.modified);
|
|
4151
|
-
if (Object.keys(currentMods).length === 0) {
|
|
4152
|
-
delete nextModified[rowId];
|
|
4153
|
-
} else {
|
|
4154
|
-
nextModified[rowId] = currentMods;
|
|
4155
|
-
}
|
|
4971
|
+
setDirty((prev) => {
|
|
4972
|
+
const isAdded = prev.added.some((r) => r.id === rowId);
|
|
4973
|
+
if (isAdded) {
|
|
4156
4974
|
return __spreadProps(__spreadValues({}, prev), {
|
|
4157
|
-
|
|
4975
|
+
added: prev.added.map(
|
|
4976
|
+
(r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
|
|
4977
|
+
)
|
|
4158
4978
|
});
|
|
4979
|
+
}
|
|
4980
|
+
const origData = baseRecordsMap.get(rowId) || {};
|
|
4981
|
+
const origValue = origData[colName];
|
|
4982
|
+
const currentMods = __spreadValues({}, prev.modified[rowId] || {});
|
|
4983
|
+
if (isEqualValues(value, origValue)) {
|
|
4984
|
+
delete currentMods[colName];
|
|
4985
|
+
} else {
|
|
4986
|
+
currentMods[colName] = value;
|
|
4987
|
+
}
|
|
4988
|
+
const nextModified = __spreadValues({}, prev.modified);
|
|
4989
|
+
if (Object.keys(currentMods).length === 0) {
|
|
4990
|
+
delete nextModified[rowId];
|
|
4991
|
+
} else {
|
|
4992
|
+
nextModified[rowId] = currentMods;
|
|
4993
|
+
}
|
|
4994
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
4995
|
+
modified: nextModified
|
|
4159
4996
|
});
|
|
4160
|
-
}
|
|
4161
|
-
};
|
|
4162
|
-
const triggerSaveSuccess =
|
|
4997
|
+
});
|
|
4998
|
+
}, [baseRecordsMap]);
|
|
4999
|
+
const triggerSaveSuccess = useCallback10(() => {
|
|
4163
5000
|
setIsSaveSuccess(true);
|
|
4164
5001
|
setTimeout(() => {
|
|
4165
5002
|
setIsSaveSuccess(false);
|
|
4166
5003
|
}, 2500);
|
|
4167
5004
|
}, []);
|
|
4168
|
-
const handleQuietCellChange =
|
|
5005
|
+
const handleQuietCellChange = useCallback10((rowId, colName, value) => {
|
|
4169
5006
|
setData((prev) => prev.map(
|
|
4170
5007
|
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
4171
5008
|
));
|
|
@@ -4189,22 +5026,28 @@ function TableBlockClient({
|
|
|
4189
5026
|
});
|
|
4190
5027
|
}
|
|
4191
5028
|
}, []);
|
|
4192
|
-
const toggleSelectAll = (checked) => {
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
5029
|
+
const toggleSelectAll = useCallback10((checked) => {
|
|
5030
|
+
setSelectedIds(checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set());
|
|
5031
|
+
}, [filteredData]);
|
|
5032
|
+
const toggleSelectRow = useCallback10((rowId, checked) => {
|
|
5033
|
+
setSelectedIds((prev) => {
|
|
5034
|
+
const next = new Set(prev);
|
|
5035
|
+
if (checked) next.add(rowId);
|
|
5036
|
+
else next.delete(rowId);
|
|
5037
|
+
return next;
|
|
5038
|
+
});
|
|
5039
|
+
}, []);
|
|
5040
|
+
const handleToggleExpand = useCallback10((rowId) => {
|
|
5041
|
+
setExpandedRowIds((prev) => {
|
|
5042
|
+
const next = new Set(prev);
|
|
5043
|
+
if (next.has(rowId)) next.delete(rowId);
|
|
5044
|
+
else next.add(rowId);
|
|
5045
|
+
return next;
|
|
5046
|
+
});
|
|
5047
|
+
}, []);
|
|
5048
|
+
const handleMarkForDeletion = useCallback10((fileId) => {
|
|
5049
|
+
setPendingDeletions((prev) => [...prev, fileId]);
|
|
5050
|
+
}, []);
|
|
4208
5051
|
const handleDeleteSelected = () => {
|
|
4209
5052
|
const idsToDelete = Array.from(selectedIds);
|
|
4210
5053
|
if (idsToDelete.length === 0) return;
|
|
@@ -4283,9 +5126,6 @@ function TableBlockClient({
|
|
|
4283
5126
|
setData(serverRecords.map((r) => __spreadProps(__spreadValues({}, r), { data: __spreadValues({}, r.data) })));
|
|
4284
5127
|
setSelectedIds(/* @__PURE__ */ new Set());
|
|
4285
5128
|
setPendingDeletions([]);
|
|
4286
|
-
if (emitEvent) {
|
|
4287
|
-
emitEvent("SELECTION_CHANGE", { selectedIds: [], componentId });
|
|
4288
|
-
}
|
|
4289
5129
|
};
|
|
4290
5130
|
const handleSave = async () => {
|
|
4291
5131
|
var _a, _b;
|
|
@@ -4433,7 +5273,7 @@ function TableBlockClient({
|
|
|
4433
5273
|
setIsSaving(false);
|
|
4434
5274
|
}
|
|
4435
5275
|
};
|
|
4436
|
-
const getRowRelationLabels =
|
|
5276
|
+
const getRowRelationLabels = useCallback10((rowVal, col) => {
|
|
4437
5277
|
const ids = normalizeRelationValue(rowVal);
|
|
4438
5278
|
if (ids.length === 0) return [];
|
|
4439
5279
|
const options = relationOptions[col.name] || [];
|
|
@@ -4441,19 +5281,23 @@ function TableBlockClient({
|
|
|
4441
5281
|
const opt = options.find((o) => o.id === id || o._id === id);
|
|
4442
5282
|
if (opt) {
|
|
4443
5283
|
const resolved = resolveRelationLabel(opt, col);
|
|
4444
|
-
if (resolved) return resolved;
|
|
4445
|
-
if (opt.label) return String(opt.label);
|
|
4446
|
-
if (opt.name) return String(opt.name);
|
|
5284
|
+
if (resolved && !isRawObjectId(resolved)) return resolved;
|
|
5285
|
+
if (opt.label && !isRawObjectId(String(opt.label))) return String(opt.label);
|
|
5286
|
+
if (opt.name && !isRawObjectId(String(opt.name))) return String(opt.name);
|
|
4447
5287
|
}
|
|
4448
5288
|
if (typeof rowVal === "object" && rowVal !== null) {
|
|
4449
|
-
if (rowVal._displayLabel) return String(rowVal._displayLabel);
|
|
4450
|
-
if (rowVal.label) return String(rowVal.label);
|
|
5289
|
+
if (rowVal._displayLabel && !isRawObjectId(String(rowVal._displayLabel))) return String(rowVal._displayLabel);
|
|
5290
|
+
if (rowVal.label && !isRawObjectId(String(rowVal.label))) return String(rowVal.label);
|
|
4451
5291
|
}
|
|
4452
|
-
return
|
|
4453
|
-
});
|
|
5292
|
+
return "";
|
|
5293
|
+
}).filter(Boolean);
|
|
4454
5294
|
}, [relationOptions]);
|
|
4455
|
-
const getUniqueRelationOptions =
|
|
5295
|
+
const getUniqueRelationOptions = useCallback10((col) => {
|
|
5296
|
+
if (relationFilterOptions[col.name]) {
|
|
5297
|
+
return relationFilterOptions[col.name];
|
|
5298
|
+
}
|
|
4456
5299
|
const seenIds = /* @__PURE__ */ new Set();
|
|
5300
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
4457
5301
|
const results = [];
|
|
4458
5302
|
const options = relationOptions[col.name] || [];
|
|
4459
5303
|
data.forEach((row) => {
|
|
@@ -4464,58 +5308,23 @@ function TableBlockClient({
|
|
|
4464
5308
|
seenIds.add(id);
|
|
4465
5309
|
const opt = options.find((o) => o.id === id || o._id === id);
|
|
4466
5310
|
let label = opt ? resolveRelationLabel(opt, col) : "";
|
|
4467
|
-
if (!label && opt)
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
});
|
|
4473
|
-
return results.sort((a, b) => a.label.localeCompare(b.label));
|
|
4474
|
-
}, [data, relationOptions]);
|
|
4475
|
-
const filteredData = useMemo5(() => {
|
|
4476
|
-
const hasGlobalSearch = Boolean(searchQuery && searchQuery.trim() !== "");
|
|
4477
|
-
const activeFilters = Object.entries(columnFilters).filter(([, val]) => Boolean(val && val.trim() !== ""));
|
|
4478
|
-
const hasColumnFilters = activeFilters.length > 0;
|
|
4479
|
-
if (!hasGlobalSearch && !hasColumnFilters) return data;
|
|
4480
|
-
const lowerGlobal = hasGlobalSearch ? searchQuery.trim().toLowerCase() : "";
|
|
4481
|
-
return data.filter((row) => {
|
|
4482
|
-
var _a;
|
|
4483
|
-
if (!row || !row.data) return false;
|
|
4484
|
-
if (hasGlobalSearch) {
|
|
4485
|
-
const matchesGlobal = (localColumns || []).some((col) => {
|
|
4486
|
-
var _a2;
|
|
4487
|
-
const rawVal = row.data[col.name];
|
|
4488
|
-
if (rawVal === void 0 || rawVal === null) return false;
|
|
4489
|
-
if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION") {
|
|
4490
|
-
const labels = getRowRelationLabels(rawVal, col);
|
|
4491
|
-
return labels.some((l) => l.toLowerCase().includes(lowerGlobal));
|
|
5311
|
+
if (!label && opt) {
|
|
5312
|
+
const fallback = opt.label || opt.name || opt.title;
|
|
5313
|
+
if (fallback && typeof fallback === "string" && !isRawObjectId(fallback)) {
|
|
5314
|
+
label = fallback.trim();
|
|
5315
|
+
}
|
|
4492
5316
|
}
|
|
4493
|
-
if (
|
|
4494
|
-
|
|
5317
|
+
if (label && label.trim() && label !== id && !isRawObjectId(label) && !seenLabels.has(label.trim())) {
|
|
5318
|
+
seenLabels.add(label.trim());
|
|
5319
|
+
results.push({ id, label: label.trim() });
|
|
4495
5320
|
}
|
|
4496
|
-
return String(rawVal).toLowerCase().includes(lowerGlobal);
|
|
4497
|
-
});
|
|
4498
|
-
if (!matchesGlobal) return false;
|
|
4499
|
-
}
|
|
4500
|
-
for (const [colName, filterVal] of activeFilters) {
|
|
4501
|
-
const lowerFilter = filterVal.trim().toLowerCase();
|
|
4502
|
-
const col = (localColumns || []).find((c) => c.name === colName);
|
|
4503
|
-
const rawVal = row.data[colName];
|
|
4504
|
-
if (((_a = col == null ? void 0 : col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION") {
|
|
4505
|
-
const labels = getRowRelationLabels(rawVal, col);
|
|
4506
|
-
const matches = labels.some((l) => l.toLowerCase().includes(lowerFilter));
|
|
4507
|
-
if (!matches) return false;
|
|
4508
|
-
} else {
|
|
4509
|
-
if (rawVal === void 0 || rawVal === null) return false;
|
|
4510
|
-
const strVal = typeof rawVal === "object" ? JSON.stringify(rawVal).toLowerCase() : String(rawVal).toLowerCase();
|
|
4511
|
-
if (!strVal.includes(lowerFilter)) return false;
|
|
4512
5321
|
}
|
|
4513
|
-
}
|
|
4514
|
-
return true;
|
|
5322
|
+
});
|
|
4515
5323
|
});
|
|
4516
|
-
|
|
5324
|
+
return results.sort((a, b) => a.label.localeCompare(b.label));
|
|
5325
|
+
}, [data, relationOptions, relationFilterOptions]);
|
|
4517
5326
|
const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
|
|
4518
|
-
const columnTotals =
|
|
5327
|
+
const columnTotals = useMemo6(() => {
|
|
4519
5328
|
const totals = {};
|
|
4520
5329
|
if (!showSummary) return totals;
|
|
4521
5330
|
filteredColumns.forEach((col) => {
|
|
@@ -4533,42 +5342,120 @@ function TableBlockClient({
|
|
|
4533
5342
|
});
|
|
4534
5343
|
return totals;
|
|
4535
5344
|
}, [filteredData, filteredColumns, showSummary]);
|
|
4536
|
-
|
|
5345
|
+
const hasSelectedRows = selectedIds.size > 0;
|
|
5346
|
+
const hasActiveSearchOrFilter = Boolean(searchQuery && searchQuery.trim() !== "") || Object.values(columnFilters).some(
|
|
5347
|
+
(v) => Array.isArray(v) ? v.length > 0 : v && typeof v === "object" && "values" in v ? v.values.length > 0 : typeof v === "string" && Boolean(v.trim())
|
|
5348
|
+
);
|
|
5349
|
+
let exportButtonText = "\u05D9\u05D9\u05E6\u05D0 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD";
|
|
5350
|
+
let ExportButtonIcon = Download;
|
|
5351
|
+
if (hasSelectedRows) {
|
|
5352
|
+
exportButtonText = `\u05D9\u05D9\u05E6\u05D0 ${selectedIds.size} \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA`;
|
|
5353
|
+
ExportButtonIcon = Download;
|
|
5354
|
+
} else if (hasActiveSearchOrFilter) {
|
|
5355
|
+
exportButtonText = "\u05D9\u05D9\u05E6\u05D0 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E1\u05D9\u05E0\u05D5\u05DF";
|
|
5356
|
+
ExportButtonIcon = Filter;
|
|
5357
|
+
}
|
|
5358
|
+
const handleExportCsv = async () => {
|
|
5359
|
+
if (isExporting) return;
|
|
5360
|
+
const systemFields = ["_id", "id", "createdAt", "updatedAt", "createdBy", "updatedBy", "orgId", "tableId"];
|
|
5361
|
+
const userHiddenColumns = normalizedColumns.filter((c) => c.isHidden && !systemFields.includes(c.name)).map((c) => c.name);
|
|
5362
|
+
if (userHiddenColumns.length > 0) {
|
|
5363
|
+
addToast({
|
|
5364
|
+
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",
|
|
5365
|
+
type: "info",
|
|
5366
|
+
duration: 3e3
|
|
5367
|
+
});
|
|
5368
|
+
} else {
|
|
5369
|
+
addToast({
|
|
5370
|
+
message: "\u05DE\u05D9\u05D9\u05E6\u05D0 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD...",
|
|
5371
|
+
type: "info",
|
|
5372
|
+
duration: 3e3
|
|
5373
|
+
});
|
|
5374
|
+
}
|
|
5375
|
+
setIsExporting(true);
|
|
5376
|
+
try {
|
|
5377
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
5378
|
+
if (!targetTableId) {
|
|
5379
|
+
showError("\u05DE\u05D6\u05D4\u05D4 \u05D4\u05D8\u05D1\u05DC\u05D4 \u05D7\u05E1\u05E8 (tableId)", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D9\u05D9\u05E6\u05D5\u05D0");
|
|
5380
|
+
return;
|
|
5381
|
+
}
|
|
5382
|
+
const payload = {
|
|
5383
|
+
tableId: targetTableId,
|
|
5384
|
+
orgId,
|
|
5385
|
+
search: searchQuery.trim() || void 0,
|
|
5386
|
+
columnFilters: Object.keys(columnFilters).length > 0 ? columnFilters : void 0,
|
|
5387
|
+
selectedRowIds: hasSelectedRows ? Array.from(selectedIds) : [],
|
|
5388
|
+
hiddenColumnIds: userHiddenColumns
|
|
5389
|
+
};
|
|
5390
|
+
let res;
|
|
5391
|
+
if (exportAction) {
|
|
5392
|
+
res = await exportAction(payload);
|
|
5393
|
+
} else if (executeAction) {
|
|
5394
|
+
res = await executeAction("EXPORT_TABLE_TO_CSV", payload);
|
|
5395
|
+
} else {
|
|
5396
|
+
throw new Error("\u05E8\u05DB\u05D9\u05D1 \u05D4\u05EA\u05E7\u05E9\u05D5\u05E8\u05EA \u05DC\u05D0 \u05D0\u05D5\u05EA\u05D7\u05DC");
|
|
5397
|
+
}
|
|
5398
|
+
const result = (res == null ? void 0 : res.data) || res;
|
|
5399
|
+
if ((result == null ? void 0 : result.success) === false) {
|
|
5400
|
+
throw new Error(result.error || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D9\u05D9\u05E6\u05D5\u05D0 \u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD");
|
|
5401
|
+
}
|
|
5402
|
+
const csvString = (result == null ? void 0 : result.csvString) || (result == null ? void 0 : result.csv);
|
|
5403
|
+
if (!csvString) {
|
|
5404
|
+
throw new Error("\u05DC\u05D0 \u05D4\u05EA\u05E7\u05D1\u05DC\u05D5 \u05E0\u05EA\u05D5\u05E0\u05D9 CSV \u05DE\u05D4\u05E9\u05E8\u05EA");
|
|
5405
|
+
}
|
|
5406
|
+
const fileName = (result == null ? void 0 : result.fileName) || `${((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name) || "table").trim()}_export.csv`;
|
|
5407
|
+
const blob = new Blob([csvString], { type: "text/csv;charset=utf-8;" });
|
|
5408
|
+
const url = URL.createObjectURL(blob);
|
|
5409
|
+
const link = document.createElement("a");
|
|
5410
|
+
link.href = url;
|
|
5411
|
+
link.setAttribute("download", fileName);
|
|
5412
|
+
document.body.appendChild(link);
|
|
5413
|
+
link.click();
|
|
5414
|
+
document.body.removeChild(link);
|
|
5415
|
+
URL.revokeObjectURL(url);
|
|
5416
|
+
} catch (err) {
|
|
5417
|
+
console.error("[TableBlock] Export to CSV failed:", err);
|
|
5418
|
+
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");
|
|
5419
|
+
} finally {
|
|
5420
|
+
setIsExporting(false);
|
|
5421
|
+
}
|
|
5422
|
+
};
|
|
5423
|
+
return /* @__PURE__ */ jsxs11(
|
|
4537
5424
|
"div",
|
|
4538
5425
|
{
|
|
4539
5426
|
id: componentId,
|
|
4540
5427
|
"data-testid": dataTestId || (componentId ? `table-block-${componentId}` : void 0),
|
|
4541
|
-
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-
|
|
5428
|
+
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs flex-1 min-h-0 overflow-hidden ${className}`,
|
|
4542
5429
|
dir: "rtl",
|
|
4543
5430
|
children: [
|
|
4544
|
-
errorMessage && /* @__PURE__ */
|
|
4545
|
-
/* @__PURE__ */
|
|
4546
|
-
/* @__PURE__ */
|
|
5431
|
+
errorMessage && /* @__PURE__ */ jsx11("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__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
5432
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
5433
|
+
/* @__PURE__ */ jsx11("span", { children: errorMessage })
|
|
4547
5434
|
] }) }),
|
|
4548
|
-
/* @__PURE__ */
|
|
4549
|
-
/* @__PURE__ */
|
|
4550
|
-
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */
|
|
4551
|
-
/* @__PURE__ */
|
|
5435
|
+
/* @__PURE__ */ jsxs11("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: [
|
|
5436
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
5437
|
+
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ jsx11("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ jsx11("span", { children: schema.title || schema.name }) }),
|
|
5438
|
+
/* @__PURE__ */ jsx11(
|
|
4552
5439
|
"button",
|
|
4553
5440
|
{
|
|
4554
5441
|
onClick: handleAddRow,
|
|
4555
5442
|
disabled: isInitialLoading || isLoading || isUpdatingActive,
|
|
4556
5443
|
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"}`,
|
|
4557
5444
|
title: isInitialLoading ? "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." : "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
4558
|
-
children: /* @__PURE__ */
|
|
5445
|
+
children: /* @__PURE__ */ jsx11("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
|
|
4559
5446
|
}
|
|
4560
5447
|
),
|
|
4561
|
-
/* @__PURE__ */
|
|
5448
|
+
/* @__PURE__ */ jsx11(
|
|
4562
5449
|
"button",
|
|
4563
5450
|
{
|
|
4564
5451
|
onClick: handleDuplicateRow,
|
|
4565
5452
|
disabled: isInitialLoading || isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
4566
5453
|
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",
|
|
4567
5454
|
title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
|
|
4568
|
-
children: /* @__PURE__ */
|
|
5455
|
+
children: /* @__PURE__ */ jsx11(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
4569
5456
|
}
|
|
4570
5457
|
),
|
|
4571
|
-
/* @__PURE__ */
|
|
5458
|
+
/* @__PURE__ */ jsxs11(
|
|
4572
5459
|
"button",
|
|
4573
5460
|
{
|
|
4574
5461
|
onClick: handleDeleteSelected,
|
|
@@ -4576,12 +5463,12 @@ function TableBlockClient({
|
|
|
4576
5463
|
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",
|
|
4577
5464
|
title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
|
|
4578
5465
|
children: [
|
|
4579
|
-
/* @__PURE__ */
|
|
4580
|
-
selectedIds.size > 0 && /* @__PURE__ */
|
|
5466
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("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" }) }),
|
|
5467
|
+
selectedIds.size > 0 && /* @__PURE__ */ jsx11("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 })
|
|
4581
5468
|
]
|
|
4582
5469
|
}
|
|
4583
5470
|
),
|
|
4584
|
-
/* @__PURE__ */
|
|
5471
|
+
/* @__PURE__ */ jsxs11(
|
|
4585
5472
|
"button",
|
|
4586
5473
|
{
|
|
4587
5474
|
onClick: toggleSummary,
|
|
@@ -4589,13 +5476,13 @@ function TableBlockClient({
|
|
|
4589
5476
|
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"}`,
|
|
4590
5477
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
|
|
4591
5478
|
children: [
|
|
4592
|
-
/* @__PURE__ */
|
|
4593
|
-
/* @__PURE__ */
|
|
5479
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
|
|
5480
|
+
/* @__PURE__ */ jsx11("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
|
|
4594
5481
|
]
|
|
4595
5482
|
}
|
|
4596
5483
|
),
|
|
4597
|
-
/* @__PURE__ */
|
|
4598
|
-
/* @__PURE__ */
|
|
5484
|
+
/* @__PURE__ */ jsxs11("div", { className: "relative", ref: dropdownRef, children: [
|
|
5485
|
+
/* @__PURE__ */ jsxs11(
|
|
4599
5486
|
"button",
|
|
4600
5487
|
{
|
|
4601
5488
|
onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
|
|
@@ -4603,16 +5490,16 @@ function TableBlockClient({
|
|
|
4603
5490
|
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",
|
|
4604
5491
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
|
|
4605
5492
|
children: [
|
|
4606
|
-
/* @__PURE__ */
|
|
4607
|
-
/* @__PURE__ */
|
|
5493
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("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" }) }),
|
|
5494
|
+
/* @__PURE__ */ jsx11("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__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
|
|
4608
5495
|
]
|
|
4609
5496
|
}
|
|
4610
5497
|
),
|
|
4611
|
-
isColumnsDropdownOpen && /* @__PURE__ */
|
|
4612
|
-
/* @__PURE__ */
|
|
4613
|
-
/* @__PURE__ */
|
|
4614
|
-
/* @__PURE__ */
|
|
4615
|
-
/* @__PURE__ */
|
|
5498
|
+
isColumnsDropdownOpen && /* @__PURE__ */ jsxs11("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: [
|
|
5499
|
+
/* @__PURE__ */ jsxs11("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: [
|
|
5500
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5", children: [
|
|
5501
|
+
/* @__PURE__ */ jsx11("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
|
|
5502
|
+
/* @__PURE__ */ jsxs11("span", { className: "text-[10px] font-normal text-slate-400", children: [
|
|
4616
5503
|
"(",
|
|
4617
5504
|
customizableColumns.filter((c) => !c.isHidden).length,
|
|
4618
5505
|
"/",
|
|
@@ -4620,7 +5507,7 @@ function TableBlockClient({
|
|
|
4620
5507
|
")"
|
|
4621
5508
|
] })
|
|
4622
5509
|
] }),
|
|
4623
|
-
/* @__PURE__ */
|
|
5510
|
+
/* @__PURE__ */ jsx11(
|
|
4624
5511
|
"button",
|
|
4625
5512
|
{
|
|
4626
5513
|
type: "button",
|
|
@@ -4630,7 +5517,7 @@ function TableBlockClient({
|
|
|
4630
5517
|
}
|
|
4631
5518
|
)
|
|
4632
5519
|
] }),
|
|
4633
|
-
/* @__PURE__ */
|
|
5520
|
+
/* @__PURE__ */ jsx11("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
|
|
4634
5521
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
4635
5522
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
4636
5523
|
const isProtected = isRequired || isUnique;
|
|
@@ -4644,7 +5531,7 @@ function TableBlockClient({
|
|
|
4644
5531
|
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";
|
|
4645
5532
|
}
|
|
4646
5533
|
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";
|
|
4647
|
-
return /* @__PURE__ */
|
|
5534
|
+
return /* @__PURE__ */ jsxs11(
|
|
4648
5535
|
"div",
|
|
4649
5536
|
{
|
|
4650
5537
|
onClick: () => {
|
|
@@ -4655,8 +5542,8 @@ function TableBlockClient({
|
|
|
4655
5542
|
title: isProtected ? protectedExplanation : void 0,
|
|
4656
5543
|
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"}`,
|
|
4657
5544
|
children: [
|
|
4658
|
-
/* @__PURE__ */
|
|
4659
|
-
/* @__PURE__ */
|
|
5545
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
5546
|
+
/* @__PURE__ */ jsx11(
|
|
4660
5547
|
"input",
|
|
4661
5548
|
{
|
|
4662
5549
|
type: "checkbox",
|
|
@@ -4667,16 +5554,16 @@ function TableBlockClient({
|
|
|
4667
5554
|
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"
|
|
4668
5555
|
}
|
|
4669
5556
|
),
|
|
4670
|
-
/* @__PURE__ */
|
|
5557
|
+
/* @__PURE__ */ jsx11("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
|
|
4671
5558
|
] }),
|
|
4672
|
-
isProtected && /* @__PURE__ */
|
|
5559
|
+
isProtected && /* @__PURE__ */ jsxs11(
|
|
4673
5560
|
"div",
|
|
4674
5561
|
{
|
|
4675
5562
|
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",
|
|
4676
5563
|
title: protectedExplanation,
|
|
4677
5564
|
children: [
|
|
4678
|
-
/* @__PURE__ */
|
|
4679
|
-
/* @__PURE__ */
|
|
5565
|
+
/* @__PURE__ */ jsx11("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__ */ jsx11("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" }) }),
|
|
5566
|
+
/* @__PURE__ */ jsx11("span", { children: badgeLabel })
|
|
4680
5567
|
]
|
|
4681
5568
|
}
|
|
4682
5569
|
)
|
|
@@ -4687,9 +5574,23 @@ function TableBlockClient({
|
|
|
4687
5574
|
}) })
|
|
4688
5575
|
] })
|
|
4689
5576
|
] }),
|
|
4690
|
-
/* @__PURE__ */
|
|
4691
|
-
|
|
4692
|
-
|
|
5577
|
+
/* @__PURE__ */ jsxs11(
|
|
5578
|
+
"button",
|
|
5579
|
+
{
|
|
5580
|
+
onClick: handleExportCsv,
|
|
5581
|
+
disabled: isLoading || isUpdatingActive || isExporting,
|
|
5582
|
+
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"}`,
|
|
5583
|
+
title: exportButtonText,
|
|
5584
|
+
"data-testid": "export-csv-button",
|
|
5585
|
+
children: [
|
|
5586
|
+
isExporting ? /* @__PURE__ */ jsx11(Loader22, { className: "w-4 h-4 shrink-0 animate-spin text-slate-500" }) : /* @__PURE__ */ jsx11(ExportButtonIcon, { className: "w-4 h-4 shrink-0" }),
|
|
5587
|
+
/* @__PURE__ */ jsx11("span", { children: isExporting ? "\u05DE\u05D9\u05D9\u05E6\u05D0..." : exportButtonText })
|
|
5588
|
+
]
|
|
5589
|
+
}
|
|
5590
|
+
),
|
|
5591
|
+
/* @__PURE__ */ jsx11("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
5592
|
+
/* @__PURE__ */ jsxs11("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
5593
|
+
/* @__PURE__ */ jsx11(
|
|
4693
5594
|
"input",
|
|
4694
5595
|
{
|
|
4695
5596
|
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
@@ -4699,28 +5600,28 @@ function TableBlockClient({
|
|
|
4699
5600
|
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"
|
|
4700
5601
|
}
|
|
4701
5602
|
),
|
|
4702
|
-
searchQuery ? /* @__PURE__ */
|
|
5603
|
+
searchQuery ? /* @__PURE__ */ jsx11(
|
|
4703
5604
|
"button",
|
|
4704
5605
|
{
|
|
4705
5606
|
type: "button",
|
|
4706
5607
|
onClick: () => setSearchQuery(""),
|
|
4707
5608
|
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",
|
|
4708
5609
|
title: "Clear search",
|
|
4709
|
-
children: /* @__PURE__ */
|
|
5610
|
+
children: /* @__PURE__ */ jsx11(X8, { className: "w-3.5 h-3.5" })
|
|
4710
5611
|
}
|
|
4711
|
-
) : /* @__PURE__ */
|
|
5612
|
+
) : /* @__PURE__ */ jsx11("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__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
|
|
4712
5613
|
] })
|
|
4713
5614
|
] }),
|
|
4714
|
-
/* @__PURE__ */
|
|
4715
|
-
isUpdatingActive ? /* @__PURE__ */
|
|
4716
|
-
/* @__PURE__ */
|
|
5615
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3", children: [
|
|
5616
|
+
isUpdatingActive ? /* @__PURE__ */ jsxs11("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: [
|
|
5617
|
+
/* @__PURE__ */ jsx11("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
4717
5618
|
"\u05DE\u05E2\u05D3\u05DB\u05DF..."
|
|
4718
|
-
] }) : isSaveSuccess ? /* @__PURE__ */
|
|
4719
|
-
/* @__PURE__ */
|
|
5619
|
+
] }) : isSaveSuccess ? /* @__PURE__ */ jsxs11("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: [
|
|
5620
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
|
|
4720
5621
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
4721
|
-
] }) : hasChanges ? /* @__PURE__ */
|
|
4722
|
-
/* @__PURE__ */
|
|
4723
|
-
/* @__PURE__ */
|
|
5622
|
+
] }) : hasChanges ? /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5 animate-in fade-in", children: [
|
|
5623
|
+
/* @__PURE__ */ jsx11("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" }),
|
|
5624
|
+
/* @__PURE__ */ jsx11(
|
|
4724
5625
|
"button",
|
|
4725
5626
|
{
|
|
4726
5627
|
type: "button",
|
|
@@ -4729,30 +5630,31 @@ function TableBlockClient({
|
|
|
4729
5630
|
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",
|
|
4730
5631
|
title: "\u05D1\u05D8\u05DC \u05D0\u05EA \u05DB\u05DC \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5",
|
|
4731
5632
|
"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",
|
|
4732
|
-
children: /* @__PURE__ */
|
|
5633
|
+
children: /* @__PURE__ */ jsx11(RotateCcw2, { className: "w-3.5 h-3.5" })
|
|
4733
5634
|
}
|
|
4734
5635
|
)
|
|
4735
5636
|
] }) : null,
|
|
4736
|
-
/* @__PURE__ */
|
|
5637
|
+
/* @__PURE__ */ jsx11(
|
|
4737
5638
|
"button",
|
|
4738
5639
|
{
|
|
4739
5640
|
onClick: handleSave,
|
|
4740
5641
|
disabled: isUpdatingActive || isLoading || !hasChanges,
|
|
4741
5642
|
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"}`,
|
|
4742
|
-
children: /* @__PURE__ */
|
|
5643
|
+
children: /* @__PURE__ */ jsx11("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
|
|
4743
5644
|
}
|
|
4744
5645
|
)
|
|
4745
5646
|
] })
|
|
4746
5647
|
] }),
|
|
4747
|
-
/* @__PURE__ */
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
/* @__PURE__ */
|
|
5648
|
+
/* @__PURE__ */ jsxs11("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: [
|
|
5649
|
+
isFetching && /* @__PURE__ */ jsx11("div", { className: "absolute top-0 left-0 right-0 h-0.5 bg-blue-500/20 overflow-hidden z-30", children: /* @__PURE__ */ jsx11("div", { className: "w-full h-full bg-brand animate-pulse" }) }),
|
|
5650
|
+
isLoading && /* @__PURE__ */ jsxs11("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
|
|
5651
|
+
/* @__PURE__ */ jsx11("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
5652
|
+
/* @__PURE__ */ jsx11("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
4751
5653
|
] }),
|
|
4752
|
-
/* @__PURE__ */
|
|
4753
|
-
/* @__PURE__ */
|
|
4754
|
-
/* @__PURE__ */
|
|
4755
|
-
/* @__PURE__ */
|
|
5654
|
+
/* @__PURE__ */ jsxs11("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
|
|
5655
|
+
/* @__PURE__ */ jsx11("thead", { className: "bg-white text-slate-700 sticky top-0 z-10 shadow-xs", children: /* @__PURE__ */ jsxs11("tr", { className: "h-12 min-h-[48px]", children: [
|
|
5656
|
+
/* @__PURE__ */ jsx11("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__ */ jsxs11("div", { className: "flex items-center justify-center gap-1.5", children: [
|
|
5657
|
+
/* @__PURE__ */ jsx11(
|
|
4756
5658
|
"input",
|
|
4757
5659
|
{
|
|
4758
5660
|
type: "checkbox",
|
|
@@ -4765,7 +5667,7 @@ function TableBlockClient({
|
|
|
4765
5667
|
filteredColumns.some((c) => {
|
|
4766
5668
|
var _a;
|
|
4767
5669
|
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
4768
|
-
}) && /* @__PURE__ */
|
|
5670
|
+
}) && /* @__PURE__ */ jsx11("div", { className: "w-5 h-5 shrink-0" })
|
|
4769
5671
|
] }) }),
|
|
4770
5672
|
filteredColumns.map((col) => {
|
|
4771
5673
|
var _a, _b;
|
|
@@ -4776,16 +5678,25 @@ function TableBlockClient({
|
|
|
4776
5678
|
const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
|
|
4777
5679
|
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
|
|
4778
5680
|
const isRelation = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
|
|
4779
|
-
const filterVal = columnFilters[col.name]
|
|
4780
|
-
|
|
5681
|
+
const filterVal = columnFilters[col.name];
|
|
5682
|
+
const hasActiveFilter = Array.isArray(filterVal) ? filterVal.length > 0 : filterVal && typeof filterVal === "object" && "values" in filterVal ? filterVal.values.length > 0 : Boolean(filterVal && filterVal.trim() !== "");
|
|
5683
|
+
let filterTooltip = "\u05D7\u05E4\u05E9 \u05D5\u05E1\u05E0\u05DF \u05D1\u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5";
|
|
5684
|
+
if (Array.isArray(filterVal)) {
|
|
5685
|
+
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`;
|
|
5686
|
+
} else if (filterVal && typeof filterVal === "object" && "operator" in filterVal && filterVal.operator === "notIn") {
|
|
5687
|
+
filterTooltip = `\u05DE\u05D5\u05D7\u05E8\u05D2\u05D9\u05DD: ${filterVal.values.length} \u05E4\u05E8\u05D9\u05D8\u05D9\u05DD (\u05D4\u05DB\u05DC \u05DC\u05DE\u05E2\u05D8)`;
|
|
5688
|
+
} else if (typeof filterVal === "string" && filterVal.trim()) {
|
|
5689
|
+
filterTooltip = `\u05DE\u05E1\u05D5\u05E0\u05DF \u05DC\u05E4\u05D9: "${filterVal}" (\u05DC\u05D7\u05E5 \u05DC\u05E2\u05E8\u05D9\u05DB\u05D4)`;
|
|
5690
|
+
}
|
|
5691
|
+
return /* @__PURE__ */ jsxs11(
|
|
4781
5692
|
"th",
|
|
4782
5693
|
__spreadProps(__spreadValues({
|
|
4783
5694
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
4784
5695
|
title: isSearching ? void 0 : col.name
|
|
4785
5696
|
}, dragProps), {
|
|
4786
|
-
className: `relative border-b border-l border-slate-200 px-2
|
|
5697
|
+
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" : ""}`,
|
|
4787
5698
|
children: [
|
|
4788
|
-
/* @__PURE__ */
|
|
5699
|
+
/* @__PURE__ */ jsx11(
|
|
4789
5700
|
"div",
|
|
4790
5701
|
{
|
|
4791
5702
|
onMouseDown: (e) => {
|
|
@@ -4797,7 +5708,7 @@ function TableBlockClient({
|
|
|
4797
5708
|
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
4798
5709
|
}
|
|
4799
5710
|
),
|
|
4800
|
-
isSearching ? /* @__PURE__ */
|
|
5711
|
+
isSearching && !isRelation ? /* @__PURE__ */ jsxs11(
|
|
4801
5712
|
"div",
|
|
4802
5713
|
{
|
|
4803
5714
|
ref: activeSearchRef,
|
|
@@ -4805,46 +5716,15 @@ function TableBlockClient({
|
|
|
4805
5716
|
onClick: (e) => e.stopPropagation(),
|
|
4806
5717
|
onMouseDown: (e) => e.stopPropagation(),
|
|
4807
5718
|
children: [
|
|
4808
|
-
|
|
4809
|
-
"select",
|
|
4810
|
-
{
|
|
4811
|
-
autoFocus: true,
|
|
4812
|
-
value: filterVal,
|
|
4813
|
-
onChange: (e) => {
|
|
4814
|
-
const val = e.target.value;
|
|
4815
|
-
setColumnFilters((prev) => {
|
|
4816
|
-
const next = __spreadValues({}, prev);
|
|
4817
|
-
if (val) next[col.name] = val;
|
|
4818
|
-
else delete next[col.name];
|
|
4819
|
-
return next;
|
|
4820
|
-
});
|
|
4821
|
-
},
|
|
4822
|
-
onKeyDown: (e) => {
|
|
4823
|
-
if (e.key === "Escape" || e.key === "Enter") {
|
|
4824
|
-
setActiveSearchCol(null);
|
|
4825
|
-
}
|
|
4826
|
-
},
|
|
4827
|
-
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",
|
|
4828
|
-
children: [
|
|
4829
|
-
/* @__PURE__ */ jsx10("option", { value: "", children: "\u05D4\u05DB\u05DC" }),
|
|
4830
|
-
getUniqueRelationOptions(col).map((opt) => /* @__PURE__ */ jsx10("option", { value: opt.label, children: opt.label }, opt.id))
|
|
4831
|
-
]
|
|
4832
|
-
}
|
|
4833
|
-
) }) : /* @__PURE__ */ jsx10("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ jsx10(
|
|
5719
|
+
/* @__PURE__ */ jsx11("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ jsx11(
|
|
4834
5720
|
"input",
|
|
4835
5721
|
{
|
|
4836
5722
|
autoFocus: true,
|
|
4837
5723
|
type: "text",
|
|
4838
5724
|
placeholder: `\u05D7\u05E4\u05E9 \u05D1-${col.name}...`,
|
|
4839
|
-
value: filterVal,
|
|
5725
|
+
value: typeof filterVal === "string" ? filterVal : "",
|
|
4840
5726
|
onChange: (e) => {
|
|
4841
|
-
|
|
4842
|
-
setColumnFilters((prev) => {
|
|
4843
|
-
const next = __spreadValues({}, prev);
|
|
4844
|
-
if (val) next[col.name] = val;
|
|
4845
|
-
else delete next[col.name];
|
|
4846
|
-
return next;
|
|
4847
|
-
});
|
|
5727
|
+
handleApplyColumnFilter(col.name, e.target.value);
|
|
4848
5728
|
},
|
|
4849
5729
|
onKeyDown: (e) => {
|
|
4850
5730
|
if (e.key === "Escape" || e.key === "Enter") {
|
|
@@ -4854,7 +5734,7 @@ function TableBlockClient({
|
|
|
4854
5734
|
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"
|
|
4855
5735
|
}
|
|
4856
5736
|
) }),
|
|
4857
|
-
/* @__PURE__ */
|
|
5737
|
+
/* @__PURE__ */ jsx11(
|
|
4858
5738
|
"button",
|
|
4859
5739
|
{
|
|
4860
5740
|
type: "button",
|
|
@@ -4864,59 +5744,60 @@ function TableBlockClient({
|
|
|
4864
5744
|
},
|
|
4865
5745
|
onClick: (e) => {
|
|
4866
5746
|
e.stopPropagation();
|
|
4867
|
-
|
|
4868
|
-
const next = __spreadValues({}, prev);
|
|
4869
|
-
delete next[col.name];
|
|
4870
|
-
return next;
|
|
4871
|
-
});
|
|
5747
|
+
handleApplyColumnFilter(col.name, void 0);
|
|
4872
5748
|
setActiveSearchCol(null);
|
|
4873
5749
|
},
|
|
4874
5750
|
className: "p-1 text-slate-400 hover:text-slate-700 hover:bg-slate-200/70 rounded transition-colors cursor-pointer shrink-0",
|
|
4875
5751
|
title: "\u05E0\u05E7\u05D4 \u05D5\u05E1\u05D2\u05D5\u05E8 \u05D7\u05D9\u05E4\u05D5\u05E9",
|
|
4876
|
-
children: /* @__PURE__ */
|
|
5752
|
+
children: /* @__PURE__ */ jsx11(X8, { className: "w-3.5 h-3.5" })
|
|
4877
5753
|
}
|
|
4878
5754
|
)
|
|
4879
5755
|
]
|
|
4880
5756
|
}
|
|
4881
|
-
) : /* @__PURE__ */
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
5757
|
+
) : /* @__PURE__ */ jsxs11("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: [
|
|
5758
|
+
((_b = col.type) == null ? void 0 : _b.toUpperCase()) !== "SUB_TABLE" && /* @__PURE__ */ jsx11(
|
|
5759
|
+
"button",
|
|
5760
|
+
{
|
|
5761
|
+
ref: (el) => {
|
|
5762
|
+
filterButtonRefs.current[col.name] = el;
|
|
5763
|
+
},
|
|
5764
|
+
type: "button",
|
|
5765
|
+
onClick: (e) => {
|
|
5766
|
+
e.stopPropagation();
|
|
5767
|
+
e.preventDefault();
|
|
5768
|
+
if (isRelation) {
|
|
5769
|
+
if (activeRelationCol === col.name) {
|
|
5770
|
+
setActiveRelationCol(null);
|
|
5771
|
+
setRelationTriggerRect(null);
|
|
5772
|
+
} else {
|
|
5773
|
+
const btn = filterButtonRefs.current[col.name];
|
|
5774
|
+
if (btn) {
|
|
5775
|
+
setRelationTriggerRect(btn.getBoundingClientRect());
|
|
5776
|
+
}
|
|
5777
|
+
setActiveRelationCol(col.name);
|
|
5778
|
+
fetchRelationFilterOptions(col.name);
|
|
5779
|
+
}
|
|
5780
|
+
} else {
|
|
4891
5781
|
setActiveSearchCol(col.name);
|
|
4892
|
-
}
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
}
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
{
|
|
4901
|
-
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
4902
|
-
fill: "none",
|
|
4903
|
-
viewBox: "0 0 24 24",
|
|
4904
|
-
stroke: "currentColor",
|
|
4905
|
-
children: /* @__PURE__ */ jsx10("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
|
|
4906
|
-
}
|
|
4907
|
-
)
|
|
4908
|
-
] })
|
|
5782
|
+
}
|
|
5783
|
+
},
|
|
5784
|
+
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"}`,
|
|
5785
|
+
title: filterTooltip,
|
|
5786
|
+
children: /* @__PURE__ */ jsx11(Filter, { className: "w-3 h-3" })
|
|
5787
|
+
}
|
|
5788
|
+
),
|
|
5789
|
+
/* @__PURE__ */ jsx11(ColumnHeaderTitle, { name: col.name, width: currentWidth, isSubTable: false })
|
|
4909
5790
|
] })
|
|
4910
5791
|
]
|
|
4911
5792
|
}),
|
|
4912
5793
|
col.name
|
|
4913
5794
|
);
|
|
4914
5795
|
}),
|
|
4915
|
-
/* @__PURE__ */
|
|
5796
|
+
/* @__PURE__ */ jsx11("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none h-12 min-h-[48px] bg-white" })
|
|
4916
5797
|
] }) }),
|
|
4917
|
-
/* @__PURE__ */
|
|
4918
|
-
/* @__PURE__ */
|
|
4919
|
-
/* @__PURE__ */
|
|
5798
|
+
/* @__PURE__ */ jsx11("tbody", { className: `bg-white transition-opacity duration-150 ${isFetching ? "opacity-50 pointer-events-none" : "opacity-100"}`, children: (isStateEmpty || filteredData.length === 0) && !isLoading && !isFetching ? /* @__PURE__ */ jsx11("tr", { children: /* @__PURE__ */ jsx11("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ jsxs11("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
5799
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("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" }) }),
|
|
5800
|
+
/* @__PURE__ */ jsx11("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
4920
5801
|
] }) }) }) : filteredData.map((row) => {
|
|
4921
5802
|
const hasSubTableCols = filteredColumns.some((c) => {
|
|
4922
5803
|
var _a;
|
|
@@ -4927,108 +5808,40 @@ function TableBlockClient({
|
|
|
4927
5808
|
var _a;
|
|
4928
5809
|
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
4929
5810
|
});
|
|
4930
|
-
return /* @__PURE__ */
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
4962
|
-
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
4963
|
-
const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
|
|
4964
|
-
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
|
|
4965
|
-
let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
|
|
4966
|
-
if (value === void 0 && col.defaultValue !== void 0) {
|
|
4967
|
-
value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
|
|
4968
|
-
if (colType === "CURRENCY" || colType === "NUMBER") {
|
|
4969
|
-
if (isNaN(value)) value = null;
|
|
4970
|
-
}
|
|
4971
|
-
}
|
|
4972
|
-
if (value === void 0) value = null;
|
|
4973
|
-
return /* @__PURE__ */ jsx10(
|
|
4974
|
-
"td",
|
|
4975
|
-
{
|
|
4976
|
-
className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
|
|
4977
|
-
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
4978
|
-
children: /* @__PURE__ */ jsx10(
|
|
4979
|
-
InputComponent,
|
|
4980
|
-
{
|
|
4981
|
-
value,
|
|
4982
|
-
column: col,
|
|
4983
|
-
rowId: row.id,
|
|
4984
|
-
onChange: (v) => handleCellChange(row.id, col.name, v),
|
|
4985
|
-
context: {
|
|
4986
|
-
tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
|
|
4987
|
-
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
4988
|
-
onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
|
|
4989
|
-
relationOptions,
|
|
4990
|
-
refetchRelation,
|
|
4991
|
-
executeAction,
|
|
4992
|
-
emitEvent,
|
|
4993
|
-
pageState,
|
|
4994
|
-
componentId,
|
|
4995
|
-
orgId,
|
|
4996
|
-
updateQuietly: handleQuietCellChange,
|
|
4997
|
-
triggerSaveSuccess,
|
|
4998
|
-
rowData: row.data
|
|
4999
|
-
}
|
|
5000
|
-
}
|
|
5001
|
-
)
|
|
5002
|
-
},
|
|
5003
|
-
col.name
|
|
5004
|
-
);
|
|
5005
|
-
}),
|
|
5006
|
-
/* @__PURE__ */ jsx10("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
5007
|
-
] }),
|
|
5008
|
-
isExpanded && /* @__PURE__ */ jsx10(
|
|
5009
|
-
ExpandedSubTables,
|
|
5010
|
-
{
|
|
5011
|
-
rowId: row.id,
|
|
5012
|
-
rowData: row.data,
|
|
5013
|
-
subTableColumns,
|
|
5014
|
-
filteredColumnsLength: filteredColumns.length,
|
|
5015
|
-
handleCellChange,
|
|
5016
|
-
context: {
|
|
5017
|
-
executeAction,
|
|
5018
|
-
orgId,
|
|
5019
|
-
parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
5020
|
-
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
5021
|
-
rowData: row.data,
|
|
5022
|
-
updateQuietly: handleQuietCellChange,
|
|
5023
|
-
triggerSaveSuccess,
|
|
5024
|
-
onUpdateColumnConfig: handleUpdateColumnConfig
|
|
5025
|
-
}
|
|
5026
|
-
}
|
|
5027
|
-
)
|
|
5028
|
-
] }, row.id);
|
|
5811
|
+
return /* @__PURE__ */ jsx11(
|
|
5812
|
+
TableRow,
|
|
5813
|
+
{
|
|
5814
|
+
row,
|
|
5815
|
+
isSelected: selectedIds.has(row.id),
|
|
5816
|
+
isExpanded,
|
|
5817
|
+
filteredColumns,
|
|
5818
|
+
columnWidths,
|
|
5819
|
+
hasSubTableCols,
|
|
5820
|
+
subTableColumns,
|
|
5821
|
+
isLoading: isLoading || isFetching,
|
|
5822
|
+
isUpdatingActive,
|
|
5823
|
+
onToggleSelect: toggleSelectRow,
|
|
5824
|
+
onToggleExpand: handleToggleExpand,
|
|
5825
|
+
handleCellChange,
|
|
5826
|
+
handleQuietCellChange,
|
|
5827
|
+
handleUpdateColumnConfig,
|
|
5828
|
+
onMarkForDeletion: handleMarkForDeletion,
|
|
5829
|
+
triggerSaveSuccess,
|
|
5830
|
+
schema,
|
|
5831
|
+
orgId,
|
|
5832
|
+
componentId,
|
|
5833
|
+
pageState,
|
|
5834
|
+
relationOptions,
|
|
5835
|
+
relationDictionaryRef,
|
|
5836
|
+
refetchRelation,
|
|
5837
|
+
executeAction,
|
|
5838
|
+
emitEvent
|
|
5839
|
+
},
|
|
5840
|
+
row.id
|
|
5841
|
+
);
|
|
5029
5842
|
}) }),
|
|
5030
|
-
showSummary && filteredData.length > 0 && /* @__PURE__ */
|
|
5031
|
-
/* @__PURE__ */
|
|
5843
|
+
showSummary && filteredData.length > 0 && /* @__PURE__ */ jsx11("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__ */ jsxs11("tr", { children: [
|
|
5844
|
+
/* @__PURE__ */ jsx11("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' }),
|
|
5032
5845
|
filteredColumns.map((col) => {
|
|
5033
5846
|
var _a, _b;
|
|
5034
5847
|
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
@@ -5042,16 +5855,16 @@ function TableBlockClient({
|
|
|
5042
5855
|
displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
|
|
5043
5856
|
}
|
|
5044
5857
|
}
|
|
5045
|
-
return /* @__PURE__ */
|
|
5858
|
+
return /* @__PURE__ */ jsx11("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__ */ jsx11("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ jsx11("span", { className: "truncate", children: displayVal }) }) }, col.name);
|
|
5046
5859
|
}),
|
|
5047
|
-
/* @__PURE__ */
|
|
5860
|
+
/* @__PURE__ */ jsx11("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
|
|
5048
5861
|
] }) })
|
|
5049
5862
|
] })
|
|
5050
5863
|
] }),
|
|
5051
|
-
/* @__PURE__ */
|
|
5052
|
-
/* @__PURE__ */
|
|
5053
|
-
/* @__PURE__ */
|
|
5054
|
-
/* @__PURE__ */
|
|
5864
|
+
/* @__PURE__ */ jsxs11("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: [
|
|
5865
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
5866
|
+
/* @__PURE__ */ jsx11("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
|
|
5867
|
+
/* @__PURE__ */ jsxs11(
|
|
5055
5868
|
"select",
|
|
5056
5869
|
{
|
|
5057
5870
|
value: limit,
|
|
@@ -5059,27 +5872,27 @@ function TableBlockClient({
|
|
|
5059
5872
|
disabled: isLoading || isUpdatingActive,
|
|
5060
5873
|
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",
|
|
5061
5874
|
children: [
|
|
5062
|
-
/* @__PURE__ */
|
|
5063
|
-
/* @__PURE__ */
|
|
5064
|
-
/* @__PURE__ */
|
|
5875
|
+
/* @__PURE__ */ jsx11("option", { value: 20, children: "20" }),
|
|
5876
|
+
/* @__PURE__ */ jsx11("option", { value: 50, children: "50" }),
|
|
5877
|
+
/* @__PURE__ */ jsx11("option", { value: 100, children: "100" })
|
|
5065
5878
|
]
|
|
5066
5879
|
}
|
|
5067
5880
|
)
|
|
5068
5881
|
] }),
|
|
5069
|
-
/* @__PURE__ */
|
|
5070
|
-
/* @__PURE__ */
|
|
5882
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-4", children: [
|
|
5883
|
+
/* @__PURE__ */ jsxs11("span", { className: "font-medium text-slate-600", children: [
|
|
5071
5884
|
"\u05E2\u05DE\u05D5\u05D3 ",
|
|
5072
|
-
/* @__PURE__ */
|
|
5885
|
+
/* @__PURE__ */ jsx11("strong", { className: "text-slate-900", children: page }),
|
|
5073
5886
|
" \u05DE\u05EA\u05D5\u05DA ",
|
|
5074
|
-
/* @__PURE__ */
|
|
5075
|
-
totalRecords > 0 && /* @__PURE__ */
|
|
5887
|
+
/* @__PURE__ */ jsx11("strong", { className: "text-slate-900", children: totalPages || 1 }),
|
|
5888
|
+
totalRecords > 0 && /* @__PURE__ */ jsxs11("span", { className: "text-slate-500 font-normal", children: [
|
|
5076
5889
|
" (",
|
|
5077
5890
|
totalRecords,
|
|
5078
5891
|
' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
|
|
5079
5892
|
] })
|
|
5080
5893
|
] }),
|
|
5081
|
-
/* @__PURE__ */
|
|
5082
|
-
/* @__PURE__ */
|
|
5894
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5", children: [
|
|
5895
|
+
/* @__PURE__ */ jsx11(
|
|
5083
5896
|
"button",
|
|
5084
5897
|
{
|
|
5085
5898
|
onClick: handlePrevPage,
|
|
@@ -5089,7 +5902,7 @@ function TableBlockClient({
|
|
|
5089
5902
|
children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
|
|
5090
5903
|
}
|
|
5091
5904
|
),
|
|
5092
|
-
/* @__PURE__ */
|
|
5905
|
+
/* @__PURE__ */ jsx11(
|
|
5093
5906
|
"button",
|
|
5094
5907
|
{
|
|
5095
5908
|
onClick: handleNextPage,
|
|
@@ -5101,7 +5914,31 @@ function TableBlockClient({
|
|
|
5101
5914
|
)
|
|
5102
5915
|
] })
|
|
5103
5916
|
] })
|
|
5104
|
-
] })
|
|
5917
|
+
] }),
|
|
5918
|
+
activeRelationCol && (() => {
|
|
5919
|
+
const activeColDef = filteredColumns.find((c) => c.name === activeRelationCol);
|
|
5920
|
+
if (!activeColDef) return null;
|
|
5921
|
+
const rawSelected = columnFilters[activeRelationCol];
|
|
5922
|
+
const currentSelected = typeof rawSelected === "object" && rawSelected !== null ? rawSelected : void 0;
|
|
5923
|
+
return /* @__PURE__ */ jsx11(
|
|
5924
|
+
RelationFilterPopover,
|
|
5925
|
+
{
|
|
5926
|
+
isOpen: Boolean(activeRelationCol),
|
|
5927
|
+
onClose: () => {
|
|
5928
|
+
setActiveRelationCol(null);
|
|
5929
|
+
setRelationTriggerRect(null);
|
|
5930
|
+
},
|
|
5931
|
+
column: activeColDef,
|
|
5932
|
+
triggerRect: relationTriggerRect,
|
|
5933
|
+
options: getUniqueRelationOptions(activeColDef),
|
|
5934
|
+
filterValue: currentSelected,
|
|
5935
|
+
onSelectionChange: (newSelected) => {
|
|
5936
|
+
handleApplyColumnFilter(activeRelationCol, newSelected);
|
|
5937
|
+
},
|
|
5938
|
+
isLoading: loadingFilterCol === activeRelationCol
|
|
5939
|
+
}
|
|
5940
|
+
);
|
|
5941
|
+
})()
|
|
5105
5942
|
]
|
|
5106
5943
|
}
|
|
5107
5944
|
);
|
|
@@ -5115,11 +5952,11 @@ function ExpandedSubTables({
|
|
|
5115
5952
|
context
|
|
5116
5953
|
}) {
|
|
5117
5954
|
var _a;
|
|
5118
|
-
const [activeTab, setActiveTab] =
|
|
5955
|
+
const [activeTab, setActiveTab] = useState12((_a = subTableColumns[0]) == null ? void 0 : _a.name);
|
|
5119
5956
|
if (subTableColumns.length === 0) return null;
|
|
5120
5957
|
if (subTableColumns.length === 1) {
|
|
5121
5958
|
const stCol = subTableColumns[0];
|
|
5122
|
-
return /* @__PURE__ */
|
|
5959
|
+
return /* @__PURE__ */ jsx11("tr", { children: /* @__PURE__ */ jsx11("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50", children: /* @__PURE__ */ jsx11(
|
|
5123
5960
|
SubTableViewer,
|
|
5124
5961
|
{
|
|
5125
5962
|
rowId,
|
|
@@ -5131,8 +5968,8 @@ function ExpandedSubTables({
|
|
|
5131
5968
|
) }) });
|
|
5132
5969
|
}
|
|
5133
5970
|
const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
|
|
5134
|
-
return /* @__PURE__ */
|
|
5135
|
-
/* @__PURE__ */
|
|
5971
|
+
return /* @__PURE__ */ jsx11("tr", { children: /* @__PURE__ */ jsxs11("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50 overflow-hidden", children: [
|
|
5972
|
+
/* @__PURE__ */ jsx11("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__ */ jsx11(
|
|
5136
5973
|
"button",
|
|
5137
5974
|
{
|
|
5138
5975
|
type: "button",
|
|
@@ -5142,7 +5979,7 @@ function ExpandedSubTables({
|
|
|
5142
5979
|
},
|
|
5143
5980
|
col.name
|
|
5144
5981
|
)) }),
|
|
5145
|
-
/* @__PURE__ */
|
|
5982
|
+
/* @__PURE__ */ jsx11("div", { className: "bg-white", children: /* @__PURE__ */ jsx11(
|
|
5146
5983
|
SubTableViewer,
|
|
5147
5984
|
{
|
|
5148
5985
|
rowId,
|
|
@@ -5155,11 +5992,134 @@ function ExpandedSubTables({
|
|
|
5155
5992
|
) })
|
|
5156
5993
|
] }) });
|
|
5157
5994
|
}
|
|
5995
|
+
var TableRow = React11.memo(function TableRow2({
|
|
5996
|
+
row,
|
|
5997
|
+
isSelected,
|
|
5998
|
+
isExpanded,
|
|
5999
|
+
filteredColumns,
|
|
6000
|
+
columnWidths,
|
|
6001
|
+
hasSubTableCols,
|
|
6002
|
+
subTableColumns,
|
|
6003
|
+
isLoading,
|
|
6004
|
+
isUpdatingActive,
|
|
6005
|
+
onToggleSelect,
|
|
6006
|
+
onToggleExpand,
|
|
6007
|
+
handleCellChange,
|
|
6008
|
+
handleQuietCellChange,
|
|
6009
|
+
handleUpdateColumnConfig,
|
|
6010
|
+
onMarkForDeletion,
|
|
6011
|
+
triggerSaveSuccess,
|
|
6012
|
+
schema,
|
|
6013
|
+
orgId,
|
|
6014
|
+
componentId,
|
|
6015
|
+
pageState,
|
|
6016
|
+
relationOptions,
|
|
6017
|
+
relationDictionaryRef,
|
|
6018
|
+
refetchRelation,
|
|
6019
|
+
executeAction,
|
|
6020
|
+
emitEvent
|
|
6021
|
+
}) {
|
|
6022
|
+
return /* @__PURE__ */ jsxs11(React11.Fragment, { children: [
|
|
6023
|
+
/* @__PURE__ */ jsxs11("tr", { className: `hover:bg-blue-50/30 transition-colors group ${isSelected ? "bg-blue-50/40" : ""}`, children: [
|
|
6024
|
+
/* @__PURE__ */ jsx11("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__ */ jsxs11("div", { className: "flex items-center justify-center gap-1.5", children: [
|
|
6025
|
+
/* @__PURE__ */ jsx11(
|
|
6026
|
+
"input",
|
|
6027
|
+
{
|
|
6028
|
+
type: "checkbox",
|
|
6029
|
+
checked: isSelected,
|
|
6030
|
+
onChange: (e) => onToggleSelect(row.id, e.target.checked),
|
|
6031
|
+
disabled: isLoading || isUpdatingActive,
|
|
6032
|
+
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
6033
|
+
}
|
|
6034
|
+
),
|
|
6035
|
+
hasSubTableCols && /* @__PURE__ */ jsx11(
|
|
6036
|
+
"button",
|
|
6037
|
+
{
|
|
6038
|
+
type: "button",
|
|
6039
|
+
onClick: () => onToggleExpand(row.id),
|
|
6040
|
+
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",
|
|
6041
|
+
title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
|
|
6042
|
+
children: /* @__PURE__ */ jsx11("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__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", d: "M9 5l7 7-7 7" }) })
|
|
6043
|
+
}
|
|
6044
|
+
)
|
|
6045
|
+
] }) }),
|
|
6046
|
+
filteredColumns.map((col) => {
|
|
6047
|
+
var _a;
|
|
6048
|
+
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
6049
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
6050
|
+
const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
|
|
6051
|
+
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
|
|
6052
|
+
let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
|
|
6053
|
+
if (value === void 0 && col.defaultValue !== void 0) {
|
|
6054
|
+
value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
|
|
6055
|
+
if (colType === "CURRENCY" || colType === "NUMBER") {
|
|
6056
|
+
if (isNaN(value)) value = null;
|
|
6057
|
+
}
|
|
6058
|
+
}
|
|
6059
|
+
if (value === void 0) value = null;
|
|
6060
|
+
return /* @__PURE__ */ jsx11(
|
|
6061
|
+
"td",
|
|
6062
|
+
{
|
|
6063
|
+
className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
|
|
6064
|
+
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
6065
|
+
children: /* @__PURE__ */ jsx11(
|
|
6066
|
+
InputComponent,
|
|
6067
|
+
{
|
|
6068
|
+
value,
|
|
6069
|
+
column: col,
|
|
6070
|
+
rowId: row.id,
|
|
6071
|
+
onChange: (v) => handleCellChange(row.id, col.name, v),
|
|
6072
|
+
context: {
|
|
6073
|
+
tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
|
|
6074
|
+
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
6075
|
+
onMarkForDeletion,
|
|
6076
|
+
relationOptions,
|
|
6077
|
+
relationDictionaryRef,
|
|
6078
|
+
refetchRelation,
|
|
6079
|
+
executeAction,
|
|
6080
|
+
emitEvent,
|
|
6081
|
+
pageState,
|
|
6082
|
+
componentId,
|
|
6083
|
+
orgId,
|
|
6084
|
+
updateQuietly: handleQuietCellChange,
|
|
6085
|
+
triggerSaveSuccess,
|
|
6086
|
+
rowData: row.data
|
|
6087
|
+
}
|
|
6088
|
+
}
|
|
6089
|
+
)
|
|
6090
|
+
},
|
|
6091
|
+
col.name
|
|
6092
|
+
);
|
|
6093
|
+
}),
|
|
6094
|
+
/* @__PURE__ */ jsx11("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
6095
|
+
] }),
|
|
6096
|
+
isExpanded && /* @__PURE__ */ jsx11(
|
|
6097
|
+
ExpandedSubTables,
|
|
6098
|
+
{
|
|
6099
|
+
rowId: row.id,
|
|
6100
|
+
rowData: row.data,
|
|
6101
|
+
subTableColumns,
|
|
6102
|
+
filteredColumnsLength: filteredColumns.length,
|
|
6103
|
+
handleCellChange,
|
|
6104
|
+
context: {
|
|
6105
|
+
executeAction,
|
|
6106
|
+
orgId,
|
|
6107
|
+
parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
6108
|
+
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
6109
|
+
rowData: row.data,
|
|
6110
|
+
updateQuietly: handleQuietCellChange,
|
|
6111
|
+
triggerSaveSuccess,
|
|
6112
|
+
onUpdateColumnConfig: handleUpdateColumnConfig
|
|
6113
|
+
}
|
|
6114
|
+
}
|
|
6115
|
+
)
|
|
6116
|
+
] });
|
|
6117
|
+
});
|
|
5158
6118
|
|
|
5159
6119
|
// src/components/TableBlock/TableBlock.tsx
|
|
5160
|
-
import { jsx as
|
|
6120
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
5161
6121
|
function TableBlock(props) {
|
|
5162
|
-
return /* @__PURE__ */
|
|
6122
|
+
return /* @__PURE__ */ jsx12(TableBlockClient, __spreadValues({}, props));
|
|
5163
6123
|
}
|
|
5164
6124
|
|
|
5165
6125
|
// src/registry.ts
|
|
@@ -5175,6 +6135,7 @@ export {
|
|
|
5175
6135
|
DatePickerCell,
|
|
5176
6136
|
LinkPickerCell,
|
|
5177
6137
|
PASTEL_PALETTES,
|
|
6138
|
+
RelationFilterPopover,
|
|
5178
6139
|
RelationPickerCell,
|
|
5179
6140
|
TEXT_REPRESENTABLE_TYPES,
|
|
5180
6141
|
TableBlock,
|