@universe-platform/ui 0.1.0-beta.10 → 0.1.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/globals.css +142 -21
- package/dist/index.d.mts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +1319 -442
- package/dist/index.mjs +1302 -426
- package/package.json +1 -1
package/dist/index.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,14 @@ function TableBlockClient({
|
|
|
3630
4279
|
return calculateMinColumnWidth(colName, false, col == null ? void 0 : col.type);
|
|
3631
4280
|
}
|
|
3632
4281
|
});
|
|
3633
|
-
const [isMounted, setIsMounted] =
|
|
3634
|
-
const [isInitialLoading, setIsInitialLoading] =
|
|
3635
|
-
const [page, setPage] =
|
|
3636
|
-
const [limit, setLimit] =
|
|
3637
|
-
const [totalRecords, setTotalRecords] =
|
|
3638
|
-
const [totalPages, setTotalPages] =
|
|
3639
|
-
const [showSummary, setShowSummary] =
|
|
3640
|
-
|
|
4282
|
+
const [isMounted, setIsMounted] = useState12(false);
|
|
4283
|
+
const [isInitialLoading, setIsInitialLoading] = useState12(true);
|
|
4284
|
+
const [page, setPage] = useState12(1);
|
|
4285
|
+
const [limit, setLimit] = useState12(50);
|
|
4286
|
+
const [totalRecords, setTotalRecords] = useState12(0);
|
|
4287
|
+
const [totalPages, setTotalPages] = useState12(1);
|
|
4288
|
+
const [showSummary, setShowSummary] = useState12(false);
|
|
4289
|
+
useEffect10(() => {
|
|
3641
4290
|
if (typeof window !== "undefined") {
|
|
3642
4291
|
const savedSummary = localStorage.getItem(`table_summary_${tableKey}`);
|
|
3643
4292
|
if (savedSummary !== null) {
|
|
@@ -3686,7 +4335,7 @@ function TableBlockClient({
|
|
|
3686
4335
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
3687
4336
|
});
|
|
3688
4337
|
};
|
|
3689
|
-
const mergeColumnDefs =
|
|
4338
|
+
const mergeColumnDefs = useCallback10((existingCols, incomingCols) => {
|
|
3690
4339
|
if (!incomingCols || incomingCols.length === 0) return existingCols || [];
|
|
3691
4340
|
if (!existingCols || existingCols.length === 0) return incomingCols;
|
|
3692
4341
|
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
@@ -3706,18 +4355,18 @@ function TableBlockClient({
|
|
|
3706
4355
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
3707
4356
|
});
|
|
3708
4357
|
}, []);
|
|
3709
|
-
const [localColumns, setLocalColumns] =
|
|
3710
|
-
|
|
4358
|
+
const [localColumns, setLocalColumns] = useState12(() => (schema == null ? void 0 : schema.columns) || []);
|
|
4359
|
+
useEffect10(() => {
|
|
3711
4360
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
3712
4361
|
setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
|
|
3713
4362
|
}
|
|
3714
4363
|
}, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
|
|
3715
|
-
const [dirty, setDirty] =
|
|
3716
|
-
const dirtyRef =
|
|
3717
|
-
|
|
4364
|
+
const [dirty, setDirty] = useState12({ added: [], modified: {}, deleted: [] });
|
|
4365
|
+
const dirtyRef = useRef8(dirty);
|
|
4366
|
+
useEffect10(() => {
|
|
3718
4367
|
dirtyRef.current = dirty;
|
|
3719
4368
|
}, [dirty]);
|
|
3720
|
-
const mergeWithDirty =
|
|
4369
|
+
const mergeWithDirty = useCallback10((baseRecords) => {
|
|
3721
4370
|
const { added, modified, deleted } = dirtyRef.current;
|
|
3722
4371
|
const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
|
|
3723
4372
|
const modifiedRecords = nonDeleted.map((r) => {
|
|
@@ -3730,9 +4379,9 @@ function TableBlockClient({
|
|
|
3730
4379
|
const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
|
|
3731
4380
|
return [...uniqueAdded, ...modifiedRecords];
|
|
3732
4381
|
}, []);
|
|
3733
|
-
const [data, setData] =
|
|
3734
|
-
const [serverRecords, setServerRecords] =
|
|
3735
|
-
|
|
4382
|
+
const [data, setData] = useState12(() => normalizeRecords(initialRecords));
|
|
4383
|
+
const [serverRecords, setServerRecords] = useState12(() => normalizeRecords(initialRecords));
|
|
4384
|
+
useEffect10(() => {
|
|
3736
4385
|
if (initialRecords) {
|
|
3737
4386
|
const norm = normalizeRecords(initialRecords);
|
|
3738
4387
|
setServerRecords(norm);
|
|
@@ -3749,25 +4398,109 @@ function TableBlockClient({
|
|
|
3749
4398
|
}
|
|
3750
4399
|
return false;
|
|
3751
4400
|
};
|
|
3752
|
-
const [baseRecordsMap, setBaseRecordsMap] =
|
|
4401
|
+
const [baseRecordsMap, setBaseRecordsMap] = useState12(() => {
|
|
3753
4402
|
const map = /* @__PURE__ */ new Map();
|
|
3754
4403
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
3755
4404
|
return map;
|
|
3756
4405
|
});
|
|
3757
|
-
|
|
4406
|
+
useEffect10(() => {
|
|
3758
4407
|
if (initialRecords && initialRecords.length > 0) {
|
|
3759
4408
|
const map = /* @__PURE__ */ new Map();
|
|
3760
4409
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
3761
4410
|
setBaseRecordsMap(map);
|
|
3762
4411
|
}
|
|
3763
4412
|
}, [initialRecords]);
|
|
3764
|
-
const
|
|
4413
|
+
const [searchQuery, setSearchQuery] = useState12("");
|
|
4414
|
+
const [columnFilters, setColumnFilters] = useState12({});
|
|
4415
|
+
const [activeSearchCol, setActiveSearchCol] = useState12(null);
|
|
4416
|
+
const activeSearchRef = useRef8(null);
|
|
4417
|
+
const [activeRelationCol, setActiveRelationCol] = useState12(null);
|
|
4418
|
+
const [relationTriggerRect, setRelationTriggerRect] = useState12(null);
|
|
4419
|
+
const filterButtonRefs = useRef8({});
|
|
4420
|
+
const [relationOptions, setRelationOptions] = useState12({});
|
|
4421
|
+
const relationDictionaryRef = useRef8({});
|
|
4422
|
+
const mergeRelationOptions = useCallback10((colName, newOptions) => {
|
|
4423
|
+
if (!Array.isArray(newOptions) || newOptions.length === 0) return;
|
|
4424
|
+
if (!relationDictionaryRef.current[colName]) {
|
|
4425
|
+
relationDictionaryRef.current[colName] = /* @__PURE__ */ new Map();
|
|
4426
|
+
}
|
|
4427
|
+
const dict = relationDictionaryRef.current[colName];
|
|
4428
|
+
let hasNew = false;
|
|
4429
|
+
for (const opt of newOptions) {
|
|
4430
|
+
if (!opt) continue;
|
|
4431
|
+
const id = String(opt.id || opt._id || "");
|
|
4432
|
+
if (!id) continue;
|
|
4433
|
+
const existing = dict.get(id);
|
|
4434
|
+
if (!existing || opt.label && !existing.label) {
|
|
4435
|
+
dict.set(id, opt);
|
|
4436
|
+
hasNew = true;
|
|
4437
|
+
}
|
|
4438
|
+
}
|
|
4439
|
+
if (hasNew) {
|
|
4440
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), {
|
|
4441
|
+
[colName]: Array.from(dict.values())
|
|
4442
|
+
}));
|
|
4443
|
+
}
|
|
4444
|
+
}, []);
|
|
4445
|
+
useEffect10(() => {
|
|
4446
|
+
if (!activeSearchCol) return;
|
|
4447
|
+
const handleMouseDown = (e) => {
|
|
4448
|
+
if (activeSearchRef.current && !activeSearchRef.current.contains(e.target)) {
|
|
4449
|
+
setActiveSearchCol(null);
|
|
4450
|
+
}
|
|
4451
|
+
};
|
|
4452
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4453
|
+
return () => {
|
|
4454
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
4455
|
+
};
|
|
4456
|
+
}, [activeSearchCol]);
|
|
4457
|
+
const filtersKey = useMemo6(() => {
|
|
4458
|
+
const active = {};
|
|
4459
|
+
Object.entries(columnFilters).forEach(([k, v]) => {
|
|
4460
|
+
if (Array.isArray(v) && v.length > 0) active[k] = v;
|
|
4461
|
+
else if (v && typeof v === "object" && "operator" in v && Array.isArray(v.values) && v.values.length > 0) active[k] = v;
|
|
4462
|
+
else if (typeof v === "string" && v.trim()) active[k] = v.trim();
|
|
4463
|
+
});
|
|
4464
|
+
return JSON.stringify(active);
|
|
4465
|
+
}, [columnFilters]);
|
|
4466
|
+
const [debouncedSearch, setDebouncedSearch] = useState12(searchQuery);
|
|
4467
|
+
useEffect10(() => {
|
|
4468
|
+
const timer = setTimeout(() => {
|
|
4469
|
+
setDebouncedSearch(searchQuery.trim());
|
|
4470
|
+
}, 300);
|
|
4471
|
+
return () => clearTimeout(timer);
|
|
4472
|
+
}, [searchQuery]);
|
|
4473
|
+
const isSearchMountedRef = useRef8(false);
|
|
4474
|
+
useEffect10(() => {
|
|
4475
|
+
if (!isSearchMountedRef.current) {
|
|
4476
|
+
isSearchMountedRef.current = true;
|
|
4477
|
+
return;
|
|
4478
|
+
}
|
|
4479
|
+
setPage(1);
|
|
4480
|
+
}, [debouncedSearch]);
|
|
4481
|
+
const [isFetching, setIsFetching] = useState12(false);
|
|
4482
|
+
const fetchRequestIdRef = useRef8(0);
|
|
4483
|
+
const fetchTableData = useCallback10((targetPage, targetLimit, targetSearch, targetFiltersKey) => {
|
|
3765
4484
|
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
3766
4485
|
if (!tableId || !executeAction) return Promise.resolve();
|
|
3767
|
-
const
|
|
3768
|
-
|
|
3769
|
-
|
|
4486
|
+
const currentRequestId = ++fetchRequestIdRef.current;
|
|
4487
|
+
setIsFetching(true);
|
|
4488
|
+
let activeFilters = {};
|
|
4489
|
+
try {
|
|
4490
|
+
activeFilters = JSON.parse(targetFiltersKey);
|
|
4491
|
+
} catch (e) {
|
|
4492
|
+
}
|
|
4493
|
+
const skip = (targetPage - 1) * targetLimit;
|
|
4494
|
+
return executeAction("FETCH_TABLE_DATA", {
|
|
4495
|
+
tableId,
|
|
4496
|
+
page: targetPage,
|
|
4497
|
+
limit: targetLimit,
|
|
4498
|
+
skip,
|
|
4499
|
+
search: targetSearch || void 0,
|
|
4500
|
+
columnFilters: Object.keys(activeFilters).length > 0 ? activeFilters : void 0
|
|
4501
|
+
}).then((res) => {
|
|
3770
4502
|
var _a;
|
|
4503
|
+
if (currentRequestId !== fetchRequestIdRef.current) return;
|
|
3771
4504
|
if (res) {
|
|
3772
4505
|
if (((_a = res.schema) == null ? void 0 : _a.columns) && res.schema.columns.length > 0) {
|
|
3773
4506
|
setLocalColumns((prev) => mergeColumnDefs(prev, res.schema.columns));
|
|
@@ -3782,37 +4515,50 @@ function TableBlockClient({
|
|
|
3782
4515
|
}
|
|
3783
4516
|
if (res.meta) {
|
|
3784
4517
|
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 /
|
|
4518
|
+
const pages = typeof res.meta.totalPages === "number" ? res.meta.totalPages : Math.ceil(total / targetLimit) || 1;
|
|
3786
4519
|
setTotalRecords(total);
|
|
3787
4520
|
setTotalPages(pages);
|
|
3788
|
-
if (activePage > pages && pages >= 1) {
|
|
3789
|
-
setPage(pages);
|
|
3790
|
-
}
|
|
3791
4521
|
} else if (res.records && Array.isArray(res.records)) {
|
|
3792
4522
|
setTotalRecords(res.records.length);
|
|
3793
|
-
setTotalPages(Math.ceil(res.records.length /
|
|
4523
|
+
setTotalPages(Math.ceil(res.records.length / targetLimit) || 1);
|
|
4524
|
+
}
|
|
4525
|
+
if (res.relationOptions && typeof res.relationOptions === "object") {
|
|
4526
|
+
for (const [colName, opts] of Object.entries(res.relationOptions)) {
|
|
4527
|
+
if (Array.isArray(opts)) {
|
|
4528
|
+
mergeRelationOptions(colName, opts);
|
|
4529
|
+
}
|
|
4530
|
+
}
|
|
3794
4531
|
}
|
|
3795
4532
|
}
|
|
3796
4533
|
}).catch((err) => {
|
|
3797
|
-
|
|
4534
|
+
if (currentRequestId === fetchRequestIdRef.current) {
|
|
4535
|
+
console.error("[TableBlock] Failed to fetch table data:", err);
|
|
4536
|
+
}
|
|
4537
|
+
}).finally(() => {
|
|
4538
|
+
if (currentRequestId === fetchRequestIdRef.current) {
|
|
4539
|
+
setIsFetching(false);
|
|
4540
|
+
setIsInitialLoading(false);
|
|
4541
|
+
}
|
|
3798
4542
|
});
|
|
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
|
-
|
|
4543
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, executeAction, mergeColumnDefs, mergeWithDirty, mergeRelationOptions]);
|
|
4544
|
+
useEffect10(() => {
|
|
4545
|
+
fetchTableData(page, limit, debouncedSearch, filtersKey);
|
|
4546
|
+
}, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
|
|
4547
|
+
const refetchTableData = useCallback10(() => {
|
|
4548
|
+
return fetchTableData(page, limit, debouncedSearch, filtersKey);
|
|
4549
|
+
}, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
|
|
4550
|
+
const handleApplyColumnFilter = useCallback10((colName, nextVal) => {
|
|
4551
|
+
setColumnFilters((prev) => {
|
|
4552
|
+
const next = __spreadValues({}, prev);
|
|
4553
|
+
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) {
|
|
4554
|
+
delete next[colName];
|
|
4555
|
+
} else {
|
|
4556
|
+
next[colName] = nextVal;
|
|
4557
|
+
}
|
|
4558
|
+
return next;
|
|
4559
|
+
});
|
|
4560
|
+
setPage(1);
|
|
4561
|
+
}, []);
|
|
3816
4562
|
const handleLimitChange = (newLimit) => {
|
|
3817
4563
|
setLimit(newLimit);
|
|
3818
4564
|
setPage(1);
|
|
@@ -3826,37 +4572,15 @@ function TableBlockClient({
|
|
|
3826
4572
|
const handleNextPage = () => {
|
|
3827
4573
|
setPage((prev) => Math.min(totalPages, prev + 1));
|
|
3828
4574
|
};
|
|
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);
|
|
4575
|
+
const [selectedIds, setSelectedIds] = useState12(/* @__PURE__ */ new Set());
|
|
4576
|
+
const [pendingDeletions, setPendingDeletions] = useState12([]);
|
|
4577
|
+
const [isSaving, setIsSaving] = useState12(false);
|
|
3853
4578
|
const isUpdatingActive = Boolean(isUpdating || isSaving);
|
|
3854
|
-
const [isSaveSuccess, setIsSaveSuccess] =
|
|
3855
|
-
const [
|
|
3856
|
-
const
|
|
3857
|
-
const
|
|
3858
|
-
|
|
3859
|
-
var _a, _b, _c;
|
|
4579
|
+
const [isSaveSuccess, setIsSaveSuccess] = useState12(false);
|
|
4580
|
+
const [expandedRowIds, setExpandedRowIds] = useState12(/* @__PURE__ */ new Set());
|
|
4581
|
+
const schemaColsString = useMemo6(() => JSON.stringify(localColumns || []), [localColumns]);
|
|
4582
|
+
const refetchRelation = useCallback10(async (colName, params) => {
|
|
4583
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3860
4584
|
let parsedCols = [];
|
|
3861
4585
|
try {
|
|
3862
4586
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -3866,19 +4590,89 @@ function TableBlockClient({
|
|
|
3866
4590
|
var _a2;
|
|
3867
4591
|
return c.name === colName && ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION";
|
|
3868
4592
|
});
|
|
3869
|
-
if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId)) return;
|
|
4593
|
+
if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId)) return [];
|
|
3870
4594
|
try {
|
|
3871
4595
|
if (executeAction) {
|
|
3872
|
-
const
|
|
3873
|
-
|
|
3874
|
-
|
|
4596
|
+
const take = (_c = (_b = params == null ? void 0 : params.take) != null ? _b : params == null ? void 0 : params.limit) != null ? _c : 1e3;
|
|
4597
|
+
const payload = {
|
|
4598
|
+
referencedTableId: (_d = col.config) == null ? void 0 : _d.referencedTableId,
|
|
4599
|
+
displayField: (_e = col.config) == null ? void 0 : _e.displayField
|
|
4600
|
+
};
|
|
4601
|
+
if (params == null ? void 0 : params.recordIds) {
|
|
4602
|
+
payload.recordIds = params.recordIds;
|
|
4603
|
+
} else {
|
|
4604
|
+
payload.take = take;
|
|
4605
|
+
payload.limit = take;
|
|
4606
|
+
payload.skip = (_f = params == null ? void 0 : params.skip) != null ? _f : 0;
|
|
4607
|
+
payload.search = (_g = params == null ? void 0 : params.search) != null ? _g : "";
|
|
4608
|
+
}
|
|
4609
|
+
const options = await executeAction("FETCH_RELATION", payload);
|
|
4610
|
+
const list = Array.isArray(options) ? options : (options == null ? void 0 : options.data) && Array.isArray(options.data) ? options.data : [];
|
|
4611
|
+
if (list && Array.isArray(list)) {
|
|
4612
|
+
mergeRelationOptions(colName, list);
|
|
4613
|
+
return list;
|
|
3875
4614
|
}
|
|
3876
4615
|
}
|
|
3877
4616
|
} catch (err) {
|
|
3878
4617
|
console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
|
|
3879
4618
|
}
|
|
3880
|
-
|
|
3881
|
-
|
|
4619
|
+
return [];
|
|
4620
|
+
}, [schemaColsString, executeAction, mergeRelationOptions]);
|
|
4621
|
+
const requestedRelationIdsRef = useRef8({});
|
|
4622
|
+
useEffect10(() => {
|
|
4623
|
+
if (!executeAction || !data || data.length === 0) return;
|
|
4624
|
+
let parsedCols = [];
|
|
4625
|
+
try {
|
|
4626
|
+
parsedCols = JSON.parse(schemaColsString);
|
|
4627
|
+
} catch (e) {
|
|
4628
|
+
}
|
|
4629
|
+
const relationCols = parsedCols.filter(
|
|
4630
|
+
(c) => {
|
|
4631
|
+
var _a;
|
|
4632
|
+
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
|
|
4633
|
+
}
|
|
4634
|
+
);
|
|
4635
|
+
if (relationCols.length === 0) return;
|
|
4636
|
+
relationCols.forEach(async (col) => {
|
|
4637
|
+
var _a, _b;
|
|
4638
|
+
const referencedTableId = (_a = col.config) == null ? void 0 : _a.referencedTableId;
|
|
4639
|
+
if (!referencedTableId) return;
|
|
4640
|
+
const extractedIds = /* @__PURE__ */ new Set();
|
|
4641
|
+
data.forEach((row) => {
|
|
4642
|
+
if (!(row == null ? void 0 : row.data)) return;
|
|
4643
|
+
const ids = normalizeRelationValue(row.data[col.name]);
|
|
4644
|
+
ids.forEach((id) => {
|
|
4645
|
+
if (/^[0-9a-fA-F]{24}$/.test(id)) {
|
|
4646
|
+
extractedIds.add(id);
|
|
4647
|
+
}
|
|
4648
|
+
});
|
|
4649
|
+
});
|
|
4650
|
+
if (extractedIds.size === 0) return;
|
|
4651
|
+
const existingOptions = relationOptions[col.name] || [];
|
|
4652
|
+
const existingIds = new Set(existingOptions.map((o) => String(o.id)));
|
|
4653
|
+
if (!requestedRelationIdsRef.current[col.name]) {
|
|
4654
|
+
requestedRelationIdsRef.current[col.name] = /* @__PURE__ */ new Set();
|
|
4655
|
+
}
|
|
4656
|
+
const inFlight = requestedRelationIdsRef.current[col.name];
|
|
4657
|
+
const missingIds = Array.from(extractedIds).filter((id) => !existingIds.has(id) && !inFlight.has(id));
|
|
4658
|
+
if (missingIds.length === 0) return;
|
|
4659
|
+
missingIds.forEach((id) => inFlight.add(id));
|
|
4660
|
+
try {
|
|
4661
|
+
const resolved = await executeAction("FETCH_RELATION", {
|
|
4662
|
+
referencedTableId,
|
|
4663
|
+
displayField: (_b = col.config) == null ? void 0 : _b.displayField,
|
|
4664
|
+
recordIds: missingIds
|
|
4665
|
+
});
|
|
4666
|
+
const items = Array.isArray(resolved) ? resolved : (resolved == null ? void 0 : resolved.data) && Array.isArray(resolved.data) ? resolved.data : [];
|
|
4667
|
+
if (items.length > 0) {
|
|
4668
|
+
mergeRelationOptions(col.name, items);
|
|
4669
|
+
}
|
|
4670
|
+
} catch (err) {
|
|
4671
|
+
console.warn(`[TableBlock] Failed to populate relations for ${col.name}:`, err);
|
|
4672
|
+
}
|
|
4673
|
+
});
|
|
4674
|
+
}, [data, schemaColsString, executeAction, relationOptions, mergeRelationOptions]);
|
|
4675
|
+
useEffect10(() => {
|
|
3882
4676
|
let parsedCols = [];
|
|
3883
4677
|
try {
|
|
3884
4678
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -3892,7 +4686,7 @@ function TableBlockClient({
|
|
|
3892
4686
|
refetchRelation(col.name);
|
|
3893
4687
|
});
|
|
3894
4688
|
}, [schemaColsString, refetchRelation]);
|
|
3895
|
-
const normalizedColumns =
|
|
4689
|
+
const normalizedColumns = useMemo6(() => {
|
|
3896
4690
|
return (localColumns || []).map((col, idx) => {
|
|
3897
4691
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
3898
4692
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
@@ -3906,17 +4700,17 @@ function TableBlockClient({
|
|
|
3906
4700
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
3907
4701
|
});
|
|
3908
4702
|
}, [localColumns]);
|
|
3909
|
-
const filteredColumns =
|
|
4703
|
+
const filteredColumns = useMemo6(() => {
|
|
3910
4704
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
3911
4705
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
|
|
3912
4706
|
}, [normalizedColumns]);
|
|
3913
|
-
const customizableColumns =
|
|
4707
|
+
const customizableColumns = useMemo6(() => {
|
|
3914
4708
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
3915
4709
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name));
|
|
3916
4710
|
}, [normalizedColumns]);
|
|
3917
|
-
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] =
|
|
3918
|
-
const dropdownRef =
|
|
3919
|
-
|
|
4711
|
+
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState12(false);
|
|
4712
|
+
const dropdownRef = useRef8(null);
|
|
4713
|
+
useEffect10(() => {
|
|
3920
4714
|
const handleClickOutside = (e) => {
|
|
3921
4715
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
3922
4716
|
setIsColumnsDropdownOpen(false);
|
|
@@ -4159,13 +4953,13 @@ function TableBlockClient({
|
|
|
4159
4953
|
});
|
|
4160
4954
|
}
|
|
4161
4955
|
};
|
|
4162
|
-
const triggerSaveSuccess =
|
|
4956
|
+
const triggerSaveSuccess = useCallback10(() => {
|
|
4163
4957
|
setIsSaveSuccess(true);
|
|
4164
4958
|
setTimeout(() => {
|
|
4165
4959
|
setIsSaveSuccess(false);
|
|
4166
4960
|
}, 2500);
|
|
4167
4961
|
}, []);
|
|
4168
|
-
const handleQuietCellChange =
|
|
4962
|
+
const handleQuietCellChange = useCallback10((rowId, colName, value) => {
|
|
4169
4963
|
setData((prev) => prev.map(
|
|
4170
4964
|
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
4171
4965
|
));
|
|
@@ -4433,7 +5227,7 @@ function TableBlockClient({
|
|
|
4433
5227
|
setIsSaving(false);
|
|
4434
5228
|
}
|
|
4435
5229
|
};
|
|
4436
|
-
const getRowRelationLabels =
|
|
5230
|
+
const getRowRelationLabels = useCallback10((rowVal, col) => {
|
|
4437
5231
|
const ids = normalizeRelationValue(rowVal);
|
|
4438
5232
|
if (ids.length === 0) return [];
|
|
4439
5233
|
const options = relationOptions[col.name] || [];
|
|
@@ -4441,21 +5235,38 @@ function TableBlockClient({
|
|
|
4441
5235
|
const opt = options.find((o) => o.id === id || o._id === id);
|
|
4442
5236
|
if (opt) {
|
|
4443
5237
|
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);
|
|
5238
|
+
if (resolved && !isRawObjectId(resolved)) return resolved;
|
|
5239
|
+
if (opt.label && !isRawObjectId(String(opt.label))) return String(opt.label);
|
|
5240
|
+
if (opt.name && !isRawObjectId(String(opt.name))) return String(opt.name);
|
|
4447
5241
|
}
|
|
4448
5242
|
if (typeof rowVal === "object" && rowVal !== null) {
|
|
4449
|
-
if (rowVal._displayLabel) return String(rowVal._displayLabel);
|
|
4450
|
-
if (rowVal.label) return String(rowVal.label);
|
|
5243
|
+
if (rowVal._displayLabel && !isRawObjectId(String(rowVal._displayLabel))) return String(rowVal._displayLabel);
|
|
5244
|
+
if (rowVal.label && !isRawObjectId(String(rowVal.label))) return String(rowVal.label);
|
|
4451
5245
|
}
|
|
4452
|
-
return
|
|
4453
|
-
});
|
|
5246
|
+
return "";
|
|
5247
|
+
}).filter(Boolean);
|
|
4454
5248
|
}, [relationOptions]);
|
|
4455
|
-
const getUniqueRelationOptions =
|
|
5249
|
+
const getUniqueRelationOptions = useCallback10((col) => {
|
|
4456
5250
|
const seenIds = /* @__PURE__ */ new Set();
|
|
5251
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
4457
5252
|
const results = [];
|
|
4458
5253
|
const options = relationOptions[col.name] || [];
|
|
5254
|
+
options.forEach((opt) => {
|
|
5255
|
+
const id = String(opt.id || opt._id || "");
|
|
5256
|
+
if (!id) return;
|
|
5257
|
+
let label = resolveRelationLabel(opt, col);
|
|
5258
|
+
if (!label) {
|
|
5259
|
+
const fallback = opt.label || opt.name || opt.title;
|
|
5260
|
+
if (fallback && typeof fallback === "string" && !isRawObjectId(fallback)) {
|
|
5261
|
+
label = fallback.trim();
|
|
5262
|
+
}
|
|
5263
|
+
}
|
|
5264
|
+
if (label && label.trim() && !isRawObjectId(label) && !seenLabels.has(label.trim())) {
|
|
5265
|
+
seenIds.add(id);
|
|
5266
|
+
seenLabels.add(label.trim());
|
|
5267
|
+
results.push({ id, label: label.trim() });
|
|
5268
|
+
}
|
|
5269
|
+
});
|
|
4459
5270
|
data.forEach((row) => {
|
|
4460
5271
|
if (!(row == null ? void 0 : row.data)) return;
|
|
4461
5272
|
const ids = normalizeRelationValue(row.data[col.name]);
|
|
@@ -4464,58 +5275,24 @@ function TableBlockClient({
|
|
|
4464
5275
|
seenIds.add(id);
|
|
4465
5276
|
const opt = options.find((o) => o.id === id || o._id === id);
|
|
4466
5277
|
let label = opt ? resolveRelationLabel(opt, col) : "";
|
|
4467
|
-
if (!label && opt)
|
|
4468
|
-
|
|
4469
|
-
|
|
5278
|
+
if (!label && opt) {
|
|
5279
|
+
const fallback = opt.label || opt.name || opt.title;
|
|
5280
|
+
if (fallback && typeof fallback === "string" && !isRawObjectId(fallback)) {
|
|
5281
|
+
label = fallback.trim();
|
|
5282
|
+
}
|
|
5283
|
+
}
|
|
5284
|
+
if (label && label.trim() && label !== id && !isRawObjectId(label) && !seenLabels.has(label.trim())) {
|
|
5285
|
+
seenLabels.add(label.trim());
|
|
5286
|
+
results.push({ id, label: label.trim() });
|
|
5287
|
+
}
|
|
4470
5288
|
}
|
|
4471
5289
|
});
|
|
4472
5290
|
});
|
|
4473
5291
|
return results.sort((a, b) => a.label.localeCompare(b.label));
|
|
4474
5292
|
}, [data, relationOptions]);
|
|
4475
|
-
const filteredData =
|
|
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));
|
|
4492
|
-
}
|
|
4493
|
-
if (typeof rawVal === "object") {
|
|
4494
|
-
return JSON.stringify(rawVal).toLowerCase().includes(lowerGlobal);
|
|
4495
|
-
}
|
|
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
|
-
}
|
|
4513
|
-
}
|
|
4514
|
-
return true;
|
|
4515
|
-
});
|
|
4516
|
-
}, [data, searchQuery, columnFilters, localColumns, getRowRelationLabels]);
|
|
5293
|
+
const filteredData = data;
|
|
4517
5294
|
const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
|
|
4518
|
-
const columnTotals =
|
|
5295
|
+
const columnTotals = useMemo6(() => {
|
|
4519
5296
|
const totals = {};
|
|
4520
5297
|
if (!showSummary) return totals;
|
|
4521
5298
|
filteredColumns.forEach((col) => {
|
|
@@ -4533,42 +5310,120 @@ function TableBlockClient({
|
|
|
4533
5310
|
});
|
|
4534
5311
|
return totals;
|
|
4535
5312
|
}, [filteredData, filteredColumns, showSummary]);
|
|
4536
|
-
|
|
5313
|
+
const hasSelectedRows = selectedIds.size > 0;
|
|
5314
|
+
const hasActiveSearchOrFilter = Boolean(searchQuery && searchQuery.trim() !== "") || Object.values(columnFilters).some(
|
|
5315
|
+
(v) => Array.isArray(v) ? v.length > 0 : v && typeof v === "object" && "values" in v ? v.values.length > 0 : typeof v === "string" && Boolean(v.trim())
|
|
5316
|
+
);
|
|
5317
|
+
let exportButtonText = "\u05D9\u05D9\u05E6\u05D0 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD";
|
|
5318
|
+
let ExportButtonIcon = Download;
|
|
5319
|
+
if (hasSelectedRows) {
|
|
5320
|
+
exportButtonText = `\u05D9\u05D9\u05E6\u05D0 ${selectedIds.size} \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA`;
|
|
5321
|
+
ExportButtonIcon = Download;
|
|
5322
|
+
} else if (hasActiveSearchOrFilter) {
|
|
5323
|
+
exportButtonText = "\u05D9\u05D9\u05E6\u05D0 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA \u05E1\u05D9\u05E0\u05D5\u05DF";
|
|
5324
|
+
ExportButtonIcon = Filter;
|
|
5325
|
+
}
|
|
5326
|
+
const handleExportCsv = async () => {
|
|
5327
|
+
if (isExporting) return;
|
|
5328
|
+
const systemFields = ["_id", "id", "createdAt", "updatedAt", "createdBy", "updatedBy", "orgId", "tableId"];
|
|
5329
|
+
const userHiddenColumns = normalizedColumns.filter((c) => c.isHidden && !systemFields.includes(c.name)).map((c) => c.name);
|
|
5330
|
+
if (userHiddenColumns.length > 0) {
|
|
5331
|
+
addToast({
|
|
5332
|
+
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",
|
|
5333
|
+
type: "info",
|
|
5334
|
+
duration: 3e3
|
|
5335
|
+
});
|
|
5336
|
+
} else {
|
|
5337
|
+
addToast({
|
|
5338
|
+
message: "\u05DE\u05D9\u05D9\u05E6\u05D0 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD...",
|
|
5339
|
+
type: "info",
|
|
5340
|
+
duration: 3e3
|
|
5341
|
+
});
|
|
5342
|
+
}
|
|
5343
|
+
setIsExporting(true);
|
|
5344
|
+
try {
|
|
5345
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
5346
|
+
if (!targetTableId) {
|
|
5347
|
+
showError("\u05DE\u05D6\u05D4\u05D4 \u05D4\u05D8\u05D1\u05DC\u05D4 \u05D7\u05E1\u05E8 (tableId)", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D9\u05D9\u05E6\u05D5\u05D0");
|
|
5348
|
+
return;
|
|
5349
|
+
}
|
|
5350
|
+
const payload = {
|
|
5351
|
+
tableId: targetTableId,
|
|
5352
|
+
orgId,
|
|
5353
|
+
search: searchQuery.trim() || void 0,
|
|
5354
|
+
columnFilters: Object.keys(columnFilters).length > 0 ? columnFilters : void 0,
|
|
5355
|
+
selectedRowIds: hasSelectedRows ? Array.from(selectedIds) : [],
|
|
5356
|
+
hiddenColumnIds: userHiddenColumns
|
|
5357
|
+
};
|
|
5358
|
+
let res;
|
|
5359
|
+
if (exportAction) {
|
|
5360
|
+
res = await exportAction(payload);
|
|
5361
|
+
} else if (executeAction) {
|
|
5362
|
+
res = await executeAction("EXPORT_TABLE_TO_CSV", payload);
|
|
5363
|
+
} else {
|
|
5364
|
+
throw new Error("\u05E8\u05DB\u05D9\u05D1 \u05D4\u05EA\u05E7\u05E9\u05D5\u05E8\u05EA \u05DC\u05D0 \u05D0\u05D5\u05EA\u05D7\u05DC");
|
|
5365
|
+
}
|
|
5366
|
+
const result = (res == null ? void 0 : res.data) || res;
|
|
5367
|
+
if ((result == null ? void 0 : result.success) === false) {
|
|
5368
|
+
throw new Error(result.error || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D9\u05D9\u05E6\u05D5\u05D0 \u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD");
|
|
5369
|
+
}
|
|
5370
|
+
const csvString = (result == null ? void 0 : result.csvString) || (result == null ? void 0 : result.csv);
|
|
5371
|
+
if (!csvString) {
|
|
5372
|
+
throw new Error("\u05DC\u05D0 \u05D4\u05EA\u05E7\u05D1\u05DC\u05D5 \u05E0\u05EA\u05D5\u05E0\u05D9 CSV \u05DE\u05D4\u05E9\u05E8\u05EA");
|
|
5373
|
+
}
|
|
5374
|
+
const fileName = (result == null ? void 0 : result.fileName) || `${((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name) || "table").trim()}_export.csv`;
|
|
5375
|
+
const blob = new Blob([csvString], { type: "text/csv;charset=utf-8;" });
|
|
5376
|
+
const url = URL.createObjectURL(blob);
|
|
5377
|
+
const link = document.createElement("a");
|
|
5378
|
+
link.href = url;
|
|
5379
|
+
link.setAttribute("download", fileName);
|
|
5380
|
+
document.body.appendChild(link);
|
|
5381
|
+
link.click();
|
|
5382
|
+
document.body.removeChild(link);
|
|
5383
|
+
URL.revokeObjectURL(url);
|
|
5384
|
+
} catch (err) {
|
|
5385
|
+
console.error("[TableBlock] Export to CSV failed:", err);
|
|
5386
|
+
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");
|
|
5387
|
+
} finally {
|
|
5388
|
+
setIsExporting(false);
|
|
5389
|
+
}
|
|
5390
|
+
};
|
|
5391
|
+
return /* @__PURE__ */ jsxs11(
|
|
4537
5392
|
"div",
|
|
4538
5393
|
{
|
|
4539
5394
|
id: componentId,
|
|
4540
5395
|
"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-
|
|
5396
|
+
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
5397
|
dir: "rtl",
|
|
4543
5398
|
children: [
|
|
4544
|
-
errorMessage && /* @__PURE__ */
|
|
4545
|
-
/* @__PURE__ */
|
|
4546
|
-
/* @__PURE__ */
|
|
5399
|
+
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: [
|
|
5400
|
+
/* @__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" }) }),
|
|
5401
|
+
/* @__PURE__ */ jsx11("span", { children: errorMessage })
|
|
4547
5402
|
] }) }),
|
|
4548
|
-
/* @__PURE__ */
|
|
4549
|
-
/* @__PURE__ */
|
|
4550
|
-
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */
|
|
4551
|
-
/* @__PURE__ */
|
|
5403
|
+
/* @__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: [
|
|
5404
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
5405
|
+
((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 }) }),
|
|
5406
|
+
/* @__PURE__ */ jsx11(
|
|
4552
5407
|
"button",
|
|
4553
5408
|
{
|
|
4554
5409
|
onClick: handleAddRow,
|
|
4555
5410
|
disabled: isInitialLoading || isLoading || isUpdatingActive,
|
|
4556
5411
|
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
5412
|
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__ */
|
|
5413
|
+
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
5414
|
}
|
|
4560
5415
|
),
|
|
4561
|
-
/* @__PURE__ */
|
|
5416
|
+
/* @__PURE__ */ jsx11(
|
|
4562
5417
|
"button",
|
|
4563
5418
|
{
|
|
4564
5419
|
onClick: handleDuplicateRow,
|
|
4565
5420
|
disabled: isInitialLoading || isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
4566
5421
|
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
5422
|
title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
|
|
4568
|
-
children: /* @__PURE__ */
|
|
5423
|
+
children: /* @__PURE__ */ jsx11(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
4569
5424
|
}
|
|
4570
5425
|
),
|
|
4571
|
-
/* @__PURE__ */
|
|
5426
|
+
/* @__PURE__ */ jsxs11(
|
|
4572
5427
|
"button",
|
|
4573
5428
|
{
|
|
4574
5429
|
onClick: handleDeleteSelected,
|
|
@@ -4576,12 +5431,12 @@ function TableBlockClient({
|
|
|
4576
5431
|
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
5432
|
title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
|
|
4578
5433
|
children: [
|
|
4579
|
-
/* @__PURE__ */
|
|
4580
|
-
selectedIds.size > 0 && /* @__PURE__ */
|
|
5434
|
+
/* @__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" }) }),
|
|
5435
|
+
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
5436
|
]
|
|
4582
5437
|
}
|
|
4583
5438
|
),
|
|
4584
|
-
/* @__PURE__ */
|
|
5439
|
+
/* @__PURE__ */ jsxs11(
|
|
4585
5440
|
"button",
|
|
4586
5441
|
{
|
|
4587
5442
|
onClick: toggleSummary,
|
|
@@ -4589,13 +5444,13 @@ function TableBlockClient({
|
|
|
4589
5444
|
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
5445
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
|
|
4591
5446
|
children: [
|
|
4592
|
-
/* @__PURE__ */
|
|
4593
|
-
/* @__PURE__ */
|
|
5447
|
+
/* @__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" }) }),
|
|
5448
|
+
/* @__PURE__ */ jsx11("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
|
|
4594
5449
|
]
|
|
4595
5450
|
}
|
|
4596
5451
|
),
|
|
4597
|
-
/* @__PURE__ */
|
|
4598
|
-
/* @__PURE__ */
|
|
5452
|
+
/* @__PURE__ */ jsxs11("div", { className: "relative", ref: dropdownRef, children: [
|
|
5453
|
+
/* @__PURE__ */ jsxs11(
|
|
4599
5454
|
"button",
|
|
4600
5455
|
{
|
|
4601
5456
|
onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
|
|
@@ -4603,16 +5458,16 @@ function TableBlockClient({
|
|
|
4603
5458
|
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
5459
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
|
|
4605
5460
|
children: [
|
|
4606
|
-
/* @__PURE__ */
|
|
4607
|
-
/* @__PURE__ */
|
|
5461
|
+
/* @__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" }) }),
|
|
5462
|
+
/* @__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
5463
|
]
|
|
4609
5464
|
}
|
|
4610
5465
|
),
|
|
4611
|
-
isColumnsDropdownOpen && /* @__PURE__ */
|
|
4612
|
-
/* @__PURE__ */
|
|
4613
|
-
/* @__PURE__ */
|
|
4614
|
-
/* @__PURE__ */
|
|
4615
|
-
/* @__PURE__ */
|
|
5466
|
+
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: [
|
|
5467
|
+
/* @__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: [
|
|
5468
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5", children: [
|
|
5469
|
+
/* @__PURE__ */ jsx11("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
|
|
5470
|
+
/* @__PURE__ */ jsxs11("span", { className: "text-[10px] font-normal text-slate-400", children: [
|
|
4616
5471
|
"(",
|
|
4617
5472
|
customizableColumns.filter((c) => !c.isHidden).length,
|
|
4618
5473
|
"/",
|
|
@@ -4620,7 +5475,7 @@ function TableBlockClient({
|
|
|
4620
5475
|
")"
|
|
4621
5476
|
] })
|
|
4622
5477
|
] }),
|
|
4623
|
-
/* @__PURE__ */
|
|
5478
|
+
/* @__PURE__ */ jsx11(
|
|
4624
5479
|
"button",
|
|
4625
5480
|
{
|
|
4626
5481
|
type: "button",
|
|
@@ -4630,7 +5485,7 @@ function TableBlockClient({
|
|
|
4630
5485
|
}
|
|
4631
5486
|
)
|
|
4632
5487
|
] }),
|
|
4633
|
-
/* @__PURE__ */
|
|
5488
|
+
/* @__PURE__ */ jsx11("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
|
|
4634
5489
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
4635
5490
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
4636
5491
|
const isProtected = isRequired || isUnique;
|
|
@@ -4644,7 +5499,7 @@ function TableBlockClient({
|
|
|
4644
5499
|
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
5500
|
}
|
|
4646
5501
|
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__ */
|
|
5502
|
+
return /* @__PURE__ */ jsxs11(
|
|
4648
5503
|
"div",
|
|
4649
5504
|
{
|
|
4650
5505
|
onClick: () => {
|
|
@@ -4655,8 +5510,8 @@ function TableBlockClient({
|
|
|
4655
5510
|
title: isProtected ? protectedExplanation : void 0,
|
|
4656
5511
|
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
5512
|
children: [
|
|
4658
|
-
/* @__PURE__ */
|
|
4659
|
-
/* @__PURE__ */
|
|
5513
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
5514
|
+
/* @__PURE__ */ jsx11(
|
|
4660
5515
|
"input",
|
|
4661
5516
|
{
|
|
4662
5517
|
type: "checkbox",
|
|
@@ -4667,16 +5522,16 @@ function TableBlockClient({
|
|
|
4667
5522
|
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
5523
|
}
|
|
4669
5524
|
),
|
|
4670
|
-
/* @__PURE__ */
|
|
5525
|
+
/* @__PURE__ */ jsx11("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
|
|
4671
5526
|
] }),
|
|
4672
|
-
isProtected && /* @__PURE__ */
|
|
5527
|
+
isProtected && /* @__PURE__ */ jsxs11(
|
|
4673
5528
|
"div",
|
|
4674
5529
|
{
|
|
4675
5530
|
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
5531
|
title: protectedExplanation,
|
|
4677
5532
|
children: [
|
|
4678
|
-
/* @__PURE__ */
|
|
4679
|
-
/* @__PURE__ */
|
|
5533
|
+
/* @__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" }) }),
|
|
5534
|
+
/* @__PURE__ */ jsx11("span", { children: badgeLabel })
|
|
4680
5535
|
]
|
|
4681
5536
|
}
|
|
4682
5537
|
)
|
|
@@ -4687,9 +5542,23 @@ function TableBlockClient({
|
|
|
4687
5542
|
}) })
|
|
4688
5543
|
] })
|
|
4689
5544
|
] }),
|
|
4690
|
-
/* @__PURE__ */
|
|
4691
|
-
|
|
4692
|
-
|
|
5545
|
+
/* @__PURE__ */ jsxs11(
|
|
5546
|
+
"button",
|
|
5547
|
+
{
|
|
5548
|
+
onClick: handleExportCsv,
|
|
5549
|
+
disabled: isLoading || isUpdatingActive || isExporting,
|
|
5550
|
+
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"}`,
|
|
5551
|
+
title: exportButtonText,
|
|
5552
|
+
"data-testid": "export-csv-button",
|
|
5553
|
+
children: [
|
|
5554
|
+
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" }),
|
|
5555
|
+
/* @__PURE__ */ jsx11("span", { children: isExporting ? "\u05DE\u05D9\u05D9\u05E6\u05D0..." : exportButtonText })
|
|
5556
|
+
]
|
|
5557
|
+
}
|
|
5558
|
+
),
|
|
5559
|
+
/* @__PURE__ */ jsx11("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
5560
|
+
/* @__PURE__ */ jsxs11("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
5561
|
+
/* @__PURE__ */ jsx11(
|
|
4693
5562
|
"input",
|
|
4694
5563
|
{
|
|
4695
5564
|
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
@@ -4699,28 +5568,28 @@ function TableBlockClient({
|
|
|
4699
5568
|
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
5569
|
}
|
|
4701
5570
|
),
|
|
4702
|
-
searchQuery ? /* @__PURE__ */
|
|
5571
|
+
searchQuery ? /* @__PURE__ */ jsx11(
|
|
4703
5572
|
"button",
|
|
4704
5573
|
{
|
|
4705
5574
|
type: "button",
|
|
4706
5575
|
onClick: () => setSearchQuery(""),
|
|
4707
5576
|
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
5577
|
title: "Clear search",
|
|
4709
|
-
children: /* @__PURE__ */
|
|
5578
|
+
children: /* @__PURE__ */ jsx11(X8, { className: "w-3.5 h-3.5" })
|
|
4710
5579
|
}
|
|
4711
|
-
) : /* @__PURE__ */
|
|
5580
|
+
) : /* @__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
5581
|
] })
|
|
4713
5582
|
] }),
|
|
4714
|
-
/* @__PURE__ */
|
|
4715
|
-
isUpdatingActive ? /* @__PURE__ */
|
|
4716
|
-
/* @__PURE__ */
|
|
5583
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3", children: [
|
|
5584
|
+
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: [
|
|
5585
|
+
/* @__PURE__ */ jsx11("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
4717
5586
|
"\u05DE\u05E2\u05D3\u05DB\u05DF..."
|
|
4718
|
-
] }) : isSaveSuccess ? /* @__PURE__ */
|
|
4719
|
-
/* @__PURE__ */
|
|
5587
|
+
] }) : 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: [
|
|
5588
|
+
/* @__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
5589
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
4721
|
-
] }) : hasChanges ? /* @__PURE__ */
|
|
4722
|
-
/* @__PURE__ */
|
|
4723
|
-
/* @__PURE__ */
|
|
5590
|
+
] }) : hasChanges ? /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5 animate-in fade-in", children: [
|
|
5591
|
+
/* @__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" }),
|
|
5592
|
+
/* @__PURE__ */ jsx11(
|
|
4724
5593
|
"button",
|
|
4725
5594
|
{
|
|
4726
5595
|
type: "button",
|
|
@@ -4729,30 +5598,31 @@ function TableBlockClient({
|
|
|
4729
5598
|
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
5599
|
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
5600
|
"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__ */
|
|
5601
|
+
children: /* @__PURE__ */ jsx11(RotateCcw2, { className: "w-3.5 h-3.5" })
|
|
4733
5602
|
}
|
|
4734
5603
|
)
|
|
4735
5604
|
] }) : null,
|
|
4736
|
-
/* @__PURE__ */
|
|
5605
|
+
/* @__PURE__ */ jsx11(
|
|
4737
5606
|
"button",
|
|
4738
5607
|
{
|
|
4739
5608
|
onClick: handleSave,
|
|
4740
5609
|
disabled: isUpdatingActive || isLoading || !hasChanges,
|
|
4741
5610
|
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__ */
|
|
5611
|
+
children: /* @__PURE__ */ jsx11("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
|
|
4743
5612
|
}
|
|
4744
5613
|
)
|
|
4745
5614
|
] })
|
|
4746
5615
|
] }),
|
|
4747
|
-
/* @__PURE__ */
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
/* @__PURE__ */
|
|
5616
|
+
/* @__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: [
|
|
5617
|
+
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" }) }),
|
|
5618
|
+
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: [
|
|
5619
|
+
/* @__PURE__ */ jsx11("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
5620
|
+
/* @__PURE__ */ jsx11("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
4751
5621
|
] }),
|
|
4752
|
-
/* @__PURE__ */
|
|
4753
|
-
/* @__PURE__ */
|
|
4754
|
-
/* @__PURE__ */
|
|
4755
|
-
/* @__PURE__ */
|
|
5622
|
+
/* @__PURE__ */ jsxs11("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
|
|
5623
|
+
/* @__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: [
|
|
5624
|
+
/* @__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: [
|
|
5625
|
+
/* @__PURE__ */ jsx11(
|
|
4756
5626
|
"input",
|
|
4757
5627
|
{
|
|
4758
5628
|
type: "checkbox",
|
|
@@ -4765,7 +5635,7 @@ function TableBlockClient({
|
|
|
4765
5635
|
filteredColumns.some((c) => {
|
|
4766
5636
|
var _a;
|
|
4767
5637
|
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
4768
|
-
}) && /* @__PURE__ */
|
|
5638
|
+
}) && /* @__PURE__ */ jsx11("div", { className: "w-5 h-5 shrink-0" })
|
|
4769
5639
|
] }) }),
|
|
4770
5640
|
filteredColumns.map((col) => {
|
|
4771
5641
|
var _a, _b;
|
|
@@ -4776,16 +5646,25 @@ function TableBlockClient({
|
|
|
4776
5646
|
const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
|
|
4777
5647
|
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
|
|
4778
5648
|
const isRelation = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
|
|
4779
|
-
const filterVal = columnFilters[col.name]
|
|
4780
|
-
|
|
5649
|
+
const filterVal = columnFilters[col.name];
|
|
5650
|
+
const hasActiveFilter = Array.isArray(filterVal) ? filterVal.length > 0 : filterVal && typeof filterVal === "object" && "values" in filterVal ? filterVal.values.length > 0 : Boolean(filterVal && filterVal.trim() !== "");
|
|
5651
|
+
let filterTooltip = "\u05D7\u05E4\u05E9 \u05D5\u05E1\u05E0\u05DF \u05D1\u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5";
|
|
5652
|
+
if (Array.isArray(filterVal)) {
|
|
5653
|
+
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`;
|
|
5654
|
+
} else if (filterVal && typeof filterVal === "object" && "operator" in filterVal && filterVal.operator === "notIn") {
|
|
5655
|
+
filterTooltip = `\u05DE\u05D5\u05D7\u05E8\u05D2\u05D9\u05DD: ${filterVal.values.length} \u05E4\u05E8\u05D9\u05D8\u05D9\u05DD (\u05D4\u05DB\u05DC \u05DC\u05DE\u05E2\u05D8)`;
|
|
5656
|
+
} else if (typeof filterVal === "string" && filterVal.trim()) {
|
|
5657
|
+
filterTooltip = `\u05DE\u05E1\u05D5\u05E0\u05DF \u05DC\u05E4\u05D9: "${filterVal}" (\u05DC\u05D7\u05E5 \u05DC\u05E2\u05E8\u05D9\u05DB\u05D4)`;
|
|
5658
|
+
}
|
|
5659
|
+
return /* @__PURE__ */ jsxs11(
|
|
4781
5660
|
"th",
|
|
4782
5661
|
__spreadProps(__spreadValues({
|
|
4783
5662
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
4784
5663
|
title: isSearching ? void 0 : col.name
|
|
4785
5664
|
}, dragProps), {
|
|
4786
|
-
className: `relative border-b border-l border-slate-200 px-2
|
|
5665
|
+
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
5666
|
children: [
|
|
4788
|
-
/* @__PURE__ */
|
|
5667
|
+
/* @__PURE__ */ jsx11(
|
|
4789
5668
|
"div",
|
|
4790
5669
|
{
|
|
4791
5670
|
onMouseDown: (e) => {
|
|
@@ -4797,7 +5676,7 @@ function TableBlockClient({
|
|
|
4797
5676
|
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
4798
5677
|
}
|
|
4799
5678
|
),
|
|
4800
|
-
isSearching ? /* @__PURE__ */
|
|
5679
|
+
isSearching && !isRelation ? /* @__PURE__ */ jsxs11(
|
|
4801
5680
|
"div",
|
|
4802
5681
|
{
|
|
4803
5682
|
ref: activeSearchRef,
|
|
@@ -4805,46 +5684,15 @@ function TableBlockClient({
|
|
|
4805
5684
|
onClick: (e) => e.stopPropagation(),
|
|
4806
5685
|
onMouseDown: (e) => e.stopPropagation(),
|
|
4807
5686
|
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(
|
|
5687
|
+
/* @__PURE__ */ jsx11("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ jsx11(
|
|
4834
5688
|
"input",
|
|
4835
5689
|
{
|
|
4836
5690
|
autoFocus: true,
|
|
4837
5691
|
type: "text",
|
|
4838
5692
|
placeholder: `\u05D7\u05E4\u05E9 \u05D1-${col.name}...`,
|
|
4839
|
-
value: filterVal,
|
|
5693
|
+
value: typeof filterVal === "string" ? filterVal : "",
|
|
4840
5694
|
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
|
-
});
|
|
5695
|
+
handleApplyColumnFilter(col.name, e.target.value);
|
|
4848
5696
|
},
|
|
4849
5697
|
onKeyDown: (e) => {
|
|
4850
5698
|
if (e.key === "Escape" || e.key === "Enter") {
|
|
@@ -4854,7 +5702,7 @@ function TableBlockClient({
|
|
|
4854
5702
|
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
5703
|
}
|
|
4856
5704
|
) }),
|
|
4857
|
-
/* @__PURE__ */
|
|
5705
|
+
/* @__PURE__ */ jsx11(
|
|
4858
5706
|
"button",
|
|
4859
5707
|
{
|
|
4860
5708
|
type: "button",
|
|
@@ -4864,59 +5712,62 @@ function TableBlockClient({
|
|
|
4864
5712
|
},
|
|
4865
5713
|
onClick: (e) => {
|
|
4866
5714
|
e.stopPropagation();
|
|
4867
|
-
|
|
4868
|
-
const next = __spreadValues({}, prev);
|
|
4869
|
-
delete next[col.name];
|
|
4870
|
-
return next;
|
|
4871
|
-
});
|
|
5715
|
+
handleApplyColumnFilter(col.name, void 0);
|
|
4872
5716
|
setActiveSearchCol(null);
|
|
4873
5717
|
},
|
|
4874
5718
|
className: "p-1 text-slate-400 hover:text-slate-700 hover:bg-slate-200/70 rounded transition-colors cursor-pointer shrink-0",
|
|
4875
5719
|
title: "\u05E0\u05E7\u05D4 \u05D5\u05E1\u05D2\u05D5\u05E8 \u05D7\u05D9\u05E4\u05D5\u05E9",
|
|
4876
|
-
children: /* @__PURE__ */
|
|
5720
|
+
children: /* @__PURE__ */ jsx11(X8, { className: "w-3.5 h-3.5" })
|
|
4877
5721
|
}
|
|
4878
5722
|
)
|
|
4879
5723
|
]
|
|
4880
5724
|
}
|
|
4881
|
-
) : /* @__PURE__ */
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
5725
|
+
) : /* @__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: [
|
|
5726
|
+
((_b = col.type) == null ? void 0 : _b.toUpperCase()) !== "SUB_TABLE" && /* @__PURE__ */ jsx11(
|
|
5727
|
+
"button",
|
|
5728
|
+
{
|
|
5729
|
+
ref: (el) => {
|
|
5730
|
+
filterButtonRefs.current[col.name] = el;
|
|
5731
|
+
},
|
|
5732
|
+
type: "button",
|
|
5733
|
+
onClick: (e) => {
|
|
5734
|
+
e.stopPropagation();
|
|
5735
|
+
e.preventDefault();
|
|
5736
|
+
if (isRelation) {
|
|
5737
|
+
if (activeRelationCol === col.name) {
|
|
5738
|
+
setActiveRelationCol(null);
|
|
5739
|
+
setRelationTriggerRect(null);
|
|
5740
|
+
} else {
|
|
5741
|
+
const btn = filterButtonRefs.current[col.name];
|
|
5742
|
+
if (btn) {
|
|
5743
|
+
setRelationTriggerRect(btn.getBoundingClientRect());
|
|
5744
|
+
}
|
|
5745
|
+
setActiveRelationCol(col.name);
|
|
5746
|
+
if (!relationOptions[col.name] || relationOptions[col.name].length < 100) {
|
|
5747
|
+
refetchRelation(col.name, { take: 1e3 });
|
|
5748
|
+
}
|
|
5749
|
+
}
|
|
5750
|
+
} else {
|
|
4891
5751
|
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
|
-
] })
|
|
5752
|
+
}
|
|
5753
|
+
},
|
|
5754
|
+
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"}`,
|
|
5755
|
+
title: filterTooltip,
|
|
5756
|
+
children: /* @__PURE__ */ jsx11(Filter, { className: "w-3 h-3" })
|
|
5757
|
+
}
|
|
5758
|
+
),
|
|
5759
|
+
/* @__PURE__ */ jsx11(ColumnHeaderTitle, { name: col.name, width: currentWidth, isSubTable: false })
|
|
4909
5760
|
] })
|
|
4910
5761
|
]
|
|
4911
5762
|
}),
|
|
4912
5763
|
col.name
|
|
4913
5764
|
);
|
|
4914
5765
|
}),
|
|
4915
|
-
/* @__PURE__ */
|
|
5766
|
+
/* @__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
5767
|
] }) }),
|
|
4917
|
-
/* @__PURE__ */
|
|
4918
|
-
/* @__PURE__ */
|
|
4919
|
-
/* @__PURE__ */
|
|
5768
|
+
/* @__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: [
|
|
5769
|
+
/* @__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" }) }),
|
|
5770
|
+
/* @__PURE__ */ jsx11("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
4920
5771
|
] }) }) }) : filteredData.map((row) => {
|
|
4921
5772
|
const hasSubTableCols = filteredColumns.some((c) => {
|
|
4922
5773
|
var _a;
|
|
@@ -4927,10 +5778,10 @@ function TableBlockClient({
|
|
|
4927
5778
|
var _a;
|
|
4928
5779
|
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
4929
5780
|
});
|
|
4930
|
-
return /* @__PURE__ */
|
|
4931
|
-
/* @__PURE__ */
|
|
4932
|
-
/* @__PURE__ */
|
|
4933
|
-
/* @__PURE__ */
|
|
5781
|
+
return /* @__PURE__ */ jsxs11(React11.Fragment, { children: [
|
|
5782
|
+
/* @__PURE__ */ jsxs11("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
|
|
5783
|
+
/* @__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: [
|
|
5784
|
+
/* @__PURE__ */ jsx11(
|
|
4934
5785
|
"input",
|
|
4935
5786
|
{
|
|
4936
5787
|
type: "checkbox",
|
|
@@ -4940,7 +5791,7 @@ function TableBlockClient({
|
|
|
4940
5791
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
4941
5792
|
}
|
|
4942
5793
|
),
|
|
4943
|
-
hasSubTableCols && /* @__PURE__ */
|
|
5794
|
+
hasSubTableCols && /* @__PURE__ */ jsx11(
|
|
4944
5795
|
"button",
|
|
4945
5796
|
{
|
|
4946
5797
|
type: "button",
|
|
@@ -4952,7 +5803,7 @@ function TableBlockClient({
|
|
|
4952
5803
|
}),
|
|
4953
5804
|
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",
|
|
4954
5805
|
title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
|
|
4955
|
-
children: /* @__PURE__ */
|
|
5806
|
+
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" }) })
|
|
4956
5807
|
}
|
|
4957
5808
|
)
|
|
4958
5809
|
] }) }),
|
|
@@ -4970,12 +5821,12 @@ function TableBlockClient({
|
|
|
4970
5821
|
}
|
|
4971
5822
|
}
|
|
4972
5823
|
if (value === void 0) value = null;
|
|
4973
|
-
return /* @__PURE__ */
|
|
5824
|
+
return /* @__PURE__ */ jsx11(
|
|
4974
5825
|
"td",
|
|
4975
5826
|
{
|
|
4976
5827
|
className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
|
|
4977
5828
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
4978
|
-
children: /* @__PURE__ */
|
|
5829
|
+
children: /* @__PURE__ */ jsx11(
|
|
4979
5830
|
InputComponent,
|
|
4980
5831
|
{
|
|
4981
5832
|
value,
|
|
@@ -4987,6 +5838,7 @@ function TableBlockClient({
|
|
|
4987
5838
|
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
4988
5839
|
onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
|
|
4989
5840
|
relationOptions,
|
|
5841
|
+
relationDictionaryRef,
|
|
4990
5842
|
refetchRelation,
|
|
4991
5843
|
executeAction,
|
|
4992
5844
|
emitEvent,
|
|
@@ -5003,9 +5855,9 @@ function TableBlockClient({
|
|
|
5003
5855
|
col.name
|
|
5004
5856
|
);
|
|
5005
5857
|
}),
|
|
5006
|
-
/* @__PURE__ */
|
|
5858
|
+
/* @__PURE__ */ jsx11("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
5007
5859
|
] }),
|
|
5008
|
-
isExpanded && /* @__PURE__ */
|
|
5860
|
+
isExpanded && /* @__PURE__ */ jsx11(
|
|
5009
5861
|
ExpandedSubTables,
|
|
5010
5862
|
{
|
|
5011
5863
|
rowId: row.id,
|
|
@@ -5027,8 +5879,8 @@ function TableBlockClient({
|
|
|
5027
5879
|
)
|
|
5028
5880
|
] }, row.id);
|
|
5029
5881
|
}) }),
|
|
5030
|
-
showSummary && filteredData.length > 0 && /* @__PURE__ */
|
|
5031
|
-
/* @__PURE__ */
|
|
5882
|
+
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: [
|
|
5883
|
+
/* @__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
5884
|
filteredColumns.map((col) => {
|
|
5033
5885
|
var _a, _b;
|
|
5034
5886
|
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
@@ -5042,16 +5894,16 @@ function TableBlockClient({
|
|
|
5042
5894
|
displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
|
|
5043
5895
|
}
|
|
5044
5896
|
}
|
|
5045
|
-
return /* @__PURE__ */
|
|
5897
|
+
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
5898
|
}),
|
|
5047
|
-
/* @__PURE__ */
|
|
5899
|
+
/* @__PURE__ */ jsx11("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
|
|
5048
5900
|
] }) })
|
|
5049
5901
|
] })
|
|
5050
5902
|
] }),
|
|
5051
|
-
/* @__PURE__ */
|
|
5052
|
-
/* @__PURE__ */
|
|
5053
|
-
/* @__PURE__ */
|
|
5054
|
-
/* @__PURE__ */
|
|
5903
|
+
/* @__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: [
|
|
5904
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
5905
|
+
/* @__PURE__ */ jsx11("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
|
|
5906
|
+
/* @__PURE__ */ jsxs11(
|
|
5055
5907
|
"select",
|
|
5056
5908
|
{
|
|
5057
5909
|
value: limit,
|
|
@@ -5059,27 +5911,27 @@ function TableBlockClient({
|
|
|
5059
5911
|
disabled: isLoading || isUpdatingActive,
|
|
5060
5912
|
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
5913
|
children: [
|
|
5062
|
-
/* @__PURE__ */
|
|
5063
|
-
/* @__PURE__ */
|
|
5064
|
-
/* @__PURE__ */
|
|
5914
|
+
/* @__PURE__ */ jsx11("option", { value: 20, children: "20" }),
|
|
5915
|
+
/* @__PURE__ */ jsx11("option", { value: 50, children: "50" }),
|
|
5916
|
+
/* @__PURE__ */ jsx11("option", { value: 100, children: "100" })
|
|
5065
5917
|
]
|
|
5066
5918
|
}
|
|
5067
5919
|
)
|
|
5068
5920
|
] }),
|
|
5069
|
-
/* @__PURE__ */
|
|
5070
|
-
/* @__PURE__ */
|
|
5921
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-4", children: [
|
|
5922
|
+
/* @__PURE__ */ jsxs11("span", { className: "font-medium text-slate-600", children: [
|
|
5071
5923
|
"\u05E2\u05DE\u05D5\u05D3 ",
|
|
5072
|
-
/* @__PURE__ */
|
|
5924
|
+
/* @__PURE__ */ jsx11("strong", { className: "text-slate-900", children: page }),
|
|
5073
5925
|
" \u05DE\u05EA\u05D5\u05DA ",
|
|
5074
|
-
/* @__PURE__ */
|
|
5075
|
-
totalRecords > 0 && /* @__PURE__ */
|
|
5926
|
+
/* @__PURE__ */ jsx11("strong", { className: "text-slate-900", children: totalPages || 1 }),
|
|
5927
|
+
totalRecords > 0 && /* @__PURE__ */ jsxs11("span", { className: "text-slate-500 font-normal", children: [
|
|
5076
5928
|
" (",
|
|
5077
5929
|
totalRecords,
|
|
5078
5930
|
' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
|
|
5079
5931
|
] })
|
|
5080
5932
|
] }),
|
|
5081
|
-
/* @__PURE__ */
|
|
5082
|
-
/* @__PURE__ */
|
|
5933
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5", children: [
|
|
5934
|
+
/* @__PURE__ */ jsx11(
|
|
5083
5935
|
"button",
|
|
5084
5936
|
{
|
|
5085
5937
|
onClick: handlePrevPage,
|
|
@@ -5089,7 +5941,7 @@ function TableBlockClient({
|
|
|
5089
5941
|
children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
|
|
5090
5942
|
}
|
|
5091
5943
|
),
|
|
5092
|
-
/* @__PURE__ */
|
|
5944
|
+
/* @__PURE__ */ jsx11(
|
|
5093
5945
|
"button",
|
|
5094
5946
|
{
|
|
5095
5947
|
onClick: handleNextPage,
|
|
@@ -5101,7 +5953,30 @@ function TableBlockClient({
|
|
|
5101
5953
|
)
|
|
5102
5954
|
] })
|
|
5103
5955
|
] })
|
|
5104
|
-
] })
|
|
5956
|
+
] }),
|
|
5957
|
+
activeRelationCol && (() => {
|
|
5958
|
+
const activeColDef = filteredColumns.find((c) => c.name === activeRelationCol);
|
|
5959
|
+
if (!activeColDef) return null;
|
|
5960
|
+
const rawSelected = columnFilters[activeRelationCol];
|
|
5961
|
+
const currentSelected = typeof rawSelected === "object" && rawSelected !== null ? rawSelected : void 0;
|
|
5962
|
+
return /* @__PURE__ */ jsx11(
|
|
5963
|
+
RelationFilterPopover,
|
|
5964
|
+
{
|
|
5965
|
+
isOpen: Boolean(activeRelationCol),
|
|
5966
|
+
onClose: () => {
|
|
5967
|
+
setActiveRelationCol(null);
|
|
5968
|
+
setRelationTriggerRect(null);
|
|
5969
|
+
},
|
|
5970
|
+
column: activeColDef,
|
|
5971
|
+
triggerRect: relationTriggerRect,
|
|
5972
|
+
options: getUniqueRelationOptions(activeColDef),
|
|
5973
|
+
filterValue: currentSelected,
|
|
5974
|
+
onSelectionChange: (newSelected) => {
|
|
5975
|
+
handleApplyColumnFilter(activeRelationCol, newSelected);
|
|
5976
|
+
}
|
|
5977
|
+
}
|
|
5978
|
+
);
|
|
5979
|
+
})()
|
|
5105
5980
|
]
|
|
5106
5981
|
}
|
|
5107
5982
|
);
|
|
@@ -5115,11 +5990,11 @@ function ExpandedSubTables({
|
|
|
5115
5990
|
context
|
|
5116
5991
|
}) {
|
|
5117
5992
|
var _a;
|
|
5118
|
-
const [activeTab, setActiveTab] =
|
|
5993
|
+
const [activeTab, setActiveTab] = useState12((_a = subTableColumns[0]) == null ? void 0 : _a.name);
|
|
5119
5994
|
if (subTableColumns.length === 0) return null;
|
|
5120
5995
|
if (subTableColumns.length === 1) {
|
|
5121
5996
|
const stCol = subTableColumns[0];
|
|
5122
|
-
return /* @__PURE__ */
|
|
5997
|
+
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
5998
|
SubTableViewer,
|
|
5124
5999
|
{
|
|
5125
6000
|
rowId,
|
|
@@ -5131,8 +6006,8 @@ function ExpandedSubTables({
|
|
|
5131
6006
|
) }) });
|
|
5132
6007
|
}
|
|
5133
6008
|
const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
|
|
5134
|
-
return /* @__PURE__ */
|
|
5135
|
-
/* @__PURE__ */
|
|
6009
|
+
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: [
|
|
6010
|
+
/* @__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
6011
|
"button",
|
|
5137
6012
|
{
|
|
5138
6013
|
type: "button",
|
|
@@ -5142,7 +6017,7 @@ function ExpandedSubTables({
|
|
|
5142
6017
|
},
|
|
5143
6018
|
col.name
|
|
5144
6019
|
)) }),
|
|
5145
|
-
/* @__PURE__ */
|
|
6020
|
+
/* @__PURE__ */ jsx11("div", { className: "bg-white", children: /* @__PURE__ */ jsx11(
|
|
5146
6021
|
SubTableViewer,
|
|
5147
6022
|
{
|
|
5148
6023
|
rowId,
|
|
@@ -5157,9 +6032,9 @@ function ExpandedSubTables({
|
|
|
5157
6032
|
}
|
|
5158
6033
|
|
|
5159
6034
|
// src/components/TableBlock/TableBlock.tsx
|
|
5160
|
-
import { jsx as
|
|
6035
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
5161
6036
|
function TableBlock(props) {
|
|
5162
|
-
return /* @__PURE__ */
|
|
6037
|
+
return /* @__PURE__ */ jsx12(TableBlockClient, __spreadValues({}, props));
|
|
5163
6038
|
}
|
|
5164
6039
|
|
|
5165
6040
|
// src/registry.ts
|
|
@@ -5175,6 +6050,7 @@ export {
|
|
|
5175
6050
|
DatePickerCell,
|
|
5176
6051
|
LinkPickerCell,
|
|
5177
6052
|
PASTEL_PALETTES,
|
|
6053
|
+
RelationFilterPopover,
|
|
5178
6054
|
RelationPickerCell,
|
|
5179
6055
|
TEXT_REPRESENTABLE_TYPES,
|
|
5180
6056
|
TableBlock,
|