@universe-platform/ui 0.1.0-beta.12 → 0.1.0-beta.15
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 +11 -2
- package/dist/index.d.mts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +245 -202
- package/dist/index.mjs +244 -202
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -99,6 +99,30 @@ function getDeterministicPastelBadge(key) {
|
|
|
99
99
|
return PASTEL_PALETTES[index];
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
// src/utils/permissions.ts
|
|
103
|
+
function getRolePermissions(role) {
|
|
104
|
+
if (role === "VIEWER" || !role) {
|
|
105
|
+
return {
|
|
106
|
+
permissions: {
|
|
107
|
+
canCreate: false,
|
|
108
|
+
canRead: true,
|
|
109
|
+
canUpdate: false,
|
|
110
|
+
canDelete: false
|
|
111
|
+
},
|
|
112
|
+
readOnly: true
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
permissions: {
|
|
117
|
+
canCreate: true,
|
|
118
|
+
canRead: true,
|
|
119
|
+
canUpdate: true,
|
|
120
|
+
canDelete: true
|
|
121
|
+
},
|
|
122
|
+
readOnly: false
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
102
126
|
// ../shared/src/columns.ts
|
|
103
127
|
var COLUMN_TYPES = [
|
|
104
128
|
"STRING",
|
|
@@ -376,7 +400,7 @@ import React7 from "react";
|
|
|
376
400
|
import React2, { useState as useState2, useEffect } from "react";
|
|
377
401
|
import { FileText, Upload, X as X2 } from "lucide-react";
|
|
378
402
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
379
|
-
function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForDeletion, context }) {
|
|
403
|
+
function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForDeletion, context, readOnly = false }) {
|
|
380
404
|
const [isOpening, setIsOpening] = useState2(false);
|
|
381
405
|
const { showError } = useToast();
|
|
382
406
|
const cellContextId = React2.useMemo(() => {
|
|
@@ -477,29 +501,33 @@ function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForD
|
|
|
477
501
|
const updated = fileList.filter((_, idx) => idx !== indexToRemove);
|
|
478
502
|
onChange(updated);
|
|
479
503
|
};
|
|
480
|
-
const renderUploadButton = () =>
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
504
|
+
const renderUploadButton = (iconOnly) => {
|
|
505
|
+
if (readOnly) return null;
|
|
506
|
+
return /* @__PURE__ */ jsxs2(
|
|
507
|
+
"button",
|
|
508
|
+
{
|
|
509
|
+
type: "button",
|
|
510
|
+
onClick: openUploadPopup,
|
|
511
|
+
disabled: isOpening || !(context == null ? void 0 : context.executeAction),
|
|
512
|
+
className: `inline-flex items-center justify-center gap-1.5 rounded-md text-xs font-medium text-slate-500 bg-slate-100 hover:bg-slate-200 hover:text-slate-700 transition-colors disabled:opacity-50 ${iconOnly ? "w-7 h-7 shrink-0" : "px-2 py-1"}`,
|
|
513
|
+
title: "Upload File",
|
|
514
|
+
children: [
|
|
515
|
+
/* @__PURE__ */ jsx2(Upload, { className: "w-3.5 h-3.5 shrink-0" }),
|
|
516
|
+
!iconOnly && /* @__PURE__ */ jsx2("span", { className: "truncate", children: isOpening ? "Loading..." : "Upload File" })
|
|
517
|
+
]
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
};
|
|
493
521
|
if (fileList.length > 0) {
|
|
494
|
-
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-
|
|
495
|
-
fileList.map((file, idx) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center
|
|
522
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-center w-full py-1 px-2 gap-1.5", children: [
|
|
523
|
+
fileList.map((file, idx) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1 max-w-full", children: [
|
|
496
524
|
/* @__PURE__ */ jsxs2(
|
|
497
525
|
"a",
|
|
498
526
|
{
|
|
499
527
|
href: file.fileUrl || file.url,
|
|
500
528
|
target: "_blank",
|
|
501
529
|
rel: "noopener noreferrer",
|
|
502
|
-
className:
|
|
530
|
+
className: `inline-flex items-center gap-1.5 px-2 py-1 rounded-md text-xs font-medium text-blue-700 bg-blue-50 hover:bg-blue-100 transition-colors truncate ${readOnly ? "max-w-full" : "max-w-[calc(100%-28px)]"}`,
|
|
503
531
|
title: file.fileName || "Open file",
|
|
504
532
|
children: [
|
|
505
533
|
/* @__PURE__ */ jsx2(FileText, { className: "w-3.5 h-3.5 shrink-0" }),
|
|
@@ -507,21 +535,24 @@ function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForD
|
|
|
507
535
|
]
|
|
508
536
|
}
|
|
509
537
|
),
|
|
510
|
-
/* @__PURE__ */ jsx2(
|
|
538
|
+
!readOnly && /* @__PURE__ */ jsx2(
|
|
511
539
|
"button",
|
|
512
540
|
{
|
|
513
541
|
type: "button",
|
|
514
542
|
onClick: () => handleRemoveFile(idx),
|
|
515
|
-
className: "shrink-0
|
|
543
|
+
className: "shrink-0 inline-flex items-center justify-center w-6 h-6 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
|
|
516
544
|
title: "Remove file",
|
|
517
|
-
children: /* @__PURE__ */ jsx2(X2, { className: "w-3.5 h-3.5" })
|
|
545
|
+
children: /* @__PURE__ */ jsx2(X2, { className: "w-3.5 h-3.5 shrink-0" })
|
|
518
546
|
}
|
|
519
547
|
)
|
|
520
548
|
] }, file.fileId || idx)),
|
|
521
|
-
renderUploadButton()
|
|
549
|
+
renderUploadButton(true)
|
|
522
550
|
] });
|
|
523
551
|
}
|
|
524
|
-
|
|
552
|
+
if (readOnly) {
|
|
553
|
+
return /* @__PURE__ */ jsx2("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "-" });
|
|
554
|
+
}
|
|
555
|
+
return /* @__PURE__ */ jsx2("div", { className: "flex items-center w-full h-8 px-2", children: renderUploadButton(false) });
|
|
525
556
|
}
|
|
526
557
|
|
|
527
558
|
// src/components/TableBlock/fields/DatePickerCell.tsx
|
|
@@ -2088,11 +2119,19 @@ function getCurrencySymbol(code) {
|
|
|
2088
2119
|
return CURRENCY_SYMBOLS[code.toUpperCase()] || code;
|
|
2089
2120
|
}
|
|
2090
2121
|
var FORM_INPUTS = {
|
|
2091
|
-
DATE: ({ value, onChange, column }) => /* @__PURE__ */ jsx7(DatePickerCell, { value, onChange, column }),
|
|
2092
|
-
CURRENCY: ({ value, column, onChange }) => {
|
|
2122
|
+
DATE: ({ value, onChange, column, readOnly }) => /* @__PURE__ */ jsx7(DatePickerCell, { value, onChange, column, readOnly }),
|
|
2123
|
+
CURRENCY: ({ value, column, onChange, readOnly }) => {
|
|
2093
2124
|
var _a;
|
|
2094
2125
|
const symbol = getCurrencySymbol((_a = column.config) == null ? void 0 : _a.currencySymbol);
|
|
2095
2126
|
const [isFocused, setIsFocused] = React7.useState(false);
|
|
2127
|
+
if (readOnly) {
|
|
2128
|
+
const num = Number(value);
|
|
2129
|
+
const formattedValue = value !== null && value !== void 0 && !isNaN(num) ? new Intl.NumberFormat("en-US").format(num) : "";
|
|
2130
|
+
return /* @__PURE__ */ jsxs7("span", { className: "px-2 py-1 flex items-center h-full text-sm select-text truncate", children: [
|
|
2131
|
+
symbol && /* @__PURE__ */ jsx7("span", { className: "text-slate-400 mr-1", children: symbol }),
|
|
2132
|
+
formattedValue
|
|
2133
|
+
] });
|
|
2134
|
+
}
|
|
2096
2135
|
const displayValue = !isFocused && value !== void 0 && value !== null && !isNaN(Number(value)) ? new Intl.NumberFormat("en-US").format(Number(value)) : value !== void 0 && value !== null ? value : "";
|
|
2097
2136
|
return /* @__PURE__ */ jsxs7("div", { className: "relative w-full h-full", children: [
|
|
2098
2137
|
symbol && /* @__PURE__ */ jsx7("span", { className: "absolute left-2 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none text-sm", children: symbol }),
|
|
@@ -2113,18 +2152,19 @@ var FORM_INPUTS = {
|
|
|
2113
2152
|
)
|
|
2114
2153
|
] });
|
|
2115
2154
|
},
|
|
2116
|
-
TIME: ({ value, onChange, column }) => /* @__PURE__ */ jsx7(TimePickerCell, { value, onChange, column }),
|
|
2117
|
-
LINK: ({ value, onChange, column }) => /* @__PURE__ */ jsx7(LinkPickerCell, { value, onChange, column }),
|
|
2118
|
-
BOOLEAN: ({ value, onChange }) => /* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center w-full h-full p-2", children: /* @__PURE__ */ jsx7(
|
|
2155
|
+
TIME: ({ value, onChange, column, readOnly }) => /* @__PURE__ */ jsx7(TimePickerCell, { value, onChange, column, readOnly }),
|
|
2156
|
+
LINK: ({ value, onChange, column, readOnly }) => /* @__PURE__ */ jsx7(LinkPickerCell, { value, onChange, column, readOnly }),
|
|
2157
|
+
BOOLEAN: ({ value, onChange, readOnly }) => /* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center w-full h-full p-2", children: /* @__PURE__ */ jsx7(
|
|
2119
2158
|
"input",
|
|
2120
2159
|
{
|
|
2121
2160
|
type: "checkbox",
|
|
2122
2161
|
checked: !!value,
|
|
2162
|
+
disabled: readOnly,
|
|
2123
2163
|
onChange: (e) => onChange(e.target.checked),
|
|
2124
|
-
className:
|
|
2164
|
+
className: `w-4 h-4 rounded border-slate-300 text-brand ${readOnly ? "cursor-not-allowed opacity-70" : "cursor-pointer"}`
|
|
2125
2165
|
}
|
|
2126
2166
|
) }),
|
|
2127
|
-
GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ jsx7(
|
|
2167
|
+
GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context, readOnly }) => /* @__PURE__ */ jsx7(
|
|
2128
2168
|
DrivePickerCell,
|
|
2129
2169
|
{
|
|
2130
2170
|
value: value || [],
|
|
@@ -2133,34 +2173,60 @@ var FORM_INPUTS = {
|
|
|
2133
2173
|
rowId,
|
|
2134
2174
|
tableName: context == null ? void 0 : context.tableName,
|
|
2135
2175
|
onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
|
|
2136
|
-
context
|
|
2176
|
+
context,
|
|
2177
|
+
readOnly
|
|
2137
2178
|
}
|
|
2138
2179
|
),
|
|
2139
|
-
RELATION: ({ value, onChange, column, context, rowId }) => /* @__PURE__ */ jsx7(
|
|
2180
|
+
RELATION: ({ value, onChange, column, context, rowId, readOnly }) => /* @__PURE__ */ jsx7(
|
|
2140
2181
|
RelationPickerCell,
|
|
2141
2182
|
{
|
|
2142
2183
|
value,
|
|
2143
2184
|
onChange,
|
|
2144
2185
|
column,
|
|
2145
2186
|
context,
|
|
2146
|
-
rowId
|
|
2187
|
+
rowId,
|
|
2188
|
+
readOnly
|
|
2147
2189
|
}
|
|
2148
2190
|
),
|
|
2149
|
-
NUMBER: ({ value, onChange }) =>
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
type: "number",
|
|
2153
|
-
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
2154
|
-
value: value !== void 0 && value !== null ? value : "",
|
|
2155
|
-
onChange: (e) => {
|
|
2156
|
-
const val = e.target.value;
|
|
2157
|
-
onChange(val === "" ? null : Number(val));
|
|
2158
|
-
}
|
|
2191
|
+
NUMBER: ({ value, onChange, readOnly }) => {
|
|
2192
|
+
if (readOnly) {
|
|
2193
|
+
return /* @__PURE__ */ jsx7("span", { className: "px-2 py-1 flex items-center h-full text-sm select-text truncate", children: value !== void 0 && value !== null ? value : "" });
|
|
2159
2194
|
}
|
|
2160
|
-
|
|
2161
|
-
|
|
2195
|
+
return /* @__PURE__ */ jsx7(
|
|
2196
|
+
"input",
|
|
2197
|
+
{
|
|
2198
|
+
type: "number",
|
|
2199
|
+
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
2200
|
+
value: value !== void 0 && value !== null ? value : "",
|
|
2201
|
+
onChange: (e) => {
|
|
2202
|
+
const val = e.target.value;
|
|
2203
|
+
onChange(val === "" ? null : Number(val));
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
);
|
|
2207
|
+
},
|
|
2208
|
+
PHONE: ({ value, onChange, column, readOnly }) => {
|
|
2162
2209
|
var _a;
|
|
2163
2210
|
const enableWhatsApp = (_a = column == null ? void 0 : column.config) == null ? void 0 : _a.enableWhatsApp;
|
|
2211
|
+
const formatted = value ? formatPhoneDisplay(String(value)) : "";
|
|
2212
|
+
if (readOnly) {
|
|
2213
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between w-full h-full px-2 gap-1.5 overflow-hidden", children: [
|
|
2214
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate text-sm", dir: "ltr", children: formatted }),
|
|
2215
|
+
enableWhatsApp && value && /* @__PURE__ */ jsx7(
|
|
2216
|
+
"button",
|
|
2217
|
+
{
|
|
2218
|
+
type: "button",
|
|
2219
|
+
className: "text-emerald-500 cursor-pointer hover:opacity-80 transition-opacity shrink-0 p-1 rounded hover:bg-emerald-50",
|
|
2220
|
+
title: "\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4",
|
|
2221
|
+
onClick: (e) => {
|
|
2222
|
+
e.stopPropagation();
|
|
2223
|
+
openWhatsAppChat(String(value));
|
|
2224
|
+
},
|
|
2225
|
+
children: /* @__PURE__ */ jsx7("svg", { className: "w-4 h-4", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx7("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
|
|
2226
|
+
}
|
|
2227
|
+
)
|
|
2228
|
+
] });
|
|
2229
|
+
}
|
|
2164
2230
|
return /* @__PURE__ */ jsxs7("div", { className: "flex items-center w-full h-full px-2 gap-1.5 overflow-hidden", children: [
|
|
2165
2231
|
/* @__PURE__ */ jsx7(
|
|
2166
2232
|
"input",
|
|
@@ -2187,85 +2253,9 @@ var FORM_INPUTS = {
|
|
|
2187
2253
|
)
|
|
2188
2254
|
] });
|
|
2189
2255
|
},
|
|
2190
|
-
GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
|
|
2256
|
+
GOOGLE_CONTACT: ({ value, column, rowId, onChange, context, readOnly }) => {
|
|
2191
2257
|
const [isSyncing, setIsSyncing] = React7.useState(false);
|
|
2192
2258
|
const { addToast } = useToast();
|
|
2193
|
-
const googleClientIdRef = React7.useRef(null);
|
|
2194
|
-
const ensureGisScript = React7.useCallback(() => {
|
|
2195
|
-
return new Promise((resolve, reject) => {
|
|
2196
|
-
var _a, _b, _c;
|
|
2197
|
-
if ((_c = (_b = (_a = window.google) == null ? void 0 : _a.accounts) == null ? void 0 : _b.oauth2) == null ? void 0 : _c.initTokenClient) {
|
|
2198
|
-
resolve();
|
|
2199
|
-
return;
|
|
2200
|
-
}
|
|
2201
|
-
if (document.querySelector('script[src*="accounts.google.com/gsi/client"]')) {
|
|
2202
|
-
const waitForLoad = setInterval(() => {
|
|
2203
|
-
var _a2, _b2, _c2;
|
|
2204
|
-
if ((_c2 = (_b2 = (_a2 = window.google) == null ? void 0 : _a2.accounts) == null ? void 0 : _b2.oauth2) == null ? void 0 : _c2.initTokenClient) {
|
|
2205
|
-
clearInterval(waitForLoad);
|
|
2206
|
-
resolve();
|
|
2207
|
-
}
|
|
2208
|
-
}, 100);
|
|
2209
|
-
setTimeout(() => {
|
|
2210
|
-
clearInterval(waitForLoad);
|
|
2211
|
-
reject(new Error("GIS script load timeout"));
|
|
2212
|
-
}, 1e4);
|
|
2213
|
-
return;
|
|
2214
|
-
}
|
|
2215
|
-
const script = document.createElement("script");
|
|
2216
|
-
script.src = "https://accounts.google.com/gsi/client";
|
|
2217
|
-
script.async = true;
|
|
2218
|
-
script.onload = () => resolve();
|
|
2219
|
-
script.onerror = () => reject(new Error("Failed to load Google Identity Services"));
|
|
2220
|
-
document.head.appendChild(script);
|
|
2221
|
-
});
|
|
2222
|
-
}, []);
|
|
2223
|
-
const requestGisToken = React7.useCallback(async (hint) => {
|
|
2224
|
-
await ensureGisScript();
|
|
2225
|
-
if (!googleClientIdRef.current && (context == null ? void 0 : context.executeAction)) {
|
|
2226
|
-
try {
|
|
2227
|
-
const config = await context.executeAction("GET_GOOGLE_CONFIG", {});
|
|
2228
|
-
googleClientIdRef.current = (config == null ? void 0 : config.clientId) || "";
|
|
2229
|
-
} catch (e) {
|
|
2230
|
-
throw new Error("Failed to fetch Google configuration");
|
|
2231
|
-
}
|
|
2232
|
-
}
|
|
2233
|
-
const clientId = googleClientIdRef.current;
|
|
2234
|
-
if (!clientId) {
|
|
2235
|
-
throw new Error("Google Client ID is not configured");
|
|
2236
|
-
}
|
|
2237
|
-
const accessToken = await new Promise((resolve, reject) => {
|
|
2238
|
-
const tokenClient = window.google.accounts.oauth2.initTokenClient({
|
|
2239
|
-
client_id: clientId,
|
|
2240
|
-
scope: "https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/userinfo.email",
|
|
2241
|
-
prompt: hint ? "" : "select_account",
|
|
2242
|
-
hint: hint || void 0,
|
|
2243
|
-
callback: (tokenResponse) => {
|
|
2244
|
-
if (tokenResponse == null ? void 0 : tokenResponse.access_token) {
|
|
2245
|
-
resolve(tokenResponse.access_token);
|
|
2246
|
-
} else {
|
|
2247
|
-
reject(new Error("Google authorization was cancelled or failed"));
|
|
2248
|
-
}
|
|
2249
|
-
},
|
|
2250
|
-
error_callback: (err) => {
|
|
2251
|
-
reject(new Error((err == null ? void 0 : err.message) || "Google authorization error"));
|
|
2252
|
-
}
|
|
2253
|
-
});
|
|
2254
|
-
tokenClient.requestAccessToken({ hint: hint || void 0 });
|
|
2255
|
-
});
|
|
2256
|
-
let email = "";
|
|
2257
|
-
try {
|
|
2258
|
-
const res = await fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
|
|
2259
|
-
headers: { Authorization: `Bearer ${accessToken}` }
|
|
2260
|
-
});
|
|
2261
|
-
if (res.ok) {
|
|
2262
|
-
const info = await res.json();
|
|
2263
|
-
email = info.email || "";
|
|
2264
|
-
}
|
|
2265
|
-
} catch (e) {
|
|
2266
|
-
}
|
|
2267
|
-
return { accessToken, email };
|
|
2268
|
-
}, [ensureGisScript, context]);
|
|
2269
2259
|
const handleSync = async () => {
|
|
2270
2260
|
var _a, _b, _c, _d, _e, _f;
|
|
2271
2261
|
if (!(context == null ? void 0 : context.executeAction)) return;
|
|
@@ -2300,17 +2290,6 @@ var FORM_INPUTS = {
|
|
|
2300
2290
|
setIsSyncing(false);
|
|
2301
2291
|
return;
|
|
2302
2292
|
}
|
|
2303
|
-
let accessToken;
|
|
2304
|
-
let userEmail = "";
|
|
2305
|
-
try {
|
|
2306
|
-
const gisResult = await requestGisToken();
|
|
2307
|
-
accessToken = gisResult.accessToken;
|
|
2308
|
-
userEmail = gisResult.email;
|
|
2309
|
-
} catch (gisError) {
|
|
2310
|
-
addToast({ type: "warning", message: gisError.message || "\u05D4\u05D4\u05E8\u05E9\u05D0\u05D4 \u05DC\u05D2\u05D5\u05D2\u05DC \u05E0\u05DB\u05E9\u05DC\u05D4" });
|
|
2311
|
-
setIsSyncing(false);
|
|
2312
|
-
return;
|
|
2313
|
-
}
|
|
2314
2293
|
const payload = {
|
|
2315
2294
|
nameParts: mapping.nameParts || [],
|
|
2316
2295
|
phoneCol: mapping.phoneCol,
|
|
@@ -2320,9 +2299,7 @@ var FORM_INPUTS = {
|
|
|
2320
2299
|
tableMetaId: targetTableMetaId,
|
|
2321
2300
|
tableId: targetTableMetaId,
|
|
2322
2301
|
recordId: rowId,
|
|
2323
|
-
orgId: targetOrgId
|
|
2324
|
-
accessToken,
|
|
2325
|
-
userEmail
|
|
2302
|
+
orgId: targetOrgId
|
|
2326
2303
|
};
|
|
2327
2304
|
const res = await context.executeAction("SYNC_GOOGLE_CONTACT", payload);
|
|
2328
2305
|
if (res && res.synced) {
|
|
@@ -2342,39 +2319,44 @@ var FORM_INPUTS = {
|
|
|
2342
2319
|
}
|
|
2343
2320
|
}
|
|
2344
2321
|
} catch (error) {
|
|
2345
|
-
|
|
2346
|
-
|
|
2322
|
+
const errorMessage = (error == null ? void 0 : error.message) || (error == null ? void 0 : error.error) || (typeof error === "string" ? error : "");
|
|
2323
|
+
if (errorMessage.includes("OAUTH_REQUIRED") || errorMessage.includes("Access Denied") || errorMessage.includes("No refresh token")) {
|
|
2324
|
+
addToast({
|
|
2325
|
+
type: "warning",
|
|
2326
|
+
message: "\u05D8\u05E8\u05DD \u05D4\u05D5\u05D2\u05D3\u05E8 \u05D7\u05E9\u05D1\u05D5\u05DF \u05D2\u05D5\u05D2\u05DC \u05D0\u05E8\u05D2\u05D5\u05E0\u05D9. \u05D9\u05E9 \u05DC\u05E4\u05E0\u05D5\u05EA \u05DC\u05DE\u05E0\u05D4\u05DC \u05D4\u05DE\u05E2\u05E8\u05DB\u05EA \u05DC\u05D7\u05D9\u05D1\u05D5\u05E8 \u05D4\u05D7\u05E9\u05D1\u05D5\u05DF \u05D1\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05D4\u05D0\u05E8\u05D2\u05D5\u05DF."
|
|
2327
|
+
});
|
|
2328
|
+
} else {
|
|
2329
|
+
console.error("Failed to sync contact:", error);
|
|
2330
|
+
addToast({
|
|
2331
|
+
type: "warning",
|
|
2332
|
+
message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message
|
|
2333
|
+
});
|
|
2334
|
+
}
|
|
2347
2335
|
} finally {
|
|
2348
2336
|
setIsSyncing(false);
|
|
2349
2337
|
}
|
|
2350
2338
|
};
|
|
2351
2339
|
const handleUnlink = async () => {
|
|
2352
|
-
let accessToken;
|
|
2353
2340
|
const targetTableMetaId = (context == null ? void 0 : context.tableMetaId) || (context == null ? void 0 : context.tableId);
|
|
2354
2341
|
const targetOrgId = context == null ? void 0 : context.orgId;
|
|
2355
2342
|
try {
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2343
|
+
if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
|
|
2344
|
+
await context.executeAction("DELETE_GOOGLE_CONTACT", {
|
|
2345
|
+
resourceName: value.resourceName,
|
|
2346
|
+
tableMetaId: targetTableMetaId,
|
|
2347
|
+
tableId: targetTableMetaId,
|
|
2348
|
+
recordId: rowId,
|
|
2349
|
+
orgId: targetOrgId
|
|
2350
|
+
});
|
|
2363
2351
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
accessToken,
|
|
2373
|
-
tableMetaId: targetTableMetaId,
|
|
2374
|
-
tableId: targetTableMetaId,
|
|
2375
|
-
recordId: rowId,
|
|
2376
|
-
orgId: targetOrgId
|
|
2377
|
-
});
|
|
2352
|
+
} catch (error) {
|
|
2353
|
+
if (error.message === "OAUTH_REQUIRED" || error.error === "OAUTH_REQUIRED") {
|
|
2354
|
+
addToast({ type: "warning", message: "\u05D8\u05E8\u05DD \u05D4\u05D5\u05D2\u05D3\u05E8 \u05D7\u05E9\u05D1\u05D5\u05DF \u05D2\u05D5\u05D2\u05DC \u05D0\u05E8\u05D2\u05D5\u05E0\u05D9. \u05D9\u05E9 \u05DC\u05E4\u05E0\u05D5\u05EA \u05DC\u05DE\u05E0\u05D4\u05DC \u05D4\u05DE\u05E2\u05E8\u05DB\u05EA \u05DC\u05D7\u05D9\u05D1\u05D5\u05E8 \u05D4\u05D7\u05E9\u05D1\u05D5\u05DF \u05D1\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05D4\u05D0\u05E8\u05D2\u05D5\u05DF." });
|
|
2355
|
+
return;
|
|
2356
|
+
}
|
|
2357
|
+
console.error("Failed to unlink contact:", error);
|
|
2358
|
+
addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D4\u05E1\u05E8\u05EA \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
|
|
2359
|
+
return;
|
|
2378
2360
|
}
|
|
2379
2361
|
if (context == null ? void 0 : context.updateQuietly) {
|
|
2380
2362
|
context.updateQuietly(rowId, column.name, null);
|
|
@@ -2394,7 +2376,7 @@ var FORM_INPUTS = {
|
|
|
2394
2376
|
if (value && value.synced && value.url) {
|
|
2395
2377
|
return /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5 h-8 px-2 group whitespace-nowrap overflow-hidden max-w-full", children: [
|
|
2396
2378
|
/* @__PURE__ */ jsx7("a", { href: value.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate text-xs whitespace-nowrap", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" }),
|
|
2397
|
-
/* @__PURE__ */ jsx7(
|
|
2379
|
+
!readOnly && /* @__PURE__ */ jsx7(
|
|
2398
2380
|
"button",
|
|
2399
2381
|
{
|
|
2400
2382
|
type: "button",
|
|
@@ -2406,6 +2388,9 @@ var FORM_INPUTS = {
|
|
|
2406
2388
|
)
|
|
2407
2389
|
] });
|
|
2408
2390
|
}
|
|
2391
|
+
if (readOnly) {
|
|
2392
|
+
return /* @__PURE__ */ jsx7("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05DC\u05D0 \u05DE\u05E1\u05D5\u05E0\u05DB\u05E8\u05DF" });
|
|
2393
|
+
}
|
|
2409
2394
|
return /* @__PURE__ */ jsx7("div", { className: "flex items-center h-8 px-2 whitespace-nowrap overflow-hidden max-w-full", children: /* @__PURE__ */ jsxs7(
|
|
2410
2395
|
"button",
|
|
2411
2396
|
{
|
|
@@ -2423,15 +2408,20 @@ var FORM_INPUTS = {
|
|
|
2423
2408
|
}
|
|
2424
2409
|
) });
|
|
2425
2410
|
},
|
|
2426
|
-
DEFAULT: ({ value, onChange }) =>
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
type: "text",
|
|
2430
|
-
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
2431
|
-
value: value !== void 0 && value !== null ? String(value) : "",
|
|
2432
|
-
onChange: (e) => onChange(e.target.value)
|
|
2411
|
+
DEFAULT: ({ value, onChange, readOnly }) => {
|
|
2412
|
+
if (readOnly) {
|
|
2413
|
+
return /* @__PURE__ */ jsx7("span", { className: "px-2 py-1 flex items-center h-full text-sm select-text truncate", children: value !== void 0 && value !== null ? String(value) : "" });
|
|
2433
2414
|
}
|
|
2434
|
-
|
|
2415
|
+
return /* @__PURE__ */ jsx7(
|
|
2416
|
+
"input",
|
|
2417
|
+
{
|
|
2418
|
+
type: "text",
|
|
2419
|
+
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
2420
|
+
value: value !== void 0 && value !== null ? String(value) : "",
|
|
2421
|
+
onChange: (e) => onChange(e.target.value)
|
|
2422
|
+
}
|
|
2423
|
+
);
|
|
2424
|
+
},
|
|
2435
2425
|
SUB_TABLE: ({ value, column }) => {
|
|
2436
2426
|
var _a, _b, _c;
|
|
2437
2427
|
if (!Array.isArray(value)) return /* @__PURE__ */ jsx7("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
|
|
@@ -2841,7 +2831,8 @@ function SubTableCell({
|
|
|
2841
2831
|
refetchRelation,
|
|
2842
2832
|
onCommit,
|
|
2843
2833
|
onQuietUpdate,
|
|
2844
|
-
width
|
|
2834
|
+
width,
|
|
2835
|
+
readOnly
|
|
2845
2836
|
}) {
|
|
2846
2837
|
var _a, _b, _c, _d, _e;
|
|
2847
2838
|
const colType = ((_a = column.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
@@ -2876,6 +2867,7 @@ function SubTableCell({
|
|
|
2876
2867
|
}
|
|
2877
2868
|
}, [serverValue]);
|
|
2878
2869
|
const commit = useCallback8(async (valToCommit) => {
|
|
2870
|
+
if (readOnly) return true;
|
|
2879
2871
|
if (isCommittingRef.current) return false;
|
|
2880
2872
|
if (!isDirtyRef.current) return true;
|
|
2881
2873
|
if (valToCommit === serverValueRef.current) {
|
|
@@ -2992,7 +2984,9 @@ function SubTableCell({
|
|
|
2992
2984
|
column,
|
|
2993
2985
|
rowId: record.id,
|
|
2994
2986
|
onChange: handleChange,
|
|
2987
|
+
readOnly,
|
|
2995
2988
|
context: __spreadProps(__spreadValues({}, context), {
|
|
2989
|
+
readOnly,
|
|
2996
2990
|
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",
|
|
2997
2991
|
relationOptions,
|
|
2998
2992
|
updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
|
|
@@ -3022,8 +3016,9 @@ function SubTableCell({
|
|
|
3022
3016
|
}
|
|
3023
3017
|
);
|
|
3024
3018
|
}
|
|
3025
|
-
function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
3019
|
+
function SubTableViewer({ rowId, column, value, onChange, context, readOnly }) {
|
|
3026
3020
|
var _a, _b, _c, _d, _e, _f;
|
|
3021
|
+
const isReadOnly = readOnly != null ? readOnly : Boolean(context == null ? void 0 : context.readOnly);
|
|
3027
3022
|
const { addToast } = useToast();
|
|
3028
3023
|
const entries = Array.isArray(value) ? value : [];
|
|
3029
3024
|
const [linkedRecords, setLinkedRecords] = useState10(() => {
|
|
@@ -3550,7 +3545,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3550
3545
|
return /* @__PURE__ */ jsxs9("div", { className: "p-3 animate-in fade-in slide-in-from-top-2 duration-200", dir: "rtl", children: [
|
|
3551
3546
|
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-4 mb-2.5", children: [
|
|
3552
3547
|
/* @__PURE__ */ jsx9("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx9("span", { className: "text-xs font-bold text-slate-600", children: (_e = targetSchema == null ? void 0 : targetSchema.name) != null ? _e : (_d = column.config) == null ? void 0 : _d.referencedTableName }) }),
|
|
3553
|
-
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1.5", children: [
|
|
3548
|
+
!isReadOnly && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1.5", children: [
|
|
3554
3549
|
/* @__PURE__ */ jsxs9("div", { className: "relative", ref: searchRef, children: [
|
|
3555
3550
|
/* @__PURE__ */ jsxs9(
|
|
3556
3551
|
"button",
|
|
@@ -3615,13 +3610,13 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3615
3610
|
)
|
|
3616
3611
|
] })
|
|
3617
3612
|
] }),
|
|
3618
|
-
isLoading ? /* @__PURE__ */ jsx9("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx9("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ jsx9("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__ */ jsx9("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ jsxs9("table", { className: "w-full text-xs border-collapse table-auto", children: [
|
|
3613
|
+
isLoading ? /* @__PURE__ */ jsx9("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx9("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ jsx9("div", { className: "text-center py-6 text-xs text-slate-400", children: isReadOnly ? "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." : "\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__ */ jsx9("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ jsxs9("table", { className: "w-full text-xs border-collapse table-auto", children: [
|
|
3619
3614
|
/* @__PURE__ */ jsx9("thead", { children: /* @__PURE__ */ jsxs9("tr", { className: "bg-slate-100/80 h-12 min-h-[48px]", children: [
|
|
3620
3615
|
/* @__PURE__ */ jsx9("th", { className: "border border-slate-200 px-2 py-1.5 text-center w-10 font-semibold text-slate-500 h-12 min-h-[48px] align-middle", style: { width: 40, minWidth: 40, maxWidth: 40 }, children: "\u05E0\u05D1\u05D7\u05E8" }),
|
|
3621
3616
|
targetColumns.map((col) => {
|
|
3622
|
-
const dragProps = getHeaderDragProps(col.name);
|
|
3623
|
-
const isDragging = draggedColName === col.name;
|
|
3624
|
-
const isDragOver = dragOverColName === col.name;
|
|
3617
|
+
const dragProps = isReadOnly ? {} : getHeaderDragProps(col.name);
|
|
3618
|
+
const isDragging = !isReadOnly && draggedColName === col.name;
|
|
3619
|
+
const isDragOver = !isReadOnly && dragOverColName === col.name;
|
|
3625
3620
|
const colMinWidth = calculateMinColumnWidth(col.name, true, col.type);
|
|
3626
3621
|
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 150);
|
|
3627
3622
|
return /* @__PURE__ */ jsxs9(
|
|
@@ -3630,7 +3625,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3630
3625
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
3631
3626
|
title: col.name
|
|
3632
3627
|
}, dragProps), {
|
|
3633
|
-
className: `relative border border-slate-200 px-3 py-1.5 font-semibold text-slate-600 select-none cursor-grab active:cursor-grabbing transition-colors h-12 min-h-[48px] align-middle ${isDragging ? "opacity-40 bg-slate-200 border-dashed border-2 border-brand" : ""} ${isDragOver ? "bg-blue-50 border-r-4 border-r-brand text-brand font-bold" : "hover:bg-slate-200/60"}`,
|
|
3628
|
+
className: `relative border border-slate-200 px-3 py-1.5 font-semibold text-slate-600 select-none ${isReadOnly ? "cursor-default" : "cursor-grab active:cursor-grabbing"} transition-colors h-12 min-h-[48px] align-middle ${isDragging ? "opacity-40 bg-slate-200 border-dashed border-2 border-brand" : ""} ${isDragOver ? "bg-blue-50 border-r-4 border-r-brand text-brand font-bold" : isReadOnly ? "" : "hover:bg-slate-200/60"}`,
|
|
3634
3629
|
children: [
|
|
3635
3630
|
/* @__PURE__ */ jsx9(
|
|
3636
3631
|
"div",
|
|
@@ -3646,7 +3641,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3646
3641
|
),
|
|
3647
3642
|
/* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-1.5 group overflow-hidden w-full", title: col.name, children: [
|
|
3648
3643
|
/* @__PURE__ */ jsx9(ColumnHeaderTitle, { name: col.name, width: currentWidth, isSubTable: true }),
|
|
3649
|
-
/* @__PURE__ */ jsx9(
|
|
3644
|
+
!isReadOnly && /* @__PURE__ */ jsx9(
|
|
3650
3645
|
"svg",
|
|
3651
3646
|
{
|
|
3652
3647
|
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
@@ -3675,8 +3670,9 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3675
3670
|
{
|
|
3676
3671
|
type: "checkbox",
|
|
3677
3672
|
checked: entry.isSelected,
|
|
3673
|
+
disabled: isReadOnly,
|
|
3678
3674
|
onChange: () => handleToggleSelected(entry.recordId),
|
|
3679
|
-
className:
|
|
3675
|
+
className: `w-3.5 h-3.5 rounded border-slate-300 text-blue-600 ${isReadOnly ? "cursor-not-allowed opacity-60" : "cursor-pointer"}`
|
|
3680
3676
|
}
|
|
3681
3677
|
) }),
|
|
3682
3678
|
targetColumns.map((col) => {
|
|
@@ -3706,7 +3702,8 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3706
3702
|
refetchRelation,
|
|
3707
3703
|
onCommit: handleCommitRecordCell,
|
|
3708
3704
|
onQuietUpdate: handleQuietSubTableCellChange,
|
|
3709
|
-
width: currentWidth
|
|
3705
|
+
width: currentWidth,
|
|
3706
|
+
readOnly: isReadOnly
|
|
3710
3707
|
},
|
|
3711
3708
|
`${record.id}_${col.name}`
|
|
3712
3709
|
);
|
|
@@ -3733,7 +3730,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3733
3730
|
}
|
|
3734
3731
|
return null;
|
|
3735
3732
|
})(),
|
|
3736
|
-
/* @__PURE__ */ jsx9(
|
|
3733
|
+
!isReadOnly && /* @__PURE__ */ jsx9(
|
|
3737
3734
|
"button",
|
|
3738
3735
|
{
|
|
3739
3736
|
type: "button",
|
|
@@ -3750,7 +3747,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
3750
3747
|
/* @__PURE__ */ jsx9("td", { className: "border border-slate-200 bg-white pointer-events-none" })
|
|
3751
3748
|
] }, entry.recordId);
|
|
3752
3749
|
}),
|
|
3753
|
-
isCreating && /* @__PURE__ */ jsxs9("tr", { className: "bg-emerald-50/40", children: [
|
|
3750
|
+
isCreating && !isReadOnly && /* @__PURE__ */ jsxs9("tr", { className: "bg-emerald-50/40", children: [
|
|
3754
3751
|
/* @__PURE__ */ jsx9("td", { className: "border border-emerald-200 px-2 py-1 text-center", style: { width: 40, minWidth: 40, maxWidth: 40 }, children: /* @__PURE__ */ jsx9("span", { className: "text-emerald-500 font-bold text-[10px]", children: "\u05D7\u05D3\u05E9" }) }),
|
|
3755
3752
|
targetColumns.map((col) => {
|
|
3756
3753
|
var _a2, _b2, _c2, _d2, _e2;
|
|
@@ -4265,10 +4262,21 @@ function TableBlockClient({
|
|
|
4265
4262
|
componentId,
|
|
4266
4263
|
orgId,
|
|
4267
4264
|
className = "",
|
|
4268
|
-
"data-testid": dataTestId
|
|
4265
|
+
"data-testid": dataTestId,
|
|
4266
|
+
role,
|
|
4267
|
+
permissions,
|
|
4268
|
+
readOnly
|
|
4269
4269
|
}) {
|
|
4270
4270
|
const { showError, addToast } = useToast();
|
|
4271
4271
|
const [isExporting, setIsExporting] = useState12(false);
|
|
4272
|
+
const resolvedRole = role ? getRolePermissions(role) : void 0;
|
|
4273
|
+
const effectivePermissions = permissions || (resolvedRole == null ? void 0 : resolvedRole.permissions) || {
|
|
4274
|
+
canCreate: !readOnly,
|
|
4275
|
+
canRead: true,
|
|
4276
|
+
canUpdate: !readOnly,
|
|
4277
|
+
canDelete: !readOnly
|
|
4278
|
+
};
|
|
4279
|
+
const effectiveReadOnly = readOnly != null ? readOnly : resolvedRole ? resolvedRole.readOnly : !effectivePermissions.canUpdate && !effectivePermissions.canCreate && !effectivePermissions.canDelete;
|
|
4272
4280
|
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";
|
|
4273
4281
|
const { columnWidths, startResize } = useColumnResize({
|
|
4274
4282
|
storageKey: `table_widths_${tableKey}`,
|
|
@@ -5397,14 +5405,29 @@ function TableBlockClient({
|
|
|
5397
5405
|
}
|
|
5398
5406
|
const result = (res == null ? void 0 : res.data) || res;
|
|
5399
5407
|
if ((result == null ? void 0 : result.success) === false) {
|
|
5400
|
-
throw new Error(result.error || "
|
|
5408
|
+
throw new Error(result.error || "Failed to export data");
|
|
5401
5409
|
}
|
|
5410
|
+
const base64Data = result == null ? void 0 : result.base64Data;
|
|
5402
5411
|
const csvString = (result == null ? void 0 : result.csvString) || (result == null ? void 0 : result.csv);
|
|
5403
|
-
if (!csvString) {
|
|
5404
|
-
throw new Error("
|
|
5412
|
+
if (!base64Data && !csvString) {
|
|
5413
|
+
throw new Error("No export data received from server");
|
|
5414
|
+
}
|
|
5415
|
+
let blob;
|
|
5416
|
+
const defaultFileName = `${((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name) || "table").trim()}_export.xlsx`;
|
|
5417
|
+
let fileName = (result == null ? void 0 : result.fileName) || defaultFileName;
|
|
5418
|
+
if (base64Data) {
|
|
5419
|
+
const byteCharacters = atob(base64Data);
|
|
5420
|
+
const byteNumbers = new Uint8Array(byteCharacters.length);
|
|
5421
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
5422
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
5423
|
+
}
|
|
5424
|
+
blob = new Blob([byteNumbers], {
|
|
5425
|
+
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
5426
|
+
});
|
|
5427
|
+
} else {
|
|
5428
|
+
fileName = fileName.replace(/\.xlsx$/i, ".csv");
|
|
5429
|
+
blob = new Blob([csvString], { type: "text/csv;charset=utf-8;" });
|
|
5405
5430
|
}
|
|
5406
|
-
const fileName = (result == null ? void 0 : result.fileName) || `${((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name) || "table").trim()}_export.csv`;
|
|
5407
|
-
const blob = new Blob([csvString], { type: "text/csv;charset=utf-8;" });
|
|
5408
5431
|
const url = URL.createObjectURL(blob);
|
|
5409
5432
|
const link = document.createElement("a");
|
|
5410
5433
|
link.href = url;
|
|
@@ -5413,6 +5436,13 @@ function TableBlockClient({
|
|
|
5413
5436
|
link.click();
|
|
5414
5437
|
document.body.removeChild(link);
|
|
5415
5438
|
URL.revokeObjectURL(url);
|
|
5439
|
+
if (result == null ? void 0 : result.isTruncated) {
|
|
5440
|
+
addToast({
|
|
5441
|
+
message: "\u05D9\u05D5\u05E6\u05D0\u05D5 10,000 \u05D4\u05E9\u05D5\u05E8\u05D5\u05EA \u05D4\u05E8\u05D0\u05E9\u05D5\u05E0\u05D5\u05EA. \u05DE\u05D5\u05DE\u05DC\u05E5 \u05DC\u05E1\u05E0\u05DF \u05D0\u05EA \u05D4\u05D8\u05D1\u05DC\u05D4 \u05DB\u05D3\u05D9 \u05DC\u05E6\u05DE\u05E6\u05DD \u05D0\u05EA \u05D4\u05DB\u05DE\u05D5\u05EA",
|
|
5442
|
+
type: "warning",
|
|
5443
|
+
duration: 5e3
|
|
5444
|
+
});
|
|
5445
|
+
}
|
|
5416
5446
|
} catch (err) {
|
|
5417
5447
|
console.error("[TableBlock] Export to CSV failed:", err);
|
|
5418
5448
|
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D9\u05D9\u05E6\u05D5\u05D0 \u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD");
|
|
@@ -5435,7 +5465,7 @@ function TableBlockClient({
|
|
|
5435
5465
|
/* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200 shrink-0", children: [
|
|
5436
5466
|
/* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
5437
5467
|
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ jsx11("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ jsx11("span", { children: schema.title || schema.name }) }),
|
|
5438
|
-
/* @__PURE__ */ jsx11(
|
|
5468
|
+
!effectiveReadOnly && effectivePermissions.canCreate && /* @__PURE__ */ jsx11(
|
|
5439
5469
|
"button",
|
|
5440
5470
|
{
|
|
5441
5471
|
onClick: handleAddRow,
|
|
@@ -5445,7 +5475,7 @@ function TableBlockClient({
|
|
|
5445
5475
|
children: /* @__PURE__ */ jsx11("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
|
|
5446
5476
|
}
|
|
5447
5477
|
),
|
|
5448
|
-
/* @__PURE__ */ jsx11(
|
|
5478
|
+
!effectiveReadOnly && effectivePermissions.canCreate && /* @__PURE__ */ jsx11(
|
|
5449
5479
|
"button",
|
|
5450
5480
|
{
|
|
5451
5481
|
onClick: handleDuplicateRow,
|
|
@@ -5455,7 +5485,7 @@ function TableBlockClient({
|
|
|
5455
5485
|
children: /* @__PURE__ */ jsx11(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
5456
5486
|
}
|
|
5457
5487
|
),
|
|
5458
|
-
/* @__PURE__ */ jsxs11(
|
|
5488
|
+
!effectiveReadOnly && effectivePermissions.canDelete && /* @__PURE__ */ jsxs11(
|
|
5459
5489
|
"button",
|
|
5460
5490
|
{
|
|
5461
5491
|
onClick: handleDeleteSelected,
|
|
@@ -5481,7 +5511,7 @@ function TableBlockClient({
|
|
|
5481
5511
|
]
|
|
5482
5512
|
}
|
|
5483
5513
|
),
|
|
5484
|
-
/* @__PURE__ */ jsxs11("div", { className: "relative", ref: dropdownRef, children: [
|
|
5514
|
+
!effectiveReadOnly && effectivePermissions.canUpdate && /* @__PURE__ */ jsxs11("div", { className: "relative", ref: dropdownRef, children: [
|
|
5485
5515
|
/* @__PURE__ */ jsxs11(
|
|
5486
5516
|
"button",
|
|
5487
5517
|
{
|
|
@@ -5619,7 +5649,7 @@ function TableBlockClient({
|
|
|
5619
5649
|
] }) : isSaveSuccess ? /* @__PURE__ */ jsxs11("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
|
|
5620
5650
|
/* @__PURE__ */ jsx11("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
|
|
5621
5651
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
5622
|
-
] }) : hasChanges ? /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5 animate-in fade-in", children: [
|
|
5652
|
+
] }) : !effectiveReadOnly && effectivePermissions.canUpdate && hasChanges ? /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5 animate-in fade-in", children: [
|
|
5623
5653
|
/* @__PURE__ */ jsx11("span", { className: "text-xs font-semibold text-amber-700", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }),
|
|
5624
5654
|
/* @__PURE__ */ jsx11(
|
|
5625
5655
|
"button",
|
|
@@ -5634,7 +5664,7 @@ function TableBlockClient({
|
|
|
5634
5664
|
}
|
|
5635
5665
|
)
|
|
5636
5666
|
] }) : null,
|
|
5637
|
-
/* @__PURE__ */ jsx11(
|
|
5667
|
+
!effectiveReadOnly && effectivePermissions.canUpdate && /* @__PURE__ */ jsx11(
|
|
5638
5668
|
"button",
|
|
5639
5669
|
{
|
|
5640
5670
|
onClick: handleSave,
|
|
@@ -5672,9 +5702,10 @@ function TableBlockClient({
|
|
|
5672
5702
|
filteredColumns.map((col) => {
|
|
5673
5703
|
var _a, _b;
|
|
5674
5704
|
const isSearching = activeSearchCol === col.name;
|
|
5675
|
-
const
|
|
5676
|
-
const
|
|
5677
|
-
const
|
|
5705
|
+
const canReorderColumns = !effectiveReadOnly && effectivePermissions.canUpdate && !isSearching;
|
|
5706
|
+
const dragProps = canReorderColumns ? getHeaderDragProps(col.name) : {};
|
|
5707
|
+
const isDragging = canReorderColumns && draggedColName === col.name;
|
|
5708
|
+
const isDragOver = canReorderColumns && dragOverColName === col.name;
|
|
5678
5709
|
const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
|
|
5679
5710
|
const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
|
|
5680
5711
|
const isRelation = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
|
|
@@ -5694,7 +5725,7 @@ function TableBlockClient({
|
|
|
5694
5725
|
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
5695
5726
|
title: isSearching ? void 0 : col.name
|
|
5696
5727
|
}, dragProps), {
|
|
5697
|
-
className: `group relative border-b border-l border-slate-200 px-2 py-1 font-semibold text-slate-700 select-none transition-colors h-12 min-h-[48px] align-middle bg-white ${isSearching ? "cursor-default bg-blue-50/40" : "cursor-grab active:cursor-grabbing hover:bg-slate-100"} ${isDragging ? "opacity-40 bg-slate-200 border-dashed border-2 border-brand" : ""} ${isDragOver ? "bg-blue-50 border-r-4 border-r-brand text-brand font-bold" : ""}`,
|
|
5728
|
+
className: `group relative border-b border-l border-slate-200 px-2 py-1 font-semibold text-slate-700 select-none transition-colors h-12 min-h-[48px] align-middle bg-white ${isSearching ? "cursor-default bg-blue-50/40" : canReorderColumns ? "cursor-grab active:cursor-grabbing hover:bg-slate-100" : "cursor-default"} ${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" : ""}`,
|
|
5698
5729
|
children: [
|
|
5699
5730
|
/* @__PURE__ */ jsx11(
|
|
5700
5731
|
"div",
|
|
@@ -5835,7 +5866,9 @@ function TableBlockClient({
|
|
|
5835
5866
|
relationDictionaryRef,
|
|
5836
5867
|
refetchRelation,
|
|
5837
5868
|
executeAction,
|
|
5838
|
-
emitEvent
|
|
5869
|
+
emitEvent,
|
|
5870
|
+
readOnly: effectiveReadOnly || !effectivePermissions.canUpdate,
|
|
5871
|
+
permissions: effectivePermissions
|
|
5839
5872
|
},
|
|
5840
5873
|
row.id
|
|
5841
5874
|
);
|
|
@@ -5986,7 +6019,8 @@ function ExpandedSubTables({
|
|
|
5986
6019
|
column: activeCol,
|
|
5987
6020
|
value: (rowData == null ? void 0 : rowData[activeCol.name]) || [],
|
|
5988
6021
|
onChange: (newVal) => handleCellChange(rowId, activeCol.name, newVal),
|
|
5989
|
-
context
|
|
6022
|
+
context,
|
|
6023
|
+
readOnly: context == null ? void 0 : context.readOnly
|
|
5990
6024
|
},
|
|
5991
6025
|
activeCol.name
|
|
5992
6026
|
) })
|
|
@@ -6017,7 +6051,9 @@ var TableRow = React11.memo(function TableRow2({
|
|
|
6017
6051
|
relationDictionaryRef,
|
|
6018
6052
|
refetchRelation,
|
|
6019
6053
|
executeAction,
|
|
6020
|
-
emitEvent
|
|
6054
|
+
emitEvent,
|
|
6055
|
+
readOnly,
|
|
6056
|
+
permissions
|
|
6021
6057
|
}) {
|
|
6022
6058
|
return /* @__PURE__ */ jsxs11(React11.Fragment, { children: [
|
|
6023
6059
|
/* @__PURE__ */ jsxs11("tr", { className: `hover:bg-blue-50/30 transition-colors group ${isSelected ? "bg-blue-50/40" : ""}`, children: [
|
|
@@ -6069,6 +6105,7 @@ var TableRow = React11.memo(function TableRow2({
|
|
|
6069
6105
|
column: col,
|
|
6070
6106
|
rowId: row.id,
|
|
6071
6107
|
onChange: (v) => handleCellChange(row.id, col.name, v),
|
|
6108
|
+
readOnly,
|
|
6072
6109
|
context: {
|
|
6073
6110
|
tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
|
|
6074
6111
|
tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
|
|
@@ -6083,7 +6120,9 @@ var TableRow = React11.memo(function TableRow2({
|
|
|
6083
6120
|
orgId,
|
|
6084
6121
|
updateQuietly: handleQuietCellChange,
|
|
6085
6122
|
triggerSaveSuccess,
|
|
6086
|
-
rowData: row.data
|
|
6123
|
+
rowData: row.data,
|
|
6124
|
+
readOnly,
|
|
6125
|
+
permissions
|
|
6087
6126
|
}
|
|
6088
6127
|
}
|
|
6089
6128
|
)
|
|
@@ -6109,7 +6148,9 @@ var TableRow = React11.memo(function TableRow2({
|
|
|
6109
6148
|
rowData: row.data,
|
|
6110
6149
|
updateQuietly: handleQuietCellChange,
|
|
6111
6150
|
triggerSaveSuccess,
|
|
6112
|
-
onUpdateColumnConfig: handleUpdateColumnConfig
|
|
6151
|
+
onUpdateColumnConfig: handleUpdateColumnConfig,
|
|
6152
|
+
readOnly,
|
|
6153
|
+
permissions
|
|
6113
6154
|
}
|
|
6114
6155
|
}
|
|
6115
6156
|
)
|
|
@@ -6150,6 +6191,7 @@ export {
|
|
|
6150
6191
|
formatTimeInput,
|
|
6151
6192
|
formatTimeIso,
|
|
6152
6193
|
getDeterministicPastelBadge,
|
|
6194
|
+
getRolePermissions,
|
|
6153
6195
|
isTextRepresentable,
|
|
6154
6196
|
measureTextWidth,
|
|
6155
6197
|
normalizeRelationValue,
|