@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
|
@@ -42,6 +42,12 @@ import { normalizeFilterValueByOperator } from '../models/blocks/filter-form/val
|
|
|
42
42
|
import { FieldAssignExactDatePicker, type ExactDatePickerMode } from './FieldAssignExactDatePicker';
|
|
43
43
|
import { limitAssociationMetaTree } from './filter/metaTreeAssociationDepth';
|
|
44
44
|
|
|
45
|
+
type VariableInputConverters = {
|
|
46
|
+
renderInputComponent?: (metaTreeNode: MetaTreeNode | null) => React.ComponentType<any> | null;
|
|
47
|
+
resolvePathFromValue?: (value: any) => string[] | undefined;
|
|
48
|
+
resolveValueFromPath?: (metaTreeNode: MetaTreeNode) => any;
|
|
49
|
+
};
|
|
50
|
+
|
|
45
51
|
const DATE_FIELD_INTERFACES = new Set(['date', 'datetime', 'datetimeNoTz', 'createdAt', 'updatedAt', 'unixTimestamp']);
|
|
46
52
|
|
|
47
53
|
const TZ_AWARE_DATE_INTERFACES = new Set(['datetime', 'createdAt', 'updatedAt', 'unixTimestamp']);
|
|
@@ -341,7 +347,11 @@ interface Props {
|
|
|
341
347
|
* 默认 false,保持历史行为。
|
|
342
348
|
*/
|
|
343
349
|
enableDateVariableAsConstant?: boolean;
|
|
350
|
+
/** 是否允许在变量选择器中使用 RunJS。默认 true,保持历史行为。 */
|
|
351
|
+
allowRunJS?: boolean;
|
|
344
352
|
maxAssociationFieldDepth?: number;
|
|
353
|
+
disabled?: boolean;
|
|
354
|
+
variableConverters?: VariableInputConverters;
|
|
345
355
|
}
|
|
346
356
|
|
|
347
357
|
type ResolvedFieldContext = {
|
|
@@ -712,7 +722,10 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
712
722
|
preferFormItemFieldModel,
|
|
713
723
|
associationFieldNamesOverride,
|
|
714
724
|
enableDateVariableAsConstant = false,
|
|
725
|
+
allowRunJS = true,
|
|
715
726
|
maxAssociationFieldDepth = 2,
|
|
727
|
+
disabled = false,
|
|
728
|
+
variableConverters,
|
|
716
729
|
}) => {
|
|
717
730
|
const flowCtx = useFlowContext<FlowModelContext>();
|
|
718
731
|
const normalizeEventValue = React.useCallback((eventOrValue: unknown) => {
|
|
@@ -1077,7 +1090,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1077
1090
|
fm.setStepParams('selectSettings', 'fieldNames', { label: overrideLabel });
|
|
1078
1091
|
}
|
|
1079
1092
|
fm?.setProps?.({
|
|
1080
|
-
disabled
|
|
1093
|
+
disabled,
|
|
1081
1094
|
readPretty: false,
|
|
1082
1095
|
pattern: 'editable',
|
|
1083
1096
|
updateAssociation: false,
|
|
@@ -1140,6 +1153,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1140
1153
|
preferFormItemFieldModel,
|
|
1141
1154
|
associationFieldNamesOverride?.label,
|
|
1142
1155
|
associationFieldNamesOverride?.value,
|
|
1156
|
+
disabled,
|
|
1143
1157
|
]);
|
|
1144
1158
|
|
|
1145
1159
|
// 当传入 operator / operatorMetaList 时,按 operator schema 适配临时字段的输入组件与 props。
|
|
@@ -1192,6 +1206,9 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1192
1206
|
React.useEffect(() => {
|
|
1193
1207
|
const coercedValue = coerceEmptyValueForRenderer(inputProps?.value);
|
|
1194
1208
|
const handleChange = (ev: any) => {
|
|
1209
|
+
if (inputProps?.disabled) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1195
1212
|
const nextRaw = normalizeEventValue(ev);
|
|
1196
1213
|
const normalizedForStore = operator ? normalizeFilterValueByOperator(operator, nextRaw) : nextRaw;
|
|
1197
1214
|
const nextValue = coerceEmptyValueForRenderer(normalizedForStore);
|
|
@@ -1223,6 +1240,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1223
1240
|
value={inputProps?.value}
|
|
1224
1241
|
onChange={(e) => inputProps?.onChange?.(normalizeEventValue(e))}
|
|
1225
1242
|
placeholder={placeholder}
|
|
1243
|
+
disabled={inputProps?.disabled}
|
|
1226
1244
|
style={withFullWidthStyle(wrapperStyle)}
|
|
1227
1245
|
/>
|
|
1228
1246
|
);
|
|
@@ -1241,6 +1259,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1241
1259
|
const C: React.FC<any> = (inputProps) => {
|
|
1242
1260
|
const wrapperStyle = pickStyle(inputProps?.style);
|
|
1243
1261
|
const raw = inputProps?.value;
|
|
1262
|
+
const isDisabled = Boolean(inputProps?.disabled);
|
|
1244
1263
|
const parsed = isCtxDateExpression(raw) ? parseCtxDateExpression(raw) : raw;
|
|
1245
1264
|
const parsedValue = typeof parsed === 'undefined' ? undefined : parsed;
|
|
1246
1265
|
const { token } = theme.useToken();
|
|
@@ -1265,6 +1284,9 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1265
1284
|
});
|
|
1266
1285
|
|
|
1267
1286
|
const handleSelect = (val: string) => {
|
|
1287
|
+
if (isDisabled) {
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1268
1290
|
setOpen(false);
|
|
1269
1291
|
if (val === 'exact') {
|
|
1270
1292
|
inputProps?.onChange?.('');
|
|
@@ -1279,10 +1301,16 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1279
1301
|
};
|
|
1280
1302
|
|
|
1281
1303
|
const handleExactSingleChange = (nextValue: any) => {
|
|
1304
|
+
if (isDisabled) {
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1282
1307
|
inputProps?.onChange?.(nextValue || '');
|
|
1283
1308
|
};
|
|
1284
1309
|
|
|
1285
1310
|
const handleExactRangeChange = (nextValue: any) => {
|
|
1311
|
+
if (isDisabled) {
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1286
1314
|
inputProps?.onChange?.(nextValue || '');
|
|
1287
1315
|
};
|
|
1288
1316
|
|
|
@@ -1327,7 +1355,11 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1327
1355
|
<Select
|
|
1328
1356
|
options={options}
|
|
1329
1357
|
open={open}
|
|
1330
|
-
onDropdownVisibleChange={
|
|
1358
|
+
onDropdownVisibleChange={(nextOpen) => {
|
|
1359
|
+
if (!isDisabled) {
|
|
1360
|
+
setOpen(nextOpen);
|
|
1361
|
+
}
|
|
1362
|
+
}}
|
|
1331
1363
|
allowClear={false}
|
|
1332
1364
|
style={{
|
|
1333
1365
|
width: '100%',
|
|
@@ -1337,13 +1369,18 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1337
1369
|
value={selectedType}
|
|
1338
1370
|
onChange={handleSelect}
|
|
1339
1371
|
dropdownRender={dropdownRender}
|
|
1372
|
+
disabled={isDisabled}
|
|
1340
1373
|
/>
|
|
1341
1374
|
{['past', 'next'].includes(selectedType) && [
|
|
1342
1375
|
<InputNumber
|
|
1343
1376
|
key="number"
|
|
1344
1377
|
style={{ flex: 1 }}
|
|
1345
1378
|
value={(parsedValue as any)?.number}
|
|
1379
|
+
disabled={isDisabled}
|
|
1346
1380
|
onChange={(nextNumber) => {
|
|
1381
|
+
if (isDisabled) {
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1347
1384
|
inputProps?.onChange?.({
|
|
1348
1385
|
...(parsedValue as any),
|
|
1349
1386
|
type: selectedType,
|
|
@@ -1356,7 +1393,11 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1356
1393
|
key="unit"
|
|
1357
1394
|
value={(parsedValue as any)?.unit}
|
|
1358
1395
|
style={{ minWidth: 130, maxWidth: 140 }}
|
|
1396
|
+
disabled={isDisabled}
|
|
1359
1397
|
onChange={(nextUnit) => {
|
|
1398
|
+
if (isDisabled) {
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
1360
1401
|
inputProps?.onChange?.({
|
|
1361
1402
|
...(parsedValue as any),
|
|
1362
1403
|
type: selectedType,
|
|
@@ -1379,6 +1420,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1379
1420
|
isRange={isRange}
|
|
1380
1421
|
value={isRange ? exactRangeValue : exactSingleValue}
|
|
1381
1422
|
onChange={isRange ? handleExactRangeChange : handleExactSingleChange}
|
|
1423
|
+
disabled={isDisabled}
|
|
1382
1424
|
style={{ flex: 1 }}
|
|
1383
1425
|
/>
|
|
1384
1426
|
)}
|
|
@@ -1398,7 +1440,12 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1398
1440
|
|
|
1399
1441
|
const RunJSComponent = React.useMemo(() => {
|
|
1400
1442
|
const C: React.FC<any> = (inputProps) => (
|
|
1401
|
-
<RunJSValueEditor
|
|
1443
|
+
<RunJSValueEditor
|
|
1444
|
+
t={flowCtx.t}
|
|
1445
|
+
value={inputProps?.value}
|
|
1446
|
+
onChange={inputProps?.onChange}
|
|
1447
|
+
disabled={inputProps?.disabled}
|
|
1448
|
+
/>
|
|
1402
1449
|
);
|
|
1403
1450
|
return C;
|
|
1404
1451
|
}, [flowCtx]);
|
|
@@ -1421,11 +1468,13 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1421
1468
|
render: ConstantEditor,
|
|
1422
1469
|
},
|
|
1423
1470
|
{ title: tExpr('Null'), name: 'null', type: 'object', paths: ['null'], render: NullComponent },
|
|
1424
|
-
|
|
1471
|
+
...(allowRunJS
|
|
1472
|
+
? [{ title: tExpr('RunJS'), name: 'runjs', type: 'object', paths: ['runjs'], render: RunJSComponent }]
|
|
1473
|
+
: []),
|
|
1425
1474
|
...limitedBase,
|
|
1426
1475
|
];
|
|
1427
1476
|
};
|
|
1428
|
-
}, [flowCtx, ConstantEditor, NullComponent, RunJSComponent, maxAssociationFieldDepth]);
|
|
1477
|
+
}, [flowCtx, ConstantEditor, NullComponent, RunJSComponent, allowRunJS, maxAssociationFieldDepth]);
|
|
1429
1478
|
|
|
1430
1479
|
const displayValue = React.useMemo(() => {
|
|
1431
1480
|
if (!useDateVariableConstant) {
|
|
@@ -1442,6 +1491,10 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1442
1491
|
|
|
1443
1492
|
const handleVariableInputChange = React.useCallback(
|
|
1444
1493
|
(nextValue: any) => {
|
|
1494
|
+
if (disabled) {
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1445
1498
|
if (!useDateVariableConstant) {
|
|
1446
1499
|
onChange(nextValue);
|
|
1447
1500
|
return;
|
|
@@ -1449,7 +1502,7 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1449
1502
|
|
|
1450
1503
|
onChange(normalizeDateVariableOutput(nextValue, dateVariableComponentProps));
|
|
1451
1504
|
},
|
|
1452
|
-
[dateVariableComponentProps, onChange, useDateVariableConstant],
|
|
1505
|
+
[dateVariableComponentProps, disabled, onChange, useDateVariableConstant],
|
|
1453
1506
|
);
|
|
1454
1507
|
|
|
1455
1508
|
if (!fieldPath) {
|
|
@@ -1464,26 +1517,40 @@ export const FieldAssignValueInput: React.FC<Props> = ({
|
|
|
1464
1517
|
metaTree={metaTree}
|
|
1465
1518
|
style={{ width: '100%' }}
|
|
1466
1519
|
clearValue={''}
|
|
1520
|
+
disabled={disabled}
|
|
1467
1521
|
converters={{
|
|
1522
|
+
...variableConverters,
|
|
1468
1523
|
renderInputComponent: (meta) => {
|
|
1524
|
+
const external = variableConverters?.renderInputComponent?.(meta ?? null);
|
|
1525
|
+
if (external) {
|
|
1526
|
+
return external;
|
|
1527
|
+
}
|
|
1469
1528
|
const firstPath = meta?.paths?.[0];
|
|
1470
1529
|
if (firstPath === 'constant') return ConstantEditor;
|
|
1471
1530
|
if (firstPath === 'null') return NullComponent;
|
|
1472
|
-
if (firstPath === 'runjs') return RunJSComponent;
|
|
1531
|
+
if (allowRunJS && firstPath === 'runjs') return RunJSComponent;
|
|
1473
1532
|
return null;
|
|
1474
1533
|
},
|
|
1475
1534
|
resolveValueFromPath: (item) => {
|
|
1535
|
+
const external = variableConverters?.resolveValueFromPath?.(item);
|
|
1536
|
+
if (external !== undefined) {
|
|
1537
|
+
return external;
|
|
1538
|
+
}
|
|
1476
1539
|
const firstPath = item?.paths?.[0];
|
|
1477
1540
|
if (firstPath === 'constant') {
|
|
1478
1541
|
return useDateVariableConstant ? { type: 'today' } : '';
|
|
1479
1542
|
}
|
|
1480
1543
|
if (firstPath === 'null') return null;
|
|
1481
|
-
if (firstPath === 'runjs') return { code: '', version: 'v2' };
|
|
1544
|
+
if (allowRunJS && firstPath === 'runjs') return { code: '', version: 'v2' };
|
|
1482
1545
|
return undefined;
|
|
1483
1546
|
},
|
|
1484
1547
|
resolvePathFromValue: (currentValue) => {
|
|
1548
|
+
const external = variableConverters?.resolvePathFromValue?.(currentValue);
|
|
1549
|
+
if (external !== undefined) {
|
|
1550
|
+
return external;
|
|
1551
|
+
}
|
|
1485
1552
|
if (currentValue === null) return ['null'];
|
|
1486
|
-
if (isRunJSValue(currentValue)) return ['runjs'];
|
|
1553
|
+
if (allowRunJS && isRunJSValue(currentValue)) return ['runjs'];
|
|
1487
1554
|
if (useDateVariableConstant && isCtxDateExpression(currentValue)) {
|
|
1488
1555
|
return ['constant'];
|
|
1489
1556
|
}
|
|
@@ -11,11 +11,14 @@ import { type FlowEngine, useFlowContext, useFlowEngine } from '@nocobase/flow-e
|
|
|
11
11
|
import { Button, Result } from 'antd';
|
|
12
12
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
13
13
|
import { useTranslation } from 'react-i18next';
|
|
14
|
-
import { useLocation, useParams } from 'react-router-dom';
|
|
14
|
+
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
|
15
15
|
import { getModernClientPrefix, stripModernClientPrefix } from '../../authRedirect';
|
|
16
16
|
import { useApp } from '../../hooks/useApp';
|
|
17
|
-
import { NocoBaseDesktopRouteType } from '../../flow-compat';
|
|
18
|
-
import {
|
|
17
|
+
import { NocoBaseDesktopRouteType, type NocoBaseDesktopRoute } from '../../flow-compat';
|
|
18
|
+
import {
|
|
19
|
+
resolveAdminRouteRuntimeTarget,
|
|
20
|
+
toRouterNavigationPath,
|
|
21
|
+
} from '../admin-shell/admin-layout/resolveAdminRouteRuntimeTarget';
|
|
19
22
|
import { getAdminLayoutModel, type AdminLayoutModel } from '../admin-shell/admin-layout/AdminLayoutModel';
|
|
20
23
|
import { getLayoutModel, type BaseLayoutModel } from '../admin-shell/BaseLayoutModel';
|
|
21
24
|
import { useLayoutRoutePage } from '../admin-shell/useLayoutRoutePage';
|
|
@@ -24,6 +27,7 @@ import { useKeepAlive } from '../../components/KeepAlive';
|
|
|
24
27
|
import { registerDeviceTypeContext } from '../internal/registerDeviceTypeContext';
|
|
25
28
|
|
|
26
29
|
type FlowRouteGuardState = {
|
|
30
|
+
pageUid?: string;
|
|
27
31
|
pending: boolean;
|
|
28
32
|
allowBridge: boolean;
|
|
29
33
|
notFound: boolean;
|
|
@@ -32,6 +36,21 @@ type FlowRouteGuardState = {
|
|
|
32
36
|
|
|
33
37
|
export type LegacyPageBehavior = 'redirect' | 'notFound' | 'bridge';
|
|
34
38
|
|
|
39
|
+
type FlowRouteLayoutContext = {
|
|
40
|
+
authCheck?: boolean;
|
|
41
|
+
routePath?: string;
|
|
42
|
+
routeName?: string;
|
|
43
|
+
uid?: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type FlowRouteRepositoryLike = {
|
|
47
|
+
refreshAccessible?: () => Promise<unknown>;
|
|
48
|
+
isAccessibleLoaded?: () => boolean;
|
|
49
|
+
ensureAccessibleLoaded?: () => Promise<unknown>;
|
|
50
|
+
getRouteBySchemaUid?: (schemaUid: string) => NocoBaseDesktopRoute | undefined;
|
|
51
|
+
listAccessible?: () => NocoBaseDesktopRoute[];
|
|
52
|
+
};
|
|
53
|
+
|
|
35
54
|
export type FlowRouteProps = {
|
|
36
55
|
pageUid?: string;
|
|
37
56
|
active?: boolean;
|
|
@@ -42,7 +61,7 @@ export type FlowRouteProps = {
|
|
|
42
61
|
const getDefaultAdminLayoutModel = (flowEngine: FlowEngine) =>
|
|
43
62
|
getAdminLayoutModel<AdminLayoutModel>(flowEngine, { required: true });
|
|
44
63
|
|
|
45
|
-
const getDefaultLayoutModel = (flowEngine: FlowEngine, contextLayout?:
|
|
64
|
+
const getDefaultLayoutModel = (flowEngine: FlowEngine, contextLayout?: FlowRouteLayoutContext) => {
|
|
46
65
|
const layout = contextLayout || flowEngine.context.layout;
|
|
47
66
|
|
|
48
67
|
if (layout?.uid) {
|
|
@@ -52,7 +71,10 @@ const getDefaultLayoutModel = (flowEngine: FlowEngine, contextLayout?: any) => {
|
|
|
52
71
|
return getDefaultAdminLayoutModel(flowEngine);
|
|
53
72
|
};
|
|
54
73
|
|
|
55
|
-
const getDefaultLegacyPageBehavior = (
|
|
74
|
+
const getDefaultLegacyPageBehavior = (
|
|
75
|
+
flowEngine: FlowEngine,
|
|
76
|
+
contextLayout?: FlowRouteLayoutContext,
|
|
77
|
+
): LegacyPageBehavior => {
|
|
56
78
|
const layout = contextLayout || flowEngine.context.layout;
|
|
57
79
|
|
|
58
80
|
if (layout?.routeName && layout.routeName !== 'admin') {
|
|
@@ -62,6 +84,46 @@ const getDefaultLegacyPageBehavior = (flowEngine: FlowEngine, contextLayout?: an
|
|
|
62
84
|
return 'redirect';
|
|
63
85
|
};
|
|
64
86
|
|
|
87
|
+
const shouldRequireAccessibleRoute = (contextLayout?: FlowRouteLayoutContext) => contextLayout?.authCheck !== false;
|
|
88
|
+
|
|
89
|
+
const findAccessibleRouteByIdentity = (
|
|
90
|
+
routes: NocoBaseDesktopRoute[] | undefined,
|
|
91
|
+
pageUid: string,
|
|
92
|
+
): NocoBaseDesktopRoute | undefined => {
|
|
93
|
+
if (!Array.isArray(routes)) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const route of routes) {
|
|
98
|
+
if (
|
|
99
|
+
(route.type !== NocoBaseDesktopRouteType.group && route.schemaUid === pageUid) ||
|
|
100
|
+
(route.type === NocoBaseDesktopRouteType.group && route.id != null && String(route.id) === pageUid)
|
|
101
|
+
) {
|
|
102
|
+
return route;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const matched = findAccessibleRouteByIdentity(route.children, pageUid);
|
|
106
|
+
if (matched) {
|
|
107
|
+
return matched;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return undefined;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const getAccessibleRouteByPageUid = (
|
|
115
|
+
routeRepository: FlowRouteRepositoryLike | undefined,
|
|
116
|
+
pageUid: string,
|
|
117
|
+
): NocoBaseDesktopRoute | undefined => {
|
|
118
|
+
const routeBySchemaUid = routeRepository?.getRouteBySchemaUid?.(pageUid);
|
|
119
|
+
|
|
120
|
+
if (routeBySchemaUid && routeBySchemaUid.type !== NocoBaseDesktopRouteType.group) {
|
|
121
|
+
return routeBySchemaUid;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return findAccessibleRouteByIdentity(routeRepository?.listAccessible?.(), pageUid);
|
|
125
|
+
};
|
|
126
|
+
|
|
65
127
|
const hasFlowModel = async (flowEngine: FlowEngine, pageUid: string) => {
|
|
66
128
|
if (flowEngine.getModel(pageUid)) {
|
|
67
129
|
return true;
|
|
@@ -177,21 +239,52 @@ const LegacyPageUnsupported = ({
|
|
|
177
239
|
* @throws {Error} 当缺少 `route.params.name` 时抛出异常
|
|
178
240
|
*/
|
|
179
241
|
const FlowRoute = (props: FlowRouteProps = {}) => {
|
|
242
|
+
const {
|
|
243
|
+
active,
|
|
244
|
+
getLayoutModel: getLayoutModelProp,
|
|
245
|
+
legacyPageBehavior: legacyPageBehaviorProp,
|
|
246
|
+
pageUid: pageUidProp,
|
|
247
|
+
} = props;
|
|
180
248
|
const flowEngine = useFlowEngine();
|
|
181
|
-
const flowContext = useFlowContext<
|
|
249
|
+
const flowContext = useFlowContext<{ layout?: FlowRouteLayoutContext }>();
|
|
182
250
|
const contextLayout = flowContext?.layout;
|
|
251
|
+
const propsLayoutModel = useMemo(() => getLayoutModelProp?.(flowEngine), [flowEngine, getLayoutModelProp]);
|
|
252
|
+
const rawRouteLayout = contextLayout || propsLayoutModel?.layout;
|
|
253
|
+
const routeLayoutUid = rawRouteLayout?.uid;
|
|
254
|
+
const routeLayoutRouteName = rawRouteLayout?.routeName;
|
|
255
|
+
const routeLayoutRoutePath = rawRouteLayout?.routePath;
|
|
256
|
+
const routeLayoutAuthCheck = rawRouteLayout?.authCheck;
|
|
257
|
+
const routeLayout = useMemo(() => {
|
|
258
|
+
if (
|
|
259
|
+
!routeLayoutUid &&
|
|
260
|
+
!routeLayoutRouteName &&
|
|
261
|
+
!routeLayoutRoutePath &&
|
|
262
|
+
typeof routeLayoutAuthCheck === 'undefined'
|
|
263
|
+
) {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
authCheck: routeLayoutAuthCheck,
|
|
268
|
+
routeName: routeLayoutRouteName,
|
|
269
|
+
routePath: routeLayoutRoutePath,
|
|
270
|
+
uid: routeLayoutUid,
|
|
271
|
+
};
|
|
272
|
+
}, [routeLayoutAuthCheck, routeLayoutRouteName, routeLayoutRoutePath, routeLayoutUid]);
|
|
183
273
|
const getLayoutModel = useMemo(
|
|
184
|
-
() =>
|
|
185
|
-
[
|
|
274
|
+
() => getLayoutModelProp || ((engine: FlowEngine) => getDefaultLayoutModel(engine, routeLayout)),
|
|
275
|
+
[getLayoutModelProp, routeLayout],
|
|
186
276
|
);
|
|
187
|
-
const legacyPageBehavior =
|
|
277
|
+
const legacyPageBehavior = legacyPageBehaviorProp || getDefaultLegacyPageBehavior(flowEngine, routeLayout);
|
|
188
278
|
const app = useApp();
|
|
189
|
-
const routeRepository = flowEngine.context.routeRepository;
|
|
190
279
|
const location = useLocation();
|
|
280
|
+
const navigate = useNavigate();
|
|
281
|
+
const routeRepository = flowEngine.context.routeRepository as FlowRouteRepositoryLike | undefined;
|
|
191
282
|
const params = useParams();
|
|
192
|
-
const pageUid =
|
|
283
|
+
const pageUid = pageUidProp || params?.name;
|
|
284
|
+
const hasNestedRoutePath = typeof params?.tabUid !== 'undefined' || typeof params?.['*'] !== 'undefined';
|
|
193
285
|
const skipRouteRepositoryCheck = !routeRepository;
|
|
194
286
|
const [guardState, setGuardState] = useState<FlowRouteGuardState>({
|
|
287
|
+
pageUid: undefined,
|
|
195
288
|
pending: true,
|
|
196
289
|
allowBridge: false,
|
|
197
290
|
notFound: false,
|
|
@@ -203,19 +296,24 @@ const FlowRoute = (props: FlowRouteProps = {}) => {
|
|
|
203
296
|
throw new Error('[NocoBase] FlowRoute requires pageUid or route.params.name.');
|
|
204
297
|
}
|
|
205
298
|
|
|
299
|
+
useEffect(() => {
|
|
300
|
+
replaceTriggeredRef.current = false;
|
|
301
|
+
}, [location.hash, location.pathname, location.search, pageUid]);
|
|
302
|
+
|
|
206
303
|
useEffect(() => {
|
|
207
304
|
let active = true;
|
|
208
305
|
const requestId = ++requestIdRef.current;
|
|
306
|
+
const requiresAccessibleRoute = shouldRequireAccessibleRoute(routeLayout);
|
|
209
307
|
|
|
210
308
|
const run = async () => {
|
|
211
|
-
setGuardState({ pending: true, allowBridge: false, notFound: false });
|
|
309
|
+
setGuardState({ pageUid, pending: true, allowBridge: false, notFound: false });
|
|
212
310
|
|
|
213
|
-
if (!skipRouteRepositoryCheck && !routeRepository?.isAccessibleLoaded?.()) {
|
|
311
|
+
if (requiresAccessibleRoute && !skipRouteRepositoryCheck && !routeRepository?.isAccessibleLoaded?.()) {
|
|
214
312
|
try {
|
|
215
313
|
await routeRepository?.ensureAccessibleLoaded?.();
|
|
216
314
|
} catch (_error) {
|
|
217
315
|
if (active && requestId === requestIdRef.current) {
|
|
218
|
-
setGuardState({ pending: false, allowBridge: true, notFound: false });
|
|
316
|
+
setGuardState({ pageUid, pending: false, allowBridge: true, notFound: false });
|
|
219
317
|
}
|
|
220
318
|
return;
|
|
221
319
|
}
|
|
@@ -225,25 +323,67 @@ const FlowRoute = (props: FlowRouteProps = {}) => {
|
|
|
225
323
|
return;
|
|
226
324
|
}
|
|
227
325
|
|
|
228
|
-
const route =
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
326
|
+
const route =
|
|
327
|
+
skipRouteRepositoryCheck || !requiresAccessibleRoute
|
|
328
|
+
? undefined
|
|
329
|
+
: getAccessibleRouteByPageUid(routeRepository, pageUid);
|
|
330
|
+
if (!route && !skipRouteRepositoryCheck && requiresAccessibleRoute) {
|
|
331
|
+
setGuardState({ pageUid, pending: false, allowBridge: false, notFound: true });
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (!route && legacyPageBehavior === 'notFound') {
|
|
232
336
|
const flowModelExists = await hasFlowModel(flowEngine, pageUid);
|
|
233
337
|
if (active && requestId === requestIdRef.current) {
|
|
234
|
-
setGuardState({ pending: false, allowBridge: flowModelExists, notFound: !flowModelExists });
|
|
338
|
+
setGuardState({ pageUid, pending: false, allowBridge: flowModelExists, notFound: !flowModelExists });
|
|
235
339
|
}
|
|
236
340
|
return;
|
|
237
341
|
}
|
|
238
342
|
|
|
343
|
+
if (route?.type === NocoBaseDesktopRouteType.group) {
|
|
344
|
+
if (hasNestedRoutePath) {
|
|
345
|
+
setGuardState({ pageUid, pending: false, allowBridge: false, notFound: true });
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const target = resolveAdminRouteRuntimeTarget({
|
|
350
|
+
app,
|
|
351
|
+
route,
|
|
352
|
+
layout: routeLayout,
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
if (target.reason === 'emptyGroup') {
|
|
356
|
+
setGuardState({ pageUid, pending: false, allowBridge: false, notFound: false });
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (target.runtimePath) {
|
|
361
|
+
if (replaceTriggeredRef.current) {
|
|
362
|
+
setGuardState({ pageUid, pending: false, allowBridge: false, notFound: false });
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
replaceTriggeredRef.current = true;
|
|
367
|
+
if (target.navigationMode === 'document') {
|
|
368
|
+
window.location.replace(target.runtimePath);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
navigate(toRouterNavigationPath(target.runtimePath, app.router?.getBasename?.()), { replace: true });
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
setGuardState({ pageUid, pending: false, allowBridge: false, notFound: true });
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
239
379
|
if (route?.type === NocoBaseDesktopRouteType.page) {
|
|
240
380
|
if (legacyPageBehavior === 'notFound') {
|
|
241
|
-
setGuardState({ pending: false, allowBridge: false, notFound: true });
|
|
381
|
+
setGuardState({ pageUid, pending: false, allowBridge: false, notFound: true });
|
|
242
382
|
return;
|
|
243
383
|
}
|
|
244
384
|
|
|
245
385
|
if (legacyPageBehavior === 'bridge') {
|
|
246
|
-
setGuardState({ pending: false, allowBridge: true, notFound: false });
|
|
386
|
+
setGuardState({ pageUid, pending: false, allowBridge: true, notFound: false });
|
|
247
387
|
return;
|
|
248
388
|
}
|
|
249
389
|
|
|
@@ -266,26 +406,42 @@ const FlowRoute = (props: FlowRouteProps = {}) => {
|
|
|
266
406
|
|
|
267
407
|
if (target.reason === 'unsupportedV2Runtime') {
|
|
268
408
|
if (active && requestId === requestIdRef.current) {
|
|
269
|
-
setGuardState({
|
|
409
|
+
setGuardState({
|
|
410
|
+
pageUid,
|
|
411
|
+
pending: false,
|
|
412
|
+
allowBridge: false,
|
|
413
|
+
notFound: false,
|
|
414
|
+
legacyPageUnsupported: true,
|
|
415
|
+
});
|
|
270
416
|
}
|
|
271
417
|
return;
|
|
272
418
|
}
|
|
273
419
|
}
|
|
274
420
|
|
|
275
421
|
if (active && requestId === requestIdRef.current) {
|
|
276
|
-
setGuardState({ pending: false, allowBridge: true, notFound: false });
|
|
422
|
+
setGuardState({ pageUid, pending: false, allowBridge: true, notFound: false });
|
|
277
423
|
}
|
|
278
424
|
};
|
|
279
425
|
|
|
280
|
-
|
|
426
|
+
run();
|
|
281
427
|
|
|
282
428
|
return () => {
|
|
283
429
|
active = false;
|
|
284
430
|
};
|
|
285
|
-
}, [
|
|
431
|
+
}, [
|
|
432
|
+
app,
|
|
433
|
+
flowEngine,
|
|
434
|
+
hasNestedRoutePath,
|
|
435
|
+
legacyPageBehavior,
|
|
436
|
+
navigate,
|
|
437
|
+
pageUid,
|
|
438
|
+
routeLayout,
|
|
439
|
+
routeRepository,
|
|
440
|
+
skipRouteRepositoryCheck,
|
|
441
|
+
]);
|
|
286
442
|
|
|
287
443
|
const content = useMemo(() => {
|
|
288
|
-
if (guardState.pending) {
|
|
444
|
+
if (guardState.pageUid !== pageUid || guardState.pending) {
|
|
289
445
|
return null;
|
|
290
446
|
}
|
|
291
447
|
|
|
@@ -301,17 +457,18 @@ const FlowRoute = (props: FlowRouteProps = {}) => {
|
|
|
301
457
|
return null;
|
|
302
458
|
}
|
|
303
459
|
|
|
304
|
-
return <BridgeFlowRoute pageUid={pageUid} active={
|
|
460
|
+
return <BridgeFlowRoute pageUid={pageUid} active={active} getLayoutModel={getLayoutModel} />;
|
|
305
461
|
}, [
|
|
462
|
+
active,
|
|
306
463
|
app,
|
|
307
464
|
getLayoutModel,
|
|
308
465
|
guardState.allowBridge,
|
|
309
466
|
guardState.legacyPageUnsupported,
|
|
310
467
|
guardState.notFound,
|
|
468
|
+
guardState.pageUid,
|
|
311
469
|
guardState.pending,
|
|
312
470
|
location,
|
|
313
471
|
pageUid,
|
|
314
|
-
props.active,
|
|
315
472
|
]);
|
|
316
473
|
|
|
317
474
|
return content;
|
|
@@ -15,6 +15,7 @@ export interface RunJSValueEditorProps {
|
|
|
15
15
|
t?: (key: string) => string;
|
|
16
16
|
value?: unknown;
|
|
17
17
|
onChange?: (value: RunJSValue) => void;
|
|
18
|
+
disabled?: boolean;
|
|
18
19
|
height?: string;
|
|
19
20
|
scene?: string;
|
|
20
21
|
containerStyle?: React.CSSProperties;
|
|
@@ -25,6 +26,7 @@ export const RunJSValueEditor: React.FC<RunJSValueEditorProps> = (props) => {
|
|
|
25
26
|
t,
|
|
26
27
|
value,
|
|
27
28
|
onChange,
|
|
29
|
+
disabled,
|
|
28
30
|
height = '200px',
|
|
29
31
|
scene = 'formValue',
|
|
30
32
|
containerStyle = { flex: 1, minWidth: 0 },
|
|
@@ -38,9 +40,15 @@ export const RunJSValueEditor: React.FC<RunJSValueEditorProps> = (props) => {
|
|
|
38
40
|
<div style={containerStyle}>
|
|
39
41
|
<CodeEditor
|
|
40
42
|
value={current.code}
|
|
41
|
-
onChange={(code) =>
|
|
43
|
+
onChange={(code) => {
|
|
44
|
+
if (disabled) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
onChange?.({ ...current, code });
|
|
48
|
+
}}
|
|
42
49
|
version={current.version}
|
|
43
50
|
height={height}
|
|
51
|
+
readonly={disabled}
|
|
44
52
|
enableLinter
|
|
45
53
|
placeholder={placeholderText}
|
|
46
54
|
scene={scene}
|