refactor(DataBlock): table selector (#3784)

* refactor: extract to common options

* refactor: migrate to modules

* test: add unit test

* refactor: use x-use-component-props instead of useProps

* chore: fix unit test

* chore: rename

* fix: useExpressionScope

---------

Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
Zeke Zhang 2024-03-27 17:51:13 +08:00 committed by GitHub
parent 76cd3474c3
commit 16cad6972e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 138 additions and 138 deletions

View File

@ -22,6 +22,7 @@ import { TableSelectorProvider, useTableSelectorProps } from './TableSelectorPro
import * as bp from './hooks';
import { useTableBlockDecoratorProps } from '../modules/blocks/data-blocks/table/hooks/useTableBlockDecoratorProps';
import { useListBlockDecoratorProps } from '../modules/blocks/data-blocks/list/hooks/useListBlockDecoratorProps';
import { useTableSelectorDecoratorProps } from '../modules/blocks/data-blocks/table-selector/hooks/useTableSelectorDecoratorProps';
// TODO: delete this, replaced by `BlockSchemaComponentPlugin`
export const BlockSchemaComponentProvider: React.FC = (props) => {
@ -54,6 +55,7 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
useTableSelectorProps,
useTableBlockDecoratorProps,
useListBlockDecoratorProps,
useTableSelectorDecoratorProps,
}}
>
{props.children}
@ -103,6 +105,7 @@ export class BlockSchemaComponentPlugin extends Plugin {
useTableSelectorProps,
useTableBlockDecoratorProps,
useListBlockDecoratorProps,
useTableSelectorDecoratorProps,
});
}
}

View File

