perf: remove lazy load association fields (#3222)
* perf: remove lazy load association fields * test: fix error * chore: fix workflows * test: fix error * test: fix errors
This commit is contained in:
parent
aaee46e0c2
commit
e7b9737920
@ -49,6 +49,74 @@ test.describe('display association fields', () => {
|
||||
);
|
||||
});
|
||||
|
||||
// https://nocobase.height.app/T-2615
|
||||
test('BUG: should load association data', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T2615).waitForInit();
|
||||
await mockRecord('T2615');
|
||||
await nocoPage.goto();
|
||||
|
||||
// 1. 新增表单中应该显示关系字段的数据
|
||||
await page.getByRole('button', { name: 'Add new' }).click();
|
||||
await page
|
||||
.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o-m2o')
|
||||
.getByTestId('select-object-single')
|
||||
.click();
|
||||
await page.getByRole('option', { name: '1' }).click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o.m2oOfTarget1')).toHaveText(
|
||||
`m2oOfTarget1:1`,
|
||||
);
|
||||
|
||||
// 关闭弹窗
|
||||
await page.getByLabel('drawer-Action.Container-T2615-Add record-mask').click();
|
||||
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||
|
||||
// 2. 编辑表单中应该显示关系字段的数据
|
||||
await page.getByLabel('action-Action.Link-Edit record-update-T2615-table-0').click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o-m2o')).toHaveText(`m2o:1`);
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o.m2oOfTarget1')).toHaveText(
|
||||
`m2oOfTarget1:1`,
|
||||
);
|
||||
|
||||
await page.getByLabel('drawer-Action.Container-T2615-Edit record-mask').click();
|
||||
|
||||
// 3. 详情中应该显示关系字段的数据
|
||||
await page.getByLabel('action-Action.Link-View record-view-T2615-table-0').click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o-m2o')).toHaveText(`m2o:1`);
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o.m2oOfTarget1')).toHaveText(
|
||||
`m2oOfTarget1:1`,
|
||||
);
|
||||
});
|
||||
|
||||
// https://nocobase.height.app/T-2614
|
||||
test('BUG: should load association data in subform', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T2614).waitForInit();
|
||||
await mockRecord('T2614');
|
||||
await nocoPage.goto();
|
||||
|
||||
// 查看详情
|
||||
await page.getByLabel('action-Action.Link-View record-view-T2614-table-0').click();
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-T2614Target1-form-T2614Target1.m2oOfTarget1-m2oOfTarget1'),
|
||||
).toHaveText(`m2oOfTarget1:1`);
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-T2614Target1-form-T2614Target1.m2oOfTarget1.id'),
|
||||
).toHaveText(`ID:1`);
|
||||
|
||||
// 关闭弹窗
|
||||
await page.getByLabel('drawer-Action.Container-T2614-View record-mask').click();
|
||||
|
||||
// 编辑详情
|
||||
await page.getByLabel('action-Action.Link-Edit record-update-T2614-table-0').click();
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-T2614Target1-form-T2614Target1.m2oOfTarget1-m2oOfTarget1'),
|
||||
).toHaveText(`m2oOfTarget1:1`);
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-T2614Target1-form-T2614Target1.m2oOfTarget1.id'),
|
||||
).toHaveText(`ID:1`);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('association fields', () => {
|
||||
test('subform: load association fields', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(oneTableSubformWithMultiLevelAssociationFields).waitForInit();
|
||||
const record = await mockRecord('general');
|
||||
@ -129,74 +197,6 @@ test.describe('display association fields', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// https://nocobase.height.app/T-2615
|
||||
test('BUG: should load association data', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T2615).waitForInit();
|
||||
await mockRecord('T2615');
|
||||
await nocoPage.goto();
|
||||
|
||||
// 1. 新增表单中应该显示关系字段的数据
|
||||
await page.getByRole('button', { name: 'Add new' }).click();
|
||||
await page
|
||||
.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o-m2o')
|
||||
.getByTestId('select-object-single')
|
||||
.click();
|
||||
await page.getByRole('option', { name: '1' }).click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o.m2oOfTarget1')).toHaveText(
|
||||
`m2oOfTarget1:1`,
|
||||
);
|
||||
|
||||
// 关闭弹窗
|
||||
await page.getByLabel('drawer-Action.Container-T2615-Add record-mask').click();
|
||||
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||
|
||||
// 2. 编辑表单中应该显示关系字段的数据
|
||||
await page.getByLabel('action-Action.Link-Edit record-update-T2615-table-0').click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o-m2o')).toHaveText(`m2o:1`);
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o.m2oOfTarget1')).toHaveText(
|
||||
`m2oOfTarget1:1`,
|
||||
);
|
||||
|
||||
await page.getByLabel('drawer-Action.Container-T2615-Edit record-mask').click();
|
||||
|
||||
// 3. 详情中应该显示关系字段的数据
|
||||
await page.getByLabel('action-Action.Link-View record-view-T2615-table-0').click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o-m2o')).toHaveText(`m2o:1`);
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o.m2oOfTarget1')).toHaveText(
|
||||
`m2oOfTarget1:1`,
|
||||
);
|
||||
});
|
||||
|
||||
// https://nocobase.height.app/T-2614
|
||||
test('BUG: should load association data in subform', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T2614).waitForInit();
|
||||
await mockRecord('T2614');
|
||||
await nocoPage.goto();
|
||||
|
||||
// 查看详情
|
||||
await page.getByLabel('action-Action.Link-View record-view-T2614-table-0').click();
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-T2614Target1-form-T2614Target1.m2oOfTarget1-m2oOfTarget1'),
|
||||
).toHaveText(`m2oOfTarget1:1`);
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-T2614Target1-form-T2614Target1.m2oOfTarget1.id'),
|
||||
).toHaveText(`ID:1`);
|
||||
|
||||
// 关闭弹窗
|
||||
await page.getByLabel('drawer-Action.Container-T2614-View record-mask').click();
|
||||
|
||||
// 编辑详情
|
||||
await page.getByLabel('action-Action.Link-Edit record-update-T2614-table-0').click();
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-T2614Target1-form-T2614Target1.m2oOfTarget1-m2oOfTarget1'),
|
||||
).toHaveText(`m2oOfTarget1:1`);
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-T2614Target1-form-T2614Target1.m2oOfTarget1.id'),
|
||||
).toHaveText(`ID:1`);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('association fields', () => {
|
||||
// fix https://nocobase.height.app/T-2200
|
||||
test('BUG: should be possible to change the value of the association field normally', async ({ page, mockPage }) => {
|
||||
await mockPage(T2200).goto();
|
||||
|
@ -14,7 +14,6 @@ import { BlockItem } from '../block-item';
|
||||
import { HTMLEncode } from '../input/shared';
|
||||
import { FilterFormDesigner } from './FormItem.FilterFormDesigner';
|
||||
import { useEnsureOperatorsValid } from './SchemaSettingOptions';
|
||||
import useLazyLoadAssociationFieldOfForm from './hooks/useLazyLoadAssociationFieldOfForm';
|
||||
import useLazyLoadDisplayAssociationFieldsOfForm from './hooks/useLazyLoadDisplayAssociationFieldsOfForm';
|
||||
import useParseDefaultValue from './hooks/useParseDefaultValue';
|
||||
|
||||
@ -34,7 +33,6 @@ export const FormItem: any = observer(
|
||||
// 需要放在注冊完变量之后
|
||||
useParseDefaultValue();
|
||||
useLazyLoadDisplayAssociationFieldsOfForm();
|
||||
useLazyLoadAssociationFieldOfForm();
|
||||
|
||||
useEffect(() => {
|
||||
addActiveFieldName?.(schema.name as string);
|
||||
|
@ -1,84 +0,0 @@
|
||||
import { Field } from '@formily/core';
|
||||
import { useField, useFieldSchema } from '@formily/react';
|
||||
import _ from 'lodash';
|
||||
import { useEffect } from 'react';
|
||||
import { useFormBlockType, useRecord } from '../../../..';
|
||||
import { useCollection, useCollectionManager } from '../../../../collection-manager';
|
||||
import { useFlag } from '../../../../flag-provider';
|
||||
import { useVariables } from '../../../../variables';
|
||||
import { transformVariableValue } from '../../../../variables/utils/transformVariableValue';
|
||||
import { isDisplayField, isFieldValueEmpty } from '../utils';
|
||||
|
||||
/**
|
||||
* 用于懒加载 Form 区块中正常的关系字段
|
||||
*
|
||||
* - 当 record 中缺少对应的字段值时,通过解析变量的方法去获取关系字段的值
|
||||
* - 注意:应该只有在编辑模式下运行,创建模式下直接返回
|
||||
*/
|
||||
const useLazyLoadAssociationFieldOfForm = () => {
|
||||
const { name } = useCollection();
|
||||
const { getCollectionJoinField } = useCollectionManager();
|
||||
const record = useRecord();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const variables = useVariables();
|
||||
const field = useField<Field>();
|
||||
const { isInAssignFieldValues, isInSubForm, isInSubTable } = useFlag() || {};
|
||||
const { type: formBlockType } = useFormBlockType();
|
||||
|
||||
const schemaName = fieldSchema.name.toString();
|
||||
|
||||
useEffect(() => {
|
||||
const cloneRecord = { ...record };
|
||||
delete cloneRecord['__parent'];
|
||||
delete cloneRecord['__collectionName'];
|
||||
|
||||
if (
|
||||
isInAssignFieldValues ||
|
||||
_.isEmpty(cloneRecord) ||
|
||||
(formBlockType === 'create' && !isInSubForm && !isInSubTable) ||
|
||||
isDisplayField(schemaName)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const collectionField = getCollectionJoinField(`${name}.${schemaName}`);
|
||||
|
||||
if (!collectionField) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!variables || !isFieldValueEmpty(_.get(record, schemaName), collectionField.targetKey || 'id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 通过模拟一个 record 变量,用解析变量的方法去获取关系字段的值
|
||||
const recordVariable = {
|
||||
name: '$nRecord',
|
||||
ctx: cloneRecord,
|
||||
collectionName: name,
|
||||
};
|
||||
const variableString = `{{ $nRecord.${schemaName} }}`;
|
||||
|
||||
variables
|
||||
.parseVariable(variableString, recordVariable)
|
||||
.then((value) => {
|
||||
// fix https://nocobase.height.app/T-2288
|
||||
// 造成这个问题的原因有以下几点:
|
||||
// 1. 编辑表单自身会请求数据,并在请求数据时,会在 appends 参数中加上所有的关系字段路径(包括子表单中的);
|
||||
// 2. 而 `变量预加载中` 也会请求对应关系字段的数据,但是请求的数据是不包含子表单中的关系字段的;
|
||||
// 3. 所以,当 `变量预加载` 的请求晚于编辑表单的请求时,就会造成这个问题;
|
||||
// 更优的解决方案是:在 `变量预加载` 中也加上子表单中的关系字段路径,并删除编辑表单请求数据的逻辑(因为没必要了)。
|
||||
// 但是这样改动较大,可以等之后 e2e 测试较完备后再处理。
|
||||
if (!isFieldValueEmpty(field.value, collectionField.targetKey || 'id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
field.value = transformVariableValue(value, { targetCollectionField: collectionField });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}, [record]);
|
||||
};
|
||||
|
||||
export default useLazyLoadAssociationFieldOfForm;
|
@ -86,22 +86,11 @@ test.describe('icon', () => {
|
||||
},
|
||||
expectReadonly: async () => {
|
||||
// 只读模式下,选择图标按钮会被禁用
|
||||
if (record.icon) {
|
||||
await expect(page.getByRole('button', { name: record.icon })).toBeDisabled();
|
||||
} else {
|
||||
await expect(page.getByRole('button', { name: 'Select icon' })).toBeDisabled();
|
||||
}
|
||||
await expect(page.getByRole('button', { name: 'account-book' })).toBeDisabled();
|
||||
},
|
||||
expectEasyReading: async () => {
|
||||
// 按钮会消失,只剩下图标
|
||||
if (record.icon) {
|
||||
await expect(page.getByRole('button', { name: record.icon })).not.toBeVisible();
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-general-form-general.icon-icon').getByLabel(record.icon),
|
||||
).toBeVisible();
|
||||
} else {
|
||||
await expect(page.getByRole('button', { name: 'Select icon' })).not.toBeVisible();
|
||||
}
|
||||
await expect(page.getByRole('button', { name: 'account-book' })).not.toBeVisible();
|
||||
},
|
||||
});
|
||||
});
|
||||
@ -298,7 +287,7 @@ test.describe('password', () => {
|
||||
page.getByLabel('block-item-CollectionField-general-form-general.password-password').getByRole('textbox'),
|
||||
).not.toBeVisible();
|
||||
await expect(page.getByLabel('block-item-CollectionField-general-form-general.password-password')).toHaveText(
|
||||
'password:',
|
||||
'password:********',
|
||||
);
|
||||
},
|
||||
});
|
||||
@ -407,7 +396,7 @@ test.describe('phone', () => {
|
||||
page.getByLabel('block-item-CollectionField-general-form-general.phone-phone').getByRole('textbox'),
|
||||
).not.toBeVisible();
|
||||
await expect(page.getByLabel('block-item-CollectionField-general-form-general.phone-phone')).toHaveText(
|
||||
'phone:',
|
||||
'phone:17777777777',
|
||||
);
|
||||
},
|
||||
});
|
||||
@ -453,7 +442,7 @@ test.describe('long text', () => {
|
||||
page.getByLabel('block-item-CollectionField-general-form-general.longText-longText').getByRole('textbox'),
|
||||
).not.toBeVisible();
|
||||
await expect(page.getByLabel('block-item-CollectionField-general-form-general.longText-longText')).toHaveText(
|
||||
`longText:${record.longText}`.replaceAll('\n', ''),
|
||||
`longText:test long text`,
|
||||
);
|
||||
},
|
||||
});
|
||||
@ -496,11 +485,12 @@ test.describe('URL', () => {
|
||||
).toBeDisabled();
|
||||
},
|
||||
expectEasyReading: async () => {
|
||||
// url 类型数据不会被 mock,所以这里不会显示值
|
||||
await expect(
|
||||
page.getByLabel('block-item-CollectionField-general-form-general.url-url').getByRole('textbox'),
|
||||
).not.toBeVisible();
|
||||
await expect(page.getByLabel('block-item-CollectionField-general-form-general.url-url')).toHaveText('url:');
|
||||
await expect(page.getByLabel('block-item-CollectionField-general-form-general.url-url')).toHaveText(
|
||||
'url:https://nocobase.com',
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user