@nocobase/client-v2 2.2.0-beta.1 → 2.2.0-beta.10
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/es/BaseApplication.d.ts +3 -0
- package/es/PluginSettingsManager.d.ts +33 -0
- package/es/RouteRepository.d.ts +29 -6
- package/es/RouterManager.d.ts +15 -0
- package/es/authRedirect.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterface.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +1 -0
- package/es/components/form/JsonTextArea.d.ts +2 -1
- package/es/components/form/VariableJsonTextArea.d.ts +19 -0
- package/es/components/form/index.d.ts +1 -0
- package/es/components/index.d.ts +1 -0
- package/es/entry-actions/EntryActionManager.d.ts +24 -0
- package/es/entry-actions/index.d.ts +9 -0
- package/es/flow/actions/afterSuccess.d.ts +8 -1
- package/es/flow/actions/index.d.ts +1 -1
- package/es/flow/admin-shell/BaseLayoutModel.d.ts +6 -0
- package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +7 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +2 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.d.ts +2 -1
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +2 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.d.ts +3 -2
- package/es/flow/admin-shell/admin-layout/AdminLayoutSlotModels.d.ts +5 -0
- package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +2 -1
- package/es/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.d.ts +24 -0
- package/es/flow/admin-shell/admin-layout/index.d.ts +1 -0
- package/es/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.d.ts +6 -0
- package/es/flow/admin-shell/admin-layout/useApplications.d.ts +7 -2
- package/es/flow/components/FieldAssignRulesEditor.d.ts +3 -1
- package/es/flow/models/base/ActionModelCore.d.ts +2 -0
- package/es/flow/models/base/GridModel.d.ts +1 -1
- package/es/flow/models/blocks/filter-form/FilterFormBlockModel.d.ts +5 -0
- package/es/flow/models/blocks/form/FormBlockModel.d.ts +4 -0
- package/es/flow/models/blocks/form/QuickEditFormModel.d.ts +17 -2
- package/es/flow/models/blocks/form/submitHandler.d.ts +1 -1
- package/es/flow/models/blocks/form/value-runtime/rules.d.ts +21 -0
- package/es/flow/models/blocks/form/value-runtime/runtime.d.ts +30 -0
- package/es/flow/models/blocks/form/value-runtime/types.d.ts +2 -2
- package/es/flow/models/blocks/js-block/JSBlock.d.ts +1 -0
- package/es/flow/models/blocks/table/TableActionsColumnModel.d.ts +1 -0
- package/es/flow/models/blocks/table/TableBlockModel.d.ts +1 -0
- package/es/flow/models/blocks/table/dragSort/dragSortHooks.d.ts +1 -1
- package/es/flow/models/blocks/table/dragSort/dragSortSettings.d.ts +2 -1
- package/es/flow/models/blocks/table/dragSort/dragSortUtils.d.ts +6 -4
- package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +2 -0
- package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.d.ts +6 -0
- package/es/flow/resolveViewParamsToViewList.d.ts +1 -1
- package/es/flow/routeTransientInputArgs.d.ts +14 -0
- package/es/flow/utils/dataScopeRowSnapshot.d.ts +59 -0
- package/es/flow/utils/dateTimeDisplayProps.d.ts +49 -0
- package/es/flow/utils/formValueDeps.d.ts +32 -0
- package/es/flow-compat/FieldValidation.d.ts +2 -1
- package/es/index.d.ts +4 -1
- package/es/index.mjs +305 -157
- package/es/utils/markdownSanitize.d.ts +11 -0
- package/lib/index.js +305 -157
- package/package.json +7 -7
- package/src/BaseApplication.tsx +6 -0
- package/src/PluginSettingsManager.ts +53 -0
- package/src/RouteRepository.ts +151 -24
- package/src/RouterManager.tsx +142 -1
- package/src/__tests__/PluginSettingsManager.test.ts +13 -0
- package/src/__tests__/RouteRepository.test.ts +239 -0
- package/src/__tests__/RouterManager.test.ts +125 -0
- package/src/__tests__/authRedirect.test.ts +17 -0
- package/src/__tests__/exports.test.ts +16 -0
- package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +199 -0
- package/src/__tests__/plugin-manager.test.tsx +44 -2
- package/src/__tests__/settings-center.test.tsx +40 -1
- package/src/authRedirect.ts +38 -0
- package/src/collection-field-interface/CollectionFieldInterface.ts +1 -0
- package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +1 -0
- package/src/collection-manager/field-configure.ts +1 -1
- package/src/collection-manager/interfaces/id.ts +1 -1
- package/src/collection-manager/interfaces/m2m.tsx +2 -2
- package/src/collection-manager/interfaces/m2o.tsx +2 -2
- package/src/collection-manager/interfaces/nanoid.ts +1 -1
- package/src/collection-manager/interfaces/o2m.tsx +2 -2
- package/src/collection-manager/interfaces/obo.tsx +2 -2
- package/src/collection-manager/interfaces/oho.tsx +2 -2
- package/src/collection-manager/interfaces/properties/index.ts +2 -2
- package/src/collection-manager/interfaces/uuid.ts +1 -1
- package/src/components/AppComponents.tsx +19 -3
- package/src/components/form/JsonTextArea.tsx +21 -11
- package/src/components/form/VariableJsonTextArea.tsx +175 -0
- package/src/components/form/__tests__/JsonTextArea.test.tsx +43 -0
- package/src/components/form/__tests__/VariableJsonTextArea.test.tsx +86 -0
- package/src/components/form/index.tsx +1 -0
- package/src/components/index.ts +1 -0
- package/src/entry-actions/EntryActionManager.ts +76 -0
- package/src/entry-actions/index.ts +10 -0
- package/src/flow/FlowPage.tsx +38 -3
- package/src/flow/__tests__/FlowPage.test.tsx +201 -27
- package/src/flow/__tests__/FlowRoute.test.tsx +1088 -105
- package/src/flow/__tests__/getKey.test.ts +7 -0
- package/src/flow/__tests__/resolveViewParamsToViewList.test.ts +34 -0
- package/src/flow/actions/__tests__/afterSuccess.test.ts +73 -0
- package/src/flow/actions/__tests__/dataScopeFilter.test.ts +120 -0
- package/src/flow/actions/__tests__/dataScopeFormValueClear.test.ts +1022 -0
- package/src/flow/actions/__tests__/fieldLinkageRules.scopeDepth.test.ts +150 -1
- package/src/flow/actions/__tests__/linkageAssignField.legacy.test.ts +135 -0
- package/src/flow/actions/__tests__/linkageRules.hiddenSync.restore.test.ts +19 -5
- package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +92 -0
- package/src/flow/actions/__tests__/openView.defineProps.route.test.tsx +164 -0
- package/src/flow/actions/__tests__/subFormFieldLinkageRules.inputArgs.test.ts +2 -2
- package/src/flow/actions/afterSuccess.tsx +142 -3
- package/src/flow/actions/customVariable.tsx +1 -2
- package/src/flow/actions/dataScopeFilter.ts +20 -1
- package/src/flow/actions/dateTimeFormat.tsx +42 -28
- package/src/flow/actions/index.ts +1 -1
- package/src/flow/actions/linkageRules.tsx +123 -35
- package/src/flow/actions/linkageRulesFormValueRefresh.ts +22 -130
- package/src/flow/actions/openView.tsx +59 -5
- package/src/flow/actions/runjs.tsx +2 -14
- package/src/flow/actions/validation.tsx +62 -30
- package/src/flow/admin-shell/BaseLayoutModel.tsx +149 -3
- package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +187 -42
- package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +1020 -110
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +74 -13
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.test.tsx +486 -0
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +64 -8
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.ts +5 -3
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +61 -9
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +71 -8
- package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +1 -1
- package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +23 -9
- package/src/flow/admin-shell/admin-layout/AppListRender.tsx +13 -2
- package/src/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.tsx +289 -0
- package/src/flow/admin-shell/admin-layout/HelpLite.tsx +1 -3
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +188 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +99 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +518 -2
- package/src/flow/admin-shell/admin-layout/__tests__/TopbarActionsBar.test.tsx +214 -2
- package/src/flow/admin-shell/admin-layout/index.ts +1 -0
- package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.test.ts +20 -0
- package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.ts +33 -5
- package/src/flow/admin-shell/admin-layout/useApplications.tsx +81 -12
- package/src/flow/common/Markdown/Display.tsx +14 -3
- package/src/flow/common/Markdown/Edit.tsx +19 -7
- package/src/flow/components/DefaultValue.tsx +1 -2
- package/src/flow/components/DynamicFlowsIcon.tsx +447 -126
- package/src/flow/components/FieldAssignRulesEditor.tsx +128 -21
- package/src/flow/components/FieldAssignValueInput.tsx +15 -11
- package/src/flow/components/FlowRoute.tsx +186 -25
- package/src/flow/components/__tests__/DynamicFlowsIcon.test.tsx +148 -2
- package/src/flow/components/__tests__/FieldAssignRulesEditor.test.tsx +508 -4
- package/src/flow/components/__tests__/FieldAssignValueInput.context.test.tsx +134 -0
- package/src/flow/components/__tests__/fieldAssignOptions.test.ts +151 -3
- package/src/flow/components/code-editor/__tests__/useCodeRunner.test.tsx +2 -17
- package/src/flow/components/code-editor/hooks/useCodeRunner.ts +2 -14
- package/src/flow/components/code-editor/runjsDiagnostics.ts +8 -45
- package/src/flow/components/fieldAssignOptions.ts +155 -27
- package/src/flow/flows/editMarkdownFlow.tsx +1 -1
- package/src/flow/getViewDiffAndUpdateHidden.tsx +1 -0
- package/src/flow/index.ts +1 -1
- package/src/flow/internal/components/Markdown/util.ts +2 -1
- package/src/flow/internal/utils/operatorSchemaHelper.ts +15 -1
- package/src/flow/models/actions/JSActionModel.tsx +2 -7
- package/src/flow/models/actions/JSCollectionActionModel.tsx +2 -7
- package/src/flow/models/actions/JSItemActionModel.tsx +2 -7
- package/src/flow/models/actions/JSRecordActionModel.tsx +2 -7
- package/src/flow/models/base/ActionModel.tsx +21 -8
- package/src/flow/models/base/ActionModelCore.tsx +11 -4
- package/src/flow/models/base/GridModel.tsx +38 -7
- package/src/flow/models/base/PageModel/PageModel.tsx +4 -1
- package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +28 -4
- package/src/flow/models/base/__tests__/ActionModel.test.ts +83 -0
- package/src/flow/models/base/__tests__/ActionModelCore.render.test.tsx +37 -0
- package/src/flow/models/base/__tests__/GridModel.dragSnapshotContainer.test.ts +239 -1
- package/src/flow/models/base/__tests__/transformRowsToSingleColumn.test.ts +48 -0
- package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +32 -3
- package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +27 -12
- package/src/flow/models/blocks/filter-form/FilterFormJSActionModel.tsx +2 -7
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +36 -0
- package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +111 -0
- package/src/flow/models/blocks/filter-form/fields/FilterFormCustomFieldModel.tsx +1 -1
- package/src/flow/models/blocks/filter-manager/flow-actions/__tests__/customizeFilterRender.test.tsx +56 -1
- package/src/flow/models/blocks/form/EditFormModel.tsx +1 -0
- package/src/flow/models/blocks/form/FormActionModel.tsx +1 -1
- package/src/flow/models/blocks/form/FormBlockModel.tsx +7 -0
- package/src/flow/models/blocks/form/JSFormActionModel.tsx +2 -7
- package/src/flow/models/blocks/form/QuickEditFormModel.tsx +189 -36
- package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +17 -0
- package/src/flow/models/blocks/form/__tests__/QuickEditFormModel.quickEdit.test.ts +350 -2
- package/src/flow/models/blocks/form/__tests__/submitHandler.test.ts +54 -1
- package/src/flow/models/blocks/form/submitHandler.ts +17 -3
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +940 -75
- package/src/flow/models/blocks/form/value-runtime/rules.ts +445 -13
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +348 -13
- package/src/flow/models/blocks/form/value-runtime/types.ts +2 -2
- package/src/flow/models/blocks/js-block/JSBlock.tsx +225 -9
- package/src/flow/models/blocks/js-block/__tests__/JSBlockModel.test.tsx +150 -0
- package/src/flow/models/blocks/table/JSColumnModel.tsx +1 -9
- package/src/flow/models/blocks/table/TableActionsColumnModel.tsx +36 -13
- package/src/flow/models/blocks/table/TableBlockModel.tsx +38 -17
- package/src/flow/models/blocks/table/TableColumnModel.tsx +42 -5
- package/src/flow/models/blocks/table/__tests__/TableActionsColumnModel.test.tsx +111 -1
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.dragSort.test.ts +127 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.mobileSettingsButtons.test.tsx +78 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.rowSelection.test.tsx +1 -0
- package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +210 -1
- package/src/flow/models/blocks/table/dragSort/dragSortHooks.tsx +28 -17
- package/src/flow/models/blocks/table/dragSort/dragSortSettings.ts +13 -6
- package/src/flow/models/blocks/table/dragSort/dragSortUtils.ts +15 -2
- package/src/flow/models/fields/AssociationFieldModel/AssociationFieldModel.tsx +1 -1
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +30 -6
- package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +61 -17
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.tsx +141 -19
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +13 -1
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableColumnModel.rowRecord.test.ts +197 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableFieldModel.reset.test.ts +180 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -4
- package/src/flow/models/fields/AssociationFieldModel/__tests__/AssociationFieldModel.updateAssociation.test.ts +72 -0
- package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +23 -0
- package/src/flow/models/fields/ClickableFieldModel.tsx +5 -0
- package/src/flow/models/fields/DisplayDateTimeFieldModel.tsx +29 -1
- package/src/flow/models/fields/InputFieldModel.tsx +40 -2
- package/src/flow/models/fields/JSEditableFieldModel.tsx +2 -11
- package/src/flow/models/fields/JSFieldModel.tsx +2 -7
- package/src/flow/models/fields/JSItemModel.tsx +2 -14
- package/src/flow/models/fields/SelectFieldModel.tsx +6 -4
- package/src/flow/models/fields/TextareaFieldModel.tsx +72 -3
- package/src/flow/models/fields/__tests__/DisplayDateTimeFieldModel.test.tsx +96 -0
- package/src/flow/models/fields/__tests__/InputFieldModel.test.tsx +117 -1
- package/src/flow/models/fields/__tests__/SelectFieldModel.test.tsx +43 -0
- package/src/flow/models/fields/__tests__/TextareaFieldModel.test.tsx +131 -0
- package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +20 -10
- package/src/flow/models/fields/mobile-components/MobileSelect.tsx +24 -12
- package/src/flow/models/topbar/TopbarActionModel.tsx +168 -10
- package/src/flow/resolveViewParamsToViewList.tsx +11 -3
- package/src/flow/routeTransientInputArgs.ts +27 -0
- package/src/flow/utils/__tests__/dateTimeFormat.test.ts +300 -0
- package/src/flow/utils/dataScopeFormValueClear.ts +218 -81
- package/src/flow/utils/dataScopeRowSnapshot.ts +616 -0
- package/src/flow/utils/dateTimeDisplayProps.ts +135 -0
- package/src/flow/utils/formValueDeps.ts +170 -0
- package/src/flow-compat/FieldValidation.tsx +122 -60
- package/src/flow-compat/Popover.tsx +43 -4
- package/src/flow-compat/__tests__/Popover.test.tsx +34 -0
- package/src/index.ts +10 -1
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +41 -1
- package/src/nocobase-buildin-plugin/index.tsx +51 -15
- package/src/settings-center/AdminSettingsLayout.tsx +10 -2
- package/src/settings-center/SystemSettingsPage.tsx +1 -2
- package/src/settings-center/plugin-manager/PluginCard.tsx +2 -2
- package/src/settings-center/plugin-manager/index.tsx +3 -0
- package/src/settings-center/utils.tsx +0 -6
- package/src/utils/markdownSanitize.ts +88 -0
|
@@ -210,7 +210,7 @@ FilterFormCustomFieldModel.registerFlow({
|
|
|
210
210
|
'x-decorator': 'FormItem',
|
|
211
211
|
required: true,
|
|
212
212
|
description:
|
|
213
|
-
'{{t("Randomly generated and can be modified. Support letters, numbers and underscores, must start with
|
|
213
|
+
'{{t("Randomly generated and can be modified. Support letters, numbers and underscores, must start with a letter.")}}',
|
|
214
214
|
},
|
|
215
215
|
source: {
|
|
216
216
|
type: 'array',
|
package/src/flow/models/blocks/filter-manager/flow-actions/__tests__/customizeFilterRender.test.tsx
CHANGED
|
@@ -18,12 +18,23 @@ type TestFieldModel = {
|
|
|
18
18
|
setupReactiveRender: ReturnType<typeof vi.fn>;
|
|
19
19
|
_reactiveWrapperCache?: unknown;
|
|
20
20
|
__originalRender?: () => React.ReactNode;
|
|
21
|
+
translate?: (text: string) => string;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
const MultipleKeywordsInput = (props: Record<string, unknown>) => {
|
|
24
25
|
return <div data-testid="multiple-keywords-input" {...props} />;
|
|
25
26
|
};
|
|
26
27
|
|
|
28
|
+
const Select = (props: Record<string, unknown>) => {
|
|
29
|
+
return <div data-testid="select" {...props} />;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function mockT(text: string) {
|
|
33
|
+
if (text === '{{t("Yes")}}') return '是';
|
|
34
|
+
if (text === '{{t("No")}}') return '否';
|
|
35
|
+
return text;
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
function createFieldModel() {
|
|
28
39
|
return {
|
|
29
40
|
props: {
|
|
@@ -52,7 +63,10 @@ function createFilterItemModel({
|
|
|
52
63
|
collectionField,
|
|
53
64
|
context: {
|
|
54
65
|
app: {
|
|
55
|
-
getComponent: (name: string) =>
|
|
66
|
+
getComponent: (name: string) => {
|
|
67
|
+
if (name === 'MultipleKeywordsInput') return MultipleKeywordsInput;
|
|
68
|
+
if (name === 'Select') return Select;
|
|
69
|
+
},
|
|
56
70
|
},
|
|
57
71
|
collectionField,
|
|
58
72
|
},
|
|
@@ -112,6 +126,47 @@ describe('customizeFilterRender action', () => {
|
|
|
112
126
|
expect((rerenderedElement as React.ReactElement).props.placeholder).toBe('updated runtime placeholder');
|
|
113
127
|
});
|
|
114
128
|
|
|
129
|
+
it('translates operator schema select options', () => {
|
|
130
|
+
const fieldModel = {
|
|
131
|
+
...createFieldModel(),
|
|
132
|
+
translate: mockT,
|
|
133
|
+
};
|
|
134
|
+
const model = createFilterItemModel({
|
|
135
|
+
fieldModel,
|
|
136
|
+
operator: '$isTruly',
|
|
137
|
+
collectionField: {
|
|
138
|
+
interface: 'checkbox',
|
|
139
|
+
type: 'boolean',
|
|
140
|
+
filterable: {
|
|
141
|
+
operators: [
|
|
142
|
+
{
|
|
143
|
+
label: '{{t("Yes")}}',
|
|
144
|
+
value: '$isTruly',
|
|
145
|
+
schema: {
|
|
146
|
+
'x-component': 'Select',
|
|
147
|
+
'x-component-props': {
|
|
148
|
+
options: [
|
|
149
|
+
{ label: '{{t("Yes")}}', value: true },
|
|
150
|
+
{ label: '{{t("No")}}', value: false },
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
customizeFilterRender.handler?.({ model } as any);
|
|
161
|
+
|
|
162
|
+
const element = fieldModel.render();
|
|
163
|
+
expect((element as React.ReactElement).type).toBe(Select);
|
|
164
|
+
expect((element as React.ReactElement).props.options).toEqual([
|
|
165
|
+
{ label: '是', value: true },
|
|
166
|
+
{ label: '否', value: false },
|
|
167
|
+
]);
|
|
168
|
+
});
|
|
169
|
+
|
|
115
170
|
it('restores original render when switching to an operator without a schema component', () => {
|
|
116
171
|
const fieldModel = createFieldModel();
|
|
117
172
|
const originalRender = fieldModel.render;
|
|
@@ -117,7 +117,7 @@ FormSubmitActionModel.registerFlow({
|
|
|
117
117
|
try {
|
|
118
118
|
ctx.model.setProps('loading', true);
|
|
119
119
|
const { submitHandler } = await import('./submitHandler');
|
|
120
|
-
await submitHandler(ctx, params);
|
|
120
|
+
return await submitHandler(ctx, params);
|
|
121
121
|
} catch (error) {
|
|
122
122
|
ctx.model.setProps('loading', false);
|
|
123
123
|
if (error instanceof FlowExitAllException) {
|
|
@@ -166,6 +166,13 @@ export class FormBlockModel<
|
|
|
166
166
|
this.userModifiedTopLevelFields.clear();
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* @internal
|
|
171
|
+
*/
|
|
172
|
+
resetRuntimeUserEditedState(): void {
|
|
173
|
+
this.formValueRuntime?.resetUserEditedState?.();
|
|
174
|
+
}
|
|
175
|
+
|
|
169
176
|
public async onDispatchEventStart(eventName: string, options?: any, inputArgs?: Record<string, any>): Promise<void> {
|
|
170
177
|
if (eventName === 'beforeRender') {
|
|
171
178
|
const grid = this.subModels.grid;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
/**
|
|
11
11
|
* JS Form Action:表单工具栏按钮点击执行 JS。
|
|
12
12
|
*/
|
|
13
|
-
import { tExpr
|
|
13
|
+
import { tExpr } from '@nocobase/flow-engine';
|
|
14
14
|
import { CodeEditor } from '../../../components/code-editor';
|
|
15
15
|
import { FormActionModel } from './FormActionModel';
|
|
16
16
|
import { resolveRunJsParams } from '../../utils/resolveRunJsParams';
|
|
@@ -73,12 +73,7 @@ ctx.message.success('Current form values: ' + JSON.stringify(values));
|
|
|
73
73
|
await ctx.resource.refresh();
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
|
-
|
|
77
|
-
await ctx.runjs(
|
|
78
|
-
code,
|
|
79
|
-
{ window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator },
|
|
80
|
-
{ version },
|
|
81
|
-
);
|
|
76
|
+
await ctx.runjs(code, undefined, { version });
|
|
82
77
|
},
|
|
83
78
|
},
|
|
84
79
|
},
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
createRecordResolveOnServerWithLocal,
|
|
23
23
|
} from '@nocobase/flow-engine';
|
|
24
24
|
import { Button, Form, Skeleton, Space } from 'antd';
|
|
25
|
-
import _ from 'lodash';
|
|
26
25
|
import React from 'react';
|
|
27
26
|
import { FieldModel } from '../../base/FieldModel';
|
|
28
27
|
import { FormComponent } from './FormBlockModel';
|
|
@@ -31,6 +30,37 @@ import { FormItemModel } from './FormItemModel';
|
|
|
31
30
|
export const QUICK_EDIT_POPOVER_MAX_HEIGHT = 'calc(100vh - 96px)';
|
|
32
31
|
export const QUICK_EDIT_FORM_MAX_HEIGHT = 'calc(100vh - 160px)';
|
|
33
32
|
export const QUICK_EDIT_MARKDOWN_HEIGHT = 'min(480px, calc(100vh - 320px))';
|
|
33
|
+
const QUICK_EDIT_MOBILE_DRAWER_HEIGHT = '50vh';
|
|
34
|
+
const QUICK_EDIT_MOBILE_FORM_MAX_HEIGHT = 'calc(50vh - var(--nb-mobile-page-header-height, 40px) - 132px)';
|
|
35
|
+
const QUICK_EDIT_MOBILE_CONTENT_PADDING = '8px var(--nb-mobile-page-tabs-content-padding, 12px) 0';
|
|
36
|
+
const QUICK_EDIT_MOBILE_ACTIONS_PADDING =
|
|
37
|
+
'8px var(--nb-mobile-page-tabs-content-padding, 12px) calc(80px + env(safe-area-inset-bottom, 0px))';
|
|
38
|
+
const QUICK_EDIT_MOBILE_MEDIA_QUERY = '(max-width: 768px)';
|
|
39
|
+
|
|
40
|
+
type QuickEditViewBeforeClosePayload = {
|
|
41
|
+
result?: unknown;
|
|
42
|
+
force?: boolean;
|
|
43
|
+
[key: string]: unknown;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type QuickEditViewBeforeCloseHandler = (
|
|
47
|
+
payload: QuickEditViewBeforeClosePayload,
|
|
48
|
+
) => Promise<boolean | void> | boolean | void;
|
|
49
|
+
|
|
50
|
+
type QuickEditViewUpdateConfig = {
|
|
51
|
+
preventClose?: boolean;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
type QuickEditViewContainer = {
|
|
56
|
+
close: (result?: unknown, force?: boolean) => Promise<boolean | void> | boolean | void;
|
|
57
|
+
update?: (newConfig: QuickEditViewUpdateConfig) => unknown;
|
|
58
|
+
beforeClose?: QuickEditViewBeforeCloseHandler;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
type QuickEditViewContext = {
|
|
62
|
+
defineProperty?: (key: string, options: { value: unknown }) => void;
|
|
63
|
+
};
|
|
34
64
|
|
|
35
65
|
export function getQuickEditFieldProps(collectionField: CollectionField, fieldProps?: Record<string, any>) {
|
|
36
66
|
const nextProps = { ...collectionField.getComponentProps(), ...(fieldProps || {}) };
|
|
@@ -40,15 +70,92 @@ export function getQuickEditFieldProps(collectionField: CollectionField, fieldPr
|
|
|
40
70
|
return nextProps;
|
|
41
71
|
}
|
|
42
72
|
|
|
73
|
+
function getQuickEditMobileLayoutState(flowEngine: FlowEngine, sourceFieldModel?: FlowModel) {
|
|
74
|
+
const sourceMobileLayout = sourceFieldModel?.context?.isMobileLayout;
|
|
75
|
+
if (typeof sourceMobileLayout === 'boolean') {
|
|
76
|
+
return { isMobileLayout: sourceMobileLayout, inheritsMobileContext: sourceMobileLayout };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const engineMobileLayout = flowEngine.context?.isMobileLayout;
|
|
80
|
+
if (typeof engineMobileLayout === 'boolean') {
|
|
81
|
+
return { isMobileLayout: engineMobileLayout, inheritsMobileContext: engineMobileLayout };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
|
|
85
|
+
return { isMobileLayout: false, inheritsMobileContext: false };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
isMobileLayout: window.matchMedia(QUICK_EDIT_MOBILE_MEDIA_QUERY).matches,
|
|
90
|
+
inheritsMobileContext: false,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function getQuickEditTitle(
|
|
95
|
+
flowEngine: FlowEngine,
|
|
96
|
+
dataSourceKey: string,
|
|
97
|
+
collectionName: string,
|
|
98
|
+
fieldPath: string,
|
|
99
|
+
sourceFieldModel?: FlowModel,
|
|
100
|
+
fieldProps?: Record<string, unknown>,
|
|
101
|
+
): React.ReactNode {
|
|
102
|
+
const sourceColumnTitle = sourceFieldModel?.parent?.props?.title;
|
|
103
|
+
if (sourceColumnTitle) {
|
|
104
|
+
return sourceColumnTitle;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const fieldPropsTitle = fieldProps?.title;
|
|
108
|
+
if (fieldPropsTitle) {
|
|
109
|
+
return fieldPropsTitle as React.ReactNode;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const collectionField = flowEngine.context.dataSourceManager.getCollectionField(
|
|
113
|
+
`${dataSourceKey}.${collectionName}.${fieldPath}`,
|
|
114
|
+
) as CollectionField | undefined;
|
|
115
|
+
return collectionField?.title || fieldPath;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function createQuickEditViewContainer(view: QuickEditViewContainer): QuickEditViewContainer {
|
|
119
|
+
let preventClose = false;
|
|
120
|
+
let nextBeforeClose = view.beforeClose;
|
|
121
|
+
const beforeClose: QuickEditViewBeforeCloseHandler = async (payload) => {
|
|
122
|
+
if (preventClose && !payload?.force) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const result = await nextBeforeClose?.(payload);
|
|
127
|
+
return result !== false;
|
|
128
|
+
};
|
|
129
|
+
view.beforeClose = beforeClose;
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
...view,
|
|
133
|
+
close(result, force) {
|
|
134
|
+
return view.close(result, force);
|
|
135
|
+
},
|
|
136
|
+
update(newConfig) {
|
|
137
|
+
if (Object.prototype.hasOwnProperty.call(newConfig, 'preventClose')) {
|
|
138
|
+
preventClose = !!newConfig.preventClose;
|
|
139
|
+
}
|
|
140
|
+
return view.update?.(newConfig);
|
|
141
|
+
},
|
|
142
|
+
get beforeClose() {
|
|
143
|
+
return view.beforeClose;
|
|
144
|
+
},
|
|
145
|
+
set beforeClose(value) {
|
|
146
|
+
nextBeforeClose = value;
|
|
147
|
+
view.beforeClose = beforeClose;
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
43
152
|
export class QuickEditFormModel extends FlowModel {
|
|
44
153
|
fieldPath: string;
|
|
45
154
|
|
|
46
155
|
declare resource: SingleRecordResource;
|
|
47
156
|
declare collection: Collection;
|
|
48
157
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
viewContainer: any;
|
|
158
|
+
declare viewContainer: QuickEditViewContainer;
|
|
52
159
|
__onSubmitSuccess;
|
|
53
160
|
_fieldProps: any;
|
|
54
161
|
_onOk: any;
|
|
@@ -89,21 +196,75 @@ export class QuickEditFormModel extends FlowModel {
|
|
|
89
196
|
onOk,
|
|
90
197
|
sourceFieldModelUid,
|
|
91
198
|
} = options;
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
199
|
+
const sourceFieldModel = sourceFieldModelUid ? flowEngine.getModel<FlowModel>(sourceFieldModelUid) : undefined;
|
|
200
|
+
const model = flowEngine.createModel(
|
|
201
|
+
{
|
|
202
|
+
use: 'QuickEditFormModel',
|
|
203
|
+
stepParams: {
|
|
204
|
+
quickEditFormSettings: {
|
|
205
|
+
init: {
|
|
206
|
+
dataSourceKey,
|
|
207
|
+
collectionName,
|
|
208
|
+
fieldPath,
|
|
209
|
+
},
|
|
100
210
|
},
|
|
101
211
|
},
|
|
102
212
|
},
|
|
103
|
-
|
|
213
|
+
sourceFieldModel ? { delegate: sourceFieldModel.context } : undefined,
|
|
214
|
+
) as QuickEditFormModel;
|
|
104
215
|
|
|
105
|
-
|
|
106
|
-
|
|
216
|
+
const bodyStyles = {
|
|
217
|
+
maxHeight: QUICK_EDIT_POPOVER_MAX_HEIGHT,
|
|
218
|
+
overflowY: 'auto',
|
|
219
|
+
overscrollBehavior: 'contain',
|
|
220
|
+
};
|
|
221
|
+
const mobileBodyStyles = {
|
|
222
|
+
...bodyStyles,
|
|
223
|
+
maxHeight: QUICK_EDIT_MOBILE_DRAWER_HEIGHT,
|
|
224
|
+
};
|
|
225
|
+
const content = (view: QuickEditViewContainer, viewContext?: QuickEditViewContext) => {
|
|
226
|
+
if (mobileLayoutState.isMobileLayout) {
|
|
227
|
+
viewContext?.defineProperty?.('isMobileLayout', { value: true });
|
|
228
|
+
}
|
|
229
|
+
model.viewContainer = createQuickEditViewContainer(view);
|
|
230
|
+
model.__onSubmitSuccess = onSuccess;
|
|
231
|
+
model._fieldProps = fieldProps;
|
|
232
|
+
model._onOk = onOk;
|
|
233
|
+
return (
|
|
234
|
+
<FlowModelRenderer
|
|
235
|
+
fallback={<Skeleton.Input size="small" />}
|
|
236
|
+
model={model}
|
|
237
|
+
inputArgs={{ filterByTk, record, sourceFieldModelUid }}
|
|
238
|
+
/>
|
|
239
|
+
);
|
|
240
|
+
};
|
|
241
|
+
const mobileLayoutState = getQuickEditMobileLayoutState(flowEngine, sourceFieldModel);
|
|
242
|
+
if (mobileLayoutState.isMobileLayout) {
|
|
243
|
+
model.context.defineProperty('isMobileLayout', { value: true });
|
|
244
|
+
const viewer = sourceFieldModel?.context?.viewer || flowEngine.context.viewer;
|
|
245
|
+
const title = getQuickEditTitle(
|
|
246
|
+
flowEngine,
|
|
247
|
+
dataSourceKey,
|
|
248
|
+
collectionName,
|
|
249
|
+
fieldPath,
|
|
250
|
+
sourceFieldModel,
|
|
251
|
+
fieldProps,
|
|
252
|
+
);
|
|
253
|
+
await viewer.open({
|
|
254
|
+
type: 'drawer',
|
|
255
|
+
title,
|
|
256
|
+
closable: true,
|
|
257
|
+
placement: 'bottom',
|
|
258
|
+
inputArgs: {
|
|
259
|
+
isMobileLayout: true,
|
|
260
|
+
},
|
|
261
|
+
styles: {
|
|
262
|
+
body: mobileBodyStyles,
|
|
263
|
+
},
|
|
264
|
+
content,
|
|
265
|
+
});
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
107
268
|
|
|
108
269
|
await flowEngine.context.viewer.open({
|
|
109
270
|
type: 'popover',
|
|
@@ -112,25 +273,10 @@ export class QuickEditFormModel extends FlowModel {
|
|
|
112
273
|
styles: {
|
|
113
274
|
body: {
|
|
114
275
|
width: 420,
|
|
115
|
-
|
|
116
|
-
overflowY: 'auto',
|
|
117
|
-
overscrollBehavior: 'contain',
|
|
276
|
+
...bodyStyles,
|
|
118
277
|
},
|
|
119
278
|
},
|
|
120
|
-
content
|
|
121
|
-
model.viewContainer = popover;
|
|
122
|
-
model.__onSubmitSuccess = onSuccess;
|
|
123
|
-
model._fieldProps = fieldProps;
|
|
124
|
-
model._onOk = onOk;
|
|
125
|
-
console.log('QuickEditFormModel.open3', Date.now() - model.now);
|
|
126
|
-
return (
|
|
127
|
-
<FlowModelRenderer
|
|
128
|
-
fallback={<Skeleton.Input size="small" />}
|
|
129
|
-
model={model}
|
|
130
|
-
inputArgs={{ filterByTk, record, sourceFieldModelUid }}
|
|
131
|
-
/>
|
|
132
|
-
);
|
|
133
|
-
},
|
|
279
|
+
content,
|
|
134
280
|
});
|
|
135
281
|
}
|
|
136
282
|
|
|
@@ -171,15 +317,15 @@ export class QuickEditFormModel extends FlowModel {
|
|
|
171
317
|
}
|
|
172
318
|
|
|
173
319
|
render() {
|
|
174
|
-
|
|
175
|
-
|
|
320
|
+
const isMobileLayout = this.context.isMobileLayout;
|
|
176
321
|
return (
|
|
177
322
|
<FormComponent model={this}>
|
|
178
323
|
<div
|
|
179
324
|
style={{
|
|
180
325
|
minHeight: 0,
|
|
181
326
|
overflowY: 'auto',
|
|
182
|
-
maxHeight: QUICK_EDIT_FORM_MAX_HEIGHT,
|
|
327
|
+
maxHeight: isMobileLayout ? QUICK_EDIT_MOBILE_FORM_MAX_HEIGHT : QUICK_EDIT_FORM_MAX_HEIGHT,
|
|
328
|
+
padding: isMobileLayout ? QUICK_EDIT_MOBILE_CONTENT_PADDING : undefined,
|
|
183
329
|
}}
|
|
184
330
|
>
|
|
185
331
|
{this.mapSubModels('fields', (field) => {
|
|
@@ -196,7 +342,14 @@ export class QuickEditFormModel extends FlowModel {
|
|
|
196
342
|
);
|
|
197
343
|
})}
|
|
198
344
|
</div>
|
|
199
|
-
<Space
|
|
345
|
+
<Space
|
|
346
|
+
style={{
|
|
347
|
+
display: 'flex',
|
|
348
|
+
justifyContent: 'flex-end',
|
|
349
|
+
flexShrink: 0,
|
|
350
|
+
padding: isMobileLayout ? QUICK_EDIT_MOBILE_ACTIONS_PADDING : undefined,
|
|
351
|
+
}}
|
|
352
|
+
>
|
|
200
353
|
<Button
|
|
201
354
|
onClick={() => {
|
|
202
355
|
this.viewContainer.close();
|
|
@@ -420,6 +420,23 @@ describe('FormBlockModel (form/formValues injection & server resolve anchors)',
|
|
|
420
420
|
expect(savedUids).toContain('grid-1');
|
|
421
421
|
});
|
|
422
422
|
|
|
423
|
+
it('keeps dirty reset separate from runtime user-edited reset', async () => {
|
|
424
|
+
const model = await setupFormModel();
|
|
425
|
+
const resetUserEditedState = vi.fn();
|
|
426
|
+
model.formValueRuntime = { resetUserEditedState } as any;
|
|
427
|
+
|
|
428
|
+
model.markUserModifiedFields({ status: 'draft' });
|
|
429
|
+
expect(model.getUserModifiedFields().has('status')).toBe(true);
|
|
430
|
+
|
|
431
|
+
model.resetUserModifiedFields();
|
|
432
|
+
|
|
433
|
+
expect(model.getUserModifiedFields().size).toBe(0);
|
|
434
|
+
expect(resetUserEditedState).not.toHaveBeenCalled();
|
|
435
|
+
|
|
436
|
+
model.resetRuntimeUserEditedState();
|
|
437
|
+
expect(resetUserEditedState).toHaveBeenCalledTimes(1);
|
|
438
|
+
});
|
|
439
|
+
|
|
423
440
|
it('re-syncs delegated assignRules when grid submodel is added after block init', async () => {
|
|
424
441
|
const model = await setupFormModel();
|
|
425
442
|
const syncAssignRules = vi.fn();
|