@object-ui/app-shell 11.3.0 → 11.4.0
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/CHANGELOG.md +522 -0
- package/README.md +23 -0
- package/dist/console/ConsoleShell.js +17 -2
- package/dist/console/home/CloudOnboardingNext.d.ts +9 -0
- package/dist/console/home/CloudOnboardingNext.js +14 -4
- package/dist/console/home/HomePage.js +34 -7
- package/dist/console/organizations/CreateWorkspaceDialog.js +33 -3
- package/dist/console/organizations/OrganizationsPage.js +16 -7
- package/dist/hooks/useConsoleActionRuntime.js +32 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/preview/DraftChangesPanel.d.ts +3 -1
- package/dist/preview/DraftChangesPanel.js +6 -5
- package/dist/utils/deriveRelatedLists.d.ts +20 -5
- package/dist/utils/deriveRelatedLists.js +31 -13
- package/dist/utils/resolveViewId.d.ts +23 -0
- package/dist/utils/resolveViewId.js +37 -0
- package/dist/utils/warnSuppressedListNav.d.ts +10 -0
- package/dist/utils/warnSuppressedListNav.js +40 -0
- package/dist/views/InterfaceListPage.js +6 -4
- package/dist/views/ObjectView.js +61 -10
- package/dist/views/RecordDetailView.js +131 -104
- package/dist/views/RecordFormPage.js +7 -1
- package/dist/views/RelatedRecordActionsBridge.d.ts +24 -0
- package/dist/views/RelatedRecordActionsBridge.js +114 -0
- package/dist/views/metadata-admin/PackagesPage.js +18 -7
- package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +18 -1
- package/dist/views/metadata-admin/PermissionMatrixEditor.js +73 -14
- package/dist/views/metadata-admin/i18n.d.ts +12 -21
- package/dist/views/metadata-admin/i18n.js +343 -2
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +25 -11
- package/dist/views/metadata-admin/permission-slice.d.ts +66 -0
- package/dist/views/metadata-admin/permission-slice.js +70 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.js +11 -7
- package/dist/views/metadata-admin/previews/FlowRunsPanel.d.ts +16 -7
- package/dist/views/metadata-admin/previews/FlowRunsPanel.js +18 -2
- package/dist/views/studio-design/BuilderLanding.d.ts +15 -0
- package/dist/views/studio-design/BuilderLanding.js +133 -0
- package/dist/views/studio-design/ObjectFormDesigner.d.ts +31 -0
- package/dist/views/studio-design/ObjectFormDesigner.js +226 -0
- package/dist/views/studio-design/ObjectSettingsPanel.d.ts +30 -0
- package/dist/views/studio-design/ObjectSettingsPanel.js +45 -0
- package/dist/views/studio-design/ObjectValidationsPanel.d.ts +30 -0
- package/dist/views/studio-design/ObjectValidationsPanel.js +78 -0
- package/dist/views/studio-design/StudioDesignSurface.js +793 -146
- package/dist/views/studio-design/metadataError.d.ts +23 -0
- package/dist/views/studio-design/metadataError.js +44 -0
- package/dist/views/studio-design/packages-io.d.ts +27 -0
- package/dist/views/studio-design/packages-io.js +61 -0
- package/package.json +42 -39
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectUI
|
|
4
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Data pillar — Validations view (builder-ui Phase B).
|
|
11
|
+
*
|
|
12
|
+
* Edits `ObjectSchema.validations` (spec `ValidationRuleSchema`, a
|
|
13
|
+
* discriminated union on `type`). The no-code surface targets the `script`
|
|
14
|
+
* rule — `{ type: 'script', name, message, condition }` where the CEL
|
|
15
|
+
* `condition` is a FAIL predicate (TRUE ⇒ the write is rejected with
|
|
16
|
+
* `message`). The condition editor reuses the metadata-admin
|
|
17
|
+
* `ConditionBuilder`, fed with the DRAFT field list so unpublished fields
|
|
18
|
+
* are pickable.
|
|
19
|
+
*
|
|
20
|
+
* Non-`script` rule types (state_machine / format / cross_field / json /
|
|
21
|
+
* conditional) are surfaced read-only with their type badge — they carry
|
|
22
|
+
* structures a row editor can't honestly express; authoring them stays in
|
|
23
|
+
* code for now. Showing them (rather than hiding) keeps the list a truthful
|
|
24
|
+
* inventory of everything that will run on save.
|
|
25
|
+
*/
|
|
26
|
+
import React from 'react';
|
|
27
|
+
import { Plus, Trash2, ShieldAlert } from 'lucide-react';
|
|
28
|
+
import { ConditionBuilder } from '../metadata-admin/inspectors/ConditionBuilder';
|
|
29
|
+
import { readFields } from '../metadata-admin/previews/object-fields-io';
|
|
30
|
+
function readRules(input) {
|
|
31
|
+
if (!Array.isArray(input))
|
|
32
|
+
return [];
|
|
33
|
+
return input.filter((r) => !!r && typeof r === 'object');
|
|
34
|
+
}
|
|
35
|
+
function nextRuleName(existing) {
|
|
36
|
+
let i = existing.length + 1;
|
|
37
|
+
let name = `validation_${i}`;
|
|
38
|
+
const taken = new Set(existing);
|
|
39
|
+
while (taken.has(name))
|
|
40
|
+
name = `validation_${++i}`;
|
|
41
|
+
return name;
|
|
42
|
+
}
|
|
43
|
+
export function ObjectValidationsPanel({ draft, onPatch, disabled, }) {
|
|
44
|
+
const rules = readRules(draft.validations);
|
|
45
|
+
const [selected, setSelected] = React.useState(null);
|
|
46
|
+
const fields = React.useMemo(() => readFields(draft.fields).entries.map((e) => ({
|
|
47
|
+
name: e.name,
|
|
48
|
+
label: typeof e.def.label === 'string' ? e.def.label : undefined,
|
|
49
|
+
hidden: e.def.hidden === true,
|
|
50
|
+
})), [draft.fields]);
|
|
51
|
+
const commit = (next) => onPatch({ validations: next });
|
|
52
|
+
const patchRule = (name, patch) => commit(rules.map((r) => (r.name === name ? { ...r, ...patch } : r)));
|
|
53
|
+
const addRule = () => {
|
|
54
|
+
const name = nextRuleName(rules.map((r) => r.name ?? ''));
|
|
55
|
+
// `condition: 'false'` — a VALID never-failing CEL placeholder. An empty
|
|
56
|
+
// condition is rejected by the spec's ExpressionInputSchema, which would
|
|
57
|
+
// 422 the whole draft save and dead-end the create flow (the same
|
|
58
|
+
// required-field-blocks-authoring class as dashboard `layout` / page
|
|
59
|
+
// `regions`). A rule that never fires is safe to save mid-authoring.
|
|
60
|
+
commit([...rules, { type: 'script', name, message: '', condition: 'false', severity: 'error' }]);
|
|
61
|
+
setSelected(name);
|
|
62
|
+
};
|
|
63
|
+
const removeRule = (name) => {
|
|
64
|
+
commit(rules.filter((r) => r.name !== name));
|
|
65
|
+
if (selected === name)
|
|
66
|
+
setSelected(null);
|
|
67
|
+
};
|
|
68
|
+
const sel = rules.find((r) => r.name === selected) ?? null;
|
|
69
|
+
return (_jsxs("div", { className: "flex min-h-0 flex-1 gap-4", children: [_jsxs("div", { className: "flex w-72 shrink-0 flex-col rounded-lg border", children: [_jsxs("header", { className: "flex items-center gap-2 border-b px-3 py-2", children: [_jsx(ShieldAlert, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-[13px] font-medium", children: "\u9A8C\u8BC1\u89C4\u5219" }), _jsxs("span", { className: "text-[11px] text-muted-foreground", children: ["(", rules.length, ")"] }), !disabled && (_jsxs("button", { type: "button", onClick: addRule, className: "ml-auto inline-flex items-center gap-1 rounded border px-1.5 py-0.5 text-[11px] hover:bg-muted", children: [_jsx(Plus, { className: "h-3 w-3" }), " \u65B0\u589E"] }))] }), _jsx("div", { className: "min-h-0 flex-1 overflow-auto", children: rules.length === 0 ? (_jsxs("p", { className: "px-3 py-6 text-center text-[11px] leading-5 text-muted-foreground", children: ["\u8FD8\u6CA1\u6709\u9A8C\u8BC1\u89C4\u5219\u3002", _jsx("br", {}), "\u89C4\u5219\u5728\u4FDD\u5B58\u8BB0\u5F55\u65F6\u6267\u884C:\u6761\u4EF6\u4E3A\u771F \u21D2 \u62D2\u7EDD\u4FDD\u5B58\u5E76\u63D0\u793A\u6D88\u606F\u3002"] })) : (rules.map((r) => (_jsxs("button", { type: "button", onClick: () => setSelected(r.name ?? null), className: 'flex w-full items-start gap-2 border-b px-3 py-2 text-left text-[12px] ' +
|
|
70
|
+
(selected === r.name ? 'bg-muted' : 'hover:bg-muted/50'), children: [_jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate font-medium", children: r.label || r.name }), _jsx("span", { className: "block truncate text-[11px] text-muted-foreground", children: r.message || '(无消息)' })] }), _jsx("span", { className: 'shrink-0 rounded-full px-1.5 py-0.5 text-[10px] ' +
|
|
71
|
+
(r.type === 'script'
|
|
72
|
+
? 'bg-primary/10 text-primary'
|
|
73
|
+
: 'bg-muted text-muted-foreground'), children: r.type ?? 'script' })] }, r.name)))) })] }), _jsx("div", { className: "flex min-w-0 flex-1 flex-col rounded-lg border", children: !sel ? (_jsx("div", { className: "flex flex-1 items-center justify-center p-6 text-center text-[12px] text-muted-foreground", children: "\u9009\u62E9\u5DE6\u4FA7\u7684\u89C4\u5219\u8FDB\u884C\u7F16\u8F91,\u6216\u70B9\u300C\u65B0\u589E\u300D\u521B\u5EFA\u4E00\u6761\u3002" })) : sel.type !== 'script' ? (_jsxs("div", { className: "flex flex-1 flex-col gap-2 p-4", children: [_jsxs("p", { className: "text-[13px] font-medium", children: [sel.label || sel.name, _jsx("span", { className: "ml-2 rounded-full bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground", children: sel.type })] }), _jsxs("p", { className: "text-[12px] leading-5 text-muted-foreground", children: ["\u300C", sel.type, "\u300D\u7C7B\u578B\u7684\u89C4\u5219\u5E26\u6709\u7ED3\u6784\u5316\u914D\u7F6E(\u72B6\u6001\u673A\u8F6C\u79FB\u8868 / \u683C\u5F0F\u7EA6\u675F\u7B49),\u6682\u4E0D\u652F\u6301\u5728\u6B64\u7F16\u8F91 \u2014\u2014 \u8BF7\u5728\u4EE3\u7801\u5305\u4E2D\u7EF4\u62A4\u3002\u6D88\u606F:", sel.message || '(无)'] }), !disabled && (_jsxs("button", { type: "button", onClick: () => removeRule(sel.name), className: "mt-auto inline-flex w-fit items-center gap-1 rounded border border-destructive/40 px-2 py-1 text-[11px] text-destructive hover:bg-destructive/10", children: [_jsx(Trash2, { className: "h-3 w-3" }), " \u5220\u9664\u89C4\u5219"] }))] })) : (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-auto p-4", children: [_jsxs("label", { className: "block", children: [_jsx("span", { className: "mb-1 block text-[11px] text-muted-foreground", children: "\u89C4\u5219\u540D(snake_case,\u552F\u4E00)" }), _jsx("input", { value: sel.name ?? '', disabled: disabled, onChange: (e) => {
|
|
74
|
+
const name = e.target.value;
|
|
75
|
+
patchRule(sel.name, { name });
|
|
76
|
+
setSelected(name);
|
|
77
|
+
}, className: "w-full rounded border bg-background px-2 py-1 text-[12px]" })] }), _jsxs("label", { className: "block", children: [_jsx("span", { className: "mb-1 block text-[11px] text-muted-foreground", children: "\u9519\u8BEF\u6D88\u606F(\u6821\u9A8C\u5931\u8D25\u65F6\u5C55\u793A\u7ED9\u7528\u6237)" }), _jsx("input", { value: sel.message ?? '', disabled: disabled, onChange: (e) => patchRule(sel.name, { message: e.target.value }), placeholder: "\u4F8B\u5982:\u5B8C\u6210\u65E5\u671F\u5728\u72B6\u6001\u4E3A\u5DF2\u5B8C\u6210\u65F6\u5FC5\u586B", className: "w-full rounded border bg-background px-2 py-1 text-[12px]" })] }), _jsxs("div", { children: [_jsxs("span", { className: "mb-1 block text-[11px] text-muted-foreground", children: ["\u5931\u8D25\u6761\u4EF6(CEL)\u2014\u2014 \u6761\u4EF6\u4E3A ", _jsx("b", { children: "\u771F" }), " \u65F6,\u62D2\u7EDD\u4FDD\u5B58\u5E76\u663E\u793A\u4E0A\u9762\u7684\u6D88\u606F;\u65B0\u89C4\u5219\u9ED8\u8BA4", ' ', _jsx("code", { className: "rounded bg-muted px-1", children: "false" }), "(\u6C38\u4E0D\u89E6\u53D1),\u8BF7\u6539\u4E3A\u771F\u5B9E\u6761\u4EF6"] }), _jsx(ConditionBuilder, { value: typeof sel.condition === 'string' ? sel.condition : '', onCommit: (cel) => patchRule(sel.name, { condition: cel }), fields: fields, disabled: disabled })] }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsxs("label", { className: "flex items-center gap-1.5 text-[12px]", children: [_jsx("span", { className: "text-muted-foreground", children: "\u4E25\u91CD\u5EA6" }), _jsxs("select", { value: sel.severity ?? 'error', disabled: disabled, onChange: (e) => patchRule(sel.name, { severity: e.target.value }), className: "rounded border bg-background px-1.5 py-0.5 text-[12px]", children: [_jsx("option", { value: "error", children: "error(\u62D2\u7EDD\u4FDD\u5B58)" }), _jsx("option", { value: "warning", children: "warning" }), _jsx("option", { value: "info", children: "info" })] })] }), _jsxs("label", { className: "flex items-center gap-1.5 text-[12px]", children: [_jsx("input", { type: "checkbox", checked: sel.active !== false, disabled: disabled, onChange: (e) => patchRule(sel.name, { active: e.target.checked }) }), "\u542F\u7528"] }), !disabled && (_jsxs("button", { type: "button", onClick: () => removeRule(sel.name), className: "ml-auto inline-flex items-center gap-1 rounded border border-destructive/40 px-2 py-1 text-[11px] text-destructive hover:bg-destructive/10", children: [_jsx(Trash2, { className: "h-3 w-3" }), " \u5220\u9664"] }))] })] })) })] }));
|
|
78
|
+
}
|