@ -11,6 +11,7 @@ import { RecordProvider, useRecord } from '../record-provider';
import { SchemaComponentOptions } from '../schema-component';
import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider';
import { useParsedFilter } from './hooks';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
type Params = {
filter?: any;
@ -141,7 +142,7 @@ const useAssociationNames = (collection) => {
);
};
export const TableSelectorProvider = (props: TableSelectorProviderProps) => {
export const TableSelectorProvider = withDynamicSchemaProps((props: TableSelectorProviderProps) => {
const parentParams = useTableSelectorParams();
const fieldSchema = useFieldSchema();
const { getCollectionJoinField, getCollectionFields } = useCollectionManager_deprecated();
@ -263,7 +264,7 @@ export const TableSelectorProvider = (props: TableSelectorProviderProps) => {
</BlockProvider>
</SchemaComponentOptions>
);
};
});
export const useTableSelectorContext = () => {
return useContext(TableSelectorContext);

View File

@ -2,7 +2,7 @@ import { FormOutlined } from '@ant-design/icons';
import React from 'react';
import { useCollection_deprecated } from '../../../../collection-manager';
import { createTableSelectorSchema } from '../../../../schema-initializer/utils';
import { createTableSelectorUISchema } from './createTableSelectorUISchema';
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
export const TableSelectorInitializer = () => {
@ -16,11 +16,10 @@ export const TableSelectorInitializer = () => {
{...others}
onClick={async () => {
insert(
createTableSelectorSchema({
createTableSelectorUISchema({
rowKey: collection.filterTargetKey,
collection: collection.name,
collectionName: collection.name,
dataSource: collection.dataSource,
resource: collection.name,
}),
);
}}

View File

@ -2,7 +2,7 @@ import { Page, expect, test } from '@nocobase/test/e2e';
import { createTable } from './utils';
test.describe('where table data selector can be added', () => {
test('popup', async ({ page, mockPage, mockRecord }) => {
test('popup', async ({ page, mockPage }) => {
await createTable({ page, mockPage, fieldName: 'manyToOne' });
// 选中一行数据之后,弹窗自动关闭,且数据被填充到关联字段中

View File

@ -0,0 +1,61 @@
import { createTableSelectorUISchema } from '../createTableSelectorUISchema';
vi.mock('@formily/shared', () => {
return {
uid: () => 'mocked-uid',
};
});
describe('createTableSelectorSchema', () => {
test('should return the correct schema', () => {
const schema = createTableSelectorUISchema({
collectionName: 'example',
dataSource: 'example',
rowKey: 'id',
});
expect(schema).toMatchInlineSnapshot(`
{
"properties": {
"mocked-uid": {
"type": "void",
"x-component": "ActionBar",
"x-component-props": {
"style": {
"marginBottom": "var(--nb-spacing)",
},
},
"x-initializer": "table:configureActions",
},
"value": {
"type": "array",
"x-component": "TableV2.Selector",
"x-component-props": {
"rowSelection": {
"type": "checkbox",
},
},
"x-initializer": "table:configureColumns",
"x-use-component-props": "useTableSelectorProps",
},
},
"type": "void",
"x-acl-action": "example:list",
"x-component": "CardItem",
"x-decorator": "TableSelectorProvider",
"x-decorator-props": {
"action": "list",
"collection": "example",
"dataSource": "example",
"params": {
"pageSize": 20,
},
"rowKey": "id",
},
"x-settings": "blockSettings:tableSelector",
"x-toolbar": "BlockSchemaToolbar",
"x-use-decorator-props": "useTableSelectorDecoratorProps",
}
`);
});
});

View File

@ -0,0 +1,56 @@
import { ISchema } from '@formily/react';
import { uid } from '@formily/shared';
export const createTableSelectorUISchema = (options: {
collectionName: string;
dataSource: string;
rowKey: string;
}): ISchema => {
const { collectionName, dataSource, rowKey } = options;
if (!collectionName || !dataSource || !rowKey) {
throw new Error('collectionName, dataSource, rowKey is required');
}
return {
type: 'void',
'x-acl-action': `${collectionName}:list`,
'x-decorator': 'TableSelectorProvider',
'x-use-decorator-props': 'useTableSelectorDecoratorProps',
'x-decorator-props': {
collection: collectionName,
dataSource,
action: 'list',
params: {
pageSize: 20,
},
rowKey,
},
'x-toolbar': 'BlockSchemaToolbar',
'x-settings': 'blockSettings:tableSelector',
'x-component': 'CardItem',
properties: {
[uid()]: {
type: 'void',
'x-initializer': 'table:configureActions',
'x-component': 'ActionBar',
'x-component-props': {
style: {
marginBottom: 'var(--nb-spacing)',
},
},
},
value: {
type: 'array',
'x-initializer': 'table:configureColumns',
'x-component': 'TableV2.Selector',
'x-use-component-props': 'useTableSelectorProps',
'x-component-props': {
rowSelection: {
type: 'checkbox',
},
},
},
},
};
};

View File

@ -0,0 +1 @@
export function useTableSelectorDecoratorProps() {}

View File

@ -2,170 +2,98 @@ import { useCollection_deprecated } from '../../../..';
import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer';
import { gridRowColWrap } from '../../../../schema-initializer/utils';
const commonOptions = {
wrap: gridRowColWrap,
title: '{{t("Add block")}}',
icon: 'PlusOutlined',
items: [
{
type: 'itemGroup',
title: '{{t("Selector")}}',
name: 'selector',
children: [
{
name: 'title',
title: 'Table',
Component: 'TableSelectorInitializer',
},
],
},
{
type: 'itemGroup',
title: '{{t("Filter blocks")}}',
name: 'filterBlocks',
useChildren() {
const { name, dataSource } = useCollection_deprecated();
return [
{
name: 'filterFormBlockInTableSelector',
title: '{{t("Form")}}',
Component: 'FilterFormBlockInitializer',
componentProps: {
filterCollections() {
return false;
},
onlyCurrentDataSource: true,
},
collectionName: name,
dataSource,
},
{
name: 'filterCollapseBlockInTableSelector',
title: '{{t("Collapse")}}',
Component: 'FilterCollapseBlockInitializer',
componentProps: {
filterCollections() {
return false;
},
onlyCurrentDataSource: true,
},
collectionName: name,
dataSource,
},
];
},
},
{
type: 'itemGroup',
title: '{{t("Other blocks")}}',
name: 'otherBlocks',
children: [
{
title: '{{t("Add text")}}',
Component: 'BlockItemInitializer',
name: 'addText',
schema: {
type: 'void',
'x-editable': false,
'x-decorator': 'BlockItem',
// 'x-designer': 'Markdown.Void.Designer',
'x-toolbar': 'BlockSchemaToolbar',
'x-settings': 'blockSettings:markdown',
'x-component': 'Markdown.Void',
'x-component-props': {
content: '{{t("This is a demo text, **supports Markdown syntax**.")}}',
},
},
},
],
},
],
};
/**
* @deprecated
*/
export const tableSelectorInitializers_deprecated = new CompatibleSchemaInitializer({
name: 'TableSelectorInitializers',
wrap: gridRowColWrap,
title: '{{t("Add block")}}',
icon: 'PlusOutlined',
items: [
{
type: 'itemGroup',
title: '{{t("Selector")}}',
name: 'selector',
children: [
{
name: 'title',
title: 'Table',
Component: 'TableSelectorInitializer',
},
],
},
{
type: 'itemGroup',
title: '{{t("Filter blocks")}}',
name: 'filterBlocks',
useChildren() {
const { name, dataSource } = useCollection_deprecated();
return [
{
name: 'filterFormBlockInTableSelector',
title: '{{t("Form")}}',
Component: 'FilterFormBlockInitializer',
componentProps: {
filterCollections() {
return false;
},
onlyCurrentDataSource: true,
},
collectionName: name,
dataSource,
},
{
name: 'filterCollapseBlockInTableSelector',
title: '{{t("Collapse")}}',
Component: 'FilterCollapseBlockInitializer',
componentProps: {
filterCollections() {
return false;
},
onlyCurrentDataSource: true,
},
collectionName: name,
dataSource,
},
];
},
},
{
type: 'itemGroup',
title: '{{t("Other blocks")}}',
name: 'otherBlocks',
children: [
{
title: '{{t("Add text")}}',
Component: 'BlockItemInitializer',
name: 'addText',
schema: {
type: 'void',
'x-editable': false,
'x-decorator': 'BlockItem',
// 'x-designer': 'Markdown.Void.Designer',
'x-toolbar': 'BlockSchemaToolbar',
'x-settings': 'blockSettings:markdown',
'x-component': 'Markdown.Void',
'x-component-props': {
content: '{{t("This is a demo text, **supports Markdown syntax**.")}}',
},
},
},
],
},
],
...commonOptions,
});
export const tableSelectorInitializers = new CompatibleSchemaInitializer(
{
name: 'popup:tableSelector:addBlock',
wrap: gridRowColWrap,
title: '{{t("Add block")}}',
icon: 'PlusOutlined',
items: [
{
type: 'itemGroup',
title: '{{t("Selector")}}',
name: 'selector',
children: [
{
name: 'title',
title: 'Table',
Component: 'TableSelectorInitializer',
},
],
},
{
type: 'itemGroup',
title: '{{t("Filter blocks")}}',
name: 'filterBlocks',
useChildren() {
const { name, dataSource } = useCollection_deprecated();
return [
{
name: 'filterFormBlockInTableSelector',
title: '{{t("Form")}}',
Component: 'FilterFormBlockInitializer',
componentProps: {
filterCollections() {
return false;
},
onlyCurrentDataSource: true,
},
collectionName: name,
dataSource,
},
{
name: 'filterCollapseBlockInTableSelector',
title: '{{t("Collapse")}}',
Component: 'FilterCollapseBlockInitializer',
componentProps: {
filterCollections() {
return false;
},
onlyCurrentDataSource: true,
},
collectionName: name,
dataSource,
},
];
},
},
{
type: 'itemGroup',
title: '{{t("Other blocks")}}',
name: 'otherBlocks',
children: [
{
title: '{{t("Add text")}}',
Component: 'BlockItemInitializer',
name: 'addText',
schema: {
type: 'void',
'x-editable': false,
'x-decorator': 'BlockItem',
// 'x-designer': 'Markdown.Void.Designer',
'x-toolbar': 'BlockSchemaToolbar',
'x-settings': 'blockSettings:markdown',
'x-component': 'Markdown.Void',
'x-component-props': {
content: '{{t("This is a demo text, **supports Markdown syntax**.")}}',
},
},
},
],
},
],
...commonOptions,
},
tableSelectorInitializers_deprecated,
);

View File

@ -1415,55 +1415,6 @@ export const createCollapseBlockSchema = (options) => {
return schema;
};
export const createTableSelectorSchema = (options) => {
const { collection, dataSource, resource, rowKey, ...others } = options;
const schema: ISchema = {
type: 'void',
'x-acl-action': `${resource || collection}:list`,
'x-decorator': 'TableSelectorProvider',
'x-decorator-props': {
collection,
resource: resource || collection,
dataSource,
action: 'list',
params: {
pageSize: 20,
},
rowKey,
...others,
},
'x-toolbar': 'BlockSchemaToolbar',
'x-settings': 'blockSettings:tableSelector',
'x-component': 'CardItem',
properties: {
[uid()]: {
type: 'void',
'x-initializer': 'table:configureActions',
'x-component': 'ActionBar',
'x-component-props': {
style: {
marginBottom: 'var(--nb-spacing)',
},
},
properties: {},
},
value: {
type: 'array',
'x-initializer': 'table:configureColumns',
'x-component': 'TableV2.Selector',
'x-component-props': {
rowSelection: {
type: 'checkbox',
},
useProps: '{{ useTableSelectorProps }}',
},
properties: {},
},
},
};
return schema;
};
const getChildren = ({
collections,
dataSource,