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 #4466

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all 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
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
Expand Up @@ -239,6 +239,10 @@ describe('FieldSettingsFormItem', () => {
title: 'Pattern',
type: 'select',
},
{
title: 'Style',
type: 'modal',
},
{
title: 'Set validation rules',
type: 'modal',
Expand Down Expand Up @@ -281,6 +285,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 @@ -24,6 +24,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 +443,25 @@ export const fieldSettingsFormItem = new SchemaSettings({
return form && !isFormReadPretty && validateSchema;
},
},
{
name: 'style',
Component: (props) => {
const propsWithType = { ...props, type: 'style' };
return <SchemaSettingsLinkageRules {...propsWithType} />;
},
useVisible() {
const field: any = useField();
return field.readPretty;
},
useComponentProps() {
const { name } = useCollection_deprecated();
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: name,
};
},
},
];
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
* 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 { useCollection_deprecated, useCollectionManager_deprecated } from '../../../../collection-manager';
import { useDesignable } from '../../../../schema-component';
import { useAssociationFieldContext } from '../../../../schema-component/antd/association-field/hooks';
import { useColumnSchema } from '../../../../schema-component/antd/table-v2/Table.Column.Decorator';
import { SchemaSettingsDefaultValue } from '../../../../schema-settings/SchemaSettingsDefaultValue';
import { useFieldComponentName } from './utils';
import { isPatternDisabled } from '../../../../schema-settings/isPatternDisabled';
import { useCollection } from '../../../../data-source';
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,50 @@ export const tableColumnSettings = new SchemaSettings({
};
},
},
{
name: 'style',
Component: (props) => {
const propsWithType = { ...props, type: 'style' };
return <SchemaSettingsLinkageRules {...propsWithType} />;
},
useVisible() {
const { uiSchema, fieldSchema } = useColumnSchema();
const field: any = useField();
const path = field.path?.splice(field.path?.length - 1, 1);
const isReadPretty = field.form.query(`${path.concat(`*.` + fieldSchema.name)}`).get('readPretty');
return isReadPretty;
},
useComponentProps() {
const { name } = useCollection_deprecated();
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
collectionName: name,
};
},
},
{
name: 'linkageRules',
Component: (props) => {
const propsWithType = { ...props };
return <SchemaSettingsLinkageRules {...propsWithType} />;
},
useVisible() {
const { uiSchema, fieldSchema } = useColumnSchema();
const field: any = useField();
const path = field.path?.splice(field.path?.length - 1, 1);
const isReadPretty = field.form.query(`${path.concat(`*.` + fieldSchema.name)}`).get('readPretty');
return isReadPretty;
},
useComponentProps() {
const { name } = useCollection_deprecated();
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 @@ -9,25 +9,27 @@

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 React, { useEffect, useMemo } from 'react';
import { Field, onFormValuesChange, Form } from '@formily/core';
import { observer, useField, useFieldSchema, useFormEffects } from '@formily/react';
import React, { useEffect, useMemo, useState } from 'react';
import { ACLCollectionFieldProvider } from '../../../acl/ACLProvider';
import { useApp } from '../../../application';
import { useFormActiveFields } from '../../../block-provider/hooks/useFormActiveFields';
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 { useVariables, useLocalVariables } from '../../../variables';
import useContextVariable from '../../../variables/hooks/useContextVariable';
import { BlockItem } from '../block-item';
import { HTMLEncode } from '../input/shared';
import { FilterFormDesigner } from './FormItem.FilterFormDesigner';
import { useEnsureOperatorsValid } from './SchemaSettingOptions';
import useLazyLoadDisplayAssociationFieldsOfForm from './hooks/useLazyLoadDisplayAssociationFieldsOfForm';
import useParseDefaultValue from './hooks/useParseDefaultValue';

import { LinkageRuleDataKey } from '../../../schema-settings/LinkageRules/type';
import { getSatisfiedValueMap } from '../../../schema-settings/LinkageRules/compute-rules';
import { isEmpty } from 'lodash';
Item.displayName = 'FormilyFormItem';

const formItemWrapCss = css`
Expand All @@ -50,11 +52,32 @@ export const FormItem: any = withDynamicSchemaProps(
const contextVariable = useContextVariable();
const variables = useVariables();
const { addActiveFieldName } = useFormActiveFields() || {};

// const form = useForm();
const [form, setForm] = useState<Form>();
const localVariables = useLocalVariables({ currentForm: { values: form?.values } as any });
const [style, setStyle] = useState({});
useEffect(() => {
variables?.registerVariable(contextVariable);
}, [contextVariable]);

useFormEffects(() => {
onFormValuesChange((form) => {
setForm(form);
});
});
useEffect(() => {
const linkageStyleRules = schema[LinkageRuleDataKey.style] || [];
if (form) {
getSatisfiedValueMap({ rules: linkageStyleRules, variables, localVariables })
.then((valueMap) => {
if (!isEmpty(valueMap)) {
setStyle(valueMap);
}
})
.catch((err) => {
throw new Error(err.message);
});
}
}, [schema, variables, localVariables, form]);
// 需要放在注冊完变量之后
useParseDefaultValue();
useLazyLoadDisplayAssociationFieldsOfForm();
Expand Down Expand Up @@ -85,7 +108,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
32 changes: 27 additions & 5 deletions packages/core/client/src/schema-component/antd/table-v2/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import { isPortalInBody } from '@nocobase/utils/client';
import { useCreation, useDeepCompareEffect, useMemoizedFn } from 'ahooks';
import { Table as AntdTable, Skeleton, TableColumnProps } from 'antd';
import { default as classNames, default as cls } from 'classnames';
import _, { omit } from 'lodash';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import _, { omit, isEmpty } from 'lodash';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useInView } from 'react-intersection-observer';
import { DndContext, useDesignable, useTableSize } from '../..';
Expand All @@ -34,14 +34,16 @@ import {
useTableBlockContext,
useTableSelectorContext,
} from '../../../';
import { useLocalVariables, useVariables } from '../../../';
import { useACLFieldWhitelist } from '../../../acl/ACLProvider';
import { isNewRecord } from '../../../data-source/collection-record/isNewRecord';
import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { useToken } from '../__builtins__';
import { SubFormProvider } from '../association-field/hooks';
import { ColumnFieldProvider } from './components/ColumnFieldProvider';
import { extractIndex, isCollectionFieldComponent, isColumnComponent } from './utils';

import { getSatisfiedValueMap } from '../../../schema-settings/LinkageRules/compute-rules';
import { LinkageRuleDataKey } from '../../../schema-settings/LinkageRules/type';
const MemoizedAntdTable = React.memo(AntdTable);

const useArrayField = (props) => {
Expand Down Expand Up @@ -108,6 +110,7 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) =>
}, [token.paddingContentVerticalLG, token.marginSM]);

const collection = useCollection();
const variables = useVariables();

const columns = useMemo(
() =>
Expand All @@ -118,6 +121,7 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) =>
}
}, []);
const dataIndex = collectionFields?.length > 0 ? collectionFields[0].name : s.name;
const linkageStyleRules = s?.[LinkageRuleDataKey.style] || [];
return {
title: <RecursionField name={s.name} schema={s} onlyRenderSelf />,
dataIndex,
Expand Down Expand Up @@ -145,6 +149,9 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) =>
</SubFormProvider>
);
},
onCell: (record) => {
return { record, linkageStyleRules, variables };
},
} as TableColumnProps<any>;

// 这里不能把 columnsSchema 作为依赖,因为其每次都会变化,这里使用 hasChangedColumns 作为依赖
Expand Down Expand Up @@ -526,16 +533,31 @@ export const Table: any = withDynamicSchemaProps(
const BodyCellComponent = useCallback(
(props) => {
const isIndex = props.className?.includes('selection-column');

const { record, linkageStyleRules, variables } = props;
const { ref, inView } = useInView({
threshold: 0,
triggerOnce: true,
initialInView: isIndex || !!process.env.__E2E__ || dataSource.length <= 10,
skip: isIndex || !!process.env.__E2E__,
});
const localVariables = useLocalVariables({ currentForm: { values: record } as any });
const [style, setStyle] = useState();
useEffect(() => {
if (linkageStyleRules) {
getSatisfiedValueMap({ rules: linkageStyleRules, variables, localVariables })
.then((valueMap) => {
if (!isEmpty(valueMap)) {
setStyle(valueMap);
}
})
.catch((err) => {
throw new Error(err);
});
}
}, [linkageStyleRules, variables, localVariables]);

return (
<td {...props} ref={ref} className={classNames(props.className, cellClass)}>
<td {...props} ref={ref} className={classNames(props.className, cellClass)} style={style}>
{inView || isIndex ? props.children : <Skeleton.Button style={{ height: '100%' }} />}
</td>
);
Expand Down
Loading
Loading