@universe-platform/ui 0.1.0-beta.7 → 0.1.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/globals.css +524 -18
- package/dist/index.d.mts +167 -45
- package/dist/index.d.ts +167 -45
- package/dist/index.js +2988 -715
- package/dist/index.mjs +3005 -706
- package/dist/phone.d.mts +38 -0
- package/dist/phone.d.ts +38 -0
- package/dist/phone.js +90 -0
- package/dist/phone.mjs +59 -0
- package/package.json +7 -1
package/dist/index.js
CHANGED
|
@@ -47,6 +47,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
47
47
|
}
|
|
48
48
|
return to;
|
|
49
49
|
};
|
|
50
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
50
51
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
51
52
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
52
53
|
// file that has been converted to a CommonJS file using a Babel-
|
|
@@ -58,16 +59,37 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
58
59
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
59
60
|
|
|
60
61
|
// src/index.ts
|
|
61
|
-
var
|
|
62
|
-
__export(
|
|
62
|
+
var src_exports = {};
|
|
63
|
+
__export(src_exports, {
|
|
64
|
+
ColumnHeaderTitle: () => ColumnHeaderTitle,
|
|
65
|
+
DatePickerCell: () => DatePickerCell,
|
|
66
|
+
LinkPickerCell: () => LinkPickerCell,
|
|
67
|
+
PASTEL_PALETTES: () => PASTEL_PALETTES,
|
|
68
|
+
RelationPickerCell: () => RelationPickerCell,
|
|
63
69
|
TableBlock: () => TableBlock,
|
|
70
|
+
TimePickerCell: () => TimePickerCell,
|
|
64
71
|
ToastContext: () => ToastContext,
|
|
65
72
|
ToastProvider: () => ToastProvider,
|
|
66
73
|
UNIVERSE_COMPONENTS: () => UNIVERSE_COMPONENTS,
|
|
74
|
+
calculateMinColumnWidth: () => calculateMinColumnWidth,
|
|
67
75
|
cn: () => cn,
|
|
76
|
+
formatConflictCellValue: () => formatConflictCellValue,
|
|
77
|
+
formatPhoneDisplay: () => formatPhoneDisplay,
|
|
78
|
+
formatTimeInput: () => formatTimeInput,
|
|
79
|
+
formatTimeIso: () => formatTimeIso,
|
|
80
|
+
getDeterministicPastelBadge: () => getDeterministicPastelBadge,
|
|
81
|
+
measureTextWidth: () => measureTextWidth,
|
|
82
|
+
normalizeRelationValue: () => normalizeRelationValue,
|
|
83
|
+
openWhatsAppChat: () => openWhatsAppChat,
|
|
84
|
+
parseLinkValue: () => parseLinkValue,
|
|
85
|
+
parseTimeParts: () => parseTimeParts,
|
|
86
|
+
resolveProtocol: () => resolveProtocol,
|
|
87
|
+
splitHeaderTitle: () => splitHeaderTitle,
|
|
88
|
+
useColumnReorder: () => useColumnReorder,
|
|
89
|
+
useColumnResize: () => useColumnResize,
|
|
68
90
|
useToast: () => useToast
|
|
69
91
|
});
|
|
70
|
-
module.exports = __toCommonJS(
|
|
92
|
+
module.exports = __toCommonJS(src_exports);
|
|
71
93
|
|
|
72
94
|
// src/utils/cn.ts
|
|
73
95
|
var import_clsx = require("clsx");
|
|
@@ -76,8 +98,76 @@ function cn(...inputs) {
|
|
|
76
98
|
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
77
99
|
}
|
|
78
100
|
|
|
101
|
+
// src/utils/whatsapp.ts
|
|
102
|
+
function openWhatsAppChat(phone, defaultCountryCode = "972") {
|
|
103
|
+
if (!phone || typeof window === "undefined") return;
|
|
104
|
+
let cleaned = phone.replace(/\D/g, "");
|
|
105
|
+
if (cleaned.startsWith("0")) {
|
|
106
|
+
cleaned = defaultCountryCode + cleaned.substring(1);
|
|
107
|
+
}
|
|
108
|
+
const appUrl = `whatsapp://send?phone=${cleaned}`;
|
|
109
|
+
const webUrl = `https://web.whatsapp.com/send?phone=${cleaned}`;
|
|
110
|
+
const start = Date.now();
|
|
111
|
+
window.location.href = appUrl;
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
if (typeof document !== "undefined" && document.hasFocus() && Date.now() - start < 2e3) {
|
|
114
|
+
window.open(webUrl, "_blank", "noopener,noreferrer");
|
|
115
|
+
}
|
|
116
|
+
}, 1200);
|
|
117
|
+
}
|
|
118
|
+
function formatPhoneDisplay(phone) {
|
|
119
|
+
if (!phone) return "";
|
|
120
|
+
const digits = phone.replace(/\D/g, "");
|
|
121
|
+
if (digits.length === 10 && digits.startsWith("05")) {
|
|
122
|
+
return `${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
|
|
123
|
+
}
|
|
124
|
+
if (digits.length === 12 && digits.startsWith("9725")) {
|
|
125
|
+
const local = "0" + digits.slice(3);
|
|
126
|
+
return `${local.slice(0, 3)}-${local.slice(3, 6)}-${local.slice(6)}`;
|
|
127
|
+
}
|
|
128
|
+
return phone;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/utils/colors.ts
|
|
132
|
+
var PASTEL_PALETTES = [
|
|
133
|
+
{ bg: "bg-blue-50", text: "text-blue-700", border: "border-blue-200" },
|
|
134
|
+
{ bg: "bg-emerald-50", text: "text-emerald-700", border: "border-emerald-200" },
|
|
135
|
+
{ bg: "bg-violet-50", text: "text-violet-700", border: "border-violet-200" },
|
|
136
|
+
{ bg: "bg-amber-50", text: "text-amber-700", border: "border-amber-200" },
|
|
137
|
+
{ bg: "bg-rose-50", text: "text-rose-700", border: "border-rose-200" },
|
|
138
|
+
{ bg: "bg-cyan-50", text: "text-cyan-700", border: "border-cyan-200" },
|
|
139
|
+
{ bg: "bg-indigo-50", text: "text-indigo-700", border: "border-indigo-200" },
|
|
140
|
+
{ bg: "bg-teal-50", text: "text-teal-700", border: "border-teal-200" },
|
|
141
|
+
{ bg: "bg-sky-50", text: "text-sky-700", border: "border-sky-200" },
|
|
142
|
+
{ bg: "bg-fuchsia-50", text: "text-fuchsia-700", border: "border-fuchsia-200" },
|
|
143
|
+
{ bg: "bg-pink-50", text: "text-pink-700", border: "border-pink-200" },
|
|
144
|
+
{ bg: "bg-purple-50", text: "text-purple-700", border: "border-purple-200" },
|
|
145
|
+
{ bg: "bg-orange-50", text: "text-orange-700", border: "border-orange-200" },
|
|
146
|
+
{ bg: "bg-red-50", text: "text-red-700", border: "border-red-200" },
|
|
147
|
+
{ bg: "bg-lime-50", text: "text-lime-700", border: "border-lime-200" },
|
|
148
|
+
{ bg: "bg-green-50", text: "text-green-700", border: "border-green-200" },
|
|
149
|
+
{ bg: "bg-yellow-50", text: "text-yellow-700", border: "border-yellow-200" }
|
|
150
|
+
];
|
|
151
|
+
function getDeterministicPastelBadge(key) {
|
|
152
|
+
if (!key) return PASTEL_PALETTES[0];
|
|
153
|
+
let hash = 2166136261;
|
|
154
|
+
for (let i = 0; i < key.length; i++) {
|
|
155
|
+
hash ^= key.charCodeAt(i);
|
|
156
|
+
hash = Math.imul(hash, 16777619);
|
|
157
|
+
}
|
|
158
|
+
const index = Math.abs(hash) % PASTEL_PALETTES.length;
|
|
159
|
+
return PASTEL_PALETTES[index];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/types/data.types.ts
|
|
163
|
+
var data_types_exports = {};
|
|
164
|
+
__reExport(data_types_exports, require("@universe-platform/shared"));
|
|
165
|
+
|
|
166
|
+
// src/index.ts
|
|
167
|
+
__reExport(src_exports, data_types_exports, module.exports);
|
|
168
|
+
|
|
79
169
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
80
|
-
var
|
|
170
|
+
var import_react12 = __toESM(require("react"));
|
|
81
171
|
|
|
82
172
|
// src/hooks/useToast.ts
|
|
83
173
|
var import_react2 = require("react");
|
|
@@ -277,7 +367,7 @@ function useToast() {
|
|
|
277
367
|
}
|
|
278
368
|
|
|
279
369
|
// src/components/TableBlock/fields/fieldRegistry.tsx
|
|
280
|
-
var
|
|
370
|
+
var import_react8 = __toESM(require("react"));
|
|
281
371
|
|
|
282
372
|
// src/components/TableBlock/fields/DrivePickerCell.tsx
|
|
283
373
|
var import_react3 = __toESM(require("react"));
|
|
@@ -734,214 +824,1086 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
|
|
|
734
824
|
] });
|
|
735
825
|
}
|
|
736
826
|
|
|
737
|
-
// src/components/TableBlock/fields/
|
|
827
|
+
// src/components/TableBlock/fields/TimePickerCell.tsx
|
|
828
|
+
var import_react5 = require("react");
|
|
829
|
+
var import_lucide_react4 = require("lucide-react");
|
|
738
830
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
};
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
831
|
+
function parseTimeParts(val) {
|
|
832
|
+
if (val === void 0 || val === null || val === "") return null;
|
|
833
|
+
if (typeof val === "string") {
|
|
834
|
+
const trimmed = val.trim();
|
|
835
|
+
if (!trimmed) return null;
|
|
836
|
+
const match = trimmed.match(/^(\d{1,2})[:.](\d{1,2})(?:[:.]\d{1,2})?$/);
|
|
837
|
+
if (match) {
|
|
838
|
+
const hour = parseInt(match[1], 10);
|
|
839
|
+
const minute = parseInt(match[2], 10);
|
|
840
|
+
if (hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59) {
|
|
841
|
+
return { hour, minute };
|
|
842
|
+
}
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
if (trimmed.includes("T")) {
|
|
846
|
+
const d = new Date(trimmed);
|
|
847
|
+
if (!isNaN(d.getTime())) {
|
|
848
|
+
return { hour: d.getHours(), minute: d.getMinutes() };
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
} else if (val instanceof Date && !isNaN(val.getTime())) {
|
|
852
|
+
return { hour: val.getHours(), minute: val.getMinutes() };
|
|
754
853
|
}
|
|
755
|
-
|
|
756
|
-
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
function formatTimeIso(hour, minute) {
|
|
857
|
+
const hh = String(hour).padStart(2, "0");
|
|
858
|
+
const mm = String(minute).padStart(2, "0");
|
|
859
|
+
return `${hh}:${mm}`;
|
|
860
|
+
}
|
|
861
|
+
function formatTimeInput(input) {
|
|
862
|
+
if (!input) return "";
|
|
863
|
+
const digits = String(input).replace(/\D/g, "");
|
|
864
|
+
if (!digits) return "";
|
|
865
|
+
if (digits.length === 1) {
|
|
866
|
+
const d = parseInt(digits, 10);
|
|
867
|
+
if (d > 2) {
|
|
868
|
+
return `0${d}:`;
|
|
869
|
+
}
|
|
870
|
+
return `${digits}:`;
|
|
757
871
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
if (typeof v === "string" && v.trim() !== "") return true;
|
|
763
|
-
if (typeof v === "number" && !isNaN(v)) return true;
|
|
764
|
-
return false;
|
|
765
|
-
});
|
|
766
|
-
if (fallbackField) return String(opt.data[fallbackField]);
|
|
872
|
+
const h = parseInt(digits.slice(0, 2), 10);
|
|
873
|
+
const hh = h > 23 ? "23" : digits.slice(0, 2);
|
|
874
|
+
if (digits.length === 2) {
|
|
875
|
+
return `${hh}:`;
|
|
767
876
|
}
|
|
768
|
-
if (
|
|
769
|
-
return
|
|
877
|
+
if (digits.length === 3) {
|
|
878
|
+
return `${hh}:${digits[2]}`;
|
|
770
879
|
}
|
|
771
|
-
|
|
880
|
+
const m = parseInt(digits.slice(2, 4), 10);
|
|
881
|
+
const mm = m > 59 ? "59" : digits.slice(2, 4);
|
|
882
|
+
return `${hh}:${mm}`;
|
|
772
883
|
}
|
|
773
|
-
var
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
884
|
+
var ALL_MINUTES = Array.from({ length: 60 }, (_, i) => i);
|
|
885
|
+
function TimePickerCell({ value, onChange, readOnly = false }) {
|
|
886
|
+
var _a, _b;
|
|
887
|
+
const [isOpen, setIsOpen] = (0, import_react5.useState)(false);
|
|
888
|
+
const containerRef = (0, import_react5.useRef)(null);
|
|
889
|
+
const hoursListRef = (0, import_react5.useRef)(null);
|
|
890
|
+
const minutesListRef = (0, import_react5.useRef)(null);
|
|
891
|
+
const [popoverPos, setPopoverPos] = (0, import_react5.useState)({ top: 0, right: 0 });
|
|
892
|
+
const parsedParts = (0, import_react5.useMemo)(() => parseTimeParts(value), [value]);
|
|
893
|
+
const displayString = (0, import_react5.useMemo)(() => {
|
|
894
|
+
return parsedParts ? formatTimeIso(parsedParts.hour, parsedParts.minute) : "";
|
|
895
|
+
}, [parsedParts]);
|
|
896
|
+
const [rawInput, setRawInput] = (0, import_react5.useState)(displayString);
|
|
897
|
+
(0, import_react5.useEffect)(() => {
|
|
898
|
+
setRawInput(displayString);
|
|
899
|
+
}, [displayString]);
|
|
900
|
+
const selectedHour = (_a = parsedParts == null ? void 0 : parsedParts.hour) != null ? _a : null;
|
|
901
|
+
const selectedMinute = (_b = parsedParts == null ? void 0 : parsedParts.minute) != null ? _b : null;
|
|
902
|
+
const updatePopoverPosition = (0, import_react5.useCallback)(() => {
|
|
903
|
+
if (containerRef.current) {
|
|
904
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
905
|
+
const right = window.innerWidth - rect.right;
|
|
906
|
+
const popoverHeight = 260;
|
|
907
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
908
|
+
if (spaceBelow < popoverHeight && rect.top > popoverHeight) {
|
|
909
|
+
setPopoverPos({
|
|
910
|
+
top: Math.max(10, rect.top - popoverHeight - 4),
|
|
911
|
+
right: Math.max(10, right)
|
|
912
|
+
});
|
|
913
|
+
} else {
|
|
914
|
+
setPopoverPos({
|
|
915
|
+
top: Math.min(window.innerHeight - popoverHeight - 10, rect.bottom + 4),
|
|
916
|
+
right: Math.max(10, right)
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
}, []);
|
|
921
|
+
(0, import_react5.useEffect)(() => {
|
|
922
|
+
if (!isOpen) return;
|
|
923
|
+
updatePopoverPosition();
|
|
924
|
+
function handleScrollOrResize() {
|
|
925
|
+
updatePopoverPosition();
|
|
926
|
+
}
|
|
927
|
+
function handleClickOutside(event) {
|
|
928
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
929
|
+
const popoverEl = document.getElementById("time-picker-popover");
|
|
930
|
+
if (popoverEl && popoverEl.contains(event.target)) {
|
|
931
|
+
return;
|
|
794
932
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
},
|
|
798
|
-
TIME: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
799
|
-
"input",
|
|
800
|
-
{
|
|
801
|
-
type: "time",
|
|
802
|
-
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
803
|
-
value: value || "",
|
|
804
|
-
onChange: (e) => onChange(e.target.value)
|
|
933
|
+
setIsOpen(false);
|
|
934
|
+
}
|
|
805
935
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
936
|
+
window.addEventListener("scroll", handleScrollOrResize, true);
|
|
937
|
+
window.addEventListener("resize", handleScrollOrResize);
|
|
938
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
939
|
+
return () => {
|
|
940
|
+
window.removeEventListener("scroll", handleScrollOrResize, true);
|
|
941
|
+
window.removeEventListener("resize", handleScrollOrResize);
|
|
942
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
943
|
+
};
|
|
944
|
+
}, [isOpen, updatePopoverPosition]);
|
|
945
|
+
(0, import_react5.useEffect)(() => {
|
|
946
|
+
if (isOpen) {
|
|
947
|
+
if (selectedHour !== null && hoursListRef.current) {
|
|
948
|
+
const activeHourBtn = hoursListRef.current.querySelector('[data-selected="true"]');
|
|
949
|
+
if (activeHourBtn) {
|
|
950
|
+
activeHourBtn.scrollIntoView({ block: "center" });
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if (selectedMinute !== null && minutesListRef.current) {
|
|
954
|
+
const activeMinBtn = minutesListRef.current.querySelector('[data-selected="true"]');
|
|
955
|
+
if (activeMinBtn) {
|
|
956
|
+
activeMinBtn.scrollIntoView({ block: "center" });
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}, [isOpen, selectedHour, selectedMinute]);
|
|
961
|
+
const handleInputChange = (e) => {
|
|
962
|
+
let val = e.target.value;
|
|
963
|
+
if (val.length === 2 && !val.includes(":") && rawInput.length === 1) {
|
|
964
|
+
val += ":";
|
|
965
|
+
}
|
|
966
|
+
if (val.length > 5) return;
|
|
967
|
+
setRawInput(val);
|
|
968
|
+
if (val.length === 5 && /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/.test(val)) {
|
|
969
|
+
onChange(val);
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
const handleKeyDown = (e) => {
|
|
973
|
+
if (e.key === "Enter") {
|
|
974
|
+
handleInputBlur();
|
|
975
|
+
setIsOpen(false);
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
if (e.key === "Backspace" || e.key === "Delete" || e.key === "ArrowLeft" || e.key === "ArrowRight" || e.key === "Tab" || e.key === "Escape" || (e.ctrlKey || e.metaKey)) {
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
if (e.key === ":") return;
|
|
982
|
+
if (!/^\d$/.test(e.key)) {
|
|
983
|
+
e.preventDefault();
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
const handleInputBlur = () => {
|
|
987
|
+
let text = rawInput.trim();
|
|
988
|
+
if (!text) {
|
|
989
|
+
onChange(null);
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
if (!text.includes(":")) {
|
|
993
|
+
if (text.length === 1 || text.length === 2) {
|
|
994
|
+
text = `${text}:00`;
|
|
995
|
+
} else if (text.length === 3) {
|
|
996
|
+
text = `0${text[0]}:${text.slice(1)}`;
|
|
997
|
+
} else if (text.length === 4) {
|
|
998
|
+
text = `${text.slice(0, 2)}:${text.slice(2)}`;
|
|
999
|
+
}
|
|
1000
|
+
} else if (text.endsWith(":")) {
|
|
1001
|
+
text = `${text}00`;
|
|
824
1002
|
}
|
|
825
|
-
|
|
1003
|
+
const parts = parseTimeParts(text);
|
|
1004
|
+
if (parts) {
|
|
1005
|
+
const iso = formatTimeIso(parts.hour, parts.minute);
|
|
1006
|
+
setRawInput(iso);
|
|
1007
|
+
onChange(iso);
|
|
1008
|
+
} else {
|
|
1009
|
+
setRawInput(displayString);
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
const handleSelectHour = (h) => {
|
|
1013
|
+
const m = selectedMinute != null ? selectedMinute : 0;
|
|
1014
|
+
const iso = formatTimeIso(h, m);
|
|
1015
|
+
onChange(iso);
|
|
1016
|
+
setRawInput(iso);
|
|
1017
|
+
};
|
|
1018
|
+
const handleSelectMinute = (m) => {
|
|
1019
|
+
const h = selectedHour != null ? selectedHour : (/* @__PURE__ */ new Date()).getHours();
|
|
1020
|
+
const iso = formatTimeIso(h, m);
|
|
1021
|
+
onChange(iso);
|
|
1022
|
+
setRawInput(iso);
|
|
1023
|
+
};
|
|
1024
|
+
const handleSetNow = () => {
|
|
1025
|
+
const now = /* @__PURE__ */ new Date();
|
|
1026
|
+
const iso = formatTimeIso(now.getHours(), now.getMinutes());
|
|
1027
|
+
onChange(iso);
|
|
1028
|
+
setRawInput(iso);
|
|
1029
|
+
};
|
|
1030
|
+
const handleClear = () => {
|
|
1031
|
+
onChange(null);
|
|
1032
|
+
setRawInput("");
|
|
1033
|
+
setIsOpen(false);
|
|
1034
|
+
};
|
|
1035
|
+
if (readOnly) {
|
|
1036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5 px-2 h-full", children: [
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react4.Clock, { className: "w-3.5 h-3.5 text-slate-400 shrink-0" }),
|
|
1038
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-sm font-normal text-slate-800 tracking-wider", dir: "ltr", children: displayString || "-" })
|
|
1039
|
+
] });
|
|
1040
|
+
}
|
|
1041
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { ref: containerRef, className: "relative w-full h-full flex items-center px-2", children: [
|
|
1042
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
826
1043
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
827
|
-
"
|
|
1044
|
+
"button",
|
|
828
1045
|
{
|
|
829
|
-
type: "
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
1046
|
+
type: "button",
|
|
1047
|
+
onClick: () => {
|
|
1048
|
+
setIsOpen((prev) => {
|
|
1049
|
+
const next = !prev;
|
|
1050
|
+
if (next) updatePopoverPosition();
|
|
1051
|
+
return next;
|
|
1052
|
+
});
|
|
1053
|
+
},
|
|
1054
|
+
className: "p-1 text-slate-400 hover:text-blue-600 rounded transition-colors cursor-pointer shrink-0",
|
|
1055
|
+
title: "\u05D1\u05D7\u05E8 \u05E9\u05E2\u05D4",
|
|
1056
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react4.Clock, { className: "w-4 h-4" })
|
|
834
1057
|
}
|
|
835
1058
|
),
|
|
836
1059
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
837
1060
|
"input",
|
|
838
1061
|
{
|
|
839
|
-
type: "
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
"button",
|
|
848
|
-
{
|
|
849
|
-
onClick: () => setIsEditing(false),
|
|
850
|
-
className: "text-xs font-medium text-green-600 hover:text-green-700 p-1 mx-1 rounded transition-colors",
|
|
851
|
-
title: "\u05E9\u05DE\u05D5\u05E8",
|
|
852
|
-
children: "\u05E9\u05DE\u05D5\u05E8"
|
|
1062
|
+
type: "text",
|
|
1063
|
+
dir: "ltr",
|
|
1064
|
+
placeholder: "--:--",
|
|
1065
|
+
className: "w-14 h-7 px-1 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm font-normal text-slate-800 tracking-wider rounded text-center",
|
|
1066
|
+
value: rawInput,
|
|
1067
|
+
onChange: handleInputChange,
|
|
1068
|
+
onKeyDown: handleKeyDown,
|
|
1069
|
+
onBlur: handleInputBlur
|
|
853
1070
|
}
|
|
854
1071
|
)
|
|
855
|
-
] })
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
"input",
|
|
859
|
-
{
|
|
860
|
-
type: "checkbox",
|
|
861
|
-
checked: !!value,
|
|
862
|
-
onChange: (e) => onChange(e.target.checked),
|
|
863
|
-
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
864
|
-
}
|
|
865
|
-
) }),
|
|
866
|
-
GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
867
|
-
DrivePickerCell,
|
|
868
|
-
{
|
|
869
|
-
value: value || [],
|
|
870
|
-
onChange,
|
|
871
|
-
column,
|
|
872
|
-
rowId,
|
|
873
|
-
tableName: context == null ? void 0 : context.tableName,
|
|
874
|
-
onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
|
|
875
|
-
context
|
|
876
|
-
}
|
|
877
|
-
),
|
|
878
|
-
RELATION: ({ value, onChange, column, context }) => {
|
|
879
|
-
var _a;
|
|
880
|
-
const options = ((_a = context == null ? void 0 : context.relationOptions) == null ? void 0 : _a[column.name]) || [];
|
|
881
|
-
import_react5.default.useEffect(() => {
|
|
882
|
-
if (typeof value === "string" && value !== "" && options.length > 0) {
|
|
883
|
-
const isValidId = options.some((o) => String(o.id) === String(value));
|
|
884
|
-
if (!isValidId) {
|
|
885
|
-
const match = options.find(
|
|
886
|
-
(o) => String(getRelationDisplayLabel(o, column)).trim() === String(value).trim()
|
|
887
|
-
);
|
|
888
|
-
if (match) {
|
|
889
|
-
onChange(match.id);
|
|
890
|
-
} else {
|
|
891
|
-
onChange("");
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
}, [value, options, column, onChange]);
|
|
896
|
-
const processedOptions = options.map((opt) => __spreadProps(__spreadValues({}, opt), {
|
|
897
|
-
_displayLabel: getRelationDisplayLabel(opt, column)
|
|
898
|
-
}));
|
|
899
|
-
const validOptions = processedOptions.filter((o) => o._displayLabel !== "\u05D4\u05E2\u05E8\u05DA \u05E9\u05D1\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05EA \u05E0\u05E9\u05D0\u05E8 \u05E8\u05D9\u05E7");
|
|
900
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
901
|
-
"select",
|
|
1072
|
+
] }),
|
|
1073
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1074
|
+
"div",
|
|
902
1075
|
{
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
if (context == null ? void 0 : context.refetchRelation) {
|
|
908
|
-
context.refetchRelation(column.name);
|
|
909
|
-
}
|
|
910
|
-
},
|
|
1076
|
+
id: "time-picker-popover",
|
|
1077
|
+
dir: "rtl",
|
|
1078
|
+
style: { top: `${popoverPos.top}px`, right: `${popoverPos.right}px` },
|
|
1079
|
+
className: "fixed z-[99999] w-64 bg-white rounded-xl shadow-2xl border border-slate-200 p-3.5 animate-in fade-in zoom-in-95 duration-150",
|
|
911
1080
|
children: [
|
|
912
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.
|
|
913
|
-
|
|
1081
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center justify-between pb-2 mb-2 border-b border-slate-100", children: [
|
|
1082
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5 text-xs font-semibold text-slate-700", children: [
|
|
1083
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react4.Clock, { className: "w-3.5 h-3.5 text-blue-600" }),
|
|
1084
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u05D1\u05D7\u05D9\u05E8\u05EA \u05E9\u05E2\u05D4" })
|
|
1085
|
+
] }),
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
1087
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1088
|
+
"button",
|
|
1089
|
+
{
|
|
1090
|
+
type: "button",
|
|
1091
|
+
onClick: handleSetNow,
|
|
1092
|
+
className: "text-[11px] px-1.5 py-0.5 font-medium text-blue-600 hover:bg-blue-50 rounded transition-colors cursor-pointer",
|
|
1093
|
+
children: "\u05E2\u05DB\u05E9\u05D9\u05D5"
|
|
1094
|
+
}
|
|
1095
|
+
),
|
|
1096
|
+
displayString && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1097
|
+
"button",
|
|
1098
|
+
{
|
|
1099
|
+
type: "button",
|
|
1100
|
+
onClick: handleClear,
|
|
1101
|
+
className: "text-[11px] px-1.5 py-0.5 font-medium text-slate-500 hover:text-rose-600 hover:bg-rose-50 rounded transition-colors cursor-pointer",
|
|
1102
|
+
children: "\u05E0\u05E7\u05D4"
|
|
1103
|
+
}
|
|
1104
|
+
),
|
|
1105
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1106
|
+
"button",
|
|
1107
|
+
{
|
|
1108
|
+
type: "button",
|
|
1109
|
+
onClick: () => setIsOpen(false),
|
|
1110
|
+
className: "p-0.5 text-slate-400 hover:text-slate-600 rounded transition-colors cursor-pointer mr-0.5",
|
|
1111
|
+
title: "\u05E1\u05D2\u05D5\u05E8",
|
|
1112
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react4.X, { className: "w-3.5 h-3.5" })
|
|
1113
|
+
}
|
|
1114
|
+
)
|
|
1115
|
+
] })
|
|
1116
|
+
] }),
|
|
1117
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center justify-center py-1 mb-2 bg-slate-50 border border-slate-100 rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-base font-semibold text-slate-800 tracking-wider", dir: "ltr", children: displayString || "--:--" }) }),
|
|
1118
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
1119
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
1120
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-[11px] font-medium text-slate-400 text-center mb-1", children: "\u05D3\u05E7\u05D5\u05EA" }),
|
|
1121
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1122
|
+
"div",
|
|
1123
|
+
{
|
|
1124
|
+
ref: minutesListRef,
|
|
1125
|
+
className: "h-44 overflow-y-auto border border-slate-100 rounded-lg p-1 space-y-0.5 bg-slate-50/50",
|
|
1126
|
+
children: ALL_MINUTES.map((m) => {
|
|
1127
|
+
const isSelected = selectedMinute === m;
|
|
1128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1129
|
+
"button",
|
|
1130
|
+
{
|
|
1131
|
+
type: "button",
|
|
1132
|
+
"data-selected": isSelected,
|
|
1133
|
+
onClick: () => handleSelectMinute(m),
|
|
1134
|
+
className: `w-full py-1 text-xs text-center rounded transition-colors cursor-pointer ${isSelected ? "bg-blue-600 text-white font-medium shadow-xs" : "text-slate-700 hover:bg-slate-200/70"}`,
|
|
1135
|
+
children: String(m).padStart(2, "0")
|
|
1136
|
+
},
|
|
1137
|
+
m
|
|
1138
|
+
);
|
|
1139
|
+
})
|
|
1140
|
+
}
|
|
1141
|
+
)
|
|
1142
|
+
] }),
|
|
1143
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
1144
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-[11px] font-medium text-slate-400 text-center mb-1", children: "\u05E9\u05E2\u05D5\u05EA" }),
|
|
1145
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1146
|
+
"div",
|
|
1147
|
+
{
|
|
1148
|
+
ref: hoursListRef,
|
|
1149
|
+
className: "h-44 overflow-y-auto border border-slate-100 rounded-lg p-1 space-y-0.5 bg-slate-50/50",
|
|
1150
|
+
children: Array.from({ length: 24 }, (_, i) => {
|
|
1151
|
+
const isSelected = selectedHour === i;
|
|
1152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1153
|
+
"button",
|
|
1154
|
+
{
|
|
1155
|
+
type: "button",
|
|
1156
|
+
"data-selected": isSelected,
|
|
1157
|
+
onClick: () => handleSelectHour(i),
|
|
1158
|
+
className: `w-full py-1 text-xs text-center rounded transition-colors cursor-pointer ${isSelected ? "bg-blue-600 text-white font-medium shadow-xs" : "text-slate-700 hover:bg-slate-200/70"}`,
|
|
1159
|
+
children: String(i).padStart(2, "0")
|
|
1160
|
+
},
|
|
1161
|
+
i
|
|
1162
|
+
);
|
|
1163
|
+
})
|
|
1164
|
+
}
|
|
1165
|
+
)
|
|
1166
|
+
] })
|
|
1167
|
+
] })
|
|
914
1168
|
]
|
|
915
1169
|
}
|
|
916
|
-
)
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
1170
|
+
)
|
|
1171
|
+
] });
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// src/components/TableBlock/fields/LinkPickerCell.tsx
|
|
1175
|
+
var import_react6 = require("react");
|
|
1176
|
+
var import_lucide_react5 = require("lucide-react");
|
|
1177
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1178
|
+
function parseLinkValue(val) {
|
|
1179
|
+
if (!val) return { url: "", label: "" };
|
|
1180
|
+
if (typeof val === "string") {
|
|
1181
|
+
return { url: val.trim(), label: "" };
|
|
1182
|
+
}
|
|
1183
|
+
if (typeof val === "object") {
|
|
1184
|
+
return {
|
|
1185
|
+
url: typeof val.url === "string" ? val.url.trim() : "",
|
|
1186
|
+
label: typeof val.label === "string" ? val.label.trim() : ""
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
return { url: "", label: "" };
|
|
1190
|
+
}
|
|
1191
|
+
function resolveProtocol(url) {
|
|
1192
|
+
const trimmed = url.trim();
|
|
1193
|
+
if (!trimmed) return "";
|
|
1194
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
1195
|
+
return trimmed;
|
|
1196
|
+
}
|
|
1197
|
+
return `https://${trimmed}`;
|
|
1198
|
+
}
|
|
1199
|
+
function LinkPickerCell({ value, onChange, readOnly = false }) {
|
|
1200
|
+
const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
|
|
1201
|
+
const containerRef = (0, import_react6.useRef)(null);
|
|
1202
|
+
const urlInputRef = (0, import_react6.useRef)(null);
|
|
1203
|
+
const [popoverPos, setPopoverPos] = (0, import_react6.useState)({ top: 0, right: 0 });
|
|
1204
|
+
const currentLink = parseLinkValue(value);
|
|
1205
|
+
const [draftUrl, setDraftUrl] = (0, import_react6.useState)(currentLink.url);
|
|
1206
|
+
const [draftLabel, setDraftLabel] = (0, import_react6.useState)(currentLink.label);
|
|
1207
|
+
const draftUrlRef = (0, import_react6.useRef)(draftUrl);
|
|
1208
|
+
const draftLabelRef = (0, import_react6.useRef)(draftLabel);
|
|
1209
|
+
(0, import_react6.useEffect)(() => {
|
|
1210
|
+
draftUrlRef.current = draftUrl;
|
|
1211
|
+
}, [draftUrl]);
|
|
1212
|
+
(0, import_react6.useEffect)(() => {
|
|
1213
|
+
draftLabelRef.current = draftLabel;
|
|
1214
|
+
}, [draftLabel]);
|
|
1215
|
+
(0, import_react6.useEffect)(() => {
|
|
1216
|
+
if (!isOpen) {
|
|
1217
|
+
setDraftUrl(currentLink.url);
|
|
1218
|
+
setDraftLabel(currentLink.label);
|
|
928
1219
|
}
|
|
929
|
-
)
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
1220
|
+
}, [value, isOpen]);
|
|
1221
|
+
const updatePopoverPosition = (0, import_react6.useCallback)(() => {
|
|
1222
|
+
if (containerRef.current) {
|
|
1223
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
1224
|
+
const right = window.innerWidth - rect.right;
|
|
1225
|
+
const popoverHeight = 220;
|
|
1226
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
1227
|
+
if (spaceBelow < popoverHeight && rect.top > popoverHeight) {
|
|
1228
|
+
setPopoverPos({
|
|
1229
|
+
top: Math.max(10, rect.top - popoverHeight - 4),
|
|
1230
|
+
right: Math.max(10, right)
|
|
1231
|
+
});
|
|
1232
|
+
} else {
|
|
1233
|
+
setPopoverPos({
|
|
1234
|
+
top: Math.min(window.innerHeight - popoverHeight - 10, rect.bottom + 4),
|
|
1235
|
+
right: Math.max(10, right)
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}, []);
|
|
1240
|
+
const handleSaveAndClose = (0, import_react6.useCallback)(() => {
|
|
1241
|
+
const rawUrl = draftUrlRef.current.trim();
|
|
1242
|
+
const rawLabel = draftLabelRef.current.trim();
|
|
1243
|
+
if (!rawUrl) {
|
|
1244
|
+
onChange(null);
|
|
1245
|
+
} else {
|
|
1246
|
+
const resolved = resolveProtocol(rawUrl);
|
|
1247
|
+
onChange({
|
|
1248
|
+
url: resolved,
|
|
1249
|
+
label: rawLabel
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
setIsOpen(false);
|
|
1253
|
+
}, [onChange]);
|
|
1254
|
+
const handleOpen = () => {
|
|
1255
|
+
setDraftUrl(currentLink.url);
|
|
1256
|
+
setDraftLabel(currentLink.label);
|
|
1257
|
+
updatePopoverPosition();
|
|
1258
|
+
setIsOpen(true);
|
|
1259
|
+
setTimeout(() => {
|
|
1260
|
+
var _a;
|
|
1261
|
+
(_a = urlInputRef.current) == null ? void 0 : _a.focus();
|
|
1262
|
+
}, 50);
|
|
1263
|
+
};
|
|
1264
|
+
(0, import_react6.useEffect)(() => {
|
|
1265
|
+
if (!isOpen) return;
|
|
1266
|
+
updatePopoverPosition();
|
|
1267
|
+
function handleScrollOrResize() {
|
|
1268
|
+
updatePopoverPosition();
|
|
1269
|
+
}
|
|
1270
|
+
function handleClickOutside(event) {
|
|
1271
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1272
|
+
const popoverEl = document.getElementById("link-picker-popover");
|
|
1273
|
+
if (popoverEl && popoverEl.contains(event.target)) {
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
handleSaveAndClose();
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
window.addEventListener("scroll", handleScrollOrResize, true);
|
|
1280
|
+
window.addEventListener("resize", handleScrollOrResize);
|
|
1281
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1282
|
+
return () => {
|
|
1283
|
+
window.removeEventListener("scroll", handleScrollOrResize, true);
|
|
1284
|
+
window.removeEventListener("resize", handleScrollOrResize);
|
|
1285
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1286
|
+
};
|
|
1287
|
+
}, [isOpen, updatePopoverPosition, handleSaveAndClose]);
|
|
1288
|
+
const handleClear = () => {
|
|
1289
|
+
onChange(null);
|
|
1290
|
+
setDraftUrl("");
|
|
1291
|
+
setDraftLabel("");
|
|
1292
|
+
setIsOpen(false);
|
|
1293
|
+
};
|
|
1294
|
+
if (readOnly) {
|
|
1295
|
+
if (!currentLink.url) {
|
|
1296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-400 text-xs italic", children: "-" });
|
|
1297
|
+
}
|
|
1298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "px-2 py-1 flex items-center h-full w-full", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1299
|
+
"a",
|
|
1300
|
+
{
|
|
1301
|
+
href: currentLink.url,
|
|
1302
|
+
target: "_blank",
|
|
1303
|
+
rel: "noopener noreferrer",
|
|
1304
|
+
className: "text-blue-600 hover:underline truncate text-sm flex items-center gap-1.5",
|
|
1305
|
+
onClick: (e) => e.stopPropagation(),
|
|
1306
|
+
children: [
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.ExternalLink, { className: "w-3.5 h-3.5 shrink-0 text-blue-500" }),
|
|
1308
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", children: currentLink.label || currentLink.url })
|
|
1309
|
+
]
|
|
1310
|
+
}
|
|
1311
|
+
) });
|
|
1312
|
+
}
|
|
1313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: containerRef, className: "relative w-full h-full flex items-center justify-between px-2 py-1 group", children: [
|
|
1314
|
+
currentLink.url ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1315
|
+
"a",
|
|
1316
|
+
{
|
|
1317
|
+
href: currentLink.url,
|
|
1318
|
+
target: "_blank",
|
|
1319
|
+
rel: "noopener noreferrer",
|
|
1320
|
+
className: "text-blue-600 hover:underline truncate text-sm flex items-center gap-1.5 flex-1 min-w-0",
|
|
1321
|
+
onClick: (e) => e.stopPropagation(),
|
|
1322
|
+
title: currentLink.url,
|
|
1323
|
+
children: [
|
|
1324
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.ExternalLink, { className: "w-3.5 h-3.5 shrink-0 text-blue-500" }),
|
|
1325
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", children: currentLink.label || currentLink.url })
|
|
1326
|
+
]
|
|
1327
|
+
}
|
|
1328
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1329
|
+
"span",
|
|
1330
|
+
{
|
|
1331
|
+
className: "text-slate-400 italic text-sm flex-1 cursor-pointer select-none",
|
|
1332
|
+
onClick: handleOpen,
|
|
1333
|
+
children: "\u05E8\u05D9\u05E7"
|
|
1334
|
+
}
|
|
1335
|
+
),
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1337
|
+
"button",
|
|
1338
|
+
{
|
|
1339
|
+
type: "button",
|
|
1340
|
+
onClick: (e) => {
|
|
1341
|
+
e.stopPropagation();
|
|
1342
|
+
if (isOpen) {
|
|
1343
|
+
handleSaveAndClose();
|
|
1344
|
+
} else {
|
|
1345
|
+
handleOpen();
|
|
1346
|
+
}
|
|
1347
|
+
},
|
|
1348
|
+
className: "p-1 text-slate-400 hover:text-blue-600 hover:bg-slate-100 rounded transition-colors cursor-pointer shrink-0 ml-1",
|
|
1349
|
+
title: "\u05E2\u05E8\u05D9\u05DB\u05EA \u05E7\u05D9\u05E9\u05D5\u05E8",
|
|
1350
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Link2, { className: "w-3.5 h-3.5" })
|
|
1351
|
+
}
|
|
1352
|
+
),
|
|
1353
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1354
|
+
"div",
|
|
1355
|
+
{
|
|
1356
|
+
id: "link-picker-popover",
|
|
1357
|
+
dir: "rtl",
|
|
1358
|
+
style: { top: `${popoverPos.top}px`, right: `${popoverPos.right}px` },
|
|
1359
|
+
className: "fixed z-[99999] w-[280px] bg-white rounded-xl shadow-2xl border border-slate-200 p-3.5 animate-in fade-in zoom-in-95 duration-150",
|
|
1360
|
+
onClick: (e) => e.stopPropagation(),
|
|
1361
|
+
children: [
|
|
1362
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between pb-2 mb-3 border-b border-slate-100", children: [
|
|
1363
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5 text-xs font-semibold text-slate-700", children: [
|
|
1364
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Link2, { className: "w-3.5 h-3.5 text-blue-600" }),
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05E2\u05E8\u05D9\u05DB\u05EA \u05E7\u05D9\u05E9\u05D5\u05E8" })
|
|
1366
|
+
] }),
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1368
|
+
"button",
|
|
1369
|
+
{
|
|
1370
|
+
type: "button",
|
|
1371
|
+
onClick: handleSaveAndClose,
|
|
1372
|
+
className: "p-0.5 text-slate-400 hover:text-slate-600 rounded transition-colors cursor-pointer",
|
|
1373
|
+
title: "\u05E1\u05D2\u05D5\u05E8 \u05D5\u05E9\u05DE\u05D5\u05E8",
|
|
1374
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.X, { className: "w-3.5 h-3.5" })
|
|
1375
|
+
}
|
|
1376
|
+
)
|
|
1377
|
+
] }),
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-2.5 mb-3.5", children: [
|
|
1379
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1380
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "block text-xs font-medium text-slate-700 mb-1", children: [
|
|
1381
|
+
"\u05DB\u05EA\u05D5\u05D1\u05EA URL ",
|
|
1382
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-rose-500", children: "*" })
|
|
1383
|
+
] }),
|
|
1384
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1385
|
+
"input",
|
|
1386
|
+
{
|
|
1387
|
+
ref: urlInputRef,
|
|
1388
|
+
type: "text",
|
|
1389
|
+
dir: "ltr",
|
|
1390
|
+
placeholder: "https://...",
|
|
1391
|
+
className: "w-full h-8 px-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm 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",
|
|
1392
|
+
value: draftUrl,
|
|
1393
|
+
onChange: (e) => setDraftUrl(e.target.value),
|
|
1394
|
+
onKeyDown: (e) => {
|
|
1395
|
+
if (e.key === "Enter") {
|
|
1396
|
+
e.preventDefault();
|
|
1397
|
+
handleSaveAndClose();
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
)
|
|
1402
|
+
] }),
|
|
1403
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "block text-xs font-medium text-slate-700 mb-1", children: [
|
|
1405
|
+
"\u05D8\u05E7\u05E1\u05D8 \u05DC\u05EA\u05E6\u05D5\u05D2\u05D4 ",
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-slate-400 font-normal", children: "(\u05D0\u05D5\u05E4\u05E6\u05D9\u05D5\u05E0\u05DC\u05D9)" })
|
|
1407
|
+
] }),
|
|
1408
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1409
|
+
"input",
|
|
1410
|
+
{
|
|
1411
|
+
type: "text",
|
|
1412
|
+
placeholder: "\u05E9\u05DD \u05D4\u05E7\u05D9\u05E9\u05D5\u05E8",
|
|
1413
|
+
className: "w-full h-8 px-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm 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",
|
|
1414
|
+
value: draftLabel,
|
|
1415
|
+
onChange: (e) => setDraftLabel(e.target.value),
|
|
1416
|
+
onKeyDown: (e) => {
|
|
1417
|
+
if (e.key === "Enter") {
|
|
1418
|
+
e.preventDefault();
|
|
1419
|
+
handleSaveAndClose();
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
)
|
|
1424
|
+
] })
|
|
1425
|
+
] }),
|
|
1426
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between pt-2 border-t border-slate-100", children: [
|
|
1427
|
+
currentLink.url ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1428
|
+
"button",
|
|
1429
|
+
{
|
|
1430
|
+
type: "button",
|
|
1431
|
+
onClick: handleClear,
|
|
1432
|
+
className: "inline-flex items-center gap-1 text-xs text-rose-600 hover:text-rose-700 hover:bg-rose-50 px-2 py-1 rounded transition-colors cursor-pointer",
|
|
1433
|
+
title: "\u05DE\u05D7\u05E7 \u05E7\u05D9\u05E9\u05D5\u05E8",
|
|
1434
|
+
children: [
|
|
1435
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Trash2, { className: "w-3 h-3" }),
|
|
1436
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05E0\u05E7\u05D4" })
|
|
1437
|
+
]
|
|
1438
|
+
}
|
|
1439
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", {}),
|
|
1440
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1441
|
+
"button",
|
|
1442
|
+
{
|
|
1443
|
+
type: "button",
|
|
1444
|
+
onClick: handleSaveAndClose,
|
|
1445
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-white bg-blue-600 hover:bg-blue-700 px-3 py-1.5 rounded-lg shadow-xs transition-colors cursor-pointer",
|
|
1446
|
+
children: [
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Check, { className: "w-3.5 h-3.5" }),
|
|
1448
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05E9\u05DE\u05D5\u05E8" })
|
|
1449
|
+
]
|
|
1450
|
+
}
|
|
1451
|
+
)
|
|
1452
|
+
] })
|
|
1453
|
+
]
|
|
1454
|
+
}
|
|
1455
|
+
)
|
|
1456
|
+
] });
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
// src/components/TableBlock/fields/RelationPickerCell.tsx
|
|
1460
|
+
var import_react7 = require("react");
|
|
1461
|
+
var import_lucide_react6 = require("lucide-react");
|
|
1462
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1463
|
+
function isRawObjectId(str) {
|
|
1464
|
+
if (typeof str !== "string") return false;
|
|
1465
|
+
const trimmed = str.trim();
|
|
1466
|
+
return /^[0-9a-fA-F]{24}$/.test(trimmed) || trimmed.startsWith("temp_");
|
|
1467
|
+
}
|
|
1468
|
+
function normalizeRelationValue(val) {
|
|
1469
|
+
if (val === null || val === void 0 || val === "") return [];
|
|
1470
|
+
if (Array.isArray(val)) {
|
|
1471
|
+
return val.map((item) => {
|
|
1472
|
+
if (typeof item === "string") return item.trim();
|
|
1473
|
+
if (typeof item === "object" && item !== null) {
|
|
1474
|
+
return String(item.id || item._id || item.value || "").trim();
|
|
1475
|
+
}
|
|
1476
|
+
return String(item).trim();
|
|
1477
|
+
}).filter((id) => Boolean(id) && id !== "");
|
|
1478
|
+
}
|
|
1479
|
+
if (typeof val === "string") {
|
|
1480
|
+
const trimmed = val.trim();
|
|
1481
|
+
return trimmed ? [trimmed] : [];
|
|
1482
|
+
}
|
|
1483
|
+
if (typeof val === "object" && val !== null) {
|
|
1484
|
+
const id = String(val.id || val._id || val.value || "").trim();
|
|
1485
|
+
return id ? [id] : [];
|
|
1486
|
+
}
|
|
1487
|
+
return [];
|
|
1488
|
+
}
|
|
1489
|
+
function resolveRelationLabel(opt, column) {
|
|
1490
|
+
var _a;
|
|
1491
|
+
if (!opt) return "";
|
|
1492
|
+
const displayField = (_a = column.config) == null ? void 0 : _a.displayField;
|
|
1493
|
+
if (displayField && opt.data) {
|
|
1494
|
+
const val = opt.data[displayField];
|
|
1495
|
+
if (val !== void 0 && val !== null) {
|
|
1496
|
+
const s = String(val).trim();
|
|
1497
|
+
if (s !== "" && !isRawObjectId(s)) {
|
|
1498
|
+
return s;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
if (opt.label && typeof opt.label === "string") {
|
|
1503
|
+
const s = opt.label.trim();
|
|
1504
|
+
if (s !== "" && !isRawObjectId(s) && s !== opt.id) {
|
|
1505
|
+
return s;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
if (opt.data) {
|
|
1509
|
+
const defaultLabel = opt.data.name || opt.data.title || opt.data.fullName;
|
|
1510
|
+
if (defaultLabel !== void 0 && defaultLabel !== null) {
|
|
1511
|
+
const s = String(defaultLabel).trim();
|
|
1512
|
+
if (s !== "" && !isRawObjectId(s)) {
|
|
1513
|
+
return s;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
return "";
|
|
1518
|
+
}
|
|
1519
|
+
function RelationPickerCell({
|
|
1520
|
+
value,
|
|
1521
|
+
onChange,
|
|
1522
|
+
column,
|
|
1523
|
+
context,
|
|
1524
|
+
rowId,
|
|
1525
|
+
readOnly = false
|
|
1526
|
+
}) {
|
|
1527
|
+
var _a;
|
|
1528
|
+
const [isOpen, setIsOpen] = (0, import_react7.useState)(false);
|
|
1529
|
+
const [searchQuery, setSearchQuery] = (0, import_react7.useState)("");
|
|
1530
|
+
const containerRef = (0, import_react7.useRef)(null);
|
|
1531
|
+
const searchInputRef = (0, import_react7.useRef)(null);
|
|
1532
|
+
const allowMultiple = Boolean((_a = column.config) == null ? void 0 : _a.allowMultiple);
|
|
1533
|
+
const selectedIds = (0, import_react7.useMemo)(() => normalizeRelationValue(value), [value]);
|
|
1534
|
+
const isStandalone = !context || context.relationOptions === void 0;
|
|
1535
|
+
const optionsLoaded = isStandalone || context.relationOptions[column.name] !== void 0;
|
|
1536
|
+
const rawOptions = (0, import_react7.useMemo)(() => {
|
|
1537
|
+
var _a2;
|
|
1538
|
+
return ((_a2 = context == null ? void 0 : context.relationOptions) == null ? void 0 : _a2[column.name]) || [];
|
|
1539
|
+
}, [context == null ? void 0 : context.relationOptions, column.name]);
|
|
1540
|
+
const processedOptions = (0, import_react7.useMemo)(() => {
|
|
1541
|
+
return rawOptions.map((opt) => {
|
|
1542
|
+
const label = resolveRelationLabel(opt, column);
|
|
1543
|
+
return {
|
|
1544
|
+
id: String(opt.id),
|
|
1545
|
+
_displayLabel: label
|
|
1546
|
+
};
|
|
1547
|
+
}).filter((opt) => opt._displayLabel && opt._displayLabel.trim() !== "" && !isRawObjectId(opt._displayLabel));
|
|
1548
|
+
}, [rawOptions, column]);
|
|
1549
|
+
const getDisplayForId = (0, import_react7.useCallback)((id) => {
|
|
1550
|
+
const found = processedOptions.find((o) => String(o.id) === String(id));
|
|
1551
|
+
if (found && found._displayLabel && !isRawObjectId(found._displayLabel)) {
|
|
1552
|
+
return found._displayLabel;
|
|
1553
|
+
}
|
|
1554
|
+
return "-";
|
|
1555
|
+
}, [processedOptions]);
|
|
1556
|
+
const handleOpen = (e) => {
|
|
1557
|
+
if (readOnly) return;
|
|
1558
|
+
e == null ? void 0 : e.stopPropagation();
|
|
1559
|
+
setIsOpen((prev) => !prev);
|
|
1560
|
+
setSearchQuery("");
|
|
1561
|
+
if (context == null ? void 0 : context.refetchRelation) {
|
|
1562
|
+
context.refetchRelation(column.name);
|
|
1563
|
+
}
|
|
1564
|
+
};
|
|
1565
|
+
(0, import_react7.useEffect)(() => {
|
|
1566
|
+
if (isOpen) {
|
|
1567
|
+
setTimeout(() => {
|
|
1568
|
+
var _a2;
|
|
1569
|
+
(_a2 = searchInputRef.current) == null ? void 0 : _a2.focus();
|
|
1570
|
+
}, 50);
|
|
1571
|
+
}
|
|
1572
|
+
}, [isOpen]);
|
|
1573
|
+
const handleSelectOption = (optId) => {
|
|
1574
|
+
if (!allowMultiple) {
|
|
1575
|
+
onChange([optId]);
|
|
1576
|
+
setIsOpen(false);
|
|
1577
|
+
} else {
|
|
1578
|
+
if (selectedIds.includes(optId)) {
|
|
1579
|
+
onChange(selectedIds.filter((id) => id !== optId));
|
|
1580
|
+
} else {
|
|
1581
|
+
onChange([...selectedIds, optId]);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
};
|
|
1585
|
+
const handleRemove = (idToRemove) => {
|
|
1586
|
+
onChange(selectedIds.filter((id) => id !== idToRemove));
|
|
1587
|
+
};
|
|
1588
|
+
const handleClearSingle = (e) => {
|
|
1589
|
+
e.stopPropagation();
|
|
1590
|
+
onChange([]);
|
|
1591
|
+
};
|
|
1592
|
+
(0, import_react7.useEffect)(() => {
|
|
1593
|
+
if (!isOpen) return;
|
|
1594
|
+
function handleClickOutside(event) {
|
|
1595
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1596
|
+
setIsOpen(false);
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
function handleKeyDown(event) {
|
|
1600
|
+
if (event.key === "Escape") {
|
|
1601
|
+
setIsOpen(false);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1605
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1606
|
+
return () => {
|
|
1607
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1608
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
1609
|
+
};
|
|
1610
|
+
}, [isOpen]);
|
|
1611
|
+
const filteredOptions = (0, import_react7.useMemo)(() => {
|
|
1612
|
+
const query = searchQuery.trim().toLowerCase();
|
|
1613
|
+
if (!query) return processedOptions;
|
|
1614
|
+
return processedOptions.filter((opt) => {
|
|
1615
|
+
return (opt._displayLabel || "").toLowerCase().includes(query);
|
|
1616
|
+
});
|
|
1617
|
+
}, [processedOptions, searchQuery]);
|
|
1618
|
+
if (!optionsLoaded && selectedIds.length > 0) {
|
|
1619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-2 py-1 flex items-center h-full w-full", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "inline-block w-16 h-4 bg-slate-100 animate-pulse rounded" }) });
|
|
1620
|
+
}
|
|
1621
|
+
if (readOnly) {
|
|
1622
|
+
if (selectedIds.length === 0) {
|
|
1623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "-" });
|
|
1624
|
+
}
|
|
1625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-1.5 py-1 flex flex-wrap items-center gap-1 h-full max-w-full overflow-hidden", dir: "rtl", children: selectedIds.map((id) => {
|
|
1626
|
+
const displayText = getDisplayForId(id);
|
|
1627
|
+
if (displayText === "-") {
|
|
1628
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-slate-400 text-xs", children: "-" }, id);
|
|
1629
|
+
}
|
|
1630
|
+
const palette = getDeterministicPastelBadge(displayText);
|
|
1631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1632
|
+
"span",
|
|
1633
|
+
{
|
|
1634
|
+
className: `inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border shadow-xs max-w-full truncate ${palette.bg} ${palette.text} ${palette.border}`,
|
|
1635
|
+
title: displayText,
|
|
1636
|
+
children: displayText
|
|
1637
|
+
},
|
|
1638
|
+
id
|
|
1639
|
+
);
|
|
1640
|
+
}) });
|
|
1641
|
+
}
|
|
1642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1643
|
+
"div",
|
|
1644
|
+
{
|
|
1645
|
+
ref: containerRef,
|
|
1646
|
+
className: `relative w-full h-full flex items-center justify-between px-1.5 py-1 ${isOpen ? "z-50" : ""}`,
|
|
1647
|
+
dir: "rtl",
|
|
1648
|
+
children: [
|
|
1649
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1650
|
+
"div",
|
|
1651
|
+
{
|
|
1652
|
+
className: "flex items-center justify-between w-full h-full overflow-hidden cursor-pointer gap-1",
|
|
1653
|
+
onClick: handleOpen,
|
|
1654
|
+
children: !allowMultiple ? (
|
|
1655
|
+
// Single Select Mode
|
|
1656
|
+
(() => {
|
|
1657
|
+
const singleId = selectedIds[0];
|
|
1658
|
+
const displayText = singleId ? getDisplayForId(singleId) : "";
|
|
1659
|
+
const hasValidSelection = singleId && displayText !== "-" && displayText !== "";
|
|
1660
|
+
if (hasValidSelection) {
|
|
1661
|
+
const palette = getDeterministicPastelBadge(displayText);
|
|
1662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full overflow-hidden", children: [
|
|
1663
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1664
|
+
"span",
|
|
1665
|
+
{
|
|
1666
|
+
className: `inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium border shadow-xs max-w-full truncate group/tag ${palette.bg} ${palette.text} ${palette.border}`,
|
|
1667
|
+
title: displayText,
|
|
1668
|
+
children: [
|
|
1669
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: displayText }),
|
|
1670
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1671
|
+
"button",
|
|
1672
|
+
{
|
|
1673
|
+
type: "button",
|
|
1674
|
+
onClick: handleClearSingle,
|
|
1675
|
+
className: "opacity-0 group-hover/tag:opacity-100 hover:opacity-100 focus:opacity-100 focus:outline-none p-0.5 rounded-full hover:bg-black/10 transition-opacity cursor-pointer shrink-0",
|
|
1676
|
+
title: "\u05E0\u05E7\u05D4",
|
|
1677
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.X, { className: "w-3 h-3" })
|
|
1678
|
+
}
|
|
1679
|
+
)
|
|
1680
|
+
]
|
|
1681
|
+
}
|
|
1682
|
+
),
|
|
1683
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-0 hover:opacity-60 transition-opacity shrink-0 ml-1" })
|
|
1684
|
+
] });
|
|
1685
|
+
}
|
|
1686
|
+
if (singleId && displayText === "-") {
|
|
1687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full text-slate-400 text-xs", children: [
|
|
1688
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "-" }),
|
|
1689
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-0 hover:opacity-60 transition-opacity shrink-0 ml-1" })
|
|
1690
|
+
] });
|
|
1691
|
+
}
|
|
1692
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full text-slate-400 italic text-xs select-none", children: [
|
|
1693
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D1\u05D7\u05E8..." }),
|
|
1694
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-60 shrink-0 ml-1" })
|
|
1695
|
+
] });
|
|
1696
|
+
})()
|
|
1697
|
+
) : (
|
|
1698
|
+
// Multi Select Mode
|
|
1699
|
+
selectedIds.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full text-slate-400 italic text-xs select-none", children: [
|
|
1700
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D1\u05D7\u05E8..." }),
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-60 shrink-0 ml-1" })
|
|
1702
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full overflow-hidden", children: [
|
|
1703
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-wrap items-center gap-1 overflow-hidden max-h-full flex-1 py-0.5", children: selectedIds.map((id) => {
|
|
1704
|
+
const displayText = getDisplayForId(id);
|
|
1705
|
+
if (displayText === "-") {
|
|
1706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-slate-400 text-xs px-1", children: "-" }, id);
|
|
1707
|
+
}
|
|
1708
|
+
const palette = getDeterministicPastelBadge(displayText);
|
|
1709
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1710
|
+
"span",
|
|
1711
|
+
{
|
|
1712
|
+
className: `inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium border shadow-xs max-w-[160px] truncate group/tag ${palette.bg} ${palette.text} ${palette.border}`,
|
|
1713
|
+
title: displayText,
|
|
1714
|
+
children: [
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: displayText }),
|
|
1716
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1717
|
+
"button",
|
|
1718
|
+
{
|
|
1719
|
+
type: "button",
|
|
1720
|
+
onClick: (e) => {
|
|
1721
|
+
e.stopPropagation();
|
|
1722
|
+
handleRemove(id);
|
|
1723
|
+
},
|
|
1724
|
+
className: "opacity-0 group-hover/tag:opacity-100 hover:opacity-100 focus:opacity-100 focus:outline-none p-0.5 rounded-full hover:bg-black/10 transition-opacity cursor-pointer shrink-0",
|
|
1725
|
+
title: "\u05D4\u05E1\u05E8",
|
|
1726
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.X, { className: "w-3 h-3" })
|
|
1727
|
+
}
|
|
1728
|
+
)
|
|
1729
|
+
]
|
|
1730
|
+
},
|
|
1731
|
+
id
|
|
1732
|
+
);
|
|
1733
|
+
}) }),
|
|
1734
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-0 hover:opacity-60 transition-opacity shrink-0 ml-1" })
|
|
1735
|
+
] })
|
|
1736
|
+
)
|
|
1737
|
+
}
|
|
1738
|
+
),
|
|
1739
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1740
|
+
"div",
|
|
1741
|
+
{
|
|
1742
|
+
id: `relation-dropdown-${column.name}-${rowId || "cell"}`,
|
|
1743
|
+
dir: "rtl",
|
|
1744
|
+
className: "absolute top-full right-0 mt-1 z-[100] bg-white rounded-md shadow-lg border border-slate-200 p-1 min-w-[200px] w-full max-w-[300px] animate-in fade-in duration-100 flex flex-col",
|
|
1745
|
+
onClick: (e) => e.stopPropagation(),
|
|
1746
|
+
children: [
|
|
1747
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative mb-1", children: [
|
|
1748
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Search, { className: "w-3.5 h-3.5 text-slate-400 absolute right-2 top-2 pointer-events-none" }),
|
|
1749
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1750
|
+
"input",
|
|
1751
|
+
{
|
|
1752
|
+
ref: searchInputRef,
|
|
1753
|
+
type: "text",
|
|
1754
|
+
placeholder: "\u05D7\u05E4\u05E9...",
|
|
1755
|
+
value: searchQuery,
|
|
1756
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
1757
|
+
onKeyDown: (e) => {
|
|
1758
|
+
if (e.key === "Escape") {
|
|
1759
|
+
e.stopPropagation();
|
|
1760
|
+
setIsOpen(false);
|
|
1761
|
+
}
|
|
1762
|
+
},
|
|
1763
|
+
className: "w-full h-7 pr-7 pl-2 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"
|
|
1764
|
+
}
|
|
1765
|
+
)
|
|
1766
|
+
] }),
|
|
1767
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "overflow-y-auto max-h-[180px] space-y-0.5", children: filteredOptions.length > 0 ? filteredOptions.map((opt) => {
|
|
1768
|
+
const isSelected = selectedIds.includes(opt.id);
|
|
1769
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1770
|
+
"div",
|
|
1771
|
+
{
|
|
1772
|
+
onClick: () => handleSelectOption(opt.id),
|
|
1773
|
+
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"}`,
|
|
1774
|
+
children: [
|
|
1775
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate flex-1", children: opt._displayLabel }),
|
|
1776
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Check, { className: "w-3.5 h-3.5 text-blue-600 shrink-0 mr-1" })
|
|
1777
|
+
]
|
|
1778
|
+
},
|
|
1779
|
+
opt.id
|
|
1780
|
+
);
|
|
1781
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "py-2.5 px-2 text-center text-xs text-slate-400 select-none", children: processedOptions.length === 0 ? "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D6\u05DE\u05D9\u05E0\u05D5\u05EA" : "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA" }) })
|
|
1782
|
+
]
|
|
1783
|
+
}
|
|
1784
|
+
)
|
|
1785
|
+
]
|
|
1786
|
+
}
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
// src/components/TableBlock/fields/fieldRegistry.tsx
|
|
1791
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1792
|
+
var CURRENCY_SYMBOLS = {
|
|
1793
|
+
USD: "$",
|
|
1794
|
+
EUR: "\u20AC",
|
|
1795
|
+
ILS: "\u20AA",
|
|
1796
|
+
GBP: "\xA3"
|
|
1797
|
+
};
|
|
1798
|
+
function getCurrencySymbol(code) {
|
|
1799
|
+
if (!code) return "";
|
|
1800
|
+
return CURRENCY_SYMBOLS[code.toUpperCase()] || code;
|
|
1801
|
+
}
|
|
1802
|
+
var FORM_INPUTS = {
|
|
1803
|
+
DATE: ({ value, onChange, column }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DatePickerCell, { value, onChange, column }),
|
|
1804
|
+
CURRENCY: ({ value, column, onChange }) => {
|
|
1805
|
+
var _a;
|
|
1806
|
+
const symbol = getCurrencySymbol((_a = column.config) == null ? void 0 : _a.currencySymbol);
|
|
1807
|
+
const [isFocused, setIsFocused] = import_react8.default.useState(false);
|
|
1808
|
+
const displayValue = !isFocused && value !== void 0 && value !== null && !isNaN(Number(value)) ? new Intl.NumberFormat("en-US").format(Number(value)) : value !== void 0 && value !== null ? value : "";
|
|
1809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative w-full h-full", children: [
|
|
1810
|
+
symbol && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "absolute left-2 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none text-sm", children: symbol }),
|
|
1811
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1812
|
+
"input",
|
|
1813
|
+
{
|
|
1814
|
+
type: isFocused ? "number" : "text",
|
|
1815
|
+
step: "any",
|
|
1816
|
+
className: `w-full h-8 ${symbol ? "pl-6 pr-2" : "px-2"} bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm`,
|
|
1817
|
+
value: displayValue,
|
|
1818
|
+
onFocus: () => setIsFocused(true),
|
|
1819
|
+
onBlur: () => setIsFocused(false),
|
|
1820
|
+
onChange: (e) => {
|
|
1821
|
+
const val = e.target.value;
|
|
1822
|
+
onChange(val === "" ? null : Number(val));
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
)
|
|
1826
|
+
] });
|
|
1827
|
+
},
|
|
1828
|
+
TIME: ({ value, onChange, column }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TimePickerCell, { value, onChange, column }),
|
|
1829
|
+
LINK: ({ value, onChange, column }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LinkPickerCell, { value, onChange, column }),
|
|
1830
|
+
BOOLEAN: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center justify-center w-full h-full p-2", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1831
|
+
"input",
|
|
1832
|
+
{
|
|
1833
|
+
type: "checkbox",
|
|
1834
|
+
checked: !!value,
|
|
1835
|
+
onChange: (e) => onChange(e.target.checked),
|
|
1836
|
+
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
1837
|
+
}
|
|
1838
|
+
) }),
|
|
1839
|
+
GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1840
|
+
DrivePickerCell,
|
|
1841
|
+
{
|
|
1842
|
+
value: value || [],
|
|
1843
|
+
onChange,
|
|
1844
|
+
column,
|
|
1845
|
+
rowId,
|
|
1846
|
+
tableName: context == null ? void 0 : context.tableName,
|
|
1847
|
+
onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
|
|
1848
|
+
context
|
|
1849
|
+
}
|
|
1850
|
+
),
|
|
1851
|
+
RELATION: ({ value, onChange, column, context, rowId }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1852
|
+
RelationPickerCell,
|
|
1853
|
+
{
|
|
1854
|
+
value,
|
|
1855
|
+
onChange,
|
|
1856
|
+
column,
|
|
1857
|
+
context,
|
|
1858
|
+
rowId
|
|
1859
|
+
}
|
|
1860
|
+
),
|
|
1861
|
+
NUMBER: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1862
|
+
"input",
|
|
1863
|
+
{
|
|
1864
|
+
type: "number",
|
|
934
1865
|
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
935
|
-
value: value !== void 0 && value !== null ?
|
|
936
|
-
onChange: (e) =>
|
|
937
|
-
|
|
1866
|
+
value: value !== void 0 && value !== null ? value : "",
|
|
1867
|
+
onChange: (e) => {
|
|
1868
|
+
const val = e.target.value;
|
|
1869
|
+
onChange(val === "" ? null : Number(val));
|
|
1870
|
+
}
|
|
938
1871
|
}
|
|
939
1872
|
),
|
|
1873
|
+
PHONE: ({ value, onChange, column }) => {
|
|
1874
|
+
var _a;
|
|
1875
|
+
const enableWhatsApp = (_a = column == null ? void 0 : column.config) == null ? void 0 : _a.enableWhatsApp;
|
|
1876
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center w-full h-full px-2 gap-1.5 overflow-hidden", children: [
|
|
1877
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1878
|
+
"input",
|
|
1879
|
+
{
|
|
1880
|
+
type: "tel",
|
|
1881
|
+
className: "w-full h-8 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm flex-1 min-w-0",
|
|
1882
|
+
value: value !== void 0 && value !== null ? String(value) : "",
|
|
1883
|
+
onChange: (e) => onChange(e.target.value || null),
|
|
1884
|
+
dir: "ltr"
|
|
1885
|
+
}
|
|
1886
|
+
),
|
|
1887
|
+
enableWhatsApp && value && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1888
|
+
"button",
|
|
1889
|
+
{
|
|
1890
|
+
type: "button",
|
|
1891
|
+
className: "text-emerald-500 cursor-pointer hover:opacity-80 transition-opacity shrink-0 p-1 rounded hover:bg-emerald-50",
|
|
1892
|
+
title: "\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4",
|
|
1893
|
+
onClick: (e) => {
|
|
1894
|
+
e.stopPropagation();
|
|
1895
|
+
openWhatsAppChat(String(value));
|
|
1896
|
+
},
|
|
1897
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "w-4 h-4", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
|
|
1898
|
+
}
|
|
1899
|
+
)
|
|
1900
|
+
] });
|
|
1901
|
+
},
|
|
940
1902
|
GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
|
|
941
|
-
const [isSyncing, setIsSyncing] =
|
|
1903
|
+
const [isSyncing, setIsSyncing] = import_react8.default.useState(false);
|
|
942
1904
|
const { addToast } = useToast();
|
|
943
|
-
const googleClientIdRef =
|
|
944
|
-
const ensureGisScript =
|
|
1905
|
+
const googleClientIdRef = import_react8.default.useRef(null);
|
|
1906
|
+
const ensureGisScript = import_react8.default.useCallback(() => {
|
|
945
1907
|
return new Promise((resolve, reject) => {
|
|
946
1908
|
var _a, _b, _c;
|
|
947
1909
|
if ((_c = (_b = (_a = window.google) == null ? void 0 : _a.accounts) == null ? void 0 : _b.oauth2) == null ? void 0 : _c.initTokenClient) {
|
|
@@ -970,7 +1932,7 @@ var FORM_INPUTS = {
|
|
|
970
1932
|
document.head.appendChild(script);
|
|
971
1933
|
});
|
|
972
1934
|
}, []);
|
|
973
|
-
const requestGisToken =
|
|
1935
|
+
const requestGisToken = import_react8.default.useCallback(async (hint) => {
|
|
974
1936
|
await ensureGisScript();
|
|
975
1937
|
if (!googleClientIdRef.current && (context == null ? void 0 : context.executeAction)) {
|
|
976
1938
|
try {
|
|
@@ -1017,19 +1979,27 @@ var FORM_INPUTS = {
|
|
|
1017
1979
|
return { accessToken, email };
|
|
1018
1980
|
}, [ensureGisScript, context]);
|
|
1019
1981
|
const handleSync = async () => {
|
|
1020
|
-
var _a, _b, _c;
|
|
1982
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1021
1983
|
if (!(context == null ? void 0 : context.executeAction)) return;
|
|
1022
1984
|
setIsSyncing(true);
|
|
1023
1985
|
try {
|
|
1024
|
-
const mapping = column.contactMapping || {};
|
|
1986
|
+
const mapping = ((_a = column.config) == null ? void 0 : _a.contactMapping) || {};
|
|
1025
1987
|
const rowData = context.rowData || {};
|
|
1988
|
+
const targetTableMetaId = (context == null ? void 0 : context.tableMetaId) || (context == null ? void 0 : context.tableId);
|
|
1989
|
+
const targetOrgId = context == null ? void 0 : context.orgId;
|
|
1026
1990
|
let hasPhone = false;
|
|
1027
1991
|
if (mapping.phoneCol && rowData[mapping.phoneCol]) hasPhone = true;
|
|
1992
|
+
const activeParentTableId = ((_b = context.parentRecord) == null ? void 0 : _b.tableId) || (context == null ? void 0 : context.parentTableId);
|
|
1028
1993
|
let hasName = false;
|
|
1029
1994
|
if (mapping.nameParts && Array.isArray(mapping.nameParts)) {
|
|
1030
1995
|
for (const part of mapping.nameParts) {
|
|
1031
1996
|
if (part.type === "LOCAL" && rowData[part.columnId]) hasName = true;
|
|
1032
|
-
if (part.type === "PARENT"
|
|
1997
|
+
if (part.type === "PARENT") {
|
|
1998
|
+
if (!activeParentTableId) continue;
|
|
1999
|
+
if (part.parentTableId && part.parentTableId !== activeParentTableId) continue;
|
|
2000
|
+
if ((_d = (_c = context.parentRecord) == null ? void 0 : _c.data) == null ? void 0 : _d[part.columnId]) hasName = true;
|
|
2001
|
+
else if (((_e = context.parentRecord) == null ? void 0 : _e.recordId) || ((_f = context.parentRecord) == null ? void 0 : _f.id)) hasName = true;
|
|
2002
|
+
}
|
|
1033
2003
|
}
|
|
1034
2004
|
}
|
|
1035
2005
|
if (!hasPhone) {
|
|
@@ -1059,6 +2029,10 @@ var FORM_INPUTS = {
|
|
|
1059
2029
|
emailCol: mapping.emailCol,
|
|
1060
2030
|
localRowData: rowData,
|
|
1061
2031
|
parentRecord: context.parentRecord,
|
|
2032
|
+
tableMetaId: targetTableMetaId,
|
|
2033
|
+
tableId: targetTableMetaId,
|
|
2034
|
+
recordId: rowId,
|
|
2035
|
+
orgId: targetOrgId,
|
|
1062
2036
|
accessToken,
|
|
1063
2037
|
userEmail
|
|
1064
2038
|
};
|
|
@@ -1069,142 +2043,740 @@ var FORM_INPUTS = {
|
|
|
1069
2043
|
} else {
|
|
1070
2044
|
onChange(res);
|
|
1071
2045
|
}
|
|
1072
|
-
if (
|
|
2046
|
+
if (targetTableMetaId && !rowId.startsWith("temp_")) {
|
|
1073
2047
|
await context.executeAction("UPDATE_RECORD", {
|
|
1074
|
-
tableId:
|
|
2048
|
+
tableId: targetTableMetaId,
|
|
2049
|
+
tableMetaId: targetTableMetaId,
|
|
1075
2050
|
recordId: rowId,
|
|
2051
|
+
orgId: targetOrgId,
|
|
1076
2052
|
data: { [column.name]: res }
|
|
1077
2053
|
});
|
|
1078
2054
|
}
|
|
1079
2055
|
}
|
|
1080
|
-
} catch (error) {
|
|
1081
|
-
console.error("Failed to sync contact:", error);
|
|
1082
|
-
addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
|
|
1083
|
-
} finally {
|
|
1084
|
-
setIsSyncing(false);
|
|
2056
|
+
} catch (error) {
|
|
2057
|
+
console.error("Failed to sync contact:", error);
|
|
2058
|
+
addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
|
|
2059
|
+
} finally {
|
|
2060
|
+
setIsSyncing(false);
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
2063
|
+
const handleUnlink = async () => {
|
|
2064
|
+
let accessToken;
|
|
2065
|
+
const targetTableMetaId = (context == null ? void 0 : context.tableMetaId) || (context == null ? void 0 : context.tableId);
|
|
2066
|
+
const targetOrgId = context == null ? void 0 : context.orgId;
|
|
2067
|
+
try {
|
|
2068
|
+
let emailHint = value == null ? void 0 : value.userEmail;
|
|
2069
|
+
if (!emailHint && (value == null ? void 0 : value.url)) {
|
|
2070
|
+
try {
|
|
2071
|
+
const parsed = new URL(value.url);
|
|
2072
|
+
emailHint = parsed.searchParams.get("authuser") || void 0;
|
|
2073
|
+
} catch (e) {
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
const auth = await requestGisToken(emailHint);
|
|
2077
|
+
accessToken = auth.accessToken;
|
|
2078
|
+
} catch (err) {
|
|
2079
|
+
console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
|
|
2080
|
+
}
|
|
2081
|
+
if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
|
|
2082
|
+
await context.executeAction("DELETE_GOOGLE_CONTACT", {
|
|
2083
|
+
resourceName: value.resourceName,
|
|
2084
|
+
accessToken,
|
|
2085
|
+
tableMetaId: targetTableMetaId,
|
|
2086
|
+
tableId: targetTableMetaId,
|
|
2087
|
+
recordId: rowId,
|
|
2088
|
+
orgId: targetOrgId
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2091
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
2092
|
+
context.updateQuietly(rowId, column.name, null);
|
|
2093
|
+
} else {
|
|
2094
|
+
onChange(null);
|
|
2095
|
+
}
|
|
2096
|
+
if (targetTableMetaId && (context == null ? void 0 : context.executeAction) && !rowId.startsWith("temp_")) {
|
|
2097
|
+
await context.executeAction("UPDATE_RECORD", {
|
|
2098
|
+
tableId: targetTableMetaId,
|
|
2099
|
+
tableMetaId: targetTableMetaId,
|
|
2100
|
+
recordId: rowId,
|
|
2101
|
+
orgId: targetOrgId,
|
|
2102
|
+
data: { [column.name]: null }
|
|
2103
|
+
});
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
if (value && value.synced && value.url) {
|
|
2107
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1.5 h-8 px-2 group whitespace-nowrap overflow-hidden max-w-full", children: [
|
|
2108
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: value.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate text-xs whitespace-nowrap", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" }),
|
|
2109
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2110
|
+
"button",
|
|
2111
|
+
{
|
|
2112
|
+
type: "button",
|
|
2113
|
+
onClick: handleUnlink,
|
|
2114
|
+
className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1 shrink-0",
|
|
2115
|
+
title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
|
|
2116
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
|
|
2117
|
+
}
|
|
2118
|
+
)
|
|
2119
|
+
] });
|
|
2120
|
+
}
|
|
2121
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center h-8 px-2 whitespace-nowrap overflow-hidden max-w-full", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2122
|
+
"button",
|
|
2123
|
+
{
|
|
2124
|
+
type: "button",
|
|
2125
|
+
onClick: handleSync,
|
|
2126
|
+
disabled: isSyncing,
|
|
2127
|
+
className: "inline-flex items-center gap-1.5 px-2.5 py-1 bg-blue-50 text-blue-600 hover:bg-blue-100 border border-blue-200 rounded-md text-xs font-medium transition-colors whitespace-nowrap shrink-0 disabled:opacity-50 cursor-pointer max-w-full overflow-hidden",
|
|
2128
|
+
children: [
|
|
2129
|
+
isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { className: "w-3.5 h-3.5 animate-spin shrink-0", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2130
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
2131
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
|
|
2132
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "whitespace-nowrap truncate", children: "\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC" })
|
|
2134
|
+
]
|
|
2135
|
+
}
|
|
2136
|
+
) });
|
|
2137
|
+
},
|
|
2138
|
+
DEFAULT: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2139
|
+
"input",
|
|
2140
|
+
{
|
|
2141
|
+
type: "text",
|
|
2142
|
+
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
2143
|
+
value: value !== void 0 && value !== null ? String(value) : "",
|
|
2144
|
+
onChange: (e) => onChange(e.target.value)
|
|
2145
|
+
}
|
|
2146
|
+
),
|
|
2147
|
+
SUB_TABLE: ({ value, column }) => {
|
|
2148
|
+
var _a, _b, _c;
|
|
2149
|
+
if (!Array.isArray(value)) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
|
|
2150
|
+
const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
|
|
2151
|
+
if (selected.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
|
|
2152
|
+
const displayFields = ((_a = column.config) == null ? void 0 : _a.subTableDisplayFields) || [];
|
|
2153
|
+
const isWhatsApp = ((_b = column.config) == null ? void 0 : _b.actionType) === "WHATSAPP";
|
|
2154
|
+
const actionPhoneCol = (_c = column.config) == null ? void 0 : _c.actionPhoneColumn;
|
|
2155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "px-1.5 py-1 flex flex-nowrap items-center gap-1 h-full overflow-hidden max-w-full", children: selected.map((entry, idx) => {
|
|
2156
|
+
var _a2, _b2;
|
|
2157
|
+
let label = "";
|
|
2158
|
+
if (entry._resolvedData) {
|
|
2159
|
+
if (displayFields.length > 0) {
|
|
2160
|
+
label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
|
|
2161
|
+
} else {
|
|
2162
|
+
const firstField = Object.keys(entry._resolvedData).find((k) => k !== "_id");
|
|
2163
|
+
if (firstField) label = String(entry._resolvedData[firstField] || "");
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
if (!label) label = ((_a2 = entry.recordId) == null ? void 0 : _a2.slice(-6)) || "...";
|
|
2167
|
+
if (isWhatsApp) {
|
|
2168
|
+
const rawPhone = actionPhoneCol ? (_b2 = entry._resolvedData) == null ? void 0 : _b2[actionPhoneCol] : null;
|
|
2169
|
+
const phone = rawPhone ? String(rawPhone).trim() : null;
|
|
2170
|
+
if (phone) {
|
|
2171
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2172
|
+
"button",
|
|
2173
|
+
{
|
|
2174
|
+
type: "button",
|
|
2175
|
+
onClick: (e) => {
|
|
2176
|
+
e.stopPropagation();
|
|
2177
|
+
openWhatsAppChat(phone);
|
|
2178
|
+
},
|
|
2179
|
+
className: "inline-flex items-center gap-1 px-1.5 py-0.5 bg-emerald-50 hover:bg-emerald-100 text-emerald-800 border border-emerald-300 hover:border-emerald-400 rounded-full text-xs font-medium max-w-full truncate cursor-pointer transition-colors shadow-xs shrink",
|
|
2180
|
+
title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
|
|
2181
|
+
children: [
|
|
2182
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "w-3 h-3 text-emerald-600 shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) }),
|
|
2183
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", children: label })
|
|
2184
|
+
]
|
|
2185
|
+
},
|
|
2186
|
+
entry.recordId || idx
|
|
2187
|
+
);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2191
|
+
"span",
|
|
2192
|
+
{
|
|
2193
|
+
className: "inline-flex items-center px-1.5 py-0.5 bg-amber-50 text-amber-800 border border-amber-200 rounded-full text-xs font-medium max-w-full truncate shrink",
|
|
2194
|
+
title: label,
|
|
2195
|
+
children: label
|
|
2196
|
+
},
|
|
2197
|
+
entry.recordId || idx
|
|
2198
|
+
);
|
|
2199
|
+
}) });
|
|
2200
|
+
}
|
|
2201
|
+
};
|
|
2202
|
+
|
|
2203
|
+
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
2204
|
+
var import_react11 = require("react");
|
|
2205
|
+
var import_shared = require("@universe-platform/shared");
|
|
2206
|
+
|
|
2207
|
+
// src/utils/phone.ts
|
|
2208
|
+
function sanitizePhoneNumber(phone) {
|
|
2209
|
+
if (!phone) return "";
|
|
2210
|
+
const trimmed = phone.trim();
|
|
2211
|
+
const hasLeadingPlus = trimmed.startsWith("+");
|
|
2212
|
+
const digitsOnly = trimmed.replace(/\D/g, "");
|
|
2213
|
+
return hasLeadingPlus ? `+${digitsOnly}` : digitsOnly;
|
|
2214
|
+
}
|
|
2215
|
+
function isValidPhoneNumber(phone) {
|
|
2216
|
+
if (!phone) return false;
|
|
2217
|
+
const cleaned = sanitizePhoneNumber(phone);
|
|
2218
|
+
return /^\+?[0-9]{9,15}$/.test(cleaned);
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
// src/components/TableBlock/useColumnResize.ts
|
|
2222
|
+
var import_react9 = require("react");
|
|
2223
|
+
function useColumnResize({
|
|
2224
|
+
storageKey,
|
|
2225
|
+
defaultWidth = 200,
|
|
2226
|
+
minWidth = 60,
|
|
2227
|
+
maxWidth = 500,
|
|
2228
|
+
getMinColWidth
|
|
2229
|
+
}) {
|
|
2230
|
+
const [columnWidths, setColumnWidths] = (0, import_react9.useState)({});
|
|
2231
|
+
const [resizingCol, setResizingCol] = (0, import_react9.useState)(null);
|
|
2232
|
+
(0, import_react9.useEffect)(() => {
|
|
2233
|
+
if (typeof window === "undefined" || !storageKey) return;
|
|
2234
|
+
try {
|
|
2235
|
+
const saved = localStorage.getItem(storageKey);
|
|
2236
|
+
if (saved) {
|
|
2237
|
+
setColumnWidths(JSON.parse(saved));
|
|
2238
|
+
}
|
|
2239
|
+
} catch (e) {
|
|
2240
|
+
console.error(`Failed to load column widths for key "${storageKey}":`, e);
|
|
2241
|
+
}
|
|
2242
|
+
}, [storageKey]);
|
|
2243
|
+
(0, import_react9.useEffect)(() => {
|
|
2244
|
+
if (!resizingCol) return;
|
|
2245
|
+
const handleMouseMove = (e) => {
|
|
2246
|
+
const diffX = resizingCol.startX - e.clientX;
|
|
2247
|
+
const colMin = resizingCol.minWidth || minWidth;
|
|
2248
|
+
const newWidth = Math.max(colMin, Math.min(maxWidth, resizingCol.startWidth + diffX));
|
|
2249
|
+
setColumnWidths((prev) => __spreadProps(__spreadValues({}, prev), { [resizingCol.name]: newWidth }));
|
|
2250
|
+
};
|
|
2251
|
+
const handleMouseUp = () => {
|
|
2252
|
+
setResizingCol(null);
|
|
2253
|
+
setColumnWidths((prev) => {
|
|
2254
|
+
if (typeof window !== "undefined" && storageKey) {
|
|
2255
|
+
try {
|
|
2256
|
+
localStorage.setItem(storageKey, JSON.stringify(prev));
|
|
2257
|
+
} catch (e) {
|
|
2258
|
+
console.error(`Failed to save column widths for key "${storageKey}":`, e);
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
return prev;
|
|
2262
|
+
});
|
|
2263
|
+
};
|
|
2264
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
2265
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
2266
|
+
return () => {
|
|
2267
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
2268
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
2269
|
+
};
|
|
2270
|
+
}, [resizingCol, storageKey, minWidth, maxWidth]);
|
|
2271
|
+
const startResize = (0, import_react9.useCallback)(
|
|
2272
|
+
(colName, currentWidth, clientX, customMinWidth) => {
|
|
2273
|
+
const colMin = customMinWidth != null ? customMinWidth : getMinColWidth ? getMinColWidth(colName) : minWidth;
|
|
2274
|
+
setResizingCol({
|
|
2275
|
+
name: colName,
|
|
2276
|
+
startWidth: currentWidth,
|
|
2277
|
+
startX: clientX,
|
|
2278
|
+
minWidth: colMin
|
|
2279
|
+
});
|
|
2280
|
+
},
|
|
2281
|
+
[getMinColWidth, minWidth]
|
|
2282
|
+
);
|
|
2283
|
+
const getWidth = (0, import_react9.useCallback)(
|
|
2284
|
+
(colName, fallback) => {
|
|
2285
|
+
const colMin = getMinColWidth ? getMinColWidth(colName) : minWidth;
|
|
2286
|
+
const saved = columnWidths[colName] || fallback || defaultWidth;
|
|
2287
|
+
return Math.max(colMin, saved);
|
|
2288
|
+
},
|
|
2289
|
+
[columnWidths, defaultWidth, getMinColWidth, minWidth]
|
|
2290
|
+
);
|
|
2291
|
+
return {
|
|
2292
|
+
columnWidths,
|
|
2293
|
+
setColumnWidths,
|
|
2294
|
+
resizingCol,
|
|
2295
|
+
startResize,
|
|
2296
|
+
getWidth,
|
|
2297
|
+
minWidth
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
// src/components/TableBlock/useColumnReorder.ts
|
|
2302
|
+
var import_react10 = require("react");
|
|
2303
|
+
function useColumnReorder({
|
|
2304
|
+
onReorder,
|
|
2305
|
+
disabled = false
|
|
2306
|
+
}) {
|
|
2307
|
+
const [draggedColName, setDraggedColName] = (0, import_react10.useState)(null);
|
|
2308
|
+
const [dragOverColName, setDragOverColName] = (0, import_react10.useState)(null);
|
|
2309
|
+
const getHeaderDragProps = (0, import_react10.useCallback)(
|
|
2310
|
+
(colName) => {
|
|
2311
|
+
if (disabled) {
|
|
2312
|
+
return {
|
|
2313
|
+
draggable: false
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
return {
|
|
2317
|
+
draggable: true,
|
|
2318
|
+
onDragStart: (e) => {
|
|
2319
|
+
e.dataTransfer.setData("text/plain", colName);
|
|
2320
|
+
e.dataTransfer.effectAllowed = "move";
|
|
2321
|
+
setDraggedColName(colName);
|
|
2322
|
+
},
|
|
2323
|
+
onDragOver: (e) => {
|
|
2324
|
+
e.preventDefault();
|
|
2325
|
+
e.dataTransfer.dropEffect = "move";
|
|
2326
|
+
if (dragOverColName !== colName) {
|
|
2327
|
+
setDragOverColName(colName);
|
|
2328
|
+
}
|
|
2329
|
+
},
|
|
2330
|
+
onDragLeave: () => {
|
|
2331
|
+
if (dragOverColName === colName) {
|
|
2332
|
+
setDragOverColName(null);
|
|
2333
|
+
}
|
|
2334
|
+
},
|
|
2335
|
+
onDrop: (e) => {
|
|
2336
|
+
e.preventDefault();
|
|
2337
|
+
if (draggedColName && draggedColName !== colName) {
|
|
2338
|
+
onReorder(draggedColName, colName);
|
|
2339
|
+
}
|
|
2340
|
+
setDraggedColName(null);
|
|
2341
|
+
setDragOverColName(null);
|
|
2342
|
+
},
|
|
2343
|
+
onDragEnd: () => {
|
|
2344
|
+
setDraggedColName(null);
|
|
2345
|
+
setDragOverColName(null);
|
|
2346
|
+
}
|
|
2347
|
+
};
|
|
2348
|
+
},
|
|
2349
|
+
[disabled, draggedColName, dragOverColName, onReorder]
|
|
2350
|
+
);
|
|
2351
|
+
const isDragging = (0, import_react10.useCallback)((colName) => draggedColName === colName, [draggedColName]);
|
|
2352
|
+
const isDragOver = (0, import_react10.useCallback)((colName) => dragOverColName === colName, [dragOverColName]);
|
|
2353
|
+
return {
|
|
2354
|
+
draggedColName,
|
|
2355
|
+
dragOverColName,
|
|
2356
|
+
isDragging,
|
|
2357
|
+
isDragOver,
|
|
2358
|
+
getHeaderDragProps
|
|
2359
|
+
};
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
// src/components/TableBlock/columnTitleUtils.tsx
|
|
2363
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2364
|
+
var canvas = null;
|
|
2365
|
+
function measureTextWidth(text, font = '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif') {
|
|
2366
|
+
if (typeof document === "undefined") return text.length * 9;
|
|
2367
|
+
if (!canvas) {
|
|
2368
|
+
canvas = document.createElement("canvas");
|
|
2369
|
+
}
|
|
2370
|
+
const ctx = canvas.getContext("2d");
|
|
2371
|
+
if (!ctx) return text.length * 9;
|
|
2372
|
+
ctx.font = font;
|
|
2373
|
+
return ctx.measureText(text).width;
|
|
2374
|
+
}
|
|
2375
|
+
function splitHeaderTitle(name) {
|
|
2376
|
+
if (!name) return { isSingleWord: true, line1: "" };
|
|
2377
|
+
const words = name.trim().split(/\s+/).filter(Boolean);
|
|
2378
|
+
if (words.length <= 1) {
|
|
2379
|
+
return { isSingleWord: true, line1: words[0] || "" };
|
|
2380
|
+
}
|
|
2381
|
+
if (words.length === 2) {
|
|
2382
|
+
return { isSingleWord: false, line1: words[0], line2: words[1] };
|
|
2383
|
+
}
|
|
2384
|
+
let bestSplit = 1;
|
|
2385
|
+
let minDiff = Infinity;
|
|
2386
|
+
for (let i = 1; i < words.length; i++) {
|
|
2387
|
+
const l1 = words.slice(0, i).join(" ");
|
|
2388
|
+
const l2 = words.slice(i).join(" ");
|
|
2389
|
+
const diff = Math.abs(l1.length - l2.length);
|
|
2390
|
+
if (diff < minDiff) {
|
|
2391
|
+
minDiff = diff;
|
|
2392
|
+
bestSplit = i;
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
return {
|
|
2396
|
+
isSingleWord: false,
|
|
2397
|
+
line1: words.slice(0, bestSplit).join(" "),
|
|
2398
|
+
line2: words.slice(bestSplit).join(" ")
|
|
2399
|
+
};
|
|
2400
|
+
}
|
|
2401
|
+
function calculateMinColumnWidth(name, isSubTable = false, colType) {
|
|
2402
|
+
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';
|
|
2403
|
+
const chromeWidth = isSubTable ? 44 : 52;
|
|
2404
|
+
let baseMin = isSubTable ? 50 : 60;
|
|
2405
|
+
if ((colType == null ? void 0 : colType.toUpperCase()) === "GOOGLE_CONTACT") {
|
|
2406
|
+
baseMin = isSubTable ? 110 : 120;
|
|
2407
|
+
}
|
|
2408
|
+
if (!name) return baseMin;
|
|
2409
|
+
const { isSingleWord, line1, line2 } = splitHeaderTitle(name);
|
|
2410
|
+
if (isSingleWord) {
|
|
2411
|
+
const wordWidth = measureTextWidth(line1, font);
|
|
2412
|
+
return Math.max(baseMin, Math.ceil(wordWidth + chromeWidth));
|
|
2413
|
+
}
|
|
2414
|
+
const w1 = measureTextWidth(line1, font);
|
|
2415
|
+
const w2 = line2 ? measureTextWidth(line2, font) : 0;
|
|
2416
|
+
const maxLine = Math.max(w1, w2);
|
|
2417
|
+
return Math.max(baseMin, Math.ceil(maxLine + chromeWidth));
|
|
2418
|
+
}
|
|
2419
|
+
function ColumnHeaderTitle({ name, width, isSubTable = false }) {
|
|
2420
|
+
const { isSingleWord, line1, line2 } = splitHeaderTitle(name);
|
|
2421
|
+
if (isSingleWord || !line2) {
|
|
2422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children: line1 });
|
|
2423
|
+
}
|
|
2424
|
+
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';
|
|
2425
|
+
const chromeWidth = isSubTable ? 44 : 52;
|
|
2426
|
+
const fullTitleWidth = measureTextWidth(name, font) + chromeWidth;
|
|
2427
|
+
if (width !== void 0 && width >= fullTitleWidth) {
|
|
2428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children: name });
|
|
2429
|
+
}
|
|
2430
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex flex-col justify-center leading-tight select-none overflow-hidden text-right flex-1", title: name, children: [
|
|
2431
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap block", children: line1 }),
|
|
2432
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap block", children: line2 })
|
|
2433
|
+
] });
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
2437
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2438
|
+
function formatConflictCellValue(rawVal, colDef, relationOptionsMap) {
|
|
2439
|
+
var _a, _b, _c;
|
|
2440
|
+
if (rawVal === void 0 || rawVal === null || rawVal === "") {
|
|
2441
|
+
return "-";
|
|
2442
|
+
}
|
|
2443
|
+
const colType = (_a = colDef == null ? void 0 : colDef.type) == null ? void 0 : _a.toUpperCase();
|
|
2444
|
+
if (typeof rawVal === "boolean" || colType === "BOOLEAN") {
|
|
2445
|
+
return rawVal ? "\u05DB\u05DF" : "\u05DC\u05D0";
|
|
2446
|
+
}
|
|
2447
|
+
if (colType === "GOOGLE_CONTACT" || typeof rawVal === "object" && rawVal !== null && ("resourceName" in rawVal || "synced" in rawVal)) {
|
|
2448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-violet-50 text-violet-700 border border-violet-200", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" });
|
|
2449
|
+
}
|
|
2450
|
+
if (colType === "GOOGLE_DRIVE_FILE" || typeof rawVal === "object" && rawVal !== null && ("fileId" in rawVal || "fileUrl" in rawVal || "fileName" in rawVal)) {
|
|
2451
|
+
const fileName = rawVal == null ? void 0 : rawVal.fileName;
|
|
2452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-rose-50 text-rose-700 border border-rose-200 truncate max-w-[150px]", title: fileName || "\u05E7\u05D5\u05D1\u05E5 \u05DE\u05E6\u05D5\u05E8\u05E3", children: fileName ? String(fileName) : "\u05E7\u05D5\u05D1\u05E5 \u05DE\u05E6\u05D5\u05E8\u05E3" });
|
|
2453
|
+
}
|
|
2454
|
+
if (colType === "LINK" || typeof rawVal === "object" && rawVal !== null && ("url" in rawVal || "label" in rawVal)) {
|
|
2455
|
+
const text = (rawVal == null ? void 0 : rawVal.label) || (rawVal == null ? void 0 : rawVal.url);
|
|
2456
|
+
return text ? String(text) : "-";
|
|
2457
|
+
}
|
|
2458
|
+
if (colType === "SUB_TABLE" || Array.isArray(rawVal) && rawVal.length > 0 && typeof rawVal[0] === "object" && ("recordId" in rawVal[0] || "id" in rawVal[0])) {
|
|
2459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-amber-50 text-amber-700 border border-amber-200", children: [
|
|
2460
|
+
rawVal.length,
|
|
2461
|
+
" \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
|
|
2462
|
+
] });
|
|
2463
|
+
}
|
|
2464
|
+
if (colType === "RELATION") {
|
|
2465
|
+
if (Array.isArray(rawVal)) {
|
|
2466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-indigo-50 text-indigo-700 border border-indigo-200", children: [
|
|
2467
|
+
rawVal.length,
|
|
2468
|
+
" \u05DE\u05E7\u05D5\u05E9\u05E8\u05D9\u05DD"
|
|
2469
|
+
] });
|
|
2470
|
+
}
|
|
2471
|
+
const colOpts = (colDef == null ? void 0 : colDef.name) && relationOptionsMap ? relationOptionsMap[colDef.name] : void 0;
|
|
2472
|
+
if (Array.isArray(colOpts)) {
|
|
2473
|
+
const opt = colOpts.find((o) => String(o.id) === String(rawVal));
|
|
2474
|
+
if (opt) {
|
|
2475
|
+
const displayField = (_b = colDef == null ? void 0 : colDef.config) == null ? void 0 : _b.displayField;
|
|
2476
|
+
const disp = opt._displayLabel || displayField && ((_c = opt.data) == null ? void 0 : _c[displayField]) || (opt.label !== opt.id ? opt.label : "");
|
|
2477
|
+
if (disp && String(disp).trim() !== "" && !/^[a-f\d]{24}$/i.test(String(disp))) {
|
|
2478
|
+
return String(disp);
|
|
2479
|
+
}
|
|
1085
2480
|
}
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
if (!emailHint && (value == null ? void 0 : value.url)) {
|
|
1092
|
-
try {
|
|
1093
|
-
const parsed = new URL(value.url);
|
|
1094
|
-
emailHint = parsed.searchParams.get("authuser") || void 0;
|
|
1095
|
-
} catch (e) {
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
const auth = await requestGisToken(emailHint);
|
|
1099
|
-
accessToken = auth.accessToken;
|
|
1100
|
-
} catch (err) {
|
|
1101
|
-
console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
|
|
2481
|
+
}
|
|
2482
|
+
if (typeof rawVal === "object" && rawVal !== null) {
|
|
2483
|
+
const relDisplay = rawVal.title || rawVal.name || rawVal.label;
|
|
2484
|
+
if (relDisplay && !/^[a-f\d]{24}$/i.test(String(relDisplay))) {
|
|
2485
|
+
return String(relDisplay);
|
|
1102
2486
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
2487
|
+
}
|
|
2488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-indigo-50 text-indigo-700 border border-indigo-200", children: "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05DE\u05E7\u05D5\u05E9\u05E8\u05EA" });
|
|
2489
|
+
}
|
|
2490
|
+
if (Array.isArray(rawVal)) {
|
|
2491
|
+
const allPrimitives = rawVal.every((v) => typeof v !== "object");
|
|
2492
|
+
if (allPrimitives) {
|
|
2493
|
+
return rawVal.join(", ") || "-";
|
|
2494
|
+
}
|
|
2495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-slate-100 text-slate-700 border border-slate-200", children: [
|
|
2496
|
+
rawVal.length,
|
|
2497
|
+
" \u05E4\u05E8\u05D9\u05D8\u05D9\u05DD"
|
|
2498
|
+
] });
|
|
2499
|
+
}
|
|
2500
|
+
if (typeof rawVal === "object" && rawVal !== null) {
|
|
2501
|
+
return "-";
|
|
2502
|
+
}
|
|
2503
|
+
if ((colDef == null ? void 0 : colDef.type) && !(0, import_shared.isTextRepresentable)(colDef.type)) {
|
|
2504
|
+
return "-";
|
|
2505
|
+
}
|
|
2506
|
+
return String(rawVal);
|
|
2507
|
+
}
|
|
2508
|
+
function validateCellValue(val, col) {
|
|
2509
|
+
var _a;
|
|
2510
|
+
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
2511
|
+
const isEmpty = val === void 0 || val === null || typeof val === "string" && val.trim() === "";
|
|
2512
|
+
if (col.isRequired && isEmpty) {
|
|
2513
|
+
return {
|
|
2514
|
+
isValid: false,
|
|
2515
|
+
error: `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05E9\u05D3\u05D4 '${col.name}' \u05D4\u05D9\u05E0\u05D5 \u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 \u05D5\u05DC\u05D0 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05E9\u05D0\u05E8 \u05E8\u05D9\u05E7.`
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2518
|
+
if (isEmpty) {
|
|
2519
|
+
return { isValid: true };
|
|
2520
|
+
}
|
|
2521
|
+
if (colType === "PHONE") {
|
|
2522
|
+
const strVal = String(val).trim();
|
|
2523
|
+
if (!isValidPhoneNumber(strVal)) {
|
|
2524
|
+
return {
|
|
2525
|
+
isValid: false,
|
|
2526
|
+
error: `\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`
|
|
2527
|
+
};
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
if (colType === "NUMBER" || colType === "CURRENCY") {
|
|
2531
|
+
if (typeof val === "string" && isNaN(Number(val))) {
|
|
2532
|
+
return {
|
|
2533
|
+
isValid: false,
|
|
2534
|
+
error: `\u05D4\u05E2\u05E8\u05DA \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D7\u05D9\u05D9\u05D1 \u05DC\u05D4\u05D9\u05D5\u05EA \u05DE\u05E1\u05E4\u05E8 \u05EA\u05E7\u05D9\u05DF.`
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
return { isValid: true };
|
|
2539
|
+
}
|
|
2540
|
+
function SubTableCell({
|
|
2541
|
+
record,
|
|
2542
|
+
column,
|
|
2543
|
+
targetSchema,
|
|
2544
|
+
referencedTableId,
|
|
2545
|
+
parentRowId,
|
|
2546
|
+
context,
|
|
2547
|
+
relationOptions,
|
|
2548
|
+
setRelationOptions,
|
|
2549
|
+
refetchRelation,
|
|
2550
|
+
onCommit,
|
|
2551
|
+
onQuietUpdate,
|
|
2552
|
+
width
|
|
2553
|
+
}) {
|
|
2554
|
+
var _a, _b, _c, _d, _e;
|
|
2555
|
+
const colType = ((_a = column.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
2556
|
+
const isContact = colType === "GOOGLE_CONTACT";
|
|
2557
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
2558
|
+
const serverValue = (_b = record.data[column.name]) != null ? _b : colType === "BOOLEAN" ? false : "";
|
|
2559
|
+
const [draftValue, setDraftValue] = (0, import_react11.useState)(serverValue);
|
|
2560
|
+
const [isDirty, setIsDirty] = (0, import_react11.useState)(false);
|
|
2561
|
+
const [validationError, setValidationError] = (0, import_react11.useState)(null);
|
|
2562
|
+
const cellRef = (0, import_react11.useRef)(null);
|
|
2563
|
+
const draftRef = (0, import_react11.useRef)(draftValue);
|
|
2564
|
+
const isDirtyRef = (0, import_react11.useRef)(isDirty);
|
|
2565
|
+
const serverValueRef = (0, import_react11.useRef)(serverValue);
|
|
2566
|
+
const recordIdRef = (0, import_react11.useRef)(record.id);
|
|
2567
|
+
const columnRef = (0, import_react11.useRef)(column);
|
|
2568
|
+
const onCommitRef = (0, import_react11.useRef)(onCommit);
|
|
2569
|
+
const isCommittingRef = (0, import_react11.useRef)(false);
|
|
2570
|
+
const lastFailedValRef = (0, import_react11.useRef)(void 0);
|
|
2571
|
+
const { addToast } = useToast();
|
|
2572
|
+
draftRef.current = draftValue;
|
|
2573
|
+
isDirtyRef.current = isDirty;
|
|
2574
|
+
serverValueRef.current = serverValue;
|
|
2575
|
+
recordIdRef.current = record.id;
|
|
2576
|
+
columnRef.current = column;
|
|
2577
|
+
onCommitRef.current = onCommit;
|
|
2578
|
+
(0, import_react11.useEffect)(() => {
|
|
2579
|
+
if (!isDirtyRef.current) {
|
|
2580
|
+
setDraftValue(serverValue);
|
|
2581
|
+
draftRef.current = serverValue;
|
|
2582
|
+
setValidationError(null);
|
|
2583
|
+
lastFailedValRef.current = void 0;
|
|
2584
|
+
}
|
|
2585
|
+
}, [serverValue]);
|
|
2586
|
+
const commit = (0, import_react11.useCallback)(async (valToCommit) => {
|
|
2587
|
+
if (isCommittingRef.current) return false;
|
|
2588
|
+
if (!isDirtyRef.current) return true;
|
|
2589
|
+
if (valToCommit === serverValueRef.current) {
|
|
2590
|
+
setIsDirty(false);
|
|
2591
|
+
isDirtyRef.current = false;
|
|
2592
|
+
setValidationError(null);
|
|
2593
|
+
lastFailedValRef.current = void 0;
|
|
2594
|
+
return true;
|
|
2595
|
+
}
|
|
2596
|
+
const valRes = validateCellValue(valToCommit, columnRef.current);
|
|
2597
|
+
if (!valRes.isValid) {
|
|
2598
|
+
const errorMsg = valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA";
|
|
2599
|
+
setValidationError(errorMsg);
|
|
2600
|
+
if (lastFailedValRef.current !== valToCommit) {
|
|
2601
|
+
addToast({ type: "error", message: errorMsg });
|
|
2602
|
+
lastFailedValRef.current = valToCommit;
|
|
1108
2603
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
2604
|
+
return false;
|
|
2605
|
+
}
|
|
2606
|
+
try {
|
|
2607
|
+
isCommittingRef.current = true;
|
|
2608
|
+
const success = await onCommitRef.current(recordIdRef.current, columnRef.current.name, valToCommit);
|
|
2609
|
+
if (success) {
|
|
2610
|
+
setIsDirty(false);
|
|
2611
|
+
isDirtyRef.current = false;
|
|
2612
|
+
serverValueRef.current = valToCommit;
|
|
2613
|
+
setValidationError(null);
|
|
2614
|
+
lastFailedValRef.current = void 0;
|
|
2615
|
+
return true;
|
|
1111
2616
|
} else {
|
|
1112
|
-
|
|
2617
|
+
setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
|
|
2618
|
+
return false;
|
|
1113
2619
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
2620
|
+
} catch (e) {
|
|
2621
|
+
setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
|
|
2622
|
+
return false;
|
|
2623
|
+
} finally {
|
|
2624
|
+
isCommittingRef.current = false;
|
|
2625
|
+
}
|
|
2626
|
+
}, [addToast]);
|
|
2627
|
+
const discard = (0, import_react11.useCallback)(() => {
|
|
2628
|
+
setDraftValue(serverValueRef.current);
|
|
2629
|
+
draftRef.current = serverValueRef.current;
|
|
2630
|
+
setIsDirty(false);
|
|
2631
|
+
isDirtyRef.current = false;
|
|
2632
|
+
setValidationError(null);
|
|
2633
|
+
lastFailedValRef.current = void 0;
|
|
2634
|
+
}, []);
|
|
2635
|
+
(0, import_react11.useEffect)(() => {
|
|
2636
|
+
return () => {
|
|
2637
|
+
if (isDirtyRef.current && !isCommittingRef.current) {
|
|
2638
|
+
const val = draftRef.current;
|
|
2639
|
+
const orig = serverValueRef.current;
|
|
2640
|
+
if (val !== orig) {
|
|
2641
|
+
const valRes = validateCellValue(val, columnRef.current);
|
|
2642
|
+
if (valRes.isValid) {
|
|
2643
|
+
onCommitRef.current(recordIdRef.current, columnRef.current.name, val);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
1120
2646
|
}
|
|
1121
2647
|
};
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
|
|
1132
|
-
}
|
|
1133
|
-
)
|
|
1134
|
-
] });
|
|
2648
|
+
}, []);
|
|
2649
|
+
const handleChange = (newVal) => {
|
|
2650
|
+
setDraftValue(newVal);
|
|
2651
|
+
draftRef.current = newVal;
|
|
2652
|
+
setIsDirty(true);
|
|
2653
|
+
isDirtyRef.current = true;
|
|
2654
|
+
if (validationError) {
|
|
2655
|
+
setValidationError(null);
|
|
2656
|
+
lastFailedValRef.current = void 0;
|
|
1135
2657
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
{
|
|
1139
|
-
onClick: handleSync,
|
|
1140
|
-
disabled: isSyncing,
|
|
1141
|
-
className: "flex items-center gap-1.5 px-3 py-1 bg-blue-50 text-blue-600 hover:bg-blue-100 border border-blue-200 rounded-md text-xs font-medium transition-colors disabled:opacity-50",
|
|
1142
|
-
children: [
|
|
1143
|
-
isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "w-3.5 h-3.5 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [
|
|
1144
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
1145
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
|
|
1146
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
|
|
1147
|
-
"\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC"
|
|
1148
|
-
]
|
|
1149
|
-
}
|
|
1150
|
-
) });
|
|
1151
|
-
},
|
|
1152
|
-
DEFAULT: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1153
|
-
"input",
|
|
1154
|
-
{
|
|
1155
|
-
type: "text",
|
|
1156
|
-
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
1157
|
-
value: value !== void 0 && value !== null ? String(value) : "",
|
|
1158
|
-
onChange: (e) => onChange(e.target.value)
|
|
2658
|
+
if (colType === "BOOLEAN" || colType === "GOOGLE_DRIVE_FILE") {
|
|
2659
|
+
commit(newVal);
|
|
1159
2660
|
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
if (
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
2661
|
+
};
|
|
2662
|
+
const handleBlur = (e) => {
|
|
2663
|
+
if (e.currentTarget.contains(e.relatedTarget)) {
|
|
2664
|
+
return;
|
|
2665
|
+
}
|
|
2666
|
+
if (isDirtyRef.current) {
|
|
2667
|
+
commit(draftRef.current);
|
|
2668
|
+
}
|
|
2669
|
+
};
|
|
2670
|
+
const handleKeyDown = (e) => {
|
|
2671
|
+
var _a2, _b2, _c2, _d2;
|
|
2672
|
+
if (e.key === "Enter") {
|
|
2673
|
+
e.preventDefault();
|
|
2674
|
+
if (isDirtyRef.current) {
|
|
2675
|
+
commit(draftRef.current);
|
|
1171
2676
|
}
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
2677
|
+
(_b2 = (_a2 = e.target) == null ? void 0 : _a2.blur) == null ? void 0 : _b2.call(_a2);
|
|
2678
|
+
} else if (e.key === "Escape") {
|
|
2679
|
+
e.preventDefault();
|
|
2680
|
+
discard();
|
|
2681
|
+
(_d2 = (_c2 = e.target) == null ? void 0 : _c2.blur) == null ? void 0 : _d2.call(_c2);
|
|
2682
|
+
}
|
|
2683
|
+
};
|
|
2684
|
+
const subTableMetaId = (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId;
|
|
2685
|
+
const parentTableId = (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId);
|
|
2686
|
+
const effectiveParentRecordId = parentRowId || ((_c = context == null ? void 0 : context.parentRecord) == null ? void 0 : _c.recordId) || ((_d = context == null ? void 0 : context.parentRecord) == null ? void 0 : _d.id) || (context == null ? void 0 : context.rowId);
|
|
2687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2688
|
+
"td",
|
|
2689
|
+
{
|
|
2690
|
+
ref: cellRef,
|
|
2691
|
+
onBlur: handleBlur,
|
|
2692
|
+
onKeyDown: handleKeyDown,
|
|
2693
|
+
title: validationError || void 0,
|
|
2694
|
+
style: width ? { width, minWidth: width, maxWidth: width } : void 0,
|
|
2695
|
+
className: `border border-slate-200 p-0 relative h-8 transition-colors ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"} ${validationError ? "border-rose-400 ring-1 ring-rose-400 bg-rose-50/20" : ""}`,
|
|
2696
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2697
|
+
InputComponent,
|
|
1175
2698
|
{
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
2699
|
+
value: draftValue,
|
|
2700
|
+
column,
|
|
2701
|
+
rowId: record.id,
|
|
2702
|
+
onChange: handleChange,
|
|
2703
|
+
context: __spreadProps(__spreadValues({}, context), {
|
|
2704
|
+
tableName: (targetSchema == null ? void 0 : targetSchema.name) || (targetSchema == null ? void 0 : targetSchema.tableName) || (targetSchema == null ? void 0 : targetSchema.title) || (targetSchema == null ? void 0 : targetSchema.id) || "Table",
|
|
2705
|
+
relationOptions,
|
|
2706
|
+
updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
|
|
2707
|
+
refetchRelation,
|
|
2708
|
+
parentTableId,
|
|
2709
|
+
parentRecord: {
|
|
2710
|
+
tableId: parentTableId,
|
|
2711
|
+
recordId: effectiveParentRecordId,
|
|
2712
|
+
id: effectiveParentRecordId,
|
|
2713
|
+
data: (context == null ? void 0 : context.rowData) || ((_e = context == null ? void 0 : context.parentRecord) == null ? void 0 : _e.data)
|
|
2714
|
+
},
|
|
2715
|
+
rowData: record.data,
|
|
2716
|
+
tableId: subTableMetaId,
|
|
2717
|
+
tableMetaId: subTableMetaId,
|
|
2718
|
+
recordId: record.id,
|
|
2719
|
+
orgId: context == null ? void 0 : context.orgId,
|
|
2720
|
+
updateQuietly: (rid, colName, val) => {
|
|
2721
|
+
if (onQuietUpdate) {
|
|
2722
|
+
onQuietUpdate(rid, colName, val);
|
|
2723
|
+
} else {
|
|
2724
|
+
onCommitRef.current(rid, colName, val);
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
})
|
|
2728
|
+
}
|
|
2729
|
+
)
|
|
2730
|
+
}
|
|
2731
|
+
);
|
|
2732
|
+
}
|
|
1189
2733
|
function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
1190
|
-
var _a;
|
|
2734
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1191
2735
|
const { addToast } = useToast();
|
|
1192
2736
|
const entries = Array.isArray(value) ? value : [];
|
|
1193
|
-
const [linkedRecords, setLinkedRecords] = (0,
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
const
|
|
1203
|
-
const
|
|
2737
|
+
const [linkedRecords, setLinkedRecords] = (0, import_react11.useState)(() => {
|
|
2738
|
+
const initial = [];
|
|
2739
|
+
for (const entry of entries) {
|
|
2740
|
+
if (entry.recordId && entry._resolvedData) {
|
|
2741
|
+
initial.push({ id: entry.recordId, data: entry._resolvedData });
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
return initial;
|
|
2745
|
+
});
|
|
2746
|
+
const [targetSchema, setTargetSchema] = (0, import_react11.useState)(null);
|
|
2747
|
+
const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
|
|
2748
|
+
const [isSearchOpen, setIsSearchOpen] = (0, import_react11.useState)(false);
|
|
2749
|
+
const [searchQuery, setSearchQuery] = (0, import_react11.useState)("");
|
|
2750
|
+
const [searchResults, setSearchResults] = (0, import_react11.useState)([]);
|
|
2751
|
+
const [isSearching, setIsSearching] = (0, import_react11.useState)(false);
|
|
2752
|
+
const [isCreating, setIsCreating] = (0, import_react11.useState)(false);
|
|
2753
|
+
const [newRecordData, setNewRecordData] = (0, import_react11.useState)({});
|
|
2754
|
+
const [conflictModalState, setConflictModalState] = (0, import_react11.useState)({
|
|
2755
|
+
isOpen: false,
|
|
2756
|
+
fieldName: "",
|
|
2757
|
+
matchingRecords: []
|
|
2758
|
+
});
|
|
2759
|
+
const searchRef = (0, import_react11.useRef)(null);
|
|
2760
|
+
const searchTimerRef = (0, import_react11.useRef)(null);
|
|
1204
2761
|
const executeAction = context == null ? void 0 : context.executeAction;
|
|
1205
|
-
const referencedTableId = column.referencedTableId;
|
|
1206
|
-
const fetchedIdsRef = (0,
|
|
1207
|
-
(0,
|
|
2762
|
+
const referencedTableId = ((_a = column.config) == null ? void 0 : _a.referencedTableId) || column.referencedTableId;
|
|
2763
|
+
const fetchedIdsRef = (0, import_react11.useRef)(/* @__PURE__ */ new Set());
|
|
2764
|
+
(0, import_react11.useEffect)(() => {
|
|
2765
|
+
if (entries.length > 0) {
|
|
2766
|
+
setLinkedRecords((prev) => {
|
|
2767
|
+
const existingIds = new Set(prev.map((r) => r.id));
|
|
2768
|
+
const toAdd = [];
|
|
2769
|
+
for (const entry of entries) {
|
|
2770
|
+
if (entry.recordId && entry._resolvedData && !existingIds.has(entry.recordId)) {
|
|
2771
|
+
toAdd.push({ id: entry.recordId, data: entry._resolvedData });
|
|
2772
|
+
existingIds.add(entry.recordId);
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
return toAdd.length > 0 ? [...prev, ...toAdd] : prev;
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
}, [entries]);
|
|
2779
|
+
(0, import_react11.useEffect)(() => {
|
|
1208
2780
|
if (!referencedTableId || !executeAction) {
|
|
1209
2781
|
setIsLoading(false);
|
|
1210
2782
|
return;
|
|
@@ -1231,7 +2803,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1231
2803
|
recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
|
|
1232
2804
|
}).finally(() => setIsLoading(false));
|
|
1233
2805
|
}, [referencedTableId, executeAction, entries, targetSchema]);
|
|
1234
|
-
(0,
|
|
2806
|
+
(0, import_react11.useEffect)(() => {
|
|
1235
2807
|
const handleClick = (e) => {
|
|
1236
2808
|
if (searchRef.current && !searchRef.current.contains(e.target)) {
|
|
1237
2809
|
setIsSearchOpen(false);
|
|
@@ -1240,7 +2812,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1240
2812
|
if (isSearchOpen) document.addEventListener("mousedown", handleClick);
|
|
1241
2813
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
1242
2814
|
}, [isSearchOpen]);
|
|
1243
|
-
const handleSearch = (0,
|
|
2815
|
+
const handleSearch = (0, import_react11.useCallback)((query) => {
|
|
1244
2816
|
setSearchQuery(query);
|
|
1245
2817
|
if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
|
|
1246
2818
|
if (!query.trim()) {
|
|
@@ -1266,24 +2838,79 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1266
2838
|
}
|
|
1267
2839
|
}, 300);
|
|
1268
2840
|
}, [executeAction, referencedTableId, entries]);
|
|
1269
|
-
const
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
2841
|
+
const [localColumnOrder, setLocalColumnOrder] = (0, import_react11.useState)(null);
|
|
2842
|
+
(0, import_react11.useEffect)(() => {
|
|
2843
|
+
setLocalColumnOrder(null);
|
|
2844
|
+
}, [column.name, (_b = column.config) == null ? void 0 : _b.subTableColumnOrder]);
|
|
2845
|
+
const rawTargetColumns = (0, import_react11.useMemo)(() => {
|
|
2846
|
+
return ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
|
|
2847
|
+
(c) => c.name !== "_id" && c.type !== "SUB_TABLE"
|
|
2848
|
+
);
|
|
2849
|
+
}, [targetSchema == null ? void 0 : targetSchema.columns]);
|
|
2850
|
+
const targetColumns = (0, import_react11.useMemo)(() => {
|
|
2851
|
+
var _a2;
|
|
2852
|
+
const activeOrder = localColumnOrder || ((_a2 = column.config) == null ? void 0 : _a2.subTableColumnOrder);
|
|
2853
|
+
if (!activeOrder || !Array.isArray(activeOrder) || activeOrder.length === 0) {
|
|
2854
|
+
return rawTargetColumns;
|
|
1273
2855
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
2856
|
+
const sorted = [...rawTargetColumns];
|
|
2857
|
+
sorted.sort((a, b) => {
|
|
2858
|
+
const idxA = activeOrder.indexOf(a.name);
|
|
2859
|
+
const idxB = activeOrder.indexOf(b.name);
|
|
2860
|
+
if (idxA === -1 && idxB === -1) return 0;
|
|
2861
|
+
if (idxA === -1) return 1;
|
|
2862
|
+
if (idxB === -1) return -1;
|
|
2863
|
+
return idxA - idxB;
|
|
2864
|
+
});
|
|
2865
|
+
return sorted;
|
|
2866
|
+
}, [rawTargetColumns, localColumnOrder, (_c = column.config) == null ? void 0 : _c.subTableColumnOrder]);
|
|
2867
|
+
const handleSubTableColumnReorder = async (draggedName, dropTargetName) => {
|
|
2868
|
+
if (draggedName === dropTargetName) return;
|
|
2869
|
+
const currentNames = targetColumns.map((c) => c.name);
|
|
2870
|
+
const fromIdx = currentNames.indexOf(draggedName);
|
|
2871
|
+
const toIdx = currentNames.indexOf(dropTargetName);
|
|
2872
|
+
if (fromIdx === -1 || toIdx === -1 || fromIdx === toIdx) return;
|
|
2873
|
+
const newOrder = [...currentNames];
|
|
2874
|
+
const [moved] = newOrder.splice(fromIdx, 1);
|
|
2875
|
+
newOrder.splice(toIdx, 0, moved);
|
|
2876
|
+
setLocalColumnOrder(newOrder);
|
|
2877
|
+
if (context == null ? void 0 : context.onUpdateColumnConfig) {
|
|
2878
|
+
try {
|
|
2879
|
+
await context.onUpdateColumnConfig(column.name, {
|
|
2880
|
+
subTableColumnOrder: newOrder
|
|
2881
|
+
});
|
|
2882
|
+
} catch (err) {
|
|
2883
|
+
console.error("[SubTableViewer] Failed to save sub-table column order:", err);
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
};
|
|
2887
|
+
const { draggedColName, dragOverColName, getHeaderDragProps } = useColumnReorder({
|
|
2888
|
+
onReorder: handleSubTableColumnReorder,
|
|
2889
|
+
disabled: isLoading
|
|
2890
|
+
});
|
|
2891
|
+
const targetTableId = (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId || column.name;
|
|
2892
|
+
const { columnWidths, startResize } = useColumnResize({
|
|
2893
|
+
storageKey: `table_sub_${targetTableId}_widths`,
|
|
2894
|
+
minWidth: 60,
|
|
2895
|
+
defaultWidth: 150,
|
|
2896
|
+
getMinColWidth: (colName) => {
|
|
2897
|
+
const col = targetColumns.find((c) => c.name === colName);
|
|
2898
|
+
return calculateMinColumnWidth(colName, true, col == null ? void 0 : col.type);
|
|
2899
|
+
}
|
|
2900
|
+
});
|
|
2901
|
+
const [relationOptions, setRelationOptions] = (0, import_react11.useState)({});
|
|
2902
|
+
(0, import_react11.useEffect)(() => {
|
|
2903
|
+
if (!executeAction || !(targetSchema == null ? void 0 : targetSchema.columns) || targetSchema.columns.length === 0) return;
|
|
2904
|
+
const relationCols = targetSchema.columns.filter((c) => {
|
|
2905
|
+
var _a2, _b2;
|
|
2906
|
+
return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION" && ((_b2 = c.config) == null ? void 0 : _b2.referencedTableId);
|
|
1281
2907
|
});
|
|
1282
2908
|
relationCols.forEach(async (col) => {
|
|
2909
|
+
var _a2, _b2;
|
|
1283
2910
|
try {
|
|
1284
2911
|
const options = await executeAction("FETCH_RELATION", {
|
|
1285
|
-
referencedTableId: col.referencedTableId,
|
|
1286
|
-
displayField: col.displayField
|
|
2912
|
+
referencedTableId: (_a2 = col.config) == null ? void 0 : _a2.referencedTableId,
|
|
2913
|
+
displayField: (_b2 = col.config) == null ? void 0 : _b2.displayField
|
|
1287
2914
|
});
|
|
1288
2915
|
if (options && Array.isArray(options)) {
|
|
1289
2916
|
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
@@ -1293,12 +2920,12 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1293
2920
|
}
|
|
1294
2921
|
});
|
|
1295
2922
|
}, [executeAction, targetColumns]);
|
|
1296
|
-
const refetchRelation = (0,
|
|
1297
|
-
var _a2;
|
|
2923
|
+
const refetchRelation = (0, import_react11.useCallback)(async (colName) => {
|
|
2924
|
+
var _a2, _b2, _c2;
|
|
1298
2925
|
const col = targetColumns.find((c) => c.name === colName);
|
|
1299
|
-
if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !col.referencedTableId || !executeAction) return;
|
|
2926
|
+
if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !((_b2 = col.config) == null ? void 0 : _b2.referencedTableId) || !executeAction) return;
|
|
1300
2927
|
try {
|
|
1301
|
-
const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
|
|
2928
|
+
const options = await executeAction("FETCH_RELATION", { referencedTableId: col.config.referencedTableId, displayField: (_c2 = col.config) == null ? void 0 : _c2.displayField });
|
|
1302
2929
|
if (options && Array.isArray(options)) {
|
|
1303
2930
|
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
1304
2931
|
}
|
|
@@ -1329,20 +2956,102 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1329
2956
|
}
|
|
1330
2957
|
}
|
|
1331
2958
|
};
|
|
1332
|
-
const
|
|
1333
|
-
|
|
1334
|
-
const
|
|
1335
|
-
const
|
|
1336
|
-
|
|
2959
|
+
const handleLinkRecords = (recordsToLink) => {
|
|
2960
|
+
if (!recordsToLink || recordsToLink.length === 0) return;
|
|
2961
|
+
const existingEntryIds = new Set(entries.map((e) => e.recordId));
|
|
2962
|
+
const newEntries = [];
|
|
2963
|
+
const newRecordsToAdd = [];
|
|
2964
|
+
for (const record of recordsToLink) {
|
|
2965
|
+
fetchedIdsRef.current.add(record.id);
|
|
2966
|
+
const resolvedData = __spreadValues({}, record.data || {});
|
|
2967
|
+
targetColumns.forEach((col) => {
|
|
2968
|
+
if ((resolvedData[col.name] === void 0 || resolvedData[col.name] === null) && record[col.name] !== void 0) {
|
|
2969
|
+
resolvedData[col.name] = record[col.name];
|
|
2970
|
+
}
|
|
2971
|
+
});
|
|
2972
|
+
if (!existingEntryIds.has(record.id)) {
|
|
2973
|
+
newEntries.push({
|
|
2974
|
+
recordId: record.id,
|
|
2975
|
+
isSelected: true,
|
|
2976
|
+
_resolvedData: resolvedData
|
|
2977
|
+
});
|
|
2978
|
+
existingEntryIds.add(record.id);
|
|
2979
|
+
}
|
|
2980
|
+
newRecordsToAdd.push({
|
|
2981
|
+
id: record.id,
|
|
2982
|
+
data: resolvedData
|
|
2983
|
+
});
|
|
2984
|
+
}
|
|
2985
|
+
const updatedEntries = [...entries, ...newEntries];
|
|
2986
|
+
updateParentLinkage(updatedEntries);
|
|
1337
2987
|
setLinkedRecords((prev) => {
|
|
1338
|
-
const
|
|
1339
|
-
|
|
1340
|
-
|
|
2988
|
+
const map = new Map(prev.map((r) => [r.id, r]));
|
|
2989
|
+
newRecordsToAdd.forEach((r) => {
|
|
2990
|
+
const existing = map.get(r.id);
|
|
2991
|
+
if (existing) {
|
|
2992
|
+
map.set(r.id, __spreadProps(__spreadValues({}, existing), {
|
|
2993
|
+
data: __spreadValues(__spreadValues({}, existing.data), r.data)
|
|
2994
|
+
}));
|
|
2995
|
+
} else {
|
|
2996
|
+
map.set(r.id, r);
|
|
2997
|
+
}
|
|
2998
|
+
});
|
|
2999
|
+
return Array.from(map.values());
|
|
1341
3000
|
});
|
|
1342
3001
|
setSearchQuery("");
|
|
1343
3002
|
setSearchResults([]);
|
|
1344
3003
|
setIsSearchOpen(false);
|
|
1345
3004
|
};
|
|
3005
|
+
const handleLinkRecord = (record) => {
|
|
3006
|
+
handleLinkRecords([record]);
|
|
3007
|
+
};
|
|
3008
|
+
const handleUniqueConflict = (conflictData) => {
|
|
3009
|
+
const rawMatching = Array.isArray(conflictData == null ? void 0 : conflictData.matchingRecords) ? conflictData.matchingRecords : [];
|
|
3010
|
+
const resolvedMatching = rawMatching.map((r) => {
|
|
3011
|
+
var _a2;
|
|
3012
|
+
const recordId = String(r.id || ((_a2 = r._id) == null ? void 0 : _a2.$oid) || r._id);
|
|
3013
|
+
let dataObj = {};
|
|
3014
|
+
if (r.data && typeof r.data === "object") {
|
|
3015
|
+
dataObj = __spreadValues({}, r.data);
|
|
3016
|
+
}
|
|
3017
|
+
targetColumns.forEach((col) => {
|
|
3018
|
+
if ((dataObj[col.name] === void 0 || dataObj[col.name] === null) && r[col.name] !== void 0) {
|
|
3019
|
+
dataObj[col.name] = r[col.name];
|
|
3020
|
+
}
|
|
3021
|
+
});
|
|
3022
|
+
return {
|
|
3023
|
+
id: recordId,
|
|
3024
|
+
data: dataObj
|
|
3025
|
+
};
|
|
3026
|
+
});
|
|
3027
|
+
setConflictModalState({
|
|
3028
|
+
isOpen: true,
|
|
3029
|
+
fieldName: (conflictData == null ? void 0 : conflictData.fieldName) || "",
|
|
3030
|
+
matchingRecords: resolvedMatching
|
|
3031
|
+
});
|
|
3032
|
+
};
|
|
3033
|
+
const handleCancelConflict = () => {
|
|
3034
|
+
setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
|
|
3035
|
+
};
|
|
3036
|
+
const handleConfirmLinkConflict = async () => {
|
|
3037
|
+
const { matchingRecords } = conflictModalState;
|
|
3038
|
+
if (matchingRecords && matchingRecords.length > 0) {
|
|
3039
|
+
handleLinkRecords(matchingRecords);
|
|
3040
|
+
setNewRecordData({});
|
|
3041
|
+
setIsCreating(false);
|
|
3042
|
+
setConflictModalState({
|
|
3043
|
+
isOpen: false,
|
|
3044
|
+
fieldName: "",
|
|
3045
|
+
matchingRecords: []
|
|
3046
|
+
});
|
|
3047
|
+
addToast({
|
|
3048
|
+
type: "success",
|
|
3049
|
+
message: "\u05D4\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D5\u05E9\u05E8\u05D4 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
3050
|
+
});
|
|
3051
|
+
} else {
|
|
3052
|
+
setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
|
|
3053
|
+
}
|
|
3054
|
+
};
|
|
1346
3055
|
const handleUnlinkRecord = (recordId) => {
|
|
1347
3056
|
const updated = entries.filter((e) => e.recordId !== recordId);
|
|
1348
3057
|
updateParentLinkage(updated);
|
|
@@ -1355,37 +3064,109 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1355
3064
|
);
|
|
1356
3065
|
updateParentLinkage(updated);
|
|
1357
3066
|
};
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
)
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
3067
|
+
const isMountedRef = (0, import_react11.useRef)(true);
|
|
3068
|
+
(0, import_react11.useEffect)(() => {
|
|
3069
|
+
isMountedRef.current = true;
|
|
3070
|
+
return () => {
|
|
3071
|
+
isMountedRef.current = false;
|
|
3072
|
+
};
|
|
3073
|
+
}, []);
|
|
3074
|
+
const handleCommitRecordCell = async (recordId, colName, value2) => {
|
|
3075
|
+
var _a2;
|
|
3076
|
+
const previousRecord = linkedRecords.find((r) => r.id === recordId);
|
|
3077
|
+
const previousValue = (_a2 = previousRecord == null ? void 0 : previousRecord.data) == null ? void 0 : _a2[colName];
|
|
3078
|
+
if (previousValue === value2) return true;
|
|
3079
|
+
const targetCol = targetColumns.find((c) => c.name === colName);
|
|
3080
|
+
const valRes = targetCol ? validateCellValue(value2, targetCol) : { isValid: true };
|
|
3081
|
+
if (!valRes.isValid) {
|
|
3082
|
+
addToast({
|
|
3083
|
+
type: "error",
|
|
3084
|
+
message: valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA"
|
|
3085
|
+
});
|
|
3086
|
+
return false;
|
|
1371
3087
|
}
|
|
1372
3088
|
if (executeAction && referencedTableId && !recordId.startsWith("temp_")) {
|
|
1373
3089
|
try {
|
|
1374
|
-
await executeAction("UPDATE_RECORD", {
|
|
3090
|
+
const res = await executeAction("UPDATE_RECORD", {
|
|
1375
3091
|
tableId: referencedTableId,
|
|
3092
|
+
tableMetaId: referencedTableId,
|
|
1376
3093
|
recordId,
|
|
3094
|
+
orgId: context == null ? void 0 : context.orgId,
|
|
1377
3095
|
data: { [colName]: value2 }
|
|
1378
3096
|
});
|
|
1379
|
-
if (
|
|
1380
|
-
|
|
3097
|
+
if (res && res.success === false) {
|
|
3098
|
+
const err = new Error(res.error || res.message || "Action execution failed");
|
|
3099
|
+
Object.assign(err, res);
|
|
3100
|
+
throw err;
|
|
3101
|
+
}
|
|
3102
|
+
if (isMountedRef.current) {
|
|
3103
|
+
const updatedRecords = linkedRecords.map(
|
|
3104
|
+
(r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
|
|
3105
|
+
);
|
|
3106
|
+
setLinkedRecords(updatedRecords);
|
|
3107
|
+
const targetRecord = updatedRecords.find((r) => r.id === recordId);
|
|
3108
|
+
const updatedEntries = entries.map(
|
|
3109
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
|
|
3110
|
+
);
|
|
3111
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
3112
|
+
context.updateQuietly(rowId, column.name, updatedEntries);
|
|
3113
|
+
} else {
|
|
3114
|
+
onChange(updatedEntries);
|
|
3115
|
+
}
|
|
3116
|
+
if (context == null ? void 0 : context.triggerSaveSuccess) {
|
|
3117
|
+
context.triggerSaveSuccess();
|
|
3118
|
+
}
|
|
1381
3119
|
}
|
|
3120
|
+
return true;
|
|
1382
3121
|
} catch (err) {
|
|
1383
3122
|
console.error("[SubTableViewer] Failed to auto-save linked record field", err);
|
|
3123
|
+
let errorMsg = (err == null ? void 0 : err.message) || (err == null ? void 0 : err.error) || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4";
|
|
3124
|
+
if ((err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" || (err == null ? void 0 : err.code) === "UNIQUE_CONSTRAINT_CONFLICT" || errorMsg.includes("must be unique") || errorMsg.includes("Duplicate value detected") || errorMsg.includes("\u05DB\u05D1\u05E8 \u05E7\u05D9\u05D9\u05DE\u05EA") || errorMsg.includes("UNIQUE_CONSTRAINT_CONFLICT")) {
|
|
3125
|
+
errorMsg = `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05D4\u05E2\u05E8\u05DA '${value2}' \u05DB\u05D1\u05E8 \u05E7\u05D9\u05D9\u05DD \u05D1\u05E9\u05D3\u05D4 '${colName}' (\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9).`;
|
|
3126
|
+
} else if (errorMsg.includes("is required") || errorMsg.includes("\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4") || errorMsg.toLowerCase().includes("required")) {
|
|
3127
|
+
errorMsg = `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05E9\u05D3\u05D4 '${colName}' \u05D4\u05D9\u05E0\u05D5 \u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 \u05D5\u05DC\u05D0 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05E9\u05D0\u05E8 \u05E8\u05D9\u05E7.`;
|
|
3128
|
+
}
|
|
3129
|
+
addToast({
|
|
3130
|
+
type: "error",
|
|
3131
|
+
message: errorMsg
|
|
3132
|
+
});
|
|
3133
|
+
return false;
|
|
3134
|
+
}
|
|
3135
|
+
} else {
|
|
3136
|
+
if (isMountedRef.current) {
|
|
3137
|
+
const updatedRecords = linkedRecords.map(
|
|
3138
|
+
(r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
|
|
3139
|
+
);
|
|
3140
|
+
setLinkedRecords(updatedRecords);
|
|
3141
|
+
const targetRecord = updatedRecords.find((r) => r.id === recordId);
|
|
3142
|
+
const updatedEntries = entries.map(
|
|
3143
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
|
|
3144
|
+
);
|
|
3145
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
3146
|
+
context.updateQuietly(rowId, column.name, updatedEntries);
|
|
3147
|
+
} else {
|
|
3148
|
+
onChange(updatedEntries);
|
|
3149
|
+
}
|
|
1384
3150
|
}
|
|
3151
|
+
return true;
|
|
1385
3152
|
}
|
|
1386
3153
|
};
|
|
3154
|
+
const handleRecordCellChange = handleCommitRecordCell;
|
|
3155
|
+
const handleQuietSubTableCellChange = (0, import_react11.useCallback)((recordId, colName, value2) => {
|
|
3156
|
+
setLinkedRecords(
|
|
3157
|
+
(prev) => prev.map((r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r)
|
|
3158
|
+
);
|
|
3159
|
+
const updatedEntries = entries.map(
|
|
3160
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: __spreadProps(__spreadValues({}, e._resolvedData || {}), { [colName]: value2 }) }) : e
|
|
3161
|
+
);
|
|
3162
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
3163
|
+
context.updateQuietly(rowId, column.name, updatedEntries);
|
|
3164
|
+
} else {
|
|
3165
|
+
onChange(updatedEntries);
|
|
3166
|
+
}
|
|
3167
|
+
}, [entries, context, rowId, column.name, onChange]);
|
|
1387
3168
|
const handleCreateRecord = async () => {
|
|
1388
|
-
var _a2;
|
|
3169
|
+
var _a2, _b2, _c2, _d2, _e2;
|
|
1389
3170
|
if (!executeAction || !referencedTableId) return;
|
|
1390
3171
|
for (const col of targetColumns) {
|
|
1391
3172
|
if (col.isRequired) {
|
|
@@ -1398,16 +3179,32 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1398
3179
|
return;
|
|
1399
3180
|
}
|
|
1400
3181
|
}
|
|
3182
|
+
if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE") {
|
|
3183
|
+
const val = newRecordData[col.name];
|
|
3184
|
+
if (val !== void 0 && val !== null && String(val).trim() !== "" && !isValidPhoneNumber(String(val))) {
|
|
3185
|
+
addToast({
|
|
3186
|
+
type: "error",
|
|
3187
|
+
message: `\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA.`
|
|
3188
|
+
});
|
|
3189
|
+
return;
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
1401
3192
|
}
|
|
1402
3193
|
try {
|
|
1403
3194
|
const res = await executeAction("CREATE_RECORD", {
|
|
1404
3195
|
tableId: referencedTableId,
|
|
3196
|
+
tableMetaId: referencedTableId,
|
|
3197
|
+
orgId: context == null ? void 0 : context.orgId,
|
|
1405
3198
|
records: [newRecordData]
|
|
1406
3199
|
});
|
|
3200
|
+
if (res && (res.error === "UNIQUE_CONSTRAINT_CONFLICT" || res.code === "UNIQUE_CONSTRAINT_CONFLICT")) {
|
|
3201
|
+
handleUniqueConflict(res);
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
1407
3204
|
if (res && res.success === false) {
|
|
1408
3205
|
throw new Error(res.error || "Action execution failed");
|
|
1409
3206
|
}
|
|
1410
|
-
const created = Array.isArray(res) ? res[0] : ((
|
|
3207
|
+
const created = Array.isArray(res) ? res[0] : ((_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2[0]) || res;
|
|
1411
3208
|
if (created) {
|
|
1412
3209
|
const newRecord = {
|
|
1413
3210
|
id: String(created.id || created._id),
|
|
@@ -1418,6 +3215,12 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1418
3215
|
setNewRecordData({});
|
|
1419
3216
|
}
|
|
1420
3217
|
} catch (err) {
|
|
3218
|
+
const isConflict = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" || (err == null ? void 0 : err.code) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_c2 = err == null ? void 0 : err.data) == null ? void 0 : _c2.error) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_d2 = err == null ? void 0 : err.message) == null ? void 0 : _d2.includes("UNIQUE_CONSTRAINT_CONFLICT"));
|
|
3219
|
+
if (isConflict) {
|
|
3220
|
+
const conflictPayload = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err : ((_e2 = err == null ? void 0 : err.data) == null ? void 0 : _e2.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err.data : err;
|
|
3221
|
+
handleUniqueConflict(conflictPayload);
|
|
3222
|
+
return;
|
|
3223
|
+
}
|
|
1421
3224
|
const msg = (err == null ? void 0 : err.message) || String(err);
|
|
1422
3225
|
addToast({
|
|
1423
3226
|
type: "error",
|
|
@@ -1426,32 +3229,33 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1426
3229
|
}
|
|
1427
3230
|
};
|
|
1428
3231
|
const getDisplayLabel = (record) => {
|
|
1429
|
-
|
|
3232
|
+
var _a2;
|
|
3233
|
+
const fields = ((_a2 = column.config) == null ? void 0 : _a2.subTableDisplayFields) || [];
|
|
1430
3234
|
if (fields.length === 0) {
|
|
1431
3235
|
const firstField = Object.keys(record.data).find((k) => k !== "_id");
|
|
1432
3236
|
return firstField ? String(record.data[firstField] || "") : record.id;
|
|
1433
3237
|
}
|
|
1434
3238
|
return fields.map((f) => String(record.data[f] || "")).filter(Boolean).join(" ");
|
|
1435
3239
|
};
|
|
1436
|
-
return /* @__PURE__ */ (0,
|
|
1437
|
-
/* @__PURE__ */ (0,
|
|
1438
|
-
/* @__PURE__ */ (0,
|
|
1439
|
-
/* @__PURE__ */ (0,
|
|
1440
|
-
/* @__PURE__ */ (0,
|
|
1441
|
-
/* @__PURE__ */ (0,
|
|
3240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-3 animate-in fade-in slide-in-from-top-2 duration-200", dir: "rtl", children: [
|
|
3241
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-4 mb-2.5", children: [
|
|
3242
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs font-bold text-slate-600", children: (_e = targetSchema == null ? void 0 : targetSchema.name) != null ? _e : (_d = column.config) == null ? void 0 : _d.referencedTableName }) }),
|
|
3243
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
3244
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "relative", ref: searchRef, children: [
|
|
3245
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1442
3246
|
"button",
|
|
1443
3247
|
{
|
|
1444
3248
|
type: "button",
|
|
1445
3249
|
onClick: () => setIsSearchOpen((prev) => !prev),
|
|
1446
3250
|
className: "h-7 px-2.5 text-[11px] font-semibold bg-blue-50 hover:bg-blue-100 text-blue-700 border border-blue-200 rounded-md transition-colors cursor-pointer flex items-center gap-1",
|
|
1447
3251
|
children: [
|
|
1448
|
-
/* @__PURE__ */ (0,
|
|
3252
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
|
|
1449
3253
|
"\u05E7\u05D9\u05E9\u05D5\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
|
|
1450
3254
|
]
|
|
1451
3255
|
}
|
|
1452
3256
|
),
|
|
1453
|
-
isSearchOpen && /* @__PURE__ */ (0,
|
|
1454
|
-
/* @__PURE__ */ (0,
|
|
3257
|
+
isSearchOpen && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "absolute right-0 top-full mt-1 w-72 bg-white border border-slate-200 rounded-lg shadow-xl z-50 p-2", children: [
|
|
3258
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1455
3259
|
"input",
|
|
1456
3260
|
{
|
|
1457
3261
|
type: "text",
|
|
@@ -1462,7 +3266,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1462
3266
|
autoFocus: true
|
|
1463
3267
|
}
|
|
1464
3268
|
),
|
|
1465
|
-
/* @__PURE__ */ (0,
|
|
3269
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "max-h-48 overflow-y-auto", children: isSearching ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "w-4 h-4 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : searchResults.length > 0 ? searchResults.map((r) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1466
3270
|
"button",
|
|
1467
3271
|
{
|
|
1468
3272
|
type: "button",
|
|
@@ -1471,10 +3275,10 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1471
3275
|
children: getDisplayLabel(r)
|
|
1472
3276
|
},
|
|
1473
3277
|
r.id
|
|
1474
|
-
)) : searchQuery.trim() ? /* @__PURE__ */ (0,
|
|
3278
|
+
)) : searchQuery.trim() ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05D4\u05E7\u05DC\u05D3 \u05DC\u05D7\u05D9\u05E4\u05D5\u05E9..." }) })
|
|
1475
3279
|
] })
|
|
1476
3280
|
] }),
|
|
1477
|
-
/* @__PURE__ */ (0,
|
|
3281
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1478
3282
|
"button",
|
|
1479
3283
|
{
|
|
1480
3284
|
type: "button",
|
|
@@ -1494,24 +3298,69 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1494
3298
|
},
|
|
1495
3299
|
className: "h-7 px-2.5 text-[11px] font-semibold bg-emerald-50 hover:bg-emerald-100 text-emerald-700 border border-emerald-200 rounded-md transition-colors cursor-pointer flex items-center gap-1",
|
|
1496
3300
|
children: [
|
|
1497
|
-
/* @__PURE__ */ (0,
|
|
3301
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) }),
|
|
1498
3302
|
"\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4"
|
|
1499
3303
|
]
|
|
1500
3304
|
}
|
|
1501
3305
|
)
|
|
1502
3306
|
] })
|
|
1503
3307
|
] }),
|
|
1504
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
1505
|
-
/* @__PURE__ */ (0,
|
|
1506
|
-
/* @__PURE__ */ (0,
|
|
1507
|
-
targetColumns.map((col) =>
|
|
1508
|
-
|
|
3308
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-center py-6 text-xs text-slate-400", children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA. \u05D4\u05E9\u05EA\u05DE\u05E9 \u05D1\u05D7\u05D9\u05E4\u05D5\u05E9 \u05DB\u05D3\u05D9 \u05DC\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA, \u05D0\u05D5 \u05D4\u05D5\u05E1\u05E3 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4." }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("table", { className: "w-full text-xs border-collapse table-auto", children: [
|
|
3309
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { className: "bg-slate-100/80 h-12 min-h-[48px]", children: [
|
|
3310
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 text-center w-10 font-semibold text-slate-500 h-12 min-h-[48px] align-middle", style: { width: 40, minWidth: 40, maxWidth: 40 }, children: "\u05E0\u05D1\u05D7\u05E8" }),
|
|
3311
|
+
targetColumns.map((col) => {
|
|
3312
|
+
const dragProps = getHeaderDragProps(col.name);
|
|
3313
|
+
const isDragging = draggedColName === col.name;
|
|
3314
|
+
const isDragOver = dragOverColName === col.name;
|
|
3315
|
+
const colMinWidth = calculateMinColumnWidth(col.name, true, col.type);
|
|
3316
|
+
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 150);
|
|
3317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3318
|
+
"th",
|
|
3319
|
+
__spreadProps(__spreadValues({
|
|
3320
|
+
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
3321
|
+
title: col.name
|
|
3322
|
+
}, dragProps), {
|
|
3323
|
+
className: `relative border border-slate-200 px-3 py-1.5 font-semibold text-slate-600 select-none cursor-grab active:cursor-grabbing transition-colors h-12 min-h-[48px] align-middle ${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" : "hover:bg-slate-200/60"}`,
|
|
3324
|
+
children: [
|
|
3325
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3326
|
+
"div",
|
|
3327
|
+
{
|
|
3328
|
+
onMouseDown: (e) => {
|
|
3329
|
+
e.preventDefault();
|
|
3330
|
+
e.stopPropagation();
|
|
3331
|
+
startResize(col.name, currentWidth, e.clientX, colMinWidth);
|
|
3332
|
+
},
|
|
3333
|
+
className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-brand active:bg-brand-hover z-20",
|
|
3334
|
+
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
3335
|
+
}
|
|
3336
|
+
),
|
|
3337
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-between gap-1.5 group overflow-hidden w-full", title: col.name, children: [
|
|
3338
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ColumnHeaderTitle, { name: col.name, width: currentWidth, isSubTable: true }),
|
|
3339
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3340
|
+
"svg",
|
|
3341
|
+
{
|
|
3342
|
+
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
3343
|
+
fill: "none",
|
|
3344
|
+
viewBox: "0 0 24 24",
|
|
3345
|
+
stroke: "currentColor",
|
|
3346
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
|
|
3347
|
+
}
|
|
3348
|
+
)
|
|
3349
|
+
] })
|
|
3350
|
+
]
|
|
3351
|
+
}),
|
|
3352
|
+
col.name
|
|
3353
|
+
);
|
|
3354
|
+
}),
|
|
3355
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 w-14 h-12 min-h-[48px]", style: { width: 56, minWidth: 56, maxWidth: 56 } }),
|
|
3356
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "w-full min-w-[50px] border border-slate-200 pointer-events-none h-12 min-h-[48px]" })
|
|
1509
3357
|
] }) }),
|
|
1510
|
-
/* @__PURE__ */ (0,
|
|
3358
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tbody", { children: [
|
|
1511
3359
|
entries.map((entry) => {
|
|
3360
|
+
var _a2;
|
|
1512
3361
|
const record = linkedRecords.find((r) => r.id === entry.recordId);
|
|
1513
|
-
return /* @__PURE__ */ (0,
|
|
1514
|
-
/* @__PURE__ */ (0,
|
|
3362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
|
|
3363
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-slate-200 px-2 py-1 text-center", style: { width: 40, minWidth: 40, maxWidth: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1515
3364
|
"input",
|
|
1516
3365
|
{
|
|
1517
3366
|
type: "checkbox",
|
|
@@ -1521,74 +3370,129 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1521
3370
|
}
|
|
1522
3371
|
) }),
|
|
1523
3372
|
targetColumns.map((col) => {
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
3373
|
+
const currentWidth = columnWidths[col.name] || 150;
|
|
3374
|
+
if (!record) {
|
|
3375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3376
|
+
"td",
|
|
3377
|
+
{
|
|
3378
|
+
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
3379
|
+
className: "border border-slate-200 p-0 relative h-8 overflow-hidden",
|
|
3380
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." })
|
|
3381
|
+
},
|
|
3382
|
+
col.name
|
|
3383
|
+
);
|
|
3384
|
+
}
|
|
3385
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3386
|
+
SubTableCell,
|
|
1529
3387
|
{
|
|
1530
|
-
|
|
3388
|
+
record,
|
|
1531
3389
|
column: col,
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." }) }, col.name);
|
|
3390
|
+
targetSchema,
|
|
3391
|
+
referencedTableId,
|
|
3392
|
+
parentRowId: rowId,
|
|
3393
|
+
context,
|
|
3394
|
+
relationOptions,
|
|
3395
|
+
setRelationOptions,
|
|
3396
|
+
refetchRelation,
|
|
3397
|
+
onCommit: handleCommitRecordCell,
|
|
3398
|
+
onQuietUpdate: handleQuietSubTableCellChange,
|
|
3399
|
+
width: currentWidth
|
|
3400
|
+
},
|
|
3401
|
+
`${record.id}_${col.name}`
|
|
3402
|
+
);
|
|
1546
3403
|
}),
|
|
1547
|
-
/* @__PURE__ */ (0,
|
|
1548
|
-
"
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
3404
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-slate-200 px-1 py-1 text-center", style: { width: 56, minWidth: 56, maxWidth: 56 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
|
|
3405
|
+
((_a2 = column.config) == null ? void 0 : _a2.actionType) === "WHATSAPP" && (() => {
|
|
3406
|
+
var _a3, _b2, _c2;
|
|
3407
|
+
const actionPhoneCol = (_a3 = column.config) == null ? void 0 : _a3.actionPhoneColumn;
|
|
3408
|
+
const phone = actionPhoneCol ? ((_b2 = record == null ? void 0 : record.data) == null ? void 0 : _b2[actionPhoneCol]) || ((_c2 = entry._resolvedData) == null ? void 0 : _c2[actionPhoneCol]) : null;
|
|
3409
|
+
if (phone) {
|
|
3410
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3411
|
+
"button",
|
|
3412
|
+
{
|
|
3413
|
+
type: "button",
|
|
3414
|
+
onClick: (e) => {
|
|
3415
|
+
e.stopPropagation();
|
|
3416
|
+
openWhatsAppChat(String(phone));
|
|
3417
|
+
},
|
|
3418
|
+
className: "text-emerald-500 hover:text-emerald-600 p-0.5 rounded hover:bg-emerald-50 transition-colors cursor-pointer",
|
|
3419
|
+
title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
|
|
3420
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3.5 h-3.5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
|
|
3421
|
+
}
|
|
3422
|
+
);
|
|
3423
|
+
}
|
|
3424
|
+
return null;
|
|
3425
|
+
})(),
|
|
3426
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3427
|
+
"button",
|
|
3428
|
+
{
|
|
3429
|
+
type: "button",
|
|
3430
|
+
onClick: (e) => {
|
|
3431
|
+
e.stopPropagation();
|
|
3432
|
+
handleUnlinkRecord(entry.recordId);
|
|
3433
|
+
},
|
|
3434
|
+
className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center",
|
|
3435
|
+
title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
|
|
3436
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
|
|
3437
|
+
}
|
|
3438
|
+
)
|
|
3439
|
+
] }) }),
|
|
3440
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-slate-200 bg-white pointer-events-none" })
|
|
1557
3441
|
] }, entry.recordId);
|
|
1558
3442
|
}),
|
|
1559
|
-
isCreating && /* @__PURE__ */ (0,
|
|
1560
|
-
/* @__PURE__ */ (0,
|
|
3443
|
+
isCreating && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { className: "bg-emerald-50/40", children: [
|
|
3444
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-emerald-200 px-2 py-1 text-center", style: { width: 40, minWidth: 40, maxWidth: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-emerald-500 font-bold text-[10px]", children: "\u05D7\u05D3\u05E9" }) }),
|
|
1561
3445
|
targetColumns.map((col) => {
|
|
1562
|
-
var _a2,
|
|
3446
|
+
var _a2, _b2, _c2, _d2, _e2;
|
|
1563
3447
|
const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
|
|
1564
3448
|
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
1565
|
-
|
|
1566
|
-
|
|
3449
|
+
const currentWidth = columnWidths[col.name] || 150;
|
|
3450
|
+
const effectiveParentId = rowId || ((_b2 = context == null ? void 0 : context.parentRecord) == null ? void 0 : _b2.recordId) || ((_c2 = context == null ? void 0 : context.parentRecord) == null ? void 0 : _c2.id) || (context == null ? void 0 : context.rowId);
|
|
3451
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3452
|
+
"td",
|
|
1567
3453
|
{
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
3454
|
+
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
3455
|
+
className: `border border-emerald-200 p-0 relative h-8 ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
|
|
3456
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3457
|
+
InputComponent,
|
|
3458
|
+
{
|
|
3459
|
+
value: (_d2 = newRecordData[col.name]) != null ? _d2 : colType === "BOOLEAN" ? false : "",
|
|
3460
|
+
column: col,
|
|
3461
|
+
rowId: "new_record",
|
|
3462
|
+
onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
|
|
3463
|
+
context: __spreadProps(__spreadValues({}, context), {
|
|
3464
|
+
tableName: (targetSchema == null ? void 0 : targetSchema.name) || (targetSchema == null ? void 0 : targetSchema.tableName) || (targetSchema == null ? void 0 : targetSchema.title) || (targetSchema == null ? void 0 : targetSchema.id) || "Table",
|
|
3465
|
+
relationOptions,
|
|
3466
|
+
refetchRelation,
|
|
3467
|
+
parentTableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId),
|
|
3468
|
+
parentRecord: {
|
|
3469
|
+
tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId),
|
|
3470
|
+
recordId: effectiveParentId,
|
|
3471
|
+
id: effectiveParentId,
|
|
3472
|
+
data: (context == null ? void 0 : context.rowData) || ((_e2 = context == null ? void 0 : context.parentRecord) == null ? void 0 : _e2.data)
|
|
3473
|
+
},
|
|
3474
|
+
tableId: targetTableId,
|
|
3475
|
+
tableMetaId: targetTableId,
|
|
3476
|
+
orgId: context == null ? void 0 : context.orgId
|
|
3477
|
+
})
|
|
3478
|
+
}
|
|
3479
|
+
)
|
|
3480
|
+
},
|
|
3481
|
+
`new_${col.name}`
|
|
3482
|
+
);
|
|
1579
3483
|
}),
|
|
1580
|
-
/* @__PURE__ */ (0,
|
|
1581
|
-
/* @__PURE__ */ (0,
|
|
3484
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-emerald-200 px-1 py-1 text-center", style: { width: 56, minWidth: 56, maxWidth: 56 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
|
|
3485
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1582
3486
|
"button",
|
|
1583
3487
|
{
|
|
1584
3488
|
type: "button",
|
|
1585
3489
|
onClick: handleCreateRecord,
|
|
1586
3490
|
className: "p-1 text-emerald-600 hover:bg-emerald-100 rounded transition-colors",
|
|
1587
3491
|
title: "\u05E9\u05DE\u05D5\u05E8",
|
|
1588
|
-
children: /* @__PURE__ */ (0,
|
|
3492
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) })
|
|
1589
3493
|
}
|
|
1590
3494
|
),
|
|
1591
|
-
/* @__PURE__ */ (0,
|
|
3495
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1592
3496
|
"button",
|
|
1593
3497
|
{
|
|
1594
3498
|
type: "button",
|
|
@@ -1597,19 +3501,107 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1597
3501
|
},
|
|
1598
3502
|
className: "p-1 text-rose-500 hover:bg-rose-100 rounded transition-colors",
|
|
1599
3503
|
title: "\u05D1\u05D9\u05D8\u05D5\u05DC",
|
|
1600
|
-
children: /* @__PURE__ */ (0,
|
|
3504
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M6 18L18 6M6 6l12 12" }) })
|
|
1601
3505
|
}
|
|
1602
3506
|
)
|
|
1603
|
-
] }) })
|
|
3507
|
+
] }) }),
|
|
3508
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-emerald-200 bg-emerald-50/40 pointer-events-none" })
|
|
1604
3509
|
] })
|
|
1605
3510
|
] })
|
|
1606
|
-
] }) })
|
|
3511
|
+
] }) }),
|
|
3512
|
+
conflictModalState.isOpen && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3513
|
+
"div",
|
|
3514
|
+
{
|
|
3515
|
+
className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/60 backdrop-blur-sm animate-in fade-in duration-200",
|
|
3516
|
+
dir: "rtl",
|
|
3517
|
+
onClick: handleCancelConflict,
|
|
3518
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3519
|
+
"div",
|
|
3520
|
+
{
|
|
3521
|
+
className: "bg-white rounded-xl shadow-2xl w-full max-w-lg sm:max-w-xl overflow-hidden border border-slate-200 animate-in fade-in zoom-in-95 duration-200",
|
|
3522
|
+
onClick: (e) => e.stopPropagation(),
|
|
3523
|
+
children: [
|
|
3524
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-5 border-b border-slate-100 flex items-center gap-3", children: [
|
|
3525
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "w-10 h-10 rounded-full bg-blue-50 border border-blue-200 flex items-center justify-center text-blue-600 flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }) }),
|
|
3526
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
3527
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "text-base font-bold text-slate-800", children: conflictModalState.matchingRecords.length > 1 ? "\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA \u05D1\u05D8\u05D1\u05DC\u05D4" : "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D9\u05D9\u05DE\u05EA \u05D1\u05D8\u05D1\u05DC\u05D4" }),
|
|
3528
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-xs text-slate-500", children: "\u05E0\u05DE\u05E6\u05D0\u05D4 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D9\u05D9\u05DE\u05EA \u05E2\u05DD \u05D0\u05D5\u05EA\u05D5 \u05E2\u05E8\u05DA \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9" })
|
|
3529
|
+
] })
|
|
3530
|
+
] }),
|
|
3531
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-5 space-y-3", children: [
|
|
3532
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "text-sm text-slate-700 leading-relaxed", children: [
|
|
3533
|
+
"\u05E7\u05D9\u05D9\u05DE\u05EA \u05DB\u05D1\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05E2\u05DD \u05D4\u05E2\u05E8\u05DA \u05E9\u05E0\u05D1\u05D7\u05E8 \u05D1\u05E9\u05D3\u05D4",
|
|
3534
|
+
" ",
|
|
3535
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "font-bold text-slate-900 bg-slate-100 px-1.5 py-0.5 rounded border border-slate-200", children: conflictModalState.fieldName }),
|
|
3536
|
+
". \u05D4\u05D0\u05DD \u05EA\u05E8\u05E6\u05D4 \u05DC\u05E7\u05E9\u05E8 \u05D0\u05D5\u05EA\u05D4 \u05DC\u05EA\u05EA-\u05D4\u05D8\u05D1\u05DC\u05D4 \u05D1\u05DE\u05E7\u05D5\u05DD \u05DC\u05D9\u05E6\u05D5\u05E8 \u05D7\u05D3\u05E9\u05D4?"
|
|
3537
|
+
] }),
|
|
3538
|
+
conflictModalState.matchingRecords.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-3 bg-blue-50 border border-blue-200 rounded-lg text-xs font-semibold text-blue-800", children: [
|
|
3539
|
+
"\u05E0\u05DE\u05E6\u05D0\u05D5 ",
|
|
3540
|
+
conflictModalState.matchingRecords.length,
|
|
3541
|
+
" \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA. \u05D4\u05D0\u05DD \u05DC\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF?"
|
|
3542
|
+
] }),
|
|
3543
|
+
conflictModalState.matchingRecords.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "overflow-x-auto border border-slate-200 rounded-lg max-h-48 text-xs bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("table", { className: "w-full text-right border-collapse", children: [
|
|
3544
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tr", { className: "bg-slate-100 text-slate-700 font-semibold border-b whitespace-nowrap", children: (targetColumns.length > 0 ? targetColumns.filter((c) => c.name !== "_id" && c.name !== "id") : Object.keys(((_f = conflictModalState.matchingRecords[0]) == null ? void 0 : _f.data) || {}).filter((k) => k !== "_id" && k !== "id").map((name) => ({ name }))).map((col) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3545
|
+
"th",
|
|
3546
|
+
{
|
|
3547
|
+
className: "bg-slate-100 text-slate-700 font-semibold p-2 border-b whitespace-nowrap",
|
|
3548
|
+
children: col.name
|
|
3549
|
+
},
|
|
3550
|
+
col.name
|
|
3551
|
+
)) }) }),
|
|
3552
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tbody", { children: conflictModalState.matchingRecords.map((r, idx) => {
|
|
3553
|
+
const cols = targetColumns.length > 0 ? targetColumns.filter((c) => c.name !== "_id" && c.name !== "id") : Object.keys(r.data || {}).filter((k) => k !== "_id" && k !== "id").map((name) => ({ name }));
|
|
3554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tr", { className: "hover:bg-slate-50/80 transition-colors", children: cols.map((col) => {
|
|
3555
|
+
var _a2;
|
|
3556
|
+
const rawVal = (_a2 = r.data) == null ? void 0 : _a2[col.name];
|
|
3557
|
+
const colDef = targetColumns.find((c) => c.name === col.name) || col;
|
|
3558
|
+
const displayVal = formatConflictCellValue(rawVal, colDef, relationOptions || (context == null ? void 0 : context.relationOptions));
|
|
3559
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3560
|
+
"td",
|
|
3561
|
+
{
|
|
3562
|
+
className: "p-2 border-b border-slate-100 whitespace-nowrap text-slate-800",
|
|
3563
|
+
children: displayVal
|
|
3564
|
+
},
|
|
3565
|
+
col.name
|
|
3566
|
+
);
|
|
3567
|
+
}) }, r.id || idx);
|
|
3568
|
+
}) })
|
|
3569
|
+
] }) })
|
|
3570
|
+
] }),
|
|
3571
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-4 bg-slate-50 border-t border-slate-100 flex items-center justify-end gap-2.5", children: [
|
|
3572
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3573
|
+
"button",
|
|
3574
|
+
{
|
|
3575
|
+
type: "button",
|
|
3576
|
+
onClick: handleCancelConflict,
|
|
3577
|
+
className: "px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-200/70 rounded-lg border border-slate-300 transition-colors cursor-pointer",
|
|
3578
|
+
children: "\u05D1\u05D9\u05D8\u05D5\u05DC"
|
|
3579
|
+
}
|
|
3580
|
+
),
|
|
3581
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3582
|
+
"button",
|
|
3583
|
+
{
|
|
3584
|
+
type: "button",
|
|
3585
|
+
onClick: handleConfirmLinkConflict,
|
|
3586
|
+
className: "px-4 py-2 text-sm font-semibold text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow transition-colors flex items-center gap-1.5 cursor-pointer",
|
|
3587
|
+
children: [
|
|
3588
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }),
|
|
3589
|
+
conflictModalState.matchingRecords.length > 1 ? "\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF" : "\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4"
|
|
3590
|
+
]
|
|
3591
|
+
}
|
|
3592
|
+
)
|
|
3593
|
+
] })
|
|
3594
|
+
]
|
|
3595
|
+
}
|
|
3596
|
+
)
|
|
3597
|
+
}
|
|
3598
|
+
)
|
|
1607
3599
|
] });
|
|
1608
3600
|
}
|
|
1609
3601
|
|
|
1610
3602
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
1611
|
-
var
|
|
1612
|
-
var
|
|
3603
|
+
var import_lucide_react7 = require("lucide-react");
|
|
3604
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1613
3605
|
function TableBlockClient({
|
|
1614
3606
|
data: initialRecords,
|
|
1615
3607
|
settings: schema,
|
|
@@ -1626,22 +3618,25 @@ function TableBlockClient({
|
|
|
1626
3618
|
"data-testid": dataTestId
|
|
1627
3619
|
}) {
|
|
1628
3620
|
const { showError, addToast } = useToast();
|
|
1629
|
-
const [columnWidths, setColumnWidths] = (0, import_react7.useState)({});
|
|
1630
|
-
const [isMounted, setIsMounted] = (0, import_react7.useState)(false);
|
|
1631
3621
|
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";
|
|
1632
|
-
const
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
3622
|
+
const { columnWidths, startResize } = useColumnResize({
|
|
3623
|
+
storageKey: `table_widths_${tableKey}`,
|
|
3624
|
+
minWidth: 60,
|
|
3625
|
+
defaultWidth: 200,
|
|
3626
|
+
getMinColWidth: (colName) => {
|
|
3627
|
+
const col = (localColumns || []).find((c) => c.name === colName);
|
|
3628
|
+
return calculateMinColumnWidth(colName, false, col == null ? void 0 : col.type);
|
|
3629
|
+
}
|
|
3630
|
+
});
|
|
3631
|
+
const [isMounted, setIsMounted] = (0, import_react12.useState)(false);
|
|
3632
|
+
const [isInitialLoading, setIsInitialLoading] = (0, import_react12.useState)(true);
|
|
3633
|
+
const [page, setPage] = (0, import_react12.useState)(1);
|
|
3634
|
+
const [limit, setLimit] = (0, import_react12.useState)(50);
|
|
3635
|
+
const [totalRecords, setTotalRecords] = (0, import_react12.useState)(0);
|
|
3636
|
+
const [totalPages, setTotalPages] = (0, import_react12.useState)(1);
|
|
3637
|
+
const [showSummary, setShowSummary] = (0, import_react12.useState)(false);
|
|
3638
|
+
(0, import_react12.useEffect)(() => {
|
|
1637
3639
|
if (typeof window !== "undefined") {
|
|
1638
|
-
const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
|
|
1639
|
-
if (savedWidths) {
|
|
1640
|
-
try {
|
|
1641
|
-
setColumnWidths(JSON.parse(savedWidths));
|
|
1642
|
-
} catch (e) {
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
3640
|
const savedSummary = localStorage.getItem(`table_summary_${tableKey}`);
|
|
1646
3641
|
if (savedSummary !== null) {
|
|
1647
3642
|
setShowSummary(savedSummary === "true");
|
|
@@ -1656,7 +3651,6 @@ function TableBlockClient({
|
|
|
1656
3651
|
}
|
|
1657
3652
|
setIsMounted(true);
|
|
1658
3653
|
}, [tableKey]);
|
|
1659
|
-
const [showSummary, setShowSummary] = (0, import_react7.useState)(false);
|
|
1660
3654
|
const toggleSummary = () => {
|
|
1661
3655
|
setShowSummary((prev) => {
|
|
1662
3656
|
const next = !prev;
|
|
@@ -1665,29 +3659,6 @@ function TableBlockClient({
|
|
|
1665
3659
|
return next;
|
|
1666
3660
|
});
|
|
1667
3661
|
};
|
|
1668
|
-
const [resizingCol, setResizingCol] = (0, import_react7.useState)(null);
|
|
1669
|
-
(0, import_react7.useEffect)(() => {
|
|
1670
|
-
if (!resizingCol) return;
|
|
1671
|
-
const handleMouseMove = (e) => {
|
|
1672
|
-
const diffX = resizingCol.startX - e.clientX;
|
|
1673
|
-
const newWidth = Math.max(100, Math.min(500, resizingCol.startWidth + diffX));
|
|
1674
|
-
setColumnWidths((prev) => __spreadProps(__spreadValues({}, prev), { [resizingCol.name]: newWidth }));
|
|
1675
|
-
};
|
|
1676
|
-
const handleMouseUp = () => {
|
|
1677
|
-
setResizingCol(null);
|
|
1678
|
-
setColumnWidths((prev) => {
|
|
1679
|
-
const tableKey2 = (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";
|
|
1680
|
-
localStorage.setItem(`table_widths_${tableKey2}`, JSON.stringify(prev));
|
|
1681
|
-
return prev;
|
|
1682
|
-
});
|
|
1683
|
-
};
|
|
1684
|
-
document.addEventListener("mousemove", handleMouseMove);
|
|
1685
|
-
document.addEventListener("mouseup", handleMouseUp);
|
|
1686
|
-
return () => {
|
|
1687
|
-
document.removeEventListener("mousemove", handleMouseMove);
|
|
1688
|
-
document.removeEventListener("mouseup", handleMouseUp);
|
|
1689
|
-
};
|
|
1690
|
-
}, [resizingCol, schema]);
|
|
1691
3662
|
const normalizeRecords = (records) => {
|
|
1692
3663
|
return (records || []).map((row) => {
|
|
1693
3664
|
var _c;
|
|
@@ -1713,7 +3684,7 @@ function TableBlockClient({
|
|
|
1713
3684
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
1714
3685
|
});
|
|
1715
3686
|
};
|
|
1716
|
-
const mergeColumnDefs = (0,
|
|
3687
|
+
const mergeColumnDefs = (0, import_react12.useCallback)((existingCols, incomingCols) => {
|
|
1717
3688
|
if (!incomingCols || incomingCols.length === 0) return existingCols || [];
|
|
1718
3689
|
if (!existingCols || existingCols.length === 0) return incomingCols;
|
|
1719
3690
|
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
@@ -1733,18 +3704,18 @@ function TableBlockClient({
|
|
|
1733
3704
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
1734
3705
|
});
|
|
1735
3706
|
}, []);
|
|
1736
|
-
const [localColumns, setLocalColumns] = (0,
|
|
1737
|
-
(0,
|
|
3707
|
+
const [localColumns, setLocalColumns] = (0, import_react12.useState)(() => (schema == null ? void 0 : schema.columns) || []);
|
|
3708
|
+
(0, import_react12.useEffect)(() => {
|
|
1738
3709
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
1739
3710
|
setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
|
|
1740
3711
|
}
|
|
1741
3712
|
}, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
|
|
1742
|
-
const [dirty, setDirty] = (0,
|
|
1743
|
-
const dirtyRef = (0,
|
|
1744
|
-
(0,
|
|
3713
|
+
const [dirty, setDirty] = (0, import_react12.useState)({ added: [], modified: {}, deleted: [] });
|
|
3714
|
+
const dirtyRef = (0, import_react12.useRef)(dirty);
|
|
3715
|
+
(0, import_react12.useEffect)(() => {
|
|
1745
3716
|
dirtyRef.current = dirty;
|
|
1746
3717
|
}, [dirty]);
|
|
1747
|
-
const mergeWithDirty = (0,
|
|
3718
|
+
const mergeWithDirty = (0, import_react12.useCallback)((baseRecords) => {
|
|
1748
3719
|
const { added, modified, deleted } = dirtyRef.current;
|
|
1749
3720
|
const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
|
|
1750
3721
|
const modifiedRecords = nonDeleted.map((r) => {
|
|
@@ -1757,10 +3728,13 @@ function TableBlockClient({
|
|
|
1757
3728
|
const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
|
|
1758
3729
|
return [...uniqueAdded, ...modifiedRecords];
|
|
1759
3730
|
}, []);
|
|
1760
|
-
const [data, setData] = (0,
|
|
1761
|
-
(0,
|
|
3731
|
+
const [data, setData] = (0, import_react12.useState)(() => normalizeRecords(initialRecords));
|
|
3732
|
+
const [serverRecords, setServerRecords] = (0, import_react12.useState)(() => normalizeRecords(initialRecords));
|
|
3733
|
+
(0, import_react12.useEffect)(() => {
|
|
1762
3734
|
if (initialRecords) {
|
|
1763
|
-
|
|
3735
|
+
const norm = normalizeRecords(initialRecords);
|
|
3736
|
+
setServerRecords(norm);
|
|
3737
|
+
setData(mergeWithDirty(norm));
|
|
1764
3738
|
}
|
|
1765
3739
|
}, [initialRecords, mergeWithDirty]);
|
|
1766
3740
|
const isEqualValues = (a, b) => {
|
|
@@ -1773,19 +3747,19 @@ function TableBlockClient({
|
|
|
1773
3747
|
}
|
|
1774
3748
|
return false;
|
|
1775
3749
|
};
|
|
1776
|
-
const [baseRecordsMap, setBaseRecordsMap] = (0,
|
|
3750
|
+
const [baseRecordsMap, setBaseRecordsMap] = (0, import_react12.useState)(() => {
|
|
1777
3751
|
const map = /* @__PURE__ */ new Map();
|
|
1778
3752
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1779
3753
|
return map;
|
|
1780
3754
|
});
|
|
1781
|
-
(0,
|
|
3755
|
+
(0, import_react12.useEffect)(() => {
|
|
1782
3756
|
if (initialRecords && initialRecords.length > 0) {
|
|
1783
3757
|
const map = /* @__PURE__ */ new Map();
|
|
1784
3758
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1785
3759
|
setBaseRecordsMap(map);
|
|
1786
3760
|
}
|
|
1787
3761
|
}, [initialRecords]);
|
|
1788
|
-
const refetchTableData = (0,
|
|
3762
|
+
const refetchTableData = (0, import_react12.useCallback)((targetPage) => {
|
|
1789
3763
|
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1790
3764
|
if (!tableId || !executeAction) return Promise.resolve();
|
|
1791
3765
|
const activePage = targetPage !== void 0 ? targetPage : page;
|
|
@@ -1801,7 +3775,8 @@ function TableBlockClient({
|
|
|
1801
3775
|
const map = /* @__PURE__ */ new Map();
|
|
1802
3776
|
norm.forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1803
3777
|
setBaseRecordsMap(map);
|
|
1804
|
-
|
|
3778
|
+
setServerRecords(norm);
|
|
3779
|
+
setData(mergeWithDirty(norm));
|
|
1805
3780
|
}
|
|
1806
3781
|
if (res.meta) {
|
|
1807
3782
|
const total = typeof res.meta.totalRecords === "number" ? res.meta.totalRecords : 0;
|
|
@@ -1819,9 +3794,22 @@ function TableBlockClient({
|
|
|
1819
3794
|
}).catch((err) => {
|
|
1820
3795
|
console.error("[TableBlock] Failed to auto-fetch table data:", err);
|
|
1821
3796
|
});
|
|
1822
|
-
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs]);
|
|
1823
|
-
(0,
|
|
1824
|
-
|
|
3797
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs, mergeWithDirty]);
|
|
3798
|
+
(0, import_react12.useEffect)(() => {
|
|
3799
|
+
let isMounted2 = true;
|
|
3800
|
+
const fetchPromise = refetchTableData();
|
|
3801
|
+
if (fetchPromise && typeof fetchPromise.finally === "function") {
|
|
3802
|
+
fetchPromise.finally(() => {
|
|
3803
|
+
if (isMounted2) {
|
|
3804
|
+
setIsInitialLoading(false);
|
|
3805
|
+
}
|
|
3806
|
+
});
|
|
3807
|
+
} else {
|
|
3808
|
+
setIsInitialLoading(false);
|
|
3809
|
+
}
|
|
3810
|
+
return () => {
|
|
3811
|
+
isMounted2 = false;
|
|
3812
|
+
};
|
|
1825
3813
|
}, [refetchTableData]);
|
|
1826
3814
|
const handleLimitChange = (newLimit) => {
|
|
1827
3815
|
setLimit(newLimit);
|
|
@@ -1836,31 +3824,50 @@ function TableBlockClient({
|
|
|
1836
3824
|
const handleNextPage = () => {
|
|
1837
3825
|
setPage((prev) => Math.min(totalPages, prev + 1));
|
|
1838
3826
|
};
|
|
1839
|
-
(0,
|
|
3827
|
+
(0, import_react12.useEffect)(() => {
|
|
1840
3828
|
if (error) {
|
|
1841
3829
|
showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
|
|
1842
3830
|
}
|
|
1843
3831
|
}, [error, showError]);
|
|
1844
|
-
const [searchQuery, setSearchQuery] = (0,
|
|
1845
|
-
const [
|
|
1846
|
-
const [
|
|
1847
|
-
const
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
3832
|
+
const [searchQuery, setSearchQuery] = (0, import_react12.useState)("");
|
|
3833
|
+
const [columnFilters, setColumnFilters] = (0, import_react12.useState)({});
|
|
3834
|
+
const [activeSearchCol, setActiveSearchCol] = (0, import_react12.useState)(null);
|
|
3835
|
+
const activeSearchRef = (0, import_react12.useRef)(null);
|
|
3836
|
+
(0, import_react12.useEffect)(() => {
|
|
3837
|
+
if (!activeSearchCol) return;
|
|
3838
|
+
const handleMouseDown = (e) => {
|
|
3839
|
+
if (activeSearchRef.current && !activeSearchRef.current.contains(e.target)) {
|
|
3840
|
+
setActiveSearchCol(null);
|
|
3841
|
+
}
|
|
3842
|
+
};
|
|
3843
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
3844
|
+
return () => {
|
|
3845
|
+
document.removeEventListener("mousedown", handleMouseDown);
|
|
3846
|
+
};
|
|
3847
|
+
}, [activeSearchCol]);
|
|
3848
|
+
const [selectedIds, setSelectedIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
|
|
3849
|
+
const [pendingDeletions, setPendingDeletions] = (0, import_react12.useState)([]);
|
|
3850
|
+
const [isSaving, setIsSaving] = (0, import_react12.useState)(false);
|
|
3851
|
+
const isUpdatingActive = Boolean(isUpdating || isSaving);
|
|
3852
|
+
const [isSaveSuccess, setIsSaveSuccess] = (0, import_react12.useState)(false);
|
|
3853
|
+
const [relationOptions, setRelationOptions] = (0, import_react12.useState)({});
|
|
3854
|
+
const [expandedRowIds, setExpandedRowIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
|
|
3855
|
+
const schemaColsString = (0, import_react12.useMemo)(() => JSON.stringify(localColumns || []), [localColumns]);
|
|
3856
|
+
const refetchRelation = (0, import_react12.useCallback)(async (colName) => {
|
|
3857
|
+
var _a, _b, _c;
|
|
1854
3858
|
let parsedCols = [];
|
|
1855
3859
|
try {
|
|
1856
3860
|
parsedCols = JSON.parse(schemaColsString);
|
|
1857
3861
|
} catch (e) {
|
|
1858
3862
|
}
|
|
1859
|
-
const col = parsedCols.find((c) =>
|
|
1860
|
-
|
|
3863
|
+
const col = parsedCols.find((c) => {
|
|
3864
|
+
var _a2;
|
|
3865
|
+
return c.name === colName && ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION";
|
|
3866
|
+
});
|
|
3867
|
+
if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId)) return;
|
|
1861
3868
|
try {
|
|
1862
3869
|
if (executeAction) {
|
|
1863
|
-
const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
|
|
3870
|
+
const options = await executeAction("FETCH_RELATION", { referencedTableId: (_b = col.config) == null ? void 0 : _b.referencedTableId, displayField: (_c = col.config) == null ? void 0 : _c.displayField });
|
|
1864
3871
|
if (options && Array.isArray(options)) {
|
|
1865
3872
|
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [colName]: options }));
|
|
1866
3873
|
}
|
|
@@ -1869,7 +3876,7 @@ function TableBlockClient({
|
|
|
1869
3876
|
console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
|
|
1870
3877
|
}
|
|
1871
3878
|
}, [schemaColsString, executeAction]);
|
|
1872
|
-
(0,
|
|
3879
|
+
(0, import_react12.useEffect)(() => {
|
|
1873
3880
|
let parsedCols = [];
|
|
1874
3881
|
try {
|
|
1875
3882
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -1883,7 +3890,7 @@ function TableBlockClient({
|
|
|
1883
3890
|
refetchRelation(col.name);
|
|
1884
3891
|
});
|
|
1885
3892
|
}, [schemaColsString, refetchRelation]);
|
|
1886
|
-
const normalizedColumns = (0,
|
|
3893
|
+
const normalizedColumns = (0, import_react12.useMemo)(() => {
|
|
1887
3894
|
return (localColumns || []).map((col, idx) => {
|
|
1888
3895
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1889
3896
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
@@ -1897,17 +3904,17 @@ function TableBlockClient({
|
|
|
1897
3904
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
1898
3905
|
});
|
|
1899
3906
|
}, [localColumns]);
|
|
1900
|
-
const filteredColumns = (0,
|
|
3907
|
+
const filteredColumns = (0, import_react12.useMemo)(() => {
|
|
1901
3908
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1902
3909
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
|
|
1903
3910
|
}, [normalizedColumns]);
|
|
1904
|
-
const customizableColumns = (0,
|
|
3911
|
+
const customizableColumns = (0, import_react12.useMemo)(() => {
|
|
1905
3912
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1906
3913
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name));
|
|
1907
3914
|
}, [normalizedColumns]);
|
|
1908
|
-
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0,
|
|
1909
|
-
const dropdownRef = (0,
|
|
1910
|
-
(0,
|
|
3915
|
+
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0, import_react12.useState)(false);
|
|
3916
|
+
const dropdownRef = (0, import_react12.useRef)(null);
|
|
3917
|
+
(0, import_react12.useEffect)(() => {
|
|
1911
3918
|
const handleClickOutside = (e) => {
|
|
1912
3919
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1913
3920
|
setIsColumnsDropdownOpen(false);
|
|
@@ -1985,8 +3992,6 @@ function TableBlockClient({
|
|
|
1985
3992
|
}
|
|
1986
3993
|
}
|
|
1987
3994
|
};
|
|
1988
|
-
const [draggedColName, setDraggedColName] = (0, import_react7.useState)(null);
|
|
1989
|
-
const [dragOverColName, setDragOverColName] = (0, import_react7.useState)(null);
|
|
1990
3995
|
const handleColumnReorder = async (draggedName, dropTargetName) => {
|
|
1991
3996
|
var _a;
|
|
1992
3997
|
if (draggedName === dropTargetName) return;
|
|
@@ -2021,6 +4026,43 @@ function TableBlockClient({
|
|
|
2021
4026
|
}
|
|
2022
4027
|
}
|
|
2023
4028
|
};
|
|
4029
|
+
const { draggedColName, dragOverColName, getHeaderDragProps } = useColumnReorder({
|
|
4030
|
+
onReorder: handleColumnReorder,
|
|
4031
|
+
disabled: isLoading || isUpdatingActive
|
|
4032
|
+
});
|
|
4033
|
+
const handleUpdateColumnConfig = async (columnName, partialConfig) => {
|
|
4034
|
+
var _a;
|
|
4035
|
+
let updatedColumns = [];
|
|
4036
|
+
setLocalColumns((prevCols) => {
|
|
4037
|
+
const nextCols = (prevCols || []).map((col) => {
|
|
4038
|
+
if (col.name === columnName) {
|
|
4039
|
+
return __spreadProps(__spreadValues({}, col), {
|
|
4040
|
+
config: __spreadValues(__spreadValues({}, col.config || {}), partialConfig)
|
|
4041
|
+
});
|
|
4042
|
+
}
|
|
4043
|
+
return col;
|
|
4044
|
+
});
|
|
4045
|
+
updatedColumns = nextCols;
|
|
4046
|
+
return nextCols;
|
|
4047
|
+
});
|
|
4048
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
4049
|
+
if (targetTableId && executeAction && updatedColumns.length > 0) {
|
|
4050
|
+
try {
|
|
4051
|
+
const res = await executeAction("UPDATE_TABLE_COLUMNS", {
|
|
4052
|
+
tableId: targetTableId,
|
|
4053
|
+
tableMetaId: targetTableId,
|
|
4054
|
+
columns: updatedColumns
|
|
4055
|
+
});
|
|
4056
|
+
const returnedCols = (res == null ? void 0 : res.columns) || ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.columns);
|
|
4057
|
+
if (returnedCols && Array.isArray(returnedCols)) {
|
|
4058
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, returnedCols));
|
|
4059
|
+
}
|
|
4060
|
+
} catch (err) {
|
|
4061
|
+
console.error("[TableBlock] Failed to save column config:", err);
|
|
4062
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E2\u05D3\u05DB\u05D5\u05DF \u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05E2\u05DE\u05D5\u05D3\u05D4");
|
|
4063
|
+
}
|
|
4064
|
+
}
|
|
4065
|
+
};
|
|
2024
4066
|
const generateTempId = () => `temp_${Math.random().toString(36).substr(2, 9)}`;
|
|
2025
4067
|
const handleAddRow = () => {
|
|
2026
4068
|
const defaultData = {};
|
|
@@ -2115,13 +4157,13 @@ function TableBlockClient({
|
|
|
2115
4157
|
});
|
|
2116
4158
|
}
|
|
2117
4159
|
};
|
|
2118
|
-
const triggerSaveSuccess = (0,
|
|
4160
|
+
const triggerSaveSuccess = (0, import_react12.useCallback)(() => {
|
|
2119
4161
|
setIsSaveSuccess(true);
|
|
2120
4162
|
setTimeout(() => {
|
|
2121
4163
|
setIsSaveSuccess(false);
|
|
2122
4164
|
}, 2500);
|
|
2123
4165
|
}, []);
|
|
2124
|
-
const handleQuietCellChange = (0,
|
|
4166
|
+
const handleQuietCellChange = (0, import_react12.useCallback)((rowId, colName, value) => {
|
|
2125
4167
|
setData((prev) => prev.map(
|
|
2126
4168
|
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
2127
4169
|
));
|
|
@@ -2209,7 +4251,7 @@ function TableBlockClient({
|
|
|
2209
4251
|
const formatPayload = (payload) => {
|
|
2210
4252
|
const formatted = {};
|
|
2211
4253
|
(localColumns || []).forEach((col) => {
|
|
2212
|
-
var _a, _b;
|
|
4254
|
+
var _a, _b, _c;
|
|
2213
4255
|
if (["_id", "id", "createdAt", "updatedAt", "orgId", "tableId", "isSelected"].includes(col.name)) return;
|
|
2214
4256
|
let val = payload[col.name];
|
|
2215
4257
|
if (val !== void 0) {
|
|
@@ -2219,7 +4261,9 @@ function TableBlockClient({
|
|
|
2219
4261
|
if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
|
|
2220
4262
|
val = val === "" ? 0 : Number(val);
|
|
2221
4263
|
if (isNaN(val)) val = 0;
|
|
2222
|
-
} else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "
|
|
4264
|
+
} else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "PHONE") {
|
|
4265
|
+
val = sanitizePhoneNumber(String(val));
|
|
4266
|
+
} else if (((_c = col.type) == null ? void 0 : _c.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
|
|
2223
4267
|
val = val.map((item) => {
|
|
2224
4268
|
const _a2 = item, { _resolvedData } = _a2, rest = __objRest(_a2, ["_resolvedData"]);
|
|
2225
4269
|
return rest;
|
|
@@ -2232,8 +4276,17 @@ function TableBlockClient({
|
|
|
2232
4276
|
return formatted;
|
|
2233
4277
|
};
|
|
2234
4278
|
const hasChanges = dirty.added.length > 0 || Object.keys(dirty.modified).length > 0 || dirty.deleted.length > 0;
|
|
4279
|
+
const handleRevertChanges = () => {
|
|
4280
|
+
setDirty({ added: [], modified: {}, deleted: [] });
|
|
4281
|
+
setData(serverRecords.map((r) => __spreadProps(__spreadValues({}, r), { data: __spreadValues({}, r.data) })));
|
|
4282
|
+
setSelectedIds(/* @__PURE__ */ new Set());
|
|
4283
|
+
setPendingDeletions([]);
|
|
4284
|
+
if (emitEvent) {
|
|
4285
|
+
emitEvent("SELECTION_CHANGE", { selectedIds: [], componentId });
|
|
4286
|
+
}
|
|
4287
|
+
};
|
|
2235
4288
|
const handleSave = async () => {
|
|
2236
|
-
var _a;
|
|
4289
|
+
var _a, _b;
|
|
2237
4290
|
if (!hasChanges) {
|
|
2238
4291
|
return;
|
|
2239
4292
|
}
|
|
@@ -2256,6 +4309,28 @@ function TableBlockClient({
|
|
|
2256
4309
|
}
|
|
2257
4310
|
}
|
|
2258
4311
|
}
|
|
4312
|
+
const phoneCols = (localColumns || []).filter((c) => {
|
|
4313
|
+
var _a2;
|
|
4314
|
+
return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE";
|
|
4315
|
+
});
|
|
4316
|
+
for (const col of phoneCols) {
|
|
4317
|
+
for (const row of dirty.added) {
|
|
4318
|
+
const val = row.data[col.name];
|
|
4319
|
+
if (!isEmpty(val) && !isValidPhoneNumber(val)) {
|
|
4320
|
+
showError(`\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 "${col.name}" \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D5\u05D5\u05DC\u05D9\u05D3\u05E6\u05D9\u05D4");
|
|
4321
|
+
return;
|
|
4322
|
+
}
|
|
4323
|
+
}
|
|
4324
|
+
for (const [rowId, mods] of Object.entries(dirty.modified)) {
|
|
4325
|
+
const rowData = ((_b = data.find((r) => r.id === rowId)) == null ? void 0 : _b.data) || {};
|
|
4326
|
+
const mergedData = __spreadValues(__spreadValues({}, rowData), mods);
|
|
4327
|
+
const val = mergedData[col.name];
|
|
4328
|
+
if (!isEmpty(val) && !isValidPhoneNumber(val)) {
|
|
4329
|
+
showError(`\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 "${col.name}" \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D5\u05D5\u05DC\u05D9\u05D3\u05E6\u05D9\u05D4");
|
|
4330
|
+
return;
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
2259
4334
|
setIsSaving(true);
|
|
2260
4335
|
try {
|
|
2261
4336
|
if (!executeAction) {
|
|
@@ -2356,18 +4431,89 @@ function TableBlockClient({
|
|
|
2356
4431
|
setIsSaving(false);
|
|
2357
4432
|
}
|
|
2358
4433
|
};
|
|
2359
|
-
const
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
)
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
4434
|
+
const getRowRelationLabels = (0, import_react12.useCallback)((rowVal, col) => {
|
|
4435
|
+
const ids = normalizeRelationValue(rowVal);
|
|
4436
|
+
if (ids.length === 0) return [];
|
|
4437
|
+
const options = relationOptions[col.name] || [];
|
|
4438
|
+
return ids.map((id) => {
|
|
4439
|
+
const opt = options.find((o) => o.id === id || o._id === id);
|
|
4440
|
+
if (opt) {
|
|
4441
|
+
const resolved = resolveRelationLabel(opt, col);
|
|
4442
|
+
if (resolved) return resolved;
|
|
4443
|
+
if (opt.label) return String(opt.label);
|
|
4444
|
+
if (opt.name) return String(opt.name);
|
|
4445
|
+
}
|
|
4446
|
+
if (typeof rowVal === "object" && rowVal !== null) {
|
|
4447
|
+
if (rowVal._displayLabel) return String(rowVal._displayLabel);
|
|
4448
|
+
if (rowVal.label) return String(rowVal.label);
|
|
4449
|
+
}
|
|
4450
|
+
return id;
|
|
4451
|
+
});
|
|
4452
|
+
}, [relationOptions]);
|
|
4453
|
+
const getUniqueRelationOptions = (0, import_react12.useCallback)((col) => {
|
|
4454
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
4455
|
+
const results = [];
|
|
4456
|
+
const options = relationOptions[col.name] || [];
|
|
4457
|
+
data.forEach((row) => {
|
|
4458
|
+
if (!(row == null ? void 0 : row.data)) return;
|
|
4459
|
+
const ids = normalizeRelationValue(row.data[col.name]);
|
|
4460
|
+
ids.forEach((id) => {
|
|
4461
|
+
if (!seenIds.has(id)) {
|
|
4462
|
+
seenIds.add(id);
|
|
4463
|
+
const opt = options.find((o) => o.id === id || o._id === id);
|
|
4464
|
+
let label = opt ? resolveRelationLabel(opt, col) : "";
|
|
4465
|
+
if (!label && opt) label = opt.label || opt.name || opt.title || id;
|
|
4466
|
+
if (!label) label = id;
|
|
4467
|
+
results.push({ id, label });
|
|
4468
|
+
}
|
|
4469
|
+
});
|
|
4470
|
+
});
|
|
4471
|
+
return results.sort((a, b) => a.label.localeCompare(b.label));
|
|
4472
|
+
}, [data, relationOptions]);
|
|
4473
|
+
const filteredData = (0, import_react12.useMemo)(() => {
|
|
4474
|
+
const hasGlobalSearch = Boolean(searchQuery && searchQuery.trim() !== "");
|
|
4475
|
+
const activeFilters = Object.entries(columnFilters).filter(([, val]) => Boolean(val && val.trim() !== ""));
|
|
4476
|
+
const hasColumnFilters = activeFilters.length > 0;
|
|
4477
|
+
if (!hasGlobalSearch && !hasColumnFilters) return data;
|
|
4478
|
+
const lowerGlobal = hasGlobalSearch ? searchQuery.trim().toLowerCase() : "";
|
|
4479
|
+
return data.filter((row) => {
|
|
4480
|
+
var _a;
|
|
4481
|
+
if (!row || !row.data) return false;
|
|
4482
|
+
if (hasGlobalSearch) {
|
|
4483
|
+
const matchesGlobal = (localColumns || []).some((col) => {
|
|
4484
|
+
var _a2;
|
|
4485
|
+
const rawVal = row.data[col.name];
|
|
4486
|
+
if (rawVal === void 0 || rawVal === null) return false;
|
|
4487
|
+
if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION") {
|
|
4488
|
+
const labels = getRowRelationLabels(rawVal, col);
|
|
4489
|
+
return labels.some((l) => l.toLowerCase().includes(lowerGlobal));
|
|
4490
|
+
}
|
|
4491
|
+
if (typeof rawVal === "object") {
|
|
4492
|
+
return JSON.stringify(rawVal).toLowerCase().includes(lowerGlobal);
|
|
4493
|
+
}
|
|
4494
|
+
return String(rawVal).toLowerCase().includes(lowerGlobal);
|
|
4495
|
+
});
|
|
4496
|
+
if (!matchesGlobal) return false;
|
|
4497
|
+
}
|
|
4498
|
+
for (const [colName, filterVal] of activeFilters) {
|
|
4499
|
+
const lowerFilter = filterVal.trim().toLowerCase();
|
|
4500
|
+
const col = (localColumns || []).find((c) => c.name === colName);
|
|
4501
|
+
const rawVal = row.data[colName];
|
|
4502
|
+
if (((_a = col == null ? void 0 : col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION") {
|
|
4503
|
+
const labels = getRowRelationLabels(rawVal, col);
|
|
4504
|
+
const matches = labels.some((l) => l.toLowerCase().includes(lowerFilter));
|
|
4505
|
+
if (!matches) return false;
|
|
4506
|
+
} else {
|
|
4507
|
+
if (rawVal === void 0 || rawVal === null) return false;
|
|
4508
|
+
const strVal = typeof rawVal === "object" ? JSON.stringify(rawVal).toLowerCase() : String(rawVal).toLowerCase();
|
|
4509
|
+
if (!strVal.includes(lowerFilter)) return false;
|
|
4510
|
+
}
|
|
4511
|
+
}
|
|
4512
|
+
return true;
|
|
4513
|
+
});
|
|
4514
|
+
}, [data, searchQuery, columnFilters, localColumns, getRowRelationLabels]);
|
|
2369
4515
|
const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
|
|
2370
|
-
const columnTotals = (0,
|
|
4516
|
+
const columnTotals = (0, import_react12.useMemo)(() => {
|
|
2371
4517
|
const totals = {};
|
|
2372
4518
|
if (!showSummary) return totals;
|
|
2373
4519
|
filteredColumns.forEach((col) => {
|
|
@@ -2385,7 +4531,7 @@ function TableBlockClient({
|
|
|
2385
4531
|
});
|
|
2386
4532
|
return totals;
|
|
2387
4533
|
}, [filteredData, filteredColumns, showSummary]);
|
|
2388
|
-
return /* @__PURE__ */ (0,
|
|
4534
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2389
4535
|
"div",
|
|
2390
4536
|
{
|
|
2391
4537
|
id: componentId,
|
|
@@ -2393,34 +4539,34 @@ function TableBlockClient({
|
|
|
2393
4539
|
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
|
|
2394
4540
|
dir: "rtl",
|
|
2395
4541
|
children: [
|
|
2396
|
-
errorMessage && /* @__PURE__ */ (0,
|
|
2397
|
-
/* @__PURE__ */ (0,
|
|
2398
|
-
/* @__PURE__ */ (0,
|
|
4542
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
4543
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
4544
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: errorMessage })
|
|
2399
4545
|
] }) }),
|
|
2400
|
-
/* @__PURE__ */ (0,
|
|
2401
|
-
/* @__PURE__ */ (0,
|
|
2402
|
-
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0,
|
|
2403
|
-
/* @__PURE__ */ (0,
|
|
4546
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200", children: [
|
|
4547
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
4548
|
+
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: schema.title || schema.name }) }),
|
|
4549
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2404
4550
|
"button",
|
|
2405
4551
|
{
|
|
2406
4552
|
onClick: handleAddRow,
|
|
2407
|
-
disabled: isLoading || isUpdatingActive,
|
|
2408
|
-
className:
|
|
2409
|
-
title: "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
2410
|
-
children: /* @__PURE__ */ (0,
|
|
4553
|
+
disabled: isInitialLoading || isLoading || isUpdatingActive,
|
|
4554
|
+
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"}`,
|
|
4555
|
+
title: isInitialLoading ? "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." : "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
4556
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
|
|
2411
4557
|
}
|
|
2412
4558
|
),
|
|
2413
|
-
/* @__PURE__ */ (0,
|
|
4559
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2414
4560
|
"button",
|
|
2415
4561
|
{
|
|
2416
4562
|
onClick: handleDuplicateRow,
|
|
2417
|
-
disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
4563
|
+
disabled: isInitialLoading || isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
2418
4564
|
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",
|
|
2419
4565
|
title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
|
|
2420
|
-
children: /* @__PURE__ */ (0,
|
|
4566
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.Copy, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
2421
4567
|
}
|
|
2422
4568
|
),
|
|
2423
|
-
/* @__PURE__ */ (0,
|
|
4569
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2424
4570
|
"button",
|
|
2425
4571
|
{
|
|
2426
4572
|
onClick: handleDeleteSelected,
|
|
@@ -2428,12 +4574,12 @@ function TableBlockClient({
|
|
|
2428
4574
|
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",
|
|
2429
4575
|
title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
|
|
2430
4576
|
children: [
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2432
|
-
selectedIds.size > 0 && /* @__PURE__ */ (0,
|
|
4577
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
|
|
4578
|
+
selectedIds.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "absolute -top-1.5 -right-1.5 bg-rose-600 text-white min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs", children: selectedIds.size })
|
|
2433
4579
|
]
|
|
2434
4580
|
}
|
|
2435
4581
|
),
|
|
2436
|
-
/* @__PURE__ */ (0,
|
|
4582
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2437
4583
|
"button",
|
|
2438
4584
|
{
|
|
2439
4585
|
onClick: toggleSummary,
|
|
@@ -2441,13 +4587,13 @@ function TableBlockClient({
|
|
|
2441
4587
|
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"}`,
|
|
2442
4588
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
|
|
2443
4589
|
children: [
|
|
2444
|
-
/* @__PURE__ */ (0,
|
|
2445
|
-
/* @__PURE__ */ (0,
|
|
4590
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
|
|
4591
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
|
|
2446
4592
|
]
|
|
2447
4593
|
}
|
|
2448
4594
|
),
|
|
2449
|
-
/* @__PURE__ */ (0,
|
|
2450
|
-
/* @__PURE__ */ (0,
|
|
4595
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
|
|
4596
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2451
4597
|
"button",
|
|
2452
4598
|
{
|
|
2453
4599
|
onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
|
|
@@ -2455,16 +4601,16 @@ function TableBlockClient({
|
|
|
2455
4601
|
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",
|
|
2456
4602
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
|
|
2457
4603
|
children: [
|
|
2458
|
-
/* @__PURE__ */ (0,
|
|
2459
|
-
/* @__PURE__ */ (0,
|
|
4604
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) }),
|
|
4605
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: `w-3.5 h-3.5 text-slate-500 transition-transform ${isColumnsDropdownOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
|
|
2460
4606
|
]
|
|
2461
4607
|
}
|
|
2462
4608
|
),
|
|
2463
|
-
isColumnsDropdownOpen && /* @__PURE__ */ (0,
|
|
2464
|
-
/* @__PURE__ */ (0,
|
|
2465
|
-
/* @__PURE__ */ (0,
|
|
2466
|
-
/* @__PURE__ */ (0,
|
|
2467
|
-
/* @__PURE__ */ (0,
|
|
4609
|
+
isColumnsDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-56 bg-white border border-slate-200 rounded-xl shadow-xl z-50 p-1.5 dir-rtl animate-in fade-in slide-in-from-top-2 duration-150", children: [
|
|
4610
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "px-2 py-1.5 text-xs font-bold text-slate-500 border-b border-slate-100 mb-1 flex items-center justify-between", children: [
|
|
4611
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
4612
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
|
|
4613
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-[10px] font-normal text-slate-400", children: [
|
|
2468
4614
|
"(",
|
|
2469
4615
|
customizableColumns.filter((c) => !c.isHidden).length,
|
|
2470
4616
|
"/",
|
|
@@ -2472,7 +4618,7 @@ function TableBlockClient({
|
|
|
2472
4618
|
")"
|
|
2473
4619
|
] })
|
|
2474
4620
|
] }),
|
|
2475
|
-
/* @__PURE__ */ (0,
|
|
4621
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2476
4622
|
"button",
|
|
2477
4623
|
{
|
|
2478
4624
|
type: "button",
|
|
@@ -2482,7 +4628,7 @@ function TableBlockClient({
|
|
|
2482
4628
|
}
|
|
2483
4629
|
)
|
|
2484
4630
|
] }),
|
|
2485
|
-
/* @__PURE__ */ (0,
|
|
4631
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
|
|
2486
4632
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
2487
4633
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
2488
4634
|
const isProtected = isRequired || isUnique;
|
|
@@ -2496,7 +4642,7 @@ function TableBlockClient({
|
|
|
2496
4642
|
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";
|
|
2497
4643
|
}
|
|
2498
4644
|
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";
|
|
2499
|
-
return /* @__PURE__ */ (0,
|
|
4645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2500
4646
|
"div",
|
|
2501
4647
|
{
|
|
2502
4648
|
onClick: () => {
|
|
@@ -2507,8 +4653,8 @@ function TableBlockClient({
|
|
|
2507
4653
|
title: isProtected ? protectedExplanation : void 0,
|
|
2508
4654
|
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"}`,
|
|
2509
4655
|
children: [
|
|
2510
|
-
/* @__PURE__ */ (0,
|
|
2511
|
-
/* @__PURE__ */ (0,
|
|
4656
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
4657
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2512
4658
|
"input",
|
|
2513
4659
|
{
|
|
2514
4660
|
type: "checkbox",
|
|
@@ -2519,16 +4665,16 @@ function TableBlockClient({
|
|
|
2519
4665
|
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"
|
|
2520
4666
|
}
|
|
2521
4667
|
),
|
|
2522
|
-
/* @__PURE__ */ (0,
|
|
4668
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
|
|
2523
4669
|
] }),
|
|
2524
|
-
isProtected && /* @__PURE__ */ (0,
|
|
4670
|
+
isProtected && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2525
4671
|
"div",
|
|
2526
4672
|
{
|
|
2527
4673
|
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",
|
|
2528
4674
|
title: protectedExplanation,
|
|
2529
4675
|
children: [
|
|
2530
|
-
/* @__PURE__ */ (0,
|
|
2531
|
-
/* @__PURE__ */ (0,
|
|
4676
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3 h-3 text-amber-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "2.2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
|
|
4677
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: badgeLabel })
|
|
2532
4678
|
]
|
|
2533
4679
|
}
|
|
2534
4680
|
)
|
|
@@ -2539,9 +4685,9 @@ function TableBlockClient({
|
|
|
2539
4685
|
}) })
|
|
2540
4686
|
] })
|
|
2541
4687
|
] }),
|
|
2542
|
-
/* @__PURE__ */ (0,
|
|
2543
|
-
/* @__PURE__ */ (0,
|
|
2544
|
-
/* @__PURE__ */ (0,
|
|
4688
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
4689
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
4690
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2545
4691
|
"input",
|
|
2546
4692
|
{
|
|
2547
4693
|
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
@@ -2551,129 +4697,224 @@ function TableBlockClient({
|
|
|
2551
4697
|
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"
|
|
2552
4698
|
}
|
|
2553
4699
|
),
|
|
2554
|
-
searchQuery ? /* @__PURE__ */ (0,
|
|
4700
|
+
searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2555
4701
|
"button",
|
|
2556
4702
|
{
|
|
2557
4703
|
type: "button",
|
|
2558
4704
|
onClick: () => setSearchQuery(""),
|
|
2559
4705
|
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",
|
|
2560
4706
|
title: "Clear search",
|
|
2561
|
-
children: /* @__PURE__ */ (0,
|
|
4707
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.X, { className: "w-3.5 h-3.5" })
|
|
2562
4708
|
}
|
|
2563
|
-
) : /* @__PURE__ */ (0,
|
|
4709
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
|
|
2564
4710
|
] })
|
|
2565
4711
|
] }),
|
|
2566
|
-
/* @__PURE__ */ (0,
|
|
2567
|
-
isUpdatingActive ? /* @__PURE__ */ (0,
|
|
2568
|
-
/* @__PURE__ */ (0,
|
|
4712
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
4713
|
+
isUpdatingActive ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-xs text-blue-600 font-semibold flex items-center gap-1.5 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-lg animate-pulse", children: [
|
|
4714
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
2569
4715
|
"\u05DE\u05E2\u05D3\u05DB\u05DF..."
|
|
2570
|
-
] }) : isSaveSuccess ? /* @__PURE__ */ (0,
|
|
2571
|
-
/* @__PURE__ */ (0,
|
|
4716
|
+
] }) : isSaveSuccess ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
|
|
4717
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
|
|
2572
4718
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
2573
|
-
] }) : hasChanges ? /* @__PURE__ */ (0,
|
|
2574
|
-
|
|
4719
|
+
] }) : hasChanges ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1.5 animate-in fade-in", children: [
|
|
4720
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs font-semibold text-amber-700", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }),
|
|
4721
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4722
|
+
"button",
|
|
4723
|
+
{
|
|
4724
|
+
type: "button",
|
|
4725
|
+
onClick: handleRevertChanges,
|
|
4726
|
+
disabled: isUpdatingActive,
|
|
4727
|
+
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",
|
|
4728
|
+
title: "\u05D1\u05D8\u05DC \u05D0\u05EA \u05DB\u05DC \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5",
|
|
4729
|
+
"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",
|
|
4730
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.RotateCcw, { className: "w-3.5 h-3.5" })
|
|
4731
|
+
}
|
|
4732
|
+
)
|
|
4733
|
+
] }) : null,
|
|
4734
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2575
4735
|
"button",
|
|
2576
4736
|
{
|
|
2577
4737
|
onClick: handleSave,
|
|
2578
4738
|
disabled: isUpdatingActive || isLoading || !hasChanges,
|
|
2579
4739
|
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"}`,
|
|
2580
|
-
children: /* @__PURE__ */ (0,
|
|
4740
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
|
|
2581
4741
|
}
|
|
2582
4742
|
)
|
|
2583
4743
|
] })
|
|
2584
4744
|
] }),
|
|
2585
|
-
/* @__PURE__ */ (0,
|
|
2586
|
-
isLoading && /* @__PURE__ */ (0,
|
|
2587
|
-
/* @__PURE__ */ (0,
|
|
2588
|
-
/* @__PURE__ */ (0,
|
|
4745
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
|
|
4746
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
|
|
4747
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
4748
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
2589
4749
|
] }),
|
|
2590
|
-
/* @__PURE__ */ (0,
|
|
2591
|
-
/* @__PURE__ */ (0,
|
|
2592
|
-
/* @__PURE__ */ (0,
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
4750
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
|
|
4751
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { className: "h-12 min-h-[48px]", children: [
|
|
4752
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { className: "border-b border-l border-slate-200 p-1.5 text-center shrink-0 h-12 min-h-[48px] align-middle", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-center gap-1.5", children: [
|
|
4753
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4754
|
+
"input",
|
|
4755
|
+
{
|
|
4756
|
+
type: "checkbox",
|
|
4757
|
+
checked: filteredData.length > 0 && selectedIds.size === filteredData.length,
|
|
4758
|
+
onChange: (e) => toggleSelectAll(e.target.checked),
|
|
4759
|
+
disabled: isLoading || isUpdatingActive,
|
|
4760
|
+
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
4761
|
+
}
|
|
4762
|
+
),
|
|
4763
|
+
filteredColumns.some((c) => {
|
|
4764
|
+
var _a;
|
|
4765
|
+
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
4766
|
+
}) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-5 h-5 shrink-0" })
|
|
4767
|
+
] }) }),
|
|
2602
4768
|
filteredColumns.map((col) => {
|
|
2603
|
-
|
|
2604
|
-
const
|
|
2605
|
-
const
|
|
2606
|
-
|
|
4769
|
+
var _a, _b;
|
|
4770
|
+
const isSearching = activeSearchCol === col.name;
|
|
4771
|
+
const dragProps = isSearching ? {} : getHeaderDragProps(col.name);
|
|
4772
|
+
const isDragging = !isSearching && draggedColName === col.name;
|
|
4773
|
+
const isDragOver = !isSearching && dragOverColName === col.name;
|
|
4774
|
+
const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
|
|
4775
|
+
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
|
|
4776
|
+
const isRelation = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
|
|
4777
|
+
const filterVal = columnFilters[col.name] || "";
|
|
4778
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2607
4779
|
"th",
|
|
2608
|
-
{
|
|
4780
|
+
__spreadProps(__spreadValues({
|
|
2609
4781
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
e.dataTransfer.effectAllowed = "move";
|
|
2614
|
-
setDraggedColName(col.name);
|
|
2615
|
-
},
|
|
2616
|
-
onDragOver: (e) => {
|
|
2617
|
-
e.preventDefault();
|
|
2618
|
-
e.dataTransfer.dropEffect = "move";
|
|
2619
|
-
if (dragOverColName !== col.name) {
|
|
2620
|
-
setDragOverColName(col.name);
|
|
2621
|
-
}
|
|
2622
|
-
},
|
|
2623
|
-
onDragLeave: () => {
|
|
2624
|
-
if (dragOverColName === col.name) {
|
|
2625
|
-
setDragOverColName(null);
|
|
2626
|
-
}
|
|
2627
|
-
},
|
|
2628
|
-
onDrop: (e) => {
|
|
2629
|
-
e.preventDefault();
|
|
2630
|
-
if (draggedColName && draggedColName !== col.name) {
|
|
2631
|
-
handleColumnReorder(draggedColName, col.name);
|
|
2632
|
-
}
|
|
2633
|
-
setDraggedColName(null);
|
|
2634
|
-
setDragOverColName(null);
|
|
2635
|
-
},
|
|
2636
|
-
onDragEnd: () => {
|
|
2637
|
-
setDraggedColName(null);
|
|
2638
|
-
setDragOverColName(null);
|
|
2639
|
-
},
|
|
2640
|
-
className: `relative border-b border-l border-slate-200 px-4 py-2.5 font-semibold text-slate-700 whitespace-nowrap select-none cursor-grab active:cursor-grabbing transition-colors ${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" : "hover:bg-slate-200/60"}`,
|
|
4782
|
+
title: isSearching ? void 0 : col.name
|
|
4783
|
+
}, dragProps), {
|
|
4784
|
+
className: `relative border-b border-l border-slate-200 px-2.5 py-1.5 font-semibold text-slate-700 select-none transition-colors h-12 min-h-[48px] align-middle ${isSearching ? "cursor-default bg-blue-50/40" : "cursor-grab active:cursor-grabbing hover:bg-slate-200/60"} ${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" : ""}`,
|
|
2641
4785
|
children: [
|
|
2642
|
-
/* @__PURE__ */ (0,
|
|
4786
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2643
4787
|
"div",
|
|
2644
4788
|
{
|
|
2645
4789
|
onMouseDown: (e) => {
|
|
2646
4790
|
e.preventDefault();
|
|
2647
4791
|
e.stopPropagation();
|
|
2648
|
-
|
|
4792
|
+
startResize(col.name, currentWidth, e.clientX, colMinWidth);
|
|
2649
4793
|
},
|
|
2650
4794
|
className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-brand active:bg-brand-hover z-20",
|
|
2651
4795
|
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
2652
4796
|
}
|
|
2653
4797
|
),
|
|
2654
|
-
/* @__PURE__ */ (0,
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
4798
|
+
isSearching ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4799
|
+
"div",
|
|
4800
|
+
{
|
|
4801
|
+
ref: activeSearchRef,
|
|
4802
|
+
className: "flex items-center gap-1 w-full",
|
|
4803
|
+
onClick: (e) => e.stopPropagation(),
|
|
4804
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
4805
|
+
children: [
|
|
4806
|
+
isRelation ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
4807
|
+
"select",
|
|
4808
|
+
{
|
|
4809
|
+
autoFocus: true,
|
|
4810
|
+
value: filterVal,
|
|
4811
|
+
onChange: (e) => {
|
|
4812
|
+
const val = e.target.value;
|
|
4813
|
+
setColumnFilters((prev) => {
|
|
4814
|
+
const next = __spreadValues({}, prev);
|
|
4815
|
+
if (val) next[col.name] = val;
|
|
4816
|
+
else delete next[col.name];
|
|
4817
|
+
return next;
|
|
4818
|
+
});
|
|
4819
|
+
},
|
|
4820
|
+
onKeyDown: (e) => {
|
|
4821
|
+
if (e.key === "Escape" || e.key === "Enter") {
|
|
4822
|
+
setActiveSearchCol(null);
|
|
4823
|
+
}
|
|
4824
|
+
},
|
|
4825
|
+
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",
|
|
4826
|
+
children: [
|
|
4827
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", children: "\u05D4\u05DB\u05DC" }),
|
|
4828
|
+
getUniqueRelationOptions(col).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: opt.label, children: opt.label }, opt.id))
|
|
4829
|
+
]
|
|
4830
|
+
}
|
|
4831
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4832
|
+
"input",
|
|
4833
|
+
{
|
|
4834
|
+
autoFocus: true,
|
|
4835
|
+
type: "text",
|
|
4836
|
+
placeholder: `\u05D7\u05E4\u05E9 \u05D1-${col.name}...`,
|
|
4837
|
+
value: filterVal,
|
|
4838
|
+
onChange: (e) => {
|
|
4839
|
+
const val = e.target.value;
|
|
4840
|
+
setColumnFilters((prev) => {
|
|
4841
|
+
const next = __spreadValues({}, prev);
|
|
4842
|
+
if (val) next[col.name] = val;
|
|
4843
|
+
else delete next[col.name];
|
|
4844
|
+
return next;
|
|
4845
|
+
});
|
|
4846
|
+
},
|
|
4847
|
+
onKeyDown: (e) => {
|
|
4848
|
+
if (e.key === "Escape" || e.key === "Enter") {
|
|
4849
|
+
setActiveSearchCol(null);
|
|
4850
|
+
}
|
|
4851
|
+
},
|
|
4852
|
+
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"
|
|
4853
|
+
}
|
|
4854
|
+
) }),
|
|
4855
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4856
|
+
"button",
|
|
4857
|
+
{
|
|
4858
|
+
type: "button",
|
|
4859
|
+
onMouseDown: (e) => {
|
|
4860
|
+
e.preventDefault();
|
|
4861
|
+
e.stopPropagation();
|
|
4862
|
+
},
|
|
4863
|
+
onClick: (e) => {
|
|
4864
|
+
e.stopPropagation();
|
|
4865
|
+
setColumnFilters((prev) => {
|
|
4866
|
+
const next = __spreadValues({}, prev);
|
|
4867
|
+
delete next[col.name];
|
|
4868
|
+
return next;
|
|
4869
|
+
});
|
|
4870
|
+
setActiveSearchCol(null);
|
|
4871
|
+
},
|
|
4872
|
+
className: "p-1 text-slate-400 hover:text-slate-700 hover:bg-slate-200/70 rounded transition-colors cursor-pointer shrink-0",
|
|
4873
|
+
title: "\u05E0\u05E7\u05D4 \u05D5\u05E1\u05D2\u05D5\u05E8 \u05D7\u05D9\u05E4\u05D5\u05E9",
|
|
4874
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.X, { className: "w-3.5 h-3.5" })
|
|
4875
|
+
}
|
|
4876
|
+
)
|
|
4877
|
+
]
|
|
4878
|
+
}
|
|
4879
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between gap-1.5 group overflow-hidden w-full", title: col.name, children: [
|
|
4880
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex items-center gap-1.5 min-w-0 flex-1 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ColumnHeaderTitle, { name: col.name, width: currentWidth, isSubTable: false }) }),
|
|
4881
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
4882
|
+
((_b = col.type) == null ? void 0 : _b.toUpperCase()) !== "SUB_TABLE" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4883
|
+
"button",
|
|
4884
|
+
{
|
|
4885
|
+
type: "button",
|
|
4886
|
+
onClick: (e) => {
|
|
4887
|
+
e.stopPropagation();
|
|
4888
|
+
e.preventDefault();
|
|
4889
|
+
setActiveSearchCol(col.name);
|
|
4890
|
+
},
|
|
4891
|
+
className: `p-1 rounded transition-all cursor-pointer ${filterVal ? "opacity-100 text-blue-600 bg-blue-100 hover:bg-blue-200" : "opacity-0 group-hover:opacity-100 text-slate-400 hover:text-slate-600 hover:bg-slate-200/60"}`,
|
|
4892
|
+
title: filterVal ? `\u05DE\u05E1\u05D5\u05E0\u05DF \u05DC\u05E4\u05D9: "${filterVal}" (\u05DC\u05D7\u05E5 \u05DC\u05E2\u05E8\u05D9\u05DB\u05D4)` : "\u05D7\u05E4\u05E9 \u05D5\u05E1\u05E0\u05DF \u05D1\u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5",
|
|
4893
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.Search, { className: "w-3.5 h-3.5" })
|
|
4894
|
+
}
|
|
4895
|
+
),
|
|
4896
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4897
|
+
"svg",
|
|
4898
|
+
{
|
|
4899
|
+
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
4900
|
+
fill: "none",
|
|
4901
|
+
viewBox: "0 0 24 24",
|
|
4902
|
+
stroke: "currentColor",
|
|
4903
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
|
|
4904
|
+
}
|
|
4905
|
+
)
|
|
4906
|
+
] })
|
|
2666
4907
|
] })
|
|
2667
4908
|
]
|
|
2668
|
-
},
|
|
4909
|
+
}),
|
|
2669
4910
|
col.name
|
|
2670
4911
|
);
|
|
2671
4912
|
}),
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
4913
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none h-12 min-h-[48px]" })
|
|
2673
4914
|
] }) }),
|
|
2674
|
-
/* @__PURE__ */ (0,
|
|
2675
|
-
/* @__PURE__ */ (0,
|
|
2676
|
-
/* @__PURE__ */ (0,
|
|
4915
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
4916
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
|
|
4917
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
2677
4918
|
] }) }) }) : filteredData.map((row) => {
|
|
2678
4919
|
const hasSubTableCols = filteredColumns.some((c) => {
|
|
2679
4920
|
var _a;
|
|
@@ -2684,10 +4925,20 @@ function TableBlockClient({
|
|
|
2684
4925
|
var _a;
|
|
2685
4926
|
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
2686
4927
|
});
|
|
2687
|
-
return /* @__PURE__ */ (0,
|
|
2688
|
-
/* @__PURE__ */ (0,
|
|
2689
|
-
/* @__PURE__ */ (0,
|
|
2690
|
-
|
|
4928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react12.default.Fragment, { children: [
|
|
4929
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
|
|
4930
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-center gap-1.5", children: [
|
|
4931
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4932
|
+
"input",
|
|
4933
|
+
{
|
|
4934
|
+
type: "checkbox",
|
|
4935
|
+
checked: selectedIds.has(row.id),
|
|
4936
|
+
onChange: (e) => toggleSelectRow(row.id, e.target.checked),
|
|
4937
|
+
disabled: isLoading || isUpdatingActive,
|
|
4938
|
+
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
4939
|
+
}
|
|
4940
|
+
),
|
|
4941
|
+
hasSubTableCols && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2691
4942
|
"button",
|
|
2692
4943
|
{
|
|
2693
4944
|
type: "button",
|
|
@@ -2697,19 +4948,9 @@ function TableBlockClient({
|
|
|
2697
4948
|
else next.add(row.id);
|
|
2698
4949
|
return next;
|
|
2699
4950
|
}),
|
|
2700
|
-
className: "
|
|
4951
|
+
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",
|
|
2701
4952
|
title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
|
|
2702
|
-
children: /* @__PURE__ */ (0,
|
|
2703
|
-
}
|
|
2704
|
-
),
|
|
2705
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2706
|
-
"input",
|
|
2707
|
-
{
|
|
2708
|
-
type: "checkbox",
|
|
2709
|
-
checked: selectedIds.has(row.id),
|
|
2710
|
-
onChange: (e) => toggleSelectRow(row.id, e.target.checked),
|
|
2711
|
-
disabled: isLoading || isUpdatingActive,
|
|
2712
|
-
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
4953
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: `w-3 h-3 transition-transform duration-150 ${isExpanded ? "rotate-90" : "rotate-180"}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", d: "M9 5l7 7-7 7" }) })
|
|
2713
4954
|
}
|
|
2714
4955
|
)
|
|
2715
4956
|
] }) }),
|
|
@@ -2717,6 +4958,8 @@ function TableBlockClient({
|
|
|
2717
4958
|
var _a;
|
|
2718
4959
|
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
2719
4960
|
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
4961
|
+
const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
|
|
4962
|
+
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
|
|
2720
4963
|
let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
|
|
2721
4964
|
if (value === void 0 && col.defaultValue !== void 0) {
|
|
2722
4965
|
value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
|
|
@@ -2725,34 +4968,42 @@ function TableBlockClient({
|
|
|
2725
4968
|
}
|
|
2726
4969
|
}
|
|
2727
4970
|
if (value === void 0) value = null;
|
|
2728
|
-
return /* @__PURE__ */ (0,
|
|
2729
|
-
|
|
4971
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4972
|
+
"td",
|
|
2730
4973
|
{
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
4974
|
+
className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
|
|
4975
|
+
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
4976
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
4977
|
+
InputComponent,
|
|
4978
|
+
{
|
|
4979
|
+
value,
|
|
4980
|
+
column: col,
|
|
4981
|
+
rowId: row.id,
|
|
4982
|
+
onChange: (v) => handleCellChange(row.id, col.name, v),
|
|
4983
|
+
context: {
|
|
4984
|
+
tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
|
|
4985
|
+
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
4986
|
+
onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
|
|
4987
|
+
relationOptions,
|
|
4988
|
+
refetchRelation,
|
|
4989
|
+
executeAction,
|
|
4990
|
+
emitEvent,
|
|
4991
|
+
pageState,
|
|
4992
|
+
componentId,
|
|
4993
|
+
orgId,
|
|
4994
|
+
updateQuietly: handleQuietCellChange,
|
|
4995
|
+
triggerSaveSuccess,
|
|
4996
|
+
rowData: row.data
|
|
4997
|
+
}
|
|
4998
|
+
}
|
|
4999
|
+
)
|
|
5000
|
+
},
|
|
5001
|
+
col.name
|
|
5002
|
+
);
|
|
2752
5003
|
}),
|
|
2753
|
-
/* @__PURE__ */ (0,
|
|
5004
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
2754
5005
|
] }),
|
|
2755
|
-
isExpanded && /* @__PURE__ */ (0,
|
|
5006
|
+
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2756
5007
|
ExpandedSubTables,
|
|
2757
5008
|
{
|
|
2758
5009
|
rowId: row.id,
|
|
@@ -2767,37 +5018,38 @@ function TableBlockClient({
|
|
|
2767
5018
|
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
2768
5019
|
rowData: row.data,
|
|
2769
5020
|
updateQuietly: handleQuietCellChange,
|
|
2770
|
-
triggerSaveSuccess
|
|
5021
|
+
triggerSaveSuccess,
|
|
5022
|
+
onUpdateColumnConfig: handleUpdateColumnConfig
|
|
2771
5023
|
}
|
|
2772
5024
|
}
|
|
2773
5025
|
)
|
|
2774
5026
|
] }, row.id);
|
|
2775
5027
|
}) }),
|
|
2776
|
-
showSummary && filteredData.length > 0 && /* @__PURE__ */ (0,
|
|
2777
|
-
/* @__PURE__ */ (0,
|
|
5028
|
+
showSummary && filteredData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tfoot", { className: "bg-slate-50 border-t-2 border-slate-300 sticky bottom-0 z-10 shadow-[0_-2px_4px_rgba(0,0,0,0.02)]", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { children: [
|
|
5029
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center font-bold text-slate-600 text-xs", children: '\u05E1\u05D4"\u05DB' }),
|
|
2778
5030
|
filteredColumns.map((col) => {
|
|
2779
|
-
var _a;
|
|
5031
|
+
var _a, _b;
|
|
2780
5032
|
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
2781
5033
|
const isNumeric = typeUpper === "CURRENCY" || typeUpper === "NUMBER";
|
|
2782
5034
|
const total = columnTotals[col.name];
|
|
2783
5035
|
let displayVal = "";
|
|
2784
5036
|
if (isNumeric && total !== void 0) {
|
|
2785
5037
|
displayVal = new Intl.NumberFormat("en-US").format(total);
|
|
2786
|
-
if (
|
|
2787
|
-
const symbol = getCurrencySymbol(col.currencySymbol);
|
|
5038
|
+
if (col.type === "CURRENCY") {
|
|
5039
|
+
const symbol = getCurrencySymbol((_b = col.config) == null ? void 0 : _b.currencySymbol);
|
|
2788
5040
|
displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
|
|
2789
5041
|
}
|
|
2790
5042
|
}
|
|
2791
|
-
return /* @__PURE__ */ (0,
|
|
5043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-l border-slate-200 p-2 text-sm font-semibold text-slate-700 bg-slate-50 relative", children: isNumeric && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "truncate", children: displayVal }) }) }, col.name);
|
|
2792
5044
|
}),
|
|
2793
|
-
/* @__PURE__ */ (0,
|
|
5045
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
|
|
2794
5046
|
] }) })
|
|
2795
5047
|
] })
|
|
2796
5048
|
] }),
|
|
2797
|
-
/* @__PURE__ */ (0,
|
|
2798
|
-
/* @__PURE__ */ (0,
|
|
2799
|
-
/* @__PURE__ */ (0,
|
|
2800
|
-
/* @__PURE__ */ (0,
|
|
5049
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 bg-slate-50 border-t border-slate-200 text-xs text-slate-600 rounded-b-xl", children: [
|
|
5050
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5051
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
|
|
5052
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2801
5053
|
"select",
|
|
2802
5054
|
{
|
|
2803
5055
|
value: limit,
|
|
@@ -2805,27 +5057,27 @@ function TableBlockClient({
|
|
|
2805
5057
|
disabled: isLoading || isUpdatingActive,
|
|
2806
5058
|
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",
|
|
2807
5059
|
children: [
|
|
2808
|
-
/* @__PURE__ */ (0,
|
|
2809
|
-
/* @__PURE__ */ (0,
|
|
2810
|
-
/* @__PURE__ */ (0,
|
|
5060
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: 20, children: "20" }),
|
|
5061
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: 50, children: "50" }),
|
|
5062
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: 100, children: "100" })
|
|
2811
5063
|
]
|
|
2812
5064
|
}
|
|
2813
5065
|
)
|
|
2814
5066
|
] }),
|
|
2815
|
-
/* @__PURE__ */ (0,
|
|
2816
|
-
/* @__PURE__ */ (0,
|
|
5067
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
5068
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-medium text-slate-600", children: [
|
|
2817
5069
|
"\u05E2\u05DE\u05D5\u05D3 ",
|
|
2818
|
-
/* @__PURE__ */ (0,
|
|
5070
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { className: "text-slate-900", children: page }),
|
|
2819
5071
|
" \u05DE\u05EA\u05D5\u05DA ",
|
|
2820
|
-
/* @__PURE__ */ (0,
|
|
2821
|
-
totalRecords > 0 && /* @__PURE__ */ (0,
|
|
5072
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { className: "text-slate-900", children: totalPages || 1 }),
|
|
5073
|
+
totalRecords > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-slate-500 font-normal", children: [
|
|
2822
5074
|
" (",
|
|
2823
5075
|
totalRecords,
|
|
2824
5076
|
' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
|
|
2825
5077
|
] })
|
|
2826
5078
|
] }),
|
|
2827
|
-
/* @__PURE__ */ (0,
|
|
2828
|
-
/* @__PURE__ */ (0,
|
|
5079
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
5080
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2829
5081
|
"button",
|
|
2830
5082
|
{
|
|
2831
5083
|
onClick: handlePrevPage,
|
|
@@ -2835,7 +5087,7 @@ function TableBlockClient({
|
|
|
2835
5087
|
children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
|
|
2836
5088
|
}
|
|
2837
5089
|
),
|
|
2838
|
-
/* @__PURE__ */ (0,
|
|
5090
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2839
5091
|
"button",
|
|
2840
5092
|
{
|
|
2841
5093
|
onClick: handleNextPage,
|
|
@@ -2861,11 +5113,11 @@ function ExpandedSubTables({
|
|
|
2861
5113
|
context
|
|
2862
5114
|
}) {
|
|
2863
5115
|
var _a;
|
|
2864
|
-
const [activeTab, setActiveTab] = (0,
|
|
5116
|
+
const [activeTab, setActiveTab] = (0, import_react12.useState)((_a = subTableColumns[0]) == null ? void 0 : _a.name);
|
|
2865
5117
|
if (subTableColumns.length === 0) return null;
|
|
2866
5118
|
if (subTableColumns.length === 1) {
|
|
2867
5119
|
const stCol = subTableColumns[0];
|
|
2868
|
-
return /* @__PURE__ */ (0,
|
|
5120
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2869
5121
|
SubTableViewer,
|
|
2870
5122
|
{
|
|
2871
5123
|
rowId,
|
|
@@ -2877,8 +5129,8 @@ function ExpandedSubTables({
|
|
|
2877
5129
|
) }) });
|
|
2878
5130
|
}
|
|
2879
5131
|
const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
|
|
2880
|
-
return /* @__PURE__ */ (0,
|
|
2881
|
-
/* @__PURE__ */ (0,
|
|
5132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50 overflow-hidden", children: [
|
|
5133
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex border-b border-slate-200 bg-slate-100/50 px-2 pt-2 gap-1 overflow-hidden", children: subTableColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2882
5134
|
"button",
|
|
2883
5135
|
{
|
|
2884
5136
|
type: "button",
|
|
@@ -2888,7 +5140,7 @@ function ExpandedSubTables({
|
|
|
2888
5140
|
},
|
|
2889
5141
|
col.name
|
|
2890
5142
|
)) }),
|
|
2891
|
-
/* @__PURE__ */ (0,
|
|
5143
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2892
5144
|
SubTableViewer,
|
|
2893
5145
|
{
|
|
2894
5146
|
rowId,
|
|
@@ -2903,9 +5155,9 @@ function ExpandedSubTables({
|
|
|
2903
5155
|
}
|
|
2904
5156
|
|
|
2905
5157
|
// src/components/TableBlock/TableBlock.tsx
|
|
2906
|
-
var
|
|
5158
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2907
5159
|
function TableBlock(props) {
|
|
2908
|
-
return /* @__PURE__ */ (0,
|
|
5160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TableBlockClient, __spreadValues({}, props));
|
|
2909
5161
|
}
|
|
2910
5162
|
|
|
2911
5163
|
// src/registry.ts
|
|
@@ -2914,10 +5166,31 @@ var UNIVERSE_COMPONENTS = {
|
|
|
2914
5166
|
};
|
|
2915
5167
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2916
5168
|
0 && (module.exports = {
|
|
5169
|
+
ColumnHeaderTitle,
|
|
5170
|
+
DatePickerCell,
|
|
5171
|
+
LinkPickerCell,
|
|
5172
|
+
PASTEL_PALETTES,
|
|
5173
|
+
RelationPickerCell,
|
|
2917
5174
|
TableBlock,
|
|
5175
|
+
TimePickerCell,
|
|
2918
5176
|
ToastContext,
|
|
2919
5177
|
ToastProvider,
|
|
2920
5178
|
UNIVERSE_COMPONENTS,
|
|
5179
|
+
calculateMinColumnWidth,
|
|
2921
5180
|
cn,
|
|
5181
|
+
formatConflictCellValue,
|
|
5182
|
+
formatPhoneDisplay,
|
|
5183
|
+
formatTimeInput,
|
|
5184
|
+
formatTimeIso,
|
|
5185
|
+
getDeterministicPastelBadge,
|
|
5186
|
+
measureTextWidth,
|
|
5187
|
+
normalizeRelationValue,
|
|
5188
|
+
openWhatsAppChat,
|
|
5189
|
+
parseLinkValue,
|
|
5190
|
+
parseTimeParts,
|
|
5191
|
+
resolveProtocol,
|
|
5192
|
+
splitHeaderTitle,
|
|
5193
|
+
useColumnReorder,
|
|
5194
|
+
useColumnResize,
|
|
2922
5195
|
useToast
|
|
2923
5196
|
});
|