@nocobase/client-v2 2.2.0-alpha.1 → 2.2.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/es/PluginSettingsManager.d.ts +33 -0
- package/es/RouteRepository.d.ts +21 -6
- package/es/components/category-tabs/SortableCategoryTabs.d.ts +55 -0
- package/es/components/category-tabs/index.d.ts +9 -0
- package/es/components/form/JsonTextArea.d.ts +2 -1
- package/es/components/form/TypedVariableInput.d.ts +22 -4
- package/es/components/form/VariableJsonTextArea.d.ts +19 -0
- package/es/components/form/filter/CollectionFilterItem.d.ts +11 -1
- package/es/components/form/filter/index.d.ts +2 -0
- package/es/components/form/index.d.ts +1 -0
- package/es/components/index.d.ts +2 -0
- package/es/flow/actions/afterSuccess.d.ts +8 -1
- package/es/flow/actions/index.d.ts +1 -1
- 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/resolveAdminRouteRuntimeTarget.d.ts +6 -0
- package/es/flow/components/FieldAssignRulesEditor.d.ts +3 -1
- package/es/flow/components/FieldAssignValueInput.d.ts +2 -0
- package/es/flow/index.d.ts +1 -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/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 +21 -0
- package/es/flow/models/blocks/form/value-runtime/types.d.ts +2 -2
- 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/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 +2 -1
- package/es/index.mjs +233 -137
- package/lib/index.js +234 -138
- package/package.json +7 -7
- package/src/PluginSettingsManager.ts +53 -0
- package/src/RouteRepository.ts +126 -24
- package/src/__tests__/PluginSettingsManager.test.ts +13 -0
- package/src/__tests__/RouteRepository.test.ts +216 -0
- package/src/__tests__/browserChecker.test.ts +61 -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/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/README.md +7 -1
- package/src/components/README.zh-CN.md +6 -1
- package/src/components/category-tabs/SortableCategoryTabs.tsx +210 -0
- package/src/components/category-tabs/index.ts +10 -0
- package/src/components/form/JsonTextArea.tsx +21 -11
- package/src/components/form/TypedVariableInput.tsx +416 -93
- package/src/components/form/VariableJsonTextArea.tsx +175 -0
- package/src/components/form/__tests__/JsonTextArea.test.tsx +43 -0
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +266 -9
- package/src/components/form/__tests__/VariableJsonTextArea.test.tsx +86 -0
- package/src/components/form/filter/CollectionFilterItem.tsx +32 -7
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +38 -0
- package/src/components/form/filter/index.ts +2 -0
- package/src/components/form/index.tsx +1 -0
- package/src/components/index.ts +2 -0
- package/src/flow/__tests__/FlowRoute.test.tsx +443 -5
- 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 +58 -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 +104 -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 +10 -0
- 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 +38 -4
- package/src/flow/actions/runjs.tsx +2 -14
- package/src/flow/actions/validation.tsx +62 -30
- package/src/flow/admin-shell/BaseLayoutModel.tsx +25 -3
- package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +5 -2
- package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +13 -0
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +34 -10
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.test.tsx +310 -0
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +44 -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/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 +82 -0
- package/src/flow/admin-shell/admin-layout/__tests__/TopbarActionsBar.test.tsx +166 -2
- 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/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 +10 -5
- package/src/flow/components/FlowRoute.tsx +56 -11
- 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__/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 +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 +12 -1
- 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__/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 +31 -3
- package/src/flow/models/blocks/filter-form/FilterFormJSActionModel.tsx +2 -7
- package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +77 -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/__tests__/FormBlockModel.test.tsx +17 -0
- 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 +880 -102
- package/src/flow/models/blocks/form/value-runtime/rules.ts +445 -13
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +257 -13
- package/src/flow/models/blocks/form/value-runtime/types.ts +2 -2
- package/src/flow/models/blocks/js-block/JSBlock.tsx +2 -7
- 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 +36 -3
- 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 +159 -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 +29 -6
- package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +16 -4
- 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 +49 -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 +100 -0
- package/src/flow/models/topbar/TopbarActionModel.tsx +93 -10
- package/src/flow/resolveViewParamsToViewList.tsx +11 -3
- package/src/flow/utils/__tests__/dateTimeFormat.test.ts +258 -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 +8 -1
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +41 -1
- package/src/nocobase-buildin-plugin/index.tsx +44 -14
- 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
|
@@ -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,7 +7,15 @@
|
|
|
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';
|
|
@@ -291,8 +299,32 @@ export const openView = defineAction({
|
|
|
291
299
|
? (inputArgs as any).associationName
|
|
292
300
|
: (params as any)?.associationName;
|
|
293
301
|
const mergedTabUid = typeof inputArgs.tabUid !== 'undefined' ? inputArgs.tabUid : params.tabUid;
|
|
294
|
-
|
|
295
|
-
const
|
|
302
|
+
const hasRunJSOpenViewRouteState = Object.prototype.hasOwnProperty.call(inputArgs, RUNJS_OPEN_VIEW_ROUTE_STATE);
|
|
303
|
+
const runJSOpenViewRouteStateInput = (inputArgs as Record<PropertyKey, unknown>)[RUNJS_OPEN_VIEW_ROUTE_STATE];
|
|
304
|
+
const runJSOpenViewRouteState = hasRunJSOpenViewRouteState
|
|
305
|
+
? createOpenViewRouteState(
|
|
306
|
+
runJSOpenViewRouteStateInput && typeof runJSOpenViewRouteStateInput === 'object'
|
|
307
|
+
? (runJSOpenViewRouteStateInput as { mode?: unknown; size?: unknown })
|
|
308
|
+
: {
|
|
309
|
+
mode: inputArgs.mode,
|
|
310
|
+
size: inputArgs.size,
|
|
311
|
+
},
|
|
312
|
+
)
|
|
313
|
+
: undefined;
|
|
314
|
+
const replayOpenViewRouteStateInput = (inputArgs as { openViewRouteState?: unknown }).openViewRouteState;
|
|
315
|
+
const replayOpenViewRouteState =
|
|
316
|
+
replayOpenViewRouteStateInput && typeof replayOpenViewRouteStateInput === 'object'
|
|
317
|
+
? createOpenViewRouteState(replayOpenViewRouteStateInput as { mode?: unknown; size?: unknown })
|
|
318
|
+
: undefined;
|
|
319
|
+
const runtimeOpenViewRouteState = runJSOpenViewRouteState || replayOpenViewRouteState;
|
|
320
|
+
// 移动端中只需要显示子页面。本次 dispatch 参数优先于持久化默认值。
|
|
321
|
+
const openMode = ctx.inputArgs?.isMobileLayout
|
|
322
|
+
? 'embed'
|
|
323
|
+
: runtimeOpenViewRouteState?.mode || ctx.inputArgs?.mode || params.mode || 'drawer';
|
|
324
|
+
const effectiveRunJSOpenViewRouteState =
|
|
325
|
+
runJSOpenViewRouteState && ctx.inputArgs?.isMobileLayout
|
|
326
|
+
? createOpenViewRouteState({ ...runJSOpenViewRouteState, mode: openMode })
|
|
327
|
+
: runJSOpenViewRouteState;
|
|
296
328
|
let navigation = typeof inputArgs.navigation !== 'undefined' ? inputArgs.navigation : params.navigation;
|
|
297
329
|
|
|
298
330
|
// 传递了上下文就必须禁用路由,否则下次路由打开会缺少上下文
|
|
@@ -313,6 +345,7 @@ export const openView = defineAction({
|
|
|
313
345
|
sourceId: mergedSourceId,
|
|
314
346
|
tabUid: mergedTabUid,
|
|
315
347
|
viewUid: ctx.model.context?.inputArgs?.viewUid || ctx.model.uid,
|
|
348
|
+
...(effectiveRunJSOpenViewRouteState ? { openViewRouteState: effectiveRunJSOpenViewRouteState } : {}),
|
|
316
349
|
} as Record<string, unknown>;
|
|
317
350
|
const pendingView = {
|
|
318
351
|
type: pendingType,
|
|
@@ -328,6 +361,7 @@ export const openView = defineAction({
|
|
|
328
361
|
filterByTk: mergedFilterByTk,
|
|
329
362
|
sourceId: mergedSourceId,
|
|
330
363
|
tabUid: mergedTabUid,
|
|
364
|
+
...(effectiveRunJSOpenViewRouteState ? { openViewRouteState: effectiveRunJSOpenViewRouteState } : {}),
|
|
331
365
|
};
|
|
332
366
|
ctx.view.navigation.navigateTo(nextView);
|
|
333
367
|
return;
|
|
@@ -373,7 +407,7 @@ export const openView = defineAction({
|
|
|
373
407
|
|
|
374
408
|
const pageModelClass =
|
|
375
409
|
ctx.inputArgs.pageModelClass || params.pageModelClass || ctx.layout?.childPageModelClass || 'ChildPageModel';
|
|
376
|
-
const size = ctx.inputArgs.size || params.size || 'medium';
|
|
410
|
+
const size = runtimeOpenViewRouteState?.size || ctx.inputArgs.size || params.size || 'medium';
|
|
377
411
|
let pageModelUid: string | null = null;
|
|
378
412
|
let pageModelRef: FlowModel | null = null;
|
|
379
413
|
|
|
@@ -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
|
}
|
|
@@ -8,7 +8,13 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { define, observable } from '@formily/reactive';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
decodeOpenViewRouteState,
|
|
13
|
+
parsePathnameToViewParams,
|
|
14
|
+
type FlowEngine,
|
|
15
|
+
FlowModel,
|
|
16
|
+
type ViewParam,
|
|
17
|
+
} from '@nocobase/flow-engine';
|
|
12
18
|
import {
|
|
13
19
|
BaseLayoutRouteCoordinator,
|
|
14
20
|
type BaseLayoutRouteCoordinatorOptions,
|
|
@@ -116,20 +122,36 @@ const isStandardLayoutRelativePath = (relativePath: string) => {
|
|
|
116
122
|
}
|
|
117
123
|
|
|
118
124
|
let i = 1;
|
|
125
|
+
let currentViewUid = segments[0];
|
|
119
126
|
while (i < segments.length) {
|
|
120
127
|
const segment = segments[i];
|
|
128
|
+
|
|
121
129
|
if (segment === 'view') {
|
|
122
130
|
if (!segments[i + 1]) {
|
|
123
131
|
return false;
|
|
124
132
|
}
|
|
133
|
+
currentViewUid = segments[i + 1];
|
|
134
|
+
i += 2;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (segment === 'opts') {
|
|
139
|
+
if (!segments[i + 1] || !decodeOpenViewRouteState(currentViewUid, segments[i + 1])) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
i += 2;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (isKnownViewParamName(segment) && segments[i + 1]) {
|
|
125
147
|
i += 2;
|
|
126
148
|
continue;
|
|
127
149
|
}
|
|
128
150
|
|
|
129
|
-
if (!
|
|
151
|
+
if (!segments[i + 1]) {
|
|
130
152
|
return false;
|
|
131
153
|
}
|
|
132
|
-
|
|
154
|
+
return false;
|
|
133
155
|
}
|
|
134
156
|
|
|
135
157
|
return true;
|
|
@@ -272,7 +272,7 @@ export class BaseLayoutRouteCoordinator {
|
|
|
272
272
|
runtime.viewState[getKey(viewItem)]?.destroy?.(true);
|
|
273
273
|
delete runtime.viewState[getKey(viewItem)];
|
|
274
274
|
});
|
|
275
|
-
updateViewListHidden(viewList);
|
|
275
|
+
updateViewListHidden(viewList, !!this.layoutContext?.isMobileLayout);
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
if (viewsToOpen.length) {
|
|
@@ -299,7 +299,7 @@ export class BaseLayoutRouteCoordinator {
|
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
if (runtime.meta.active) {
|
|
302
|
-
updateViewListHidden(viewList);
|
|
302
|
+
updateViewListHidden(viewList, !!this.layoutContext?.isMobileLayout);
|
|
303
303
|
return;
|
|
304
304
|
}
|
|
305
305
|
|
|
@@ -390,6 +390,7 @@ export class BaseLayoutRouteCoordinator {
|
|
|
390
390
|
openViewParams?.associationName && !hasUsableSourceId(viewItem.params.sourceId)
|
|
391
391
|
? null
|
|
392
392
|
: openViewParams?.associationName;
|
|
393
|
+
const openViewRouteState = viewItem.params.openViewRouteState;
|
|
393
394
|
const openerUids = viewList.slice(0, viewItem.index).map((item) => item.params.viewUid);
|
|
394
395
|
const navigation = new ViewNavigation(
|
|
395
396
|
this.flowEngine.context,
|
|
@@ -408,6 +409,8 @@ export class BaseLayoutRouteCoordinator {
|
|
|
408
409
|
deactivateRef,
|
|
409
410
|
openerUids,
|
|
410
411
|
...viewItem.params,
|
|
412
|
+
...(openViewRouteState?.mode ? { mode: openViewRouteState.mode } : {}),
|
|
413
|
+
...(openViewRouteState?.size ? { size: openViewRouteState.size } : {}),
|
|
411
414
|
pageActive: runtime.meta.active,
|
|
412
415
|
activationControlledByLayout: true,
|
|
413
416
|
navigation,
|
|
@@ -121,6 +121,19 @@ describe('AdminLayoutRouteCoordinator', () => {
|
|
|
121
121
|
});
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
+
it('passes RunJS openView route state as runtime mode and size during route replay', () => {
|
|
125
|
+
const { dispatchEvent } = setupRouteReplay({
|
|
126
|
+
openViewRouteState: { mode: 'dialog', size: 'large' },
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
expect(dispatchEvent.mock.calls[0][1]).toMatchObject({
|
|
130
|
+
mode: 'dialog',
|
|
131
|
+
size: 'large',
|
|
132
|
+
openViewRouteState: { mode: 'dialog', size: 'large' },
|
|
133
|
+
triggerByRouter: true,
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
124
137
|
it('uses layout content element before route page placeholder as view target', () => {
|
|
125
138
|
const engine = new FlowEngine();
|
|
126
139
|
engine.registerModels({ RouteModel });
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
FLOW_SETTINGS_PREFERENCE_STORAGE_KEY,
|
|
43
43
|
readFlowSettingsPreference,
|
|
44
44
|
} from './flowSettingsPreference';
|
|
45
|
+
import { joinAdminLayoutRoutePath, type AdminLayoutRoutePathLike } from './resolveAdminRouteRuntimeTarget';
|
|
45
46
|
import { useAppListRender } from './AppListRender';
|
|
46
47
|
|
|
47
48
|
const className1 = css`
|
|
@@ -314,25 +315,37 @@ const DesignerButtonMenuItem: FC<{ item: AdminLayoutMenuNode; fallbackParentRout
|
|
|
314
315
|
);
|
|
315
316
|
};
|
|
316
317
|
|
|
317
|
-
const matchesRoutePath = (
|
|
318
|
+
const matchesRoutePath = (
|
|
319
|
+
route: NocoBaseDesktopRoute | undefined,
|
|
320
|
+
pathname: string,
|
|
321
|
+
layout?: AdminLayoutRoutePathLike | null,
|
|
322
|
+
): boolean => {
|
|
318
323
|
if (!route) {
|
|
319
324
|
return false;
|
|
320
325
|
}
|
|
321
326
|
|
|
322
327
|
const candidates = [
|
|
323
|
-
route.id != null ?
|
|
324
|
-
route.schemaUid ?
|
|
328
|
+
route.id != null ? joinAdminLayoutRoutePath(layout, route.id) : null,
|
|
329
|
+
route.schemaUid ? joinAdminLayoutRoutePath(layout, route.schemaUid) : null,
|
|
325
330
|
].filter(Boolean) as string[];
|
|
326
331
|
|
|
327
332
|
if (candidates.some((candidate) => pathname === candidate || pathname.startsWith(`${candidate}/`))) {
|
|
328
333
|
return true;
|
|
329
334
|
}
|
|
330
335
|
|
|
331
|
-
return Array.isArray(route.children)
|
|
336
|
+
return Array.isArray(route.children)
|
|
337
|
+
? route.children.some((child) => matchesRoutePath(child, pathname, layout))
|
|
338
|
+
: false;
|
|
332
339
|
};
|
|
333
340
|
|
|
334
|
-
const findSelectedTopGroupRoute = (
|
|
335
|
-
|
|
341
|
+
const findSelectedTopGroupRoute = (
|
|
342
|
+
routes: NocoBaseDesktopRoute[],
|
|
343
|
+
pathname: string,
|
|
344
|
+
layout?: AdminLayoutRoutePathLike | null,
|
|
345
|
+
) => {
|
|
346
|
+
return routes.find(
|
|
347
|
+
(route) => route.type === NocoBaseDesktopRouteType.group && matchesRoutePath(route, pathname, layout),
|
|
348
|
+
);
|
|
336
349
|
};
|
|
337
350
|
|
|
338
351
|
const renderMenuNodeWithModel = (
|
|
@@ -376,6 +389,11 @@ export const AdminLayoutComponent = observer((props: any) => {
|
|
|
376
389
|
const { token } = antdTheme.useToken();
|
|
377
390
|
const customToken = token as CustomToken;
|
|
378
391
|
const isMobileLayout = !!adminLayoutModel?.isMobileLayout;
|
|
392
|
+
const adminLayoutRoutePath = adminLayoutModel?.layout?.routePath;
|
|
393
|
+
const adminLayoutRoutePathLike = useMemo<AdminLayoutRoutePathLike | undefined>(
|
|
394
|
+
() => (adminLayoutRoutePath ? { routePath: adminLayoutRoutePath } : undefined),
|
|
395
|
+
[adminLayoutRoutePath],
|
|
396
|
+
);
|
|
379
397
|
const menuRouteRefreshVersion = adminLayoutModel?.menuRouteRefreshVersion || 0;
|
|
380
398
|
const isMobileSider = isMobileLayout;
|
|
381
399
|
const [collapsed, setCollapsed] = useState(isMobileSider);
|
|
@@ -403,8 +421,8 @@ export const AdminLayoutComponent = observer((props: any) => {
|
|
|
403
421
|
[adminLayoutModel],
|
|
404
422
|
);
|
|
405
423
|
const selectedTopGroupRoute = useMemo(
|
|
406
|
-
() => findSelectedTopGroupRoute(allAccessRoutes, location.pathname),
|
|
407
|
-
[allAccessRoutes, location.pathname],
|
|
424
|
+
() => findSelectedTopGroupRoute(allAccessRoutes, location.pathname, adminLayoutRoutePathLike),
|
|
425
|
+
[adminLayoutRoutePathLike, allAccessRoutes, location.pathname],
|
|
408
426
|
);
|
|
409
427
|
|
|
410
428
|
const handleMenuDragEnd = useCallback(
|
|
@@ -458,6 +476,7 @@ export const AdminLayoutComponent = observer((props: any) => {
|
|
|
458
476
|
|
|
459
477
|
useEffect(() => {
|
|
460
478
|
const routeRepository = flowEngine.context.routeRepository;
|
|
479
|
+
const deactivateLayout = routeRepository?.activateLayout?.(adminLayoutModel?.layout);
|
|
461
480
|
const subscriber = () => {
|
|
462
481
|
const updatedRoutes = routeRepository?.listAccessible() || [];
|
|
463
482
|
setAllAccessRoutes(updatedRoutes);
|
|
@@ -470,8 +489,9 @@ export const AdminLayoutComponent = observer((props: any) => {
|
|
|
470
489
|
|
|
471
490
|
return () => {
|
|
472
491
|
routeRepository?.unsubscribe(subscriber);
|
|
492
|
+
deactivateLayout?.();
|
|
473
493
|
};
|
|
474
|
-
}, [flowEngine]);
|
|
494
|
+
}, [adminLayoutModel, adminLayoutModel?.layout?.uid, flowEngine]);
|
|
475
495
|
|
|
476
496
|
useEffect(() => {
|
|
477
497
|
if (typeof window === 'undefined') {
|
|
@@ -697,7 +717,11 @@ export const AdminLayoutComponent = observer((props: any) => {
|
|
|
697
717
|
<SetIsMobileLayout isMobile={isMobile} model={adminLayoutModel}>
|
|
698
718
|
<ConfigProvider theme={isMobile ? mobileTheme : theme}>
|
|
699
719
|
<GlobalStyle />
|
|
700
|
-
<AdminLayoutContent
|
|
720
|
+
<AdminLayoutContent
|
|
721
|
+
designable={designable}
|
|
722
|
+
layout={adminLayoutModel?.layout}
|
|
723
|
+
onContentElementChange={handleLayoutContentElementChange}
|
|
724
|
+
/>
|
|
701
725
|
</ConfigProvider>
|
|
702
726
|
</SetIsMobileLayout>
|
|
703
727
|
);
|