@nocobase/client-v2 2.1.31 → 2.2.0-alpha.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/APIClient.d.ts +1 -3
- package/es/BaseApplication.d.ts +2 -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/components/category-tabs/SortableCategoryTabs.d.ts +55 -0
- package/es/components/category-tabs/index.d.ts +9 -0
- package/es/components/form/TypedVariableInput.d.ts +31 -5
- package/es/components/form/filter/CollectionFilter.d.ts +2 -0
- package/es/components/form/filter/CollectionFilterItem.d.ts +11 -1
- package/es/components/form/filter/CollectionFilterPanel.d.ts +2 -0
- package/es/components/form/filter/index.d.ts +2 -0
- package/es/components/form/filter/useFilterActionProps.d.ts +2 -0
- package/es/components/index.d.ts +2 -0
- package/es/entry-actions/EntryActionManager.d.ts +24 -0
- package/es/entry-actions/index.d.ts +9 -0
- package/es/flow/actions/index.d.ts +1 -1
- package/es/flow/actions/linkageRules.d.ts +2 -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 +3 -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/FieldAssignExactDatePicker.d.ts +1 -0
- package/es/flow/components/FieldAssignValueInput.d.ts +9 -0
- package/es/flow/components/RunJSValueEditor.d.ts +1 -0
- package/es/flow/components/filter/FilterGroup.d.ts +1 -0
- package/es/flow/components/filter/VariableFilterItem.d.ts +6 -1
- package/es/flow/index.d.ts +1 -0
- package/es/flow/models/base/ActionModelCore.d.ts +2 -0
- package/es/flow/models/base/GridModel.d.ts +1 -1
- package/es/flow/models/base/PageModel/PageModel.d.ts +12 -0
- package/es/flow/models/base/PageModel/PageModelTabBar.d.ts +22 -0
- package/es/flow/models/base/PageModel/PageTabModel.d.ts +12 -0
- package/es/flow/models/blocks/form/value-runtime/runtime.d.ts +9 -0
- package/es/flow-compat/routeTypes.d.ts +1 -0
- package/es/index.d.ts +7 -1
- package/es/index.mjs +223 -135
- package/es/utils/getRouteRuntimeVersion.d.ts +23 -0
- package/es/utils/index.d.ts +1 -0
- package/lib/index.js +220 -132
- package/package.json +7 -7
- package/src/APIClient.ts +1 -10
- package/src/Application.tsx +4 -0
- package/src/BaseApplication.tsx +2 -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__/app.test.tsx +18 -0
- package/src/__tests__/authRedirect.test.ts +17 -0
- package/src/__tests__/browserChecker.test.ts +61 -0
- package/src/__tests__/exports.test.ts +16 -0
- package/src/__tests__/getRouteRuntimeVersion.test.ts +68 -0
- package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +28 -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/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 +4 -0
- package/src/components/form/TypedVariableInput.tsx +452 -101
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +364 -12
- package/src/components/form/filter/CollectionFilter.tsx +4 -0
- package/src/components/form/filter/CollectionFilterItem.tsx +32 -7
- package/src/components/form/filter/CollectionFilterPanel.tsx +4 -0
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +38 -0
- package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +95 -0
- package/src/components/form/filter/index.ts +2 -0
- package/src/components/form/filter/useFilterActionProps.ts +37 -6
- package/src/components/index.ts +2 -0
- package/src/entry-actions/EntryActionManager.ts +76 -0
- package/src/entry-actions/index.ts +10 -0
- package/src/flow/__tests__/FlowRoute.test.tsx +1084 -145
- package/src/flow/actions/__tests__/linkageRules.tab.test.ts +171 -0
- package/src/flow/actions/customVariable.tsx +1 -2
- package/src/flow/actions/index.ts +2 -0
- package/src/flow/actions/linkageRules.tsx +65 -8
- package/src/flow/actions/runjs.tsx +2 -14
- package/src/flow/admin-shell/BaseLayoutModel.tsx +13 -0
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +46 -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/__tests__/AdminLayoutComponent.test.tsx +435 -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 +77 -0
- 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/components/DefaultValue.tsx +1 -2
- package/src/flow/components/FieldAssignExactDatePicker.tsx +25 -11
- package/src/flow/components/FieldAssignValueInput.tsx +76 -9
- package/src/flow/components/FlowRoute.tsx +185 -28
- package/src/flow/components/RunJSValueEditor.tsx +9 -1
- package/src/flow/components/__tests__/FieldAssignValueInput.context.test.tsx +84 -2
- 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/filter/FilterGroup.tsx +33 -5
- package/src/flow/components/filter/VariableFilterItem.tsx +158 -10
- package/src/flow/components/filter/__tests__/FilterGroup.test.tsx +45 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.leftMetaTree.test.tsx +9 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +70 -1
- package/src/flow/index.ts +1 -0
- 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 +5 -0
- package/src/flow/models/base/GridModel.tsx +38 -7
- package/src/flow/models/base/PageModel/PageModel.tsx +387 -53
- package/src/flow/models/base/PageModel/PageModelTabBar.tsx +114 -0
- package/src/flow/models/base/PageModel/PageTabModel.tsx +186 -3
- package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +790 -14
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.module-isolation.test.tsx +130 -0
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.test.tsx +118 -0
- package/src/flow/models/base/PageModel/__tests__/PageTabModel.test.ts +586 -1
- 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 +1 -2
- package/src/flow/models/blocks/filter-form/FilterFormJSActionModel.tsx +2 -7
- package/src/flow/models/blocks/form/JSFormActionModel.tsx +2 -7
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +87 -0
- package/src/flow/models/blocks/form/value-runtime/rules.ts +2 -2
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +91 -0
- 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 +1 -1
- package/src/flow/models/blocks/table/TableBlockModel.tsx +13 -3
- package/src/flow/models/blocks/table/__tests__/TableActionsColumnModel.test.tsx +54 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.mobileSettingsButtons.test.tsx +78 -0
- 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/VariableFieldFormModel.tsx +3 -3
- package/src/flow/models/fields/__tests__/VariableFieldFormModel.test.tsx +51 -0
- package/src/flow/models/topbar/TopbarActionModel.tsx +168 -10
- package/src/flow-compat/Popover.tsx +43 -4
- package/src/flow-compat/__tests__/Popover.test.tsx +34 -0
- package/src/flow-compat/routeTypes.ts +1 -0
- package/src/index.ts +13 -1
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +41 -1
- package/src/nocobase-buildin-plugin/index.tsx +19 -3
- package/src/settings-center/AdminSettingsLayout.tsx +10 -2
- package/src/settings-center/SystemSettingsPage.tsx +0 -1
- package/src/settings-center/plugin-manager/PluginCard.tsx +2 -2
- package/src/settings-center/utils.tsx +0 -6
- package/src/utils/getRouteRuntimeVersion.ts +185 -0
- package/src/utils/index.tsx +1 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { FlowEngine } from '@nocobase/flow-engine';
|
|
11
11
|
import React from 'react';
|
|
12
12
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
13
|
-
import { GridModel } from '../GridModel';
|
|
13
|
+
import { GridModel, transformRowsToSingleColumn } from '../GridModel';
|
|
14
14
|
|
|
15
15
|
const createMockRect = ({ top, left, width, height }: { top: number; left: number; width: number; height: number }) => {
|
|
16
16
|
return {
|
|
@@ -66,6 +66,83 @@ const createGridContainer = () => {
|
|
|
66
66
|
return container;
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
+
const createGridContainerWithEmptyColumn = () => {
|
|
70
|
+
const container = document.createElement('div');
|
|
71
|
+
container.setAttribute('data-grid-root', '');
|
|
72
|
+
const row = document.createElement('div');
|
|
73
|
+
row.setAttribute('data-grid-row-id', 'row-1');
|
|
74
|
+
container.appendChild(row);
|
|
75
|
+
|
|
76
|
+
const firstColumn = document.createElement('div');
|
|
77
|
+
firstColumn.setAttribute('data-grid-column-row-id', 'row-1');
|
|
78
|
+
firstColumn.setAttribute('data-grid-column-index', '0');
|
|
79
|
+
row.appendChild(firstColumn);
|
|
80
|
+
|
|
81
|
+
const item = document.createElement('div');
|
|
82
|
+
item.setAttribute('data-grid-item-row-id', 'row-1');
|
|
83
|
+
item.setAttribute('data-grid-column-index', '0');
|
|
84
|
+
item.setAttribute('data-grid-item-index', '0');
|
|
85
|
+
item.setAttribute('data-grid-item-uid', 'item-1');
|
|
86
|
+
firstColumn.appendChild(item);
|
|
87
|
+
|
|
88
|
+
const secondColumn = document.createElement('div');
|
|
89
|
+
secondColumn.setAttribute('data-grid-column-row-id', 'row-1');
|
|
90
|
+
secondColumn.setAttribute('data-grid-column-index', '1');
|
|
91
|
+
row.appendChild(secondColumn);
|
|
92
|
+
|
|
93
|
+
mockRect(container, { top: 0, left: 0, width: 480, height: 280 });
|
|
94
|
+
mockRect(row, { top: 20, left: 20, width: 440, height: 120 });
|
|
95
|
+
mockRect(firstColumn, { top: 20, left: 20, width: 220, height: 120 });
|
|
96
|
+
mockRect(item, { top: 30, left: 30, width: 200, height: 100 });
|
|
97
|
+
mockRect(secondColumn, { top: 20, left: 260, width: 200, height: 120 });
|
|
98
|
+
return container;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const createProjectedMobileGridContainer = (rows: Record<string, string[][]>) => {
|
|
102
|
+
const container = document.createElement('div');
|
|
103
|
+
container.setAttribute('data-grid-root', '');
|
|
104
|
+
mockRect(container, { top: 0, left: 0, width: 480, height: 320 });
|
|
105
|
+
|
|
106
|
+
let top = 20;
|
|
107
|
+
Object.entries(transformRowsToSingleColumn(rows)).forEach(([rowId, columns]) => {
|
|
108
|
+
const row = document.createElement('div');
|
|
109
|
+
row.setAttribute('data-grid-row-id', rowId);
|
|
110
|
+
container.appendChild(row);
|
|
111
|
+
|
|
112
|
+
const column = document.createElement('div');
|
|
113
|
+
column.setAttribute('data-grid-column-row-id', rowId);
|
|
114
|
+
column.setAttribute('data-grid-column-index', '0');
|
|
115
|
+
row.appendChild(column);
|
|
116
|
+
|
|
117
|
+
const items = columns[0] || [];
|
|
118
|
+
items.forEach((itemUid, itemIndex) => {
|
|
119
|
+
const item = document.createElement('div');
|
|
120
|
+
item.setAttribute('data-grid-item-row-id', rowId);
|
|
121
|
+
item.setAttribute('data-grid-column-index', '0');
|
|
122
|
+
item.setAttribute('data-grid-item-index', String(itemIndex));
|
|
123
|
+
item.setAttribute('data-grid-item-uid', itemUid);
|
|
124
|
+
column.appendChild(item);
|
|
125
|
+
mockRect(item, { top: top + 10 + itemIndex * 36, left: 30, width: 420, height: 32 });
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
mockRect(row, { top, left: 20, width: 440, height: 52 });
|
|
129
|
+
mockRect(column, { top, left: 20, width: 440, height: 52 });
|
|
130
|
+
top += 72;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
return container;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const setMobileGridItems = (engine: FlowEngine, model: GridModel, itemUids: string[]) => {
|
|
137
|
+
(model as any).subModels = {
|
|
138
|
+
items: itemUids.map((itemUid) => engine.createModel({ use: 'FlowModel', uid: itemUid })),
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const getSavedTopLevelItemOrder = (model: GridModel) => {
|
|
143
|
+
return Object.values(model.props.rows || {}).map((columns: string[][]) => columns[0]?.[0]);
|
|
144
|
+
};
|
|
145
|
+
|
|
69
146
|
describe('GridModel drag snapshot container', () => {
|
|
70
147
|
let engine: FlowEngine;
|
|
71
148
|
|
|
@@ -106,6 +183,167 @@ describe('GridModel drag snapshot container', () => {
|
|
|
106
183
|
model.handleDragCancel({} as any);
|
|
107
184
|
});
|
|
108
185
|
|
|
186
|
+
it('filters multi-column drop slots from mobile drag snapshots', () => {
|
|
187
|
+
const model = engine.createModel<GridModel>({
|
|
188
|
+
use: 'GridModel',
|
|
189
|
+
uid: 'grid-mobile-drag-slots',
|
|
190
|
+
props: {
|
|
191
|
+
rows: {
|
|
192
|
+
'row-1': [['item-1'], []],
|
|
193
|
+
},
|
|
194
|
+
sizes: {
|
|
195
|
+
'row-1': [12, 12],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
structure: {} as any,
|
|
199
|
+
});
|
|
200
|
+
model.context.defineProperty('isMobileLayout', { value: true });
|
|
201
|
+
|
|
202
|
+
const container = createGridContainerWithEmptyColumn();
|
|
203
|
+
(model.gridContainerRef as any).current = container;
|
|
204
|
+
|
|
205
|
+
model.handleDragStart({
|
|
206
|
+
active: { id: 'item-1' },
|
|
207
|
+
activatorEvent: { clientX: 80, clientY: 80 },
|
|
208
|
+
} as any);
|
|
209
|
+
|
|
210
|
+
const slotTypes = ((model as any).dragState?.slots || []).map((slot) => slot.type);
|
|
211
|
+
expect(slotTypes).toContain('column');
|
|
212
|
+
expect(slotTypes).toContain('row-gap');
|
|
213
|
+
expect(slotTypes).not.toContain('column-edge');
|
|
214
|
+
expect(slotTypes).not.toContain('item-edge');
|
|
215
|
+
expect(slotTypes).not.toContain('empty-column');
|
|
216
|
+
model.handleDragCancel({} as any);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('keeps empty-row slot available for the first mobile grid item', () => {
|
|
220
|
+
const model = engine.createModel<GridModel>({
|
|
221
|
+
use: 'GridModel',
|
|
222
|
+
uid: 'grid-mobile-empty-drag-slots',
|
|
223
|
+
props: {},
|
|
224
|
+
structure: {} as any,
|
|
225
|
+
});
|
|
226
|
+
model.context.defineProperty('isMobileLayout', { value: true });
|
|
227
|
+
|
|
228
|
+
const container = document.createElement('div');
|
|
229
|
+
mockRect(container, { top: 0, left: 0, width: 480, height: 280 });
|
|
230
|
+
(model.gridContainerRef as any).current = container;
|
|
231
|
+
|
|
232
|
+
model.handleDragStart({
|
|
233
|
+
active: { id: 'item-1' },
|
|
234
|
+
activatorEvent: { clientX: 80, clientY: 80 },
|
|
235
|
+
} as any);
|
|
236
|
+
|
|
237
|
+
expect(((model as any).dragState?.slots || []).map((slot) => slot.type)).toEqual(['empty-row']);
|
|
238
|
+
model.handleDragCancel({} as any);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('saves mobile vertical sorting when moving the second item above the first one', () => {
|
|
242
|
+
const rows = {
|
|
243
|
+
'row-a': [['item-a']],
|
|
244
|
+
'row-b': [['item-b']],
|
|
245
|
+
};
|
|
246
|
+
const model = engine.createModel<GridModel>({
|
|
247
|
+
use: 'GridModel',
|
|
248
|
+
uid: 'grid-mobile-sort-second-above-first',
|
|
249
|
+
props: {
|
|
250
|
+
rows,
|
|
251
|
+
sizes: {
|
|
252
|
+
'row-a': [24],
|
|
253
|
+
'row-b': [24],
|
|
254
|
+
},
|
|
255
|
+
rowOrder: ['row-a', 'row-b'],
|
|
256
|
+
},
|
|
257
|
+
structure: {} as any,
|
|
258
|
+
});
|
|
259
|
+
model.context.defineProperty('isMobileLayout', { value: true });
|
|
260
|
+
setMobileGridItems(engine, model, ['item-a', 'item-b']);
|
|
261
|
+
(model as any).saveStepParams = vi.fn();
|
|
262
|
+
|
|
263
|
+
const container = createProjectedMobileGridContainer(rows);
|
|
264
|
+
(model.gridContainerRef as any).current = container;
|
|
265
|
+
|
|
266
|
+
model.handleDragStart({
|
|
267
|
+
active: { id: 'item-b' },
|
|
268
|
+
activatorEvent: { clientX: 240, clientY: 118 },
|
|
269
|
+
} as any);
|
|
270
|
+
model.handleDragEnd({
|
|
271
|
+
delta: { x: 0, y: -112 },
|
|
272
|
+
} as any);
|
|
273
|
+
|
|
274
|
+
expect(getSavedTopLevelItemOrder(model)).toEqual(['item-b', 'item-a']);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('saves mobile vertical sorting when moving the first item below the last one', () => {
|
|
278
|
+
const rows = {
|
|
279
|
+
'row-a': [['item-a']],
|
|
280
|
+
'row-b': [['item-b']],
|
|
281
|
+
'row-c': [['item-c']],
|
|
282
|
+
};
|
|
283
|
+
const model = engine.createModel<GridModel>({
|
|
284
|
+
use: 'GridModel',
|
|
285
|
+
uid: 'grid-mobile-sort-first-below-last',
|
|
286
|
+
props: {
|
|
287
|
+
rows,
|
|
288
|
+
sizes: {
|
|
289
|
+
'row-a': [24],
|
|
290
|
+
'row-b': [24],
|
|
291
|
+
'row-c': [24],
|
|
292
|
+
},
|
|
293
|
+
rowOrder: ['row-a', 'row-b', 'row-c'],
|
|
294
|
+
},
|
|
295
|
+
structure: {} as any,
|
|
296
|
+
});
|
|
297
|
+
model.context.defineProperty('isMobileLayout', { value: true });
|
|
298
|
+
setMobileGridItems(engine, model, ['item-a', 'item-b', 'item-c']);
|
|
299
|
+
(model as any).saveStepParams = vi.fn();
|
|
300
|
+
|
|
301
|
+
const container = createProjectedMobileGridContainer(rows);
|
|
302
|
+
(model.gridContainerRef as any).current = container;
|
|
303
|
+
|
|
304
|
+
model.handleDragStart({
|
|
305
|
+
active: { id: 'item-a' },
|
|
306
|
+
activatorEvent: { clientX: 240, clientY: 46 },
|
|
307
|
+
} as any);
|
|
308
|
+
model.handleDragEnd({
|
|
309
|
+
delta: { x: 0, y: 184 },
|
|
310
|
+
} as any);
|
|
311
|
+
|
|
312
|
+
expect(getSavedTopLevelItemOrder(model)).toEqual(['item-b', 'item-c', 'item-a']);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('does not filter multi-column drop slots from desktop drag snapshots', () => {
|
|
316
|
+
const model = engine.createModel<GridModel>({
|
|
317
|
+
use: 'GridModel',
|
|
318
|
+
uid: 'grid-desktop-drag-slots',
|
|
319
|
+
props: {
|
|
320
|
+
rows: {
|
|
321
|
+
'row-1': [['item-1'], []],
|
|
322
|
+
},
|
|
323
|
+
sizes: {
|
|
324
|
+
'row-1': [12, 12],
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
structure: {} as any,
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
const container = createGridContainerWithEmptyColumn();
|
|
331
|
+
(model.gridContainerRef as any).current = container;
|
|
332
|
+
|
|
333
|
+
model.handleDragStart({
|
|
334
|
+
active: { id: 'item-1' },
|
|
335
|
+
activatorEvent: { clientX: 80, clientY: 80 },
|
|
336
|
+
} as any);
|
|
337
|
+
|
|
338
|
+
const slotTypes = ((model as any).dragState?.slots || []).map((slot) => slot.type);
|
|
339
|
+
expect(slotTypes).toContain('column');
|
|
340
|
+
expect(slotTypes).toContain('row-gap');
|
|
341
|
+
expect(slotTypes).toContain('column-edge');
|
|
342
|
+
expect(slotTypes).toContain('item-edge');
|
|
343
|
+
expect(slotTypes).toContain('empty-column');
|
|
344
|
+
model.handleDragCancel({} as any);
|
|
345
|
+
});
|
|
346
|
+
|
|
109
347
|
it('uses native pointer position instead of scroll-adjusted drag delta', () => {
|
|
110
348
|
const model = engine.createModel<GridModel>({
|
|
111
349
|
use: 'GridModel',
|
|
@@ -35,6 +35,36 @@ describe('transformRowsToSingleColumn', () => {
|
|
|
35
35
|
expect(all).toEqual([['a'], ['b', 'c'], ['d'], ['e']]);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
+
it('should preserve row ids for ordinary single-column mobile rows', () => {
|
|
39
|
+
const rows = {
|
|
40
|
+
row_a: [['a']],
|
|
41
|
+
row_b: [['b']],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
expect(transformRowsToSingleColumn(rows)).toEqual(rows);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should avoid adding another mobile prefix to ordinary single-column projected rows', () => {
|
|
48
|
+
const rows = {
|
|
49
|
+
'mobile:row_a:0': [['a']],
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
expect(Object.keys(transformRowsToSingleColumn(rows))).toEqual(['mobile:row_a:0']);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should keep split multi-column row keys stable and unique', () => {
|
|
56
|
+
const rows = {
|
|
57
|
+
row_a: [['a'], ['b']],
|
|
58
|
+
};
|
|
59
|
+
const result = transformRowsToSingleColumn(rows);
|
|
60
|
+
const keys = Object.keys(result);
|
|
61
|
+
|
|
62
|
+
expect(keys).toHaveLength(2);
|
|
63
|
+
expect(new Set(keys).size).toBe(2);
|
|
64
|
+
expect(keys.every((key) => key.startsWith('mobile:'))).toBe(true);
|
|
65
|
+
expect(Object.values(result).map((row) => row[0])).toEqual([['a'], ['b']]);
|
|
66
|
+
});
|
|
67
|
+
|
|
38
68
|
it('should skip columns that only contain EMPTY_COLUMN_UID', () => {
|
|
39
69
|
const rows = buildRows([[[EMPTY_COLUMN_UID], ['a']]]);
|
|
40
70
|
const result = transformRowsToSingleColumn(rows);
|
|
@@ -55,4 +85,22 @@ describe('transformRowsToSingleColumn', () => {
|
|
|
55
85
|
const all = Object.values(result).map((r) => r[0]);
|
|
56
86
|
expect(all).toEqual([['x'], ['y']]);
|
|
57
87
|
});
|
|
88
|
+
|
|
89
|
+
it('should keep generated row keys stable for the same input', () => {
|
|
90
|
+
const rows = buildRows([
|
|
91
|
+
[['a'], ['b']],
|
|
92
|
+
[['c'], ['d']],
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
expect(Object.keys(transformRowsToSingleColumn(rows))).toEqual(Object.keys(transformRowsToSingleColumn(rows)));
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should keep existing row keys stable when appending new mobile rows', () => {
|
|
99
|
+
const before = buildRows([[['a'], ['b']]]);
|
|
100
|
+
const after = buildRows([[['a'], ['b']], [['c']]]);
|
|
101
|
+
const beforeKeys = Object.keys(transformRowsToSingleColumn(before));
|
|
102
|
+
const afterKeys = Object.keys(transformRowsToSingleColumn(after));
|
|
103
|
+
|
|
104
|
+
expect(afterKeys.slice(0, beforeKeys.length)).toEqual(beforeKeys);
|
|
105
|
+
});
|
|
58
106
|
});
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
isRunJSValue,
|
|
20
20
|
normalizeRunJSValue,
|
|
21
21
|
parseCtxDateExpression,
|
|
22
|
-
runjsWithSafeGlobals,
|
|
23
22
|
tExpr,
|
|
24
23
|
FlowModelRenderer,
|
|
25
24
|
FlowSettingsButton,
|
|
@@ -513,7 +512,7 @@ export class FilterFormBlockModel extends FilterBlockModel<{
|
|
|
513
512
|
// RunJS support
|
|
514
513
|
if (isRunJSValue(raw)) {
|
|
515
514
|
const { code, version } = normalizeRunJSValue(raw);
|
|
516
|
-
const ret = await
|
|
515
|
+
const ret = await this.context.runjs(code, undefined, { version });
|
|
517
516
|
return ret?.success ? ret.value : undefined;
|
|
518
517
|
}
|
|
519
518
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { tExpr } from '@nocobase/flow-engine';
|
|
11
11
|
import { CodeEditor } from '../../../components/code-editor';
|
|
12
12
|
import { FilterFormActionModel } from './FilterFormActionModel';
|
|
13
13
|
import { resolveRunJsParams } from '../../utils/resolveRunJsParams';
|
|
@@ -60,12 +60,7 @@ FilterFormJSActionModel.registerFlow({
|
|
|
60
60
|
},
|
|
61
61
|
async handler(ctx, params) {
|
|
62
62
|
const { code, version } = resolveRunJsParams(ctx, params);
|
|
63
|
-
|
|
64
|
-
await ctx.runjs(
|
|
65
|
-
code,
|
|
66
|
-
{ window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator },
|
|
67
|
-
{ version },
|
|
68
|
-
);
|
|
63
|
+
await ctx.runjs(code, undefined, { version });
|
|
69
64
|
},
|
|
70
65
|
},
|
|
71
66
|
},
|
|
@@ -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
|
},
|
|
@@ -127,6 +127,93 @@ function createFieldContext(runtime: FormValueRuntime) {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
describe('FormValueRuntime (default rules)', () => {
|
|
130
|
+
it('builds draft snapshots from current user-edited values only', async () => {
|
|
131
|
+
const engineEmitter = new EventEmitter();
|
|
132
|
+
const blockEmitter = new EventEmitter();
|
|
133
|
+
const formStub = createFormStub({});
|
|
134
|
+
const dispatchEvent = vi.fn();
|
|
135
|
+
|
|
136
|
+
const blockModel = {
|
|
137
|
+
uid: 'form-user-edited-draft-snapshot',
|
|
138
|
+
flowEngine: { emitter: engineEmitter },
|
|
139
|
+
emitter: blockEmitter,
|
|
140
|
+
dispatchEvent,
|
|
141
|
+
getAclActionName: () => 'create',
|
|
142
|
+
} as ConstructorParameters<typeof FormValueRuntime>[0]['model'];
|
|
143
|
+
|
|
144
|
+
const runtime = new FormValueRuntime({ model: blockModel, getForm: () => formStub as unknown as FormInstance });
|
|
145
|
+
runtime.mount({ sync: true });
|
|
146
|
+
|
|
147
|
+
const blockCtx = createFieldContext(runtime);
|
|
148
|
+
await runtime.setFormValues(blockCtx, [{ path: ['fixed'], value: 'Fixed auto value' }], { source: 'system' });
|
|
149
|
+
await runtime.setFormValues(blockCtx, [{ path: ['defaultTitle'], value: 'Default auto value' }], {
|
|
150
|
+
source: 'default',
|
|
151
|
+
});
|
|
152
|
+
await runtime.setFormValues(blockCtx, [{ path: ['overrideTitle'], value: 'Override auto value' }], {
|
|
153
|
+
source: 'override',
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
expect(runtime.getUserEditedValuePatches()).toEqual([]);
|
|
157
|
+
expect(runtime.getUserEditedValuesSnapshot()).toEqual({});
|
|
158
|
+
|
|
159
|
+
await runtime.setFormValues(
|
|
160
|
+
blockCtx,
|
|
161
|
+
[
|
|
162
|
+
{ path: ['title'], value: 'Manual title' },
|
|
163
|
+
{ path: ['roles', 0, 'roleName'], value: 'Manual role' },
|
|
164
|
+
],
|
|
165
|
+
{ source: 'user' },
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
expect(runtime.getUserEditedValuePatches()).toEqual([
|
|
169
|
+
{ path: ['title'], value: 'Manual title' },
|
|
170
|
+
{ path: ['roles', 0, 'roleName'], value: 'Manual role' },
|
|
171
|
+
]);
|
|
172
|
+
expect(runtime.getUserEditedValuesSnapshot()).toEqual({
|
|
173
|
+
title: 'Manual title',
|
|
174
|
+
roles: [{ roleName: 'Manual role' }],
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
await runtime.setFormValues(blockCtx, [{ path: ['title'], value: 'Fixed title' }], { source: 'system' });
|
|
178
|
+
|
|
179
|
+
expect(runtime.getUserEditedValuesSnapshot()).toEqual({
|
|
180
|
+
roles: [{ roleName: 'Manual role' }],
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('omits non-user descendant values from parent user-edited draft patches', async () => {
|
|
185
|
+
const engineEmitter = new EventEmitter();
|
|
186
|
+
const blockEmitter = new EventEmitter();
|
|
187
|
+
const formStub = createFormStub({});
|
|
188
|
+
const dispatchEvent = vi.fn();
|
|
189
|
+
|
|
190
|
+
const blockModel = {
|
|
191
|
+
uid: 'form-user-edited-parent-draft-patch',
|
|
192
|
+
flowEngine: { emitter: engineEmitter },
|
|
193
|
+
emitter: blockEmitter,
|
|
194
|
+
dispatchEvent,
|
|
195
|
+
getAclActionName: () => 'create',
|
|
196
|
+
} as ConstructorParameters<typeof FormValueRuntime>[0]['model'];
|
|
197
|
+
|
|
198
|
+
const runtime = new FormValueRuntime({ model: blockModel, getForm: () => formStub as unknown as FormInstance });
|
|
199
|
+
runtime.mount({ sync: true });
|
|
200
|
+
|
|
201
|
+
const blockCtx = createFieldContext(runtime);
|
|
202
|
+
await runtime.setFormValues(
|
|
203
|
+
blockCtx,
|
|
204
|
+
[{ path: ['roles'], value: [{ roleName: 'Manual role', fixedRoleName: 'Initial fixed role' }] }],
|
|
205
|
+
{ source: 'user' },
|
|
206
|
+
);
|
|
207
|
+
await runtime.setFormValues(blockCtx, [{ path: ['roles', 0, 'fixedRoleName'], value: 'System fixed role' }], {
|
|
208
|
+
source: 'system',
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
expect(runtime.getUserEditedValuePatches()).toEqual([{ path: ['roles'], value: [{ roleName: 'Manual role' }] }]);
|
|
212
|
+
expect(runtime.getUserEditedValuesSnapshot()).toEqual({
|
|
213
|
+
roles: [{ roleName: 'Manual role' }],
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
130
217
|
it('skips object patches when values are unchanged', async () => {
|
|
131
218
|
const engineEmitter = new EventEmitter();
|
|
132
219
|
const blockEmitter = new EventEmitter();
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { isObservable, reaction, toJS } from '@formily/reactive';
|
|
11
|
-
import { FlowContext, FlowModel, isRunJSValue, normalizeRunJSValue
|
|
11
|
+
import { FlowContext, FlowModel, isRunJSValue, normalizeRunJSValue } from '@nocobase/flow-engine';
|
|
12
12
|
import { getValuesByPath } from '@nocobase/shared';
|
|
13
13
|
import _ from 'lodash';
|
|
14
14
|
import { dayjs } from '@nocobase/utils/client';
|
|
@@ -1718,7 +1718,7 @@ export class RuleEngine {
|
|
|
1718
1718
|
): Promise<any> {
|
|
1719
1719
|
try {
|
|
1720
1720
|
const { code, version } = normalizeRunJSValue(rawValue);
|
|
1721
|
-
const ret = await
|
|
1721
|
+
const ret = await evalCtx.runjs(code, undefined, { version });
|
|
1722
1722
|
if (!ret?.success) {
|
|
1723
1723
|
if (seq !== state.runSeq) return SKIP_RULE_VALUE;
|
|
1724
1724
|
this.commitRuleDeps(rule, state, collector);
|
|
@@ -38,6 +38,11 @@ type FormBlockModel = FlowModel & {
|
|
|
38
38
|
getAclActionName?: () => string;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
+
export type FormValuePatch = {
|
|
42
|
+
path: NamePath;
|
|
43
|
+
value: unknown;
|
|
44
|
+
};
|
|
45
|
+
|
|
41
46
|
export class FormValueRuntime {
|
|
42
47
|
private readonly model: FormBlockModel;
|
|
43
48
|
private readonly getForm: () => FormInstance;
|
|
@@ -142,6 +147,49 @@ export class FormValueRuntime {
|
|
|
142
147
|
return this.getForm().getFieldsValue(true);
|
|
143
148
|
}
|
|
144
149
|
|
|
150
|
+
getUserEditedValuePatches(): FormValuePatch[] {
|
|
151
|
+
const snapshot = this.getFormValuesSnapshot();
|
|
152
|
+
if (!snapshot || typeof snapshot !== 'object') {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const patches: FormValuePatch[] = [];
|
|
157
|
+
const pathKeys = Array.from(this.userEditedSet).sort(
|
|
158
|
+
(a, b) => pathKeyToNamePath(a).length - pathKeyToNamePath(b).length,
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
for (const pathKey of pathKeys) {
|
|
162
|
+
if (!this.isCurrentUserEditedPath(pathKey)) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const namePath = pathKeyToNamePath(pathKey);
|
|
167
|
+
if (!namePath.length || !_.has(snapshot, namePath as any)) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const value = _.get(snapshot, namePath as any);
|
|
172
|
+
if (typeof value === 'undefined') {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
patches.push({
|
|
177
|
+
path: namePath,
|
|
178
|
+
value: this.omitNonUserDescendantValues(pathKey, this.toMirrorSnapshot(value)),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return patches;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
getUserEditedValuesSnapshot(): Record<string, unknown> {
|
|
186
|
+
const values: Record<string, unknown> = {};
|
|
187
|
+
for (const patch of this.getUserEditedValuePatches()) {
|
|
188
|
+
_.set(values, patch.path as any, patch.value);
|
|
189
|
+
}
|
|
190
|
+
return values;
|
|
191
|
+
}
|
|
192
|
+
|
|
145
193
|
private toMirrorSnapshot(value: any) {
|
|
146
194
|
const raw = isObservable(value) ? toJS(value) : value;
|
|
147
195
|
return _.cloneDeepWith(raw, (item) => {
|
|
@@ -1453,6 +1501,49 @@ export class FormValueRuntime {
|
|
|
1453
1501
|
return null;
|
|
1454
1502
|
}
|
|
1455
1503
|
|
|
1504
|
+
private findLatestWriteMeta(pathKey: string): FormValueWriteMeta | undefined {
|
|
1505
|
+
let latest: FormValueWriteMeta | undefined;
|
|
1506
|
+
const namePath = pathKeyToNamePath(pathKey);
|
|
1507
|
+
const prefix: NamePath = [];
|
|
1508
|
+
|
|
1509
|
+
for (let i = 0; i < namePath.length; i++) {
|
|
1510
|
+
prefix.push(namePath[i]);
|
|
1511
|
+
const meta = this.lastWriteMetaByPathKey.get(namePathToPathKey(prefix as any));
|
|
1512
|
+
if (!meta) {
|
|
1513
|
+
continue;
|
|
1514
|
+
}
|
|
1515
|
+
if (!latest || meta.writeSeq >= latest.writeSeq) {
|
|
1516
|
+
latest = meta;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
return latest;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
private isCurrentUserEditedPath(pathKey: string) {
|
|
1524
|
+
const lastWrite = this.findLatestWriteMeta(pathKey);
|
|
1525
|
+
return !lastWrite || lastWrite.source === 'user';
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
private omitNonUserDescendantValues(pathKey: string, value: unknown) {
|
|
1529
|
+
if (!value || typeof value !== 'object') {
|
|
1530
|
+
return value;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
const namePath = pathKeyToNamePath(pathKey);
|
|
1534
|
+
for (const childKey of this.lastWriteMetaByPathKey.keys()) {
|
|
1535
|
+
if (!this.isDescendantPathKey(childKey, pathKey)) {
|
|
1536
|
+
continue;
|
|
1537
|
+
}
|
|
1538
|
+
if (this.isCurrentUserEditedPath(childKey)) {
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1541
|
+
_.unset(value as Record<string, unknown>, pathKeyToNamePath(childKey).slice(namePath.length) as any);
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
return value;
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1456
1547
|
private isDescendantPathKey(candidateKey: string, parentKey: string) {
|
|
1457
1548
|
if (!candidateKey || !parentKey || candidateKey === parentKey) return false;
|
|
1458
1549
|
const candidatePath = pathKeyToNamePath(candidateKey);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { ElementProxy, tExpr
|
|
10
|
+
import { ElementProxy, tExpr } from '@nocobase/flow-engine';
|
|
11
11
|
import React from 'react';
|
|
12
12
|
import { BlockModel } from '../../base';
|
|
13
13
|
import { BlockItemCard } from '../../../components';
|
|
@@ -388,12 +388,7 @@ ctx.render(\`
|
|
|
388
388
|
},
|
|
389
389
|
},
|
|
390
390
|
});
|
|
391
|
-
|
|
392
|
-
await ctx.runjs(
|
|
393
|
-
code,
|
|
394
|
-
{ window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator },
|
|
395
|
-
{ version },
|
|
396
|
-
);
|
|
391
|
+
await ctx.runjs(code, undefined, { version });
|
|
397
392
|
});
|
|
398
393
|
},
|
|
399
394
|
},
|
|
@@ -19,9 +19,6 @@ import {
|
|
|
19
19
|
createRecordMetaFactory,
|
|
20
20
|
createRecordResolveOnServerWithLocal,
|
|
21
21
|
ElementProxy,
|
|
22
|
-
createSafeDocument,
|
|
23
|
-
createSafeWindow,
|
|
24
|
-
createSafeNavigator,
|
|
25
22
|
observer,
|
|
26
23
|
} from '@nocobase/flow-engine';
|
|
27
24
|
import { Tooltip } from 'antd';
|
|
@@ -294,12 +291,7 @@ JSColumnModel.registerFlow({
|
|
|
294
291
|
get: () => new ElementProxy((ctx.ref?.current as HTMLElement | null) || element),
|
|
295
292
|
cache: false,
|
|
296
293
|
});
|
|
297
|
-
|
|
298
|
-
await ctx.runjs(
|
|
299
|
-
code,
|
|
300
|
-
{ window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator },
|
|
301
|
-
{ version },
|
|
302
|
-
);
|
|
294
|
+
await ctx.runjs(code, undefined, { version });
|
|
303
295
|
});
|
|
304
296
|
},
|
|
305
297
|
},
|
|
@@ -164,7 +164,7 @@ const AddActionToolbarComponent = observer(({ model }: any) => {
|
|
|
164
164
|
subModelBaseClass={model.context.getModelClassName('RecordActionGroupModel')}
|
|
165
165
|
subModelKey="actions"
|
|
166
166
|
afterSubModelInit={async (actionModel) => {
|
|
167
|
-
actionModel.setStepParams('buttonSettings', 'general', { type: 'link', icon: null });
|
|
167
|
+
actionModel.setStepParams('buttonSettings', 'general', { type: 'link', icon: null, iconOnly: false });
|
|
168
168
|
}}
|
|
169
169
|
>
|
|
170
170
|
<PlusOutlined />
|