@nocobase/client-v2 2.2.0-alpha.7 → 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 +1 -1
- package/es/components/form/TypedVariableInput.d.ts +5 -31
- package/es/components/form/filter/CollectionFilter.d.ts +0 -2
- package/es/components/form/filter/CollectionFilterItem.d.ts +1 -11
- package/es/components/form/filter/CollectionFilterPanel.d.ts +0 -2
- package/es/components/form/filter/index.d.ts +0 -2
- package/es/components/form/filter/useFilterActionProps.d.ts +0 -2
- package/es/components/index.d.ts +0 -1
- package/es/flow/components/FieldAssignExactDatePicker.d.ts +0 -1
- package/es/flow/components/FieldAssignValueInput.d.ts +0 -3
- package/es/flow/components/RunJSValueEditor.d.ts +0 -1
- package/es/flow/index.d.ts +0 -1
- package/es/index.d.ts +0 -4
- package/es/index.mjs +99 -133
- package/es/utils/index.d.ts +0 -1
- package/lib/index.js +106 -140
- package/package.json +7 -8
- package/src/BaseApplication.tsx +6 -6
- package/src/__tests__/app.test.tsx +0 -26
- package/src/__tests__/browserChecker.test.ts +0 -61
- package/src/components/README.md +1 -7
- package/src/components/README.zh-CN.md +1 -6
- package/src/components/form/JsonTextArea.tsx +0 -4
- package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +2 -145
- package/src/components/form/ScanInput/useCodeScanner.ts +2 -154
- package/src/components/form/TypedVariableInput.tsx +98 -445
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +9 -320
- package/src/components/form/filter/CollectionFilter.tsx +0 -4
- package/src/components/form/filter/CollectionFilterItem.tsx +7 -32
- package/src/components/form/filter/CollectionFilterPanel.tsx +0 -4
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +0 -38
- package/src/components/form/filter/index.ts +0 -2
- package/src/components/form/filter/useFilterActionProps.ts +6 -37
- package/src/components/index.ts +0 -1
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +1 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +6 -253
- package/src/flow/components/FieldAssignExactDatePicker.tsx +11 -25
- package/src/flow/components/FieldAssignValueInput.tsx +9 -55
- package/src/flow/components/RunJSValueEditor.tsx +1 -9
- package/src/flow/index.ts +0 -1
- package/src/index.ts +0 -4
- package/src/utils/index.tsx +0 -1
- package/es/components/category-tabs/SortableCategoryTabs.d.ts +0 -55
- package/es/components/category-tabs/index.d.ts +0 -9
- package/es/utils/getRouteRuntimeVersion.d.ts +0 -23
- package/src/__tests__/getRouteRuntimeVersion.test.ts +0 -68
- package/src/components/category-tabs/SortableCategoryTabs.tsx +0 -210
- package/src/components/category-tabs/index.ts +0 -10
- package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +0 -95
- package/src/utils/getRouteRuntimeVersion.ts +0 -185
|
@@ -11,58 +11,23 @@ import { FlowEngine, FlowEngineProvider } from '@nocobase/flow-engine';
|
|
|
11
11
|
import { act, render, screen, waitFor } from '@testing-library/react';
|
|
12
12
|
import React, { useEffect } from 'react';
|
|
13
13
|
import { createMemoryRouter, RouterProvider, useParams } from 'react-router-dom';
|
|
14
|
-
import {
|
|
15
|
-
import { NocoBaseDesktopRouteType, type NocoBaseDesktopRoute } from '../../../../flow-compat';
|
|
14
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
16
15
|
import type { LayoutDefinition } from '../../../../layout-manager/types';
|
|
17
16
|
import { AdminLayoutComponent } from '../AdminLayoutComponent';
|
|
18
17
|
import { AdminLayoutModel } from '../AdminLayoutModel';
|
|
19
|
-
import { AdminLayoutMenuItemModel } from '../AdminLayoutMenuModels';
|
|
20
18
|
import { AdminLayoutContent } from '../AdminLayoutSlotModels';
|
|
21
19
|
|
|
22
|
-
const proLayoutLifecycle = vi.hoisted(() => ({
|
|
23
|
-
events: [] as string[],
|
|
24
|
-
routes: [] as Array<{ children?: Array<{ name?: React.ReactNode }> }>,
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
20
|
vi.mock('@ant-design/pro-layout', async () => {
|
|
28
21
|
const ReactModule = await import('react');
|
|
29
22
|
const RouteContext = ReactModule.createContext({ isMobile: false });
|
|
30
|
-
const ProLayoutMock = (props: {
|
|
31
|
-
children?: React.ReactNode;
|
|
32
|
-
route?: { children?: Array<{ name?: React.ReactNode }> };
|
|
33
|
-
}) => {
|
|
34
|
-
ReactModule.useEffect(() => {
|
|
35
|
-
proLayoutLifecycle.events.push('pro-layout:mount');
|
|
36
|
-
return () => {
|
|
37
|
-
proLayoutLifecycle.events.push('pro-layout:unmount');
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
|
-
proLayoutLifecycle.routes.push(props.route || {});
|
|
41
23
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{ value: { isMobile: false } },
|
|
24
|
+
return {
|
|
25
|
+
default: (props: { children?: React.ReactNode }) =>
|
|
45
26
|
ReactModule.createElement(
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
ReactModule.createElement(
|
|
49
|
-
'nav',
|
|
50
|
-
{ 'data-testid': 'pro-layout-menu' },
|
|
51
|
-
(props.route?.children || []).map((item) =>
|
|
52
|
-
ReactModule.createElement(
|
|
53
|
-
'span',
|
|
54
|
-
{ key: String(item.name), 'data-testid': 'pro-layout-menu-item' },
|
|
55
|
-
item.name,
|
|
56
|
-
),
|
|
57
|
-
),
|
|
58
|
-
),
|
|
59
|
-
props.children,
|
|
27
|
+
RouteContext.Provider,
|
|
28
|
+
{ value: { isMobile: false } },
|
|
29
|
+
ReactModule.createElement('div', { 'data-testid': 'pro-layout' }, props.children),
|
|
60
30
|
),
|
|
61
|
-
);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
default: ProLayoutMock,
|
|
66
31
|
RouteContext,
|
|
67
32
|
};
|
|
68
33
|
});
|
|
@@ -88,10 +53,6 @@ vi.mock('../AppListRender', () => ({
|
|
|
88
53
|
useAppListRender: () => undefined,
|
|
89
54
|
}));
|
|
90
55
|
|
|
91
|
-
afterEach(() => {
|
|
92
|
-
delete (window as Window & { __nocobase_modern_client_prefix__?: string }).__nocobase_modern_client_prefix__;
|
|
93
|
-
});
|
|
94
|
-
|
|
95
56
|
describe('AdminLayoutComponent', () => {
|
|
96
57
|
it('keeps custom admin layout pages alive by layout route name', async () => {
|
|
97
58
|
const layout: LayoutDefinition = {
|
|
@@ -224,212 +185,4 @@ describe('AdminLayoutComponent', () => {
|
|
|
224
185
|
|
|
225
186
|
expect(deactivateLayout).toHaveBeenCalledTimes(1);
|
|
226
187
|
});
|
|
227
|
-
|
|
228
|
-
it('keeps layout content mounted when the menu route tree refreshes', async () => {
|
|
229
|
-
proLayoutLifecycle.events = [];
|
|
230
|
-
proLayoutLifecycle.routes = [];
|
|
231
|
-
const layout: LayoutDefinition = {
|
|
232
|
-
routeName: 'admin',
|
|
233
|
-
routePath: '/admin',
|
|
234
|
-
rootRouteName: 'admin',
|
|
235
|
-
uid: 'admin-layout-model',
|
|
236
|
-
layoutModelClass: 'AdminLayoutModel',
|
|
237
|
-
rootPageModelClass: 'RootPageModel',
|
|
238
|
-
childPageModelClass: 'ChildPageModel',
|
|
239
|
-
authCheck: true,
|
|
240
|
-
};
|
|
241
|
-
const events: string[] = [];
|
|
242
|
-
const engine = new FlowEngine();
|
|
243
|
-
engine.context.defineProperty('routeRepository', {
|
|
244
|
-
value: {
|
|
245
|
-
activateLayout: vi.fn(() => vi.fn()),
|
|
246
|
-
ensureAccessibleLoaded: vi.fn(async () => []),
|
|
247
|
-
listAccessible: () => [],
|
|
248
|
-
subscribe: vi.fn(),
|
|
249
|
-
unsubscribe: vi.fn(),
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
engine.context.defineProperty('t', {
|
|
253
|
-
value: (key: string) => key,
|
|
254
|
-
});
|
|
255
|
-
const model = engine.createModel<AdminLayoutModel>({
|
|
256
|
-
uid: layout.uid,
|
|
257
|
-
use: AdminLayoutModel,
|
|
258
|
-
props: {
|
|
259
|
-
layout,
|
|
260
|
-
},
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
const Page = () => {
|
|
264
|
-
useEffect(() => {
|
|
265
|
-
events.push('page:mount');
|
|
266
|
-
return () => {
|
|
267
|
-
events.push('page:unmount');
|
|
268
|
-
};
|
|
269
|
-
}, []);
|
|
270
|
-
|
|
271
|
-
return <div data-testid="custom-admin-route">Workflow tasks</div>;
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const router = createMemoryRouter(
|
|
275
|
-
[
|
|
276
|
-
{
|
|
277
|
-
id: layout.routeName,
|
|
278
|
-
path: layout.routePath,
|
|
279
|
-
element: <AdminLayoutComponent model={model} />,
|
|
280
|
-
children: [
|
|
281
|
-
{
|
|
282
|
-
id: 'admin.workflow.tasks',
|
|
283
|
-
path: 'workflow/tasks/:taskType?/:status?/:popupId?',
|
|
284
|
-
element: <Page />,
|
|
285
|
-
},
|
|
286
|
-
],
|
|
287
|
-
},
|
|
288
|
-
],
|
|
289
|
-
{
|
|
290
|
-
initialEntries: ['/admin/workflow/tasks/approval-apply/pending'],
|
|
291
|
-
},
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
render(
|
|
295
|
-
<FlowEngineProvider engine={engine}>
|
|
296
|
-
<RouterProvider router={router} />
|
|
297
|
-
</FlowEngineProvider>,
|
|
298
|
-
);
|
|
299
|
-
|
|
300
|
-
expect(await screen.findByTestId('custom-admin-route')).toBeInTheDocument();
|
|
301
|
-
expect(proLayoutLifecycle.events).toEqual(['pro-layout:mount']);
|
|
302
|
-
|
|
303
|
-
act(() => {
|
|
304
|
-
model.refreshMenuRouteTree();
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
await act(async () => {
|
|
308
|
-
await router.navigate('/admin/workflow/tasks/approval-apply/pending/1');
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
expect(screen.getByTestId('custom-admin-route')).toBeInTheDocument();
|
|
312
|
-
expect(proLayoutLifecycle.events).toEqual(['pro-layout:mount']);
|
|
313
|
-
expect(events).toEqual(['page:mount']);
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it('updates ProLayout menu routes after accessible routes change without remounting the layout', async () => {
|
|
317
|
-
proLayoutLifecycle.events = [];
|
|
318
|
-
proLayoutLifecycle.routes = [];
|
|
319
|
-
(window as Window & { __nocobase_modern_client_prefix__?: string }).__nocobase_modern_client_prefix__ = 'v2';
|
|
320
|
-
const layout: LayoutDefinition = {
|
|
321
|
-
routeName: 'admin',
|
|
322
|
-
routePath: '/admin',
|
|
323
|
-
rootRouteName: 'admin',
|
|
324
|
-
uid: 'admin-layout-model',
|
|
325
|
-
layoutModelClass: 'AdminLayoutModel',
|
|
326
|
-
rootPageModelClass: 'RootPageModel',
|
|
327
|
-
childPageModelClass: 'ChildPageModel',
|
|
328
|
-
authCheck: true,
|
|
329
|
-
};
|
|
330
|
-
let accessibleRoutes: NocoBaseDesktopRoute[] = [
|
|
331
|
-
{
|
|
332
|
-
id: 1,
|
|
333
|
-
title: 'Visible page',
|
|
334
|
-
schemaUid: 'visible-page',
|
|
335
|
-
type: NocoBaseDesktopRouteType.flowPage,
|
|
336
|
-
},
|
|
337
|
-
];
|
|
338
|
-
let routeRepositorySubscriber: (() => void) | undefined;
|
|
339
|
-
const events: string[] = [];
|
|
340
|
-
const engine = new FlowEngine();
|
|
341
|
-
engine.registerModels({
|
|
342
|
-
AdminLayoutMenuItemModel,
|
|
343
|
-
});
|
|
344
|
-
engine.context.defineProperty('routeRepository', {
|
|
345
|
-
value: {
|
|
346
|
-
activateLayout: vi.fn(() => vi.fn()),
|
|
347
|
-
ensureAccessibleLoaded: vi.fn(async () => accessibleRoutes),
|
|
348
|
-
listAccessible: () => accessibleRoutes,
|
|
349
|
-
subscribe: vi.fn((subscriber: () => void) => {
|
|
350
|
-
routeRepositorySubscriber = subscriber;
|
|
351
|
-
}),
|
|
352
|
-
unsubscribe: vi.fn(),
|
|
353
|
-
},
|
|
354
|
-
});
|
|
355
|
-
engine.context.defineProperty('app', {
|
|
356
|
-
value: {
|
|
357
|
-
getPublicPath: () => '/v/',
|
|
358
|
-
router: {
|
|
359
|
-
getBasename: () => '/v',
|
|
360
|
-
},
|
|
361
|
-
},
|
|
362
|
-
});
|
|
363
|
-
engine.context.defineProperty('t', {
|
|
364
|
-
value: (key: string) => key,
|
|
365
|
-
});
|
|
366
|
-
const model = engine.createModel<AdminLayoutModel>({
|
|
367
|
-
uid: layout.uid,
|
|
368
|
-
use: AdminLayoutModel,
|
|
369
|
-
props: {
|
|
370
|
-
layout,
|
|
371
|
-
},
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
const Page = () => {
|
|
375
|
-
useEffect(() => {
|
|
376
|
-
events.push('page:mount');
|
|
377
|
-
return () => {
|
|
378
|
-
events.push('page:unmount');
|
|
379
|
-
};
|
|
380
|
-
}, []);
|
|
381
|
-
|
|
382
|
-
return <div data-testid="custom-admin-route">Workflow tasks</div>;
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
const router = createMemoryRouter(
|
|
386
|
-
[
|
|
387
|
-
{
|
|
388
|
-
id: layout.routeName,
|
|
389
|
-
path: layout.routePath,
|
|
390
|
-
element: <AdminLayoutComponent model={model} />,
|
|
391
|
-
children: [
|
|
392
|
-
{
|
|
393
|
-
id: 'admin.workflow.tasks',
|
|
394
|
-
path: 'workflow/tasks/:taskType?/:status?/:popupId?',
|
|
395
|
-
element: <Page />,
|
|
396
|
-
},
|
|
397
|
-
],
|
|
398
|
-
},
|
|
399
|
-
],
|
|
400
|
-
{
|
|
401
|
-
initialEntries: ['/admin/workflow/tasks/approval-apply/pending'],
|
|
402
|
-
},
|
|
403
|
-
);
|
|
404
|
-
|
|
405
|
-
render(
|
|
406
|
-
<FlowEngineProvider engine={engine}>
|
|
407
|
-
<RouterProvider router={router} />
|
|
408
|
-
</FlowEngineProvider>,
|
|
409
|
-
);
|
|
410
|
-
|
|
411
|
-
expect(await screen.findByText('Visible page')).toBeInTheDocument();
|
|
412
|
-
expect(proLayoutLifecycle.events).toEqual(['pro-layout:mount']);
|
|
413
|
-
|
|
414
|
-
act(() => {
|
|
415
|
-
accessibleRoutes = [];
|
|
416
|
-
routeRepositorySubscriber?.();
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
await waitFor(() => {
|
|
420
|
-
expect(screen.queryByText('Visible page')).not.toBeInTheDocument();
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
await act(async () => {
|
|
424
|
-
await router.navigate('/admin/workflow/tasks/approval-apply/pending/1');
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
expect(screen.getByTestId('custom-admin-route')).toBeInTheDocument();
|
|
428
|
-
expect(proLayoutLifecycle.events).toEqual(['pro-layout:mount']);
|
|
429
|
-
expect(events).toEqual(['page:mount']);
|
|
430
|
-
expect(
|
|
431
|
-
proLayoutLifecycle.routes.some((route) => route.children?.some((item) => item.name === 'Visible page')),
|
|
432
|
-
).toBe(true);
|
|
433
|
-
expect(proLayoutLifecycle.routes.at(-1)?.children?.some((item) => item.name === 'Visible page')).toBe(false);
|
|
434
|
-
});
|
|
435
188
|
});
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import React, {
|
|
10
|
+
import React, { useMemo, useState } from 'react';
|
|
11
11
|
import { DatePicker, Select, Space } from 'antd';
|
|
12
12
|
import { inferPickerType } from '../../flow-compat';
|
|
13
13
|
import { dayjs, getDateTimeFormat, getPickerFormat } from '@nocobase/utils/client';
|
|
@@ -29,7 +29,6 @@ export interface FieldAssignExactDatePickerProps {
|
|
|
29
29
|
isRange?: boolean;
|
|
30
30
|
onChange?: (value: ExactDatePickerValue) => void;
|
|
31
31
|
style?: React.CSSProperties;
|
|
32
|
-
disabled?: boolean;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
function getRawSingleValue(value: unknown, isRange: boolean): unknown {
|
|
@@ -115,7 +114,7 @@ function parseRangeValue(value: unknown, format: string): [dayjs.Dayjs, dayjs.Da
|
|
|
115
114
|
}
|
|
116
115
|
|
|
117
116
|
export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProps> = (props) => {
|
|
118
|
-
const { picker = 'date', format, showTime, timeFormat, value, isRange = false, onChange, style
|
|
117
|
+
const { picker = 'date', format, showTime, timeFormat, value, isRange = false, onChange, style } = props;
|
|
119
118
|
const flowCtx = useFlowContext();
|
|
120
119
|
const t = flowCtx.model.translate.bind(flowCtx.model);
|
|
121
120
|
|
|
@@ -125,16 +124,16 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
125
124
|
return inferPickerFromRawValue(rawSingleValue, picker);
|
|
126
125
|
});
|
|
127
126
|
|
|
128
|
-
const getResolvedFormat =
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
},
|
|
134
|
-
[format, picker, showTime, timeFormat],
|
|
135
|
-
);
|
|
127
|
+
const getResolvedFormat = (nextPicker: ExactDatePickerMode) => {
|
|
128
|
+
const baseFormat = nextPicker === picker && format ? format : getPickerFormat(nextPicker);
|
|
129
|
+
const dateFormat = nextPicker === 'date' ? stripTimeFromFormat(baseFormat) : baseFormat;
|
|
130
|
+
return getDateTimeFormat(nextPicker, dateFormat, showTime, timeFormat);
|
|
131
|
+
};
|
|
136
132
|
|
|
137
|
-
const resolvedFormat = useMemo(
|
|
133
|
+
const resolvedFormat = useMemo(
|
|
134
|
+
() => getResolvedFormat(targetPicker),
|
|
135
|
+
[targetPicker, format, picker, showTime, timeFormat],
|
|
136
|
+
);
|
|
138
137
|
|
|
139
138
|
const singleValue = useMemo(() => {
|
|
140
139
|
if (isRange) return null;
|
|
@@ -157,10 +156,6 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
157
156
|
);
|
|
158
157
|
|
|
159
158
|
const handlePickerTypeChange = (nextPicker: ExactDatePickerMode) => {
|
|
160
|
-
if (disabled) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
159
|
setTargetPicker(nextPicker);
|
|
165
160
|
|
|
166
161
|
if (!onChange) {
|
|
@@ -187,11 +182,7 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
187
182
|
inputReadOnly: flowCtx.isMobileLayout,
|
|
188
183
|
showTime: showTime ? { defaultValue: dayjs('00:00:00', 'HH:mm:ss') } : false,
|
|
189
184
|
value: singleValue,
|
|
190
|
-
disabled,
|
|
191
185
|
onChange: (nextDate: dayjs.Dayjs | null) => {
|
|
192
|
-
if (disabled) {
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
186
|
if (nextDate && dayjs.isDayjs(nextDate)) {
|
|
196
187
|
onChange?.(nextDate);
|
|
197
188
|
return;
|
|
@@ -209,11 +200,7 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
209
200
|
inputReadOnly: flowCtx.isMobileLayout,
|
|
210
201
|
showTime: showTime ? { defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')] } : false,
|
|
211
202
|
value: rangeValue,
|
|
212
|
-
disabled,
|
|
213
203
|
onChange: (nextDates: [dayjs.Dayjs | null, dayjs.Dayjs | null] | null) => {
|
|
214
|
-
if (disabled) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
204
|
if (Array.isArray(nextDates) && nextDates[0] && nextDates[1]) {
|
|
218
205
|
onChange?.([nextDates[0], nextDates[1]]);
|
|
219
206
|
return;
|
|
@@ -231,7 +218,6 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
231
218
|
value={targetPicker}
|
|
232
219
|
options={pickerOptions}
|
|
233
220
|
onChange={handlePickerTypeChange}
|
|
234
|
-
disabled={disabled}
|
|
235
221
|
/>
|
|
236
222
|
{isRange ? <DatePicker.RangePicker {...rangePickerProps} /> : <DatePicker {...singlePickerProps} />}
|
|
237
223
|
</Space.Compact>
|
|
@@ -341,10 +341,7 @@ interface Props {
|
|
|
341
341
|
* 默认 false,保持历史行为。
|
|
342
342
|
*/
|
|
343
343
|
enableDateVariableAsConstant?: boolean;
|
|
344
|
-
/** 是否允许在变量选择器中使用 RunJS。默认 true,保持历史行为。 */
|
|
345
|
-
allowRunJS?: boolean;
|
|
346
344
|
maxAssociationFieldDepth?: number;
|
|
347
|
-
disabled?: boolean;
|
|
348
345
|
}
|
|
349
346
|
|
|
350
347
|
type ResolvedFieldContext = {
|
|
@@ -715,9 +712,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
715
712
|
preferFormItemFieldModel,
|
|
716
713
|
associationFieldNamesOverride,
|
|
717
714
|
enableDateVariableAsConstant = false,
|
|
718
|
-
allowRunJS = true,
|
|
719
715
|
maxAssociationFieldDepth = 2,
|
|
720
|
-
disabled = false,
|
|
721
716
|
}) => {
|
|
722
717
|
const flowCtx = useFlowContext<FlowModelContext>();
|
|
723
718
|
const normalizeEventValue = React.useCallback((eventOrValue: unknown) => {
|
|
@@ -1082,7 +1077,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1082
1077
|
fm.setStepParams('selectSettings', 'fieldNames', { label: overrideLabel });
|
|
1083
1078
|
}
|
|
1084
1079
|
fm?.setProps?.({
|
|
1085
|
-
disabled,
|
|
1080
|
+
disabled: false,
|
|
1086
1081
|
readPretty: false,
|
|
1087
1082
|
pattern: 'editable',
|
|
1088
1083
|
updateAssociation: false,
|
|
@@ -1145,7 +1140,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1145
1140
|
preferFormItemFieldModel,
|
|
1146
1141
|
associationFieldNamesOverride?.label,
|
|
1147
1142
|
associationFieldNamesOverride?.value,
|
|
1148
|
-
disabled,
|
|
1149
1143
|
]);
|
|
1150
1144
|
|
|
1151
1145
|
// 当传入 operator / operatorMetaList 时,按 operator schema 适配临时字段的输入组件与 props。
|
|
@@ -1198,9 +1192,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1198
1192
|
React.useEffect(() => {
|
|
1199
1193
|
const coercedValue = coerceEmptyValueForRenderer(inputProps?.value);
|
|
1200
1194
|
const handleChange = (ev: any) => {
|
|
1201
|
-
if (inputProps?.disabled) {
|
|
1202
|
-
return;
|
|
1203
|
-
}
|
|
1204
1195
|
const nextRaw = normalizeEventValue(ev);
|
|
1205
1196
|
const normalizedForStore = operator ? normalizeFilterValueByOperator(operator, nextRaw) : nextRaw;
|
|
1206
1197
|
const nextValue = coerceEmptyValueForRenderer(normalizedForStore);
|
|
@@ -1232,7 +1223,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1232
1223
|
value={inputProps?.value}
|
|
1233
1224
|
onChange={(e) => inputProps?.onChange?.(normalizeEventValue(e))}
|
|
1234
1225
|
placeholder={placeholder}
|
|
1235
|
-
disabled={inputProps?.disabled}
|
|
1236
1226
|
style={withFullWidthStyle(wrapperStyle)}
|
|
1237
1227
|
/>
|
|
1238
1228
|
);
|
|
@@ -1251,7 +1241,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1251
1241
|
const C: React.FC<any> = (inputProps) => {
|
|
1252
1242
|
const wrapperStyle = pickStyle(inputProps?.style);
|
|
1253
1243
|
const raw = inputProps?.value;
|
|
1254
|
-
const isDisabled = Boolean(inputProps?.disabled);
|
|
1255
1244
|
const parsed = isCtxDateExpression(raw) ? parseCtxDateExpression(raw) : raw;
|
|
1256
1245
|
const parsedValue = typeof parsed === 'undefined' ? undefined : parsed;
|
|
1257
1246
|
const { token } = theme.useToken();
|
|
@@ -1276,9 +1265,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1276
1265
|
});
|
|
1277
1266
|
|
|
1278
1267
|
const handleSelect = (val: string) => {
|
|
1279
|
-
if (isDisabled) {
|
|
1280
|
-
return;
|
|
1281
|
-
}
|
|
1282
1268
|
setOpen(false);
|
|
1283
1269
|
if (val === 'exact') {
|
|
1284
1270
|
inputProps?.onChange?.('');
|
|
@@ -1293,16 +1279,10 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1293
1279
|
};
|
|
1294
1280
|
|
|
1295
1281
|
const handleExactSingleChange = (nextValue: any) => {
|
|
1296
|
-
if (isDisabled) {
|
|
1297
|
-
return;
|
|
1298
|
-
}
|
|
1299
1282
|
inputProps?.onChange?.(nextValue || '');
|
|
1300
1283
|
};
|
|
1301
1284
|
|
|
1302
1285
|
const handleExactRangeChange = (nextValue: any) => {
|
|
1303
|
-
if (isDisabled) {
|
|
1304
|
-
return;
|
|
1305
|
-
}
|
|
1306
1286
|
inputProps?.onChange?.(nextValue || '');
|
|
1307
1287
|
};
|
|
1308
1288
|
|
|
@@ -1347,11 +1327,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1347
1327
|
<Select
|
|
1348
1328
|
options={options}
|
|
1349
1329
|
open={open}
|
|
1350
|
-
onDropdownVisibleChange={
|
|
1351
|
-
if (!isDisabled) {
|
|
1352
|
-
setOpen(nextOpen);
|
|
1353
|
-
}
|
|
1354
|
-
}}
|
|
1330
|
+
onDropdownVisibleChange={setOpen}
|
|
1355
1331
|
allowClear={false}
|
|
1356
1332
|
style={{
|
|
1357
1333
|
width: '100%',
|
|
@@ -1361,18 +1337,13 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1361
1337
|
value={selectedType}
|
|
1362
1338
|
onChange={handleSelect}
|
|
1363
1339
|
dropdownRender={dropdownRender}
|
|
1364
|
-
disabled={isDisabled}
|
|
1365
1340
|
/>
|
|
1366
1341
|
{['past', 'next'].includes(selectedType) && [
|
|
1367
1342
|
<InputNumber
|
|
1368
1343
|
key="number"
|
|
1369
1344
|
style={{ flex: 1 }}
|
|
1370
1345
|
value={(parsedValue as any)?.number}
|
|
1371
|
-
disabled={isDisabled}
|
|
1372
1346
|
onChange={(nextNumber) => {
|
|
1373
|
-
if (isDisabled) {
|
|
1374
|
-
return;
|
|
1375
|
-
}
|
|
1376
1347
|
inputProps?.onChange?.({
|
|
1377
1348
|
...(parsedValue as any),
|
|
1378
1349
|
type: selectedType,
|
|
@@ -1385,11 +1356,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1385
1356
|
key="unit"
|
|
1386
1357
|
value={(parsedValue as any)?.unit}
|
|
1387
1358
|
style={{ minWidth: 130, maxWidth: 140 }}
|
|
1388
|
-
disabled={isDisabled}
|
|
1389
1359
|
onChange={(nextUnit) => {
|
|
1390
|
-
if (isDisabled) {
|
|
1391
|
-
return;
|
|
1392
|
-
}
|
|
1393
1360
|
inputProps?.onChange?.({
|
|
1394
1361
|
...(parsedValue as any),
|
|
1395
1362
|
type: selectedType,
|
|
@@ -1412,7 +1379,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1412
1379
|
isRange={isRange}
|
|
1413
1380
|
value={isRange ? exactRangeValue : exactSingleValue}
|
|
1414
1381
|
onChange={isRange ? handleExactRangeChange : handleExactSingleChange}
|
|
1415
|
-
disabled={isDisabled}
|
|
1416
1382
|
style={{ flex: 1 }}
|
|
1417
1383
|
/>
|
|
1418
1384
|
)}
|
|
@@ -1432,12 +1398,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1432
1398
|
|
|
1433
1399
|
const RunJSComponent = React.useMemo(() => {
|
|
1434
1400
|
const C: React.FC<any> = (inputProps) => (
|
|
1435
|
-
<RunJSValueEditor
|
|
1436
|
-
t={flowCtx.t}
|
|
1437
|
-
value={inputProps?.value}
|
|
1438
|
-
onChange={inputProps?.onChange}
|
|
1439
|
-
disabled={inputProps?.disabled}
|
|
1440
|
-
/>
|
|
1401
|
+
<RunJSValueEditor t={flowCtx.t} value={inputProps?.value} onChange={inputProps?.onChange} />
|
|
1441
1402
|
);
|
|
1442
1403
|
return C;
|
|
1443
1404
|
}, [flowCtx]);
|
|
@@ -1460,13 +1421,11 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1460
1421
|
render: ConstantEditor,
|
|
1461
1422
|
},
|
|
1462
1423
|
{ title: tExpr('Null'), name: 'null', type: 'object', paths: ['null'], render: NullComponent },
|
|
1463
|
-
|
|
1464
|
-
? [{ title: tExpr('RunJS'), name: 'runjs', type: 'object', paths: ['runjs'], render: RunJSComponent }]
|
|
1465
|
-
: []),
|
|
1424
|
+
{ title: tExpr('RunJS'), name: 'runjs', type: 'object', paths: ['runjs'], render: RunJSComponent },
|
|
1466
1425
|
...limitedBase,
|
|
1467
1426
|
];
|
|
1468
1427
|
};
|
|
1469
|
-
}, [flowCtx, ConstantEditor, NullComponent, RunJSComponent,
|
|
1428
|
+
}, [flowCtx, ConstantEditor, NullComponent, RunJSComponent, maxAssociationFieldDepth]);
|
|
1470
1429
|
|
|
1471
1430
|
const displayValue = React.useMemo(() => {
|
|
1472
1431
|
if (!useDateVariableConstant) {
|
|
@@ -1483,10 +1442,6 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1483
1442
|
|
|
1484
1443
|
const handleVariableInputChange = React.useCallback(
|
|
1485
1444
|
(nextValue: any) => {
|
|
1486
|
-
if (disabled) {
|
|
1487
|
-
return;
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
1445
|
if (!useDateVariableConstant) {
|
|
1491
1446
|
onChange(nextValue);
|
|
1492
1447
|
return;
|
|
@@ -1494,7 +1449,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1494
1449
|
|
|
1495
1450
|
onChange(normalizeDateVariableOutput(nextValue, dateVariableComponentProps));
|
|
1496
1451
|
},
|
|
1497
|
-
[dateVariableComponentProps,
|
|
1452
|
+
[dateVariableComponentProps, onChange, useDateVariableConstant],
|
|
1498
1453
|
);
|
|
1499
1454
|
|
|
1500
1455
|
if (!fieldPath) {
|
|
@@ -1509,13 +1464,12 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1509
1464
|
metaTree={metaTree}
|
|
1510
1465
|
style={{ width: '100%' }}
|
|
1511
1466
|
clearValue={''}
|
|
1512
|
-
disabled={disabled}
|
|
1513
1467
|
converters={{
|
|
1514
1468
|
renderInputComponent: (meta) => {
|
|
1515
1469
|
const firstPath = meta?.paths?.[0];
|
|
1516
1470
|
if (firstPath === 'constant') return ConstantEditor;
|
|
1517
1471
|
if (firstPath === 'null') return NullComponent;
|
|
1518
|
-
if (
|
|
1472
|
+
if (firstPath === 'runjs') return RunJSComponent;
|
|
1519
1473
|
return null;
|
|
1520
1474
|
},
|
|
1521
1475
|
resolveValueFromPath: (item) => {
|
|
@@ -1524,12 +1478,12 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1524
1478
|
return useDateVariableConstant ? { type: 'today' } : '';
|
|
1525
1479
|
}
|
|
1526
1480
|
if (firstPath === 'null') return null;
|
|
1527
|
-
if (
|
|
1481
|
+
if (firstPath === 'runjs') return { code: '', version: 'v2' };
|
|
1528
1482
|
return undefined;
|
|
1529
1483
|
},
|
|
1530
1484
|
resolvePathFromValue: (currentValue) => {
|
|
1531
1485
|
if (currentValue === null) return ['null'];
|
|
1532
|
-
if (
|
|
1486
|
+
if (isRunJSValue(currentValue)) return ['runjs'];
|
|
1533
1487
|
if (useDateVariableConstant && isCtxDateExpression(currentValue)) {
|
|
1534
1488
|
return ['constant'];
|
|
1535
1489
|
}
|
|
@@ -15,7 +15,6 @@ export interface RunJSValueEditorProps {
|
|
|
15
15
|
t?: (key: string) => string;
|
|
16
16
|
value?: unknown;
|
|
17
17
|
onChange?: (value: RunJSValue) => void;
|
|
18
|
-
disabled?: boolean;
|
|
19
18
|
height?: string;
|
|
20
19
|
scene?: string;
|
|
21
20
|
containerStyle?: React.CSSProperties;
|
|
@@ -26,7 +25,6 @@ export const RunJSValueEditor: React.FC<RunJSValueEditorProps> = (props) => {
|
|
|
26
25
|
t,
|
|
27
26
|
value,
|
|
28
27
|
onChange,
|
|
29
|
-
disabled,
|
|
30
28
|
height = '200px',
|
|
31
29
|
scene = 'formValue',
|
|
32
30
|
containerStyle = { flex: 1, minWidth: 0 },
|
|
@@ -40,15 +38,9 @@ export const RunJSValueEditor: React.FC<RunJSValueEditorProps> = (props) => {
|
|
|
40
38
|
<div style={containerStyle}>
|
|
41
39
|
<CodeEditor
|
|
42
40
|
value={current.code}
|
|
43
|
-
onChange={(code) => {
|
|
44
|
-
if (disabled) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
onChange?.({ ...current, code });
|
|
48
|
-
}}
|
|
41
|
+
onChange={(code) => onChange?.({ ...current, code })}
|
|
49
42
|
version={current.version}
|
|
50
43
|
height={height}
|
|
51
|
-
readonly={disabled}
|
|
52
44
|
enableLinter
|
|
53
45
|
placeholder={placeholderText}
|
|
54
46
|
scene={scene}
|
package/src/flow/index.ts
CHANGED
|
@@ -98,7 +98,6 @@ export * from './FlowPage';
|
|
|
98
98
|
export * from './models';
|
|
99
99
|
export * from './utils';
|
|
100
100
|
export * from './actions';
|
|
101
|
-
export { FieldAssignValueInput } from './components/FieldAssignValueInput';
|
|
102
101
|
export * from './system-settings';
|
|
103
102
|
export * from './admin-shell/admin-layout';
|
|
104
103
|
export * from './admin-shell/BaseLayoutModel';
|
package/src/index.ts
CHANGED
|
@@ -30,8 +30,6 @@ export * from './layout-manager';
|
|
|
30
30
|
export * from './hooks';
|
|
31
31
|
export { default as languageCodes } from './locale/languageCodes';
|
|
32
32
|
export * from './nocobase-buildin-plugin';
|
|
33
|
-
export { getRouteRuntimeVersion } from './utils/getRouteRuntimeVersion';
|
|
34
|
-
export type { RouteRuntimeVersion } from './utils/getRouteRuntimeVersion';
|
|
35
33
|
export * from './collection-field-interface/CollectionFieldInterface';
|
|
36
34
|
export * from './collection-field-interface/CollectionFieldInterfaceManager';
|
|
37
35
|
export * from './collection-manager/field-configure';
|
|
@@ -42,8 +40,6 @@ export * from './collection-manager/template-fields';
|
|
|
42
40
|
export * from './data-source';
|
|
43
41
|
export * from './entry-actions';
|
|
44
42
|
export * from './flow';
|
|
45
|
-
export { CodeEditorExtension } from './flow/components/code-editor/extension';
|
|
46
|
-
export type { CodeEditorExtra, CodeEditorExtraRegistry, EditorRef } from './flow/components/code-editor/types';
|
|
47
43
|
export {
|
|
48
44
|
DEFAULT_DATA_SOURCE_KEY,
|
|
49
45
|
IconPicker,
|
package/src/utils/index.tsx
CHANGED
|
@@ -11,7 +11,6 @@ import React, { ComponentType, FC } from 'react';
|
|
|
11
11
|
import { BlankComponent } from '../components';
|
|
12
12
|
|
|
13
13
|
export * from './appVersionHTML';
|
|
14
|
-
export * from './getRouteRuntimeVersion';
|
|
15
14
|
|
|
16
15
|
export function normalizeContainer(container: Element | ShadowRoot | string): Element | null {
|
|
17
16
|
if (!container) {
|