Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(client): support linkage style in table and form #4467

Merged
merged 16 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useCreateFormBlockDecoratorProps } from '../modules/blocks/data-blocks/
import { useCreateFormBlockProps } from '../modules/blocks/data-blocks/form/hooks/useCreateFormBlockProps';
import { useEditFormBlockDecoratorProps } from '../modules/blocks/data-blocks/form/hooks/useEditFormBlockDecoratorProps';
import { useEditFormBlockProps } from '../modules/blocks/data-blocks/form/hooks/useEditFormBlockProps';
import { useDataFormItemProps } from '../modules/blocks/data-blocks/form/hooks/useDataFormItemProps';
import { useGridCardBlockDecoratorProps } from '../modules/blocks/data-blocks/grid-card/hooks/useGridCardBlockDecoratorProps';
import { useListBlockDecoratorProps } from '../modules/blocks/data-blocks/list/hooks/useListBlockDecoratorProps';
import { useTableSelectorDecoratorProps } from '../modules/blocks/data-blocks/table-selector/hooks/useTableSelectorDecoratorProps';
Expand Down Expand Up @@ -85,6 +86,7 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
useFilterFormBlockDecoratorProps,
useGridCardBlockDecoratorProps,
useFormItemProps,
useDataFormItemProps,
}}
>
{props.children}
Expand Down Expand Up @@ -145,6 +147,7 @@ export class BlockSchemaComponentPlugin extends Plugin {
useFilterFormBlockDecoratorProps,
useGridCardBlockDecoratorProps,
useFormItemProps,
useDataFormItemProps,
});
}
}
1 change: 0 additions & 1 deletion packages/core/client/src/block-provider/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1490,7 +1490,6 @@ export function useLinkActionProps() {
};
}


export async function replaceVariableValue(
url: string,
variables: VariablesContextType,
Expand Down
2 changes: 2 additions & 0 deletions packages/core/client/src/locale/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@
"Option value": "Option value",
"Option label": "Option label",
"Color": "Color",
"Background Color": "Background Color",
"Add option": "Add option",
"Related collection": "Related collection",
"Allow linking to multiple records": "Allow linking to multiple records",
Expand Down Expand Up @@ -552,6 +553,7 @@
"Add condition group": "Add condition group",
"exists": "exists",
"not exists": "not exists",
"Style": "Style",
"=": "=",
"≠": "≠",
">": ">",
Expand Down
1 change: 1 addition & 0 deletions packages/core/client/src/locale/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@
"Option value": "选项值",
"Option label": "选项标签",
"Color": "颜色",
"Background Color": "背景颜色",
"Add option": "添加选项",
"Related collection": "关系表",
"Allow linking to multiple records": "允许关联多条记录",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* 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, commonFormViewPage, test } from '@nocobase/test/e2e';

