@universe-platform/ui 0.1.0-beta.6 → 0.1.0-beta.8
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 +244 -0
- package/dist/index.d.mts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +1748 -232
- package/dist/index.mjs +1741 -227
- 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 +6 -1
package/dist/index.mjs
CHANGED
|
@@ -38,8 +38,38 @@ function cn(...inputs) {
|
|
|
38
38
|
return twMerge(clsx(inputs));
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// src/utils/whatsapp.ts
|
|
42
|
+
function openWhatsAppChat(phone, defaultCountryCode = "972") {
|
|
43
|
+
if (!phone || typeof window === "undefined") return;
|
|
44
|
+
let cleaned = phone.replace(/\D/g, "");
|
|
45
|
+
if (cleaned.startsWith("0")) {
|
|
46
|
+
cleaned = defaultCountryCode + cleaned.substring(1);
|
|
47
|
+
}
|
|
48
|
+
const appUrl = `whatsapp://send?phone=${cleaned}`;
|
|
49
|
+
const webUrl = `https://web.whatsapp.com/send?phone=${cleaned}`;
|
|
50
|
+
const start = Date.now();
|
|
51
|
+
window.location.href = appUrl;
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
if (typeof document !== "undefined" && document.hasFocus() && Date.now() - start < 2e3) {
|
|
54
|
+
window.open(webUrl, "_blank", "noopener,noreferrer");
|
|
55
|
+
}
|
|
56
|
+
}, 1200);
|
|
57
|
+
}
|
|
58
|
+
function formatPhoneDisplay(phone) {
|
|
59
|
+
if (!phone) return "";
|
|
60
|
+
const digits = phone.replace(/\D/g, "");
|
|
61
|
+
if (digits.length === 10 && digits.startsWith("05")) {
|
|
62
|
+
return `${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
|
|
63
|
+
}
|
|
64
|
+
if (digits.length === 12 && digits.startsWith("9725")) {
|
|
65
|
+
const local = "0" + digits.slice(3);
|
|
66
|
+
return `${local.slice(0, 3)}-${local.slice(3, 6)}-${local.slice(6)}`;
|
|
67
|
+
}
|
|
68
|
+
return phone;
|
|
69
|
+
}
|
|
70
|
+
|
|
41
71
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
42
|
-
import { useState as
|
|
72
|
+
import React6, { useState as useState5, useMemo as useMemo2, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
43
73
|
|
|
44
74
|
// src/hooks/useToast.ts
|
|
45
75
|
import { useContext as useContext2 } from "react";
|
|
@@ -242,12 +272,36 @@ function useToast() {
|
|
|
242
272
|
import React4 from "react";
|
|
243
273
|
|
|
244
274
|
// src/components/TableBlock/fields/DrivePickerCell.tsx
|
|
245
|
-
import { useState as useState2 } from "react";
|
|
275
|
+
import React2, { useState as useState2, useEffect } from "react";
|
|
246
276
|
import { FileText, Upload, X as X2 } from "lucide-react";
|
|
247
277
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
248
|
-
function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, context }) {
|
|
278
|
+
function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForDeletion, context }) {
|
|
249
279
|
const [isOpening, setIsOpening] = useState2(false);
|
|
250
280
|
const { showError } = useToast();
|
|
281
|
+
const cellContextId = React2.useMemo(() => {
|
|
282
|
+
const colName = (column == null ? void 0 : column.name) || "col";
|
|
283
|
+
const rId = rowId || "row";
|
|
284
|
+
return `${rId}-${colName}`;
|
|
285
|
+
}, [rowId, column == null ? void 0 : column.name]);
|
|
286
|
+
const fileList = React2.useMemo(() => {
|
|
287
|
+
if (!value) return [];
|
|
288
|
+
if (Array.isArray(value)) return value;
|
|
289
|
+
if (typeof value === "object" && (value.fileId || value.fileUrl || value.url)) {
|
|
290
|
+
return [value];
|
|
291
|
+
}
|
|
292
|
+
return [];
|
|
293
|
+
}, [value]);
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
const handleMessage = (event) => {
|
|
296
|
+
var _a, _b, _c;
|
|
297
|
+
if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.payload) && ((_c = event.data) == null ? void 0 : _c.cellContextId) === cellContextId) {
|
|
298
|
+
const incoming = Array.isArray(event.data.payload) ? event.data.payload : [event.data.payload];
|
|
299
|
+
onChange([...fileList, ...incoming]);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
window.addEventListener("message", handleMessage);
|
|
303
|
+
return () => window.removeEventListener("message", handleMessage);
|
|
304
|
+
}, [fileList, onChange, cellContextId]);
|
|
251
305
|
const openUploadPopup = async () => {
|
|
252
306
|
if (isOpening) return;
|
|
253
307
|
setIsOpening(true);
|
|
@@ -276,34 +330,35 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
|
|
|
276
330
|
} catch (e) {
|
|
277
331
|
}
|
|
278
332
|
}
|
|
279
|
-
const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName });
|
|
333
|
+
const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName, cellContextId });
|
|
280
334
|
const folderId = actionResult == null ? void 0 : actionResult.folderId;
|
|
281
|
-
|
|
335
|
+
let pickerUrl = (actionResult == null ? void 0 : actionResult.pickerUrl) || (folderId ? `/embed/picker?folderId=${encodeURIComponent(folderId)}` : `/embed/picker`);
|
|
336
|
+
if (!pickerUrl.includes("cellContextId=")) {
|
|
337
|
+
const separator = pickerUrl.includes("?") ? "&" : "?";
|
|
338
|
+
pickerUrl = `${pickerUrl}${separator}cellContextId=${encodeURIComponent(cellContextId)}`;
|
|
339
|
+
}
|
|
282
340
|
if (popup) {
|
|
283
341
|
popup.location.href = pickerUrl;
|
|
284
342
|
}
|
|
285
|
-
|
|
343
|
+
await new Promise((resolve) => {
|
|
286
344
|
let timer = null;
|
|
287
|
-
const
|
|
345
|
+
const handlePopupMessage = (event) => {
|
|
288
346
|
var _a, _b;
|
|
289
|
-
if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.
|
|
290
|
-
window.removeEventListener("message",
|
|
347
|
+
if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.cellContextId) === cellContextId) {
|
|
348
|
+
window.removeEventListener("message", handlePopupMessage);
|
|
291
349
|
if (timer) clearInterval(timer);
|
|
292
|
-
resolve(
|
|
350
|
+
resolve();
|
|
293
351
|
}
|
|
294
352
|
};
|
|
295
353
|
timer = setInterval(() => {
|
|
296
354
|
if (!popup || popup.closed) {
|
|
297
355
|
if (timer) clearInterval(timer);
|
|
298
|
-
window.removeEventListener("message",
|
|
299
|
-
resolve(
|
|
356
|
+
window.removeEventListener("message", handlePopupMessage);
|
|
357
|
+
resolve();
|
|
300
358
|
}
|
|
301
359
|
}, 800);
|
|
302
|
-
window.addEventListener("message",
|
|
360
|
+
window.addEventListener("message", handlePopupMessage);
|
|
303
361
|
});
|
|
304
|
-
if (newFile) {
|
|
305
|
-
onChange(newFile);
|
|
306
|
-
}
|
|
307
362
|
}
|
|
308
363
|
} catch (error) {
|
|
309
364
|
console.error("[DrivePickerCell] Error uploading file:", error);
|
|
@@ -313,40 +368,15 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
|
|
|
313
368
|
setIsOpening(false);
|
|
314
369
|
}
|
|
315
370
|
};
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
title: value.fileName || "Open file",
|
|
326
|
-
children: [
|
|
327
|
-
/* @__PURE__ */ jsx2(FileText, { className: "w-3.5 h-3.5 shrink-0" }),
|
|
328
|
-
/* @__PURE__ */ jsx2("span", { className: "truncate", children: value.fileName || "Unnamed file" })
|
|
329
|
-
]
|
|
330
|
-
}
|
|
331
|
-
),
|
|
332
|
-
/* @__PURE__ */ jsx2(
|
|
333
|
-
"button",
|
|
334
|
-
{
|
|
335
|
-
type: "button",
|
|
336
|
-
onClick: () => {
|
|
337
|
-
if ((value == null ? void 0 : value.fileId) && onMarkForDeletion) {
|
|
338
|
-
onMarkForDeletion(value.fileId);
|
|
339
|
-
}
|
|
340
|
-
onChange(null);
|
|
341
|
-
},
|
|
342
|
-
className: "shrink-0 p-0.5 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
|
|
343
|
-
title: "Remove file",
|
|
344
|
-
children: /* @__PURE__ */ jsx2(X2, { className: "w-3.5 h-3.5" })
|
|
345
|
-
}
|
|
346
|
-
)
|
|
347
|
-
] });
|
|
348
|
-
}
|
|
349
|
-
return /* @__PURE__ */ jsx2("div", { className: "flex items-center w-full h-8 px-2", children: /* @__PURE__ */ jsxs2(
|
|
371
|
+
const handleRemoveFile = (indexToRemove) => {
|
|
372
|
+
const fileToRemove = fileList[indexToRemove];
|
|
373
|
+
if ((fileToRemove == null ? void 0 : fileToRemove.fileId) && onMarkForDeletion) {
|
|
374
|
+
onMarkForDeletion(fileToRemove.fileId);
|
|
375
|
+
}
|
|
376
|
+
const updated = fileList.filter((_, idx) => idx !== indexToRemove);
|
|
377
|
+
onChange(updated);
|
|
378
|
+
};
|
|
379
|
+
const renderUploadButton = () => /* @__PURE__ */ jsx2("div", { className: "flex items-center w-full h-8 px-2", children: /* @__PURE__ */ jsxs2(
|
|
350
380
|
"button",
|
|
351
381
|
{
|
|
352
382
|
type: "button",
|
|
@@ -359,10 +389,42 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
|
|
|
359
389
|
]
|
|
360
390
|
}
|
|
361
391
|
) });
|
|
392
|
+
if (fileList.length > 0) {
|
|
393
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col w-full py-1 gap-1", children: [
|
|
394
|
+
fileList.map((file, idx) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center w-full h-8 px-2 gap-1", children: [
|
|
395
|
+
/* @__PURE__ */ jsxs2(
|
|
396
|
+
"a",
|
|
397
|
+
{
|
|
398
|
+
href: file.fileUrl || file.url,
|
|
399
|
+
target: "_blank",
|
|
400
|
+
rel: "noopener noreferrer",
|
|
401
|
+
className: "inline-flex items-center gap-1.5 max-w-[calc(100%-24px)] px-2 py-1 rounded-md text-xs font-medium text-blue-700 bg-blue-50 hover:bg-blue-100 transition-colors truncate",
|
|
402
|
+
title: file.fileName || "Open file",
|
|
403
|
+
children: [
|
|
404
|
+
/* @__PURE__ */ jsx2(FileText, { className: "w-3.5 h-3.5 shrink-0" }),
|
|
405
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate", children: file.fileName || "Unnamed file" })
|
|
406
|
+
]
|
|
407
|
+
}
|
|
408
|
+
),
|
|
409
|
+
/* @__PURE__ */ jsx2(
|
|
410
|
+
"button",
|
|
411
|
+
{
|
|
412
|
+
type: "button",
|
|
413
|
+
onClick: () => handleRemoveFile(idx),
|
|
414
|
+
className: "shrink-0 p-0.5 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
|
|
415
|
+
title: "Remove file",
|
|
416
|
+
children: /* @__PURE__ */ jsx2(X2, { className: "w-3.5 h-3.5" })
|
|
417
|
+
}
|
|
418
|
+
)
|
|
419
|
+
] }, file.fileId || idx)),
|
|
420
|
+
renderUploadButton()
|
|
421
|
+
] });
|
|
422
|
+
}
|
|
423
|
+
return renderUploadButton();
|
|
362
424
|
}
|
|
363
425
|
|
|
364
426
|
// src/components/TableBlock/fields/DatePickerCell.tsx
|
|
365
|
-
import { useState as useState3, useRef as useRef2, useEffect, useMemo, useCallback as useCallback2 } from "react";
|
|
427
|
+
import { useState as useState3, useRef as useRef2, useEffect as useEffect2, useMemo, useCallback as useCallback2 } from "react";
|
|
366
428
|
import { Calendar as CalendarIcon, ChevronLeft, ChevronRight, X as X3 } from "lucide-react";
|
|
367
429
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
368
430
|
function parseDateParts(val) {
|
|
@@ -447,13 +509,13 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
|
|
|
447
509
|
const parsedParts = useMemo(() => parseDateParts(value), [value]);
|
|
448
510
|
const displayString = useMemo(() => formatDateDisplay(parsedParts), [parsedParts]);
|
|
449
511
|
const [rawInput, setRawInput] = useState3(displayString);
|
|
450
|
-
|
|
512
|
+
useEffect2(() => {
|
|
451
513
|
setRawInput(displayString);
|
|
452
514
|
}, [displayString]);
|
|
453
515
|
const now = /* @__PURE__ */ new Date();
|
|
454
516
|
const [viewYear, setViewYear] = useState3((parsedParts == null ? void 0 : parsedParts.year) || now.getFullYear());
|
|
455
517
|
const [viewMonth, setViewMonth] = useState3((parsedParts == null ? void 0 : parsedParts.month) || now.getMonth() + 1);
|
|
456
|
-
|
|
518
|
+
useEffect2(() => {
|
|
457
519
|
if (parsedParts) {
|
|
458
520
|
setViewYear(parsedParts.year);
|
|
459
521
|
setViewMonth(parsedParts.month);
|
|
@@ -478,7 +540,7 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
|
|
|
478
540
|
}
|
|
479
541
|
}
|
|
480
542
|
}, []);
|
|
481
|
-
|
|
543
|
+
useEffect2(() => {
|
|
482
544
|
if (!isOpen) return;
|
|
483
545
|
updatePopoverPosition();
|
|
484
546
|
function handleScrollOrResize() {
|
|
@@ -793,11 +855,13 @@ var FORM_INPUTS = {
|
|
|
793
855
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
794
856
|
}
|
|
795
857
|
) }),
|
|
796
|
-
GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */ jsx4(
|
|
858
|
+
GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ jsx4(
|
|
797
859
|
DrivePickerCell,
|
|
798
860
|
{
|
|
799
|
-
value: value ||
|
|
861
|
+
value: value || [],
|
|
800
862
|
onChange,
|
|
863
|
+
column,
|
|
864
|
+
rowId,
|
|
801
865
|
tableName: context == null ? void 0 : context.tableName,
|
|
802
866
|
onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
|
|
803
867
|
context
|
|
@@ -855,6 +919,249 @@ var FORM_INPUTS = {
|
|
|
855
919
|
}
|
|
856
920
|
}
|
|
857
921
|
),
|
|
922
|
+
PHONE: ({ value, onChange, column }) => {
|
|
923
|
+
var _a;
|
|
924
|
+
const enableWhatsApp = (_a = column == null ? void 0 : column.config) == null ? void 0 : _a.enableWhatsApp;
|
|
925
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center w-full h-full px-2 gap-1.5", children: [
|
|
926
|
+
/* @__PURE__ */ jsx4(
|
|
927
|
+
"input",
|
|
928
|
+
{
|
|
929
|
+
type: "tel",
|
|
930
|
+
className: "w-full h-8 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm flex-1",
|
|
931
|
+
value: value !== void 0 && value !== null ? String(value) : "",
|
|
932
|
+
onChange: (e) => onChange(e.target.value),
|
|
933
|
+
dir: "ltr"
|
|
934
|
+
}
|
|
935
|
+
),
|
|
936
|
+
enableWhatsApp && value && /* @__PURE__ */ jsx4(
|
|
937
|
+
"button",
|
|
938
|
+
{
|
|
939
|
+
type: "button",
|
|
940
|
+
className: "text-emerald-500 cursor-pointer hover:opacity-80 transition-opacity shrink-0 p-1 rounded hover:bg-emerald-50",
|
|
941
|
+
title: "\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4",
|
|
942
|
+
onClick: (e) => {
|
|
943
|
+
e.stopPropagation();
|
|
944
|
+
openWhatsAppChat(String(value));
|
|
945
|
+
},
|
|
946
|
+
children: /* @__PURE__ */ jsx4("svg", { className: "w-4 h-4", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("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" }) })
|
|
947
|
+
}
|
|
948
|
+
)
|
|
949
|
+
] });
|
|
950
|
+
},
|
|
951
|
+
GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
|
|
952
|
+
const [isSyncing, setIsSyncing] = React4.useState(false);
|
|
953
|
+
const { addToast } = useToast();
|
|
954
|
+
const googleClientIdRef = React4.useRef(null);
|
|
955
|
+
const ensureGisScript = React4.useCallback(() => {
|
|
956
|
+
return new Promise((resolve, reject) => {
|
|
957
|
+
var _a, _b, _c;
|
|
958
|
+
if ((_c = (_b = (_a = window.google) == null ? void 0 : _a.accounts) == null ? void 0 : _b.oauth2) == null ? void 0 : _c.initTokenClient) {
|
|
959
|
+
resolve();
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
if (document.querySelector('script[src*="accounts.google.com/gsi/client"]')) {
|
|
963
|
+
const waitForLoad = setInterval(() => {
|
|
964
|
+
var _a2, _b2, _c2;
|
|
965
|
+
if ((_c2 = (_b2 = (_a2 = window.google) == null ? void 0 : _a2.accounts) == null ? void 0 : _b2.oauth2) == null ? void 0 : _c2.initTokenClient) {
|
|
966
|
+
clearInterval(waitForLoad);
|
|
967
|
+
resolve();
|
|
968
|
+
}
|
|
969
|
+
}, 100);
|
|
970
|
+
setTimeout(() => {
|
|
971
|
+
clearInterval(waitForLoad);
|
|
972
|
+
reject(new Error("GIS script load timeout"));
|
|
973
|
+
}, 1e4);
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
const script = document.createElement("script");
|
|
977
|
+
script.src = "https://accounts.google.com/gsi/client";
|
|
978
|
+
script.async = true;
|
|
979
|
+
script.onload = () => resolve();
|
|
980
|
+
script.onerror = () => reject(new Error("Failed to load Google Identity Services"));
|
|
981
|
+
document.head.appendChild(script);
|
|
982
|
+
});
|
|
983
|
+
}, []);
|
|
984
|
+
const requestGisToken = React4.useCallback(async (hint) => {
|
|
985
|
+
await ensureGisScript();
|
|
986
|
+
if (!googleClientIdRef.current && (context == null ? void 0 : context.executeAction)) {
|
|
987
|
+
try {
|
|
988
|
+
const config = await context.executeAction("GET_GOOGLE_CONFIG", {});
|
|
989
|
+
googleClientIdRef.current = (config == null ? void 0 : config.clientId) || "";
|
|
990
|
+
} catch (e) {
|
|
991
|
+
throw new Error("Failed to fetch Google configuration");
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
const clientId = googleClientIdRef.current;
|
|
995
|
+
if (!clientId) {
|
|
996
|
+
throw new Error("Google Client ID is not configured");
|
|
997
|
+
}
|
|
998
|
+
const accessToken = await new Promise((resolve, reject) => {
|
|
999
|
+
const tokenClient = window.google.accounts.oauth2.initTokenClient({
|
|
1000
|
+
client_id: clientId,
|
|
1001
|
+
scope: "https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/userinfo.email",
|
|
1002
|
+
prompt: hint ? "" : "select_account",
|
|
1003
|
+
hint: hint || void 0,
|
|
1004
|
+
callback: (tokenResponse) => {
|
|
1005
|
+
if (tokenResponse == null ? void 0 : tokenResponse.access_token) {
|
|
1006
|
+
resolve(tokenResponse.access_token);
|
|
1007
|
+
} else {
|
|
1008
|
+
reject(new Error("Google authorization was cancelled or failed"));
|
|
1009
|
+
}
|
|
1010
|
+
},
|
|
1011
|
+
error_callback: (err) => {
|
|
1012
|
+
reject(new Error((err == null ? void 0 : err.message) || "Google authorization error"));
|
|
1013
|
+
}
|
|
1014
|
+
});
|
|
1015
|
+
tokenClient.requestAccessToken({ hint: hint || void 0 });
|
|
1016
|
+
});
|
|
1017
|
+
let email = "";
|
|
1018
|
+
try {
|
|
1019
|
+
const res = await fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
|
|
1020
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
1021
|
+
});
|
|
1022
|
+
if (res.ok) {
|
|
1023
|
+
const info = await res.json();
|
|
1024
|
+
email = info.email || "";
|
|
1025
|
+
}
|
|
1026
|
+
} catch (e) {
|
|
1027
|
+
}
|
|
1028
|
+
return { accessToken, email };
|
|
1029
|
+
}, [ensureGisScript, context]);
|
|
1030
|
+
const handleSync = async () => {
|
|
1031
|
+
var _a, _b, _c;
|
|
1032
|
+
if (!(context == null ? void 0 : context.executeAction)) return;
|
|
1033
|
+
setIsSyncing(true);
|
|
1034
|
+
try {
|
|
1035
|
+
const mapping = column.contactMapping || {};
|
|
1036
|
+
const rowData = context.rowData || {};
|
|
1037
|
+
let hasPhone = false;
|
|
1038
|
+
if (mapping.phoneCol && rowData[mapping.phoneCol]) hasPhone = true;
|
|
1039
|
+
let hasName = false;
|
|
1040
|
+
if (mapping.nameParts && Array.isArray(mapping.nameParts)) {
|
|
1041
|
+
for (const part of mapping.nameParts) {
|
|
1042
|
+
if (part.type === "LOCAL" && rowData[part.columnId]) hasName = true;
|
|
1043
|
+
if (part.type === "PARENT" && ((_a = context.parentRecord) == null ? void 0 : _a.tableId) === part.parentTableId && ((_c = (_b = context.parentRecord) == null ? void 0 : _b.data) == null ? void 0 : _c[part.columnId])) hasName = true;
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
if (!hasPhone) {
|
|
1047
|
+
addToast({ type: "warning", message: "\u05E0\u05D0 \u05DC\u05DE\u05DC\u05D0 \u05DE\u05E1\u05E4\u05E8 \u05D8\u05DC\u05E4\u05D5\u05DF \u05DB\u05D3\u05D9 \u05DC\u05E1\u05E0\u05DB\u05E8\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05DC\u05D2\u05D5\u05D2\u05DC" });
|
|
1048
|
+
setIsSyncing(false);
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
if (!hasName) {
|
|
1052
|
+
addToast({ type: "warning", message: "\u05E0\u05D0 \u05DC\u05DE\u05DC\u05D0 \u05E9\u05DD \u05DB\u05D3\u05D9 \u05DC\u05E1\u05E0\u05DB\u05E8\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05DC\u05D2\u05D5\u05D2\u05DC" });
|
|
1053
|
+
setIsSyncing(false);
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
let accessToken;
|
|
1057
|
+
let userEmail = "";
|
|
1058
|
+
try {
|
|
1059
|
+
const gisResult = await requestGisToken();
|
|
1060
|
+
accessToken = gisResult.accessToken;
|
|
1061
|
+
userEmail = gisResult.email;
|
|
1062
|
+
} catch (gisError) {
|
|
1063
|
+
addToast({ type: "warning", message: gisError.message || "\u05D4\u05D4\u05E8\u05E9\u05D0\u05D4 \u05DC\u05D2\u05D5\u05D2\u05DC \u05E0\u05DB\u05E9\u05DC\u05D4" });
|
|
1064
|
+
setIsSyncing(false);
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
const payload = {
|
|
1068
|
+
nameParts: mapping.nameParts || [],
|
|
1069
|
+
phoneCol: mapping.phoneCol,
|
|
1070
|
+
emailCol: mapping.emailCol,
|
|
1071
|
+
localRowData: rowData,
|
|
1072
|
+
parentRecord: context.parentRecord,
|
|
1073
|
+
accessToken,
|
|
1074
|
+
userEmail
|
|
1075
|
+
};
|
|
1076
|
+
const res = await context.executeAction("SYNC_GOOGLE_CONTACT", payload);
|
|
1077
|
+
if (res && res.synced) {
|
|
1078
|
+
if (context.updateQuietly) {
|
|
1079
|
+
context.updateQuietly(rowId, column.name, res);
|
|
1080
|
+
} else {
|
|
1081
|
+
onChange(res);
|
|
1082
|
+
}
|
|
1083
|
+
if (context.tableId && !rowId.startsWith("temp_")) {
|
|
1084
|
+
await context.executeAction("UPDATE_RECORD", {
|
|
1085
|
+
tableId: context.tableId,
|
|
1086
|
+
recordId: rowId,
|
|
1087
|
+
data: { [column.name]: res }
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
} catch (error) {
|
|
1092
|
+
console.error("Failed to sync contact:", error);
|
|
1093
|
+
addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
|
|
1094
|
+
} finally {
|
|
1095
|
+
setIsSyncing(false);
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
const handleUnlink = async () => {
|
|
1099
|
+
let accessToken;
|
|
1100
|
+
try {
|
|
1101
|
+
let emailHint = value == null ? void 0 : value.userEmail;
|
|
1102
|
+
if (!emailHint && (value == null ? void 0 : value.url)) {
|
|
1103
|
+
try {
|
|
1104
|
+
const parsed = new URL(value.url);
|
|
1105
|
+
emailHint = parsed.searchParams.get("authuser") || void 0;
|
|
1106
|
+
} catch (e) {
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
const auth = await requestGisToken(emailHint);
|
|
1110
|
+
accessToken = auth.accessToken;
|
|
1111
|
+
} catch (err) {
|
|
1112
|
+
console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
|
|
1113
|
+
}
|
|
1114
|
+
if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
|
|
1115
|
+
await context.executeAction("DELETE_GOOGLE_CONTACT", {
|
|
1116
|
+
resourceName: value.resourceName,
|
|
1117
|
+
accessToken
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1121
|
+
context.updateQuietly(rowId, column.name, null);
|
|
1122
|
+
} else {
|
|
1123
|
+
onChange(null);
|
|
1124
|
+
}
|
|
1125
|
+
if ((context == null ? void 0 : context.tableId) && (context == null ? void 0 : context.executeAction) && !rowId.startsWith("temp_")) {
|
|
1126
|
+
await context.executeAction("UPDATE_RECORD", {
|
|
1127
|
+
tableId: context.tableId,
|
|
1128
|
+
recordId: rowId,
|
|
1129
|
+
data: { [column.name]: null }
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
if (value && value.synced && value.url) {
|
|
1134
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5 h-8 px-2 group whitespace-nowrap", children: [
|
|
1135
|
+
/* @__PURE__ */ jsx4("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" }),
|
|
1136
|
+
/* @__PURE__ */ jsx4(
|
|
1137
|
+
"button",
|
|
1138
|
+
{
|
|
1139
|
+
type: "button",
|
|
1140
|
+
onClick: handleUnlink,
|
|
1141
|
+
className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1 shrink-0",
|
|
1142
|
+
title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
|
|
1143
|
+
children: /* @__PURE__ */ jsx4("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
|
|
1144
|
+
}
|
|
1145
|
+
)
|
|
1146
|
+
] });
|
|
1147
|
+
}
|
|
1148
|
+
return /* @__PURE__ */ jsx4("div", { className: "flex items-center h-8 px-2 whitespace-nowrap", children: /* @__PURE__ */ jsxs4(
|
|
1149
|
+
"button",
|
|
1150
|
+
{
|
|
1151
|
+
type: "button",
|
|
1152
|
+
onClick: handleSync,
|
|
1153
|
+
disabled: isSyncing,
|
|
1154
|
+
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",
|
|
1155
|
+
children: [
|
|
1156
|
+
isSyncing ? /* @__PURE__ */ jsxs4("svg", { className: "w-3.5 h-3.5 animate-spin shrink-0", viewBox: "0 0 24 24", fill: "none", children: [
|
|
1157
|
+
/* @__PURE__ */ jsx4("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
1158
|
+
/* @__PURE__ */ jsx4("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" })
|
|
1159
|
+
] }) : /* @__PURE__ */ jsx4("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
|
|
1160
|
+
/* @__PURE__ */ jsx4("span", { className: "whitespace-nowrap", children: "\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC" })
|
|
1161
|
+
]
|
|
1162
|
+
}
|
|
1163
|
+
) });
|
|
1164
|
+
},
|
|
858
1165
|
DEFAULT: ({ value, onChange }) => /* @__PURE__ */ jsx4(
|
|
859
1166
|
"input",
|
|
860
1167
|
{
|
|
@@ -863,12 +1170,1045 @@ var FORM_INPUTS = {
|
|
|
863
1170
|
value: value !== void 0 && value !== null ? String(value) : "",
|
|
864
1171
|
onChange: (e) => onChange(e.target.value)
|
|
865
1172
|
}
|
|
866
|
-
)
|
|
1173
|
+
),
|
|
1174
|
+
SUB_TABLE: ({ value, column }) => {
|
|
1175
|
+
var _a, _b;
|
|
1176
|
+
if (!Array.isArray(value)) return /* @__PURE__ */ jsx4("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
|
|
1177
|
+
const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
|
|
1178
|
+
if (selected.length === 0) return /* @__PURE__ */ jsx4("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
|
|
1179
|
+
const displayFields = column.subTableDisplayFields || [];
|
|
1180
|
+
const isWhatsApp = ((_a = column.config) == null ? void 0 : _a.actionType) === "WHATSAPP";
|
|
1181
|
+
const actionPhoneCol = (_b = column.config) == null ? void 0 : _b.actionPhoneColumn;
|
|
1182
|
+
return /* @__PURE__ */ jsx4("div", { className: "px-1.5 py-1 flex flex-wrap items-center gap-1 h-full", children: selected.map((entry, idx) => {
|
|
1183
|
+
var _a2, _b2;
|
|
1184
|
+
let label = "";
|
|
1185
|
+
if (entry._resolvedData) {
|
|
1186
|
+
if (displayFields.length > 0) {
|
|
1187
|
+
label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
|
|
1188
|
+
} else {
|
|
1189
|
+
const firstField = Object.keys(entry._resolvedData).find((k) => k !== "_id");
|
|
1190
|
+
if (firstField) label = String(entry._resolvedData[firstField] || "");
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if (!label) label = ((_a2 = entry.recordId) == null ? void 0 : _a2.slice(-6)) || "...";
|
|
1194
|
+
if (isWhatsApp) {
|
|
1195
|
+
const rawPhone = actionPhoneCol ? (_b2 = entry._resolvedData) == null ? void 0 : _b2[actionPhoneCol] : null;
|
|
1196
|
+
const phone = rawPhone ? String(rawPhone).trim() : null;
|
|
1197
|
+
if (phone) {
|
|
1198
|
+
return /* @__PURE__ */ jsxs4(
|
|
1199
|
+
"button",
|
|
1200
|
+
{
|
|
1201
|
+
type: "button",
|
|
1202
|
+
onClick: (e) => {
|
|
1203
|
+
e.stopPropagation();
|
|
1204
|
+
openWhatsAppChat(phone);
|
|
1205
|
+
},
|
|
1206
|
+
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-[150px] truncate cursor-pointer transition-colors shadow-xs",
|
|
1207
|
+
title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
|
|
1208
|
+
children: [
|
|
1209
|
+
/* @__PURE__ */ jsx4("svg", { className: "w-3 h-3 text-emerald-600 shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("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" }) }),
|
|
1210
|
+
/* @__PURE__ */ jsx4("span", { className: "truncate", children: label })
|
|
1211
|
+
]
|
|
1212
|
+
},
|
|
1213
|
+
entry.recordId || idx
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
return /* @__PURE__ */ jsx4(
|
|
1218
|
+
"span",
|
|
1219
|
+
{
|
|
1220
|
+
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-[140px] truncate",
|
|
1221
|
+
title: label,
|
|
1222
|
+
children: label
|
|
1223
|
+
},
|
|
1224
|
+
entry.recordId || idx
|
|
1225
|
+
);
|
|
1226
|
+
}) });
|
|
1227
|
+
}
|
|
867
1228
|
};
|
|
868
1229
|
|
|
1230
|
+
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
1231
|
+
import { useState as useState4, useEffect as useEffect3, useRef as useRef3, useCallback as useCallback3 } from "react";
|
|
1232
|
+
|
|
1233
|
+
// src/utils/phone.ts
|
|
1234
|
+
function sanitizePhoneNumber(phone) {
|
|
1235
|
+
if (!phone) return "";
|
|
1236
|
+
const trimmed = phone.trim();
|
|
1237
|
+
const hasLeadingPlus = trimmed.startsWith("+");
|
|
1238
|
+
const digitsOnly = trimmed.replace(/\D/g, "");
|
|
1239
|
+
return hasLeadingPlus ? `+${digitsOnly}` : digitsOnly;
|
|
1240
|
+
}
|
|
1241
|
+
function isValidPhoneNumber(phone) {
|
|
1242
|
+
if (!phone) return false;
|
|
1243
|
+
const cleaned = sanitizePhoneNumber(phone);
|
|
1244
|
+
return /^\+?[0-9]{9,15}$/.test(cleaned);
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
1248
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1249
|
+
function validateCellValue(val, col) {
|
|
1250
|
+
var _a;
|
|
1251
|
+
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
1252
|
+
const isEmpty = val === void 0 || val === null || typeof val === "string" && val.trim() === "";
|
|
1253
|
+
if (col.isRequired && isEmpty) {
|
|
1254
|
+
return {
|
|
1255
|
+
isValid: false,
|
|
1256
|
+
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.`
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
if (isEmpty) {
|
|
1260
|
+
return { isValid: true };
|
|
1261
|
+
}
|
|
1262
|
+
if (colType === "PHONE") {
|
|
1263
|
+
const strVal = String(val).trim();
|
|
1264
|
+
if (!isValidPhoneNumber(strVal)) {
|
|
1265
|
+
return {
|
|
1266
|
+
isValid: false,
|
|
1267
|
+
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).`
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
if (colType === "NUMBER" || colType === "CURRENCY") {
|
|
1272
|
+
if (typeof val === "string" && isNaN(Number(val))) {
|
|
1273
|
+
return {
|
|
1274
|
+
isValid: false,
|
|
1275
|
+
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.`
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return { isValid: true };
|
|
1280
|
+
}
|
|
1281
|
+
function SubTableCell({
|
|
1282
|
+
record,
|
|
1283
|
+
column,
|
|
1284
|
+
targetSchema,
|
|
1285
|
+
referencedTableId,
|
|
1286
|
+
context,
|
|
1287
|
+
relationOptions,
|
|
1288
|
+
setRelationOptions,
|
|
1289
|
+
refetchRelation,
|
|
1290
|
+
onCommit
|
|
1291
|
+
}) {
|
|
1292
|
+
var _a, _b;
|
|
1293
|
+
const colType = ((_a = column.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
1294
|
+
const isContact = colType === "GOOGLE_CONTACT";
|
|
1295
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
1296
|
+
const serverValue = (_b = record.data[column.name]) != null ? _b : colType === "BOOLEAN" ? false : "";
|
|
1297
|
+
const [draftValue, setDraftValue] = useState4(serverValue);
|
|
1298
|
+
const [isDirty, setIsDirty] = useState4(false);
|
|
1299
|
+
const [validationError, setValidationError] = useState4(null);
|
|
1300
|
+
const cellRef = useRef3(null);
|
|
1301
|
+
const draftRef = useRef3(draftValue);
|
|
1302
|
+
const isDirtyRef = useRef3(isDirty);
|
|
1303
|
+
const serverValueRef = useRef3(serverValue);
|
|
1304
|
+
const recordIdRef = useRef3(record.id);
|
|
1305
|
+
const columnRef = useRef3(column);
|
|
1306
|
+
const onCommitRef = useRef3(onCommit);
|
|
1307
|
+
const isCommittingRef = useRef3(false);
|
|
1308
|
+
const lastFailedValRef = useRef3(void 0);
|
|
1309
|
+
const { addToast } = useToast();
|
|
1310
|
+
draftRef.current = draftValue;
|
|
1311
|
+
isDirtyRef.current = isDirty;
|
|
1312
|
+
serverValueRef.current = serverValue;
|
|
1313
|
+
recordIdRef.current = record.id;
|
|
1314
|
+
columnRef.current = column;
|
|
1315
|
+
onCommitRef.current = onCommit;
|
|
1316
|
+
useEffect3(() => {
|
|
1317
|
+
if (!isDirtyRef.current) {
|
|
1318
|
+
setDraftValue(serverValue);
|
|
1319
|
+
draftRef.current = serverValue;
|
|
1320
|
+
setValidationError(null);
|
|
1321
|
+
lastFailedValRef.current = void 0;
|
|
1322
|
+
}
|
|
1323
|
+
}, [serverValue]);
|
|
1324
|
+
const commit = useCallback3(async (valToCommit) => {
|
|
1325
|
+
if (isCommittingRef.current) return false;
|
|
1326
|
+
if (!isDirtyRef.current) return true;
|
|
1327
|
+
if (valToCommit === serverValueRef.current) {
|
|
1328
|
+
setIsDirty(false);
|
|
1329
|
+
isDirtyRef.current = false;
|
|
1330
|
+
setValidationError(null);
|
|
1331
|
+
lastFailedValRef.current = void 0;
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1334
|
+
const valRes = validateCellValue(valToCommit, columnRef.current);
|
|
1335
|
+
if (!valRes.isValid) {
|
|
1336
|
+
const errorMsg = valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA";
|
|
1337
|
+
setValidationError(errorMsg);
|
|
1338
|
+
if (lastFailedValRef.current !== valToCommit) {
|
|
1339
|
+
addToast({ type: "error", message: errorMsg });
|
|
1340
|
+
lastFailedValRef.current = valToCommit;
|
|
1341
|
+
}
|
|
1342
|
+
return false;
|
|
1343
|
+
}
|
|
1344
|
+
try {
|
|
1345
|
+
isCommittingRef.current = true;
|
|
1346
|
+
const success = await onCommitRef.current(recordIdRef.current, columnRef.current.name, valToCommit);
|
|
1347
|
+
if (success) {
|
|
1348
|
+
setIsDirty(false);
|
|
1349
|
+
isDirtyRef.current = false;
|
|
1350
|
+
serverValueRef.current = valToCommit;
|
|
1351
|
+
setValidationError(null);
|
|
1352
|
+
lastFailedValRef.current = void 0;
|
|
1353
|
+
return true;
|
|
1354
|
+
} else {
|
|
1355
|
+
setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
|
|
1356
|
+
return false;
|
|
1357
|
+
}
|
|
1358
|
+
} catch (e) {
|
|
1359
|
+
setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
|
|
1360
|
+
return false;
|
|
1361
|
+
} finally {
|
|
1362
|
+
isCommittingRef.current = false;
|
|
1363
|
+
}
|
|
1364
|
+
}, [addToast]);
|
|
1365
|
+
const discard = useCallback3(() => {
|
|
1366
|
+
setDraftValue(serverValueRef.current);
|
|
1367
|
+
draftRef.current = serverValueRef.current;
|
|
1368
|
+
setIsDirty(false);
|
|
1369
|
+
isDirtyRef.current = false;
|
|
1370
|
+
setValidationError(null);
|
|
1371
|
+
lastFailedValRef.current = void 0;
|
|
1372
|
+
}, []);
|
|
1373
|
+
useEffect3(() => {
|
|
1374
|
+
return () => {
|
|
1375
|
+
if (isDirtyRef.current && !isCommittingRef.current) {
|
|
1376
|
+
const val = draftRef.current;
|
|
1377
|
+
const orig = serverValueRef.current;
|
|
1378
|
+
if (val !== orig) {
|
|
1379
|
+
const valRes = validateCellValue(val, columnRef.current);
|
|
1380
|
+
if (valRes.isValid) {
|
|
1381
|
+
onCommitRef.current(recordIdRef.current, columnRef.current.name, val);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
}, []);
|
|
1387
|
+
const handleChange = (newVal) => {
|
|
1388
|
+
setDraftValue(newVal);
|
|
1389
|
+
draftRef.current = newVal;
|
|
1390
|
+
setIsDirty(true);
|
|
1391
|
+
isDirtyRef.current = true;
|
|
1392
|
+
if (validationError) {
|
|
1393
|
+
setValidationError(null);
|
|
1394
|
+
lastFailedValRef.current = void 0;
|
|
1395
|
+
}
|
|
1396
|
+
if (colType === "BOOLEAN" || colType === "GOOGLE_DRIVE_FILE") {
|
|
1397
|
+
commit(newVal);
|
|
1398
|
+
}
|
|
1399
|
+
};
|
|
1400
|
+
const handleBlur = (e) => {
|
|
1401
|
+
if (e.currentTarget.contains(e.relatedTarget)) {
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
if (isDirtyRef.current) {
|
|
1405
|
+
commit(draftRef.current);
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
const handleKeyDown = (e) => {
|
|
1409
|
+
var _a2, _b2, _c, _d;
|
|
1410
|
+
if (e.key === "Enter") {
|
|
1411
|
+
e.preventDefault();
|
|
1412
|
+
if (isDirtyRef.current) {
|
|
1413
|
+
commit(draftRef.current);
|
|
1414
|
+
}
|
|
1415
|
+
(_b2 = (_a2 = e.target) == null ? void 0 : _a2.blur) == null ? void 0 : _b2.call(_a2);
|
|
1416
|
+
} else if (e.key === "Escape") {
|
|
1417
|
+
e.preventDefault();
|
|
1418
|
+
discard();
|
|
1419
|
+
(_d = (_c = e.target) == null ? void 0 : _c.blur) == null ? void 0 : _d.call(_c);
|
|
1420
|
+
}
|
|
1421
|
+
};
|
|
1422
|
+
return /* @__PURE__ */ jsx5(
|
|
1423
|
+
"td",
|
|
1424
|
+
{
|
|
1425
|
+
ref: cellRef,
|
|
1426
|
+
onBlur: handleBlur,
|
|
1427
|
+
onKeyDown: handleKeyDown,
|
|
1428
|
+
title: validationError || void 0,
|
|
1429
|
+
className: `border border-slate-200 p-0 relative h-8 transition-colors ${isContact ? "min-w-[140px]" : ""} ${validationError ? "border-rose-400 ring-1 ring-rose-400 bg-rose-50/20" : ""}`,
|
|
1430
|
+
children: /* @__PURE__ */ jsx5(
|
|
1431
|
+
InputComponent,
|
|
1432
|
+
{
|
|
1433
|
+
value: draftValue,
|
|
1434
|
+
column,
|
|
1435
|
+
rowId: record.id,
|
|
1436
|
+
onChange: handleChange,
|
|
1437
|
+
context: __spreadProps(__spreadValues({}, context), {
|
|
1438
|
+
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",
|
|
1439
|
+
relationOptions,
|
|
1440
|
+
updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
|
|
1441
|
+
refetchRelation,
|
|
1442
|
+
parentRecord: { tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId), data: context == null ? void 0 : context.rowData },
|
|
1443
|
+
rowData: record.data,
|
|
1444
|
+
tableId: (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId,
|
|
1445
|
+
updateQuietly: (rid, colName, val) => onCommitRef.current(rid, colName, val)
|
|
1446
|
+
})
|
|
1447
|
+
}
|
|
1448
|
+
)
|
|
1449
|
+
}
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
1453
|
+
var _a, _b;
|
|
1454
|
+
const { addToast } = useToast();
|
|
1455
|
+
const entries = Array.isArray(value) ? value : [];
|
|
1456
|
+
const [linkedRecords, setLinkedRecords] = useState4(() => {
|
|
1457
|
+
const initial = [];
|
|
1458
|
+
if (Array.isArray(value)) {
|
|
1459
|
+
for (const entry of value) {
|
|
1460
|
+
if (entry.recordId && entry._resolvedData) {
|
|
1461
|
+
initial.push({ id: entry.recordId, data: entry._resolvedData });
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
return initial;
|
|
1466
|
+
});
|
|
1467
|
+
const [targetSchema, setTargetSchema] = useState4(null);
|
|
1468
|
+
const [isLoading, setIsLoading] = useState4(true);
|
|
1469
|
+
const [isSearchOpen, setIsSearchOpen] = useState4(false);
|
|
1470
|
+
const [searchQuery, setSearchQuery] = useState4("");
|
|
1471
|
+
const [searchResults, setSearchResults] = useState4([]);
|
|
1472
|
+
const [isSearching, setIsSearching] = useState4(false);
|
|
1473
|
+
const [isCreating, setIsCreating] = useState4(false);
|
|
1474
|
+
const [newRecordData, setNewRecordData] = useState4({});
|
|
1475
|
+
const [conflictModalState, setConflictModalState] = useState4({
|
|
1476
|
+
isOpen: false,
|
|
1477
|
+
fieldName: "",
|
|
1478
|
+
matchingRecords: []
|
|
1479
|
+
});
|
|
1480
|
+
const searchRef = useRef3(null);
|
|
1481
|
+
const searchTimerRef = useRef3(null);
|
|
1482
|
+
const executeAction = context == null ? void 0 : context.executeAction;
|
|
1483
|
+
const referencedTableId = column.referencedTableId;
|
|
1484
|
+
const fetchedIdsRef = useRef3(/* @__PURE__ */ new Set());
|
|
1485
|
+
useEffect3(() => {
|
|
1486
|
+
if (entries.length > 0) {
|
|
1487
|
+
setLinkedRecords((prev) => {
|
|
1488
|
+
const existingIds = new Set(prev.map((r) => r.id));
|
|
1489
|
+
const toAdd = [];
|
|
1490
|
+
for (const entry of entries) {
|
|
1491
|
+
if (entry.recordId && entry._resolvedData && !existingIds.has(entry.recordId)) {
|
|
1492
|
+
toAdd.push({ id: entry.recordId, data: entry._resolvedData });
|
|
1493
|
+
existingIds.add(entry.recordId);
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return toAdd.length > 0 ? [...prev, ...toAdd] : prev;
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
}, [entries]);
|
|
1500
|
+
useEffect3(() => {
|
|
1501
|
+
if (!referencedTableId || !executeAction) {
|
|
1502
|
+
setIsLoading(false);
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
const recordIdsToFetch = entries.map((e) => e.recordId).filter((id) => !fetchedIdsRef.current.has(id));
|
|
1506
|
+
if (recordIdsToFetch.length === 0 && targetSchema) return;
|
|
1507
|
+
if (recordIdsToFetch.length > 0) {
|
|
1508
|
+
recordIdsToFetch.forEach((id) => fetchedIdsRef.current.add(id));
|
|
1509
|
+
}
|
|
1510
|
+
setIsLoading(true);
|
|
1511
|
+
executeAction("FETCH_SUB_TABLE_RECORDS", { referencedTableId, recordIds: recordIdsToFetch }).then((res) => {
|
|
1512
|
+
const payload = (res == null ? void 0 : res.data) || res;
|
|
1513
|
+
if (payload == null ? void 0 : payload.records) {
|
|
1514
|
+
setLinkedRecords((prev) => {
|
|
1515
|
+
const map = new Map(prev.map((r) => [r.id, r]));
|
|
1516
|
+
payload.records.forEach((r) => map.set(r.id, r));
|
|
1517
|
+
return Array.from(map.values());
|
|
1518
|
+
});
|
|
1519
|
+
}
|
|
1520
|
+
if (payload == null ? void 0 : payload.schema) {
|
|
1521
|
+
setTargetSchema(payload.schema);
|
|
1522
|
+
}
|
|
1523
|
+
}).catch(() => {
|
|
1524
|
+
recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
|
|
1525
|
+
}).finally(() => setIsLoading(false));
|
|
1526
|
+
}, [referencedTableId, executeAction, entries, targetSchema]);
|
|
1527
|
+
useEffect3(() => {
|
|
1528
|
+
const handleClick = (e) => {
|
|
1529
|
+
if (searchRef.current && !searchRef.current.contains(e.target)) {
|
|
1530
|
+
setIsSearchOpen(false);
|
|
1531
|
+
}
|
|
1532
|
+
};
|
|
1533
|
+
if (isSearchOpen) document.addEventListener("mousedown", handleClick);
|
|
1534
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
1535
|
+
}, [isSearchOpen]);
|
|
1536
|
+
const handleSearch = useCallback3((query) => {
|
|
1537
|
+
setSearchQuery(query);
|
|
1538
|
+
if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
|
|
1539
|
+
if (!query.trim()) {
|
|
1540
|
+
setSearchResults([]);
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
searchTimerRef.current = setTimeout(async () => {
|
|
1544
|
+
if (!executeAction || !referencedTableId) return;
|
|
1545
|
+
setIsSearching(true);
|
|
1546
|
+
try {
|
|
1547
|
+
const excludeIds = entries.map((e) => e.recordId);
|
|
1548
|
+
const res = await executeAction("SEARCH_SUB_TABLE_RECORDS", {
|
|
1549
|
+
referencedTableId,
|
|
1550
|
+
query: query.trim(),
|
|
1551
|
+
excludeIds,
|
|
1552
|
+
limit: 15
|
|
1553
|
+
});
|
|
1554
|
+
setSearchResults(Array.isArray(res) ? res : []);
|
|
1555
|
+
} catch (e) {
|
|
1556
|
+
setSearchResults([]);
|
|
1557
|
+
} finally {
|
|
1558
|
+
setIsSearching(false);
|
|
1559
|
+
}
|
|
1560
|
+
}, 300);
|
|
1561
|
+
}, [executeAction, referencedTableId, entries]);
|
|
1562
|
+
const targetColumns = ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
|
|
1563
|
+
(c) => {
|
|
1564
|
+
if (c.name === "_id" || c.type === "SUB_TABLE") return false;
|
|
1565
|
+
return true;
|
|
1566
|
+
}
|
|
1567
|
+
);
|
|
1568
|
+
const [relationOptions, setRelationOptions] = useState4({});
|
|
1569
|
+
useEffect3(() => {
|
|
1570
|
+
if (!executeAction || targetColumns.length === 0) return;
|
|
1571
|
+
const relationCols = targetColumns.filter((c) => {
|
|
1572
|
+
var _a2;
|
|
1573
|
+
return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION" && c.referencedTableId;
|
|
1574
|
+
});
|
|
1575
|
+
relationCols.forEach(async (col) => {
|
|
1576
|
+
try {
|
|
1577
|
+
const options = await executeAction("FETCH_RELATION", {
|
|
1578
|
+
referencedTableId: col.referencedTableId,
|
|
1579
|
+
displayField: col.displayField
|
|
1580
|
+
});
|
|
1581
|
+
if (options && Array.isArray(options)) {
|
|
1582
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
1583
|
+
}
|
|
1584
|
+
} catch (err) {
|
|
1585
|
+
console.warn(`[SubTableViewer] Could not fetch relation options for column ${col.name}:`, err);
|
|
1586
|
+
}
|
|
1587
|
+
});
|
|
1588
|
+
}, [executeAction, targetColumns]);
|
|
1589
|
+
const refetchRelation = useCallback3(async (colName) => {
|
|
1590
|
+
var _a2;
|
|
1591
|
+
const col = targetColumns.find((c) => c.name === colName);
|
|
1592
|
+
if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !col.referencedTableId || !executeAction) return;
|
|
1593
|
+
try {
|
|
1594
|
+
const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
|
|
1595
|
+
if (options && Array.isArray(options)) {
|
|
1596
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
1597
|
+
}
|
|
1598
|
+
} catch (err) {
|
|
1599
|
+
console.warn(`[SubTableViewer] Could not refetch relation options for column ${col.name}:`, err);
|
|
1600
|
+
}
|
|
1601
|
+
}, [targetColumns, executeAction]);
|
|
1602
|
+
const updateParentLinkage = async (updated) => {
|
|
1603
|
+
const isNewRow = rowId.startsWith("temp_");
|
|
1604
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1605
|
+
context.updateQuietly(rowId, column.name, updated);
|
|
1606
|
+
} else {
|
|
1607
|
+
onChange(updated);
|
|
1608
|
+
}
|
|
1609
|
+
if (executeAction && (context == null ? void 0 : context.parentTableId) && !isNewRow) {
|
|
1610
|
+
try {
|
|
1611
|
+
const payloadToSave = updated.map(({ recordId, isSelected }) => ({ recordId, isSelected }));
|
|
1612
|
+
await executeAction("UPDATE_RECORD", {
|
|
1613
|
+
tableId: context.parentTableId,
|
|
1614
|
+
recordId: rowId,
|
|
1615
|
+
data: { [column.name]: payloadToSave }
|
|
1616
|
+
});
|
|
1617
|
+
if (context == null ? void 0 : context.triggerSaveSuccess) {
|
|
1618
|
+
context.triggerSaveSuccess();
|
|
1619
|
+
}
|
|
1620
|
+
} catch (err) {
|
|
1621
|
+
console.error("Failed to auto-save parent linkage", err);
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
};
|
|
1625
|
+
const handleLinkRecords = (recordsToLink) => {
|
|
1626
|
+
if (!recordsToLink || recordsToLink.length === 0) return;
|
|
1627
|
+
const existingEntryIds = new Set(entries.map((e) => e.recordId));
|
|
1628
|
+
const newEntries = [];
|
|
1629
|
+
const newRecordsToAdd = [];
|
|
1630
|
+
for (const record of recordsToLink) {
|
|
1631
|
+
fetchedIdsRef.current.add(record.id);
|
|
1632
|
+
const resolvedData = __spreadValues({}, record.data || {});
|
|
1633
|
+
targetColumns.forEach((col) => {
|
|
1634
|
+
if ((resolvedData[col.name] === void 0 || resolvedData[col.name] === null) && record[col.name] !== void 0) {
|
|
1635
|
+
resolvedData[col.name] = record[col.name];
|
|
1636
|
+
}
|
|
1637
|
+
});
|
|
1638
|
+
if (!existingEntryIds.has(record.id)) {
|
|
1639
|
+
newEntries.push({
|
|
1640
|
+
recordId: record.id,
|
|
1641
|
+
isSelected: true,
|
|
1642
|
+
_resolvedData: resolvedData
|
|
1643
|
+
});
|
|
1644
|
+
existingEntryIds.add(record.id);
|
|
1645
|
+
}
|
|
1646
|
+
newRecordsToAdd.push({
|
|
1647
|
+
id: record.id,
|
|
1648
|
+
data: resolvedData
|
|
1649
|
+
});
|
|
1650
|
+
}
|
|
1651
|
+
const updatedEntries = [...entries, ...newEntries];
|
|
1652
|
+
updateParentLinkage(updatedEntries);
|
|
1653
|
+
setLinkedRecords((prev) => {
|
|
1654
|
+
const map = new Map(prev.map((r) => [r.id, r]));
|
|
1655
|
+
newRecordsToAdd.forEach((r) => {
|
|
1656
|
+
const existing = map.get(r.id);
|
|
1657
|
+
if (existing) {
|
|
1658
|
+
map.set(r.id, __spreadProps(__spreadValues({}, existing), {
|
|
1659
|
+
data: __spreadValues(__spreadValues({}, existing.data), r.data)
|
|
1660
|
+
}));
|
|
1661
|
+
} else {
|
|
1662
|
+
map.set(r.id, r);
|
|
1663
|
+
}
|
|
1664
|
+
});
|
|
1665
|
+
return Array.from(map.values());
|
|
1666
|
+
});
|
|
1667
|
+
setSearchQuery("");
|
|
1668
|
+
setSearchResults([]);
|
|
1669
|
+
setIsSearchOpen(false);
|
|
1670
|
+
};
|
|
1671
|
+
const handleLinkRecord = (record) => {
|
|
1672
|
+
handleLinkRecords([record]);
|
|
1673
|
+
};
|
|
1674
|
+
const handleUniqueConflict = (conflictData) => {
|
|
1675
|
+
const rawMatching = Array.isArray(conflictData == null ? void 0 : conflictData.matchingRecords) ? conflictData.matchingRecords : [];
|
|
1676
|
+
const resolvedMatching = rawMatching.map((r) => {
|
|
1677
|
+
var _a2;
|
|
1678
|
+
const recordId = String(r.id || ((_a2 = r._id) == null ? void 0 : _a2.$oid) || r._id);
|
|
1679
|
+
let dataObj = {};
|
|
1680
|
+
if (r.data && typeof r.data === "object") {
|
|
1681
|
+
dataObj = __spreadValues({}, r.data);
|
|
1682
|
+
}
|
|
1683
|
+
targetColumns.forEach((col) => {
|
|
1684
|
+
if ((dataObj[col.name] === void 0 || dataObj[col.name] === null) && r[col.name] !== void 0) {
|
|
1685
|
+
dataObj[col.name] = r[col.name];
|
|
1686
|
+
}
|
|
1687
|
+
});
|
|
1688
|
+
return {
|
|
1689
|
+
id: recordId,
|
|
1690
|
+
data: dataObj
|
|
1691
|
+
};
|
|
1692
|
+
});
|
|
1693
|
+
setConflictModalState({
|
|
1694
|
+
isOpen: true,
|
|
1695
|
+
fieldName: (conflictData == null ? void 0 : conflictData.fieldName) || "",
|
|
1696
|
+
matchingRecords: resolvedMatching
|
|
1697
|
+
});
|
|
1698
|
+
};
|
|
1699
|
+
const handleCancelConflict = () => {
|
|
1700
|
+
setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
|
|
1701
|
+
};
|
|
1702
|
+
const handleConfirmLinkConflict = async () => {
|
|
1703
|
+
const { matchingRecords } = conflictModalState;
|
|
1704
|
+
if (matchingRecords && matchingRecords.length > 0) {
|
|
1705
|
+
handleLinkRecords(matchingRecords);
|
|
1706
|
+
setNewRecordData({});
|
|
1707
|
+
setIsCreating(false);
|
|
1708
|
+
setConflictModalState({
|
|
1709
|
+
isOpen: false,
|
|
1710
|
+
fieldName: "",
|
|
1711
|
+
matchingRecords: []
|
|
1712
|
+
});
|
|
1713
|
+
addToast({
|
|
1714
|
+
type: "success",
|
|
1715
|
+
message: "\u05D4\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D5\u05E9\u05E8\u05D4 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
1716
|
+
});
|
|
1717
|
+
} else {
|
|
1718
|
+
setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1721
|
+
const handleUnlinkRecord = (recordId) => {
|
|
1722
|
+
const updated = entries.filter((e) => e.recordId !== recordId);
|
|
1723
|
+
updateParentLinkage(updated);
|
|
1724
|
+
setLinkedRecords((prev) => prev.filter((r) => r.id !== recordId));
|
|
1725
|
+
};
|
|
1726
|
+
const handleToggleSelected = (recordId) => {
|
|
1727
|
+
const record = linkedRecords.find((r) => r.id === recordId);
|
|
1728
|
+
const updated = entries.map(
|
|
1729
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { isSelected: !e.isSelected, _resolvedData: (record == null ? void 0 : record.data) || e._resolvedData }) : e
|
|
1730
|
+
);
|
|
1731
|
+
updateParentLinkage(updated);
|
|
1732
|
+
};
|
|
1733
|
+
const isMountedRef = useRef3(true);
|
|
1734
|
+
useEffect3(() => {
|
|
1735
|
+
isMountedRef.current = true;
|
|
1736
|
+
return () => {
|
|
1737
|
+
isMountedRef.current = false;
|
|
1738
|
+
};
|
|
1739
|
+
}, []);
|
|
1740
|
+
const handleCommitRecordCell = async (recordId, colName, value2) => {
|
|
1741
|
+
var _a2;
|
|
1742
|
+
const previousRecord = linkedRecords.find((r) => r.id === recordId);
|
|
1743
|
+
const previousValue = (_a2 = previousRecord == null ? void 0 : previousRecord.data) == null ? void 0 : _a2[colName];
|
|
1744
|
+
if (previousValue === value2) return true;
|
|
1745
|
+
const targetCol = targetColumns.find((c) => c.name === colName);
|
|
1746
|
+
const valRes = targetCol ? validateCellValue(value2, targetCol) : { isValid: true };
|
|
1747
|
+
if (!valRes.isValid) {
|
|
1748
|
+
addToast({
|
|
1749
|
+
type: "error",
|
|
1750
|
+
message: valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA"
|
|
1751
|
+
});
|
|
1752
|
+
return false;
|
|
1753
|
+
}
|
|
1754
|
+
if (executeAction && referencedTableId && !recordId.startsWith("temp_")) {
|
|
1755
|
+
try {
|
|
1756
|
+
const res = await executeAction("UPDATE_RECORD", {
|
|
1757
|
+
tableId: referencedTableId,
|
|
1758
|
+
recordId,
|
|
1759
|
+
data: { [colName]: value2 }
|
|
1760
|
+
});
|
|
1761
|
+
if (res && res.success === false) {
|
|
1762
|
+
const err = new Error(res.error || res.message || "Action execution failed");
|
|
1763
|
+
Object.assign(err, res);
|
|
1764
|
+
throw err;
|
|
1765
|
+
}
|
|
1766
|
+
if (isMountedRef.current) {
|
|
1767
|
+
const updatedRecords = linkedRecords.map(
|
|
1768
|
+
(r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
|
|
1769
|
+
);
|
|
1770
|
+
setLinkedRecords(updatedRecords);
|
|
1771
|
+
const targetRecord = updatedRecords.find((r) => r.id === recordId);
|
|
1772
|
+
const updatedEntries = entries.map(
|
|
1773
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
|
|
1774
|
+
);
|
|
1775
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1776
|
+
context.updateQuietly(rowId, column.name, updatedEntries);
|
|
1777
|
+
} else {
|
|
1778
|
+
onChange(updatedEntries);
|
|
1779
|
+
}
|
|
1780
|
+
if (context == null ? void 0 : context.triggerSaveSuccess) {
|
|
1781
|
+
context.triggerSaveSuccess();
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
return true;
|
|
1785
|
+
} catch (err) {
|
|
1786
|
+
console.error("[SubTableViewer] Failed to auto-save linked record field", err);
|
|
1787
|
+
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";
|
|
1788
|
+
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")) {
|
|
1789
|
+
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).`;
|
|
1790
|
+
} else if (errorMsg.includes("is required") || errorMsg.includes("\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4") || errorMsg.toLowerCase().includes("required")) {
|
|
1791
|
+
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.`;
|
|
1792
|
+
}
|
|
1793
|
+
addToast({
|
|
1794
|
+
type: "error",
|
|
1795
|
+
message: errorMsg
|
|
1796
|
+
});
|
|
1797
|
+
return false;
|
|
1798
|
+
}
|
|
1799
|
+
} else {
|
|
1800
|
+
if (isMountedRef.current) {
|
|
1801
|
+
const updatedRecords = linkedRecords.map(
|
|
1802
|
+
(r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
|
|
1803
|
+
);
|
|
1804
|
+
setLinkedRecords(updatedRecords);
|
|
1805
|
+
const targetRecord = updatedRecords.find((r) => r.id === recordId);
|
|
1806
|
+
const updatedEntries = entries.map(
|
|
1807
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
|
|
1808
|
+
);
|
|
1809
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1810
|
+
context.updateQuietly(rowId, column.name, updatedEntries);
|
|
1811
|
+
} else {
|
|
1812
|
+
onChange(updatedEntries);
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
return true;
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
const handleRecordCellChange = handleCommitRecordCell;
|
|
1819
|
+
const handleCreateRecord = async () => {
|
|
1820
|
+
var _a2, _b2, _c, _d, _e;
|
|
1821
|
+
if (!executeAction || !referencedTableId) return;
|
|
1822
|
+
for (const col of targetColumns) {
|
|
1823
|
+
if (col.isRequired) {
|
|
1824
|
+
const val = newRecordData[col.name];
|
|
1825
|
+
if (val === void 0 || val === null || typeof val === "string" && val.trim() === "") {
|
|
1826
|
+
addToast({
|
|
1827
|
+
type: "error",
|
|
1828
|
+
message: `Validation Error: Field '${col.name}' is required but was not provided.`
|
|
1829
|
+
});
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE") {
|
|
1834
|
+
const val = newRecordData[col.name];
|
|
1835
|
+
if (val !== void 0 && val !== null && String(val).trim() !== "" && !isValidPhoneNumber(String(val))) {
|
|
1836
|
+
addToast({
|
|
1837
|
+
type: "error",
|
|
1838
|
+
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.`
|
|
1839
|
+
});
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
try {
|
|
1845
|
+
const res = await executeAction("CREATE_RECORD", {
|
|
1846
|
+
tableId: referencedTableId,
|
|
1847
|
+
records: [newRecordData]
|
|
1848
|
+
});
|
|
1849
|
+
if (res && (res.error === "UNIQUE_CONSTRAINT_CONFLICT" || res.code === "UNIQUE_CONSTRAINT_CONFLICT")) {
|
|
1850
|
+
handleUniqueConflict(res);
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1853
|
+
if (res && res.success === false) {
|
|
1854
|
+
throw new Error(res.error || "Action execution failed");
|
|
1855
|
+
}
|
|
1856
|
+
const created = Array.isArray(res) ? res[0] : ((_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2[0]) || res;
|
|
1857
|
+
if (created) {
|
|
1858
|
+
const newRecord = {
|
|
1859
|
+
id: String(created.id || created._id),
|
|
1860
|
+
data: created.data || newRecordData
|
|
1861
|
+
};
|
|
1862
|
+
handleLinkRecord(newRecord);
|
|
1863
|
+
setIsCreating(false);
|
|
1864
|
+
setNewRecordData({});
|
|
1865
|
+
}
|
|
1866
|
+
} catch (err) {
|
|
1867
|
+
const isConflict = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" || (err == null ? void 0 : err.code) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_c = err == null ? void 0 : err.data) == null ? void 0 : _c.error) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_d = err == null ? void 0 : err.message) == null ? void 0 : _d.includes("UNIQUE_CONSTRAINT_CONFLICT"));
|
|
1868
|
+
if (isConflict) {
|
|
1869
|
+
const conflictPayload = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err : ((_e = err == null ? void 0 : err.data) == null ? void 0 : _e.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err.data : err;
|
|
1870
|
+
handleUniqueConflict(conflictPayload);
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
const msg = (err == null ? void 0 : err.message) || String(err);
|
|
1874
|
+
addToast({
|
|
1875
|
+
type: "error",
|
|
1876
|
+
message: msg
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
};
|
|
1880
|
+
const getDisplayLabel = (record) => {
|
|
1881
|
+
const fields = column.subTableDisplayFields || [];
|
|
1882
|
+
if (fields.length === 0) {
|
|
1883
|
+
const firstField = Object.keys(record.data).find((k) => k !== "_id");
|
|
1884
|
+
return firstField ? String(record.data[firstField] || "") : record.id;
|
|
1885
|
+
}
|
|
1886
|
+
return fields.map((f) => String(record.data[f] || "")).filter(Boolean).join(" ");
|
|
1887
|
+
};
|
|
1888
|
+
return /* @__PURE__ */ jsxs5("div", { className: "p-3 animate-in fade-in slide-in-from-top-2 duration-200", dir: "rtl", children: [
|
|
1889
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-4 mb-2.5", children: [
|
|
1890
|
+
/* @__PURE__ */ jsx5("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx5("span", { className: "text-xs font-bold text-slate-600", children: (_a = targetSchema == null ? void 0 : targetSchema.name) != null ? _a : column.referencedTableName }) }),
|
|
1891
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
|
|
1892
|
+
/* @__PURE__ */ jsxs5("div", { className: "relative", ref: searchRef, children: [
|
|
1893
|
+
/* @__PURE__ */ jsxs5(
|
|
1894
|
+
"button",
|
|
1895
|
+
{
|
|
1896
|
+
type: "button",
|
|
1897
|
+
onClick: () => setIsSearchOpen((prev) => !prev),
|
|
1898
|
+
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",
|
|
1899
|
+
children: [
|
|
1900
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
|
|
1901
|
+
"\u05E7\u05D9\u05E9\u05D5\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
|
|
1902
|
+
]
|
|
1903
|
+
}
|
|
1904
|
+
),
|
|
1905
|
+
isSearchOpen && /* @__PURE__ */ jsxs5("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: [
|
|
1906
|
+
/* @__PURE__ */ jsx5(
|
|
1907
|
+
"input",
|
|
1908
|
+
{
|
|
1909
|
+
type: "text",
|
|
1910
|
+
value: searchQuery,
|
|
1911
|
+
onChange: (e) => handleSearch(e.target.value),
|
|
1912
|
+
placeholder: "\u05D7\u05E4\u05E9 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
1913
|
+
className: "w-full h-8 px-2.5 text-xs border border-slate-300 rounded-md focus:outline-none focus:ring-1 focus:ring-blue-400 mb-1.5",
|
|
1914
|
+
autoFocus: true
|
|
1915
|
+
}
|
|
1916
|
+
),
|
|
1917
|
+
/* @__PURE__ */ jsx5("div", { className: "max-h-48 overflow-y-auto", children: isSearching ? /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsx5("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__ */ jsx5(
|
|
1918
|
+
"button",
|
|
1919
|
+
{
|
|
1920
|
+
type: "button",
|
|
1921
|
+
onClick: () => handleLinkRecord(r),
|
|
1922
|
+
className: "w-full text-right px-2 py-1.5 text-xs hover:bg-blue-50 rounded cursor-pointer transition-colors",
|
|
1923
|
+
children: getDisplayLabel(r)
|
|
1924
|
+
},
|
|
1925
|
+
r.id
|
|
1926
|
+
)) : searchQuery.trim() ? /* @__PURE__ */ jsx5("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__ */ jsx5("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05D4\u05E7\u05DC\u05D3 \u05DC\u05D7\u05D9\u05E4\u05D5\u05E9..." }) })
|
|
1927
|
+
] })
|
|
1928
|
+
] }),
|
|
1929
|
+
/* @__PURE__ */ jsxs5(
|
|
1930
|
+
"button",
|
|
1931
|
+
{
|
|
1932
|
+
type: "button",
|
|
1933
|
+
onClick: () => {
|
|
1934
|
+
setIsCreating(true);
|
|
1935
|
+
const initialData = {};
|
|
1936
|
+
targetColumns.forEach((c) => {
|
|
1937
|
+
if (c.defaultValue !== void 0 && c.defaultValue !== null) {
|
|
1938
|
+
initialData[c.name] = c.type === "NUMBER" || c.type === "CURRENCY" ? parseFloat(c.defaultValue) : c.type === "BOOLEAN" ? c.defaultValue === "true" || c.defaultValue === true : c.defaultValue;
|
|
1939
|
+
} else {
|
|
1940
|
+
if (c.type === "NUMBER" || c.type === "CURRENCY") initialData[c.name] = 0;
|
|
1941
|
+
else if (c.type === "BOOLEAN") initialData[c.name] = false;
|
|
1942
|
+
else initialData[c.name] = "";
|
|
1943
|
+
}
|
|
1944
|
+
});
|
|
1945
|
+
setNewRecordData(initialData);
|
|
1946
|
+
},
|
|
1947
|
+
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",
|
|
1948
|
+
children: [
|
|
1949
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) }),
|
|
1950
|
+
"\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4"
|
|
1951
|
+
]
|
|
1952
|
+
}
|
|
1953
|
+
)
|
|
1954
|
+
] })
|
|
1955
|
+
] }),
|
|
1956
|
+
isLoading ? /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx5("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ jsx5("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__ */ jsx5("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-xs border-collapse", children: [
|
|
1957
|
+
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsxs5("tr", { className: "bg-slate-100/80", children: [
|
|
1958
|
+
/* @__PURE__ */ jsx5("th", { className: "border border-slate-200 px-2 py-1.5 text-center w-10 font-semibold text-slate-500", children: "\u05E0\u05D1\u05D7\u05E8" }),
|
|
1959
|
+
targetColumns.map((col) => {
|
|
1960
|
+
var _a2;
|
|
1961
|
+
const isContact = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "GOOGLE_CONTACT";
|
|
1962
|
+
return /* @__PURE__ */ jsx5(
|
|
1963
|
+
"th",
|
|
1964
|
+
{
|
|
1965
|
+
className: `border border-slate-200 px-2 py-1.5 text-right font-semibold text-slate-600 whitespace-nowrap ${isContact ? "min-w-[140px]" : ""}`,
|
|
1966
|
+
children: col.name
|
|
1967
|
+
},
|
|
1968
|
+
col.name
|
|
1969
|
+
);
|
|
1970
|
+
}),
|
|
1971
|
+
/* @__PURE__ */ jsx5("th", { className: "border border-slate-200 px-2 py-1.5 w-14" })
|
|
1972
|
+
] }) }),
|
|
1973
|
+
/* @__PURE__ */ jsxs5("tbody", { children: [
|
|
1974
|
+
entries.map((entry) => {
|
|
1975
|
+
var _a2;
|
|
1976
|
+
const record = linkedRecords.find((r) => r.id === entry.recordId);
|
|
1977
|
+
return /* @__PURE__ */ jsxs5("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
|
|
1978
|
+
/* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-2 py-1 text-center", children: /* @__PURE__ */ jsx5(
|
|
1979
|
+
"input",
|
|
1980
|
+
{
|
|
1981
|
+
type: "checkbox",
|
|
1982
|
+
checked: entry.isSelected,
|
|
1983
|
+
onChange: () => handleToggleSelected(entry.recordId),
|
|
1984
|
+
className: "w-3.5 h-3.5 rounded border-slate-300 text-blue-600 cursor-pointer"
|
|
1985
|
+
}
|
|
1986
|
+
) }),
|
|
1987
|
+
targetColumns.map((col) => {
|
|
1988
|
+
var _a3;
|
|
1989
|
+
const isContact = ((_a3 = col.type) == null ? void 0 : _a3.toUpperCase()) === "GOOGLE_CONTACT";
|
|
1990
|
+
if (!record) {
|
|
1991
|
+
return /* @__PURE__ */ jsx5(
|
|
1992
|
+
"td",
|
|
1993
|
+
{
|
|
1994
|
+
className: `border border-slate-200 p-0 relative h-8 ${isContact ? "min-w-[140px]" : ""}`,
|
|
1995
|
+
children: /* @__PURE__ */ jsx5("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." })
|
|
1996
|
+
},
|
|
1997
|
+
col.name
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
return /* @__PURE__ */ jsx5(
|
|
2001
|
+
SubTableCell,
|
|
2002
|
+
{
|
|
2003
|
+
record,
|
|
2004
|
+
column: col,
|
|
2005
|
+
targetSchema,
|
|
2006
|
+
referencedTableId,
|
|
2007
|
+
context,
|
|
2008
|
+
relationOptions,
|
|
2009
|
+
setRelationOptions,
|
|
2010
|
+
refetchRelation,
|
|
2011
|
+
onCommit: handleCommitRecordCell
|
|
2012
|
+
},
|
|
2013
|
+
`${record.id}_${col.name}`
|
|
2014
|
+
);
|
|
2015
|
+
}),
|
|
2016
|
+
/* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-1 py-1 text-center", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-center gap-1", children: [
|
|
2017
|
+
((_a2 = column.config) == null ? void 0 : _a2.actionType) === "WHATSAPP" && (() => {
|
|
2018
|
+
var _a3, _b2, _c;
|
|
2019
|
+
const actionPhoneCol = (_a3 = column.config) == null ? void 0 : _a3.actionPhoneColumn;
|
|
2020
|
+
const phone = actionPhoneCol ? ((_b2 = record == null ? void 0 : record.data) == null ? void 0 : _b2[actionPhoneCol]) || ((_c = entry._resolvedData) == null ? void 0 : _c[actionPhoneCol]) : null;
|
|
2021
|
+
if (phone) {
|
|
2022
|
+
return /* @__PURE__ */ jsx5(
|
|
2023
|
+
"button",
|
|
2024
|
+
{
|
|
2025
|
+
type: "button",
|
|
2026
|
+
onClick: (e) => {
|
|
2027
|
+
e.stopPropagation();
|
|
2028
|
+
openWhatsAppChat(String(phone));
|
|
2029
|
+
},
|
|
2030
|
+
className: "text-emerald-500 hover:text-emerald-600 p-0.5 rounded hover:bg-emerald-50 transition-colors cursor-pointer",
|
|
2031
|
+
title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
|
|
2032
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("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" }) })
|
|
2033
|
+
}
|
|
2034
|
+
);
|
|
2035
|
+
}
|
|
2036
|
+
return null;
|
|
2037
|
+
})(),
|
|
2038
|
+
/* @__PURE__ */ jsx5(
|
|
2039
|
+
"button",
|
|
2040
|
+
{
|
|
2041
|
+
type: "button",
|
|
2042
|
+
onClick: (e) => {
|
|
2043
|
+
e.stopPropagation();
|
|
2044
|
+
handleUnlinkRecord(entry.recordId);
|
|
2045
|
+
},
|
|
2046
|
+
className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center",
|
|
2047
|
+
title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
|
|
2048
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
|
|
2049
|
+
}
|
|
2050
|
+
)
|
|
2051
|
+
] }) })
|
|
2052
|
+
] }, entry.recordId);
|
|
2053
|
+
}),
|
|
2054
|
+
isCreating && /* @__PURE__ */ jsxs5("tr", { className: "bg-emerald-50/40", children: [
|
|
2055
|
+
/* @__PURE__ */ jsx5("td", { className: "border border-emerald-200 px-2 py-1 text-center", children: /* @__PURE__ */ jsx5("span", { className: "text-emerald-500 font-bold text-[10px]", children: "\u05D7\u05D3\u05E9" }) }),
|
|
2056
|
+
targetColumns.map((col) => {
|
|
2057
|
+
var _a2, _b2;
|
|
2058
|
+
const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
|
|
2059
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
2060
|
+
const isContact = colType === "GOOGLE_CONTACT";
|
|
2061
|
+
return /* @__PURE__ */ jsx5(
|
|
2062
|
+
"td",
|
|
2063
|
+
{
|
|
2064
|
+
className: `border border-emerald-200 p-0 relative h-8 ${isContact ? "min-w-[140px]" : ""}`,
|
|
2065
|
+
children: /* @__PURE__ */ jsx5(
|
|
2066
|
+
InputComponent,
|
|
2067
|
+
{
|
|
2068
|
+
value: (_b2 = newRecordData[col.name]) != null ? _b2 : colType === "BOOLEAN" ? false : "",
|
|
2069
|
+
column: col,
|
|
2070
|
+
rowId: "new_record",
|
|
2071
|
+
onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
|
|
2072
|
+
context: __spreadProps(__spreadValues({}, context), {
|
|
2073
|
+
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",
|
|
2074
|
+
relationOptions,
|
|
2075
|
+
refetchRelation,
|
|
2076
|
+
tableId: (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId
|
|
2077
|
+
})
|
|
2078
|
+
}
|
|
2079
|
+
)
|
|
2080
|
+
},
|
|
2081
|
+
`new_${col.name}`
|
|
2082
|
+
);
|
|
2083
|
+
}),
|
|
2084
|
+
/* @__PURE__ */ jsx5("td", { className: "border border-emerald-200 px-1 py-1 text-center", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-center gap-1", children: [
|
|
2085
|
+
/* @__PURE__ */ jsx5(
|
|
2086
|
+
"button",
|
|
2087
|
+
{
|
|
2088
|
+
type: "button",
|
|
2089
|
+
onClick: handleCreateRecord,
|
|
2090
|
+
className: "p-1 text-emerald-600 hover:bg-emerald-100 rounded transition-colors",
|
|
2091
|
+
title: "\u05E9\u05DE\u05D5\u05E8",
|
|
2092
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) })
|
|
2093
|
+
}
|
|
2094
|
+
),
|
|
2095
|
+
/* @__PURE__ */ jsx5(
|
|
2096
|
+
"button",
|
|
2097
|
+
{
|
|
2098
|
+
type: "button",
|
|
2099
|
+
onClick: () => {
|
|
2100
|
+
setIsCreating(false);
|
|
2101
|
+
},
|
|
2102
|
+
className: "p-1 text-rose-500 hover:bg-rose-100 rounded transition-colors",
|
|
2103
|
+
title: "\u05D1\u05D9\u05D8\u05D5\u05DC",
|
|
2104
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M6 18L18 6M6 6l12 12" }) })
|
|
2105
|
+
}
|
|
2106
|
+
)
|
|
2107
|
+
] }) })
|
|
2108
|
+
] })
|
|
2109
|
+
] })
|
|
2110
|
+
] }) }),
|
|
2111
|
+
conflictModalState.isOpen && /* @__PURE__ */ jsx5(
|
|
2112
|
+
"div",
|
|
2113
|
+
{
|
|
2114
|
+
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",
|
|
2115
|
+
dir: "rtl",
|
|
2116
|
+
onClick: handleCancelConflict,
|
|
2117
|
+
children: /* @__PURE__ */ jsxs5(
|
|
2118
|
+
"div",
|
|
2119
|
+
{
|
|
2120
|
+
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",
|
|
2121
|
+
onClick: (e) => e.stopPropagation(),
|
|
2122
|
+
children: [
|
|
2123
|
+
/* @__PURE__ */ jsxs5("div", { className: "p-5 border-b border-slate-100 flex items-center gap-3", children: [
|
|
2124
|
+
/* @__PURE__ */ jsx5("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__ */ jsx5("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("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" }) }) }),
|
|
2125
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
2126
|
+
/* @__PURE__ */ jsx5("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" }),
|
|
2127
|
+
/* @__PURE__ */ jsx5("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" })
|
|
2128
|
+
] })
|
|
2129
|
+
] }),
|
|
2130
|
+
/* @__PURE__ */ jsxs5("div", { className: "p-5 space-y-3", children: [
|
|
2131
|
+
/* @__PURE__ */ jsxs5("p", { className: "text-sm text-slate-700 leading-relaxed", children: [
|
|
2132
|
+
"\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",
|
|
2133
|
+
" ",
|
|
2134
|
+
/* @__PURE__ */ jsx5("span", { className: "font-bold text-slate-900 bg-slate-100 px-1.5 py-0.5 rounded border border-slate-200", children: conflictModalState.fieldName }),
|
|
2135
|
+
". \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?"
|
|
2136
|
+
] }),
|
|
2137
|
+
conflictModalState.matchingRecords.length > 1 && /* @__PURE__ */ jsxs5("div", { className: "p-3 bg-blue-50 border border-blue-200 rounded-lg text-xs font-semibold text-blue-800", children: [
|
|
2138
|
+
"\u05E0\u05DE\u05E6\u05D0\u05D5 ",
|
|
2139
|
+
conflictModalState.matchingRecords.length,
|
|
2140
|
+
" \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?"
|
|
2141
|
+
] }),
|
|
2142
|
+
conflictModalState.matchingRecords.length > 0 && /* @__PURE__ */ jsx5("div", { className: "overflow-x-auto border border-slate-200 rounded-lg max-h-48 text-xs bg-white", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-right border-collapse", children: [
|
|
2143
|
+
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsx5("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(((_b = conflictModalState.matchingRecords[0]) == null ? void 0 : _b.data) || {}).filter((k) => k !== "_id" && k !== "id").map((name) => ({ name }))).map((col) => /* @__PURE__ */ jsx5(
|
|
2144
|
+
"th",
|
|
2145
|
+
{
|
|
2146
|
+
className: "bg-slate-100 text-slate-700 font-semibold p-2 border-b whitespace-nowrap",
|
|
2147
|
+
children: col.name
|
|
2148
|
+
},
|
|
2149
|
+
col.name
|
|
2150
|
+
)) }) }),
|
|
2151
|
+
/* @__PURE__ */ jsx5("tbody", { children: conflictModalState.matchingRecords.map((r, idx) => {
|
|
2152
|
+
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 }));
|
|
2153
|
+
return /* @__PURE__ */ jsx5("tr", { className: "hover:bg-slate-50/80 transition-colors", children: cols.map((col) => {
|
|
2154
|
+
var _a2;
|
|
2155
|
+
const rawVal = (_a2 = r.data) == null ? void 0 : _a2[col.name];
|
|
2156
|
+
let displayVal = "-";
|
|
2157
|
+
if (rawVal !== void 0 && rawVal !== null && rawVal !== "") {
|
|
2158
|
+
if (typeof rawVal === "boolean") {
|
|
2159
|
+
displayVal = rawVal ? "\u05DB\u05DF" : "\u05DC\u05D0";
|
|
2160
|
+
} else if (typeof rawVal === "object") {
|
|
2161
|
+
displayVal = Array.isArray(rawVal) ? rawVal.join(", ") : JSON.stringify(rawVal);
|
|
2162
|
+
} else {
|
|
2163
|
+
displayVal = String(rawVal);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
return /* @__PURE__ */ jsx5(
|
|
2167
|
+
"td",
|
|
2168
|
+
{
|
|
2169
|
+
className: "p-2 border-b border-slate-100 whitespace-nowrap text-slate-800",
|
|
2170
|
+
children: displayVal
|
|
2171
|
+
},
|
|
2172
|
+
col.name
|
|
2173
|
+
);
|
|
2174
|
+
}) }, r.id || idx);
|
|
2175
|
+
}) })
|
|
2176
|
+
] }) })
|
|
2177
|
+
] }),
|
|
2178
|
+
/* @__PURE__ */ jsxs5("div", { className: "p-4 bg-slate-50 border-t border-slate-100 flex items-center justify-end gap-2.5", children: [
|
|
2179
|
+
/* @__PURE__ */ jsx5(
|
|
2180
|
+
"button",
|
|
2181
|
+
{
|
|
2182
|
+
type: "button",
|
|
2183
|
+
onClick: handleCancelConflict,
|
|
2184
|
+
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",
|
|
2185
|
+
children: "\u05D1\u05D9\u05D8\u05D5\u05DC"
|
|
2186
|
+
}
|
|
2187
|
+
),
|
|
2188
|
+
/* @__PURE__ */ jsxs5(
|
|
2189
|
+
"button",
|
|
2190
|
+
{
|
|
2191
|
+
type: "button",
|
|
2192
|
+
onClick: handleConfirmLinkConflict,
|
|
2193
|
+
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",
|
|
2194
|
+
children: [
|
|
2195
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("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" }) }),
|
|
2196
|
+
conflictModalState.matchingRecords.length > 1 ? "\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF" : "\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4"
|
|
2197
|
+
]
|
|
2198
|
+
}
|
|
2199
|
+
)
|
|
2200
|
+
] })
|
|
2201
|
+
]
|
|
2202
|
+
}
|
|
2203
|
+
)
|
|
2204
|
+
}
|
|
2205
|
+
)
|
|
2206
|
+
] });
|
|
2207
|
+
}
|
|
2208
|
+
|
|
869
2209
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
870
2210
|
import { X as X4, Copy as Copy2 } from "lucide-react";
|
|
871
|
-
import { jsx as
|
|
2211
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
872
2212
|
function TableBlockClient({
|
|
873
2213
|
data: initialRecords,
|
|
874
2214
|
settings: schema,
|
|
@@ -885,14 +2225,14 @@ function TableBlockClient({
|
|
|
885
2225
|
"data-testid": dataTestId
|
|
886
2226
|
}) {
|
|
887
2227
|
const { showError, addToast } = useToast();
|
|
888
|
-
const [columnWidths, setColumnWidths] =
|
|
889
|
-
const [isMounted, setIsMounted] =
|
|
2228
|
+
const [columnWidths, setColumnWidths] = useState5({});
|
|
2229
|
+
const [isMounted, setIsMounted] = useState5(false);
|
|
890
2230
|
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";
|
|
891
|
-
const [page, setPage] =
|
|
892
|
-
const [limit, setLimit] =
|
|
893
|
-
const [totalRecords, setTotalRecords] =
|
|
894
|
-
const [totalPages, setTotalPages] =
|
|
895
|
-
|
|
2231
|
+
const [page, setPage] = useState5(1);
|
|
2232
|
+
const [limit, setLimit] = useState5(50);
|
|
2233
|
+
const [totalRecords, setTotalRecords] = useState5(0);
|
|
2234
|
+
const [totalPages, setTotalPages] = useState5(1);
|
|
2235
|
+
useEffect4(() => {
|
|
896
2236
|
if (typeof window !== "undefined") {
|
|
897
2237
|
const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
|
|
898
2238
|
if (savedWidths) {
|
|
@@ -915,7 +2255,7 @@ function TableBlockClient({
|
|
|
915
2255
|
}
|
|
916
2256
|
setIsMounted(true);
|
|
917
2257
|
}, [tableKey]);
|
|
918
|
-
const [showSummary, setShowSummary] =
|
|
2258
|
+
const [showSummary, setShowSummary] = useState5(false);
|
|
919
2259
|
const toggleSummary = () => {
|
|
920
2260
|
setShowSummary((prev) => {
|
|
921
2261
|
const next = !prev;
|
|
@@ -924,8 +2264,8 @@ function TableBlockClient({
|
|
|
924
2264
|
return next;
|
|
925
2265
|
});
|
|
926
2266
|
};
|
|
927
|
-
const [resizingCol, setResizingCol] =
|
|
928
|
-
|
|
2267
|
+
const [resizingCol, setResizingCol] = useState5(null);
|
|
2268
|
+
useEffect4(() => {
|
|
929
2269
|
if (!resizingCol) return;
|
|
930
2270
|
const handleMouseMove = (e) => {
|
|
931
2271
|
const diffX = resizingCol.startX - e.clientX;
|
|
@@ -972,7 +2312,7 @@ function TableBlockClient({
|
|
|
972
2312
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
973
2313
|
});
|
|
974
2314
|
};
|
|
975
|
-
const mergeColumnDefs =
|
|
2315
|
+
const mergeColumnDefs = useCallback4((existingCols, incomingCols) => {
|
|
976
2316
|
if (!incomingCols || incomingCols.length === 0) return existingCols || [];
|
|
977
2317
|
if (!existingCols || existingCols.length === 0) return incomingCols;
|
|
978
2318
|
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
@@ -992,18 +2332,18 @@ function TableBlockClient({
|
|
|
992
2332
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
993
2333
|
});
|
|
994
2334
|
}, []);
|
|
995
|
-
const [localColumns, setLocalColumns] =
|
|
996
|
-
|
|
2335
|
+
const [localColumns, setLocalColumns] = useState5(() => (schema == null ? void 0 : schema.columns) || []);
|
|
2336
|
+
useEffect4(() => {
|
|
997
2337
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
998
2338
|
setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
|
|
999
2339
|
}
|
|
1000
2340
|
}, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
|
|
1001
|
-
const [dirty, setDirty] =
|
|
1002
|
-
const dirtyRef =
|
|
1003
|
-
|
|
2341
|
+
const [dirty, setDirty] = useState5({ added: [], modified: {}, deleted: [] });
|
|
2342
|
+
const dirtyRef = useRef4(dirty);
|
|
2343
|
+
useEffect4(() => {
|
|
1004
2344
|
dirtyRef.current = dirty;
|
|
1005
2345
|
}, [dirty]);
|
|
1006
|
-
const mergeWithDirty =
|
|
2346
|
+
const mergeWithDirty = useCallback4((baseRecords) => {
|
|
1007
2347
|
const { added, modified, deleted } = dirtyRef.current;
|
|
1008
2348
|
const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
|
|
1009
2349
|
const modifiedRecords = nonDeleted.map((r) => {
|
|
@@ -1016,8 +2356,8 @@ function TableBlockClient({
|
|
|
1016
2356
|
const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
|
|
1017
2357
|
return [...uniqueAdded, ...modifiedRecords];
|
|
1018
2358
|
}, []);
|
|
1019
|
-
const [data, setData] =
|
|
1020
|
-
|
|
2359
|
+
const [data, setData] = useState5(() => normalizeRecords(initialRecords));
|
|
2360
|
+
useEffect4(() => {
|
|
1021
2361
|
if (initialRecords) {
|
|
1022
2362
|
setData(mergeWithDirty(normalizeRecords(initialRecords)));
|
|
1023
2363
|
}
|
|
@@ -1032,19 +2372,19 @@ function TableBlockClient({
|
|
|
1032
2372
|
}
|
|
1033
2373
|
return false;
|
|
1034
2374
|
};
|
|
1035
|
-
const [baseRecordsMap, setBaseRecordsMap] =
|
|
2375
|
+
const [baseRecordsMap, setBaseRecordsMap] = useState5(() => {
|
|
1036
2376
|
const map = /* @__PURE__ */ new Map();
|
|
1037
2377
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1038
2378
|
return map;
|
|
1039
2379
|
});
|
|
1040
|
-
|
|
2380
|
+
useEffect4(() => {
|
|
1041
2381
|
if (initialRecords && initialRecords.length > 0) {
|
|
1042
2382
|
const map = /* @__PURE__ */ new Map();
|
|
1043
2383
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1044
2384
|
setBaseRecordsMap(map);
|
|
1045
2385
|
}
|
|
1046
2386
|
}, [initialRecords]);
|
|
1047
|
-
const refetchTableData =
|
|
2387
|
+
const refetchTableData = useCallback4((targetPage) => {
|
|
1048
2388
|
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1049
2389
|
if (!tableId || !executeAction) return Promise.resolve();
|
|
1050
2390
|
const activePage = targetPage !== void 0 ? targetPage : page;
|
|
@@ -1078,8 +2418,8 @@ function TableBlockClient({
|
|
|
1078
2418
|
}).catch((err) => {
|
|
1079
2419
|
console.error("[TableBlock] Failed to auto-fetch table data:", err);
|
|
1080
2420
|
});
|
|
1081
|
-
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction,
|
|
1082
|
-
|
|
2421
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs]);
|
|
2422
|
+
useEffect4(() => {
|
|
1083
2423
|
refetchTableData();
|
|
1084
2424
|
}, [refetchTableData]);
|
|
1085
2425
|
const handleLimitChange = (newLimit) => {
|
|
@@ -1095,19 +2435,20 @@ function TableBlockClient({
|
|
|
1095
2435
|
const handleNextPage = () => {
|
|
1096
2436
|
setPage((prev) => Math.min(totalPages, prev + 1));
|
|
1097
2437
|
};
|
|
1098
|
-
|
|
2438
|
+
useEffect4(() => {
|
|
1099
2439
|
if (error) {
|
|
1100
2440
|
showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
|
|
1101
2441
|
}
|
|
1102
2442
|
}, [error, showError]);
|
|
1103
|
-
const [searchQuery, setSearchQuery] =
|
|
1104
|
-
const [selectedIds, setSelectedIds] =
|
|
1105
|
-
const [pendingDeletions, setPendingDeletions] =
|
|
1106
|
-
const [isSaving, setIsSaving] =
|
|
1107
|
-
const [isSaveSuccess, setIsSaveSuccess] =
|
|
1108
|
-
const [relationOptions, setRelationOptions] =
|
|
2443
|
+
const [searchQuery, setSearchQuery] = useState5("");
|
|
2444
|
+
const [selectedIds, setSelectedIds] = useState5(/* @__PURE__ */ new Set());
|
|
2445
|
+
const [pendingDeletions, setPendingDeletions] = useState5([]);
|
|
2446
|
+
const [isSaving, setIsSaving] = useState5(false);
|
|
2447
|
+
const [isSaveSuccess, setIsSaveSuccess] = useState5(false);
|
|
2448
|
+
const [relationOptions, setRelationOptions] = useState5({});
|
|
2449
|
+
const [expandedRowIds, setExpandedRowIds] = useState5(/* @__PURE__ */ new Set());
|
|
1109
2450
|
const schemaColsString = useMemo2(() => JSON.stringify(localColumns || []), [localColumns]);
|
|
1110
|
-
const refetchRelation =
|
|
2451
|
+
const refetchRelation = useCallback4(async (colName) => {
|
|
1111
2452
|
var _a;
|
|
1112
2453
|
let parsedCols = [];
|
|
1113
2454
|
try {
|
|
@@ -1127,7 +2468,7 @@ function TableBlockClient({
|
|
|
1127
2468
|
console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
|
|
1128
2469
|
}
|
|
1129
2470
|
}, [schemaColsString, executeAction]);
|
|
1130
|
-
|
|
2471
|
+
useEffect4(() => {
|
|
1131
2472
|
let parsedCols = [];
|
|
1132
2473
|
try {
|
|
1133
2474
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -1163,9 +2504,9 @@ function TableBlockClient({
|
|
|
1163
2504
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1164
2505
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name));
|
|
1165
2506
|
}, [normalizedColumns]);
|
|
1166
|
-
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] =
|
|
1167
|
-
const dropdownRef =
|
|
1168
|
-
|
|
2507
|
+
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState5(false);
|
|
2508
|
+
const dropdownRef = useRef4(null);
|
|
2509
|
+
useEffect4(() => {
|
|
1169
2510
|
const handleClickOutside = (e) => {
|
|
1170
2511
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1171
2512
|
setIsColumnsDropdownOpen(false);
|
|
@@ -1243,8 +2584,8 @@ function TableBlockClient({
|
|
|
1243
2584
|
}
|
|
1244
2585
|
}
|
|
1245
2586
|
};
|
|
1246
|
-
const [draggedColName, setDraggedColName] =
|
|
1247
|
-
const [dragOverColName, setDragOverColName] =
|
|
2587
|
+
const [draggedColName, setDraggedColName] = useState5(null);
|
|
2588
|
+
const [dragOverColName, setDragOverColName] = useState5(null);
|
|
1248
2589
|
const handleColumnReorder = async (draggedName, dropTargetName) => {
|
|
1249
2590
|
var _a;
|
|
1250
2591
|
if (draggedName === dropTargetName) return;
|
|
@@ -1286,6 +2627,10 @@ function TableBlockClient({
|
|
|
1286
2627
|
var _a;
|
|
1287
2628
|
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
1288
2629
|
let initialValue = col.defaultValue;
|
|
2630
|
+
if (typeUpper === "SUB_TABLE") {
|
|
2631
|
+
defaultData[col.name] = [];
|
|
2632
|
+
return;
|
|
2633
|
+
}
|
|
1289
2634
|
if (initialValue !== void 0 && initialValue !== null && initialValue !== "") {
|
|
1290
2635
|
if (typeUpper === "CURRENCY" || typeUpper === "NUMBER") {
|
|
1291
2636
|
initialValue = parseFloat(initialValue);
|
|
@@ -1369,6 +2714,36 @@ function TableBlockClient({
|
|
|
1369
2714
|
});
|
|
1370
2715
|
}
|
|
1371
2716
|
};
|
|
2717
|
+
const triggerSaveSuccess = useCallback4(() => {
|
|
2718
|
+
setIsSaveSuccess(true);
|
|
2719
|
+
setTimeout(() => {
|
|
2720
|
+
setIsSaveSuccess(false);
|
|
2721
|
+
}, 2500);
|
|
2722
|
+
}, []);
|
|
2723
|
+
const handleQuietCellChange = useCallback4((rowId, colName, value) => {
|
|
2724
|
+
setData((prev) => prev.map(
|
|
2725
|
+
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
2726
|
+
));
|
|
2727
|
+
if (rowId.startsWith("temp_")) {
|
|
2728
|
+
setDirty((prev) => {
|
|
2729
|
+
if (!prev.added.some((r) => r.id === rowId)) return prev;
|
|
2730
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
2731
|
+
added: prev.added.map(
|
|
2732
|
+
(r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
|
|
2733
|
+
)
|
|
2734
|
+
});
|
|
2735
|
+
});
|
|
2736
|
+
} else {
|
|
2737
|
+
setBaseRecordsMap((prev) => {
|
|
2738
|
+
const next = new Map(prev);
|
|
2739
|
+
const rowData = next.get(rowId);
|
|
2740
|
+
if (rowData) {
|
|
2741
|
+
next.set(rowId, __spreadProps(__spreadValues({}, rowData), { [colName]: value }));
|
|
2742
|
+
}
|
|
2743
|
+
return next;
|
|
2744
|
+
});
|
|
2745
|
+
}
|
|
2746
|
+
}, []);
|
|
1372
2747
|
const toggleSelectAll = (checked) => {
|
|
1373
2748
|
const nextSelected = checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set();
|
|
1374
2749
|
setSelectedIds(nextSelected);
|
|
@@ -1398,9 +2773,15 @@ function TableBlockClient({
|
|
|
1398
2773
|
const row = data.find((r) => r.id === id);
|
|
1399
2774
|
if (row) {
|
|
1400
2775
|
driveCols.forEach((col) => {
|
|
1401
|
-
const
|
|
1402
|
-
if (
|
|
1403
|
-
|
|
2776
|
+
const fileVal = row.data[col.name];
|
|
2777
|
+
if (Array.isArray(fileVal)) {
|
|
2778
|
+
fileVal.forEach((fileObj) => {
|
|
2779
|
+
if (fileObj && fileObj.fileId) {
|
|
2780
|
+
filesToDelete.push(fileObj.fileId);
|
|
2781
|
+
}
|
|
2782
|
+
});
|
|
2783
|
+
} else if (fileVal && fileVal.fileId) {
|
|
2784
|
+
filesToDelete.push(fileVal.fileId);
|
|
1404
2785
|
}
|
|
1405
2786
|
});
|
|
1406
2787
|
}
|
|
@@ -1427,7 +2808,7 @@ function TableBlockClient({
|
|
|
1427
2808
|
const formatPayload = (payload) => {
|
|
1428
2809
|
const formatted = {};
|
|
1429
2810
|
(localColumns || []).forEach((col) => {
|
|
1430
|
-
var _a;
|
|
2811
|
+
var _a, _b, _c;
|
|
1431
2812
|
if (["_id", "id", "createdAt", "updatedAt", "orgId", "tableId", "isSelected"].includes(col.name)) return;
|
|
1432
2813
|
let val = payload[col.name];
|
|
1433
2814
|
if (val !== void 0) {
|
|
@@ -1437,6 +2818,13 @@ function TableBlockClient({
|
|
|
1437
2818
|
if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
|
|
1438
2819
|
val = val === "" ? 0 : Number(val);
|
|
1439
2820
|
if (isNaN(val)) val = 0;
|
|
2821
|
+
} else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "PHONE") {
|
|
2822
|
+
val = sanitizePhoneNumber(String(val));
|
|
2823
|
+
} else if (((_c = col.type) == null ? void 0 : _c.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
|
|
2824
|
+
val = val.map((item) => {
|
|
2825
|
+
const _a2 = item, { _resolvedData } = _a2, rest = __objRest(_a2, ["_resolvedData"]);
|
|
2826
|
+
return rest;
|
|
2827
|
+
});
|
|
1440
2828
|
}
|
|
1441
2829
|
formatted[col.name] = val;
|
|
1442
2830
|
}
|
|
@@ -1446,7 +2834,7 @@ function TableBlockClient({
|
|
|
1446
2834
|
};
|
|
1447
2835
|
const hasChanges = dirty.added.length > 0 || Object.keys(dirty.modified).length > 0 || dirty.deleted.length > 0;
|
|
1448
2836
|
const handleSave = async () => {
|
|
1449
|
-
var _a;
|
|
2837
|
+
var _a, _b;
|
|
1450
2838
|
if (!hasChanges) {
|
|
1451
2839
|
return;
|
|
1452
2840
|
}
|
|
@@ -1469,6 +2857,28 @@ function TableBlockClient({
|
|
|
1469
2857
|
}
|
|
1470
2858
|
}
|
|
1471
2859
|
}
|
|
2860
|
+
const phoneCols = (localColumns || []).filter((c) => {
|
|
2861
|
+
var _a2;
|
|
2862
|
+
return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE";
|
|
2863
|
+
});
|
|
2864
|
+
for (const col of phoneCols) {
|
|
2865
|
+
for (const row of dirty.added) {
|
|
2866
|
+
const val = row.data[col.name];
|
|
2867
|
+
if (!isEmpty(val) && !isValidPhoneNumber(val)) {
|
|
2868
|
+
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");
|
|
2869
|
+
return;
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
for (const [rowId, mods] of Object.entries(dirty.modified)) {
|
|
2873
|
+
const rowData = ((_b = data.find((r) => r.id === rowId)) == null ? void 0 : _b.data) || {};
|
|
2874
|
+
const mergedData = __spreadValues(__spreadValues({}, rowData), mods);
|
|
2875
|
+
const val = mergedData[col.name];
|
|
2876
|
+
if (!isEmpty(val) && !isValidPhoneNumber(val)) {
|
|
2877
|
+
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");
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
1472
2882
|
setIsSaving(true);
|
|
1473
2883
|
try {
|
|
1474
2884
|
if (!executeAction) {
|
|
@@ -1598,7 +3008,7 @@ function TableBlockClient({
|
|
|
1598
3008
|
});
|
|
1599
3009
|
return totals;
|
|
1600
3010
|
}, [filteredData, filteredColumns, showSummary]);
|
|
1601
|
-
return /* @__PURE__ */
|
|
3011
|
+
return /* @__PURE__ */ jsxs6(
|
|
1602
3012
|
"div",
|
|
1603
3013
|
{
|
|
1604
3014
|
id: componentId,
|
|
@@ -1606,34 +3016,34 @@ function TableBlockClient({
|
|
|
1606
3016
|
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
|
|
1607
3017
|
dir: "rtl",
|
|
1608
3018
|
children: [
|
|
1609
|
-
errorMessage && /* @__PURE__ */
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
3019
|
+
errorMessage && /* @__PURE__ */ jsx6("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
3020
|
+
/* @__PURE__ */ jsx6("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
3021
|
+
/* @__PURE__ */ jsx6("span", { children: errorMessage })
|
|
1612
3022
|
] }) }),
|
|
1613
|
-
/* @__PURE__ */
|
|
1614
|
-
/* @__PURE__ */
|
|
1615
|
-
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */
|
|
1616
|
-
/* @__PURE__ */
|
|
3023
|
+
/* @__PURE__ */ jsxs6("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: [
|
|
3024
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
3025
|
+
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ jsx6("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ jsx6("span", { children: schema.title || schema.name }) }),
|
|
3026
|
+
/* @__PURE__ */ jsx6(
|
|
1617
3027
|
"button",
|
|
1618
3028
|
{
|
|
1619
3029
|
onClick: handleAddRow,
|
|
1620
3030
|
disabled: isLoading || isUpdatingActive,
|
|
1621
3031
|
className: "w-9 h-9 bg-emerald-600 hover:bg-emerald-700 active:bg-emerald-800 text-white rounded-lg shadow-xs flex items-center justify-center transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
|
|
1622
3032
|
title: "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
1623
|
-
children: /* @__PURE__ */
|
|
3033
|
+
children: /* @__PURE__ */ jsx6("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
|
|
1624
3034
|
}
|
|
1625
3035
|
),
|
|
1626
|
-
/* @__PURE__ */
|
|
3036
|
+
/* @__PURE__ */ jsx6(
|
|
1627
3037
|
"button",
|
|
1628
3038
|
{
|
|
1629
3039
|
onClick: handleDuplicateRow,
|
|
1630
3040
|
disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
1631
3041
|
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",
|
|
1632
3042
|
title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
|
|
1633
|
-
children: /* @__PURE__ */
|
|
3043
|
+
children: /* @__PURE__ */ jsx6(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
1634
3044
|
}
|
|
1635
3045
|
),
|
|
1636
|
-
/* @__PURE__ */
|
|
3046
|
+
/* @__PURE__ */ jsxs6(
|
|
1637
3047
|
"button",
|
|
1638
3048
|
{
|
|
1639
3049
|
onClick: handleDeleteSelected,
|
|
@@ -1641,12 +3051,12 @@ function TableBlockClient({
|
|
|
1641
3051
|
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",
|
|
1642
3052
|
title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
|
|
1643
3053
|
children: [
|
|
1644
|
-
/* @__PURE__ */
|
|
1645
|
-
selectedIds.size > 0 && /* @__PURE__ */
|
|
3054
|
+
/* @__PURE__ */ jsx6("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("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" }) }),
|
|
3055
|
+
selectedIds.size > 0 && /* @__PURE__ */ jsx6("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 })
|
|
1646
3056
|
]
|
|
1647
3057
|
}
|
|
1648
3058
|
),
|
|
1649
|
-
/* @__PURE__ */
|
|
3059
|
+
/* @__PURE__ */ jsxs6(
|
|
1650
3060
|
"button",
|
|
1651
3061
|
{
|
|
1652
3062
|
onClick: toggleSummary,
|
|
@@ -1654,13 +3064,13 @@ function TableBlockClient({
|
|
|
1654
3064
|
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"}`,
|
|
1655
3065
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
|
|
1656
3066
|
children: [
|
|
1657
|
-
/* @__PURE__ */
|
|
1658
|
-
/* @__PURE__ */
|
|
3067
|
+
/* @__PURE__ */ jsx6("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
|
|
3068
|
+
/* @__PURE__ */ jsx6("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
|
|
1659
3069
|
]
|
|
1660
3070
|
}
|
|
1661
3071
|
),
|
|
1662
|
-
/* @__PURE__ */
|
|
1663
|
-
/* @__PURE__ */
|
|
3072
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative", ref: dropdownRef, children: [
|
|
3073
|
+
/* @__PURE__ */ jsxs6(
|
|
1664
3074
|
"button",
|
|
1665
3075
|
{
|
|
1666
3076
|
onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
|
|
@@ -1668,16 +3078,16 @@ function TableBlockClient({
|
|
|
1668
3078
|
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",
|
|
1669
3079
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
|
|
1670
3080
|
children: [
|
|
1671
|
-
/* @__PURE__ */
|
|
1672
|
-
/* @__PURE__ */
|
|
3081
|
+
/* @__PURE__ */ jsx6("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("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" }) }),
|
|
3082
|
+
/* @__PURE__ */ jsx6("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__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
|
|
1673
3083
|
]
|
|
1674
3084
|
}
|
|
1675
3085
|
),
|
|
1676
|
-
isColumnsDropdownOpen && /* @__PURE__ */
|
|
1677
|
-
/* @__PURE__ */
|
|
1678
|
-
/* @__PURE__ */
|
|
1679
|
-
/* @__PURE__ */
|
|
1680
|
-
/* @__PURE__ */
|
|
3086
|
+
isColumnsDropdownOpen && /* @__PURE__ */ jsxs6("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: [
|
|
3087
|
+
/* @__PURE__ */ jsxs6("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: [
|
|
3088
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
|
|
3089
|
+
/* @__PURE__ */ jsx6("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
|
|
3090
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-[10px] font-normal text-slate-400", children: [
|
|
1681
3091
|
"(",
|
|
1682
3092
|
customizableColumns.filter((c) => !c.isHidden).length,
|
|
1683
3093
|
"/",
|
|
@@ -1685,7 +3095,7 @@ function TableBlockClient({
|
|
|
1685
3095
|
")"
|
|
1686
3096
|
] })
|
|
1687
3097
|
] }),
|
|
1688
|
-
/* @__PURE__ */
|
|
3098
|
+
/* @__PURE__ */ jsx6(
|
|
1689
3099
|
"button",
|
|
1690
3100
|
{
|
|
1691
3101
|
type: "button",
|
|
@@ -1695,7 +3105,7 @@ function TableBlockClient({
|
|
|
1695
3105
|
}
|
|
1696
3106
|
)
|
|
1697
3107
|
] }),
|
|
1698
|
-
/* @__PURE__ */
|
|
3108
|
+
/* @__PURE__ */ jsx6("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
|
|
1699
3109
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1700
3110
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
1701
3111
|
const isProtected = isRequired || isUnique;
|
|
@@ -1709,7 +3119,7 @@ function TableBlockClient({
|
|
|
1709
3119
|
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";
|
|
1710
3120
|
}
|
|
1711
3121
|
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";
|
|
1712
|
-
return /* @__PURE__ */
|
|
3122
|
+
return /* @__PURE__ */ jsxs6(
|
|
1713
3123
|
"div",
|
|
1714
3124
|
{
|
|
1715
3125
|
onClick: () => {
|
|
@@ -1720,8 +3130,8 @@ function TableBlockClient({
|
|
|
1720
3130
|
title: isProtected ? protectedExplanation : void 0,
|
|
1721
3131
|
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"}`,
|
|
1722
3132
|
children: [
|
|
1723
|
-
/* @__PURE__ */
|
|
1724
|
-
/* @__PURE__ */
|
|
3133
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
3134
|
+
/* @__PURE__ */ jsx6(
|
|
1725
3135
|
"input",
|
|
1726
3136
|
{
|
|
1727
3137
|
type: "checkbox",
|
|
@@ -1732,16 +3142,16 @@ function TableBlockClient({
|
|
|
1732
3142
|
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"
|
|
1733
3143
|
}
|
|
1734
3144
|
),
|
|
1735
|
-
/* @__PURE__ */
|
|
3145
|
+
/* @__PURE__ */ jsx6("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
|
|
1736
3146
|
] }),
|
|
1737
|
-
isProtected && /* @__PURE__ */
|
|
3147
|
+
isProtected && /* @__PURE__ */ jsxs6(
|
|
1738
3148
|
"div",
|
|
1739
3149
|
{
|
|
1740
3150
|
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",
|
|
1741
3151
|
title: protectedExplanation,
|
|
1742
3152
|
children: [
|
|
1743
|
-
/* @__PURE__ */
|
|
1744
|
-
/* @__PURE__ */
|
|
3153
|
+
/* @__PURE__ */ jsx6("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__ */ jsx6("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" }) }),
|
|
3154
|
+
/* @__PURE__ */ jsx6("span", { children: badgeLabel })
|
|
1745
3155
|
]
|
|
1746
3156
|
}
|
|
1747
3157
|
)
|
|
@@ -1752,9 +3162,9 @@ function TableBlockClient({
|
|
|
1752
3162
|
}) })
|
|
1753
3163
|
] })
|
|
1754
3164
|
] }),
|
|
1755
|
-
/* @__PURE__ */
|
|
1756
|
-
/* @__PURE__ */
|
|
1757
|
-
/* @__PURE__ */
|
|
3165
|
+
/* @__PURE__ */ jsx6("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
3166
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
3167
|
+
/* @__PURE__ */ jsx6(
|
|
1758
3168
|
"input",
|
|
1759
3169
|
{
|
|
1760
3170
|
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
@@ -1764,45 +3174,45 @@ function TableBlockClient({
|
|
|
1764
3174
|
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"
|
|
1765
3175
|
}
|
|
1766
3176
|
),
|
|
1767
|
-
searchQuery ? /* @__PURE__ */
|
|
3177
|
+
searchQuery ? /* @__PURE__ */ jsx6(
|
|
1768
3178
|
"button",
|
|
1769
3179
|
{
|
|
1770
3180
|
type: "button",
|
|
1771
3181
|
onClick: () => setSearchQuery(""),
|
|
1772
3182
|
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",
|
|
1773
3183
|
title: "Clear search",
|
|
1774
|
-
children: /* @__PURE__ */
|
|
3184
|
+
children: /* @__PURE__ */ jsx6(X4, { className: "w-3.5 h-3.5" })
|
|
1775
3185
|
}
|
|
1776
|
-
) : /* @__PURE__ */
|
|
3186
|
+
) : /* @__PURE__ */ jsx6("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__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
|
|
1777
3187
|
] })
|
|
1778
3188
|
] }),
|
|
1779
|
-
/* @__PURE__ */
|
|
1780
|
-
isUpdatingActive ? /* @__PURE__ */
|
|
1781
|
-
/* @__PURE__ */
|
|
3189
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
|
|
3190
|
+
isUpdatingActive ? /* @__PURE__ */ jsxs6("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: [
|
|
3191
|
+
/* @__PURE__ */ jsx6("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
1782
3192
|
"\u05DE\u05E2\u05D3\u05DB\u05DF..."
|
|
1783
|
-
] }) : isSaveSuccess ? /* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
3193
|
+
] }) : isSaveSuccess ? /* @__PURE__ */ jsxs6("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: [
|
|
3194
|
+
/* @__PURE__ */ jsx6("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
|
|
1785
3195
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
1786
|
-
] }) : hasChanges ? /* @__PURE__ */
|
|
1787
|
-
/* @__PURE__ */
|
|
3196
|
+
] }) : hasChanges ? /* @__PURE__ */ jsx6("span", { className: "text-xs font-semibold text-amber-700 animate-in fade-in", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }) : null,
|
|
3197
|
+
/* @__PURE__ */ jsx6(
|
|
1788
3198
|
"button",
|
|
1789
3199
|
{
|
|
1790
3200
|
onClick: handleSave,
|
|
1791
3201
|
disabled: isUpdatingActive || isLoading || !hasChanges,
|
|
1792
3202
|
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"}`,
|
|
1793
|
-
children: /* @__PURE__ */
|
|
3203
|
+
children: /* @__PURE__ */ jsx6("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
|
|
1794
3204
|
}
|
|
1795
3205
|
)
|
|
1796
3206
|
] })
|
|
1797
3207
|
] }),
|
|
1798
|
-
/* @__PURE__ */
|
|
1799
|
-
isLoading && /* @__PURE__ */
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
3208
|
+
/* @__PURE__ */ jsxs6("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
|
|
3209
|
+
isLoading && /* @__PURE__ */ jsxs6("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
|
|
3210
|
+
/* @__PURE__ */ jsx6("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
3211
|
+
/* @__PURE__ */ jsx6("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
1802
3212
|
] }),
|
|
1803
|
-
/* @__PURE__ */
|
|
1804
|
-
/* @__PURE__ */
|
|
1805
|
-
/* @__PURE__ */
|
|
3213
|
+
/* @__PURE__ */ jsxs6("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
|
|
3214
|
+
/* @__PURE__ */ jsx6("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ jsxs6("tr", { children: [
|
|
3215
|
+
/* @__PURE__ */ jsx6("th", { className: "border-b border-l border-slate-200 p-2.5 w-10 text-center shrink-0", style: { width: 50, minWidth: 50, maxWidth: 50 }, children: /* @__PURE__ */ jsx6(
|
|
1806
3216
|
"input",
|
|
1807
3217
|
{
|
|
1808
3218
|
type: "checkbox",
|
|
@@ -1816,7 +3226,7 @@ function TableBlockClient({
|
|
|
1816
3226
|
const isDragging = draggedColName === col.name;
|
|
1817
3227
|
const isDragOver = dragOverColName === col.name;
|
|
1818
3228
|
const currentWidth = columnWidths[col.name] || 200;
|
|
1819
|
-
return /* @__PURE__ */
|
|
3229
|
+
return /* @__PURE__ */ jsxs6(
|
|
1820
3230
|
"th",
|
|
1821
3231
|
{
|
|
1822
3232
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
@@ -1852,7 +3262,7 @@ function TableBlockClient({
|
|
|
1852
3262
|
},
|
|
1853
3263
|
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"}`,
|
|
1854
3264
|
children: [
|
|
1855
|
-
/* @__PURE__ */
|
|
3265
|
+
/* @__PURE__ */ jsx6(
|
|
1856
3266
|
"div",
|
|
1857
3267
|
{
|
|
1858
3268
|
onMouseDown: (e) => {
|
|
@@ -1864,16 +3274,16 @@ function TableBlockClient({
|
|
|
1864
3274
|
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
1865
3275
|
}
|
|
1866
3276
|
),
|
|
1867
|
-
/* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
1869
|
-
/* @__PURE__ */
|
|
3277
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2 group overflow-hidden", title: "\u05D2\u05E8\u05D5\u05E8 \u05DC\u05E9\u05D9\u05E0\u05D5\u05D9 \u05E1\u05D3\u05E8 \u05D4\u05E2\u05DE\u05D5\u05D3\u05D4", children: [
|
|
3278
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate", children: col.name }),
|
|
3279
|
+
/* @__PURE__ */ jsx6(
|
|
1870
3280
|
"svg",
|
|
1871
3281
|
{
|
|
1872
3282
|
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
1873
3283
|
fill: "none",
|
|
1874
3284
|
viewBox: "0 0 24 24",
|
|
1875
3285
|
stroke: "currentColor",
|
|
1876
|
-
children: /* @__PURE__ */
|
|
3286
|
+
children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
|
|
1877
3287
|
}
|
|
1878
3288
|
)
|
|
1879
3289
|
] })
|
|
@@ -1882,59 +3292,112 @@ function TableBlockClient({
|
|
|
1882
3292
|
col.name
|
|
1883
3293
|
);
|
|
1884
3294
|
}),
|
|
1885
|
-
/* @__PURE__ */
|
|
3295
|
+
/* @__PURE__ */ jsx6("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
|
|
1886
3296
|
] }) }),
|
|
1887
|
-
/* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
1889
|
-
/* @__PURE__ */
|
|
1890
|
-
] }) }) }) : filteredData.map((row) =>
|
|
1891
|
-
|
|
1892
|
-
"input",
|
|
1893
|
-
{
|
|
1894
|
-
type: "checkbox",
|
|
1895
|
-
checked: selectedIds.has(row.id),
|
|
1896
|
-
onChange: (e) => toggleSelectRow(row.id, e.target.checked),
|
|
1897
|
-
disabled: isLoading || isUpdatingActive,
|
|
1898
|
-
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
1899
|
-
}
|
|
1900
|
-
) }),
|
|
1901
|
-
filteredColumns.map((col) => {
|
|
3297
|
+
/* @__PURE__ */ jsx6("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ jsx6("tr", { children: /* @__PURE__ */ jsx6("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
3298
|
+
/* @__PURE__ */ jsx6("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("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" }) }),
|
|
3299
|
+
/* @__PURE__ */ jsx6("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
3300
|
+
] }) }) }) : filteredData.map((row) => {
|
|
3301
|
+
const hasSubTableCols = filteredColumns.some((c) => {
|
|
1902
3302
|
var _a;
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
3303
|
+
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
3304
|
+
});
|
|
3305
|
+
const isExpanded = expandedRowIds.has(row.id);
|
|
3306
|
+
const subTableColumns = filteredColumns.filter((c) => {
|
|
3307
|
+
var _a;
|
|
3308
|
+
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
3309
|
+
});
|
|
3310
|
+
return /* @__PURE__ */ jsxs6(React6.Fragment, { children: [
|
|
3311
|
+
/* @__PURE__ */ jsxs6("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
|
|
3312
|
+
/* @__PURE__ */ jsx6("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-center gap-1", children: [
|
|
3313
|
+
hasSubTableCols && /* @__PURE__ */ jsx6(
|
|
3314
|
+
"button",
|
|
3315
|
+
{
|
|
3316
|
+
type: "button",
|
|
3317
|
+
onClick: () => setExpandedRowIds((prev) => {
|
|
3318
|
+
const next = new Set(prev);
|
|
3319
|
+
if (next.has(row.id)) next.delete(row.id);
|
|
3320
|
+
else next.add(row.id);
|
|
3321
|
+
return next;
|
|
3322
|
+
}),
|
|
3323
|
+
className: "text-slate-400 hover:text-blue-600 p-0.5 rounded transition-colors cursor-pointer",
|
|
3324
|
+
title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
|
|
3325
|
+
children: /* @__PURE__ */ jsx6("svg", { className: `w-3.5 h-3.5 transition-transform duration-150 ${isExpanded ? "rotate-90" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 5l7 7-7 7" }) })
|
|
3326
|
+
}
|
|
3327
|
+
),
|
|
3328
|
+
/* @__PURE__ */ jsx6(
|
|
3329
|
+
"input",
|
|
3330
|
+
{
|
|
3331
|
+
type: "checkbox",
|
|
3332
|
+
checked: selectedIds.has(row.id),
|
|
3333
|
+
onChange: (e) => toggleSelectRow(row.id, e.target.checked),
|
|
3334
|
+
disabled: isLoading || isUpdatingActive,
|
|
3335
|
+
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
3336
|
+
}
|
|
3337
|
+
)
|
|
3338
|
+
] }) }),
|
|
3339
|
+
filteredColumns.map((col) => {
|
|
3340
|
+
var _a;
|
|
3341
|
+
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
3342
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
3343
|
+
let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
|
|
3344
|
+
if (value === void 0 && col.defaultValue !== void 0) {
|
|
3345
|
+
value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
|
|
3346
|
+
if (colType === "CURRENCY" || colType === "NUMBER") {
|
|
3347
|
+
if (isNaN(value)) value = null;
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
if (value === void 0) value = null;
|
|
3351
|
+
return /* @__PURE__ */ jsx6("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ jsx6(
|
|
3352
|
+
InputComponent,
|
|
3353
|
+
{
|
|
3354
|
+
value,
|
|
3355
|
+
column: col,
|
|
3356
|
+
rowId: row.id,
|
|
3357
|
+
onChange: (v) => handleCellChange(row.id, col.name, v),
|
|
3358
|
+
context: {
|
|
3359
|
+
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",
|
|
3360
|
+
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
3361
|
+
onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
|
|
3362
|
+
relationOptions,
|
|
3363
|
+
refetchRelation,
|
|
3364
|
+
executeAction,
|
|
3365
|
+
emitEvent,
|
|
3366
|
+
pageState,
|
|
3367
|
+
componentId,
|
|
3368
|
+
orgId,
|
|
3369
|
+
updateQuietly: handleQuietCellChange,
|
|
3370
|
+
triggerSaveSuccess,
|
|
3371
|
+
rowData: row.data
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3374
|
+
) }, col.name);
|
|
3375
|
+
}),
|
|
3376
|
+
/* @__PURE__ */ jsx6("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
3377
|
+
] }),
|
|
3378
|
+
isExpanded && /* @__PURE__ */ jsx6(
|
|
3379
|
+
ExpandedSubTables,
|
|
1915
3380
|
{
|
|
1916
|
-
value,
|
|
1917
|
-
column: col,
|
|
1918
3381
|
rowId: row.id,
|
|
1919
|
-
|
|
3382
|
+
rowData: row.data,
|
|
3383
|
+
subTableColumns,
|
|
3384
|
+
filteredColumnsLength: filteredColumns.length,
|
|
3385
|
+
handleCellChange,
|
|
1920
3386
|
context: {
|
|
1921
|
-
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",
|
|
1922
|
-
onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
|
|
1923
|
-
relationOptions,
|
|
1924
|
-
refetchRelation,
|
|
1925
3387
|
executeAction,
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
3388
|
+
orgId,
|
|
3389
|
+
parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
3390
|
+
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
3391
|
+
rowData: row.data,
|
|
3392
|
+
updateQuietly: handleQuietCellChange,
|
|
3393
|
+
triggerSaveSuccess
|
|
1930
3394
|
}
|
|
1931
3395
|
}
|
|
1932
|
-
)
|
|
1933
|
-
})
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
/* @__PURE__ */ jsx5("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' }),
|
|
3396
|
+
)
|
|
3397
|
+
] }, row.id);
|
|
3398
|
+
}) }),
|
|
3399
|
+
showSummary && filteredData.length > 0 && /* @__PURE__ */ jsx6("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__ */ jsxs6("tr", { children: [
|
|
3400
|
+
/* @__PURE__ */ jsx6("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' }),
|
|
1938
3401
|
filteredColumns.map((col) => {
|
|
1939
3402
|
var _a;
|
|
1940
3403
|
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
@@ -1948,16 +3411,16 @@ function TableBlockClient({
|
|
|
1948
3411
|
displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
|
|
1949
3412
|
}
|
|
1950
3413
|
}
|
|
1951
|
-
return /* @__PURE__ */
|
|
3414
|
+
return /* @__PURE__ */ jsx6("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__ */ jsx6("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ jsx6("span", { className: "truncate", children: displayVal }) }) }, col.name);
|
|
1952
3415
|
}),
|
|
1953
|
-
/* @__PURE__ */
|
|
3416
|
+
/* @__PURE__ */ jsx6("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
|
|
1954
3417
|
] }) })
|
|
1955
3418
|
] })
|
|
1956
3419
|
] }),
|
|
1957
|
-
/* @__PURE__ */
|
|
1958
|
-
/* @__PURE__ */
|
|
1959
|
-
/* @__PURE__ */
|
|
1960
|
-
/* @__PURE__ */
|
|
3420
|
+
/* @__PURE__ */ jsxs6("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: [
|
|
3421
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
3422
|
+
/* @__PURE__ */ jsx6("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
|
|
3423
|
+
/* @__PURE__ */ jsxs6(
|
|
1961
3424
|
"select",
|
|
1962
3425
|
{
|
|
1963
3426
|
value: limit,
|
|
@@ -1965,27 +3428,27 @@ function TableBlockClient({
|
|
|
1965
3428
|
disabled: isLoading || isUpdatingActive,
|
|
1966
3429
|
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",
|
|
1967
3430
|
children: [
|
|
1968
|
-
/* @__PURE__ */
|
|
1969
|
-
/* @__PURE__ */
|
|
1970
|
-
/* @__PURE__ */
|
|
3431
|
+
/* @__PURE__ */ jsx6("option", { value: 20, children: "20" }),
|
|
3432
|
+
/* @__PURE__ */ jsx6("option", { value: 50, children: "50" }),
|
|
3433
|
+
/* @__PURE__ */ jsx6("option", { value: 100, children: "100" })
|
|
1971
3434
|
]
|
|
1972
3435
|
}
|
|
1973
3436
|
)
|
|
1974
3437
|
] }),
|
|
1975
|
-
/* @__PURE__ */
|
|
1976
|
-
/* @__PURE__ */
|
|
3438
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-4", children: [
|
|
3439
|
+
/* @__PURE__ */ jsxs6("span", { className: "font-medium text-slate-600", children: [
|
|
1977
3440
|
"\u05E2\u05DE\u05D5\u05D3 ",
|
|
1978
|
-
/* @__PURE__ */
|
|
3441
|
+
/* @__PURE__ */ jsx6("strong", { className: "text-slate-900", children: page }),
|
|
1979
3442
|
" \u05DE\u05EA\u05D5\u05DA ",
|
|
1980
|
-
/* @__PURE__ */
|
|
1981
|
-
totalRecords > 0 && /* @__PURE__ */
|
|
3443
|
+
/* @__PURE__ */ jsx6("strong", { className: "text-slate-900", children: totalPages || 1 }),
|
|
3444
|
+
totalRecords > 0 && /* @__PURE__ */ jsxs6("span", { className: "text-slate-500 font-normal", children: [
|
|
1982
3445
|
" (",
|
|
1983
3446
|
totalRecords,
|
|
1984
3447
|
' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
|
|
1985
3448
|
] })
|
|
1986
3449
|
] }),
|
|
1987
|
-
/* @__PURE__ */
|
|
1988
|
-
/* @__PURE__ */
|
|
3450
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
|
|
3451
|
+
/* @__PURE__ */ jsx6(
|
|
1989
3452
|
"button",
|
|
1990
3453
|
{
|
|
1991
3454
|
onClick: handlePrevPage,
|
|
@@ -1995,7 +3458,7 @@ function TableBlockClient({
|
|
|
1995
3458
|
children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
|
|
1996
3459
|
}
|
|
1997
3460
|
),
|
|
1998
|
-
/* @__PURE__ */
|
|
3461
|
+
/* @__PURE__ */ jsx6(
|
|
1999
3462
|
"button",
|
|
2000
3463
|
{
|
|
2001
3464
|
onClick: handleNextPage,
|
|
@@ -2012,11 +3475,60 @@ function TableBlockClient({
|
|
|
2012
3475
|
}
|
|
2013
3476
|
);
|
|
2014
3477
|
}
|
|
3478
|
+
function ExpandedSubTables({
|
|
3479
|
+
rowId,
|
|
3480
|
+
rowData,
|
|
3481
|
+
subTableColumns,
|
|
3482
|
+
filteredColumnsLength,
|
|
3483
|
+
handleCellChange,
|
|
3484
|
+
context
|
|
3485
|
+
}) {
|
|
3486
|
+
var _a;
|
|
3487
|
+
const [activeTab, setActiveTab] = useState5((_a = subTableColumns[0]) == null ? void 0 : _a.name);
|
|
3488
|
+
if (subTableColumns.length === 0) return null;
|
|
3489
|
+
if (subTableColumns.length === 1) {
|
|
3490
|
+
const stCol = subTableColumns[0];
|
|
3491
|
+
return /* @__PURE__ */ jsx6("tr", { children: /* @__PURE__ */ jsx6("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50", children: /* @__PURE__ */ jsx6(
|
|
3492
|
+
SubTableViewer,
|
|
3493
|
+
{
|
|
3494
|
+
rowId,
|
|
3495
|
+
column: stCol,
|
|
3496
|
+
value: (rowData == null ? void 0 : rowData[stCol.name]) || [],
|
|
3497
|
+
onChange: (newVal) => handleCellChange(rowId, stCol.name, newVal),
|
|
3498
|
+
context
|
|
3499
|
+
}
|
|
3500
|
+
) }) });
|
|
3501
|
+
}
|
|
3502
|
+
const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
|
|
3503
|
+
return /* @__PURE__ */ jsx6("tr", { children: /* @__PURE__ */ jsxs6("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50 overflow-hidden", children: [
|
|
3504
|
+
/* @__PURE__ */ jsx6("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__ */ jsx6(
|
|
3505
|
+
"button",
|
|
3506
|
+
{
|
|
3507
|
+
type: "button",
|
|
3508
|
+
onClick: () => setActiveTab(col.name),
|
|
3509
|
+
className: `px-4 py-2 text-sm font-semibold rounded-t-lg transition-colors whitespace-nowrap cursor-pointer relative top-[1px] ${activeTab === col.name ? "bg-white border border-slate-200 border-b-transparent text-brand" : "bg-transparent border border-transparent text-slate-500 hover:text-slate-700 hover:bg-slate-200/50"}`,
|
|
3510
|
+
children: col.name
|
|
3511
|
+
},
|
|
3512
|
+
col.name
|
|
3513
|
+
)) }),
|
|
3514
|
+
/* @__PURE__ */ jsx6("div", { className: "bg-white", children: /* @__PURE__ */ jsx6(
|
|
3515
|
+
SubTableViewer,
|
|
3516
|
+
{
|
|
3517
|
+
rowId,
|
|
3518
|
+
column: activeCol,
|
|
3519
|
+
value: (rowData == null ? void 0 : rowData[activeCol.name]) || [],
|
|
3520
|
+
onChange: (newVal) => handleCellChange(rowId, activeCol.name, newVal),
|
|
3521
|
+
context
|
|
3522
|
+
},
|
|
3523
|
+
activeCol.name
|
|
3524
|
+
) })
|
|
3525
|
+
] }) });
|
|
3526
|
+
}
|
|
2015
3527
|
|
|
2016
3528
|
// src/components/TableBlock/TableBlock.tsx
|
|
2017
|
-
import { jsx as
|
|
3529
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2018
3530
|
function TableBlock(props) {
|
|
2019
|
-
return /* @__PURE__ */
|
|
3531
|
+
return /* @__PURE__ */ jsx7(TableBlockClient, __spreadValues({}, props));
|
|
2020
3532
|
}
|
|
2021
3533
|
|
|
2022
3534
|
// src/registry.ts
|
|
@@ -2029,5 +3541,7 @@ export {
|
|
|
2029
3541
|
ToastProvider,
|
|
2030
3542
|
UNIVERSE_COMPONENTS,
|
|
2031
3543
|
cn,
|
|
3544
|
+
formatPhoneDisplay,
|
|
3545
|
+
openWhatsAppChat,
|
|
2032
3546
|
useToast
|
|
2033
3547
|
};
|