@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
|
@@ -15,17 +15,29 @@ import {
|
|
|
15
15
|
isRunJSValue,
|
|
16
16
|
} from '@nocobase/flow-engine';
|
|
17
17
|
import _ from 'lodash';
|
|
18
|
-
import { namePathToPathKey
|
|
18
|
+
import { namePathToPathKey } from '../models/blocks/form/value-runtime/path';
|
|
19
19
|
import {
|
|
20
20
|
collectStaticDepsFromRunJSValue,
|
|
21
21
|
collectStaticDepsFromTemplateValue,
|
|
22
22
|
recordDep,
|
|
23
23
|
type DepCollector,
|
|
24
24
|
} from '../models/blocks/form/value-runtime/deps';
|
|
25
|
+
import {
|
|
26
|
+
buildItemListRootPath,
|
|
27
|
+
buildItemRowPath,
|
|
28
|
+
dedupeNamePaths,
|
|
29
|
+
findFormValueChangeSource,
|
|
30
|
+
getChangedPathsFromPayload,
|
|
31
|
+
getFieldIndexEntriesFromContext,
|
|
32
|
+
isNamePathPrefix,
|
|
33
|
+
isSameNamePath,
|
|
34
|
+
minimizeNamePaths,
|
|
35
|
+
parseDependencyPath,
|
|
36
|
+
parsePathKey,
|
|
37
|
+
type NamePath,
|
|
38
|
+
} from '../utils/formValueDeps';
|
|
25
39
|
import { linkageRulesRefresh } from './linkageRulesRefresh';
|
|
26
40
|
|
|
27
|
-
type NamePath = Array<string | number>;
|
|
28
|
-
|
|
29
41
|
type LinkageRefreshDeps = {
|
|
30
42
|
wildcard: boolean;
|
|
31
43
|
valuePaths: NamePath[];
|
|
@@ -40,75 +52,11 @@ type LinkageRefreshBinding = {
|
|
|
40
52
|
dispose: () => void;
|
|
41
53
|
};
|
|
42
54
|
|
|
43
|
-
type FieldIndexEntry = {
|
|
44
|
-
name: string;
|
|
45
|
-
index: number;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
55
|
const FORM_VALUES_CHANGE_EVENT = 'formValuesChange';
|
|
49
56
|
const LINKAGE_REFRESH_BINDINGS_KEY = '__formValueDrivenLinkageRefreshBindings';
|
|
50
57
|
|
|
51
|
-
function isSameNamePath(a: NamePath, b: NamePath) {
|
|
52
|
-
return a.length === b.length && a.every((seg, index) => seg === b[index]);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function isNamePathPrefix(prefix: NamePath, path: NamePath) {
|
|
56
|
-
if (prefix.length > path.length) return false;
|
|
57
|
-
return prefix.every((seg, index) => seg === path[index]);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function dedupeNamePaths(paths: NamePath[]) {
|
|
61
|
-
const byKey = new Map<string, NamePath>();
|
|
62
|
-
for (const path of paths) {
|
|
63
|
-
if (!path?.length) continue;
|
|
64
|
-
byKey.set(namePathToPathKey(path), path);
|
|
65
|
-
}
|
|
66
|
-
return Array.from(byKey.values());
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function minimizeValueNamePaths(paths: NamePath[]) {
|
|
70
|
-
const deduped = dedupeNamePaths(paths);
|
|
71
|
-
return deduped.filter((path, index) => {
|
|
72
|
-
return !deduped.some((other, otherIndex) => otherIndex !== index && isNamePathPrefix(path, other));
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function parseFieldIndexEntries(fieldIndex: unknown): FieldIndexEntry[] {
|
|
77
|
-
const arr = Array.isArray(fieldIndex) ? fieldIndex : [];
|
|
78
|
-
const entries: FieldIndexEntry[] = [];
|
|
79
|
-
for (const it of arr) {
|
|
80
|
-
if (typeof it !== 'string') continue;
|
|
81
|
-
const [name, indexStr] = it.split(':');
|
|
82
|
-
const index = Number(indexStr);
|
|
83
|
-
if (!name || Number.isNaN(index)) continue;
|
|
84
|
-
entries.push({ name, index });
|
|
85
|
-
}
|
|
86
|
-
return entries;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function getFieldIndexEntriesFromContext(ctx: any): FieldIndexEntry[] {
|
|
90
|
-
return parseFieldIndexEntries(ctx?.model?.context?.fieldIndex ?? ctx?.fieldIndex);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function buildItemRowPath(entries: FieldIndexEntry[], parentDepth: number): NamePath | null {
|
|
94
|
-
const targetIndex = entries.length - 1 - parentDepth;
|
|
95
|
-
if (targetIndex < 0) return null;
|
|
96
|
-
|
|
97
|
-
const out: NamePath = [];
|
|
98
|
-
for (let i = 0; i <= targetIndex; i++) {
|
|
99
|
-
out.push(entries[i].name, entries[i].index);
|
|
100
|
-
}
|
|
101
|
-
return out;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function buildItemListRootPath(entries: FieldIndexEntry[], parentDepth: number): NamePath | null {
|
|
105
|
-
const rowPath = buildItemRowPath(entries, parentDepth);
|
|
106
|
-
if (!rowPath?.length) return null;
|
|
107
|
-
return rowPath.slice(0, -1);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
58
|
function resolveItemDependencyPath(ctx: FlowContext, depPath: NamePath): LinkageRefreshDeps {
|
|
111
|
-
const entries = getFieldIndexEntriesFromContext(ctx
|
|
59
|
+
const entries = getFieldIndexEntriesFromContext(ctx);
|
|
112
60
|
if (!entries.length) {
|
|
113
61
|
return { wildcard: true, valuePaths: [], structuralPaths: [] };
|
|
114
62
|
}
|
|
@@ -171,8 +119,7 @@ function addRunjsUsageToCollector(script: string, collector: DepCollector) {
|
|
|
171
119
|
collector.wildcard = true;
|
|
172
120
|
continue;
|
|
173
121
|
}
|
|
174
|
-
|
|
175
|
-
recordDep(segs, collector);
|
|
122
|
+
recordDep(parseDependencyPath(String(subPath)), collector);
|
|
176
123
|
continue;
|
|
177
124
|
}
|
|
178
125
|
if (varName === 'item') {
|
|
@@ -233,13 +180,13 @@ function collectLinkageRefreshDeps(ctx: FlowContext, params: any): LinkageRefres
|
|
|
233
180
|
wildcard = true;
|
|
234
181
|
continue;
|
|
235
182
|
}
|
|
236
|
-
valuePaths.push(
|
|
183
|
+
valuePaths.push(parsePathKey(inner));
|
|
237
184
|
continue;
|
|
238
185
|
}
|
|
239
186
|
|
|
240
187
|
if (depKey === 'ctx:item' || depKey.startsWith('ctx:item:')) {
|
|
241
188
|
const subPath = depKey === 'ctx:item' ? '' : depKey.slice('ctx:item:'.length);
|
|
242
|
-
const depPath = subPath ? (
|
|
189
|
+
const depPath = subPath ? parseDependencyPath(subPath) : [];
|
|
243
190
|
const resolved = resolveItemDependencyPath(ctx, depPath);
|
|
244
191
|
wildcard ||= resolved.wildcard;
|
|
245
192
|
valuePaths.push(...resolved.valuePaths);
|
|
@@ -249,7 +196,7 @@ function collectLinkageRefreshDeps(ctx: FlowContext, params: any): LinkageRefres
|
|
|
249
196
|
|
|
250
197
|
return {
|
|
251
198
|
wildcard,
|
|
252
|
-
valuePaths:
|
|
199
|
+
valuePaths: minimizeNamePaths(valuePaths),
|
|
253
200
|
structuralPaths: dedupeNamePaths(structuralPaths),
|
|
254
201
|
};
|
|
255
202
|
}
|
|
@@ -258,44 +205,9 @@ function hasLinkageRefreshDeps(deps: LinkageRefreshDeps) {
|
|
|
258
205
|
return deps.wildcard || deps.valuePaths.length > 0 || deps.structuralPaths.length > 0;
|
|
259
206
|
}
|
|
260
207
|
|
|
261
|
-
function getChangedPathsFromPayload(payload: any): NamePath[] {
|
|
262
|
-
const rawChangedPaths = Array.isArray(payload?.changedPaths) ? payload.changedPaths : [];
|
|
263
|
-
const out: NamePath[] = [];
|
|
264
|
-
|
|
265
|
-
for (const path of rawChangedPaths) {
|
|
266
|
-
if (Array.isArray(path)) {
|
|
267
|
-
if (path.length === 1 && typeof path[0] === 'string') {
|
|
268
|
-
const namePath = pathKeyToNamePath(path[0]);
|
|
269
|
-
if (namePath.length) out.push(namePath);
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
const segs = path.filter((seg) => typeof seg === 'string' || typeof seg === 'number') as NamePath;
|
|
273
|
-
if (segs.length) out.push(segs);
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
if (typeof path === 'string' && path) {
|
|
277
|
-
out.push(pathKeyToNamePath(path));
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (out.length) {
|
|
282
|
-
return out;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const changedValues = payload?.changedValues;
|
|
286
|
-
if (changedValues && typeof changedValues === 'object') {
|
|
287
|
-
for (const key of Object.keys(changedValues)) {
|
|
288
|
-
const namePath = pathKeyToNamePath(key);
|
|
289
|
-
if (namePath.length) out.push(namePath);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return out;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
208
|
function linkageRefreshDepsMatchPayload(deps: LinkageRefreshDeps, payload: any) {
|
|
297
209
|
if (!hasLinkageRefreshDeps(deps)) return false;
|
|
298
|
-
const changedPaths = getChangedPathsFromPayload(payload);
|
|
210
|
+
const changedPaths = getChangedPathsFromPayload(payload, { includeArrayChangedValues: true });
|
|
299
211
|
if (deps.wildcard) return true;
|
|
300
212
|
if (!changedPaths.length) return true;
|
|
301
213
|
|
|
@@ -330,28 +242,8 @@ function getLinkageRefreshBindings(model: any): Map<string, LinkageRefreshBindin
|
|
|
330
242
|
return (model[LINKAGE_REFRESH_BINDINGS_KEY] ||= new Map<string, LinkageRefreshBinding>());
|
|
331
243
|
}
|
|
332
244
|
|
|
333
|
-
function isFormBlockForLinkageRefresh(model: any) {
|
|
334
|
-
if (!model || typeof model !== 'object') return false;
|
|
335
|
-
if (!model.emitter || typeof model.emitter.on !== 'function' || typeof model.emitter.off !== 'function') return false;
|
|
336
|
-
return !!model.formValueRuntime || !!model.context?.form || typeof model.context?.setFormValues === 'function';
|
|
337
|
-
}
|
|
338
|
-
|
|
339
245
|
function findFormBlockForLinkageRefresh(ctx: FlowContext): any | null {
|
|
340
|
-
|
|
341
|
-
const push = (model: any) => {
|
|
342
|
-
if (model && !candidates.includes(model)) candidates.push(model);
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
push((ctx.model as any)?.context?.blockModel);
|
|
346
|
-
push(ctx.model);
|
|
347
|
-
|
|
348
|
-
let cursor: any = (ctx.model as any)?.parent;
|
|
349
|
-
while (cursor) {
|
|
350
|
-
push(cursor);
|
|
351
|
-
cursor = cursor?.parent;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return candidates.find(isFormBlockForLinkageRefresh) || null;
|
|
246
|
+
return findFormValueChangeSource(ctx) as any;
|
|
355
247
|
}
|
|
356
248
|
|
|
357
249
|
function disposeLinkageRefreshBinding(model: any, key: string) {
|
|
@@ -7,11 +7,20 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
defineAction,
|
|
12
|
+
tExpr,
|
|
13
|
+
FlowModelContext,
|
|
14
|
+
FlowModel,
|
|
15
|
+
FlowExitAllException,
|
|
16
|
+
createOpenViewRouteState,
|
|
17
|
+
RUNJS_OPEN_VIEW_ROUTE_STATE,
|
|
18
|
+
} from '@nocobase/flow-engine';
|
|
11
19
|
import React from 'react';
|
|
12
20
|
import { FlowPage } from '../FlowPage';
|
|
13
21
|
import { PageModel, RootPageModel } from '../models';
|
|
14
22
|
import _ from 'lodash';
|
|
23
|
+
import { ROUTE_TRANSIENT_INPUT_ARGS_KEY } from '../routeTransientInputArgs';
|
|
15
24
|
|
|
16
25
|
type DirtyAwareFlowModel = FlowModel & {
|
|
17
26
|
getUserModifiedFields?: () => Set<string> | undefined;
|
|
@@ -23,6 +32,15 @@ type BeforeCloseDirtyState = {
|
|
|
23
32
|
formModelUids: string[];
|
|
24
33
|
};
|
|
25
34
|
|
|
35
|
+
const pickRouteTransientInputArgs = (inputArgs: Record<string, unknown>) => {
|
|
36
|
+
return _.pickBy(
|
|
37
|
+
{
|
|
38
|
+
formData: inputArgs.formData,
|
|
39
|
+
},
|
|
40
|
+
(value) => typeof value !== 'undefined',
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
26
44
|
function collectDirtyFormModelUids(model?: FlowModel | null, ignoredDirtyFormModelUids: string[] = []): string[] {
|
|
27
45
|
if (!model) {
|
|
28
46
|
return [];
|
|
@@ -291,8 +309,32 @@ export const openView = defineAction({
|
|
|
291
309
|
? (inputArgs as any).associationName
|
|
292
310
|
: (params as any)?.associationName;
|
|
293
311
|
const mergedTabUid = typeof inputArgs.tabUid !== 'undefined' ? inputArgs.tabUid : params.tabUid;
|
|
294
|
-
|
|
295
|
-
const
|
|
312
|
+
const hasRunJSOpenViewRouteState = Object.prototype.hasOwnProperty.call(inputArgs, RUNJS_OPEN_VIEW_ROUTE_STATE);
|
|
313
|
+
const runJSOpenViewRouteStateInput = (inputArgs as Record<PropertyKey, unknown>)[RUNJS_OPEN_VIEW_ROUTE_STATE];
|
|
314
|
+
const runJSOpenViewRouteState = hasRunJSOpenViewRouteState
|
|
315
|
+
? createOpenViewRouteState(
|
|
316
|
+
runJSOpenViewRouteStateInput && typeof runJSOpenViewRouteStateInput === 'object'
|
|
317
|
+
? (runJSOpenViewRouteStateInput as { mode?: unknown; size?: unknown })
|
|
318
|
+
: {
|
|
319
|
+
mode: inputArgs.mode,
|
|
320
|
+
size: inputArgs.size,
|
|
321
|
+
},
|
|
322
|
+
)
|
|
323
|
+
: undefined;
|
|
324
|
+
const replayOpenViewRouteStateInput = (inputArgs as { openViewRouteState?: unknown }).openViewRouteState;
|
|
325
|
+
const replayOpenViewRouteState =
|
|
326
|
+
replayOpenViewRouteStateInput && typeof replayOpenViewRouteStateInput === 'object'
|
|
327
|
+
? createOpenViewRouteState(replayOpenViewRouteStateInput as { mode?: unknown; size?: unknown })
|
|
328
|
+
: undefined;
|
|
329
|
+
const runtimeOpenViewRouteState = runJSOpenViewRouteState || replayOpenViewRouteState;
|
|
330
|
+
// 移动端中只需要显示子页面。本次 dispatch 参数优先于持久化默认值。
|
|
331
|
+
const openMode = ctx.inputArgs?.isMobileLayout
|
|
332
|
+
? 'embed'
|
|
333
|
+
: runtimeOpenViewRouteState?.mode || ctx.inputArgs?.mode || params.mode || 'drawer';
|
|
334
|
+
const effectiveRunJSOpenViewRouteState =
|
|
335
|
+
runJSOpenViewRouteState && ctx.inputArgs?.isMobileLayout
|
|
336
|
+
? createOpenViewRouteState({ ...runJSOpenViewRouteState, mode: openMode })
|
|
337
|
+
: runJSOpenViewRouteState;
|
|
296
338
|
let navigation = typeof inputArgs.navigation !== 'undefined' ? inputArgs.navigation : params.navigation;
|
|
297
339
|
|
|
298
340
|
// 传递了上下文就必须禁用路由,否则下次路由打开会缺少上下文
|
|
@@ -313,6 +355,7 @@ export const openView = defineAction({
|
|
|
313
355
|
sourceId: mergedSourceId,
|
|
314
356
|
tabUid: mergedTabUid,
|
|
315
357
|
viewUid: ctx.model.context?.inputArgs?.viewUid || ctx.model.uid,
|
|
358
|
+
...(effectiveRunJSOpenViewRouteState ? { openViewRouteState: effectiveRunJSOpenViewRouteState } : {}),
|
|
316
359
|
} as Record<string, unknown>;
|
|
317
360
|
const pendingView = {
|
|
318
361
|
type: pendingType,
|
|
@@ -328,8 +371,19 @@ export const openView = defineAction({
|
|
|
328
371
|
filterByTk: mergedFilterByTk,
|
|
329
372
|
sourceId: mergedSourceId,
|
|
330
373
|
tabUid: mergedTabUid,
|
|
374
|
+
...(effectiveRunJSOpenViewRouteState ? { openViewRouteState: effectiveRunJSOpenViewRouteState } : {}),
|
|
331
375
|
};
|
|
332
|
-
|
|
376
|
+
const transientInputArgs = pickRouteTransientInputArgs(inputArgs);
|
|
377
|
+
const navigationOptions = Object.keys(transientInputArgs).length
|
|
378
|
+
? {
|
|
379
|
+
state: {
|
|
380
|
+
[ROUTE_TRANSIENT_INPUT_ARGS_KEY]: {
|
|
381
|
+
[nextView.viewUid]: transientInputArgs,
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
}
|
|
385
|
+
: undefined;
|
|
386
|
+
ctx.view.navigation.navigateTo(nextView, navigationOptions);
|
|
333
387
|
return;
|
|
334
388
|
}
|
|
335
389
|
}
|
|
@@ -373,7 +427,7 @@ export const openView = defineAction({
|
|
|
373
427
|
|
|
374
428
|
const pageModelClass =
|
|
375
429
|
ctx.inputArgs.pageModelClass || params.pageModelClass || ctx.layout?.childPageModelClass || 'ChildPageModel';
|
|
376
|
-
const size = ctx.inputArgs.size || params.size || 'medium';
|
|
430
|
+
const size = runtimeOpenViewRouteState?.size || ctx.inputArgs.size || params.size || 'medium';
|
|
377
431
|
let pageModelUid: string | null = null;
|
|
378
432
|
let pageModelRef: FlowModel | null = null;
|
|
379
433
|
|
|
@@ -7,14 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
ActionScene,
|
|
12
|
-
defineAction,
|
|
13
|
-
tExpr,
|
|
14
|
-
createSafeWindow,
|
|
15
|
-
createSafeDocument,
|
|
16
|
-
createSafeNavigator,
|
|
17
|
-
} from '@nocobase/flow-engine';
|
|
10
|
+
import { ActionScene, defineAction, tExpr } from '@nocobase/flow-engine';
|
|
18
11
|
import { CodeEditor } from '../components/code-editor';
|
|
19
12
|
|
|
20
13
|
export const runjs = defineAction({
|
|
@@ -38,11 +31,6 @@ export const runjs = defineAction({
|
|
|
38
31
|
// 如果是 URL 触发的,则不执行代码
|
|
39
32
|
if (ctx.inputArgs?.navigation) return;
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
return ctx.runjs(params.code, {
|
|
43
|
-
window: createSafeWindow({ navigator }),
|
|
44
|
-
document: createSafeDocument(),
|
|
45
|
-
navigator,
|
|
46
|
-
});
|
|
34
|
+
return ctx.runjs(params.code);
|
|
47
35
|
},
|
|
48
36
|
});
|
|
@@ -10,6 +10,56 @@
|
|
|
10
10
|
import { defineAction, jioToJoiSchema, tExpr } from '@nocobase/flow-engine';
|
|
11
11
|
import { FieldValidation } from '../../flow-compat';
|
|
12
12
|
|
|
13
|
+
type ValidationType = 'string' | 'number' | 'array' | 'boolean' | 'any';
|
|
14
|
+
|
|
15
|
+
interface ValidationRule {
|
|
16
|
+
name: string;
|
|
17
|
+
args?: any;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ValidationData {
|
|
21
|
+
type: ValidationType;
|
|
22
|
+
rules?: ValidationRule[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface ValidationContext {
|
|
26
|
+
model: {
|
|
27
|
+
props: {
|
|
28
|
+
label?: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
t: (key: string, options?: Record<string, unknown>) => string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function buildValidationRules(ctx: ValidationContext, validation: ValidationData) {
|
|
35
|
+
const rules = [];
|
|
36
|
+
const schema = jioToJoiSchema(validation);
|
|
37
|
+
const label = ctx.model.props.label;
|
|
38
|
+
rules.push({
|
|
39
|
+
validator: (_: unknown, value: unknown) => {
|
|
40
|
+
const { error } = schema.validate(value, {
|
|
41
|
+
abortEarly: false,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (error) {
|
|
45
|
+
const messages = error.details.map((d: { type: string; context?: Record<string, unknown> }) => {
|
|
46
|
+
return ctx.t(`${d.type}`, {
|
|
47
|
+
...d.context,
|
|
48
|
+
ns: 'data-source-main',
|
|
49
|
+
label,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
const div = document.createElement('div');
|
|
53
|
+
div.innerHTML = messages.join('; ');
|
|
54
|
+
return Promise.reject(div.textContent);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return Promise.resolve();
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
return rules;
|
|
61
|
+
}
|
|
62
|
+
|
|
13
63
|
export const validation = defineAction({
|
|
14
64
|
title: tExpr('Validation'),
|
|
15
65
|
name: 'validation',
|
|
@@ -29,6 +79,7 @@ export const validation = defineAction({
|
|
|
29
79
|
type: targetInterface.validationType,
|
|
30
80
|
availableValidationOptions: [...new Set(targetInterface.availableValidationOptions)],
|
|
31
81
|
excludeValidationOptions: [...new Set(targetInterface.excludeValidationOptions)],
|
|
82
|
+
inheritedValue: ctx.model.collectionField.validation,
|
|
32
83
|
isAssociation: targetInterface.isAssociation,
|
|
33
84
|
},
|
|
34
85
|
},
|
|
@@ -36,40 +87,21 @@ export const validation = defineAction({
|
|
|
36
87
|
},
|
|
37
88
|
handler(ctx, params) {
|
|
38
89
|
if (params.validation) {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (error) {
|
|
49
|
-
const messages = error.details.map((d) => {
|
|
50
|
-
return ctx.t(`${d.type}`, {
|
|
51
|
-
...d.context,
|
|
52
|
-
ns: 'data-source-main',
|
|
53
|
-
label,
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
const div = document.createElement('div');
|
|
57
|
-
div.innerHTML = messages.join('; ');
|
|
58
|
-
return Promise.reject(div.textContent);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return Promise.resolve();
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
const hasRequiredInCollection = params.validation.rules.some((rule) => rule.name === 'required');
|
|
65
|
-
if (hasRequiredInCollection) {
|
|
90
|
+
const collectionValidation = ctx.model.collectionField?.validation;
|
|
91
|
+
const collectionRules = ctx.model.collectionField?.getComponentProps?.().rules || [];
|
|
92
|
+
const uiRules = params.validation.rules?.length
|
|
93
|
+
? buildValidationRules(ctx as unknown as ValidationContext, params.validation)
|
|
94
|
+
: [];
|
|
95
|
+
const hasRequiredInValidation = [collectionValidation, params.validation].some(
|
|
96
|
+
(validation) => validation?.rules?.some((rule) => rule.name === 'required'),
|
|
97
|
+
);
|
|
98
|
+
if (hasRequiredInValidation) {
|
|
66
99
|
ctx.model.setProps({
|
|
67
|
-
required:
|
|
100
|
+
required: hasRequiredInValidation,
|
|
68
101
|
});
|
|
69
102
|
}
|
|
70
|
-
console.log(rules);
|
|
71
103
|
ctx.model.setProps({
|
|
72
|
-
rules,
|
|
104
|
+
rules: [...collectionRules, ...uiRules],
|
|
73
105
|
validation: params.validation,
|
|
74
106
|
});
|
|
75
107
|
}
|