test.describe('field schema settings', () => {
test('linkage style color', async ({ page, mockPage, mockRecord }) => {
const nocoPage = await mockPage(commonFormViewPage).waitForInit();
await mockRecord('general', { singleLineText: 'asdfcedg' });
await nocoPage.goto();
await page.getByText('asdfcedg', { exact: true }).hover();
await page.getByLabel('block-item-CollectionField-general-details-general.singleLineText-singleLineText').hover();

await page
.getByLabel('designer-schema-settings-CollectionField-fieldSettings:FormItem-general-general.singleLineText', {
exact: true,
})
.click();
await page.getByRole('menuitem', { name: 'Style' }).click();
await page.getByRole('button', { name: 'plus Add linkage rule' }).click();
await page.getByText('Add property').click();
await page.getByTestId('select-linkage-properties').click();
await page.getByText('Color', { exact: true }).click();
await page.getByLabel('color-picker-normal').click();
await page.locator('input[type="text"]').fill('A34FCC');
await page.getByRole('button', { name: 'OK' }).click();
const cell = await page
.getByLabel('block-item-CollectionField-general-details-general.singleLineText-singleLineText')
.locator('div.ant-formily-item');
await expect(cell).toHaveCSS('color', 'rgb(163, 79, 204)');
});
test('linkage style background color', async ({ page, mockPage, mockRecord }) => {
const nocoPage = await mockPage(commonFormViewPage).waitForInit();
await mockRecord('general', { singleLineText: 'asdfcedg' });
await nocoPage.goto();
await page.getByText('asdfcedg', { exact: true }).hover();
await page.getByLabel('block-item-CollectionField-general-details-general.singleLineText-singleLineText').hover();

await page
.getByLabel('designer-schema-settings-CollectionField-fieldSettings:FormItem-general-general.singleLineText', {
exact: true,
})
.click();
await page.getByRole('menuitem', { name: 'Style' }).click();
await page.getByRole('button', { name: 'plus Add linkage rule' }).click();
await page.getByText('Add property').click();
await page.getByTestId('select-linkage-properties').click();
await page.getByText('Background Color', { exact: true }).click();
await page.getByLabel('color-picker-normal').click();
await page.locator('input[type="text"]').fill('A34FCC');
await page.getByRole('button', { name: 'OK' }).click();
const cell = await page
.getByLabel('block-item-CollectionField-general-details-general.singleLineText-singleLineText')
.locator('div.ant-formily-item');
await expect(cell).toHaveCSS('background-color', 'rgb(163, 79, 204)');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ describe('FieldSettingsFormItem', () => {
title: 'Pattern',
type: 'select',
},
{
title: 'Style',
type: 'modal',
},
{
title: 'Set validation rules',
type: 'modal',
Expand Down Expand Up @@ -284,6 +288,10 @@ describe('FieldSettingsFormItem', () => {
title: 'Pattern',
type: 'select',
},
{
title: 'Style',
type: 'modal',
},
{
title: 'Field component',
type: 'select',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* 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 React from 'react';
import { ArrayCollapse, FormLayout } from '@formily/antd-v5';
import { Field } from '@formily/core';
import { ISchema, useField, useFieldSchema } from '@formily/react';
Expand All @@ -16,6 +16,7 @@ import { useApp, useSchemaToolbar } from '../../../../application';
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
import { useFormBlockContext } from '../../../../block-provider/FormBlockProvider';
import { useCollectionManager_deprecated, useCollection_deprecated } from '../../../../collection-manager';
import { useCollection } from '../../../../data-source';
import { useFieldComponentName } from '../../../../common/useFieldComponentName';
import { useDesignable, useValidateSchema } from '../../../../schema-component';
import { useIsFormReadPretty } from '../../../../schema-component/antd/form-item/FormItem.Settings';
Expand All @@ -24,6 +25,7 @@ import { isPatternDisabled } from '../../../../schema-settings';
import { ActionType } from '../../../../schema-settings/LinkageRules/type';
import { SchemaSettingsDefaultValue } from '../../../../schema-settings/SchemaSettingsDefaultValue';
import { useIsAllowToSetDefaultValue } from '../../../../schema-settings/hooks/useIsAllowToSetDefaultValue';
import { SchemaSettingsLinkageRules } from '../../../../schema-settings';

export const fieldSettingsFormItem = new SchemaSettings({
name: 'fieldSettings:FormItem',
Expand Down Expand Up @@ -442,6 +444,25 @@ export const fieldSettingsFormItem = new SchemaSettings({
return form && !isFormReadPretty && validateSchema;
},
},
{
name: 'style',
Component: (props) => {
const localProps = { ...props, category: 'style' };
return <SchemaSettingsLinkageRules {...localProps} />;
},
useVisible() {
const field: any = useField();
return field.readPretty;
},
useComponentProps() {
const { name } = useCollection();
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: name,
};
},
},
];
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* 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 { useForm } from '@formily/react';
import { useSatisfiedActionValues } from '../../../../../schema-settings/LinkageRules/useActionValues';
export function useDataFormItemProps() {
const form = useForm();
const { valueMap: style } = useSatisfiedActionValues({ category: 'style', formValues: form?.values });
return { style };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* 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, oneTableBlockWithIntegerAndIDColumn, test } from '@nocobase/test/e2e';

test.describe('view', () => {
test('linkage style color', async ({ page, mockPage, mockRecord }) => {
const nocoPage = await mockPage(oneTableBlockWithIntegerAndIDColumn).waitForInit();
await mockRecord('general', { integer: '423' });
await nocoPage.goto();

await page.getByText('integer', { exact: true }).hover();
await page
.getByRole('button', {
name: 'designer-schema-settings-TableV2.Column-fieldSettings:TableColumn-general',
})
.click();
await page.getByRole('menuitem', { name: 'Style' }).click();
await page.getByRole('button', { name: 'plus Add linkage rule' }).click();
await page.getByText('Add property').click();
await page.getByTestId('select-linkage-properties').click();
await page.getByText('Color', { exact: true }).click();
await page.getByLabel('color-picker-normal').click();
await page.locator('input[type="text"]').fill('A34FCC');
await page.getByRole('button', { name: 'OK' }).click();
const cell = page.getByRole('button', { name: '423' });
const color = await cell.evaluate((el) => getComputedStyle(el).color);
expect(color).toContain('163, 79, 204');
});

test('linkage style background color', async ({ page, mockPage, mockRecord }) => {
const nocoPage = await mockPage(oneTableBlockWithIntegerAndIDColumn).waitForInit();
await mockRecord('general', { integer: '423' });
await nocoPage.goto();
await page.getByText('integer', { exact: true }).hover();

await page
.getByRole('button', {
name: 'designer-schema-settings-TableV2.Column-fieldSettings:TableColumn-general',
})
.click();
await page.getByRole('menuitem', { name: 'Style' }).click();
await page.getByRole('button', { name: 'plus Add linkage rule' }).click();
await page.getByText('Add property').click();
await page.getByTestId('select-linkage-properties').click();
await page.getByText('Background Color', { exact: true }).click();
await page.getByLabel('color-picker-normal').click();
await page.locator('input[type="text"]').fill('A34FCC');
await page.getByRole('button', { name: 'OK' }).click();
const cell = page.getByRole('button', { name: '423' });
const bgColor = await cell.evaluate((el) => getComputedStyle(el.parentElement).backgroundColor);
expect(bgColor).toContain('163, 79, 204');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/

import React from 'react';
import { ISchema } from '@formily/json-schema';
import { useField, useFieldSchema } from '@formily/react';
import { useTranslation } from 'react-i18next';
import { useApp } from '../../../../application';
import { useApp, useSchemaToolbar } from '../../../../application';
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
import { useCollectionManager_deprecated } from '../../../../collection-manager';
import { useFieldComponentName } from '../../../../common/useFieldComponentName';
Expand All @@ -20,6 +21,7 @@ import { useAssociationFieldContext } from '../../../../schema-component/antd/as
import { useColumnSchema } from '../../../../schema-component/antd/table-v2/Table.Column.Decorator';
import { SchemaSettingsDefaultValue } from '../../../../schema-settings/SchemaSettingsDefaultValue';
import { isPatternDisabled } from '../../../../schema-settings/isPatternDisabled';
import { SchemaSettingsLinkageRules } from '../../../../schema-settings';

export const tableColumnSettings = new SchemaSettings({
name: 'fieldSettings:TableColumn',
Expand All @@ -44,7 +46,6 @@ export const tableColumnSettings = new SchemaSettings({
const { t } = useTranslation();
const columnSchema = useFieldSchema();
const { dn } = useDesignable();

return {
title: t('Custom column title'),
schema: {
Expand Down Expand Up @@ -79,6 +80,30 @@ export const tableColumnSettings = new SchemaSettings({
};
},
},
{
name: 'style',
Component: (props) => {
const localProps = { ...props, category: 'style' };
return <SchemaSettingsLinkageRules {...localProps} />;
},
useVisible() {
const { fieldSchema } = useColumnSchema();
const field: any = useField();
const path = field.path?.splice(field.path?.length - 1, 1);
if (fieldSchema) {
const isReadPretty = field.form.query(`${path.concat(`*.` + fieldSchema.name)}`).get('readPretty');
return isReadPretty;
} else return false;
},
useComponentProps() {
const { name } = useCollection();
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: name,
};
},
},
{
name: 'columnWidth',
type: 'modal',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import { css, cx } from '@emotion/css';
import { IFormItemProps, FormItem as Item } from '@formily/antd-v5';
import { Field } from '@formily/core';
import { observer, useField, useFieldSchema } from '@formily/react';
import { observer, useField, useFieldSchema, useForm } from '@formily/react';
import React, { useEffect, useMemo } from 'react';
import { ACLCollectionFieldProvider } from '../../../acl/ACLProvider';
import { useApp } from '../../../application';
Expand All @@ -19,8 +19,6 @@ import { Collection_deprecated } from '../../../collection-manager';
import { CollectionFieldProvider } from '../../../data-source/collection-field/CollectionFieldProvider';
import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { GeneralSchemaDesigner } from '../../../schema-settings';
import { useVariables } from '../../../variables';
import useContextVariable from '../../../variables/hooks/useContextVariable';
import { BlockItem } from '../block-item';
import { HTMLEncode } from '../input/shared';
import { FilterFormDesigner } from './FormItem.FilterFormDesigner';
Expand All @@ -47,14 +45,9 @@ export const FormItem: any = withDynamicSchemaProps(
useEnsureOperatorsValid();
const field = useField<Field>();
const schema = useFieldSchema();
const contextVariable = useContextVariable();
const variables = useVariables();
const { addActiveFieldName } = useFormActiveFields() || {};

useEffect(() => {
variables?.registerVariable(contextVariable);
}, [contextVariable]);

zhangzhonghe marked this conversation as resolved.
Show resolved Hide resolved
const form = useForm();
const { style } = props;
// 需要放在注冊完变量之后
useParseDefaultValue();
useLazyLoadDisplayAssociationFieldsOfForm();
Expand Down Expand Up @@ -85,7 +78,7 @@ export const FormItem: any = withDynamicSchemaProps(
<CollectionFieldProvider allowNull={true}>
<BlockItem className={'nb-form-item'}>
<ACLCollectionFieldProvider>
<Item className={className} {...props} extra={extra} />
<Item className={className} {...props} extra={extra} wrapperStyle={style} />
</ACLCollectionFieldProvider>
</BlockItem>
</CollectionFieldProvider>
Expand Down
Loading
Loading