From 08162e1004db07df202c20a6fa8a6d1104f05f89 Mon Sep 17 00:00:00 2001
From: Zeke Zhang <958414905@qq.com>
Date: Thu, 28 Mar 2024 22:03:22 +0800
Subject: [PATCH] fix(LinkageRules): should work properly after the block is
saved as a template (#3855)
* test: add e2e
* chore: optimize e2e
* fix: use context in Form
---
.../form-create/schemaSettings.test.ts | 43 +++-
.../__e2e__/form-create/templatesOfBug.ts | 201 ++++++++++++++++++
.../schema-component/antd/form-v2/Form.tsx | 4 +-
3 files changed, 246 insertions(+), 2 deletions(-)
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings.test.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings.test.ts
index 738b7d6a12..836d3847ad 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings.test.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings.test.ts
@@ -9,7 +9,7 @@ import {
oneTableBlockWithAddNewAndViewAndEditAndBasicFields,
test,
} from '@nocobase/test/e2e';
-import { T2165, T2174, T3251 } from './templatesOfBug';
+import { T2165, T2174, T3251, T3806 } from './templatesOfBug';
const clickOption = async (page: Page, optionName: string) => {
await page.getByLabel('block-item-CardItem-general-form').hover();
@@ -254,6 +254,47 @@ test.describe('creation form block schema settings', () => {
page.getByLabel('block-item-CollectionField-users-form-users.email-Email').getByRole('textbox'),
).toBeEditable();
});
+
+ // https://nocobase.height.app/T-3806
+ test('after save as block template', async ({ page, mockPage }) => {
+ await mockPage(T3806).goto();
+
+ // 1. 一开始联动规则应该正常
+ await page
+ .getByLabel('block-item-CollectionField-users-form-users.nickname-Nickname')
+ .getByRole('textbox')
+ .fill('123');
+ await expect(
+ page.getByLabel('block-item-CollectionField-users-form-users.username-Username').getByRole('textbox'),
+ ).toHaveValue('123');
+
+ try {
+ // 2. 将表单区块保存为模板后
+ await page.getByLabel('block-item-CardItem-users-form').hover();
+ await page.getByLabel('designer-schema-settings-CardItem-blockSettings:createForm-users').hover();
+ await page.getByRole('menuitem', { name: 'Save as block template' }).click();
+ await page.getByRole('button', { name: 'OK', exact: true }).click();
+ await page.waitForTimeout(1000);
+
+ // 3. 联动规则应该依然是正常的
+ await page
+ .getByLabel('block-item-CollectionField-users-form-users.nickname-Nickname')
+ .getByRole('textbox')
+ .fill('456');
+ await expect(
+ page.getByLabel('block-item-CollectionField-users-form-users.username-Username').getByRole('textbox'),
+ ).toHaveValue('456');
+ } catch (err) {
+ throw err;
+ } finally {
+ // 4. 把创建的模板删除
+ await page.goto('/admin/settings/ui-schema-storage');
+ await page.getByLabel('Select all').check();
+ await page.getByLabel('action-Action-Delete-destroy-').click();
+ await page.getByRole('button', { name: 'OK', exact: true }).click();
+ await expect(page.getByRole('row', { name: 'Users_Form' }).first()).toBeHidden();
+ }
+ });
});
test('Save as block template & convert reference to duplicate', async ({ page, mockPage }) => {
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts
index adf352e49b..2f6ed4d94c 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts
@@ -6066,3 +6066,204 @@ export const T3529: PageConfig = {
'x-index': 1,
},
};
+
+export const T3806: PageConfig = {
+ pageSchema: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Page',
+ properties: {
+ '6w8tkq3665g': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-initializer': 'page:addBlock',
+ properties: {
+ '0k0yifwylj8': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ properties: {
+ v5cdqnvyh3z: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ properties: {
+ p9pszqbz1n5: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-acl-action-props': {
+ skipScopeCheck: true,
+ },
+ 'x-acl-action': 'users:create',
+ 'x-decorator': 'FormBlockProvider',
+ 'x-use-decorator-props': 'useCreateFormBlockDecoratorProps',
+ 'x-decorator-props': {
+ dataSource: 'main',
+ collection: 'users',
+ },
+ 'x-toolbar': 'BlockSchemaToolbar',
+ 'x-settings': 'blockSettings:createForm',
+ 'x-component': 'CardItem',
+ properties: {
+ '578cg3ao40s': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'FormV2',
+ 'x-use-component-props': 'useCreateFormBlockProps',
+ properties: {
+ grid: {
+ 'x-uid': 'xpdqjz634mt',
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-initializer': 'form:configureFields',
+ 'x-linkage-rules': [
+ {
+ condition: {
+ $and: [],
+ },
+ actions: [
+ {
+ targetFields: ['username'],
+ operator: 'value',
+ value: {
+ mode: 'express',
+ value: '{{$nForm.nickname}}',
+ result: '{{$nForm.nickname}}',
+ },
+ },
+ ],
+ },
+ ],
+ properties: {
+ gjck905cyws: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ properties: {
+ i041myizzph: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ properties: {
+ nickname: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'string',
+ 'x-toolbar': 'FormItemSchemaToolbar',
+ 'x-settings': 'fieldSettings:FormItem',
+ 'x-component': 'CollectionField',
+ 'x-decorator': 'FormItem',
+ 'x-collection-field': 'users.nickname',
+ 'x-component-props': {},
+ 'x-uid': 'afnfoxl5cbi',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'a3o7l08zz6e',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'zoakp82dymw',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ qffoo7lqua1: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ properties: {
+ nq0rbuti1d9: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ properties: {
+ username: {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'string',
+ 'x-toolbar': 'FormItemSchemaToolbar',
+ 'x-settings': 'fieldSettings:FormItem',
+ 'x-component': 'CollectionField',
+ 'x-decorator': 'FormItem',
+ 'x-collection-field': 'users.username',
+ 'x-component-props': {},
+ 'x-uid': 'mq80n8nyuq8',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'hf9bq4vjm80',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'ua08izsl514',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ },
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ '006ip4mnr75': {
+ _isJSONSchemaObject: true,
+ version: '2.0',
+ type: 'void',
+ 'x-initializer': 'createForm:configureActions',
+ 'x-component': 'ActionBar',
+ 'x-component-props': {
+ layout: 'one-column',
+ style: {
+ marginTop: 24,
+ },
+ },
+ 'x-uid': 'u6d026lia1x',
+ 'x-async': false,
+ 'x-index': 2,
+ },
+ },
+ 'x-uid': 'p7ucl8ixcx4',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'hz9xoui3o9d',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'j1q201o2wju',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 't0olm6ygvas',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'aq4i1y0nf00',
+ 'x-async': false,
+ 'x-index': 1,
+ },
+ },
+ 'x-uid': 'px8uapyslvw',
+ 'x-async': true,
+ 'x-index': 1,
+ },
+};
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 4c707ba6ee..176fdd7daf 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
@@ -19,6 +19,7 @@ import { getInnermostKeyAndValue, getTargetField } from '../../common/utils/uitl
import { useProps } from '../../hooks/useProps';
import { collectFieldStateOfLinkageRules, getTempFieldState } from './utils';
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
+import { useTemplateBlockContext } from '../../../block-provider/TemplateBlockProvider';
export interface FormProps {
[key: string]: any;
@@ -87,6 +88,7 @@ const WithForm = (props: WithFormProps) => {
const { setFormValueChanged } = useActionContext();
const variables = useVariables();
const localVariables = useLocalVariables({ currentForm: form });
+ const { templateFinshed } = useTemplateBlockContext();
const linkageRules: any[] =
(getLinkageRules(fieldSchema) || fieldSchema.parent?.['x-linkage-rules'])?.filter((k) => !k.disabled) || [];
@@ -166,7 +168,7 @@ const WithForm = (props: WithFormProps) => {
dispose();
});
};
- }, [linkageRules]);
+ }, [linkageRules, templateFinshed]);
return fieldSchema['x-decorator'] === 'FormV2' ? : ;
};