@universe-platform/ui 0.1.0-beta.6 → 0.1.0-beta.7
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 +111 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1079 -228
- package/dist/index.mjs +1077 -226
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -39,7 +39,7 @@ function cn(...inputs) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
42
|
-
import { useState as
|
|
42
|
+
import React6, { useState as useState5, useMemo as useMemo2, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
43
43
|
|
|
44
44
|
// src/hooks/useToast.ts
|
|
45
45
|
import { useContext as useContext2 } from "react";
|
|
@@ -242,12 +242,36 @@ function useToast() {
|
|
|
242
242
|
import React4 from "react";
|
|
243
243
|
|
|
244
244
|
// src/components/TableBlock/fields/DrivePickerCell.tsx
|
|
245
|
-
import { useState as useState2 } from "react";
|
|
245
|
+
import React2, { useState as useState2, useEffect } from "react";
|
|
246
246
|
import { FileText, Upload, X as X2 } from "lucide-react";
|
|
247
247
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
248
|
-
function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, context }) {
|
|
248
|
+
function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForDeletion, context }) {
|
|
249
249
|
const [isOpening, setIsOpening] = useState2(false);
|
|
250
250
|
const { showError } = useToast();
|
|
251
|
+
const cellContextId = React2.useMemo(() => {
|
|
252
|
+
const colName = (column == null ? void 0 : column.name) || "col";
|
|
253
|
+
const rId = rowId || "row";
|
|
254
|
+
return `${rId}-${colName}`;
|
|
255
|
+
}, [rowId, column == null ? void 0 : column.name]);
|
|
256
|
+
const fileList = React2.useMemo(() => {
|
|
257
|
+
if (!value) return [];
|
|
258
|
+
if (Array.isArray(value)) return value;
|
|
259
|
+
if (typeof value === "object" && (value.fileId || value.fileUrl || value.url)) {
|
|
260
|
+
return [value];
|
|
261
|
+
}
|
|
262
|
+
return [];
|
|
263
|
+
}, [value]);
|
|
264
|
+
useEffect(() => {
|
|
265
|
+
const handleMessage = (event) => {
|
|
266
|
+
var _a, _b, _c;
|
|
267
|
+
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) {
|
|
268
|
+
const incoming = Array.isArray(event.data.payload) ? event.data.payload : [event.data.payload];
|
|
269
|
+
onChange([...fileList, ...incoming]);
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
window.addEventListener("message", handleMessage);
|
|
273
|
+
return () => window.removeEventListener("message", handleMessage);
|
|
274
|
+
}, [fileList, onChange, cellContextId]);
|
|
251
275
|
const openUploadPopup = async () => {
|
|
252
276
|
if (isOpening) return;
|
|
253
277
|
setIsOpening(true);
|
|
@@ -276,34 +300,35 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
|
|
|
276
300
|
} catch (e) {
|
|
277
301
|
}
|
|
278
302
|
}
|
|
279
|
-
const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName });
|
|
303
|
+
const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName, cellContextId });
|
|
280
304
|
const folderId = actionResult == null ? void 0 : actionResult.folderId;
|
|
281
|
-
|
|
305
|
+
let pickerUrl = (actionResult == null ? void 0 : actionResult.pickerUrl) || (folderId ? `/embed/picker?folderId=${encodeURIComponent(folderId)}` : `/embed/picker`);
|
|
306
|
+
if (!pickerUrl.includes("cellContextId=")) {
|
|
307
|
+
const separator = pickerUrl.includes("?") ? "&" : "?";
|
|
308
|
+
pickerUrl = `${pickerUrl}${separator}cellContextId=${encodeURIComponent(cellContextId)}`;
|
|
309
|
+
}
|
|
282
310
|
if (popup) {
|
|
283
311
|
popup.location.href = pickerUrl;
|
|
284
312
|
}
|
|
285
|
-
|
|
313
|
+
await new Promise((resolve) => {
|
|
286
314
|
let timer = null;
|
|
287
|
-
const
|
|
315
|
+
const handlePopupMessage = (event) => {
|
|
288
316
|
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",
|
|
317
|
+
if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.cellContextId) === cellContextId) {
|
|
318
|
+
window.removeEventListener("message", handlePopupMessage);
|
|
291
319
|
if (timer) clearInterval(timer);
|
|
292
|
-
resolve(
|
|
320
|
+
resolve();
|
|
293
321
|
}
|
|
294
322
|
};
|
|
295
323
|
timer = setInterval(() => {
|
|
296
324
|
if (!popup || popup.closed) {
|
|
297
325
|
if (timer) clearInterval(timer);
|
|
298
|
-
window.removeEventListener("message",
|
|
299
|
-
resolve(
|
|
326
|
+
window.removeEventListener("message", handlePopupMessage);
|
|
327
|
+
resolve();
|
|
300
328
|
}
|
|
301
329
|
}, 800);
|
|
302
|
-
window.addEventListener("message",
|
|
330
|
+
window.addEventListener("message", handlePopupMessage);
|
|
303
331
|
});
|
|
304
|
-
if (newFile) {
|
|
305
|
-
onChange(newFile);
|
|
306
|
-
}
|
|
307
332
|
}
|
|
308
333
|
} catch (error) {
|
|
309
334
|
console.error("[DrivePickerCell] Error uploading file:", error);
|
|
@@ -313,40 +338,15 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
|
|
|
313
338
|
setIsOpening(false);
|
|
314
339
|
}
|
|
315
340
|
};
|
|
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(
|
|
341
|
+
const handleRemoveFile = (indexToRemove) => {
|
|
342
|
+
const fileToRemove = fileList[indexToRemove];
|
|
343
|
+
if ((fileToRemove == null ? void 0 : fileToRemove.fileId) && onMarkForDeletion) {
|
|
344
|
+
onMarkForDeletion(fileToRemove.fileId);
|
|
345
|
+
}
|
|
346
|
+
const updated = fileList.filter((_, idx) => idx !== indexToRemove);
|
|
347
|
+
onChange(updated);
|
|
348
|
+
};
|
|
349
|
+
const renderUploadButton = () => /* @__PURE__ */ jsx2("div", { className: "flex items-center w-full h-8 px-2", children: /* @__PURE__ */ jsxs2(
|
|
350
350
|
"button",
|
|
351
351
|
{
|
|
352
352
|
type: "button",
|
|
@@ -359,10 +359,42 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
|
|
|
359
359
|
]
|
|
360
360
|
}
|
|
361
361
|
) });
|
|
362
|
+
if (fileList.length > 0) {
|
|
363
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col w-full py-1 gap-1", children: [
|
|
364
|
+
fileList.map((file, idx) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center w-full h-8 px-2 gap-1", children: [
|
|
365
|
+
/* @__PURE__ */ jsxs2(
|
|
366
|
+
"a",
|
|
367
|
+
{
|
|
368
|
+
href: file.fileUrl || file.url,
|
|
369
|
+
target: "_blank",
|
|
370
|
+
rel: "noopener noreferrer",
|
|
371
|
+
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",
|
|
372
|
+
title: file.fileName || "Open file",
|
|
373
|
+
children: [
|
|
374
|
+
/* @__PURE__ */ jsx2(FileText, { className: "w-3.5 h-3.5 shrink-0" }),
|
|
375
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate", children: file.fileName || "Unnamed file" })
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
),
|
|
379
|
+
/* @__PURE__ */ jsx2(
|
|
380
|
+
"button",
|
|
381
|
+
{
|
|
382
|
+
type: "button",
|
|
383
|
+
onClick: () => handleRemoveFile(idx),
|
|
384
|
+
className: "shrink-0 p-0.5 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
|
|
385
|
+
title: "Remove file",
|
|
386
|
+
children: /* @__PURE__ */ jsx2(X2, { className: "w-3.5 h-3.5" })
|
|
387
|
+
}
|
|
388
|
+
)
|
|
389
|
+
] }, file.fileId || idx)),
|
|
390
|
+
renderUploadButton()
|
|
391
|
+
] });
|
|
392
|
+
}
|
|
393
|
+
return renderUploadButton();
|
|
362
394
|
}
|
|
363
395
|
|
|
364
396
|
// src/components/TableBlock/fields/DatePickerCell.tsx
|
|
365
|
-
import { useState as useState3, useRef as useRef2, useEffect, useMemo, useCallback as useCallback2 } from "react";
|
|
397
|
+
import { useState as useState3, useRef as useRef2, useEffect as useEffect2, useMemo, useCallback as useCallback2 } from "react";
|
|
366
398
|
import { Calendar as CalendarIcon, ChevronLeft, ChevronRight, X as X3 } from "lucide-react";
|
|
367
399
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
368
400
|
function parseDateParts(val) {
|
|
@@ -447,13 +479,13 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
|
|
|
447
479
|
const parsedParts = useMemo(() => parseDateParts(value), [value]);
|
|
448
480
|
const displayString = useMemo(() => formatDateDisplay(parsedParts), [parsedParts]);
|
|
449
481
|
const [rawInput, setRawInput] = useState3(displayString);
|
|
450
|
-
|
|
482
|
+
useEffect2(() => {
|
|
451
483
|
setRawInput(displayString);
|
|
452
484
|
}, [displayString]);
|
|
453
485
|
const now = /* @__PURE__ */ new Date();
|
|
454
486
|
const [viewYear, setViewYear] = useState3((parsedParts == null ? void 0 : parsedParts.year) || now.getFullYear());
|
|
455
487
|
const [viewMonth, setViewMonth] = useState3((parsedParts == null ? void 0 : parsedParts.month) || now.getMonth() + 1);
|
|
456
|
-
|
|
488
|
+
useEffect2(() => {
|
|
457
489
|
if (parsedParts) {
|
|
458
490
|
setViewYear(parsedParts.year);
|
|
459
491
|
setViewMonth(parsedParts.month);
|
|
@@ -478,7 +510,7 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
|
|
|
478
510
|
}
|
|
479
511
|
}
|
|
480
512
|
}, []);
|
|
481
|
-
|
|
513
|
+
useEffect2(() => {
|
|
482
514
|
if (!isOpen) return;
|
|
483
515
|
updatePopoverPosition();
|
|
484
516
|
function handleScrollOrResize() {
|
|
@@ -793,11 +825,13 @@ var FORM_INPUTS = {
|
|
|
793
825
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
794
826
|
}
|
|
795
827
|
) }),
|
|
796
|
-
GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */ jsx4(
|
|
828
|
+
GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ jsx4(
|
|
797
829
|
DrivePickerCell,
|
|
798
830
|
{
|
|
799
|
-
value: value ||
|
|
831
|
+
value: value || [],
|
|
800
832
|
onChange,
|
|
833
|
+
column,
|
|
834
|
+
rowId,
|
|
801
835
|
tableName: context == null ? void 0 : context.tableName,
|
|
802
836
|
onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
|
|
803
837
|
context
|
|
@@ -855,6 +889,228 @@ var FORM_INPUTS = {
|
|
|
855
889
|
}
|
|
856
890
|
}
|
|
857
891
|
),
|
|
892
|
+
PHONE: ({ value, onChange }) => /* @__PURE__ */ jsx4(
|
|
893
|
+
"input",
|
|
894
|
+
{
|
|
895
|
+
type: "tel",
|
|
896
|
+
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
897
|
+
value: value !== void 0 && value !== null ? String(value) : "",
|
|
898
|
+
onChange: (e) => onChange(e.target.value),
|
|
899
|
+
dir: "ltr"
|
|
900
|
+
}
|
|
901
|
+
),
|
|
902
|
+
GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
|
|
903
|
+
const [isSyncing, setIsSyncing] = React4.useState(false);
|
|
904
|
+
const { addToast } = useToast();
|
|
905
|
+
const googleClientIdRef = React4.useRef(null);
|
|
906
|
+
const ensureGisScript = React4.useCallback(() => {
|
|
907
|
+
return new Promise((resolve, reject) => {
|
|
908
|
+
var _a, _b, _c;
|
|
909
|
+
if ((_c = (_b = (_a = window.google) == null ? void 0 : _a.accounts) == null ? void 0 : _b.oauth2) == null ? void 0 : _c.initTokenClient) {
|
|
910
|
+
resolve();
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
if (document.querySelector('script[src*="accounts.google.com/gsi/client"]')) {
|
|
914
|
+
const waitForLoad = setInterval(() => {
|
|
915
|
+
var _a2, _b2, _c2;
|
|
916
|
+
if ((_c2 = (_b2 = (_a2 = window.google) == null ? void 0 : _a2.accounts) == null ? void 0 : _b2.oauth2) == null ? void 0 : _c2.initTokenClient) {
|
|
917
|
+
clearInterval(waitForLoad);
|
|
918
|
+
resolve();
|
|
919
|
+
}
|
|
920
|
+
}, 100);
|
|
921
|
+
setTimeout(() => {
|
|
922
|
+
clearInterval(waitForLoad);
|
|
923
|
+
reject(new Error("GIS script load timeout"));
|
|
924
|
+
}, 1e4);
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
const script = document.createElement("script");
|
|
928
|
+
script.src = "https://accounts.google.com/gsi/client";
|
|
929
|
+
script.async = true;
|
|
930
|
+
script.onload = () => resolve();
|
|
931
|
+
script.onerror = () => reject(new Error("Failed to load Google Identity Services"));
|
|
932
|
+
document.head.appendChild(script);
|
|
933
|
+
});
|
|
934
|
+
}, []);
|
|
935
|
+
const requestGisToken = React4.useCallback(async (hint) => {
|
|
936
|
+
await ensureGisScript();
|
|
937
|
+
if (!googleClientIdRef.current && (context == null ? void 0 : context.executeAction)) {
|
|
938
|
+
try {
|
|
939
|
+
const config = await context.executeAction("GET_GOOGLE_CONFIG", {});
|
|
940
|
+
googleClientIdRef.current = (config == null ? void 0 : config.clientId) || "";
|
|
941
|
+
} catch (e) {
|
|
942
|
+
throw new Error("Failed to fetch Google configuration");
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
const clientId = googleClientIdRef.current;
|
|
946
|
+
if (!clientId) {
|
|
947
|
+
throw new Error("Google Client ID is not configured");
|
|
948
|
+
}
|
|
949
|
+
const accessToken = await new Promise((resolve, reject) => {
|
|
950
|
+
const tokenClient = window.google.accounts.oauth2.initTokenClient({
|
|
951
|
+
client_id: clientId,
|
|
952
|
+
scope: "https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/userinfo.email",
|
|
953
|
+
prompt: hint ? "" : "select_account",
|
|
954
|
+
hint: hint || void 0,
|
|
955
|
+
callback: (tokenResponse) => {
|
|
956
|
+
if (tokenResponse == null ? void 0 : tokenResponse.access_token) {
|
|
957
|
+
resolve(tokenResponse.access_token);
|
|
958
|
+
} else {
|
|
959
|
+
reject(new Error("Google authorization was cancelled or failed"));
|
|
960
|
+
}
|
|
961
|
+
},
|
|
962
|
+
error_callback: (err) => {
|
|
963
|
+
reject(new Error((err == null ? void 0 : err.message) || "Google authorization error"));
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
tokenClient.requestAccessToken({ hint: hint || void 0 });
|
|
967
|
+
});
|
|
968
|
+
let email = "";
|
|
969
|
+
try {
|
|
970
|
+
const res = await fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
|
|
971
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
972
|
+
});
|
|
973
|
+
if (res.ok) {
|
|
974
|
+
const info = await res.json();
|
|
975
|
+
email = info.email || "";
|
|
976
|
+
}
|
|
977
|
+
} catch (e) {
|
|
978
|
+
}
|
|
979
|
+
return { accessToken, email };
|
|
980
|
+
}, [ensureGisScript, context]);
|
|
981
|
+
const handleSync = async () => {
|
|
982
|
+
var _a, _b, _c;
|
|
983
|
+
if (!(context == null ? void 0 : context.executeAction)) return;
|
|
984
|
+
setIsSyncing(true);
|
|
985
|
+
try {
|
|
986
|
+
const mapping = column.contactMapping || {};
|
|
987
|
+
const rowData = context.rowData || {};
|
|
988
|
+
let hasPhone = false;
|
|
989
|
+
if (mapping.phoneCol && rowData[mapping.phoneCol]) hasPhone = true;
|
|
990
|
+
let hasName = false;
|
|
991
|
+
if (mapping.nameParts && Array.isArray(mapping.nameParts)) {
|
|
992
|
+
for (const part of mapping.nameParts) {
|
|
993
|
+
if (part.type === "LOCAL" && rowData[part.columnId]) hasName = true;
|
|
994
|
+
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;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
if (!hasPhone) {
|
|
998
|
+
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" });
|
|
999
|
+
setIsSyncing(false);
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
if (!hasName) {
|
|
1003
|
+
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" });
|
|
1004
|
+
setIsSyncing(false);
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
let accessToken;
|
|
1008
|
+
let userEmail = "";
|
|
1009
|
+
try {
|
|
1010
|
+
const gisResult = await requestGisToken();
|
|
1011
|
+
accessToken = gisResult.accessToken;
|
|
1012
|
+
userEmail = gisResult.email;
|
|
1013
|
+
} catch (gisError) {
|
|
1014
|
+
addToast({ type: "warning", message: gisError.message || "\u05D4\u05D4\u05E8\u05E9\u05D0\u05D4 \u05DC\u05D2\u05D5\u05D2\u05DC \u05E0\u05DB\u05E9\u05DC\u05D4" });
|
|
1015
|
+
setIsSyncing(false);
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
const payload = {
|
|
1019
|
+
nameParts: mapping.nameParts || [],
|
|
1020
|
+
phoneCol: mapping.phoneCol,
|
|
1021
|
+
emailCol: mapping.emailCol,
|
|
1022
|
+
localRowData: rowData,
|
|
1023
|
+
parentRecord: context.parentRecord,
|
|
1024
|
+
accessToken,
|
|
1025
|
+
userEmail
|
|
1026
|
+
};
|
|
1027
|
+
const res = await context.executeAction("SYNC_GOOGLE_CONTACT", payload);
|
|
1028
|
+
if (res && res.synced) {
|
|
1029
|
+
if (context.updateQuietly) {
|
|
1030
|
+
context.updateQuietly(rowId, column.name, res);
|
|
1031
|
+
} else {
|
|
1032
|
+
onChange(res);
|
|
1033
|
+
}
|
|
1034
|
+
if (context.tableId && !rowId.startsWith("temp_")) {
|
|
1035
|
+
await context.executeAction("UPDATE_RECORD", {
|
|
1036
|
+
tableId: context.tableId,
|
|
1037
|
+
recordId: rowId,
|
|
1038
|
+
data: { [column.name]: res }
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
console.error("Failed to sync contact:", error);
|
|
1044
|
+
addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
|
|
1045
|
+
} finally {
|
|
1046
|
+
setIsSyncing(false);
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
const handleUnlink = async () => {
|
|
1050
|
+
let accessToken;
|
|
1051
|
+
try {
|
|
1052
|
+
let emailHint = value == null ? void 0 : value.userEmail;
|
|
1053
|
+
if (!emailHint && (value == null ? void 0 : value.url)) {
|
|
1054
|
+
try {
|
|
1055
|
+
const parsed = new URL(value.url);
|
|
1056
|
+
emailHint = parsed.searchParams.get("authuser") || void 0;
|
|
1057
|
+
} catch (e) {
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
const auth = await requestGisToken(emailHint);
|
|
1061
|
+
accessToken = auth.accessToken;
|
|
1062
|
+
} catch (err) {
|
|
1063
|
+
console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
|
|
1064
|
+
}
|
|
1065
|
+
if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
|
|
1066
|
+
await context.executeAction("DELETE_GOOGLE_CONTACT", {
|
|
1067
|
+
resourceName: value.resourceName,
|
|
1068
|
+
accessToken
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1072
|
+
context.updateQuietly(rowId, column.name, null);
|
|
1073
|
+
} else {
|
|
1074
|
+
onChange(null);
|
|
1075
|
+
}
|
|
1076
|
+
if ((context == null ? void 0 : context.tableId) && (context == null ? void 0 : context.executeAction) && !rowId.startsWith("temp_")) {
|
|
1077
|
+
await context.executeAction("UPDATE_RECORD", {
|
|
1078
|
+
tableId: context.tableId,
|
|
1079
|
+
recordId: rowId,
|
|
1080
|
+
data: { [column.name]: null }
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1084
|
+
if (value && value.synced && value.url) {
|
|
1085
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 h-8 px-2 group", children: [
|
|
1086
|
+
/* @__PURE__ */ jsx4("a", { href: value.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate text-sm", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" }),
|
|
1087
|
+
/* @__PURE__ */ jsx4(
|
|
1088
|
+
"button",
|
|
1089
|
+
{
|
|
1090
|
+
onClick: handleUnlink,
|
|
1091
|
+
className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1",
|
|
1092
|
+
title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
|
|
1093
|
+
children: /* @__PURE__ */ jsx4("svg", { className: "w-4 h-4", 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" }) })
|
|
1094
|
+
}
|
|
1095
|
+
)
|
|
1096
|
+
] });
|
|
1097
|
+
}
|
|
1098
|
+
return /* @__PURE__ */ jsx4("div", { className: "flex items-center h-8 px-2", children: /* @__PURE__ */ jsxs4(
|
|
1099
|
+
"button",
|
|
1100
|
+
{
|
|
1101
|
+
onClick: handleSync,
|
|
1102
|
+
disabled: isSyncing,
|
|
1103
|
+
className: "flex items-center gap-1.5 px-3 py-1 bg-blue-50 text-blue-600 hover:bg-blue-100 border border-blue-200 rounded-md text-xs font-medium transition-colors disabled:opacity-50",
|
|
1104
|
+
children: [
|
|
1105
|
+
isSyncing ? /* @__PURE__ */ jsxs4("svg", { className: "w-3.5 h-3.5 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [
|
|
1106
|
+
/* @__PURE__ */ jsx4("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
1107
|
+
/* @__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" })
|
|
1108
|
+
] }) : /* @__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: "M12 4v16m8-8H4" }) }),
|
|
1109
|
+
"\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC"
|
|
1110
|
+
]
|
|
1111
|
+
}
|
|
1112
|
+
) });
|
|
1113
|
+
},
|
|
858
1114
|
DEFAULT: ({ value, onChange }) => /* @__PURE__ */ jsx4(
|
|
859
1115
|
"input",
|
|
860
1116
|
{
|
|
@@ -863,12 +1119,459 @@ var FORM_INPUTS = {
|
|
|
863
1119
|
value: value !== void 0 && value !== null ? String(value) : "",
|
|
864
1120
|
onChange: (e) => onChange(e.target.value)
|
|
865
1121
|
}
|
|
866
|
-
)
|
|
1122
|
+
),
|
|
1123
|
+
SUB_TABLE: ({ value, column }) => {
|
|
1124
|
+
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" });
|
|
1125
|
+
const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
|
|
1126
|
+
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" });
|
|
1127
|
+
const displayFields = column.subTableDisplayFields || [];
|
|
1128
|
+
return /* @__PURE__ */ jsx4("div", { className: "px-1.5 py-1 flex flex-wrap items-center gap-1 h-full", children: selected.map((entry, idx) => {
|
|
1129
|
+
var _a;
|
|
1130
|
+
let label = "";
|
|
1131
|
+
if (entry._resolvedData && displayFields.length > 0) {
|
|
1132
|
+
label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
|
|
1133
|
+
}
|
|
1134
|
+
if (!label) label = ((_a = entry.recordId) == null ? void 0 : _a.slice(-6)) || "...";
|
|
1135
|
+
return /* @__PURE__ */ jsx4(
|
|
1136
|
+
"span",
|
|
1137
|
+
{
|
|
1138
|
+
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",
|
|
1139
|
+
title: label,
|
|
1140
|
+
children: label
|
|
1141
|
+
},
|
|
1142
|
+
entry.recordId || idx
|
|
1143
|
+
);
|
|
1144
|
+
}) });
|
|
1145
|
+
}
|
|
867
1146
|
};
|
|
868
1147
|
|
|
1148
|
+
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
1149
|
+
import { useState as useState4, useEffect as useEffect3, useRef as useRef3, useCallback as useCallback3 } from "react";
|
|
1150
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1151
|
+
function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
1152
|
+
var _a;
|
|
1153
|
+
const { addToast } = useToast();
|
|
1154
|
+
const entries = Array.isArray(value) ? value : [];
|
|
1155
|
+
const [linkedRecords, setLinkedRecords] = useState4([]);
|
|
1156
|
+
const [targetSchema, setTargetSchema] = useState4(null);
|
|
1157
|
+
const [isLoading, setIsLoading] = useState4(true);
|
|
1158
|
+
const [isSearchOpen, setIsSearchOpen] = useState4(false);
|
|
1159
|
+
const [searchQuery, setSearchQuery] = useState4("");
|
|
1160
|
+
const [searchResults, setSearchResults] = useState4([]);
|
|
1161
|
+
const [isSearching, setIsSearching] = useState4(false);
|
|
1162
|
+
const [isCreating, setIsCreating] = useState4(false);
|
|
1163
|
+
const [newRecordData, setNewRecordData] = useState4({});
|
|
1164
|
+
const searchRef = useRef3(null);
|
|
1165
|
+
const searchTimerRef = useRef3(null);
|
|
1166
|
+
const executeAction = context == null ? void 0 : context.executeAction;
|
|
1167
|
+
const referencedTableId = column.referencedTableId;
|
|
1168
|
+
const fetchedIdsRef = useRef3(/* @__PURE__ */ new Set());
|
|
1169
|
+
useEffect3(() => {
|
|
1170
|
+
if (!referencedTableId || !executeAction) {
|
|
1171
|
+
setIsLoading(false);
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
const recordIdsToFetch = entries.map((e) => e.recordId).filter((id) => !fetchedIdsRef.current.has(id));
|
|
1175
|
+
if (recordIdsToFetch.length === 0 && targetSchema) return;
|
|
1176
|
+
if (recordIdsToFetch.length > 0) {
|
|
1177
|
+
recordIdsToFetch.forEach((id) => fetchedIdsRef.current.add(id));
|
|
1178
|
+
}
|
|
1179
|
+
setIsLoading(true);
|
|
1180
|
+
executeAction("FETCH_SUB_TABLE_RECORDS", { referencedTableId, recordIds: recordIdsToFetch }).then((res) => {
|
|
1181
|
+
const payload = (res == null ? void 0 : res.data) || res;
|
|
1182
|
+
if (payload == null ? void 0 : payload.records) {
|
|
1183
|
+
setLinkedRecords((prev) => {
|
|
1184
|
+
const map = new Map(prev.map((r) => [r.id, r]));
|
|
1185
|
+
payload.records.forEach((r) => map.set(r.id, r));
|
|
1186
|
+
return Array.from(map.values());
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
if (payload == null ? void 0 : payload.schema) {
|
|
1190
|
+
setTargetSchema(payload.schema);
|
|
1191
|
+
}
|
|
1192
|
+
}).catch(() => {
|
|
1193
|
+
recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
|
|
1194
|
+
}).finally(() => setIsLoading(false));
|
|
1195
|
+
}, [referencedTableId, executeAction, entries, targetSchema]);
|
|
1196
|
+
useEffect3(() => {
|
|
1197
|
+
const handleClick = (e) => {
|
|
1198
|
+
if (searchRef.current && !searchRef.current.contains(e.target)) {
|
|
1199
|
+
setIsSearchOpen(false);
|
|
1200
|
+
}
|
|
1201
|
+
};
|
|
1202
|
+
if (isSearchOpen) document.addEventListener("mousedown", handleClick);
|
|
1203
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
1204
|
+
}, [isSearchOpen]);
|
|
1205
|
+
const handleSearch = useCallback3((query) => {
|
|
1206
|
+
setSearchQuery(query);
|
|
1207
|
+
if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
|
|
1208
|
+
if (!query.trim()) {
|
|
1209
|
+
setSearchResults([]);
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
searchTimerRef.current = setTimeout(async () => {
|
|
1213
|
+
if (!executeAction || !referencedTableId) return;
|
|
1214
|
+
setIsSearching(true);
|
|
1215
|
+
try {
|
|
1216
|
+
const excludeIds = entries.map((e) => e.recordId);
|
|
1217
|
+
const res = await executeAction("SEARCH_SUB_TABLE_RECORDS", {
|
|
1218
|
+
referencedTableId,
|
|
1219
|
+
query: query.trim(),
|
|
1220
|
+
excludeIds,
|
|
1221
|
+
limit: 15
|
|
1222
|
+
});
|
|
1223
|
+
setSearchResults(Array.isArray(res) ? res : []);
|
|
1224
|
+
} catch (e) {
|
|
1225
|
+
setSearchResults([]);
|
|
1226
|
+
} finally {
|
|
1227
|
+
setIsSearching(false);
|
|
1228
|
+
}
|
|
1229
|
+
}, 300);
|
|
1230
|
+
}, [executeAction, referencedTableId, entries]);
|
|
1231
|
+
const targetColumns = ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
|
|
1232
|
+
(c) => {
|
|
1233
|
+
if (c.name === "_id" || c.type === "SUB_TABLE") return false;
|
|
1234
|
+
return true;
|
|
1235
|
+
}
|
|
1236
|
+
);
|
|
1237
|
+
const [relationOptions, setRelationOptions] = useState4({});
|
|
1238
|
+
useEffect3(() => {
|
|
1239
|
+
if (!executeAction || targetColumns.length === 0) return;
|
|
1240
|
+
const relationCols = targetColumns.filter((c) => {
|
|
1241
|
+
var _a2;
|
|
1242
|
+
return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION" && c.referencedTableId;
|
|
1243
|
+
});
|
|
1244
|
+
relationCols.forEach(async (col) => {
|
|
1245
|
+
try {
|
|
1246
|
+
const options = await executeAction("FETCH_RELATION", {
|
|
1247
|
+
referencedTableId: col.referencedTableId,
|
|
1248
|
+
displayField: col.displayField
|
|
1249
|
+
});
|
|
1250
|
+
if (options && Array.isArray(options)) {
|
|
1251
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
1252
|
+
}
|
|
1253
|
+
} catch (err) {
|
|
1254
|
+
console.warn(`[SubTableViewer] Could not fetch relation options for column ${col.name}:`, err);
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
1257
|
+
}, [executeAction, targetColumns]);
|
|
1258
|
+
const refetchRelation = useCallback3(async (colName) => {
|
|
1259
|
+
var _a2;
|
|
1260
|
+
const col = targetColumns.find((c) => c.name === colName);
|
|
1261
|
+
if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !col.referencedTableId || !executeAction) return;
|
|
1262
|
+
try {
|
|
1263
|
+
const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
|
|
1264
|
+
if (options && Array.isArray(options)) {
|
|
1265
|
+
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
|
|
1266
|
+
}
|
|
1267
|
+
} catch (err) {
|
|
1268
|
+
console.warn(`[SubTableViewer] Could not refetch relation options for column ${col.name}:`, err);
|
|
1269
|
+
}
|
|
1270
|
+
}, [targetColumns, executeAction]);
|
|
1271
|
+
const updateParentLinkage = async (updated) => {
|
|
1272
|
+
const isNewRow = rowId.startsWith("temp_");
|
|
1273
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1274
|
+
context.updateQuietly(rowId, column.name, updated);
|
|
1275
|
+
} else {
|
|
1276
|
+
onChange(updated);
|
|
1277
|
+
}
|
|
1278
|
+
if (executeAction && (context == null ? void 0 : context.parentTableId) && !isNewRow) {
|
|
1279
|
+
try {
|
|
1280
|
+
const payloadToSave = updated.map(({ recordId, isSelected }) => ({ recordId, isSelected }));
|
|
1281
|
+
await executeAction("UPDATE_RECORD", {
|
|
1282
|
+
tableId: context.parentTableId,
|
|
1283
|
+
recordId: rowId,
|
|
1284
|
+
data: { [column.name]: payloadToSave }
|
|
1285
|
+
});
|
|
1286
|
+
if (context == null ? void 0 : context.triggerSaveSuccess) {
|
|
1287
|
+
context.triggerSaveSuccess();
|
|
1288
|
+
}
|
|
1289
|
+
} catch (err) {
|
|
1290
|
+
console.error("Failed to auto-save parent linkage", err);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
const handleLinkRecord = (record) => {
|
|
1295
|
+
fetchedIdsRef.current.add(record.id);
|
|
1296
|
+
const newEntry = { recordId: record.id, isSelected: true, _resolvedData: record.data };
|
|
1297
|
+
const updated = [...entries, newEntry];
|
|
1298
|
+
updateParentLinkage(updated);
|
|
1299
|
+
setLinkedRecords((prev) => {
|
|
1300
|
+
const exists = prev.find((r) => r.id === record.id);
|
|
1301
|
+
if (exists) return prev;
|
|
1302
|
+
return [...prev, record];
|
|
1303
|
+
});
|
|
1304
|
+
setSearchQuery("");
|
|
1305
|
+
setSearchResults([]);
|
|
1306
|
+
setIsSearchOpen(false);
|
|
1307
|
+
};
|
|
1308
|
+
const handleUnlinkRecord = (recordId) => {
|
|
1309
|
+
const updated = entries.filter((e) => e.recordId !== recordId);
|
|
1310
|
+
updateParentLinkage(updated);
|
|
1311
|
+
setLinkedRecords((prev) => prev.filter((r) => r.id !== recordId));
|
|
1312
|
+
};
|
|
1313
|
+
const handleToggleSelected = (recordId) => {
|
|
1314
|
+
const record = linkedRecords.find((r) => r.id === recordId);
|
|
1315
|
+
const updated = entries.map(
|
|
1316
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { isSelected: !e.isSelected, _resolvedData: (record == null ? void 0 : record.data) || e._resolvedData }) : e
|
|
1317
|
+
);
|
|
1318
|
+
updateParentLinkage(updated);
|
|
1319
|
+
};
|
|
1320
|
+
const handleRecordCellChange = async (recordId, colName, value2) => {
|
|
1321
|
+
const updatedRecords = linkedRecords.map(
|
|
1322
|
+
(r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
|
|
1323
|
+
);
|
|
1324
|
+
setLinkedRecords(updatedRecords);
|
|
1325
|
+
const targetRecord = updatedRecords.find((r) => r.id === recordId);
|
|
1326
|
+
const updatedEntries = entries.map(
|
|
1327
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
|
|
1328
|
+
);
|
|
1329
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1330
|
+
context.updateQuietly(rowId, column.name, updatedEntries);
|
|
1331
|
+
} else {
|
|
1332
|
+
onChange(updatedEntries);
|
|
1333
|
+
}
|
|
1334
|
+
if (executeAction && referencedTableId && !recordId.startsWith("temp_")) {
|
|
1335
|
+
try {
|
|
1336
|
+
await executeAction("UPDATE_RECORD", {
|
|
1337
|
+
tableId: referencedTableId,
|
|
1338
|
+
recordId,
|
|
1339
|
+
data: { [colName]: value2 }
|
|
1340
|
+
});
|
|
1341
|
+
if (context == null ? void 0 : context.triggerSaveSuccess) {
|
|
1342
|
+
context.triggerSaveSuccess();
|
|
1343
|
+
}
|
|
1344
|
+
} catch (err) {
|
|
1345
|
+
console.error("[SubTableViewer] Failed to auto-save linked record field", err);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
};
|
|
1349
|
+
const handleCreateRecord = async () => {
|
|
1350
|
+
var _a2;
|
|
1351
|
+
if (!executeAction || !referencedTableId) return;
|
|
1352
|
+
for (const col of targetColumns) {
|
|
1353
|
+
if (col.isRequired) {
|
|
1354
|
+
const val = newRecordData[col.name];
|
|
1355
|
+
if (val === void 0 || val === null || typeof val === "string" && val.trim() === "") {
|
|
1356
|
+
addToast({
|
|
1357
|
+
type: "error",
|
|
1358
|
+
message: `Validation Error: Field '${col.name}' is required but was not provided.`
|
|
1359
|
+
});
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
try {
|
|
1365
|
+
const res = await executeAction("CREATE_RECORD", {
|
|
1366
|
+
tableId: referencedTableId,
|
|
1367
|
+
records: [newRecordData]
|
|
1368
|
+
});
|
|
1369
|
+
if (res && res.success === false) {
|
|
1370
|
+
throw new Error(res.error || "Action execution failed");
|
|
1371
|
+
}
|
|
1372
|
+
const created = Array.isArray(res) ? res[0] : ((_a2 = res == null ? void 0 : res.data) == null ? void 0 : _a2[0]) || res;
|
|
1373
|
+
if (created) {
|
|
1374
|
+
const newRecord = {
|
|
1375
|
+
id: String(created.id || created._id),
|
|
1376
|
+
data: created.data || newRecordData
|
|
1377
|
+
};
|
|
1378
|
+
handleLinkRecord(newRecord);
|
|
1379
|
+
setIsCreating(false);
|
|
1380
|
+
setNewRecordData({});
|
|
1381
|
+
}
|
|
1382
|
+
} catch (err) {
|
|
1383
|
+
const msg = (err == null ? void 0 : err.message) || String(err);
|
|
1384
|
+
addToast({
|
|
1385
|
+
type: "error",
|
|
1386
|
+
message: msg
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
const getDisplayLabel = (record) => {
|
|
1391
|
+
const fields = column.subTableDisplayFields || [];
|
|
1392
|
+
if (fields.length === 0) {
|
|
1393
|
+
const firstField = Object.keys(record.data).find((k) => k !== "_id");
|
|
1394
|
+
return firstField ? String(record.data[firstField] || "") : record.id;
|
|
1395
|
+
}
|
|
1396
|
+
return fields.map((f) => String(record.data[f] || "")).filter(Boolean).join(" ");
|
|
1397
|
+
};
|
|
1398
|
+
return /* @__PURE__ */ jsxs5("div", { className: "p-3 animate-in fade-in slide-in-from-top-2 duration-200", dir: "rtl", children: [
|
|
1399
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-4 mb-2.5", children: [
|
|
1400
|
+
/* @__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 }) }),
|
|
1401
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
|
|
1402
|
+
/* @__PURE__ */ jsxs5("div", { className: "relative", ref: searchRef, children: [
|
|
1403
|
+
/* @__PURE__ */ jsxs5(
|
|
1404
|
+
"button",
|
|
1405
|
+
{
|
|
1406
|
+
type: "button",
|
|
1407
|
+
onClick: () => setIsSearchOpen((prev) => !prev),
|
|
1408
|
+
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",
|
|
1409
|
+
children: [
|
|
1410
|
+
/* @__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" }) }),
|
|
1411
|
+
"\u05E7\u05D9\u05E9\u05D5\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
|
|
1412
|
+
]
|
|
1413
|
+
}
|
|
1414
|
+
),
|
|
1415
|
+
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: [
|
|
1416
|
+
/* @__PURE__ */ jsx5(
|
|
1417
|
+
"input",
|
|
1418
|
+
{
|
|
1419
|
+
type: "text",
|
|
1420
|
+
value: searchQuery,
|
|
1421
|
+
onChange: (e) => handleSearch(e.target.value),
|
|
1422
|
+
placeholder: "\u05D7\u05E4\u05E9 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
1423
|
+
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",
|
|
1424
|
+
autoFocus: true
|
|
1425
|
+
}
|
|
1426
|
+
),
|
|
1427
|
+
/* @__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(
|
|
1428
|
+
"button",
|
|
1429
|
+
{
|
|
1430
|
+
type: "button",
|
|
1431
|
+
onClick: () => handleLinkRecord(r),
|
|
1432
|
+
className: "w-full text-right px-2 py-1.5 text-xs hover:bg-blue-50 rounded cursor-pointer transition-colors",
|
|
1433
|
+
children: getDisplayLabel(r)
|
|
1434
|
+
},
|
|
1435
|
+
r.id
|
|
1436
|
+
)) : 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..." }) })
|
|
1437
|
+
] })
|
|
1438
|
+
] }),
|
|
1439
|
+
/* @__PURE__ */ jsxs5(
|
|
1440
|
+
"button",
|
|
1441
|
+
{
|
|
1442
|
+
type: "button",
|
|
1443
|
+
onClick: () => {
|
|
1444
|
+
setIsCreating(true);
|
|
1445
|
+
const initialData = {};
|
|
1446
|
+
targetColumns.forEach((c) => {
|
|
1447
|
+
if (c.defaultValue !== void 0 && c.defaultValue !== null) {
|
|
1448
|
+
initialData[c.name] = c.type === "NUMBER" || c.type === "CURRENCY" ? parseFloat(c.defaultValue) : c.type === "BOOLEAN" ? c.defaultValue === "true" || c.defaultValue === true : c.defaultValue;
|
|
1449
|
+
} else {
|
|
1450
|
+
if (c.type === "NUMBER" || c.type === "CURRENCY") initialData[c.name] = 0;
|
|
1451
|
+
else if (c.type === "BOOLEAN") initialData[c.name] = false;
|
|
1452
|
+
else initialData[c.name] = "";
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1455
|
+
setNewRecordData(initialData);
|
|
1456
|
+
},
|
|
1457
|
+
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",
|
|
1458
|
+
children: [
|
|
1459
|
+
/* @__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" }) }),
|
|
1460
|
+
"\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4"
|
|
1461
|
+
]
|
|
1462
|
+
}
|
|
1463
|
+
)
|
|
1464
|
+
] })
|
|
1465
|
+
] }),
|
|
1466
|
+
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: [
|
|
1467
|
+
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsxs5("tr", { className: "bg-slate-100/80", children: [
|
|
1468
|
+
/* @__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" }),
|
|
1469
|
+
targetColumns.map((col) => /* @__PURE__ */ jsx5("th", { className: "border border-slate-200 px-2 py-1.5 text-right font-semibold text-slate-600 whitespace-nowrap", children: col.name }, col.name)),
|
|
1470
|
+
/* @__PURE__ */ jsx5("th", { className: "border border-slate-200 px-2 py-1.5 w-14" })
|
|
1471
|
+
] }) }),
|
|
1472
|
+
/* @__PURE__ */ jsxs5("tbody", { children: [
|
|
1473
|
+
entries.map((entry) => {
|
|
1474
|
+
const record = linkedRecords.find((r) => r.id === entry.recordId);
|
|
1475
|
+
return /* @__PURE__ */ jsxs5("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
|
|
1476
|
+
/* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-2 py-1 text-center", children: /* @__PURE__ */ jsx5(
|
|
1477
|
+
"input",
|
|
1478
|
+
{
|
|
1479
|
+
type: "checkbox",
|
|
1480
|
+
checked: entry.isSelected,
|
|
1481
|
+
onChange: () => handleToggleSelected(entry.recordId),
|
|
1482
|
+
className: "w-3.5 h-3.5 rounded border-slate-300 text-blue-600 cursor-pointer"
|
|
1483
|
+
}
|
|
1484
|
+
) }),
|
|
1485
|
+
targetColumns.map((col) => {
|
|
1486
|
+
var _a2, _b;
|
|
1487
|
+
const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
|
|
1488
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
1489
|
+
return /* @__PURE__ */ jsx5("td", { className: "border border-slate-200 p-0 relative h-8", children: record ? /* @__PURE__ */ jsx5(
|
|
1490
|
+
InputComponent,
|
|
1491
|
+
{
|
|
1492
|
+
value: (_b = record.data[col.name]) != null ? _b : colType === "BOOLEAN" ? false : "",
|
|
1493
|
+
column: col,
|
|
1494
|
+
rowId: record.id,
|
|
1495
|
+
onChange: (v) => handleRecordCellChange(record.id, col.name, v),
|
|
1496
|
+
context: __spreadProps(__spreadValues({}, context), {
|
|
1497
|
+
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",
|
|
1498
|
+
relationOptions,
|
|
1499
|
+
updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
|
|
1500
|
+
refetchRelation,
|
|
1501
|
+
parentRecord: { tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId), data: context == null ? void 0 : context.rowData },
|
|
1502
|
+
rowData: record.data,
|
|
1503
|
+
tableId: targetSchema == null ? void 0 : targetSchema.id,
|
|
1504
|
+
updateQuietly: (rid, colName, val) => handleRecordCellChange(rid, colName, val)
|
|
1505
|
+
})
|
|
1506
|
+
}
|
|
1507
|
+
) : /* @__PURE__ */ jsx5("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." }) }, col.name);
|
|
1508
|
+
}),
|
|
1509
|
+
/* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-1 py-1 text-center", children: /* @__PURE__ */ jsx5(
|
|
1510
|
+
"button",
|
|
1511
|
+
{
|
|
1512
|
+
type: "button",
|
|
1513
|
+
onClick: () => handleUnlinkRecord(entry.recordId),
|
|
1514
|
+
className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center w-full",
|
|
1515
|
+
title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
|
|
1516
|
+
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" }) })
|
|
1517
|
+
}
|
|
1518
|
+
) })
|
|
1519
|
+
] }, entry.recordId);
|
|
1520
|
+
}),
|
|
1521
|
+
isCreating && /* @__PURE__ */ jsxs5("tr", { className: "bg-emerald-50/40", children: [
|
|
1522
|
+
/* @__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" }) }),
|
|
1523
|
+
targetColumns.map((col) => {
|
|
1524
|
+
var _a2, _b;
|
|
1525
|
+
const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
|
|
1526
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
1527
|
+
return /* @__PURE__ */ jsx5("td", { className: "border border-emerald-200 p-0 relative h-8", children: /* @__PURE__ */ jsx5(
|
|
1528
|
+
InputComponent,
|
|
1529
|
+
{
|
|
1530
|
+
value: (_b = newRecordData[col.name]) != null ? _b : colType === "BOOLEAN" ? false : "",
|
|
1531
|
+
column: col,
|
|
1532
|
+
rowId: "new_record",
|
|
1533
|
+
onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
|
|
1534
|
+
context: __spreadProps(__spreadValues({}, context), {
|
|
1535
|
+
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",
|
|
1536
|
+
relationOptions,
|
|
1537
|
+
refetchRelation
|
|
1538
|
+
})
|
|
1539
|
+
}
|
|
1540
|
+
) }, `new_${col.name}`);
|
|
1541
|
+
}),
|
|
1542
|
+
/* @__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: [
|
|
1543
|
+
/* @__PURE__ */ jsx5(
|
|
1544
|
+
"button",
|
|
1545
|
+
{
|
|
1546
|
+
type: "button",
|
|
1547
|
+
onClick: handleCreateRecord,
|
|
1548
|
+
className: "p-1 text-emerald-600 hover:bg-emerald-100 rounded transition-colors",
|
|
1549
|
+
title: "\u05E9\u05DE\u05D5\u05E8",
|
|
1550
|
+
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" }) })
|
|
1551
|
+
}
|
|
1552
|
+
),
|
|
1553
|
+
/* @__PURE__ */ jsx5(
|
|
1554
|
+
"button",
|
|
1555
|
+
{
|
|
1556
|
+
type: "button",
|
|
1557
|
+
onClick: () => {
|
|
1558
|
+
setIsCreating(false);
|
|
1559
|
+
},
|
|
1560
|
+
className: "p-1 text-rose-500 hover:bg-rose-100 rounded transition-colors",
|
|
1561
|
+
title: "\u05D1\u05D9\u05D8\u05D5\u05DC",
|
|
1562
|
+
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" }) })
|
|
1563
|
+
}
|
|
1564
|
+
)
|
|
1565
|
+
] }) })
|
|
1566
|
+
] })
|
|
1567
|
+
] })
|
|
1568
|
+
] }) })
|
|
1569
|
+
] });
|
|
1570
|
+
}
|
|
1571
|
+
|
|
869
1572
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
870
1573
|
import { X as X4, Copy as Copy2 } from "lucide-react";
|
|
871
|
-
import { jsx as
|
|
1574
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
872
1575
|
function TableBlockClient({
|
|
873
1576
|
data: initialRecords,
|
|
874
1577
|
settings: schema,
|
|
@@ -885,14 +1588,14 @@ function TableBlockClient({
|
|
|
885
1588
|
"data-testid": dataTestId
|
|
886
1589
|
}) {
|
|
887
1590
|
const { showError, addToast } = useToast();
|
|
888
|
-
const [columnWidths, setColumnWidths] =
|
|
889
|
-
const [isMounted, setIsMounted] =
|
|
1591
|
+
const [columnWidths, setColumnWidths] = useState5({});
|
|
1592
|
+
const [isMounted, setIsMounted] = useState5(false);
|
|
890
1593
|
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
|
-
|
|
1594
|
+
const [page, setPage] = useState5(1);
|
|
1595
|
+
const [limit, setLimit] = useState5(50);
|
|
1596
|
+
const [totalRecords, setTotalRecords] = useState5(0);
|
|
1597
|
+
const [totalPages, setTotalPages] = useState5(1);
|
|
1598
|
+
useEffect4(() => {
|
|
896
1599
|
if (typeof window !== "undefined") {
|
|
897
1600
|
const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
|
|
898
1601
|
if (savedWidths) {
|
|
@@ -915,7 +1618,7 @@ function TableBlockClient({
|
|
|
915
1618
|
}
|
|
916
1619
|
setIsMounted(true);
|
|
917
1620
|
}, [tableKey]);
|
|
918
|
-
const [showSummary, setShowSummary] =
|
|
1621
|
+
const [showSummary, setShowSummary] = useState5(false);
|
|
919
1622
|
const toggleSummary = () => {
|
|
920
1623
|
setShowSummary((prev) => {
|
|
921
1624
|
const next = !prev;
|
|
@@ -924,8 +1627,8 @@ function TableBlockClient({
|
|
|
924
1627
|
return next;
|
|
925
1628
|
});
|
|
926
1629
|
};
|
|
927
|
-
const [resizingCol, setResizingCol] =
|
|
928
|
-
|
|
1630
|
+
const [resizingCol, setResizingCol] = useState5(null);
|
|
1631
|
+
useEffect4(() => {
|
|
929
1632
|
if (!resizingCol) return;
|
|
930
1633
|
const handleMouseMove = (e) => {
|
|
931
1634
|
const diffX = resizingCol.startX - e.clientX;
|
|
@@ -972,7 +1675,7 @@ function TableBlockClient({
|
|
|
972
1675
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
973
1676
|
});
|
|
974
1677
|
};
|
|
975
|
-
const mergeColumnDefs =
|
|
1678
|
+
const mergeColumnDefs = useCallback4((existingCols, incomingCols) => {
|
|
976
1679
|
if (!incomingCols || incomingCols.length === 0) return existingCols || [];
|
|
977
1680
|
if (!existingCols || existingCols.length === 0) return incomingCols;
|
|
978
1681
|
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
@@ -992,18 +1695,18 @@ function TableBlockClient({
|
|
|
992
1695
|
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
993
1696
|
});
|
|
994
1697
|
}, []);
|
|
995
|
-
const [localColumns, setLocalColumns] =
|
|
996
|
-
|
|
1698
|
+
const [localColumns, setLocalColumns] = useState5(() => (schema == null ? void 0 : schema.columns) || []);
|
|
1699
|
+
useEffect4(() => {
|
|
997
1700
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
998
1701
|
setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
|
|
999
1702
|
}
|
|
1000
1703
|
}, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
|
|
1001
|
-
const [dirty, setDirty] =
|
|
1002
|
-
const dirtyRef =
|
|
1003
|
-
|
|
1704
|
+
const [dirty, setDirty] = useState5({ added: [], modified: {}, deleted: [] });
|
|
1705
|
+
const dirtyRef = useRef4(dirty);
|
|
1706
|
+
useEffect4(() => {
|
|
1004
1707
|
dirtyRef.current = dirty;
|
|
1005
1708
|
}, [dirty]);
|
|
1006
|
-
const mergeWithDirty =
|
|
1709
|
+
const mergeWithDirty = useCallback4((baseRecords) => {
|
|
1007
1710
|
const { added, modified, deleted } = dirtyRef.current;
|
|
1008
1711
|
const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
|
|
1009
1712
|
const modifiedRecords = nonDeleted.map((r) => {
|
|
@@ -1016,8 +1719,8 @@ function TableBlockClient({
|
|
|
1016
1719
|
const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
|
|
1017
1720
|
return [...uniqueAdded, ...modifiedRecords];
|
|
1018
1721
|
}, []);
|
|
1019
|
-
const [data, setData] =
|
|
1020
|
-
|
|
1722
|
+
const [data, setData] = useState5(() => normalizeRecords(initialRecords));
|
|
1723
|
+
useEffect4(() => {
|
|
1021
1724
|
if (initialRecords) {
|
|
1022
1725
|
setData(mergeWithDirty(normalizeRecords(initialRecords)));
|
|
1023
1726
|
}
|
|
@@ -1032,19 +1735,19 @@ function TableBlockClient({
|
|
|
1032
1735
|
}
|
|
1033
1736
|
return false;
|
|
1034
1737
|
};
|
|
1035
|
-
const [baseRecordsMap, setBaseRecordsMap] =
|
|
1738
|
+
const [baseRecordsMap, setBaseRecordsMap] = useState5(() => {
|
|
1036
1739
|
const map = /* @__PURE__ */ new Map();
|
|
1037
1740
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1038
1741
|
return map;
|
|
1039
1742
|
});
|
|
1040
|
-
|
|
1743
|
+
useEffect4(() => {
|
|
1041
1744
|
if (initialRecords && initialRecords.length > 0) {
|
|
1042
1745
|
const map = /* @__PURE__ */ new Map();
|
|
1043
1746
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1044
1747
|
setBaseRecordsMap(map);
|
|
1045
1748
|
}
|
|
1046
1749
|
}, [initialRecords]);
|
|
1047
|
-
const refetchTableData =
|
|
1750
|
+
const refetchTableData = useCallback4((targetPage) => {
|
|
1048
1751
|
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1049
1752
|
if (!tableId || !executeAction) return Promise.resolve();
|
|
1050
1753
|
const activePage = targetPage !== void 0 ? targetPage : page;
|
|
@@ -1078,8 +1781,8 @@ function TableBlockClient({
|
|
|
1078
1781
|
}).catch((err) => {
|
|
1079
1782
|
console.error("[TableBlock] Failed to auto-fetch table data:", err);
|
|
1080
1783
|
});
|
|
1081
|
-
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction,
|
|
1082
|
-
|
|
1784
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs]);
|
|
1785
|
+
useEffect4(() => {
|
|
1083
1786
|
refetchTableData();
|
|
1084
1787
|
}, [refetchTableData]);
|
|
1085
1788
|
const handleLimitChange = (newLimit) => {
|
|
@@ -1095,19 +1798,20 @@ function TableBlockClient({
|
|
|
1095
1798
|
const handleNextPage = () => {
|
|
1096
1799
|
setPage((prev) => Math.min(totalPages, prev + 1));
|
|
1097
1800
|
};
|
|
1098
|
-
|
|
1801
|
+
useEffect4(() => {
|
|
1099
1802
|
if (error) {
|
|
1100
1803
|
showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
|
|
1101
1804
|
}
|
|
1102
1805
|
}, [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] =
|
|
1806
|
+
const [searchQuery, setSearchQuery] = useState5("");
|
|
1807
|
+
const [selectedIds, setSelectedIds] = useState5(/* @__PURE__ */ new Set());
|
|
1808
|
+
const [pendingDeletions, setPendingDeletions] = useState5([]);
|
|
1809
|
+
const [isSaving, setIsSaving] = useState5(false);
|
|
1810
|
+
const [isSaveSuccess, setIsSaveSuccess] = useState5(false);
|
|
1811
|
+
const [relationOptions, setRelationOptions] = useState5({});
|
|
1812
|
+
const [expandedRowIds, setExpandedRowIds] = useState5(/* @__PURE__ */ new Set());
|
|
1109
1813
|
const schemaColsString = useMemo2(() => JSON.stringify(localColumns || []), [localColumns]);
|
|
1110
|
-
const refetchRelation =
|
|
1814
|
+
const refetchRelation = useCallback4(async (colName) => {
|
|
1111
1815
|
var _a;
|
|
1112
1816
|
let parsedCols = [];
|
|
1113
1817
|
try {
|
|
@@ -1127,7 +1831,7 @@ function TableBlockClient({
|
|
|
1127
1831
|
console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
|
|
1128
1832
|
}
|
|
1129
1833
|
}, [schemaColsString, executeAction]);
|
|
1130
|
-
|
|
1834
|
+
useEffect4(() => {
|
|
1131
1835
|
let parsedCols = [];
|
|
1132
1836
|
try {
|
|
1133
1837
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -1163,9 +1867,9 @@ function TableBlockClient({
|
|
|
1163
1867
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1164
1868
|
return normalizedColumns.filter((col) => !systemFields.includes(col.name));
|
|
1165
1869
|
}, [normalizedColumns]);
|
|
1166
|
-
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] =
|
|
1167
|
-
const dropdownRef =
|
|
1168
|
-
|
|
1870
|
+
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState5(false);
|
|
1871
|
+
const dropdownRef = useRef4(null);
|
|
1872
|
+
useEffect4(() => {
|
|
1169
1873
|
const handleClickOutside = (e) => {
|
|
1170
1874
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1171
1875
|
setIsColumnsDropdownOpen(false);
|
|
@@ -1243,8 +1947,8 @@ function TableBlockClient({
|
|
|
1243
1947
|
}
|
|
1244
1948
|
}
|
|
1245
1949
|
};
|
|
1246
|
-
const [draggedColName, setDraggedColName] =
|
|
1247
|
-
const [dragOverColName, setDragOverColName] =
|
|
1950
|
+
const [draggedColName, setDraggedColName] = useState5(null);
|
|
1951
|
+
const [dragOverColName, setDragOverColName] = useState5(null);
|
|
1248
1952
|
const handleColumnReorder = async (draggedName, dropTargetName) => {
|
|
1249
1953
|
var _a;
|
|
1250
1954
|
if (draggedName === dropTargetName) return;
|
|
@@ -1286,6 +1990,10 @@ function TableBlockClient({
|
|
|
1286
1990
|
var _a;
|
|
1287
1991
|
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
1288
1992
|
let initialValue = col.defaultValue;
|
|
1993
|
+
if (typeUpper === "SUB_TABLE") {
|
|
1994
|
+
defaultData[col.name] = [];
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1289
1997
|
if (initialValue !== void 0 && initialValue !== null && initialValue !== "") {
|
|
1290
1998
|
if (typeUpper === "CURRENCY" || typeUpper === "NUMBER") {
|
|
1291
1999
|
initialValue = parseFloat(initialValue);
|
|
@@ -1369,6 +2077,36 @@ function TableBlockClient({
|
|
|
1369
2077
|
});
|
|
1370
2078
|
}
|
|
1371
2079
|
};
|
|
2080
|
+
const triggerSaveSuccess = useCallback4(() => {
|
|
2081
|
+
setIsSaveSuccess(true);
|
|
2082
|
+
setTimeout(() => {
|
|
2083
|
+
setIsSaveSuccess(false);
|
|
2084
|
+
}, 2500);
|
|
2085
|
+
}, []);
|
|
2086
|
+
const handleQuietCellChange = useCallback4((rowId, colName, value) => {
|
|
2087
|
+
setData((prev) => prev.map(
|
|
2088
|
+
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
2089
|
+
));
|
|
2090
|
+
if (rowId.startsWith("temp_")) {
|
|
2091
|
+
setDirty((prev) => {
|
|
2092
|
+
if (!prev.added.some((r) => r.id === rowId)) return prev;
|
|
2093
|
+
return __spreadProps(__spreadValues({}, prev), {
|
|
2094
|
+
added: prev.added.map(
|
|
2095
|
+
(r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
|
|
2096
|
+
)
|
|
2097
|
+
});
|
|
2098
|
+
});
|
|
2099
|
+
} else {
|
|
2100
|
+
setBaseRecordsMap((prev) => {
|
|
2101
|
+
const next = new Map(prev);
|
|
2102
|
+
const rowData = next.get(rowId);
|
|
2103
|
+
if (rowData) {
|
|
2104
|
+
next.set(rowId, __spreadProps(__spreadValues({}, rowData), { [colName]: value }));
|
|
2105
|
+
}
|
|
2106
|
+
return next;
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
}, []);
|
|
1372
2110
|
const toggleSelectAll = (checked) => {
|
|
1373
2111
|
const nextSelected = checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set();
|
|
1374
2112
|
setSelectedIds(nextSelected);
|
|
@@ -1398,9 +2136,15 @@ function TableBlockClient({
|
|
|
1398
2136
|
const row = data.find((r) => r.id === id);
|
|
1399
2137
|
if (row) {
|
|
1400
2138
|
driveCols.forEach((col) => {
|
|
1401
|
-
const
|
|
1402
|
-
if (
|
|
1403
|
-
|
|
2139
|
+
const fileVal = row.data[col.name];
|
|
2140
|
+
if (Array.isArray(fileVal)) {
|
|
2141
|
+
fileVal.forEach((fileObj) => {
|
|
2142
|
+
if (fileObj && fileObj.fileId) {
|
|
2143
|
+
filesToDelete.push(fileObj.fileId);
|
|
2144
|
+
}
|
|
2145
|
+
});
|
|
2146
|
+
} else if (fileVal && fileVal.fileId) {
|
|
2147
|
+
filesToDelete.push(fileVal.fileId);
|
|
1404
2148
|
}
|
|
1405
2149
|
});
|
|
1406
2150
|
}
|
|
@@ -1427,7 +2171,7 @@ function TableBlockClient({
|
|
|
1427
2171
|
const formatPayload = (payload) => {
|
|
1428
2172
|
const formatted = {};
|
|
1429
2173
|
(localColumns || []).forEach((col) => {
|
|
1430
|
-
var _a;
|
|
2174
|
+
var _a, _b;
|
|
1431
2175
|
if (["_id", "id", "createdAt", "updatedAt", "orgId", "tableId", "isSelected"].includes(col.name)) return;
|
|
1432
2176
|
let val = payload[col.name];
|
|
1433
2177
|
if (val !== void 0) {
|
|
@@ -1437,6 +2181,11 @@ function TableBlockClient({
|
|
|
1437
2181
|
if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
|
|
1438
2182
|
val = val === "" ? 0 : Number(val);
|
|
1439
2183
|
if (isNaN(val)) val = 0;
|
|
2184
|
+
} else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
|
|
2185
|
+
val = val.map((item) => {
|
|
2186
|
+
const _a2 = item, { _resolvedData } = _a2, rest = __objRest(_a2, ["_resolvedData"]);
|
|
2187
|
+
return rest;
|
|
2188
|
+
});
|
|
1440
2189
|
}
|
|
1441
2190
|
formatted[col.name] = val;
|
|
1442
2191
|
}
|
|
@@ -1598,7 +2347,7 @@ function TableBlockClient({
|
|
|
1598
2347
|
});
|
|
1599
2348
|
return totals;
|
|
1600
2349
|
}, [filteredData, filteredColumns, showSummary]);
|
|
1601
|
-
return /* @__PURE__ */
|
|
2350
|
+
return /* @__PURE__ */ jsxs6(
|
|
1602
2351
|
"div",
|
|
1603
2352
|
{
|
|
1604
2353
|
id: componentId,
|
|
@@ -1606,34 +2355,34 @@ function TableBlockClient({
|
|
|
1606
2355
|
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
|
|
1607
2356
|
dir: "rtl",
|
|
1608
2357
|
children: [
|
|
1609
|
-
errorMessage && /* @__PURE__ */
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
2358
|
+
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: [
|
|
2359
|
+
/* @__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" }) }),
|
|
2360
|
+
/* @__PURE__ */ jsx6("span", { children: errorMessage })
|
|
1612
2361
|
] }) }),
|
|
1613
|
-
/* @__PURE__ */
|
|
1614
|
-
/* @__PURE__ */
|
|
1615
|
-
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */
|
|
1616
|
-
/* @__PURE__ */
|
|
2362
|
+
/* @__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: [
|
|
2363
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
2364
|
+
((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 }) }),
|
|
2365
|
+
/* @__PURE__ */ jsx6(
|
|
1617
2366
|
"button",
|
|
1618
2367
|
{
|
|
1619
2368
|
onClick: handleAddRow,
|
|
1620
2369
|
disabled: isLoading || isUpdatingActive,
|
|
1621
2370
|
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
2371
|
title: "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
1623
|
-
children: /* @__PURE__ */
|
|
2372
|
+
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
2373
|
}
|
|
1625
2374
|
),
|
|
1626
|
-
/* @__PURE__ */
|
|
2375
|
+
/* @__PURE__ */ jsx6(
|
|
1627
2376
|
"button",
|
|
1628
2377
|
{
|
|
1629
2378
|
onClick: handleDuplicateRow,
|
|
1630
2379
|
disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
1631
2380
|
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
2381
|
title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
|
|
1633
|
-
children: /* @__PURE__ */
|
|
2382
|
+
children: /* @__PURE__ */ jsx6(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
1634
2383
|
}
|
|
1635
2384
|
),
|
|
1636
|
-
/* @__PURE__ */
|
|
2385
|
+
/* @__PURE__ */ jsxs6(
|
|
1637
2386
|
"button",
|
|
1638
2387
|
{
|
|
1639
2388
|
onClick: handleDeleteSelected,
|
|
@@ -1641,12 +2390,12 @@ function TableBlockClient({
|
|
|
1641
2390
|
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
2391
|
title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
|
|
1643
2392
|
children: [
|
|
1644
|
-
/* @__PURE__ */
|
|
1645
|
-
selectedIds.size > 0 && /* @__PURE__ */
|
|
2393
|
+
/* @__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" }) }),
|
|
2394
|
+
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
2395
|
]
|
|
1647
2396
|
}
|
|
1648
2397
|
),
|
|
1649
|
-
/* @__PURE__ */
|
|
2398
|
+
/* @__PURE__ */ jsxs6(
|
|
1650
2399
|
"button",
|
|
1651
2400
|
{
|
|
1652
2401
|
onClick: toggleSummary,
|
|
@@ -1654,13 +2403,13 @@ function TableBlockClient({
|
|
|
1654
2403
|
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
2404
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
|
|
1656
2405
|
children: [
|
|
1657
|
-
/* @__PURE__ */
|
|
1658
|
-
/* @__PURE__ */
|
|
2406
|
+
/* @__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" }) }),
|
|
2407
|
+
/* @__PURE__ */ jsx6("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
|
|
1659
2408
|
]
|
|
1660
2409
|
}
|
|
1661
2410
|
),
|
|
1662
|
-
/* @__PURE__ */
|
|
1663
|
-
/* @__PURE__ */
|
|
2411
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative", ref: dropdownRef, children: [
|
|
2412
|
+
/* @__PURE__ */ jsxs6(
|
|
1664
2413
|
"button",
|
|
1665
2414
|
{
|
|
1666
2415
|
onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
|
|
@@ -1668,16 +2417,16 @@ function TableBlockClient({
|
|
|
1668
2417
|
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
2418
|
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
|
|
1670
2419
|
children: [
|
|
1671
|
-
/* @__PURE__ */
|
|
1672
|
-
/* @__PURE__ */
|
|
2420
|
+
/* @__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" }) }),
|
|
2421
|
+
/* @__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
2422
|
]
|
|
1674
2423
|
}
|
|
1675
2424
|
),
|
|
1676
|
-
isColumnsDropdownOpen && /* @__PURE__ */
|
|
1677
|
-
/* @__PURE__ */
|
|
1678
|
-
/* @__PURE__ */
|
|
1679
|
-
/* @__PURE__ */
|
|
1680
|
-
/* @__PURE__ */
|
|
2425
|
+
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: [
|
|
2426
|
+
/* @__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: [
|
|
2427
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
|
|
2428
|
+
/* @__PURE__ */ jsx6("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
|
|
2429
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-[10px] font-normal text-slate-400", children: [
|
|
1681
2430
|
"(",
|
|
1682
2431
|
customizableColumns.filter((c) => !c.isHidden).length,
|
|
1683
2432
|
"/",
|
|
@@ -1685,7 +2434,7 @@ function TableBlockClient({
|
|
|
1685
2434
|
")"
|
|
1686
2435
|
] })
|
|
1687
2436
|
] }),
|
|
1688
|
-
/* @__PURE__ */
|
|
2437
|
+
/* @__PURE__ */ jsx6(
|
|
1689
2438
|
"button",
|
|
1690
2439
|
{
|
|
1691
2440
|
type: "button",
|
|
@@ -1695,7 +2444,7 @@ function TableBlockClient({
|
|
|
1695
2444
|
}
|
|
1696
2445
|
)
|
|
1697
2446
|
] }),
|
|
1698
|
-
/* @__PURE__ */
|
|
2447
|
+
/* @__PURE__ */ jsx6("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
|
|
1699
2448
|
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1700
2449
|
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
1701
2450
|
const isProtected = isRequired || isUnique;
|
|
@@ -1709,7 +2458,7 @@ function TableBlockClient({
|
|
|
1709
2458
|
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
2459
|
}
|
|
1711
2460
|
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__ */
|
|
2461
|
+
return /* @__PURE__ */ jsxs6(
|
|
1713
2462
|
"div",
|
|
1714
2463
|
{
|
|
1715
2464
|
onClick: () => {
|
|
@@ -1720,8 +2469,8 @@ function TableBlockClient({
|
|
|
1720
2469
|
title: isProtected ? protectedExplanation : void 0,
|
|
1721
2470
|
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
2471
|
children: [
|
|
1723
|
-
/* @__PURE__ */
|
|
1724
|
-
/* @__PURE__ */
|
|
2472
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
2473
|
+
/* @__PURE__ */ jsx6(
|
|
1725
2474
|
"input",
|
|
1726
2475
|
{
|
|
1727
2476
|
type: "checkbox",
|
|
@@ -1732,16 +2481,16 @@ function TableBlockClient({
|
|
|
1732
2481
|
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
2482
|
}
|
|
1734
2483
|
),
|
|
1735
|
-
/* @__PURE__ */
|
|
2484
|
+
/* @__PURE__ */ jsx6("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
|
|
1736
2485
|
] }),
|
|
1737
|
-
isProtected && /* @__PURE__ */
|
|
2486
|
+
isProtected && /* @__PURE__ */ jsxs6(
|
|
1738
2487
|
"div",
|
|
1739
2488
|
{
|
|
1740
2489
|
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
2490
|
title: protectedExplanation,
|
|
1742
2491
|
children: [
|
|
1743
|
-
/* @__PURE__ */
|
|
1744
|
-
/* @__PURE__ */
|
|
2492
|
+
/* @__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" }) }),
|
|
2493
|
+
/* @__PURE__ */ jsx6("span", { children: badgeLabel })
|
|
1745
2494
|
]
|
|
1746
2495
|
}
|
|
1747
2496
|
)
|
|
@@ -1752,9 +2501,9 @@ function TableBlockClient({
|
|
|
1752
2501
|
}) })
|
|
1753
2502
|
] })
|
|
1754
2503
|
] }),
|
|
1755
|
-
/* @__PURE__ */
|
|
1756
|
-
/* @__PURE__ */
|
|
1757
|
-
/* @__PURE__ */
|
|
2504
|
+
/* @__PURE__ */ jsx6("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
2505
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
2506
|
+
/* @__PURE__ */ jsx6(
|
|
1758
2507
|
"input",
|
|
1759
2508
|
{
|
|
1760
2509
|
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
@@ -1764,45 +2513,45 @@ function TableBlockClient({
|
|
|
1764
2513
|
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
2514
|
}
|
|
1766
2515
|
),
|
|
1767
|
-
searchQuery ? /* @__PURE__ */
|
|
2516
|
+
searchQuery ? /* @__PURE__ */ jsx6(
|
|
1768
2517
|
"button",
|
|
1769
2518
|
{
|
|
1770
2519
|
type: "button",
|
|
1771
2520
|
onClick: () => setSearchQuery(""),
|
|
1772
2521
|
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
2522
|
title: "Clear search",
|
|
1774
|
-
children: /* @__PURE__ */
|
|
2523
|
+
children: /* @__PURE__ */ jsx6(X4, { className: "w-3.5 h-3.5" })
|
|
1775
2524
|
}
|
|
1776
|
-
) : /* @__PURE__ */
|
|
2525
|
+
) : /* @__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
2526
|
] })
|
|
1778
2527
|
] }),
|
|
1779
|
-
/* @__PURE__ */
|
|
1780
|
-
isUpdatingActive ? /* @__PURE__ */
|
|
1781
|
-
/* @__PURE__ */
|
|
2528
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
|
|
2529
|
+
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: [
|
|
2530
|
+
/* @__PURE__ */ jsx6("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
1782
2531
|
"\u05DE\u05E2\u05D3\u05DB\u05DF..."
|
|
1783
|
-
] }) : isSaveSuccess ? /* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
2532
|
+
] }) : 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: [
|
|
2533
|
+
/* @__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
2534
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
1786
|
-
] }) : hasChanges ? /* @__PURE__ */
|
|
1787
|
-
/* @__PURE__ */
|
|
2535
|
+
] }) : 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,
|
|
2536
|
+
/* @__PURE__ */ jsx6(
|
|
1788
2537
|
"button",
|
|
1789
2538
|
{
|
|
1790
2539
|
onClick: handleSave,
|
|
1791
2540
|
disabled: isUpdatingActive || isLoading || !hasChanges,
|
|
1792
2541
|
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__ */
|
|
2542
|
+
children: /* @__PURE__ */ jsx6("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
|
|
1794
2543
|
}
|
|
1795
2544
|
)
|
|
1796
2545
|
] })
|
|
1797
2546
|
] }),
|
|
1798
|
-
/* @__PURE__ */
|
|
1799
|
-
isLoading && /* @__PURE__ */
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
2547
|
+
/* @__PURE__ */ jsxs6("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
|
|
2548
|
+
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: [
|
|
2549
|
+
/* @__PURE__ */ jsx6("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
2550
|
+
/* @__PURE__ */ jsx6("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
1802
2551
|
] }),
|
|
1803
|
-
/* @__PURE__ */
|
|
1804
|
-
/* @__PURE__ */
|
|
1805
|
-
/* @__PURE__ */
|
|
2552
|
+
/* @__PURE__ */ jsxs6("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
|
|
2553
|
+
/* @__PURE__ */ jsx6("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ jsxs6("tr", { children: [
|
|
2554
|
+
/* @__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
2555
|
"input",
|
|
1807
2556
|
{
|
|
1808
2557
|
type: "checkbox",
|
|
@@ -1816,7 +2565,7 @@ function TableBlockClient({
|
|
|
1816
2565
|
const isDragging = draggedColName === col.name;
|
|
1817
2566
|
const isDragOver = dragOverColName === col.name;
|
|
1818
2567
|
const currentWidth = columnWidths[col.name] || 200;
|
|
1819
|
-
return /* @__PURE__ */
|
|
2568
|
+
return /* @__PURE__ */ jsxs6(
|
|
1820
2569
|
"th",
|
|
1821
2570
|
{
|
|
1822
2571
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
@@ -1852,7 +2601,7 @@ function TableBlockClient({
|
|
|
1852
2601
|
},
|
|
1853
2602
|
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
2603
|
children: [
|
|
1855
|
-
/* @__PURE__ */
|
|
2604
|
+
/* @__PURE__ */ jsx6(
|
|
1856
2605
|
"div",
|
|
1857
2606
|
{
|
|
1858
2607
|
onMouseDown: (e) => {
|
|
@@ -1864,16 +2613,16 @@ function TableBlockClient({
|
|
|
1864
2613
|
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
1865
2614
|
}
|
|
1866
2615
|
),
|
|
1867
|
-
/* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
1869
|
-
/* @__PURE__ */
|
|
2616
|
+
/* @__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: [
|
|
2617
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate", children: col.name }),
|
|
2618
|
+
/* @__PURE__ */ jsx6(
|
|
1870
2619
|
"svg",
|
|
1871
2620
|
{
|
|
1872
2621
|
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
1873
2622
|
fill: "none",
|
|
1874
2623
|
viewBox: "0 0 24 24",
|
|
1875
2624
|
stroke: "currentColor",
|
|
1876
|
-
children: /* @__PURE__ */
|
|
2625
|
+
children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
|
|
1877
2626
|
}
|
|
1878
2627
|
)
|
|
1879
2628
|
] })
|
|
@@ -1882,59 +2631,112 @@ function TableBlockClient({
|
|
|
1882
2631
|
col.name
|
|
1883
2632
|
);
|
|
1884
2633
|
}),
|
|
1885
|
-
/* @__PURE__ */
|
|
2634
|
+
/* @__PURE__ */ jsx6("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
|
|
1886
2635
|
] }) }),
|
|
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) => {
|
|
2636
|
+
/* @__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: [
|
|
2637
|
+
/* @__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" }) }),
|
|
2638
|
+
/* @__PURE__ */ jsx6("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
2639
|
+
] }) }) }) : filteredData.map((row) => {
|
|
2640
|
+
const hasSubTableCols = filteredColumns.some((c) => {
|
|
1902
2641
|
var _a;
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
2642
|
+
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
2643
|
+
});
|
|
2644
|
+
const isExpanded = expandedRowIds.has(row.id);
|
|
2645
|
+
const subTableColumns = filteredColumns.filter((c) => {
|
|
2646
|
+
var _a;
|
|
2647
|
+
return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
|
|
2648
|
+
});
|
|
2649
|
+
return /* @__PURE__ */ jsxs6(React6.Fragment, { children: [
|
|
2650
|
+
/* @__PURE__ */ jsxs6("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
|
|
2651
|
+
/* @__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: [
|
|
2652
|
+
hasSubTableCols && /* @__PURE__ */ jsx6(
|
|
2653
|
+
"button",
|
|
2654
|
+
{
|
|
2655
|
+
type: "button",
|
|
2656
|
+
onClick: () => setExpandedRowIds((prev) => {
|
|
2657
|
+
const next = new Set(prev);
|
|
2658
|
+
if (next.has(row.id)) next.delete(row.id);
|
|
2659
|
+
else next.add(row.id);
|
|
2660
|
+
return next;
|
|
2661
|
+
}),
|
|
2662
|
+
className: "text-slate-400 hover:text-blue-600 p-0.5 rounded transition-colors cursor-pointer",
|
|
2663
|
+
title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
|
|
2664
|
+
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" }) })
|
|
2665
|
+
}
|
|
2666
|
+
),
|
|
2667
|
+
/* @__PURE__ */ jsx6(
|
|
2668
|
+
"input",
|
|
2669
|
+
{
|
|
2670
|
+
type: "checkbox",
|
|
2671
|
+
checked: selectedIds.has(row.id),
|
|
2672
|
+
onChange: (e) => toggleSelectRow(row.id, e.target.checked),
|
|
2673
|
+
disabled: isLoading || isUpdatingActive,
|
|
2674
|
+
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
2675
|
+
}
|
|
2676
|
+
)
|
|
2677
|
+
] }) }),
|
|
2678
|
+
filteredColumns.map((col) => {
|
|
2679
|
+
var _a;
|
|
2680
|
+
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
2681
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
2682
|
+
let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
|
|
2683
|
+
if (value === void 0 && col.defaultValue !== void 0) {
|
|
2684
|
+
value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
|
|
2685
|
+
if (colType === "CURRENCY" || colType === "NUMBER") {
|
|
2686
|
+
if (isNaN(value)) value = null;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
if (value === void 0) value = null;
|
|
2690
|
+
return /* @__PURE__ */ jsx6("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ jsx6(
|
|
2691
|
+
InputComponent,
|
|
2692
|
+
{
|
|
2693
|
+
value,
|
|
2694
|
+
column: col,
|
|
2695
|
+
rowId: row.id,
|
|
2696
|
+
onChange: (v) => handleCellChange(row.id, col.name, v),
|
|
2697
|
+
context: {
|
|
2698
|
+
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",
|
|
2699
|
+
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
2700
|
+
onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
|
|
2701
|
+
relationOptions,
|
|
2702
|
+
refetchRelation,
|
|
2703
|
+
executeAction,
|
|
2704
|
+
emitEvent,
|
|
2705
|
+
pageState,
|
|
2706
|
+
componentId,
|
|
2707
|
+
orgId,
|
|
2708
|
+
updateQuietly: handleQuietCellChange,
|
|
2709
|
+
triggerSaveSuccess,
|
|
2710
|
+
rowData: row.data
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
) }, col.name);
|
|
2714
|
+
}),
|
|
2715
|
+
/* @__PURE__ */ jsx6("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
2716
|
+
] }),
|
|
2717
|
+
isExpanded && /* @__PURE__ */ jsx6(
|
|
2718
|
+
ExpandedSubTables,
|
|
1915
2719
|
{
|
|
1916
|
-
value,
|
|
1917
|
-
column: col,
|
|
1918
2720
|
rowId: row.id,
|
|
1919
|
-
|
|
2721
|
+
rowData: row.data,
|
|
2722
|
+
subTableColumns,
|
|
2723
|
+
filteredColumnsLength: filteredColumns.length,
|
|
2724
|
+
handleCellChange,
|
|
1920
2725
|
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
2726
|
executeAction,
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
2727
|
+
orgId,
|
|
2728
|
+
parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
2729
|
+
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
2730
|
+
rowData: row.data,
|
|
2731
|
+
updateQuietly: handleQuietCellChange,
|
|
2732
|
+
triggerSaveSuccess
|
|
1930
2733
|
}
|
|
1931
2734
|
}
|
|
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' }),
|
|
2735
|
+
)
|
|
2736
|
+
] }, row.id);
|
|
2737
|
+
}) }),
|
|
2738
|
+
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: [
|
|
2739
|
+
/* @__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
2740
|
filteredColumns.map((col) => {
|
|
1939
2741
|
var _a;
|
|
1940
2742
|
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
@@ -1948,16 +2750,16 @@ function TableBlockClient({
|
|
|
1948
2750
|
displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
|
|
1949
2751
|
}
|
|
1950
2752
|
}
|
|
1951
|
-
return /* @__PURE__ */
|
|
2753
|
+
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
2754
|
}),
|
|
1953
|
-
/* @__PURE__ */
|
|
2755
|
+
/* @__PURE__ */ jsx6("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
|
|
1954
2756
|
] }) })
|
|
1955
2757
|
] })
|
|
1956
2758
|
] }),
|
|
1957
|
-
/* @__PURE__ */
|
|
1958
|
-
/* @__PURE__ */
|
|
1959
|
-
/* @__PURE__ */
|
|
1960
|
-
/* @__PURE__ */
|
|
2759
|
+
/* @__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: [
|
|
2760
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
2761
|
+
/* @__PURE__ */ jsx6("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
|
|
2762
|
+
/* @__PURE__ */ jsxs6(
|
|
1961
2763
|
"select",
|
|
1962
2764
|
{
|
|
1963
2765
|
value: limit,
|
|
@@ -1965,27 +2767,27 @@ function TableBlockClient({
|
|
|
1965
2767
|
disabled: isLoading || isUpdatingActive,
|
|
1966
2768
|
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
2769
|
children: [
|
|
1968
|
-
/* @__PURE__ */
|
|
1969
|
-
/* @__PURE__ */
|
|
1970
|
-
/* @__PURE__ */
|
|
2770
|
+
/* @__PURE__ */ jsx6("option", { value: 20, children: "20" }),
|
|
2771
|
+
/* @__PURE__ */ jsx6("option", { value: 50, children: "50" }),
|
|
2772
|
+
/* @__PURE__ */ jsx6("option", { value: 100, children: "100" })
|
|
1971
2773
|
]
|
|
1972
2774
|
}
|
|
1973
2775
|
)
|
|
1974
2776
|
] }),
|
|
1975
|
-
/* @__PURE__ */
|
|
1976
|
-
/* @__PURE__ */
|
|
2777
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-4", children: [
|
|
2778
|
+
/* @__PURE__ */ jsxs6("span", { className: "font-medium text-slate-600", children: [
|
|
1977
2779
|
"\u05E2\u05DE\u05D5\u05D3 ",
|
|
1978
|
-
/* @__PURE__ */
|
|
2780
|
+
/* @__PURE__ */ jsx6("strong", { className: "text-slate-900", children: page }),
|
|
1979
2781
|
" \u05DE\u05EA\u05D5\u05DA ",
|
|
1980
|
-
/* @__PURE__ */
|
|
1981
|
-
totalRecords > 0 && /* @__PURE__ */
|
|
2782
|
+
/* @__PURE__ */ jsx6("strong", { className: "text-slate-900", children: totalPages || 1 }),
|
|
2783
|
+
totalRecords > 0 && /* @__PURE__ */ jsxs6("span", { className: "text-slate-500 font-normal", children: [
|
|
1982
2784
|
" (",
|
|
1983
2785
|
totalRecords,
|
|
1984
2786
|
' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
|
|
1985
2787
|
] })
|
|
1986
2788
|
] }),
|
|
1987
|
-
/* @__PURE__ */
|
|
1988
|
-
/* @__PURE__ */
|
|
2789
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
|
|
2790
|
+
/* @__PURE__ */ jsx6(
|
|
1989
2791
|
"button",
|
|
1990
2792
|
{
|
|
1991
2793
|
onClick: handlePrevPage,
|
|
@@ -1995,7 +2797,7 @@ function TableBlockClient({
|
|
|
1995
2797
|
children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
|
|
1996
2798
|
}
|
|
1997
2799
|
),
|
|
1998
|
-
/* @__PURE__ */
|
|
2800
|
+
/* @__PURE__ */ jsx6(
|
|
1999
2801
|
"button",
|
|
2000
2802
|
{
|
|
2001
2803
|
onClick: handleNextPage,
|
|
@@ -2012,11 +2814,60 @@ function TableBlockClient({
|
|
|
2012
2814
|
}
|
|
2013
2815
|
);
|
|
2014
2816
|
}
|
|
2817
|
+
function ExpandedSubTables({
|
|
2818
|
+
rowId,
|
|
2819
|
+
rowData,
|
|
2820
|
+
subTableColumns,
|
|
2821
|
+
filteredColumnsLength,
|
|
2822
|
+
handleCellChange,
|
|
2823
|
+
context
|
|
2824
|
+
}) {
|
|
2825
|
+
var _a;
|
|
2826
|
+
const [activeTab, setActiveTab] = useState5((_a = subTableColumns[0]) == null ? void 0 : _a.name);
|
|
2827
|
+
if (subTableColumns.length === 0) return null;
|
|
2828
|
+
if (subTableColumns.length === 1) {
|
|
2829
|
+
const stCol = subTableColumns[0];
|
|
2830
|
+
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(
|
|
2831
|
+
SubTableViewer,
|
|
2832
|
+
{
|
|
2833
|
+
rowId,
|
|
2834
|
+
column: stCol,
|
|
2835
|
+
value: (rowData == null ? void 0 : rowData[stCol.name]) || [],
|
|
2836
|
+
onChange: (newVal) => handleCellChange(rowId, stCol.name, newVal),
|
|
2837
|
+
context
|
|
2838
|
+
}
|
|
2839
|
+
) }) });
|
|
2840
|
+
}
|
|
2841
|
+
const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
|
|
2842
|
+
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: [
|
|
2843
|
+
/* @__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(
|
|
2844
|
+
"button",
|
|
2845
|
+
{
|
|
2846
|
+
type: "button",
|
|
2847
|
+
onClick: () => setActiveTab(col.name),
|
|
2848
|
+
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"}`,
|
|
2849
|
+
children: col.name
|
|
2850
|
+
},
|
|
2851
|
+
col.name
|
|
2852
|
+
)) }),
|
|
2853
|
+
/* @__PURE__ */ jsx6("div", { className: "bg-white", children: /* @__PURE__ */ jsx6(
|
|
2854
|
+
SubTableViewer,
|
|
2855
|
+
{
|
|
2856
|
+
rowId,
|
|
2857
|
+
column: activeCol,
|
|
2858
|
+
value: (rowData == null ? void 0 : rowData[activeCol.name]) || [],
|
|
2859
|
+
onChange: (newVal) => handleCellChange(rowId, activeCol.name, newVal),
|
|
2860
|
+
context
|
|
2861
|
+
},
|
|
2862
|
+
activeCol.name
|
|
2863
|
+
) })
|
|
2864
|
+
] }) });
|
|
2865
|
+
}
|
|
2015
2866
|
|
|
2016
2867
|
// src/components/TableBlock/TableBlock.tsx
|
|
2017
|
-
import { jsx as
|
|
2868
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2018
2869
|
function TableBlock(props) {
|
|
2019
|
-
return /* @__PURE__ */
|
|
2870
|
+
return /* @__PURE__ */ jsx7(TableBlockClient, __spreadValues({}, props));
|
|
2020
2871
|
}
|
|
2021
2872
|
|
|
2022
2873
|
// src/registry.ts
|