refactor(sub-table): sub-table support selection of existing records (#3311)
* refactor: sub-table support selection of existing records * refactor: local improve * refactor: sub-table support select existing records * refactor: create action support updateAssociationValues * refactor: sub-table * fix: omit foreignKey * refactor: record picker omit foreignKey * test: manyToMany * test: subform: basic fields * test: table column & sub-table in edit form
This commit is contained in:
parent
dc71a77d8c
commit
6fb5af993e
@ -268,10 +268,17 @@ export const useTableSelectorContext = () => {
|
|||||||
export const useTableSelectorProps = () => {
|
export const useTableSelectorProps = () => {
|
||||||
const field = useField<ArrayField>();
|
const field = useField<ArrayField>();
|
||||||
const ctx = useTableSelectorContext();
|
const ctx = useTableSelectorContext();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { getCollectionJoinField } = useCollectionManager();
|
||||||
|
const collectionFieldSchema = recursiveParent(fieldSchema, 'CollectionField');
|
||||||
|
const collectionField = getCollectionJoinField(collectionFieldSchema?.['x-collection-field']);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ctx?.service?.loading) {
|
if (!ctx?.service?.loading) {
|
||||||
field.value = ctx?.service?.data?.data;
|
const data = ctx?.service?.data?.data.map((v) => {
|
||||||
field?.setInitialValue?.(ctx?.service?.data?.data);
|
return _.omit(v, collectionField?.foreignKey);
|
||||||
|
});
|
||||||
|
field.value = data;
|
||||||
|
field?.setInitialValue?.(data);
|
||||||
field.data = field.data || {};
|
field.data = field.data || {};
|
||||||
field.data.selectedRowKeys = ctx?.field?.data?.selectedRowKeys;
|
field.data.selectedRowKeys = ctx?.field?.data?.selectedRowKeys;
|
||||||
field.componentProps.pagination = field.componentProps.pagination || {};
|
field.componentProps.pagination = field.componentProps.pagination || {};
|
||||||
|
@ -184,6 +184,7 @@ export const useCreateActionProps = () => {
|
|||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
const { modal } = App.useApp();
|
const { modal } = App.useApp();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { updateAssociationValues } = useFormBlockContext();
|
||||||
const collectValues = useCollectValuesToSubmit();
|
const collectValues = useCollectValuesToSubmit();
|
||||||
const action = actionField.componentProps.saveMode || 'create';
|
const action = actionField.componentProps.saveMode || 'create';
|
||||||
const filterKeys = actionField.componentProps.filterKeys?.checked || [];
|
const filterKeys = actionField.componentProps.filterKeys?.checked || [];
|
||||||
@ -205,6 +206,7 @@ export const useCreateActionProps = () => {
|
|||||||
triggerWorkflows: triggerWorkflows?.length
|
triggerWorkflows: triggerWorkflows?.length
|
||||||
? triggerWorkflows.map((row) => [row.workflowKey, row.context].filter(Boolean).join('!')).join(',')
|
? triggerWorkflows.map((row) => [row.workflowKey, row.context].filter(Boolean).join('!')).join(',')
|
||||||
: undefined,
|
: undefined,
|
||||||
|
updateAssociationValues,
|
||||||
});
|
});
|
||||||
setVisible?.(false);
|
setVisible?.(false);
|
||||||
actionField.data.loading = false;
|
actionField.data.loading = false;
|
||||||
|
@ -749,5 +749,7 @@
|
|||||||
"Current form": "Formulaire actuel",
|
"Current form": "Formulaire actuel",
|
||||||
"Current object": "Objet actuel",
|
"Current object": "Objet actuel",
|
||||||
"Linkage with form fields": "Lien avec les champs de formulaire",
|
"Linkage with form fields": "Lien avec les champs de formulaire",
|
||||||
"Allow add new, update and delete actions": "Autoriser les actions d'ajout, de mise à jour et de suppression"
|
"Allow add new, update and delete actions": "Autoriser les actions d'ajout, de mise à jour et de suppression",
|
||||||
|
"Allow add new":"Autoriser les ajouts",
|
||||||
|
"Allow selection of existing records":"Permet de sélectionner des données existantes"
|
||||||
}
|
}
|
||||||
|
@ -666,5 +666,7 @@
|
|||||||
"Search plugin": "プラグインを検索",
|
"Search plugin": "プラグインを検索",
|
||||||
"Author": "著者",
|
"Author": "著者",
|
||||||
"Plugin loading failed. Please check the server logs.": "プラグインのロードに失敗しました。サーバーログを確認してください。",
|
"Plugin loading failed. Please check the server logs.": "プラグインのロードに失敗しました。サーバーログを確認してください。",
|
||||||
"Automatically drop objects that depend on the collection (such as views), and in turn all objects that depend on those objects": "テーブルに依存するオブジェクト、およびそれらに依存するオブジェクトを自動的に削除する"
|
"Automatically drop objects that depend on the collection (such as views), and in turn all objects that depend on those objects": "テーブルに依存するオブジェクト、およびそれらに依存するオブジェクトを自動的に削除する",
|
||||||
|
"Allow add new":"新規作成を許可",
|
||||||
|
"Allow selection of existing records":"既存のデータの選択を許可"
|
||||||
}
|
}
|
||||||
|
@ -708,5 +708,7 @@
|
|||||||
"Data template": "Modelo de dados",
|
"Data template": "Modelo de dados",
|
||||||
"Not found": "Não encontrado",
|
"Not found": "Não encontrado",
|
||||||
"Add": "Adicionar",
|
"Add": "Adicionar",
|
||||||
"Automatically drop objects that depend on the collection (such as views), and in turn all objects that depend on those objects": "Excluir automaticamente objetos que dependem desta tabela, bem como objetos que dependem desses objetos"
|
"Automatically drop objects that depend on the collection (such as views), and in turn all objects that depend on those objects": "Excluir automaticamente objetos que dependem desta tabela, bem como objetos que dependem desses objetos",
|
||||||
|
"Allow add new":"Permitir novas adições",
|
||||||
|
"Allow selection of existing records":"Permitir a selecção dos registos existentes"
|
||||||
}
|
}
|
||||||
|
@ -839,5 +839,7 @@
|
|||||||
"Are you sure you want to perform the {{title}} action?": "你确定执行{{title}}操作吗?",
|
"Are you sure you want to perform the {{title}} action?": "你确定执行{{title}}操作吗?",
|
||||||
"Sign in with another account": "登录其他账号",
|
"Sign in with another account": "登录其他账号",
|
||||||
"Return to the main application": "返回主应用",
|
"Return to the main application": "返回主应用",
|
||||||
"Permission denied": "没有权限"
|
"Permission denied": "没有权限",
|
||||||
|
"Allow add new":"允许新增",
|
||||||
|
"Allow selection of existing records":"允许选择已有数据"
|
||||||
}
|
}
|
||||||
|
@ -597,7 +597,10 @@ test.describe('creation form block schema settings', () => {
|
|||||||
await page.mouse.move(300, 0);
|
await page.mouse.move(300, 0);
|
||||||
|
|
||||||
// 当新增一行时,应该显示默认值
|
// 当新增一行时,应该显示默认值
|
||||||
await page.getByRole('button', { name: 'plus' }).click();
|
await page
|
||||||
|
.getByTestId('drawer-Action.Container-general-Add record')
|
||||||
|
.getByRole('button', { name: 'Add new' })
|
||||||
|
.click();
|
||||||
await expect(
|
await expect(
|
||||||
page
|
page
|
||||||
.getByRole('cell', { name: 'block-item-CollectionField-users-form-users.nickname-Nickname' })
|
.getByRole('cell', { name: 'block-item-CollectionField-users-form-users.nickname-Nickname' })
|
||||||
|
@ -21,7 +21,7 @@ import { useAssociationFieldContext, useFieldNames, useInsertSchema } from './ho
|
|||||||
import schema from './schema';
|
import schema from './schema';
|
||||||
import { flatData, getLabelFormatValue, useLabelUiSchema } from './util';
|
import { flatData, getLabelFormatValue, useLabelUiSchema } from './util';
|
||||||
|
|
||||||
const useTableSelectorProps = () => {
|
export const useTableSelectorProps = () => {
|
||||||
const field: any = useField();
|
const field: any = useField();
|
||||||
const {
|
const {
|
||||||
multiple,
|
multiple,
|
||||||
|
@ -14,13 +14,18 @@ export const InternalSubTable = observer(
|
|||||||
const field: any = useField();
|
const field: any = useField();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const insert = useInsertSchema('SubTable');
|
const insert = useInsertSchema('SubTable');
|
||||||
|
const insertSelector = useInsertSchema('Selector');
|
||||||
const { options } = useAssociationFieldContext();
|
const { options } = useAssociationFieldContext();
|
||||||
const { actionName } = useACLActionParamsContext();
|
const { actionName } = useACLActionParamsContext();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
insert(schema.SubTable);
|
insert(schema.SubTable);
|
||||||
field.required = fieldSchema['required'];
|
field.required = fieldSchema['required'];
|
||||||
}, []);
|
}, []);
|
||||||
|
useEffect(() => {
|
||||||
|
if (field.componentProps?.allowSelectExistingRecord) {
|
||||||
|
insertSelector(schema.Selector);
|
||||||
|
}
|
||||||
|
}, [field.componentProps?.allowSelectExistingRecord]);
|
||||||
const option = useSchemaOptionsContext();
|
const option = useSchemaOptionsContext();
|
||||||
const components = {
|
const components = {
|
||||||
...option.components,
|
...option.components,
|
||||||
|
@ -1,21 +1,44 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons';
|
|
||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { ArrayField } from '@formily/core';
|
import { ArrayField } from '@formily/core';
|
||||||
import { exchangeArrayState } from '@formily/core/esm/shared/internals';
|
import { exchangeArrayState } from '@formily/core/esm/shared/internals';
|
||||||
import { observer } from '@formily/react';
|
import { observer, RecursionField, useFieldSchema } from '@formily/react';
|
||||||
import { action } from '@formily/reactive';
|
import { action } from '@formily/reactive';
|
||||||
import { isArr } from '@formily/shared';
|
import { isArr } from '@formily/shared';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import React from 'react';
|
import { omit, unionBy, uniqBy } from 'lodash';
|
||||||
|
import React, { useState, useMemo, useContext } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { FormActiveFieldsProvider } from '../../../block-provider';
|
import { FormActiveFieldsProvider } from '../../../block-provider';
|
||||||
import { FlagProvider } from '../../../flag-provider';
|
import { FlagProvider } from '../../../flag-provider';
|
||||||
import { Table } from '../table-v2/Table';
|
import { Table } from '../table-v2/Table';
|
||||||
import { useAssociationFieldContext } from './hooks';
|
import { useAssociationFieldContext, useFieldNames } from './hooks';
|
||||||
|
import { ActionContextProvider } from '../action';
|
||||||
|
import {
|
||||||
|
FormProvider,
|
||||||
|
RecordPickerProvider,
|
||||||
|
SchemaComponentOptions,
|
||||||
|
useActionContext,
|
||||||
|
RecordPickerContext,
|
||||||
|
} from '../..';
|
||||||
|
import { getLabelFormatValue, useLabelUiSchema } from './util';
|
||||||
|
import { CollectionProvider } from '../../../collection-manager';
|
||||||
|
import { TableSelectorParamsProvider } from '../../../block-provider/TableSelectorProvider';
|
||||||
|
import { useCompile } from '../../hooks';
|
||||||
|
import { useTableSelectorProps } from './InternalPicker';
|
||||||
|
import { useCreateActionProps } from '../../../block-provider/hooks';
|
||||||
|
|
||||||
export const SubTable: any = observer(
|
export const SubTable: any = observer(
|
||||||
(props: any) => {
|
(props: any) => {
|
||||||
const { field } = useAssociationFieldContext<ArrayField>();
|
const { openSize } = props;
|
||||||
// useSubTableSpecialCase({ field });
|
const { field, options: collectionField } = useAssociationFieldContext<ArrayField>();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [visibleSelector, setVisibleSelector] = useState(false);
|
||||||
|
const [selectedRows, setSelectedRows] = useState([]);
|
||||||
|
const fieldNames = useFieldNames(props);
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const compile = useCompile();
|
||||||
|
const labelUiSchema = useLabelUiSchema(collectionField, fieldNames?.label || 'label');
|
||||||
|
|
||||||
const move = (fromIndex: number, toIndex: number) => {
|
const move = (fromIndex: number, toIndex: number) => {
|
||||||
if (toIndex === undefined) return;
|
if (toIndex === undefined) return;
|
||||||
if (!isArr(field.value)) return;
|
if (!isArr(field.value)) return;
|
||||||
@ -32,6 +55,55 @@ export const SubTable: any = observer(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
field.move = move;
|
field.move = move;
|
||||||
|
|
||||||
|
const options = useMemo(() => {
|
||||||
|
if (field.value && Object.keys(field.value).length > 0) {
|
||||||
|
const opts = (Array.isArray(field.value) ? field.value : field.value ? [field.value] : [])
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((option) => {
|
||||||
|
const label = option?.[fieldNames.label];
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
[fieldNames.label]: getLabelFormatValue(compile(labelUiSchema), compile(label)),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}, [field.value, fieldNames?.label]);
|
||||||
|
|
||||||
|
const pickerProps = {
|
||||||
|
size: 'small',
|
||||||
|
fieldNames: field.componentProps.fieldNames,
|
||||||
|
multiple: true,
|
||||||
|
association: {
|
||||||
|
target: collectionField?.target,
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
onChange: props?.onChange,
|
||||||
|
selectedRows,
|
||||||
|
setSelectedRows,
|
||||||
|
collectionField,
|
||||||
|
};
|
||||||
|
const usePickActionProps = () => {
|
||||||
|
const { setVisible } = useActionContext();
|
||||||
|
const { selectedRows, options, collectionField } = useContext(RecordPickerContext);
|
||||||
|
return {
|
||||||
|
onClick() {
|
||||||
|
const selectData = unionBy(selectedRows, options, collectionField?.targetKey || 'id');
|
||||||
|
const data = field.value || [];
|
||||||
|
field.value = uniqBy(data.concat(selectData), collectionField?.targetKey || 'id');
|
||||||
|
field.onInput(field.value);
|
||||||
|
setVisible(false);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const getFilter = () => {
|
||||||
|
const targetKey = collectionField?.targetKey || 'id';
|
||||||
|
const list = options.map((option) => option[targetKey]).filter(Boolean);
|
||||||
|
const filter = list.length ? { $and: [{ [`${targetKey}.$ne`]: list }] } : {};
|
||||||
|
return filter;
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={css`
|
className={css`
|
||||||
@ -72,6 +144,9 @@ export const SubTable: any = observer(
|
|||||||
.ant-formily-editable {
|
.ant-formily-editable {
|
||||||
vertical-align: sub;
|
vertical-align: sub;
|
||||||
}
|
}
|
||||||
|
.ant-table-footer {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
`}
|
`}
|
||||||
bordered
|
bordered
|
||||||
size={'small'}
|
size={'small'}
|
||||||
@ -83,27 +158,80 @@ export const SubTable: any = observer(
|
|||||||
rowSelection={{ type: 'none', hideSelectAll: true }}
|
rowSelection={{ type: 'none', hideSelectAll: true }}
|
||||||
footer={() =>
|
footer={() =>
|
||||||
field.editable && (
|
field.editable && (
|
||||||
<Button
|
<>
|
||||||
type={'text'}
|
{field.componentProps?.allowAddnew !== false && (
|
||||||
block
|
<Button
|
||||||
className={css`
|
type={'text'}
|
||||||
display: block;
|
block
|
||||||
`}
|
className={css`
|
||||||
onClick={() => {
|
display: block;
|
||||||
field.value = field.value || [];
|
border-radius: 0px;
|
||||||
field.value.push({});
|
border-right: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
field.onInput(field.value);
|
`}
|
||||||
}}
|
onClick={() => {
|
||||||
icon={<PlusOutlined />}
|
field.value = field.value || [];
|
||||||
>
|
field.value.push({});
|
||||||
{/* {t('Add new')} */}
|
field.onInput(field.value);
|
||||||
</Button>
|
}}
|
||||||
|
>
|
||||||
|
{t('Add new')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{field.componentProps?.allowSelectExistingRecord && (
|
||||||
|
<Button
|
||||||
|
type={'text'}
|
||||||
|
block
|
||||||
|
className={css`
|
||||||
|
display: block;
|
||||||
|
border-radius: 0px;
|
||||||
|
`}
|
||||||
|
onClick={() => {
|
||||||
|
setVisibleSelector(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('Select')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
isSubTable={true}
|
isSubTable={true}
|
||||||
/>
|
/>
|
||||||
</FormActiveFieldsProvider>
|
</FormActiveFieldsProvider>
|
||||||
</FlagProvider>
|
</FlagProvider>
|
||||||
|
<ActionContextProvider
|
||||||
|
value={{
|
||||||
|
openSize,
|
||||||
|
openMode: 'drawer',
|
||||||
|
visible: visibleSelector,
|
||||||
|
setVisible: setVisibleSelector,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RecordPickerProvider {...pickerProps}>
|
||||||
|
<CollectionProvider name={collectionField?.target}>
|
||||||
|
<FormProvider>
|
||||||
|
<TableSelectorParamsProvider params={{ filter: getFilter() }}>
|
||||||
|
<SchemaComponentOptions
|
||||||
|
scope={{
|
||||||
|
usePickActionProps,
|
||||||
|
useTableSelectorProps,
|
||||||
|
useCreateActionProps,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RecursionField
|
||||||
|
onlyRenderProperties
|
||||||
|
basePath={field.address}
|
||||||
|
schema={fieldSchema.parent}
|
||||||
|
filterProperties={(s) => {
|
||||||
|
return s['x-component'] === 'AssociationField.Selector';
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SchemaComponentOptions>
|
||||||
|
</TableSelectorParamsProvider>
|
||||||
|
</FormProvider>
|
||||||
|
</CollectionProvider>
|
||||||
|
</RecordPickerProvider>
|
||||||
|
</ActionContextProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -32,6 +32,72 @@ export const formItemSettings = new SchemaSettings({
|
|||||||
name: 'FormItemSettings',
|
name: 'FormItemSettings',
|
||||||
items: [
|
items: [
|
||||||
...(generalSettingsItems as any),
|
...(generalSettingsItems as any),
|
||||||
|
{
|
||||||
|
name: 'allowAddNewData',
|
||||||
|
type: 'switch',
|
||||||
|
useVisible() {
|
||||||
|
const readPretty = useIsFieldReadPretty();
|
||||||
|
const isAssociationField = useIsAssociationField();
|
||||||
|
const fieldMode = useFieldMode();
|
||||||
|
return !readPretty && isAssociationField && ['SubTable'].includes(fieldMode);
|
||||||
|
},
|
||||||
|
useComponentProps() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const field = useField<Field>();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { dn, refresh } = useDesignable();
|
||||||
|
return {
|
||||||
|
title: t('Allow add new'),
|
||||||
|
checked: fieldSchema['x-component-props']?.allowAddnew !== (false as boolean),
|
||||||
|
onChange(value) {
|
||||||
|
const schema = {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
};
|
||||||
|
field.componentProps.allowAddnew = value;
|
||||||
|
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
|
||||||
|
fieldSchema['x-component-props'].allowAddnew = value;
|
||||||
|
schema['x-component-props'] = fieldSchema['x-component-props'];
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema,
|
||||||
|
});
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'allowSelectExistingRecord',
|
||||||
|
type: 'switch',
|
||||||
|
useVisible() {
|
||||||
|
const readPretty = useIsFieldReadPretty();
|
||||||
|
const isAssociationField = useIsAssociationField();
|
||||||
|
const fieldMode = useFieldMode();
|
||||||
|
return !readPretty && isAssociationField && ['SubTable'].includes(fieldMode);
|
||||||
|
},
|
||||||
|
useComponentProps() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const field = useField<Field>();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { dn, refresh } = useDesignable();
|
||||||
|
return {
|
||||||
|
title: t('Allow selection of existing records'),
|
||||||
|
checked: fieldSchema['x-component-props']?.allowSelectExistingRecord,
|
||||||
|
onChange(value) {
|
||||||
|
const schema = {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
};
|
||||||
|
field.componentProps.allowSelectExistingRecord = value;
|
||||||
|
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
|
||||||
|
fieldSchema['x-component-props'].allowSelectExistingRecord = value;
|
||||||
|
schema['x-component-props'] = fieldSchema['x-component-props'];
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema,
|
||||||
|
});
|
||||||
|
refresh();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'quickUpload',
|
name: 'quickUpload',
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
|
@ -266,9 +266,9 @@ test.describe('form item & create form', () => {
|
|||||||
// 选择 Sub-form
|
// 选择 Sub-form
|
||||||
await (async (page: Page, fieldName: string) => {
|
await (async (page: Page, fieldName: string) => {
|
||||||
await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover();
|
await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover();
|
||||||
await page
|
// await page
|
||||||
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`)
|
// .getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`)
|
||||||
.hover();
|
// .hover();
|
||||||
})(page, 'manyToMany');
|
})(page, 'manyToMany');
|
||||||
await page.getByRole('menuitem', { name: 'Field component' }).click();
|
await page.getByRole('menuitem', { name: 'Field component' }).click();
|
||||||
await page.getByRole('option', { name: 'Sub-form', exact: true }).click();
|
await page.getByRole('option', { name: 'Sub-form', exact: true }).click();
|
||||||
|
@ -419,7 +419,7 @@ test.describe('table column & sub-table in edit form', () => {
|
|||||||
],
|
],
|
||||||
variableValue: ['Current user', 'Nickname'],
|
variableValue: ['Current user', 'Nickname'],
|
||||||
expectVariableValue: async () => {
|
expectVariableValue: async () => {
|
||||||
await page.getByRole('button', { name: 'plus' }).click();
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
await expect(
|
await expect(
|
||||||
page
|
page
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText')
|
.getByLabel('block-item-CollectionField-general-form-general.singleLineText-singleLineText')
|
||||||
|
Loading…
Reference in New Issue
Block a user