From 29f9daae21772e45db297c77ee2014ce6b5bd961 Mon Sep 17 00:00:00 2001
From: Zeke Zhang <958414905@qq.com>
Date: Sun, 22 Dec 2024 00:28:21 +0800
Subject: [PATCH] fix(linkageRules): fix invalid issue of form linkage rules
(#5876)
* test: add e2e test
* fix: complete the fix
* fix: fix e2e errors
* fix: fix e2e errors
---
.../form-create/schemaSettings2.test.ts | 3 +-
.../schema-component/antd/form-v2/Form.tsx | 49 +-
.../schema-component/common/utils/uitls.tsx | 3 +-
.../LinkageRules/bindLinkageRulesToFiled.ts | 1 -
.../VariableInput/hooks/useFormVariable.ts | 7 +-
.../__e2e__/linkageRules.test.ts | 61 +
.../src/schema-settings/__e2e__/template.ts | 1076 +++++++++++++++++
7 files changed, 1170 insertions(+), 30 deletions(-)
create mode 100644 packages/core/client/src/schema-settings/__e2e__/linkageRules.test.ts
create mode 100644 packages/core/client/src/schema-settings/__e2e__/template.ts
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings2.test.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings2.test.ts
index b5c9ba1b56..32be64963f 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings2.test.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings2.test.ts
@@ -13,7 +13,7 @@ import {
oneTableBlockWithAddNewAndViewAndEditAndBasicFields,
test,
} from '@nocobase/test/e2e';
-import { T2165, T3251, T3806, T3815, expressionTemplateInLinkageRules, T4891 } from './templatesOfBug';
+import { expressionTemplateInLinkageRules, T2165, T3251, T3806, T3815, T4891 } from './templatesOfBug';
test.describe('linkage rules', () => {
test('basic usage', async ({ page, mockPage }) => {
@@ -276,7 +276,6 @@ test.describe('linkage rules', () => {
}
});
- // https://nocobase.height.app/T-T3815 &&T-3802
test('fireImmediately in create form & edit form', async ({ page, mockPage, mockRecord }) => {
const nocoPage = await mockPage(T3815).waitForInit();
await mockRecord('general', {
diff --git a/packages/core/client/src/schema-component/antd/form-v2/Form.tsx b/packages/core/client/src/schema-component/antd/form-v2/Form.tsx
index aee121a92b..d304ba463b 100644
--- a/packages/core/client/src/schema-component/antd/form-v2/Form.tsx
+++ b/packages/core/client/src/schema-component/antd/form-v2/Form.tsx
@@ -18,6 +18,7 @@ import { useActionContext } from '..';
import { useAttach, useComponent } from '../..';
import { getCardItemSchema } from '../../../block-provider';
import { useTemplateBlockContext } from '../../../block-provider/TemplateBlockProvider';
+import { useDataBlockRequest } from '../../../data-source/data-block/DataBlockRequestProvider';
import { NocoBaseRecursionField } from '../../../formily/NocoBaseRecursionField';
import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { bindLinkageRulesToFiled } from '../../../schema-settings/LinkageRules/bindLinkageRulesToFiled';
@@ -134,6 +135,7 @@ const WithForm = (props: WithFormProps) => {
const variables = useVariables();
const localVariables = useLocalVariables({ currentForm: form });
const { templateFinished } = useTemplateBlockContext();
+ const { loading } = useDataBlockRequest() || {};
const linkageRules: any[] =
(getLinkageRules(fieldSchema) || fieldSchema.parent?.['x-linkage-rules'])?.filter((k) => !k.disabled) || [];
@@ -156,29 +158,36 @@ const WithForm = (props: WithFormProps) => {
}, [form, props.disabled, setFormValueChanged]);
useEffect(() => {
+ if (loading) {
+ return;
+ }
+
const id = uid();
const disposes = [];
- form.addEffects(id, () => {
- forEachLinkageRule(linkageRules, (action, rule) => {
- if (action.targetFields?.length) {
- const fields = action.targetFields.join(',');
+ // 如果不延迟执行,那么一开始获取到的 form.values 的值是旧的,会导致详情区块的联动规则出现一些问题
+ setTimeout(() => {
+ form.addEffects(id, () => {
+ forEachLinkageRule(linkageRules, (action, rule) => {
+ if (action.targetFields?.length) {
+ const fields = action.targetFields.join(',');
- // 之前使用的 `onFieldReact` 有问题,没有办法被取消监听,所以这里用 `onFieldInit` 和 `reaction` 代替
- onFieldInit(`*(${fields})`, (field: any, form) => {
- disposes.push(
- bindLinkageRulesToFiled({
- field,
- linkageRules,
- formValues: form.values,
- localVariables,
- action,
- rule,
- variables,
- }),
- );
- });
- }
+ // 之前使用的 `onFieldReact` 有问题,没有办法被取消监听,所以这里用 `onFieldInit` 和 `reaction` 代替
+ onFieldInit(`*(${fields})`, (field: any, form) => {
+ disposes.push(
+ bindLinkageRulesToFiled({
+ field,
+ linkageRules,
+ formValues: form.values,
+ localVariables,
+ action,
+ rule,
+ variables,
+ }),
+ );
+ });
+ }
+ });
});
});
@@ -188,7 +197,7 @@ const WithForm = (props: WithFormProps) => {
dispose();
});
};
- }, [linkageRules, templateFinished]);
+ }, [linkageRules, templateFinished, loading]);
return fieldSchema['x-decorator'] === 'FormV2' ? : ;
};
diff --git a/packages/core/client/src/schema-component/common/utils/uitls.tsx b/packages/core/client/src/schema-component/common/utils/uitls.tsx
index 8f0cf07acf..836abdbcc2 100644
--- a/packages/core/client/src/schema-component/common/utils/uitls.tsx
+++ b/packages/core/client/src/schema-component/common/utils/uitls.tsx
@@ -95,7 +95,6 @@ export const conditionAnalyses = async ({
const conditions = ruleGroup[type];
let results = conditions.map(async (condition) => {
- // fix https://nocobase.height.app/T-3152
if ('$and' in condition || '$or' in condition) {
return await conditionAnalyses({ ruleGroup: condition, variables, localVariables });
}
@@ -155,7 +154,7 @@ export const conditionAnalyses = async ({
* @param targetField
* @returns
*/
-export function targetFieldToVariableString(targetField: string[], variableName = '$nForm') {
+function targetFieldToVariableString(targetField: string[], variableName = '$nForm') {
// Action 中的联动规则虽然没有 form 上下文但是在这里也使用的是 `$nForm` 变量,这样实现更简单
return `{{ ${variableName}.${targetField.join('.')} }}`;
}
diff --git a/packages/core/client/src/schema-settings/LinkageRules/bindLinkageRulesToFiled.ts b/packages/core/client/src/schema-settings/LinkageRules/bindLinkageRulesToFiled.ts
index 9ea823c30f..b399ef9513 100644
--- a/packages/core/client/src/schema-settings/LinkageRules/bindLinkageRulesToFiled.ts
+++ b/packages/core/client/src/schema-settings/LinkageRules/bindLinkageRulesToFiled.ts
@@ -102,7 +102,6 @@ function getFieldValuesInCondition({ linkageRules, formValues }) {
return conditions
.map((condition) => {
- // fix https://nocobase.height.app/T-3251
if ('$and' in condition || '$or' in condition) {
return run(condition);
}
diff --git a/packages/core/client/src/schema-settings/VariableInput/hooks/useFormVariable.ts b/packages/core/client/src/schema-settings/VariableInput/hooks/useFormVariable.ts
index 668a17b1e9..f99c6b7644 100644
--- a/packages/core/client/src/schema-settings/VariableInput/hooks/useFormVariable.ts
+++ b/packages/core/client/src/schema-settings/VariableInput/hooks/useFormVariable.ts
@@ -77,16 +77,13 @@ const useCurrentFormData = () => {
*/
export const useCurrentFormContext = ({ form: _form }: Pick = {}) => {
const { form } = useFormBlockContext();
- const formData = useCurrentFormData();
const { isVariableParsedInOtherContext } = useFlag();
+
const formInstance = _form || form;
return {
/** 变量值 */
- currentFormCtx:
- formInstance?.readPretty === false && formInstance?.values && Object.keys(formInstance?.values)?.length
- ? formInstance?.values
- : formData || formInstance?.values,
+ currentFormCtx: formInstance?.values,
/** 用来判断是否可以显示`当前表单`变量 */
shouldDisplayCurrentForm: formInstance && !formInstance.readPretty && !isVariableParsedInOtherContext,
};
diff --git a/packages/core/client/src/schema-settings/__e2e__/linkageRules.test.ts b/packages/core/client/src/schema-settings/__e2e__/linkageRules.test.ts
new file mode 100644
index 0000000000..31cdb9327a
--- /dev/null
+++ b/packages/core/client/src/schema-settings/__e2e__/linkageRules.test.ts
@@ -0,0 +1,61 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+import { expect, test } from '@nocobase/test/e2e';
+import { formFieldDependsOnSubtableFieldsWithLinkageRules } from './template';
+
+test.describe('linkage rules', () => {
+ test('form field depends on subtable fields with linkage rules', async ({ page, mockPage, mockRecord }) => {
+ const nocoPage = await mockPage(formFieldDependsOnSubtableFieldsWithLinkageRules).waitForInit();
+ const record = await mockRecord('test');
+ await nocoPage.goto();
+
+ // 1. 点击 Add new,打开新增表单弹窗
+ await page.getByLabel('action-Action-Add new-create-').click();
+
+ // 2. 新增表单中,填上子表单的值,result 会自动计算结果
+ await page.getByLabel('action-AssociationField.').click();
+ await page.getByLabel('block-item-CollectionField-A-form-A.count-count').getByRole('spinbutton').fill('10');
+ await page.getByLabel('block-item-CollectionField-A-form-A.price-price').getByRole('spinbutton').fill('10');
+ // 10 * 10 = 100
+ await expect(
+ page.getByLabel('block-item-CollectionField-test-form-test.result-result').getByRole('spinbutton'),
+ ).toHaveValue('100');
+
+ // 3. 关闭弹窗,点击 Edit 按钮打开编辑表单弹窗
+ await page.getByLabel('drawer-Action.Container-test-Add record-mask').click();
+ await page.getByRole('button', { name: 'OK', exact: true }).click();
+ await page.getByLabel('action-Action.Link-Edit-').click();
+
+ // 4. 编辑表单中的 result 字段值,应该是由子表格中填入的值计算得出的
+ await expect(
+ page.getByLabel('block-item-CollectionField-test-form-test.result-result').getByRole('spinbutton'),
+ ).toHaveValue(String(calcResult(record)));
+
+ // 5. 在子表格中新增并输入新的值,result 字段值会自动计算
+ await page.getByLabel('action-AssociationField.').click();
+ await page
+ .getByRole('row', { name: `table-index-${record.subtable.length + 1} block-item-` })
+ .getByRole('spinbutton')
+ .first()
+ .fill('10');
+ await page
+ .getByRole('row', { name: `table-index-${record.subtable.length + 1} block-item-` })
+ .getByRole('spinbutton')
+ .nth(1)
+ .fill('10');
+ await expect(
+ page.getByLabel('block-item-CollectionField-test-form-test.result-result').getByRole('spinbutton'),
+ ).toHaveValue(String(calcResult(record) + 10 * 10));
+ });
+});
+
+function calcResult(record) {
+ return record.subtable.reduce((acc, item) => acc + item.count * item.price, 0);
+}
diff --git a/packages/core/client/src/schema-settings/__e2e__/template.ts b/packages/core/client/src/schema-settings/__e2e__/template.ts
new file mode 100644
index 0000000000..13b17febb5
--- /dev/null
+++ b/packages/core/client/src/schema-settings/__e2e__/template.ts
@@ -0,0 +1,1076 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+export const formFieldDependsOnSubtableFieldsWithLinkageRules = {
+ collections: [
+ {
+ name: 'test',
+ fields: [
+ {
+ name: 'subtable',
+ interface: 'm2m',
+ target: 'A',
+ },
+ {
+ name: 'result',
+ interface: 'integer',
+ },
+ ],
+ },
+ {
+ name: 'A',
+ fields: [
+ {
+ name: 'count',
+ interface: 'integer',
+ },
+ {
+ name: 'price',
+ interface: 'integer',
+ },
+ {
+ name: 'totalPrice',
+ interface: 'integer',
+ },
+ ],
+ },
+ ],
+ pageSchema: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Page',
+ properties: {
+ s9fsohlzw8f: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-initializer': 'page:addBlock',
+ properties: {
+ v7w7gyk1f5i: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ uind6ar45tp: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ m51dz0t9b6y: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-decorator': 'TableBlockProvider',
+ 'x-acl-action': 'test:list',
+ 'x-use-decorator-props': 'useTableBlockDecoratorProps',
+ 'x-decorator-props': {
+ collection: 'test',
+ dataSource: 'main',
+ action: 'list',
+ params: {
+ pageSize: 20,
+ },
+ rowKey: 'id',
+ showIndex: true,
+ dragSort: false,
+ },
+ 'x-toolbar': 'BlockSchemaToolbar',
+ 'x-settings': 'blockSettings:table',
+ 'x-component': 'CardItem',
+ 'x-filter-targets': [],
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ actions: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-initializer': 'table:configureActions',
+ 'x-component': 'ActionBar',
+ 'x-component-props': {
+ style: {
+ marginBottom: 'var(--nb-spacing)',
+ },
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ rt2cjy9rsvk: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-action': 'create',
+ 'x-acl-action': 'create',
+ title: "{{t('Add new')}}",
+ 'x-toolbar': 'ActionSchemaToolbar',
+ 'x-settings': 'actionSettings:addNew',
+ 'x-component': 'Action',
+ 'x-decorator': 'ACLActionProvider',
+ 'x-component-props': {
+ openMode: 'drawer',
+ type: 'primary',
+ component: 'CreateRecordAction',
+ icon: 'PlusOutlined',
+ },
+ 'x-action-context': {
+ dataSource: 'main',
+ collection: 'test',
+ },
+ 'x-align': 'right',
+ 'x-acl-action-props': {
+ skipScopeCheck: true,
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ drawer: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ title: '{{ t("Add record") }}',
+ 'x-component': 'Action.Container',
+ 'x-component-props': {
+ className: 'nb-action-popup',
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ tabs: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Tabs',
+ 'x-component-props': {},
+ 'x-initializer': 'popup:addTab',
+ 'x-initializer-props': {
+ gridInitializer: 'popup:addNew:addBlock',
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ tab1: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ title: '{{t("Add new")}}',
+ 'x-component': 'Tabs.TabPane',
+ 'x-designer': 'Tabs.Designer',
+ 'x-component-props': {},
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ grid: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-initializer': 'popup:addNew:addBlock',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ ywxffhjclua: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ a9kvacdg2tc: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ o8zjbma555j: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-acl-action-props': {
+ skipScopeCheck: true,
+ },
+ 'x-acl-action': 'test:create',
+ 'x-decorator': 'FormBlockProvider',
+ 'x-use-decorator-props': 'useCreateFormBlockDecoratorProps',
+ 'x-decorator-props': {
+ dataSource: 'main',
+ collection: 'test',
+ },
+ 'x-toolbar': 'BlockSchemaToolbar',
+ 'x-settings': 'blockSettings:createForm',
+ 'x-component': 'CardItem',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ tm8ivq7t4am: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'FormV2',
+ 'x-use-component-props': 'useCreateFormBlockProps',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ grid: {
+ 'x-uid': 'n9mnrndx0su',
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-initializer': 'form:configureFields',
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-linkage-rules': [
+ {
+ condition: {
+ $and: [],
+ },
+ actions: [
+ {
+ targetFields: ['result'],
+ operator: 'value',
+ value: {
+ mode: 'express',
+ value: 'SUM({{$nForm.subtable.totalPrice}})',
+ result: 'SUM({{$nForm.subtable.totalPrice}})',
+ },
+ },
+ ],
+ },
+ ],
+ properties: {
+ dps74740h83: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ es5wn4kpq0n: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ subtable: {
+ 'x-uid': '5cy392nt0ue',
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'string',
+ 'x-toolbar': 'FormItemSchemaToolbar',
+ 'x-settings': 'fieldSettings:FormItem',
+ 'x-component': 'CollectionField',
+ 'x-decorator': 'FormItem',
+ 'x-collection-field': 'test.subtable',
+ 'x-component-props': {
+ fieldNames: {
+ label: 'id',
+ value: 'id',
+ },
+ mode: 'SubTable',
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ default: null,
+ 'x-linkage-rules': [
+ {
+ condition: {
+ $and: [],
+ },
+ actions: [
+ {
+ targetFields: ['totalPrice'],
+ operator: 'value',
+ value: {
+ mode: 'express',
+ value:
+ '{{$iteration.count}} * {{$iteration.price}}',
+ result:
+ '{{$iteration.count}} * {{$iteration.price}}',
+ },
+ },
+ ],
+ },
+ ],
+ properties: {
+ fudb5i21fut: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component':
+ 'AssociationField.SubTable',
+ 'x-initializer':
+ 'table:configureColumns',
+ 'x-initializer-props': {
+ action: false,
+ },
+ 'x-index': 1,
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ '6x5wkmj87ds': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-decorator':
+ 'TableV2.Column.Decorator',
+ 'x-toolbar':
+ 'TableColumnSchemaToolbar',
+ 'x-settings':
+ 'fieldSettings:TableColumn',
+ 'x-component': 'TableV2.Column',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ count: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ 'x-collection-field': 'A.count',
+ 'x-component':
+ 'CollectionField',
+ 'x-component-props': {},
+ 'x-decorator': 'FormItem',
+ 'x-decorator-props': {
+ labelStyle: {
+ display: 'none',
+ },
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-uid': 'tejnrvflzcc',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'xo439o33oad',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ o25avq2mf8k: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-decorator':
+ 'TableV2.Column.Decorator',
+ 'x-toolbar':
+ 'TableColumnSchemaToolbar',
+ 'x-settings':
+ 'fieldSettings:TableColumn',
+ 'x-component': 'TableV2.Column',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ price: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ 'x-collection-field': 'A.price',
+ 'x-component':
+ 'CollectionField',
+ 'x-component-props': {},
+ 'x-decorator': 'FormItem',
+ 'x-decorator-props': {
+ labelStyle: {
+ display: 'none',
+ },
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-uid': 'jsbtond5omz',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '9f63c4olrwn',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ '60tkt9imffo': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-decorator':
+ 'TableV2.Column.Decorator',
+ 'x-toolbar':
+ 'TableColumnSchemaToolbar',
+ 'x-settings':
+ 'fieldSettings:TableColumn',
+ 'x-component': 'TableV2.Column',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ totalPrice: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ 'x-collection-field':
+ 'A.totalPrice',
+ 'x-component':
+ 'CollectionField',
+ 'x-component-props': {},
+ 'x-decorator': 'FormItem',
+ 'x-decorator-props': {
+ labelStyle: {
+ display: 'none',
+ },
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-uid': '3t5mcxqnvug',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'ia6b07nznai',
+ 'x-async': false,
+ 'x-index': 3,
+ },
+ },
+ 'x-uid': '7mfo2ghlm1u',
+ 'x-async': false,
+ },
+ },
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '4ybaip2vsom',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '0htuiv6h9q3',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ '5nb0mqfghxn': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ '7s16r268pzg': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ result: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'string',
+ 'x-toolbar': 'FormItemSchemaToolbar',
+ 'x-settings': 'fieldSettings:FormItem',
+ 'x-component': 'CollectionField',
+ 'x-decorator': 'FormItem',
+ 'x-collection-field': 'test.result',
+ 'x-component-props': {},
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-uid': 'oox2v051uny',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'hrdncy8zala',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '5e0rr72styk',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ },
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ skjmcwe0p20: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-initializer': 'createForm:configureActions',
+ 'x-component': 'ActionBar',
+ 'x-component-props': {
+ layout: 'one-column',
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-uid': '18t8ku582fy',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ },
+ 'x-uid': 'fm804i55bj5',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'zywps9uss57',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '2rflbnog4zn',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'vp4003775uj',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'pfbg2t0s0xq',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '8zvo8pxibxw',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 's9lqnj4dbmh',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'lsfsv0rhz3z',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'wtqgiyld6w5',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'ix7m1ttw4qc',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ c2soycrurkj: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'array',
+ 'x-initializer': 'table:configureColumns',
+ 'x-component': 'TableV2',
+ 'x-use-component-props': 'useTableBlockProps',
+ 'x-component-props': {
+ rowKey: 'id',
+ rowSelection: {
+ type: 'checkbox',
+ },
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ actions: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ title: '{{ t("Actions") }}',
+ 'x-action-column': 'actions',
+ 'x-decorator': 'TableV2.Column.ActionBar',
+ 'x-component': 'TableV2.Column',
+ 'x-toolbar': 'TableColumnSchemaToolbar',
+ 'x-initializer': 'table:configureItemActions',
+ 'x-settings': 'fieldSettings:TableColumn',
+ 'x-toolbar-props': {
+ initializer: 'table:configureItemActions',
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ t2ffxdsxbyn: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-decorator': 'DndContext',
+ 'x-component': 'Space',
+ 'x-component-props': {
+ split: '|',
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ y7vo4p2gfyl: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ title: '{{ t("Edit") }}',
+ 'x-action': 'update',
+ 'x-toolbar': 'ActionSchemaToolbar',
+ 'x-settings': 'actionSettings:edit',
+ 'x-component': 'Action.Link',
+ 'x-component-props': {
+ openMode: 'drawer',
+ icon: 'EditOutlined',
+ },
+ 'x-action-context': {
+ dataSource: 'main',
+ collection: 'test',
+ },
+ 'x-decorator': 'ACLActionProvider',
+ 'x-designer-props': {
+ linkageAction: true,
+ },
+ properties: {
+ drawer: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ title: '{{ t("Edit record") }}',
+ 'x-component': 'Action.Container',
+ 'x-component-props': {
+ className: 'nb-action-popup',
+ },
+ properties: {
+ tabs: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Tabs',
+ 'x-component-props': {},
+ 'x-initializer': 'popup:addTab',
+ properties: {
+ tab1: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ title: '{{t("Edit")}}',
+ 'x-component': 'Tabs.TabPane',
+ 'x-designer': 'Tabs.Designer',
+ 'x-component-props': {},
+ properties: {
+ grid: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-initializer': 'popup:common:addBlock',
+ properties: {
+ oupr0q9l79t: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ ktzwrj8g09a: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ fsgs3lhyhaq: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-acl-action-props': {
+ skipScopeCheck: false,
+ },
+ 'x-acl-action': 'test:update',
+ 'x-decorator': 'FormBlockProvider',
+ 'x-use-decorator-props':
+ 'useEditFormBlockDecoratorProps',
+ 'x-decorator-props': {
+ action: 'get',
+ dataSource: 'main',
+ collection: 'test',
+ },
+ 'x-toolbar': 'BlockSchemaToolbar',
+ 'x-settings': 'blockSettings:editForm',
+ 'x-component': 'CardItem',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ '1xi8hkpsalu': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'FormV2',
+ 'x-use-component-props': 'useEditFormBlockProps',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ grid: {
+ 'x-uid': 'xvc3xco2z03',
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-initializer': 'form:configureFields',
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-linkage-rules': [
+ {
+ condition: {
+ $and: [],
+ },
+ actions: [
+ {
+ targetFields: ['result'],
+ operator: 'value',
+ value: {
+ mode: 'express',
+ value:
+ 'SUM({{$nForm.subtable.totalPrice}})',
+ result:
+ 'SUM({{$nForm.subtable.totalPrice}})',
+ },
+ },
+ ],
+ },
+ ],
+ properties: {
+ q8u7c53id3k: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ jng7w3s4wcv: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ subtable: {
+ 'x-uid': 'vvqvpcok2f2',
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'string',
+ 'x-toolbar':
+ 'FormItemSchemaToolbar',
+ 'x-settings':
+ 'fieldSettings:FormItem',
+ 'x-component': 'CollectionField',
+ 'x-decorator': 'FormItem',
+ 'x-collection-field':
+ 'test.subtable',
+ 'x-component-props': {
+ fieldNames: {
+ label: 'id',
+ value: 'id',
+ },
+ mode: 'SubTable',
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-linkage-rules': [
+ {
+ condition: {
+ $and: [],
+ },
+ actions: [
+ {
+ targetFields: [
+ 'totalPrice',
+ ],
+ operator: 'value',
+ value: {
+ mode: 'express',
+ value:
+ '{{$iteration.count}} * {{$iteration.price}}',
+ result:
+ '{{$iteration.count}} * {{$iteration.price}}',
+ },
+ },
+ ],
+ },
+ ],
+ properties: {
+ znd2re8ssi4: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component':
+ 'AssociationField.SubTable',
+ 'x-initializer':
+ 'table:configureColumns',
+ 'x-initializer-props': {
+ action: false,
+ },
+ 'x-index': 1,
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ n4vmmrdqjzl: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-decorator':
+ 'TableV2.Column.Decorator',
+ 'x-toolbar':
+ 'TableColumnSchemaToolbar',
+ 'x-settings':
+ 'fieldSettings:TableColumn',
+ 'x-component':
+ 'TableV2.Column',
+ 'x-app-version':
+ '1.5.0-beta.6',
+ properties: {
+ count: {
+ _isJSONSchemaObject:
+ true,
+ version: '2.0',
+ 'x-collection-field':
+ 'A.count',
+ 'x-component':
+ 'CollectionField',
+ 'x-component-props': {},
+ 'x-decorator':
+ 'FormItem',
+ 'x-decorator-props': {
+ labelStyle: {
+ display: 'none',
+ },
+ },
+ 'x-app-version':
+ '1.5.0-beta.6',
+ 'x-uid': 'zv2z6805whp',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'r1ungnjfbgu',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ jz1by8rmwfk: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-decorator':
+ 'TableV2.Column.Decorator',
+ 'x-toolbar':
+ 'TableColumnSchemaToolbar',
+ 'x-settings':
+ 'fieldSettings:TableColumn',
+ 'x-component':
+ 'TableV2.Column',
+ 'x-app-version':
+ '1.5.0-beta.6',
+ properties: {
+ price: {
+ _isJSONSchemaObject:
+ true,
+ version: '2.0',
+ 'x-collection-field':
+ 'A.price',
+ 'x-component':
+ 'CollectionField',
+ 'x-component-props': {},
+ 'x-decorator':
+ 'FormItem',
+ 'x-decorator-props': {
+ labelStyle: {
+ display: 'none',
+ },
+ },
+ 'x-app-version':
+ '1.5.0-beta.6',
+ 'x-uid': '88jtwgdvfm8',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'ytfcqn0iaof',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ yv763dj36k6: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-decorator':
+ 'TableV2.Column.Decorator',
+ 'x-toolbar':
+ 'TableColumnSchemaToolbar',
+ 'x-settings':
+ 'fieldSettings:TableColumn',
+ 'x-component':
+ 'TableV2.Column',
+ 'x-app-version':
+ '1.5.0-beta.6',
+ properties: {
+ totalPrice: {
+ _isJSONSchemaObject:
+ true,
+ version: '2.0',
+ 'x-collection-field':
+ 'A.totalPrice',
+ 'x-component':
+ 'CollectionField',
+ 'x-component-props': {},
+ 'x-decorator':
+ 'FormItem',
+ 'x-decorator-props': {
+ labelStyle: {
+ display: 'none',
+ },
+ },
+ 'x-app-version':
+ '1.5.0-beta.6',
+ 'x-uid': 'hmo5jyy232z',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '9ydu5bfuane',
+ 'x-async': false,
+ 'x-index': 3,
+ },
+ },
+ 'x-uid': 'r15f9730kx9',
+ 'x-async': false,
+ },
+ },
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '8etldmvdcuk',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'phzdazcju65',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ iub3idfpdh4: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ lanveo0xcn8: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ 'x-app-version': '1.5.0-beta.6',
+ properties: {
+ result: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'string',
+ 'x-toolbar':
+ 'FormItemSchemaToolbar',
+ 'x-settings':
+ 'fieldSettings:FormItem',
+ 'x-component': 'CollectionField',
+ 'x-decorator': 'FormItem',
+ 'x-collection-field': 'test.result',
+ 'x-component-props': {},
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-uid': 'dx1iv4qkd1b',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'uopqm34ayjo',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'fzfarnr4w4j',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ },
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ '2t6nvnwkbnw': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-initializer': 'editForm:configureActions',
+ 'x-component': 'ActionBar',
+ 'x-component-props': {
+ layout: 'one-column',
+ },
+ 'x-app-version': '1.5.0-beta.6',
+ 'x-uid': 'uxn3xrgzvtz',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ },
+ 'x-uid': 'pn1nhhwzbsg',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '8d6rs0f8wzh',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'r678ucgswj3',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'nvaaet6kz8g',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'xjmk0qr3mbt',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'vc90fgylb6h',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'w5xitaqziom',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'ehdyxv75fuw',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': '42vuhd1ofz1',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'k36zbevibrq',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'ugqxdneo59c',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'salmxthgmls',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ },
+ 'x-uid': 'czxd4c86gvq',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'jqbr04lfqlk',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'ae2fs884ol4',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'p568ms2llzx',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'plh5cv01fwd',
+ 'x-async': true,
+ 'x-index': 1,
+ },
+};