mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-02 20:27:49 +08:00
fix: use appends param to load association data (#3282)
* fix: use appends param to load association data * chore: update yarn.lock * test: add test * test: remove the 'BUG:' text * test: fix 'window is not defined' * test: increase timeout
This commit is contained in:
parent
0c12fbce29
commit
c6915c69f8
@ -305,7 +305,8 @@ export const BlockProvider = (props: {
|
||||
}) => {
|
||||
const { collection, association, name } = props;
|
||||
const resource = useResource(props);
|
||||
const { appends, updateAssociationValues } = useAssociationNames();
|
||||
const { getAssociationAppends } = useAssociationNames();
|
||||
const { appends, updateAssociationValues } = getAssociationAppends();
|
||||
const params = useMemo(() => {
|
||||
if (!props.params?.['appends']) {
|
||||
return { ...props.params, appends };
|
||||
|
@ -1295,11 +1295,11 @@ export function getAssociationPath(str) {
|
||||
}
|
||||
|
||||
export const useAssociationNames = () => {
|
||||
let updateAssociationValues = new Set([]);
|
||||
let appends = new Set([]);
|
||||
const { getCollectionJoinField, getCollection } = useCollectionManager();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const updateAssociationValues = new Set([]);
|
||||
const appends = new Set([]);
|
||||
const getAssociationAppends = (schema, str) => {
|
||||
const _getAssociationAppends = (schema, str) => {
|
||||
schema.reduceProperties((pre, s) => {
|
||||
const prefix = pre || str;
|
||||
const collectionField = s['x-collection-field'] && getCollectionJoinField(s['x-collection-field']);
|
||||
@ -1338,7 +1338,7 @@ export const useAssociationNames = () => {
|
||||
if (['Nester', 'SubTable', 'PopoverNester'].includes(s['x-component-props']?.mode)) {
|
||||
updateAssociationValues.add(path);
|
||||
const bufPrefix = prefix && prefix !== '' ? prefix + '.' + s.name : s.name;
|
||||
getAssociationAppends(s, bufPrefix);
|
||||
_getAssociationAppends(s, bufPrefix);
|
||||
}
|
||||
} else if (
|
||||
![
|
||||
@ -1354,12 +1354,18 @@ export const useAssociationNames = () => {
|
||||
'TableField',
|
||||
].includes(s['x-component'])
|
||||
) {
|
||||
getAssociationAppends(s, str);
|
||||
_getAssociationAppends(s, str);
|
||||
}
|
||||
}, str);
|
||||
};
|
||||
getAssociationAppends(fieldSchema, '');
|
||||
return { appends: [...appends], updateAssociationValues: [...updateAssociationValues] };
|
||||
const getAssociationAppends = () => {
|
||||
updateAssociationValues = new Set([]);
|
||||
appends = new Set([]);
|
||||
_getAssociationAppends(fieldSchema, '');
|
||||
return { appends: [...appends], updateAssociationValues: [...updateAssociationValues] };
|
||||
};
|
||||
|
||||
return { getAssociationAppends };
|
||||
};
|
||||
|
||||
function getTargetField(obj) {
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
oneTableSubtableWithMultiLevelAssociationFields,
|
||||
test,
|
||||
} from '@nocobase/test/e2e';
|
||||
import { T2200, T2614, T2615 } from './templatesOfBug';
|
||||
import { T2200, T2614, T2615, T2845 } from './templatesOfBug';
|
||||
|
||||
test.describe('display association fields', () => {
|
||||
test('form: should display correctly', async ({ page, mockPage, mockRecord }) => {
|
||||
@ -50,7 +50,7 @@ test.describe('display association fields', () => {
|
||||
});
|
||||
|
||||
// https://nocobase.height.app/T-2615
|
||||
test('BUG: should load association data', async ({ page, mockPage, mockRecord }) => {
|
||||
test('should load association data', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T2615).waitForInit();
|
||||
await mockRecord('T2615');
|
||||
await nocoPage.goto();
|
||||
@ -87,8 +87,57 @@ test.describe('display association fields', () => {
|
||||
);
|
||||
});
|
||||
|
||||
// https://nocobase.height.app/T-2845
|
||||
test('should load association data of subform', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T2845).waitForInit();
|
||||
// 和 T2615 使用一样的数据表结构
|
||||
const record = 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: String(record.m2o.id) }).click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615Target2-form-T2615Target2.id-ID')).toHaveText(
|
||||
`ID:${record.m2o.m2oOfTarget1.id}`,
|
||||
);
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615Target2-form-T2615Target2.m2oOfTarget2-')).toHaveText(
|
||||
`m2oOfTarget2:${record.m2o.m2oOfTarget1.m2oOfTarget2.id}`,
|
||||
);
|
||||
|
||||
// 关闭弹窗
|
||||
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-${record.id - 1}`).click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615Target2-form-T2615Target2.id-ID')).toHaveText(
|
||||
`ID:${record.m2o.m2oOfTarget1.id}`,
|
||||
);
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615Target2-form-T2615Target2.m2oOfTarget2-')).toHaveText(
|
||||
`m2oOfTarget2:${record.m2o.m2oOfTarget1.m2oOfTarget2.id}`,
|
||||
);
|
||||
|
||||
await page.getByLabel('drawer-Action.Container-T2615-Edit record-mask').click();
|
||||
|
||||
// 3. 详情中应该显示关系字段的数据
|
||||
await page.getByLabel(`action-Action.Link-View record-view-T2615-table-${record.id - 1}`).click();
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615-form-T2615.m2o-m2o')).toHaveText(
|
||||
`m2o:${record.m2o.id}`,
|
||||
);
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615Target2-form-T2615Target2.id-ID')).toHaveText(
|
||||
`ID:${record.m2o.m2oOfTarget1.id}`,
|
||||
);
|
||||
await expect(page.getByLabel('block-item-CollectionField-T2615Target2-form-T2615Target2.m2oOfTarget2-')).toHaveText(
|
||||
`m2oOfTarget2:${record.m2o.m2oOfTarget1.m2oOfTarget2.id}`,
|
||||
);
|
||||
});
|
||||
|
||||
// https://nocobase.height.app/T-2614
|
||||
test('BUG: should load association data in subform', async ({ page, mockPage, mockRecord }) => {
|
||||
test('should load association data in subform', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T2614).waitForInit();
|
||||
await mockRecord('T2614');
|
||||
await nocoPage.goto();
|
||||
@ -198,7 +247,7 @@ 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 }) => {
|
||||
test('should be possible to change the value of the association field normally', async ({ page, mockPage }) => {
|
||||
await mockPage(T2200).goto();
|
||||
|
||||
await page.getByLabel('action-Action.Link-Edit-update-users-table-0').click();
|
||||
|
@ -212,7 +212,7 @@ test.describe('creation form block schema settings', () => {
|
||||
});
|
||||
|
||||
// fix https://nocobase.height.app/T-2165
|
||||
test('BUG: variable labels should be displayed normally', async ({ page, mockPage }) => {
|
||||
test('variable labels should be displayed normally', async ({ page, mockPage }) => {
|
||||
await mockPage(T2165).goto();
|
||||
|
||||
await page.getByLabel('block-item-CardItem-users-form').hover();
|
||||
@ -628,7 +628,7 @@ test.describe('creation form block schema settings', () => {
|
||||
});
|
||||
|
||||
// fix https://nocobase.height.app/T-2174
|
||||
test('BUG: should show default value option', async ({ page, mockPage, mockRecord }) => {
|
||||
test('should show default value option', async ({ page, mockPage, mockRecord }) => {
|
||||
const nocoPage = await mockPage(T2174).waitForInit();
|
||||
await mockRecord('test2174');
|
||||
await nocoPage.goto();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@ import { expect, test } from '@nocobase/test/e2e';
|
||||
import { T2187 } from '../templatesOfBug';
|
||||
|
||||
// fix https://nocobase.height.app/T-2187
|
||||
test('BUG: in the Duplicate mode, the Roles field should not have a value after clicking it because it is not selected', async ({
|
||||
test('in the Duplicate mode, the Roles field should not have a value after clicking it because it is not selected', async ({
|
||||
page,
|
||||
mockPage,
|
||||
}) => {
|
||||
|
@ -2,7 +2,7 @@ import { expect, test } from '@nocobase/test/e2e';
|
||||
import { T2183, T2186 } from '../templatesOfBug';
|
||||
|
||||
// fix https://nocobase.height.app/T-2183
|
||||
test('BUG: should save conditions', async ({ page, mockPage }) => {
|
||||
test('should save conditions', async ({ page, mockPage }) => {
|
||||
await mockPage(T2183).goto();
|
||||
await page.getByLabel('action-Filter.Action-Filter-filter-users-table').click();
|
||||
await page.getByText('Add condition', { exact: true }).click();
|
||||
@ -19,7 +19,7 @@ test('BUG: should save conditions', async ({ page, mockPage }) => {
|
||||
});
|
||||
|
||||
// fix https://nocobase.height.app/T-2186
|
||||
test('BUG: the input box displayed should correspond to the field type', async ({ page, mockPage }) => {
|
||||
test('the input box displayed should correspond to the field type', async ({ page, mockPage }) => {
|
||||
await mockPage(T2186).goto();
|
||||
|
||||
await page.getByLabel('action-Filter.Action-Filter-filter-users-table').click();
|
||||
|
@ -3,6 +3,7 @@ import { useField, useFieldSchema, useForm } from '@formily/react';
|
||||
import { nextTick } from '@nocobase/utils/client';
|
||||
import _ from 'lodash';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useAssociationNames } from '../../../../block-provider';
|
||||
import { useCollection, useCollectionManager } from '../../../../collection-manager';
|
||||
import { useFlag } from '../../../../flag-provider';
|
||||
import { useVariables } from '../../../../variables';
|
||||
@ -25,6 +26,7 @@ const useLazyLoadDisplayAssociationFieldsOfForm = () => {
|
||||
const field = useField<Field>();
|
||||
const { formValue: subFormValue } = useSubFormValue();
|
||||
const { isInSubForm, isInSubTable } = useFlag() || {};
|
||||
const { getAssociationAppends } = useAssociationNames();
|
||||
|
||||
const schemaName = fieldSchema.name.toString();
|
||||
const formValue = _.cloneDeep(isInSubForm || isInSubTable ? subFormValue : form.values);
|
||||
@ -66,8 +68,10 @@ const useLazyLoadDisplayAssociationFieldsOfForm = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const { appends } = getAssociationAppends();
|
||||
|
||||
variables
|
||||
.parseVariable(variableString, formVariable)
|
||||
.parseVariable(variableString, formVariable, { appends })
|
||||
.then((value) => {
|
||||
nextTick(() => {
|
||||
const result = transformVariableValue(value, { targetCollectionField: collectionFieldRef.current });
|
||||
|
@ -51,7 +51,14 @@ const VariablesProvider = ({ children }) => {
|
||||
* 3. 如果某个 `key` 不存在,且 `key` 不是一个关联字段,则返回当前值
|
||||
*/
|
||||
const getValue = useCallback(
|
||||
async (variablePath: string, localVariables?: VariableOption[]) => {
|
||||
async (
|
||||
variablePath: string,
|
||||
localVariables?: VariableOption[],
|
||||
options?: {
|
||||
/** 第一次请求时,需要包含的关系字段 */
|
||||
appends?: string[];
|
||||
},
|
||||
) => {
|
||||
const list = variablePath.split('.');
|
||||
const variableName = list[0];
|
||||
const _variableToCollectionName = mergeVariableToCollectionNameWithLocalVariables(
|
||||
@ -85,6 +92,9 @@ const VariablesProvider = ({ children }) => {
|
||||
const result = api
|
||||
.request({
|
||||
url,
|
||||
params: {
|
||||
appends: options?.appends,
|
||||
},
|
||||
})
|
||||
.then((data) => {
|
||||
clearRequested(url);
|
||||
@ -106,6 +116,9 @@ const VariablesProvider = ({ children }) => {
|
||||
} else {
|
||||
const waitForData = api.request({
|
||||
url,
|
||||
params: {
|
||||
appends: options?.appends,
|
||||
},
|
||||
});
|
||||
stashRequested(url, waitForData);
|
||||
data = await waitForData;
|
||||
@ -180,7 +193,14 @@ const VariablesProvider = ({ children }) => {
|
||||
* @param localVariables 局部变量,解析完成后会被清除
|
||||
* @returns
|
||||
*/
|
||||
async (str: string, localVariables?: VariableOption | VariableOption[]) => {
|
||||
async (
|
||||
str: string,
|
||||
localVariables?: VariableOption | VariableOption[],
|
||||
options?: {
|
||||
/** 第一次请求时,需要包含的关系字段 */
|
||||
appends?: string[];
|
||||
},
|
||||
) => {
|
||||
if (!isVariable(str)) {
|
||||
return str;
|
||||
}
|
||||
@ -190,7 +210,7 @@ const VariablesProvider = ({ children }) => {
|
||||
}
|
||||
|
||||
const path = getPath(str);
|
||||
const value = await getValue(path, localVariables as VariableOption[]);
|
||||
const value = await getValue(path, localVariables as VariableOption[], options);
|
||||
|
||||
return uniq(filterEmptyValues(value));
|
||||
},
|
||||
|
@ -29,7 +29,14 @@ export interface VariablesContextType {
|
||||
* console.log(value); // test
|
||||
* ```
|
||||
*/
|
||||
parseVariable: (str: string, localVariable?: VariableOption | VariableOption[]) => Promise<any>;
|
||||
parseVariable: (
|
||||
str: string,
|
||||
localVariable?: VariableOption | VariableOption[],
|
||||
options?: {
|
||||
/** 第一次请求时,需要包含的关系字段 */
|
||||
appends?: string[];
|
||||
},
|
||||
) => Promise<any>;
|
||||
/**
|
||||
* 注册变量
|
||||
* @param variableOption 新变量的配置
|
||||
|
@ -34,6 +34,10 @@ Object.defineProperty(window, 'matchMedia', {
|
||||
const { getComputedStyle } = window;
|
||||
window.getComputedStyle = (elt) => getComputedStyle(elt);
|
||||
|
||||
// 解决 https://github.com/nocobase/nocobase/actions/runs/7353181446/job/20018831007?pr=3282
|
||||
// 该错误是发生在测试环境之后的,应该是存在异步代码没有 await 导致的,但是不知道是哪里的问题,所以先这样处理
|
||||
global.window = window;
|
||||
|
||||
/**
|
||||
* 解决 TypeError: range.getBoundingClientRect is not a function
|
||||
* 参见:https://github.com/jsdom/jsdom/issues/3002
|
||||
|
@ -71,6 +71,7 @@ test.describe('form item & create form', () => {
|
||||
});
|
||||
|
||||
test('pattern', async ({ page, mockPage }) => {
|
||||
test.slow();
|
||||
await testPattern({
|
||||
page,
|
||||
gotoPage: () =>
|
||||
|
@ -1,4 +1,3 @@
|
||||
import React, { useRef, useMemo, useContext } from 'react';
|
||||
import { createForm } from '@formily/core';
|
||||
import { useField } from '@formily/react';
|
||||
import {
|
||||
@ -9,8 +8,9 @@ import {
|
||||
useAPIClient,
|
||||
useAssociationNames,
|
||||
} from '@nocobase/client';
|
||||
import { parse } from '@nocobase/utils/client';
|
||||
import { useFlowContext } from '@nocobase/plugin-workflow/client';
|
||||
import { parse } from '@nocobase/utils/client';
|
||||
import React, { useContext, useMemo, useRef } from 'react';
|
||||
|
||||
function useFlowContextData(dataSource) {
|
||||
const { execution, nodes } = useFlowContext();
|
||||
@ -37,7 +37,8 @@ function useFlowContextData(dataSource) {
|
||||
export function DetailsBlockProvider(props) {
|
||||
const field = useField();
|
||||
const formBlockRef = useRef(null);
|
||||
const { appends, updateAssociationValues } = useAssociationNames();
|
||||
const { getAssociationAppends } = useAssociationNames();
|
||||
const { appends, updateAssociationValues } = getAssociationAppends();
|
||||
const values = useFlowContextData(props.dataSource);
|
||||
|
||||
const form = useMemo(
|
||||
|
@ -19,7 +19,8 @@ export function FormBlockProvider(props) {
|
||||
const fieldSchema = useFieldSchema();
|
||||
const field = useField();
|
||||
const formBlockRef = useRef(null);
|
||||
const { appends, updateAssociationValues } = useAssociationNames();
|
||||
const { getAssociationAppends } = useAssociationNames();
|
||||
const { appends, updateAssociationValues } = getAssociationAppends();
|
||||
const [formKey] = Object.keys(fieldSchema.toJSON().properties ?? {});
|
||||
const values = userJob?.result?.[formKey];
|
||||
|
||||
|
@ -4215,6 +4215,11 @@
|
||||
dependencies:
|
||||
eslint-scope "5.1.1"
|
||||
|
||||
"@nocobase/plugin-workflow-test@>=0.17.0-alpha.3":
|
||||
version "0.17.0-alpha.7"
|
||||
resolved "https://registry.yarnpkg.com/@nocobase/plugin-workflow-test/-/plugin-workflow-test-0.17.0-alpha.7.tgz#219a3a1e91e51bec08b1adbb1c4c5c9c7184ecce"
|
||||
integrity sha512-krZlo1xDM66spbQG6jAYSraxazuxCuA2rD9TxptFQXjkAMTGkuDilJ+edMj6p866N3nyzvFh8lZ2/XY1HUC7Xw==
|
||||
|
||||
"@node-saml/node-saml@^4.0.2":
|
||||
version "4.0.5"
|
||||
resolved "https://registry.npmmirror.com/@node-saml/node-saml/-/node-saml-4.0.5.tgz#039e387095b54639b06df62b1b4a6d8941c6d907"
|
||||
|
Loading…
Reference in New Issue
Block a user