@supos-grid-table/core 0.1.0-alpha.1 → 0.1.0-alpha.2
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/README.md +12 -1
- package/SHADCN.json +117 -0
- package/dist/{grid-DqJTLeBs.mjs → grid-DeVIC26t.mjs} +109 -124
- package/dist/grid-DeVIC26t.mjs.map +1 -0
- package/dist/grid.d.mts +2 -2
- package/dist/grid.mjs +1 -1
- package/dist/react.d.mts +1 -1
- package/dist/react.mjs +424 -211
- package/dist/react.mjs.map +1 -1
- package/dist/style.css +2 -1
- package/dist/ui-esOhDo-4.mjs +946 -0
- package/dist/ui-esOhDo-4.mjs.map +1 -0
- package/dist/ui.d.mts +183 -0
- package/dist/ui.mjs +2 -0
- package/licenses/@base-ui_react-LICENSE +21 -0
- package/licenses/DEPENDENCIES.json +49 -9
- package/licenses/Shadcn-MIT.txt +21 -0
- package/licenses/class-variance-authority-LICENSE +190 -0
- package/licenses/cmdk-LICENSE.md +21 -0
- package/licenses/cn-LICENSE +21 -0
- package/licenses/lucide-react-LICENSE +7 -3
- package/licenses/tw-animate-css-LICENSE +21 -0
- package/package.json +53 -18
- package/dist/grid-DqJTLeBs.mjs.map +0 -1
package/dist/react.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { n as copyTemplate, r as isComputed, t as TableError } from "./model-BrBCOyRY.mjs";
|
|
2
2
|
import { a as summarize, i as queryRows, n as groupRows, t as displayValue } from "./query-DDwS9-yU.mjs";
|
|
3
|
-
import { t as Grid } from "./grid-
|
|
3
|
+
import { t as Grid } from "./grid-DeVIC26t.mjs";
|
|
4
|
+
import { At as DialogHeader, Bt as Textarea, C as ComboboxChip, Ct as AlertDialogTitle, D as ComboboxContent, Dt as DialogContent, Et as DialogClose, Ft as Checkbox, Ht as Button, I as ComboboxValue, It as NativeSelect, L as useComboboxAnchor, N as ComboboxList, Nt as DialogTitle, O as ComboboxEmpty, Ot as DialogDescription, Rt as NativeSelectOption, S as Combobox, T as ComboboxChipsInput, Tt as Dialog, Vt as Input, _ as Tabs, _t as AlertDialogDescription, b as TabsTrigger, c as Alert, g as CollapsibleTrigger, gt as AlertDialogContent, h as CollapsibleContent, ht as AlertDialogCancel, j as ComboboxItem, m as Collapsible, mt as AlertDialogAction, pt as AlertDialog, t as Card, v as TabsContent, vt as AlertDialogFooter, w as ComboboxChips, y as TabsList, yt as AlertDialogHeader, zt as Label } from "./ui-esOhDo-4.mjs";
|
|
4
5
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { AlertTriangle, ArrowDownUp, Braces, CalendarDays, ChartNoAxesCombined, Check, ChevronDown, ClipboardList, Columns3, Database, Download, Filter, Plus, Redo2, Search, SlidersHorizontal, Table2, Trash2, Undo2, X } from "lucide-react";
|
|
@@ -153,43 +154,58 @@ function fromCell(field, value) {
|
|
|
153
154
|
return raw;
|
|
154
155
|
}
|
|
155
156
|
function Modal({ title, close, children, error }) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
close();
|
|
157
|
+
return /* @__PURE__ */ jsx(Dialog, {
|
|
158
|
+
open: true,
|
|
159
|
+
disablePointerDismissal: true,
|
|
160
|
+
onOpenChange: (open, details) => {
|
|
161
|
+
const target = details.event.target;
|
|
162
|
+
if (!open && details.reason === "escape-key" && target instanceof Element && target.closest("[role=\"combobox\"]")) {
|
|
163
|
+
details.cancel();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (!open) close();
|
|
167
167
|
},
|
|
168
|
-
children:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
168
|
+
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
169
|
+
className: "sg-portal sg-modal",
|
|
170
|
+
showCloseButton: false,
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ jsxs(DialogHeader, {
|
|
173
|
+
className: "sg-modal-header",
|
|
174
|
+
children: [
|
|
175
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: title }),
|
|
176
|
+
/* @__PURE__ */ jsx(DialogDescription, {
|
|
177
|
+
className: "sr-only",
|
|
178
|
+
children: "填写并保存本次修改,按 Escape 或关闭按钮返回。"
|
|
179
|
+
}),
|
|
180
|
+
/* @__PURE__ */ jsx(DialogClose, {
|
|
181
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
182
|
+
variant: "ghost",
|
|
183
|
+
size: "icon-sm",
|
|
184
|
+
"aria-label": "关闭"
|
|
185
|
+
}),
|
|
186
|
+
children: /* @__PURE__ */ jsx(X, { size: 18 })
|
|
187
|
+
})
|
|
188
|
+
]
|
|
189
|
+
}),
|
|
190
|
+
error && /* @__PURE__ */ jsx(Alert, {
|
|
191
|
+
className: "sg-error",
|
|
192
|
+
role: "alert",
|
|
193
|
+
children: error
|
|
194
|
+
}),
|
|
195
|
+
children
|
|
196
|
+
]
|
|
197
|
+
})
|
|
182
198
|
});
|
|
183
199
|
}
|
|
184
200
|
function FieldInput({ field, value, set, snapshot }) {
|
|
201
|
+
const anchor = useComboboxAnchor();
|
|
185
202
|
if (isComputed(field) || field.readonly) return /* @__PURE__ */ jsx("output", { children: displayValue(value) || "保存后计算" });
|
|
186
|
-
if (field.type === "boolean") return /* @__PURE__ */ jsx(
|
|
203
|
+
if (field.type === "boolean") return /* @__PURE__ */ jsx(Checkbox, {
|
|
187
204
|
"aria-label": field.name,
|
|
188
|
-
type: "checkbox",
|
|
189
205
|
checked: value === true,
|
|
190
|
-
|
|
206
|
+
onCheckedChange: (checked) => set(checked === true)
|
|
191
207
|
});
|
|
192
|
-
if (field.type === "textarea") return /* @__PURE__ */ jsx(
|
|
208
|
+
if (field.type === "textarea") return /* @__PURE__ */ jsx(Textarea, {
|
|
193
209
|
"aria-label": field.name,
|
|
194
210
|
rows: 3,
|
|
195
211
|
value: String(value ?? ""),
|
|
@@ -205,22 +221,52 @@ function FieldInput({ field, value, set, snapshot }) {
|
|
|
205
221
|
id: o,
|
|
206
222
|
label: o
|
|
207
223
|
}));
|
|
208
|
-
return /* @__PURE__ */ jsxs(
|
|
224
|
+
if (multiple) return /* @__PURE__ */ jsxs(Combobox, {
|
|
225
|
+
multiple: true,
|
|
226
|
+
items: options.map((option) => option.id),
|
|
227
|
+
value: Array.isArray(value) ? value.map(String) : [],
|
|
228
|
+
onValueChange: (next, details) => {
|
|
229
|
+
if (details.reason === "escape-key") {
|
|
230
|
+
details.cancel();
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
set(next);
|
|
234
|
+
},
|
|
235
|
+
itemToStringLabel: (id) => options.find((option) => option.id === id)?.label ?? id,
|
|
236
|
+
children: [/* @__PURE__ */ jsxs(ComboboxChips, {
|
|
237
|
+
ref: anchor,
|
|
238
|
+
children: [/* @__PURE__ */ jsx(ComboboxValue, { children: (selected) => selected.map((id) => /* @__PURE__ */ jsx(ComboboxChip, {
|
|
239
|
+
"aria-label": `移除 ${options.find((option) => option.id === id)?.label ?? id}`,
|
|
240
|
+
children: options.find((option) => option.id === id)?.label ?? id
|
|
241
|
+
}, id)) }), /* @__PURE__ */ jsx(ComboboxChipsInput, {
|
|
242
|
+
"aria-label": field.name,
|
|
243
|
+
placeholder: "搜索并选择,可多选"
|
|
244
|
+
})]
|
|
245
|
+
}), /* @__PURE__ */ jsxs(ComboboxContent, {
|
|
246
|
+
className: "sg-portal",
|
|
247
|
+
anchor,
|
|
248
|
+
children: [/* @__PURE__ */ jsx(ComboboxEmpty, { children: "没有匹配的记录或选项" }), /* @__PURE__ */ jsx(ComboboxList, { children: (id) => /* @__PURE__ */ jsx(ComboboxItem, {
|
|
249
|
+
value: id,
|
|
250
|
+
children: options.find((option) => option.id === id)?.label ?? id
|
|
251
|
+
}, id) })]
|
|
252
|
+
})]
|
|
253
|
+
});
|
|
254
|
+
return /* @__PURE__ */ jsxs(NativeSelect, {
|
|
209
255
|
"aria-label": field.name,
|
|
210
256
|
multiple: !!multiple,
|
|
211
257
|
required: field.required,
|
|
212
258
|
value: multiple ? Array.isArray(value) ? value.map(String) : [] : Array.isArray(value) ? String(value[0] ?? "") : String(value ?? ""),
|
|
213
259
|
onChange: (e) => set(multiple ? Array.from(e.target.selectedOptions, (o) => o.value) : field.type === "relation" ? e.target.value ? [e.target.value] : [] : e.target.value || null),
|
|
214
|
-
children: [!multiple && /* @__PURE__ */ jsx(
|
|
260
|
+
children: [!multiple && /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
215
261
|
value: "",
|
|
216
262
|
children: "请选择"
|
|
217
|
-
}), options.map((o) => /* @__PURE__ */ jsx(
|
|
263
|
+
}), options.map((o) => /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
218
264
|
value: o.id,
|
|
219
265
|
children: o.label
|
|
220
266
|
}, o.id))]
|
|
221
267
|
});
|
|
222
268
|
}
|
|
223
|
-
return /* @__PURE__ */ jsx(
|
|
269
|
+
return /* @__PURE__ */ jsx(Input, {
|
|
224
270
|
"aria-label": field.name,
|
|
225
271
|
type: field.type === "number" ? "number" : field.type === "date" ? "date" : "text",
|
|
226
272
|
step: field.type === "number" ? "any" : void 0,
|
|
@@ -261,12 +307,12 @@ function RecordForm({ table, snapshot, row, busy, onSave, onDelete, error }) {
|
|
|
261
307
|
className: "sg-muted",
|
|
262
308
|
children: row ? "修改将校验打开记录时的版本,其他人的更新会提示冲突。" : "按数据模型填写,保存成功后可在所有视图查看。"
|
|
263
309
|
}),
|
|
264
|
-
error && /* @__PURE__ */ jsxs(
|
|
310
|
+
error && /* @__PURE__ */ jsxs(Alert, {
|
|
265
311
|
role: "alert",
|
|
266
312
|
className: "sg-error",
|
|
267
313
|
children: [error, "。待提交内容已保留。"]
|
|
268
314
|
}),
|
|
269
|
-
table.fields.map((field) => /* @__PURE__ */ jsxs(
|
|
315
|
+
table.fields.map((field) => /* @__PURE__ */ jsxs(Label, { children: [
|
|
270
316
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
271
317
|
field.name,
|
|
272
318
|
field.required && /* @__PURE__ */ jsx("b", {
|
|
@@ -287,7 +333,9 @@ function RecordForm({ table, snapshot, row, busy, onSave, onDelete, error }) {
|
|
|
287
333
|
},
|
|
288
334
|
snapshot: draftSnapshot
|
|
289
335
|
}),
|
|
290
|
-
field.type === "relation" && !field.readonly && /* @__PURE__ */ jsxs(
|
|
336
|
+
field.type === "relation" && !field.readonly && /* @__PURE__ */ jsxs(Button, {
|
|
337
|
+
variant: "ghost",
|
|
338
|
+
size: "sm",
|
|
291
339
|
type: "button",
|
|
292
340
|
disabled: !snapshot.capabilities.atomicBatch || busy,
|
|
293
341
|
onClick: () => setRelationDraft(field),
|
|
@@ -295,7 +343,9 @@ function RecordForm({ table, snapshot, row, busy, onSave, onDelete, error }) {
|
|
|
295
343
|
})
|
|
296
344
|
] }, field.id)),
|
|
297
345
|
/* @__PURE__ */ jsxs("footer", { children: [
|
|
298
|
-
onDelete && /* @__PURE__ */ jsxs(
|
|
346
|
+
onDelete && /* @__PURE__ */ jsxs(Button, {
|
|
347
|
+
variant: "ghost",
|
|
348
|
+
size: "sm",
|
|
299
349
|
type: "button",
|
|
300
350
|
className: "sg-danger",
|
|
301
351
|
disabled: busy,
|
|
@@ -307,7 +357,9 @@ function RecordForm({ table, snapshot, row, busy, onSave, onDelete, error }) {
|
|
|
307
357
|
className: "sg-success",
|
|
308
358
|
children: [/* @__PURE__ */ jsx(Check, { size: 15 }), "已保存"]
|
|
309
359
|
}),
|
|
310
|
-
/* @__PURE__ */ jsx(
|
|
360
|
+
/* @__PURE__ */ jsx(Button, {
|
|
361
|
+
variant: "default",
|
|
362
|
+
size: "sm",
|
|
311
363
|
className: "sg-primary",
|
|
312
364
|
type: "submit",
|
|
313
365
|
disabled: busy || !snapshot.capabilities.write,
|
|
@@ -346,15 +398,16 @@ function RecordForm({ table, snapshot, row, busy, onSave, onDelete, error }) {
|
|
|
346
398
|
}
|
|
347
399
|
function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
348
400
|
const [base, setBase] = useState(() => structuredClone(snapshot.base));
|
|
401
|
+
const [deleteField, setDeleteField] = useState();
|
|
349
402
|
const draft = base.tables.find((t) => t.id === table.id);
|
|
350
403
|
function update() {
|
|
351
404
|
setBase(structuredClone(base));
|
|
352
405
|
}
|
|
353
|
-
return /* @__PURE__ */
|
|
406
|
+
return /* @__PURE__ */ jsxs(Modal, {
|
|
354
407
|
title: "字段与 UNS 绑定",
|
|
355
408
|
close,
|
|
356
409
|
error,
|
|
357
|
-
children: /* @__PURE__ */ jsxs("form", {
|
|
410
|
+
children: [/* @__PURE__ */ jsxs("form", {
|
|
358
411
|
className: "sg-schema",
|
|
359
412
|
onSubmit: async (e) => {
|
|
360
413
|
e.preventDefault();
|
|
@@ -365,7 +418,7 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
365
418
|
className: "sg-muted",
|
|
366
419
|
children: "字段引用使用稳定 ID。绑定仅配置映射,实际读写由已接入的 UNS 适配器执行。"
|
|
367
420
|
}),
|
|
368
|
-
/* @__PURE__ */ jsxs(
|
|
421
|
+
/* @__PURE__ */ jsxs(Label, { children: ["数据表名称", /* @__PURE__ */ jsx(Input, {
|
|
369
422
|
required: true,
|
|
370
423
|
value: draft.name,
|
|
371
424
|
onChange: (e) => {
|
|
@@ -378,18 +431,16 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
378
431
|
children: draft.fields.map((field) => /* @__PURE__ */ jsxs("fieldset", { children: [
|
|
379
432
|
/* @__PURE__ */ jsxs("div", {
|
|
380
433
|
className: "sg-field-heading",
|
|
381
|
-
children: [/* @__PURE__ */ jsx("code", { children: field.id }), /* @__PURE__ */ jsx(
|
|
434
|
+
children: [/* @__PURE__ */ jsx("code", { children: field.id }), /* @__PURE__ */ jsx(Button, {
|
|
435
|
+
variant: "ghost",
|
|
436
|
+
size: "sm",
|
|
382
437
|
type: "button",
|
|
383
438
|
title: `删除字段 ${field.name}`,
|
|
384
|
-
onClick: () =>
|
|
385
|
-
if (!confirm(`删除字段“${field.name}”的应用配置?关联公式和视图也需要调整。`)) return;
|
|
386
|
-
draft.fields = draft.fields.filter((f) => f.id !== field.id);
|
|
387
|
-
update();
|
|
388
|
-
},
|
|
439
|
+
onClick: () => setDeleteField(field),
|
|
389
440
|
children: /* @__PURE__ */ jsx(Trash2, { size: 14 })
|
|
390
441
|
})]
|
|
391
442
|
}),
|
|
392
|
-
/* @__PURE__ */ jsxs(
|
|
443
|
+
/* @__PURE__ */ jsxs(Label, { children: ["名称", /* @__PURE__ */ jsx(Input, {
|
|
393
444
|
required: true,
|
|
394
445
|
value: field.name,
|
|
395
446
|
onChange: (e) => {
|
|
@@ -397,7 +448,7 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
397
448
|
update();
|
|
398
449
|
}
|
|
399
450
|
})] }),
|
|
400
|
-
/* @__PURE__ */ jsxs(
|
|
451
|
+
/* @__PURE__ */ jsxs(Label, { children: ["类型", /* @__PURE__ */ jsx(NativeSelect, {
|
|
401
452
|
value: field.type,
|
|
402
453
|
onChange: (e) => {
|
|
403
454
|
field.type = e.target.value;
|
|
@@ -416,38 +467,36 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
416
467
|
"formula",
|
|
417
468
|
"lookup",
|
|
418
469
|
"rollup"
|
|
419
|
-
].map((kind) => /* @__PURE__ */ jsx(
|
|
470
|
+
].map((kind) => /* @__PURE__ */ jsx(NativeSelectOption, { children: kind }, kind))
|
|
420
471
|
})] }),
|
|
421
|
-
/* @__PURE__ */ jsxs(
|
|
472
|
+
/* @__PURE__ */ jsxs(Label, {
|
|
422
473
|
className: "sg-check",
|
|
423
|
-
children: [/* @__PURE__ */ jsx(
|
|
424
|
-
type: "checkbox",
|
|
474
|
+
children: [/* @__PURE__ */ jsx(Checkbox, {
|
|
425
475
|
checked: !!field.required,
|
|
426
|
-
|
|
427
|
-
field.required =
|
|
476
|
+
onCheckedChange: (checked) => {
|
|
477
|
+
field.required = checked === true;
|
|
428
478
|
update();
|
|
429
479
|
}
|
|
430
480
|
}), "必填"]
|
|
431
481
|
}),
|
|
432
|
-
/* @__PURE__ */ jsxs(
|
|
482
|
+
/* @__PURE__ */ jsxs(Label, {
|
|
433
483
|
className: "sg-check",
|
|
434
|
-
children: [/* @__PURE__ */ jsx(
|
|
435
|
-
type: "checkbox",
|
|
484
|
+
children: [/* @__PURE__ */ jsx(Checkbox, {
|
|
436
485
|
checked: !!field.readonly,
|
|
437
|
-
|
|
438
|
-
field.readonly =
|
|
486
|
+
onCheckedChange: (checked) => {
|
|
487
|
+
field.readonly = checked === true;
|
|
439
488
|
update();
|
|
440
489
|
}
|
|
441
490
|
}), "只读"]
|
|
442
491
|
}),
|
|
443
|
-
(field.type === "select" || field.type === "multiSelect") && /* @__PURE__ */ jsxs(
|
|
492
|
+
(field.type === "select" || field.type === "multiSelect") && /* @__PURE__ */ jsxs(Label, { children: ["选项(每行一个)", /* @__PURE__ */ jsx(Textarea, {
|
|
444
493
|
value: (field.options ?? []).join("\n"),
|
|
445
494
|
onChange: (e) => {
|
|
446
495
|
field.options = e.target.value.split("\n");
|
|
447
496
|
update();
|
|
448
497
|
}
|
|
449
498
|
})] }),
|
|
450
|
-
field.type === "formula" && /* @__PURE__ */ jsxs(
|
|
499
|
+
field.type === "formula" && /* @__PURE__ */ jsxs(Label, { children: ["公式", /* @__PURE__ */ jsx(Textarea, {
|
|
451
500
|
placeholder: "IF({status} = '已过账', {quantity}, 0)",
|
|
452
501
|
value: field.formula ?? "",
|
|
453
502
|
onChange: (e) => {
|
|
@@ -455,7 +504,7 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
455
504
|
update();
|
|
456
505
|
}
|
|
457
506
|
})] }),
|
|
458
|
-
field.type === "relation" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(
|
|
507
|
+
field.type === "relation" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Label, { children: ["关联表", /* @__PURE__ */ jsxs(NativeSelect, {
|
|
459
508
|
value: field.relation?.tableId ?? "",
|
|
460
509
|
onChange: (e) => {
|
|
461
510
|
field.relation = {
|
|
@@ -464,29 +513,28 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
464
513
|
};
|
|
465
514
|
update();
|
|
466
515
|
},
|
|
467
|
-
children: [/* @__PURE__ */ jsx(
|
|
516
|
+
children: [/* @__PURE__ */ jsx(NativeSelectOption, {
|
|
468
517
|
value: "",
|
|
469
518
|
children: "请选择"
|
|
470
|
-
}), base.tables.map((t) => /* @__PURE__ */ jsx(
|
|
519
|
+
}), base.tables.map((t) => /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
471
520
|
value: t.id,
|
|
472
521
|
children: t.name
|
|
473
522
|
}, t.id))]
|
|
474
|
-
})] }), /* @__PURE__ */ jsxs(
|
|
523
|
+
})] }), /* @__PURE__ */ jsxs(Label, {
|
|
475
524
|
className: "sg-check",
|
|
476
|
-
children: [/* @__PURE__ */ jsx(
|
|
477
|
-
type: "checkbox",
|
|
525
|
+
children: [/* @__PURE__ */ jsx(Checkbox, {
|
|
478
526
|
checked: field.relation?.multiple ?? true,
|
|
479
|
-
|
|
527
|
+
onCheckedChange: (checked) => {
|
|
480
528
|
field.relation = {
|
|
481
529
|
tableId: field.relation?.tableId ?? "",
|
|
482
|
-
multiple:
|
|
530
|
+
multiple: checked === true
|
|
483
531
|
};
|
|
484
532
|
update();
|
|
485
533
|
}
|
|
486
534
|
}), "允许关联多个记录"]
|
|
487
535
|
})] }),
|
|
488
536
|
(field.type === "lookup" || field.type === "rollup") && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
489
|
-
/* @__PURE__ */ jsxs(
|
|
537
|
+
/* @__PURE__ */ jsxs(Label, { children: ["关联字段 ID", /* @__PURE__ */ jsx(Input, {
|
|
490
538
|
value: field.lookup?.relationFieldId ?? "",
|
|
491
539
|
onChange: (e) => {
|
|
492
540
|
field.lookup = {
|
|
@@ -497,7 +545,7 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
497
545
|
update();
|
|
498
546
|
}
|
|
499
547
|
})] }),
|
|
500
|
-
/* @__PURE__ */ jsxs(
|
|
548
|
+
/* @__PURE__ */ jsxs(Label, { children: ["目标字段 ID", /* @__PURE__ */ jsx(Input, {
|
|
501
549
|
value: field.lookup?.targetFieldId ?? "",
|
|
502
550
|
onChange: (e) => {
|
|
503
551
|
field.lookup = {
|
|
@@ -508,7 +556,7 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
508
556
|
update();
|
|
509
557
|
}
|
|
510
558
|
})] }),
|
|
511
|
-
field.type === "rollup" && /* @__PURE__ */ jsxs(
|
|
559
|
+
field.type === "rollup" && /* @__PURE__ */ jsxs(Label, { children: ["汇总", /* @__PURE__ */ jsx(NativeSelect, {
|
|
512
560
|
value: field.lookup?.aggregate ?? "sum",
|
|
513
561
|
onChange: (e) => {
|
|
514
562
|
field.lookup = {
|
|
@@ -523,12 +571,14 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
523
571
|
"min",
|
|
524
572
|
"max",
|
|
525
573
|
"average"
|
|
526
|
-
].map((s) => /* @__PURE__ */ jsx(
|
|
574
|
+
].map((s) => /* @__PURE__ */ jsx(NativeSelectOption, { children: s }, s))
|
|
527
575
|
})] })
|
|
528
576
|
] })
|
|
529
577
|
] }, field.id))
|
|
530
578
|
}),
|
|
531
|
-
/* @__PURE__ */ jsxs(
|
|
579
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
580
|
+
variant: "ghost",
|
|
581
|
+
size: "sm",
|
|
532
582
|
type: "button",
|
|
533
583
|
onClick: () => {
|
|
534
584
|
draft.fields.push({
|
|
@@ -540,39 +590,63 @@ function SchemaEditor({ snapshot, table, save, close, error }) {
|
|
|
540
590
|
},
|
|
541
591
|
children: [/* @__PURE__ */ jsx(Plus, { size: 16 }), "新增字段"]
|
|
542
592
|
}),
|
|
543
|
-
/* @__PURE__ */ jsxs(
|
|
544
|
-
/* @__PURE__ */ jsx(
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
593
|
+
/* @__PURE__ */ jsxs(Collapsible, { children: [/* @__PURE__ */ jsx(CollapsibleTrigger, {
|
|
594
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
595
|
+
variant: "ghost",
|
|
596
|
+
type: "button"
|
|
597
|
+
}),
|
|
598
|
+
children: "UNS 数据绑定"
|
|
599
|
+
}), /* @__PURE__ */ jsxs(CollapsibleContent, { children: [/* @__PURE__ */ jsxs(Label, { children: ["UNS alias", /* @__PURE__ */ jsx(Input, {
|
|
600
|
+
value: draft.binding?.alias ?? "",
|
|
601
|
+
onChange: (e) => {
|
|
602
|
+
draft.binding = {
|
|
603
|
+
alias: e.target.value,
|
|
604
|
+
fieldMap: draft.binding?.fieldMap ?? {}
|
|
605
|
+
};
|
|
606
|
+
update();
|
|
607
|
+
}
|
|
608
|
+
})] }), draft.fields.filter((f) => !isComputed(f)).map((f) => /* @__PURE__ */ jsxs(Label, { children: [f.name, /* @__PURE__ */ jsx(Input, {
|
|
609
|
+
placeholder: "UNS 字段名",
|
|
610
|
+
value: draft.binding?.fieldMap[f.id] ?? "",
|
|
611
|
+
onChange: (e) => {
|
|
612
|
+
draft.binding ??= {
|
|
613
|
+
alias: "",
|
|
614
|
+
fieldMap: {}
|
|
615
|
+
};
|
|
616
|
+
if (e.target.value) draft.binding.fieldMap[f.id] = e.target.value;
|
|
617
|
+
else delete draft.binding.fieldMap[f.id];
|
|
618
|
+
update();
|
|
619
|
+
}
|
|
620
|
+
})] }, f.id))] })] }),
|
|
621
|
+
/* @__PURE__ */ jsx("footer", { children: /* @__PURE__ */ jsx(Button, {
|
|
622
|
+
variant: "default",
|
|
623
|
+
size: "sm",
|
|
570
624
|
type: "submit",
|
|
571
625
|
className: "sg-primary",
|
|
572
626
|
children: "保存配置"
|
|
573
627
|
}) })
|
|
574
628
|
]
|
|
575
|
-
})
|
|
629
|
+
}), /* @__PURE__ */ jsx(AlertDialog, {
|
|
630
|
+
open: !!deleteField,
|
|
631
|
+
onOpenChange: (open) => {
|
|
632
|
+
if (!open) setDeleteField(void 0);
|
|
633
|
+
},
|
|
634
|
+
children: /* @__PURE__ */ jsxs(AlertDialogContent, {
|
|
635
|
+
className: "sg-portal",
|
|
636
|
+
children: [/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: "删除字段配置" }), /* @__PURE__ */ jsxs(AlertDialogDescription, { children: [
|
|
637
|
+
"确认删除“",
|
|
638
|
+
deleteField?.name,
|
|
639
|
+
"”的应用配置?关联公式和视图也需要调整。"
|
|
640
|
+
] })] }), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, { children: "取消" }), /* @__PURE__ */ jsx(AlertDialogAction, {
|
|
641
|
+
onClick: () => {
|
|
642
|
+
draft.fields = draft.fields.filter((field) => field.id !== deleteField?.id);
|
|
643
|
+
update();
|
|
644
|
+
setDeleteField(void 0);
|
|
645
|
+
},
|
|
646
|
+
children: "确认删除"
|
|
647
|
+
})] })]
|
|
648
|
+
})
|
|
649
|
+
})]
|
|
576
650
|
});
|
|
577
651
|
}
|
|
578
652
|
function ViewEditor({ view, table, save, close, error }) {
|
|
@@ -588,7 +662,7 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
588
662
|
if (await save(draft)) close();
|
|
589
663
|
},
|
|
590
664
|
children: [
|
|
591
|
-
/* @__PURE__ */ jsxs(
|
|
665
|
+
/* @__PURE__ */ jsxs(Label, { children: ["名称", /* @__PURE__ */ jsx(Input, {
|
|
592
666
|
required: true,
|
|
593
667
|
value: draft.name,
|
|
594
668
|
onChange: (e) => setDraft({
|
|
@@ -596,46 +670,46 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
596
670
|
name: e.target.value
|
|
597
671
|
})
|
|
598
672
|
})] }),
|
|
599
|
-
/* @__PURE__ */ jsxs(
|
|
673
|
+
/* @__PURE__ */ jsxs(Label, { children: ["视图类型", /* @__PURE__ */ jsx(NativeSelect, {
|
|
600
674
|
value: draft.type,
|
|
601
675
|
onChange: (e) => setDraft({
|
|
602
676
|
...draft,
|
|
603
677
|
type: e.target.value
|
|
604
678
|
}),
|
|
605
|
-
children: Object.entries(viewNames).map(([id, name]) => /* @__PURE__ */ jsx(
|
|
679
|
+
children: Object.entries(viewNames).map(([id, name]) => /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
606
680
|
value: id,
|
|
607
681
|
children: name
|
|
608
682
|
}, id))
|
|
609
683
|
})] }),
|
|
610
|
-
/* @__PURE__ */ jsxs(
|
|
684
|
+
/* @__PURE__ */ jsxs(Label, { children: ["分组字段", /* @__PURE__ */ jsxs(NativeSelect, {
|
|
611
685
|
value: draft.groupBy ?? "",
|
|
612
686
|
onChange: (e) => setDraft({
|
|
613
687
|
...draft,
|
|
614
688
|
groupBy: e.target.value || void 0
|
|
615
689
|
}),
|
|
616
|
-
children: [/* @__PURE__ */ jsx(
|
|
690
|
+
children: [/* @__PURE__ */ jsx(NativeSelectOption, {
|
|
617
691
|
value: "",
|
|
618
692
|
children: "不分组"
|
|
619
|
-
}), table.fields.map((f) => /* @__PURE__ */ jsx(
|
|
693
|
+
}), table.fields.map((f) => /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
620
694
|
value: f.id,
|
|
621
695
|
children: f.name
|
|
622
696
|
}, f.id))]
|
|
623
697
|
})] }),
|
|
624
|
-
/* @__PURE__ */ jsxs(
|
|
698
|
+
/* @__PURE__ */ jsxs(Label, { children: ["日历日期字段", /* @__PURE__ */ jsxs(NativeSelect, {
|
|
625
699
|
value: draft.dateFieldId ?? "",
|
|
626
700
|
onChange: (e) => setDraft({
|
|
627
701
|
...draft,
|
|
628
702
|
dateFieldId: e.target.value || void 0
|
|
629
703
|
}),
|
|
630
|
-
children: [/* @__PURE__ */ jsx(
|
|
704
|
+
children: [/* @__PURE__ */ jsx(NativeSelectOption, {
|
|
631
705
|
value: "",
|
|
632
706
|
children: "请选择"
|
|
633
|
-
}), table.fields.filter((f) => f.type === "date").map((f) => /* @__PURE__ */ jsx(
|
|
707
|
+
}), table.fields.filter((f) => f.type === "date").map((f) => /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
634
708
|
value: f.id,
|
|
635
709
|
children: f.name
|
|
636
710
|
}, f.id))]
|
|
637
711
|
})] }),
|
|
638
|
-
/* @__PURE__ */ jsxs(
|
|
712
|
+
/* @__PURE__ */ jsxs(Label, { children: ["冻结列数", /* @__PURE__ */ jsx(Input, {
|
|
639
713
|
type: "number",
|
|
640
714
|
min: 0,
|
|
641
715
|
max: table.fields.length,
|
|
@@ -645,14 +719,13 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
645
719
|
freezeColumns: Number(e.target.value)
|
|
646
720
|
})
|
|
647
721
|
})] }),
|
|
648
|
-
/* @__PURE__ */ jsxs("fieldset", { children: [/* @__PURE__ */ jsx("legend", { children: "显示字段" }), table.fields.map((f) => /* @__PURE__ */ jsxs(
|
|
722
|
+
/* @__PURE__ */ jsxs("fieldset", { children: [/* @__PURE__ */ jsx("legend", { children: "显示字段" }), table.fields.map((f) => /* @__PURE__ */ jsxs(Label, {
|
|
649
723
|
className: "sg-check",
|
|
650
|
-
children: [/* @__PURE__ */ jsx(
|
|
651
|
-
type: "checkbox",
|
|
724
|
+
children: [/* @__PURE__ */ jsx(Checkbox, {
|
|
652
725
|
checked: !draft.hiddenFields?.includes(f.id),
|
|
653
|
-
|
|
726
|
+
onCheckedChange: (checked) => setDraft({
|
|
654
727
|
...draft,
|
|
655
|
-
hiddenFields:
|
|
728
|
+
hiddenFields: checked === true ? (draft.hiddenFields ?? []).filter((id) => id !== f.id) : [...draft.hiddenFields ?? [], f.id]
|
|
656
729
|
})
|
|
657
730
|
}), f.name]
|
|
658
731
|
}, f.id))] }),
|
|
@@ -661,19 +734,19 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
661
734
|
(draft.filters ?? []).map((filter, index) => /* @__PURE__ */ jsxs("div", {
|
|
662
735
|
className: "sg-filter-line",
|
|
663
736
|
children: [
|
|
664
|
-
/* @__PURE__ */ jsx(
|
|
737
|
+
/* @__PURE__ */ jsx(NativeSelect, {
|
|
665
738
|
"aria-label": "筛选字段",
|
|
666
739
|
value: filter.fieldId,
|
|
667
740
|
onChange: (e) => {
|
|
668
741
|
draft.filters[index].fieldId = e.target.value;
|
|
669
742
|
setDraft(structuredClone(draft));
|
|
670
743
|
},
|
|
671
|
-
children: table.fields.map((f) => /* @__PURE__ */ jsx(
|
|
744
|
+
children: table.fields.map((f) => /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
672
745
|
value: f.id,
|
|
673
746
|
children: f.name
|
|
674
747
|
}, f.id))
|
|
675
748
|
}),
|
|
676
|
-
/* @__PURE__ */ jsx(
|
|
749
|
+
/* @__PURE__ */ jsx(NativeSelect, {
|
|
677
750
|
"aria-label": "筛选方式",
|
|
678
751
|
value: filter.op,
|
|
679
752
|
onChange: (e) => {
|
|
@@ -689,9 +762,9 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
689
762
|
"lt",
|
|
690
763
|
"lte",
|
|
691
764
|
"empty"
|
|
692
|
-
].map((op) => /* @__PURE__ */ jsx(
|
|
765
|
+
].map((op) => /* @__PURE__ */ jsx(NativeSelectOption, { children: op }, op))
|
|
693
766
|
}),
|
|
694
|
-
/* @__PURE__ */ jsx(
|
|
767
|
+
/* @__PURE__ */ jsx(Input, {
|
|
695
768
|
"aria-label": "筛选值",
|
|
696
769
|
value: displayValue(filter.value),
|
|
697
770
|
onChange: (e) => {
|
|
@@ -700,7 +773,9 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
700
773
|
setDraft(structuredClone(draft));
|
|
701
774
|
}
|
|
702
775
|
}),
|
|
703
|
-
/* @__PURE__ */ jsx(
|
|
776
|
+
/* @__PURE__ */ jsx(Button, {
|
|
777
|
+
variant: "ghost",
|
|
778
|
+
size: "sm",
|
|
704
779
|
type: "button",
|
|
705
780
|
"aria-label": "移除筛选",
|
|
706
781
|
onClick: () => setDraft({
|
|
@@ -711,7 +786,9 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
711
786
|
})
|
|
712
787
|
]
|
|
713
788
|
}, index)),
|
|
714
|
-
/* @__PURE__ */ jsx(
|
|
789
|
+
/* @__PURE__ */ jsx(Button, {
|
|
790
|
+
variant: "ghost",
|
|
791
|
+
size: "sm",
|
|
715
792
|
type: "button",
|
|
716
793
|
onClick: () => setDraft({
|
|
717
794
|
...draft,
|
|
@@ -724,7 +801,7 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
724
801
|
children: "添加条件"
|
|
725
802
|
})
|
|
726
803
|
] }),
|
|
727
|
-
/* @__PURE__ */ jsxs(
|
|
804
|
+
/* @__PURE__ */ jsxs(Label, { children: ["排序字段", /* @__PURE__ */ jsxs(NativeSelect, {
|
|
728
805
|
value: draft.sorts?.[0]?.fieldId ?? "",
|
|
729
806
|
onChange: (e) => setDraft({
|
|
730
807
|
...draft,
|
|
@@ -733,15 +810,15 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
733
810
|
direction: draft.sorts?.[0]?.direction ?? "asc"
|
|
734
811
|
}] : []
|
|
735
812
|
}),
|
|
736
|
-
children: [/* @__PURE__ */ jsx(
|
|
813
|
+
children: [/* @__PURE__ */ jsx(NativeSelectOption, {
|
|
737
814
|
value: "",
|
|
738
815
|
children: "默认顺序"
|
|
739
|
-
}), table.fields.map((f) => /* @__PURE__ */ jsx(
|
|
816
|
+
}), table.fields.map((f) => /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
740
817
|
value: f.id,
|
|
741
818
|
children: f.name
|
|
742
819
|
}, f.id))]
|
|
743
820
|
})] }),
|
|
744
|
-
/* @__PURE__ */ jsxs(
|
|
821
|
+
/* @__PURE__ */ jsxs(Label, { children: ["方向", /* @__PURE__ */ jsxs(NativeSelect, {
|
|
745
822
|
value: draft.sorts?.[0]?.direction ?? "asc",
|
|
746
823
|
onChange: (e) => setDraft({
|
|
747
824
|
...draft,
|
|
@@ -750,15 +827,17 @@ function ViewEditor({ view, table, save, close, error }) {
|
|
|
750
827
|
direction: e.target.value
|
|
751
828
|
}))
|
|
752
829
|
}),
|
|
753
|
-
children: [/* @__PURE__ */ jsx(
|
|
830
|
+
children: [/* @__PURE__ */ jsx(NativeSelectOption, {
|
|
754
831
|
value: "asc",
|
|
755
832
|
children: "升序"
|
|
756
|
-
}), /* @__PURE__ */ jsx(
|
|
833
|
+
}), /* @__PURE__ */ jsx(NativeSelectOption, {
|
|
757
834
|
value: "desc",
|
|
758
835
|
children: "降序"
|
|
759
836
|
})]
|
|
760
837
|
})] }),
|
|
761
|
-
/* @__PURE__ */ jsx("footer", { children: /* @__PURE__ */ jsx(
|
|
838
|
+
/* @__PURE__ */ jsx("footer", { children: /* @__PURE__ */ jsx(Button, {
|
|
839
|
+
variant: "default",
|
|
840
|
+
size: "sm",
|
|
762
841
|
className: "sg-primary",
|
|
763
842
|
type: "submit",
|
|
764
843
|
children: "保存视图"
|
|
@@ -779,7 +858,7 @@ function CalendarView({ rows, view, table, open }) {
|
|
|
779
858
|
const padding = new Date(Date.UTC(year, mm - 1, 1)).getUTCDay();
|
|
780
859
|
return /* @__PURE__ */ jsxs("section", {
|
|
781
860
|
className: "sg-calendar",
|
|
782
|
-
children: [/* @__PURE__ */ jsxs(
|
|
861
|
+
children: [/* @__PURE__ */ jsxs(Label, { children: ["月份", /* @__PURE__ */ jsx(Input, {
|
|
783
862
|
"aria-label": "日历月份",
|
|
784
863
|
type: "month",
|
|
785
864
|
value: month,
|
|
@@ -803,7 +882,10 @@ function CalendarView({ rows, view, table, open }) {
|
|
|
803
882
|
const date = `${month}-${String(i + 1).padStart(2, "0")}`;
|
|
804
883
|
return /* @__PURE__ */ jsxs("div", {
|
|
805
884
|
className: "sg-calendar-day",
|
|
806
|
-
children: [/* @__PURE__ */ jsx("span", { children: i + 1 }), rows.filter((r) => r.values[dateField] === date).map((r) => /* @__PURE__ */ jsx(
|
|
885
|
+
children: [/* @__PURE__ */ jsx("span", { children: i + 1 }), rows.filter((r) => r.values[dateField] === date).map((r) => /* @__PURE__ */ jsx(Button, {
|
|
886
|
+
variant: "ghost",
|
|
887
|
+
size: "sm",
|
|
888
|
+
type: "button",
|
|
807
889
|
onClick: () => open(r),
|
|
808
890
|
children: displayValue(r.values[table.fields[0].id]) || r.id
|
|
809
891
|
}, r.id))]
|
|
@@ -821,6 +903,8 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
821
903
|
const [busy, setBusy] = useState(false), [connected, setConnected] = useState(false);
|
|
822
904
|
const [online, setOnline] = useState([]);
|
|
823
905
|
const [record, setRecord] = useState();
|
|
906
|
+
const [newTable, setNewTable] = useState(false), [newTableName, setNewTableName] = useState("");
|
|
907
|
+
const [confirmation, setConfirmation] = useState();
|
|
824
908
|
const [schemaOpen, setSchemaOpen] = useState(false), [viewDraft, setViewDraft] = useState();
|
|
825
909
|
const [pending, setPending] = useState();
|
|
826
910
|
const [undo, setUndo] = useState([]), [redo, setRedo] = useState([]);
|
|
@@ -924,7 +1008,10 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
924
1008
|
children: [
|
|
925
1009
|
/* @__PURE__ */ jsx(Database, { size: 32 }),
|
|
926
1010
|
/* @__PURE__ */ jsx("p", { children: error || "正在加载多维表格…" }),
|
|
927
|
-
error && /* @__PURE__ */ jsx(
|
|
1011
|
+
error && /* @__PURE__ */ jsx(Button, {
|
|
1012
|
+
variant: "ghost",
|
|
1013
|
+
size: "sm",
|
|
1014
|
+
type: "button",
|
|
928
1015
|
onClick: () => void refresh(),
|
|
929
1016
|
children: "重新加载"
|
|
930
1017
|
})
|
|
@@ -1003,7 +1090,10 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1003
1090
|
/* @__PURE__ */ jsx("i", {}),
|
|
1004
1091
|
name,
|
|
1005
1092
|
/* @__PURE__ */ jsx("small", { children: records.length })
|
|
1006
|
-
] }), records.map((row) => /* @__PURE__ */ jsxs(
|
|
1093
|
+
] }), records.map((row) => /* @__PURE__ */ jsxs(Button, {
|
|
1094
|
+
variant: "ghost",
|
|
1095
|
+
size: "sm",
|
|
1096
|
+
type: "button",
|
|
1007
1097
|
className: "sg-card",
|
|
1008
1098
|
draggable: !readonly && groupingField?.type === "select",
|
|
1009
1099
|
onDragStart: (e) => e.dataTransfer.setData("text/plain", row.id),
|
|
@@ -1152,6 +1242,22 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1152
1242
|
})]
|
|
1153
1243
|
}, groupName ?? "all");
|
|
1154
1244
|
}
|
|
1245
|
+
const confirmationDialog = /* @__PURE__ */ jsx(AlertDialog, {
|
|
1246
|
+
open: !!confirmation,
|
|
1247
|
+
onOpenChange: (open) => {
|
|
1248
|
+
if (!open) setConfirmation(void 0);
|
|
1249
|
+
},
|
|
1250
|
+
children: /* @__PURE__ */ jsxs(AlertDialogContent, {
|
|
1251
|
+
className: "sg-portal",
|
|
1252
|
+
children: [/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: confirmation?.title }), /* @__PURE__ */ jsx(AlertDialogDescription, { children: confirmation?.description })] }), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, { children: "取消" }), /* @__PURE__ */ jsx(AlertDialogAction, {
|
|
1253
|
+
onClick: () => {
|
|
1254
|
+
confirmation?.action();
|
|
1255
|
+
setConfirmation(void 0);
|
|
1256
|
+
},
|
|
1257
|
+
children: "确认"
|
|
1258
|
+
})] })]
|
|
1259
|
+
})
|
|
1260
|
+
});
|
|
1155
1261
|
return /* @__PURE__ */ jsxs("main", {
|
|
1156
1262
|
className: "sg-app",
|
|
1157
1263
|
children: [
|
|
@@ -1171,7 +1277,10 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1171
1277
|
}),
|
|
1172
1278
|
/* @__PURE__ */ jsx("nav", {
|
|
1173
1279
|
"aria-label": "数据表",
|
|
1174
|
-
children: snapshot.base.tables.map((t) => /* @__PURE__ */ jsxs(
|
|
1280
|
+
children: snapshot.base.tables.map((t) => /* @__PURE__ */ jsxs(Button, {
|
|
1281
|
+
variant: "ghost",
|
|
1282
|
+
size: "sm",
|
|
1283
|
+
type: "button",
|
|
1175
1284
|
className: t.id === table.id ? "active" : "",
|
|
1176
1285
|
onClick: () => {
|
|
1177
1286
|
setTableId(t.id);
|
|
@@ -1186,28 +1295,14 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1186
1295
|
]
|
|
1187
1296
|
}, t.id))
|
|
1188
1297
|
}),
|
|
1189
|
-
/* @__PURE__ */ jsxs(
|
|
1298
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
1299
|
+
variant: "ghost",
|
|
1300
|
+
size: "sm",
|
|
1301
|
+
type: "button",
|
|
1190
1302
|
className: "sg-add-table",
|
|
1191
|
-
onClick:
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
const id = `t_${crypto.randomUUID().slice(0, 8)}`, base = structuredClone(snapshot.base);
|
|
1195
|
-
base.tables.push({
|
|
1196
|
-
id,
|
|
1197
|
-
name,
|
|
1198
|
-
fields: [{
|
|
1199
|
-
id: "name",
|
|
1200
|
-
name: "名称",
|
|
1201
|
-
type: "text",
|
|
1202
|
-
required: true
|
|
1203
|
-
}],
|
|
1204
|
-
views: [{
|
|
1205
|
-
id: "grid",
|
|
1206
|
-
name: "全部记录",
|
|
1207
|
-
type: "grid"
|
|
1208
|
-
}]
|
|
1209
|
-
});
|
|
1210
|
-
if (await configure(base)) setTableId(id);
|
|
1303
|
+
onClick: () => {
|
|
1304
|
+
setNewTableName("");
|
|
1305
|
+
setNewTable(true);
|
|
1211
1306
|
},
|
|
1212
1307
|
children: [/* @__PURE__ */ jsx(Plus, { size: 15 }), "添加数据表"]
|
|
1213
1308
|
}),
|
|
@@ -1216,7 +1311,10 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1216
1311
|
children: [
|
|
1217
1312
|
/* @__PURE__ */ jsx("span", { className: `sg-connection ${connected ? "connected" : ""}` }),
|
|
1218
1313
|
connected ? "协同已连接" : "正在重连,输入会保留",
|
|
1219
|
-
/* @__PURE__ */ jsx(
|
|
1314
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1315
|
+
variant: "ghost",
|
|
1316
|
+
size: "sm",
|
|
1317
|
+
type: "button",
|
|
1220
1318
|
title: "导出不含数据和绑定的应用模板",
|
|
1221
1319
|
onClick: () => download(`${snapshot.base.name}.template.json`, JSON.stringify(copyTemplate(snapshot.base), null, 2), "application/json"),
|
|
1222
1320
|
children: /* @__PURE__ */ jsx(Download, { size: 15 })
|
|
@@ -1225,8 +1323,11 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1225
1323
|
})
|
|
1226
1324
|
]
|
|
1227
1325
|
}),
|
|
1228
|
-
/* @__PURE__ */ jsxs(
|
|
1326
|
+
/* @__PURE__ */ jsxs(Tabs, {
|
|
1327
|
+
value: view.id,
|
|
1328
|
+
onValueChange: (value) => setViewId(String(value)),
|
|
1229
1329
|
className: "sg-workspace",
|
|
1330
|
+
render: /* @__PURE__ */ jsx("section", {}),
|
|
1230
1331
|
children: [
|
|
1231
1332
|
/* @__PURE__ */ jsxs("header", {
|
|
1232
1333
|
className: "sg-topbar",
|
|
@@ -1242,7 +1343,10 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1242
1343
|
title: `${p.name}${p.fieldId ? ` · ${p.fieldId}` : ""}`,
|
|
1243
1344
|
children: p.name.slice(0, 1)
|
|
1244
1345
|
}, `${p.userId}/${p.clientId}`))
|
|
1245
|
-
}), /* @__PURE__ */ jsxs(
|
|
1346
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
1347
|
+
variant: "ghost",
|
|
1348
|
+
size: "sm",
|
|
1349
|
+
type: "button",
|
|
1246
1350
|
onClick: () => setSchemaOpen(true),
|
|
1247
1351
|
children: [/* @__PURE__ */ jsx(SlidersHorizontal, { size: 16 }), "字段与绑定"]
|
|
1248
1352
|
})]
|
|
@@ -1251,14 +1355,21 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1251
1355
|
/* @__PURE__ */ jsxs("nav", {
|
|
1252
1356
|
className: "sg-view-tabs",
|
|
1253
1357
|
"aria-label": "视图",
|
|
1254
|
-
children: [
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1358
|
+
children: [/* @__PURE__ */ jsx(TabsList, {
|
|
1359
|
+
variant: "line",
|
|
1360
|
+
"aria-label": "视图",
|
|
1361
|
+
children: table.views.map((v) => {
|
|
1362
|
+
const Icon = viewIcons[v.type];
|
|
1363
|
+
return /* @__PURE__ */ jsxs(TabsTrigger, {
|
|
1364
|
+
value: v.id,
|
|
1365
|
+
className: v.id === view.id ? "active" : "",
|
|
1366
|
+
children: [/* @__PURE__ */ jsx(Icon, { size: 15 }), v.name]
|
|
1367
|
+
}, v.id);
|
|
1368
|
+
})
|
|
1369
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
1370
|
+
variant: "ghost",
|
|
1371
|
+
size: "sm",
|
|
1372
|
+
type: "button",
|
|
1262
1373
|
"aria-label": "新增视图",
|
|
1263
1374
|
onClick: () => setViewDraft({
|
|
1264
1375
|
id: `v_${crypto.randomUUID().slice(0, 8)}`,
|
|
@@ -1271,13 +1382,19 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1271
1382
|
/* @__PURE__ */ jsxs("div", {
|
|
1272
1383
|
className: "sg-toolbar",
|
|
1273
1384
|
children: [/* @__PURE__ */ jsxs("div", { children: [
|
|
1274
|
-
/* @__PURE__ */ jsxs(
|
|
1385
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
1386
|
+
variant: "default",
|
|
1387
|
+
size: "sm",
|
|
1388
|
+
type: "button",
|
|
1275
1389
|
className: "sg-primary",
|
|
1276
1390
|
disabled: readonly || busy,
|
|
1277
1391
|
onClick: () => setRecord("new"),
|
|
1278
1392
|
children: [/* @__PURE__ */ jsx(Plus, { size: 16 }), "新增记录"]
|
|
1279
1393
|
}),
|
|
1280
|
-
/* @__PURE__ */ jsxs(
|
|
1394
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
1395
|
+
variant: "ghost",
|
|
1396
|
+
size: "sm",
|
|
1397
|
+
type: "button",
|
|
1281
1398
|
onClick: () => setViewDraft(view),
|
|
1282
1399
|
children: [
|
|
1283
1400
|
/* @__PURE__ */ jsx(Filter, { size: 15 }),
|
|
@@ -1285,35 +1402,50 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1285
1402
|
view.filters?.length ? ` ${view.filters.length}` : ""
|
|
1286
1403
|
]
|
|
1287
1404
|
}),
|
|
1288
|
-
/* @__PURE__ */ jsxs(
|
|
1405
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
1406
|
+
variant: "ghost",
|
|
1407
|
+
size: "sm",
|
|
1408
|
+
type: "button",
|
|
1289
1409
|
onClick: () => setViewDraft(view),
|
|
1290
1410
|
children: [/* @__PURE__ */ jsx(ArrowDownUp, { size: 15 }), "排序"]
|
|
1291
1411
|
}),
|
|
1292
|
-
/* @__PURE__ */ jsxs(
|
|
1412
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
1413
|
+
variant: "ghost",
|
|
1414
|
+
size: "sm",
|
|
1415
|
+
type: "button",
|
|
1293
1416
|
onClick: () => setViewDraft(view),
|
|
1294
1417
|
children: [/* @__PURE__ */ jsx(SlidersHorizontal, { size: 15 }), "视图设置"]
|
|
1295
1418
|
})
|
|
1296
1419
|
] }), /* @__PURE__ */ jsxs("div", { children: [
|
|
1297
|
-
/* @__PURE__ */ jsx(
|
|
1420
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1421
|
+
variant: "ghost",
|
|
1422
|
+
size: "sm",
|
|
1423
|
+
type: "button",
|
|
1298
1424
|
"aria-label": "撤销",
|
|
1299
1425
|
disabled: !undo.length || busy,
|
|
1300
1426
|
onClick: () => void commit(undo[undo.length - 1], "undo"),
|
|
1301
1427
|
children: /* @__PURE__ */ jsx(Undo2, { size: 16 })
|
|
1302
1428
|
}),
|
|
1303
|
-
/* @__PURE__ */ jsx(
|
|
1429
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1430
|
+
variant: "ghost",
|
|
1431
|
+
size: "sm",
|
|
1432
|
+
type: "button",
|
|
1304
1433
|
"aria-label": "重做",
|
|
1305
1434
|
disabled: !redo.length || busy,
|
|
1306
1435
|
onClick: () => void commit(redo[redo.length - 1], "redo"),
|
|
1307
1436
|
children: /* @__PURE__ */ jsx(Redo2, { size: 16 })
|
|
1308
1437
|
}),
|
|
1309
|
-
/* @__PURE__ */ jsx(
|
|
1438
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1439
|
+
variant: "ghost",
|
|
1440
|
+
size: "sm",
|
|
1441
|
+
type: "button",
|
|
1310
1442
|
"aria-label": "导出 CSV",
|
|
1311
1443
|
onClick: exportCsv,
|
|
1312
1444
|
children: /* @__PURE__ */ jsx(Download, { size: 16 })
|
|
1313
1445
|
}),
|
|
1314
|
-
/* @__PURE__ */ jsxs(
|
|
1446
|
+
/* @__PURE__ */ jsxs(Label, {
|
|
1315
1447
|
className: "sg-search",
|
|
1316
|
-
children: [/* @__PURE__ */ jsx(Search, { size: 15 }), /* @__PURE__ */ jsx(
|
|
1448
|
+
children: [/* @__PURE__ */ jsx(Search, { size: 15 }), /* @__PURE__ */ jsx(Input, {
|
|
1317
1449
|
placeholder: "搜索当前表",
|
|
1318
1450
|
value: search,
|
|
1319
1451
|
onChange: (e) => setSearch(e.target.value)
|
|
@@ -1321,74 +1453,105 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1321
1453
|
})
|
|
1322
1454
|
] })]
|
|
1323
1455
|
}),
|
|
1324
|
-
snapshot.dataError && /* @__PURE__ */ jsxs(
|
|
1456
|
+
snapshot.dataError && /* @__PURE__ */ jsxs(Alert, {
|
|
1325
1457
|
className: "sg-error",
|
|
1326
1458
|
role: "alert",
|
|
1327
1459
|
children: [
|
|
1328
1460
|
/* @__PURE__ */ jsx(AlertTriangle, { size: 16 }),
|
|
1329
1461
|
/* @__PURE__ */ jsx("span", { children: snapshot.dataError }),
|
|
1330
|
-
/* @__PURE__ */ jsx(
|
|
1462
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1463
|
+
variant: "ghost",
|
|
1464
|
+
size: "sm",
|
|
1465
|
+
type: "button",
|
|
1331
1466
|
onClick: () => setSchemaOpen(true),
|
|
1332
1467
|
children: "检查字段与绑定"
|
|
1333
1468
|
}),
|
|
1334
|
-
/* @__PURE__ */ jsx(
|
|
1469
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1470
|
+
variant: "ghost",
|
|
1471
|
+
size: "sm",
|
|
1472
|
+
type: "button",
|
|
1335
1473
|
onClick: () => void refresh(),
|
|
1336
1474
|
children: "重新连接"
|
|
1337
1475
|
})
|
|
1338
1476
|
]
|
|
1339
1477
|
}),
|
|
1340
|
-
error && /* @__PURE__ */ jsxs(
|
|
1478
|
+
error && /* @__PURE__ */ jsxs(Alert, {
|
|
1341
1479
|
className: "sg-error",
|
|
1342
1480
|
role: "alert",
|
|
1343
1481
|
children: [
|
|
1344
1482
|
/* @__PURE__ */ jsx(AlertTriangle, { size: 16 }),
|
|
1345
1483
|
/* @__PURE__ */ jsxs("span", { children: [error, pending && "。待提交内容已保留。"] }),
|
|
1346
|
-
pending && /* @__PURE__ */ jsxs(
|
|
1484
|
+
pending && /* @__PURE__ */ jsxs(Collapsible, { children: [/* @__PURE__ */ jsx(CollapsibleTrigger, {
|
|
1485
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
1486
|
+
variant: "ghost",
|
|
1487
|
+
type: "button"
|
|
1488
|
+
}),
|
|
1489
|
+
children: "查看保留的修改"
|
|
1490
|
+
}), /* @__PURE__ */ jsx(CollapsibleContent, { children: pending.map((mutation) => /* @__PURE__ */ jsxs("p", { children: [
|
|
1347
1491
|
snapshot.base.tables.find((t) => t.id === mutation.tableId)?.name,
|
|
1348
|
-
" ·
|
|
1492
|
+
" ·",
|
|
1493
|
+
" ",
|
|
1349
1494
|
mutation.type === "delete" ? "删除记录" : Object.entries(mutation.values).map(([id, value]) => `${snapshot.base.tables.find((t) => t.id === mutation.tableId)?.fields.find((f) => f.id === id)?.name ?? id}:${displayValue(value)}`).join(";")
|
|
1350
|
-
] }, `${mutation.tableId}/${mutation.id}`))] }),
|
|
1351
|
-
/* @__PURE__ */ jsx(
|
|
1495
|
+
] }, `${mutation.tableId}/${mutation.id}`)) })] }),
|
|
1496
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1497
|
+
variant: "ghost",
|
|
1498
|
+
size: "sm",
|
|
1499
|
+
type: "button",
|
|
1352
1500
|
onClick: () => void refresh(),
|
|
1353
1501
|
children: "刷新数据"
|
|
1354
1502
|
}),
|
|
1355
|
-
pending && /* @__PURE__ */ jsx(
|
|
1503
|
+
pending && /* @__PURE__ */ jsx(Button, {
|
|
1504
|
+
variant: "ghost",
|
|
1505
|
+
size: "sm",
|
|
1506
|
+
type: "button",
|
|
1356
1507
|
onClick: () => {
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1508
|
+
setConfirmation({
|
|
1509
|
+
title: "核对后重新提交",
|
|
1510
|
+
description: "请确认已核对其他人的修改。将把保留的字段值提交到当前最新版本。",
|
|
1511
|
+
action: () => {
|
|
1512
|
+
const latest = snapshotRef.current;
|
|
1513
|
+
commit(pending.map((m) => m.type === "create" ? m : {
|
|
1514
|
+
...m,
|
|
1515
|
+
expectedVersion: latest.records[m.tableId]?.find((r) => r.id === m.id)?.version ?? m.expectedVersion
|
|
1516
|
+
}));
|
|
1517
|
+
}
|
|
1518
|
+
});
|
|
1363
1519
|
},
|
|
1364
1520
|
children: "核对后重新提交"
|
|
1365
1521
|
}),
|
|
1366
|
-
/* @__PURE__ */ jsx(
|
|
1522
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1523
|
+
variant: "ghost",
|
|
1524
|
+
size: "sm",
|
|
1525
|
+
type: "button",
|
|
1367
1526
|
"aria-label": "关闭错误提示",
|
|
1368
1527
|
onClick: () => setError(""),
|
|
1369
1528
|
children: /* @__PURE__ */ jsx(X, { size: 15 })
|
|
1370
1529
|
})
|
|
1371
1530
|
]
|
|
1372
1531
|
}),
|
|
1373
|
-
Object.keys(snapshot.errors).length > 0 && /* @__PURE__ */ jsxs(
|
|
1532
|
+
Object.keys(snapshot.errors).length > 0 && /* @__PURE__ */ jsxs(Alert, {
|
|
1374
1533
|
className: "sg-error",
|
|
1375
1534
|
children: [
|
|
1376
1535
|
/* @__PURE__ */ jsx(Braces, { size: 16 }),
|
|
1377
1536
|
"有 ",
|
|
1378
1537
|
Object.keys(snapshot.errors).length,
|
|
1379
1538
|
" 个计算字段错误,请检查公式与引用。",
|
|
1380
|
-
/* @__PURE__ */ jsx(
|
|
1539
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1540
|
+
variant: "ghost",
|
|
1541
|
+
size: "sm",
|
|
1542
|
+
type: "button",
|
|
1381
1543
|
onClick: () => setSchemaOpen(true),
|
|
1382
1544
|
children: "检查字段"
|
|
1383
1545
|
})
|
|
1384
1546
|
]
|
|
1385
1547
|
}),
|
|
1386
|
-
/* @__PURE__ */ jsxs(
|
|
1548
|
+
/* @__PURE__ */ jsxs(TabsContent, {
|
|
1549
|
+
value: view.id,
|
|
1387
1550
|
className: `sg-content sg-content-${view.type}`,
|
|
1388
1551
|
children: [
|
|
1389
1552
|
view.type === "grid" && (view.groupBy ? [...groups].map(([name, records]) => grid(records, name)) : grid(rows)),
|
|
1390
1553
|
view.type === "kanban" && board(),
|
|
1391
|
-
view.type === "form" && /* @__PURE__ */ jsxs(
|
|
1554
|
+
view.type === "form" && /* @__PURE__ */ jsxs(Card, {
|
|
1392
1555
|
className: "sg-form-page",
|
|
1393
1556
|
children: [
|
|
1394
1557
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -1418,7 +1581,7 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1418
1581
|
}),
|
|
1419
1582
|
view.type === "dashboard" && /* @__PURE__ */ jsxs("div", {
|
|
1420
1583
|
className: "sg-dashboard",
|
|
1421
|
-
children: [/* @__PURE__ */ jsxs(
|
|
1584
|
+
children: [/* @__PURE__ */ jsxs(Card, {
|
|
1422
1585
|
className: "sg-metric",
|
|
1423
1586
|
children: [
|
|
1424
1587
|
/* @__PURE__ */ jsx("small", { children: "匹配记录" }),
|
|
@@ -1427,7 +1590,7 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1427
1590
|
]
|
|
1428
1591
|
}), table.fields.filter((f) => f.type === "number" || f.type === "rollup" || f.type === "formula").map((f) => {
|
|
1429
1592
|
const stats = summarize(rows, f.id);
|
|
1430
|
-
return /* @__PURE__ */ jsxs(
|
|
1593
|
+
return /* @__PURE__ */ jsxs(Card, {
|
|
1431
1594
|
className: "sg-metric",
|
|
1432
1595
|
children: [
|
|
1433
1596
|
/* @__PURE__ */ jsxs("small", { children: [f.name, " · 合计"] }),
|
|
@@ -1463,10 +1626,54 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1463
1626
|
})
|
|
1464
1627
|
]
|
|
1465
1628
|
}),
|
|
1466
|
-
|
|
1629
|
+
newTable && /* @__PURE__ */ jsx(Modal, {
|
|
1630
|
+
title: "新增数据表",
|
|
1631
|
+
close: () => setNewTable(false),
|
|
1632
|
+
error,
|
|
1633
|
+
children: /* @__PURE__ */ jsxs("form", {
|
|
1634
|
+
className: "sg-record-form",
|
|
1635
|
+
onSubmit: async (event) => {
|
|
1636
|
+
event.preventDefault();
|
|
1637
|
+
if (!newTableName.trim()) return;
|
|
1638
|
+
const id = `t_${crypto.randomUUID().slice(0, 8)}`, base = structuredClone(snapshot.base);
|
|
1639
|
+
base.tables.push({
|
|
1640
|
+
id,
|
|
1641
|
+
name: newTableName.trim(),
|
|
1642
|
+
fields: [{
|
|
1643
|
+
id: "name",
|
|
1644
|
+
name: "名称",
|
|
1645
|
+
type: "text",
|
|
1646
|
+
required: true
|
|
1647
|
+
}],
|
|
1648
|
+
views: [{
|
|
1649
|
+
id: "grid",
|
|
1650
|
+
name: "全部记录",
|
|
1651
|
+
type: "grid"
|
|
1652
|
+
}]
|
|
1653
|
+
});
|
|
1654
|
+
if (await configure(base)) {
|
|
1655
|
+
setTableId(id);
|
|
1656
|
+
setNewTable(false);
|
|
1657
|
+
}
|
|
1658
|
+
},
|
|
1659
|
+
children: [/* @__PURE__ */ jsxs(Label, { children: ["数据表名称", /* @__PURE__ */ jsx(Input, {
|
|
1660
|
+
"aria-label": "数据表名称",
|
|
1661
|
+
required: true,
|
|
1662
|
+
maxLength: 200,
|
|
1663
|
+
value: newTableName,
|
|
1664
|
+
onChange: (event) => setNewTableName(event.target.value)
|
|
1665
|
+
})] }), /* @__PURE__ */ jsx("footer", { children: /* @__PURE__ */ jsx(Button, {
|
|
1666
|
+
type: "submit",
|
|
1667
|
+
disabled: busy,
|
|
1668
|
+
children: "创建数据表"
|
|
1669
|
+
}) })]
|
|
1670
|
+
})
|
|
1671
|
+
}),
|
|
1672
|
+
!record && confirmationDialog,
|
|
1673
|
+
record && /* @__PURE__ */ jsxs(Modal, {
|
|
1467
1674
|
title: record === "new" ? `新增${table.name}记录` : "记录详情",
|
|
1468
1675
|
close: () => setRecord(void 0),
|
|
1469
|
-
children: /* @__PURE__ */ jsx(RecordForm, {
|
|
1676
|
+
children: [/* @__PURE__ */ jsx(RecordForm, {
|
|
1470
1677
|
table,
|
|
1471
1678
|
row: record === "new" ? void 0 : record,
|
|
1472
1679
|
snapshot,
|
|
@@ -1489,16 +1696,22 @@ function MultiTableApp({ endpoint = "/api/multitable", client: suppliedClient })
|
|
|
1489
1696
|
return success;
|
|
1490
1697
|
},
|
|
1491
1698
|
onDelete: record === "new" ? void 0 : () => {
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1699
|
+
setConfirmation({
|
|
1700
|
+
title: "删除记录",
|
|
1701
|
+
description: "确认删除此记录?被其他记录引用时会拒绝删除。",
|
|
1702
|
+
action: () => {
|
|
1703
|
+
commit([{
|
|
1704
|
+
type: "delete",
|
|
1705
|
+
tableId: table.id,
|
|
1706
|
+
id: record.id,
|
|
1707
|
+
expectedVersion: record.version
|
|
1708
|
+
}]).then((ok) => {
|
|
1709
|
+
if (ok) setRecord(void 0);
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1499
1712
|
});
|
|
1500
1713
|
}
|
|
1501
|
-
}, record === "new" ? "new" : record.id)
|
|
1714
|
+
}, record === "new" ? "new" : record.id), confirmationDialog]
|
|
1502
1715
|
}),
|
|
1503
1716
|
schemaOpen && /* @__PURE__ */ jsx(SchemaEditor, {
|
|
1504
1717
|
snapshot,
|