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:
parent
76cd3474c3
commit
16cad6972e
@ -22,6 +22,7 @@ import { TableSelectorProvider, useTableSelectorProps } from './TableSelectorPro
|
|||||||
import * as bp from './hooks';
|
import * as bp from './hooks';
|
||||||
import { useTableBlockDecoratorProps } from '../modules/blocks/data-blocks/table/hooks/useTableBlockDecoratorProps';
|
import { useTableBlockDecoratorProps } from '../modules/blocks/data-blocks/table/hooks/useTableBlockDecoratorProps';
|
||||||
import { useListBlockDecoratorProps } from '../modules/blocks/data-blocks/list/hooks/useListBlockDecoratorProps';
|
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`
|
// TODO: delete this, replaced by `BlockSchemaComponentPlugin`
|
||||||
export const BlockSchemaComponentProvider: React.FC = (props) => {
|
export const BlockSchemaComponentProvider: React.FC = (props) => {
|
||||||
@ -54,6 +55,7 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
|
|||||||
useTableSelectorProps,
|
useTableSelectorProps,
|
||||||
useTableBlockDecoratorProps,
|
useTableBlockDecoratorProps,
|
||||||
useListBlockDecoratorProps,
|
useListBlockDecoratorProps,
|
||||||
|
useTableSelectorDecoratorProps,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
@ -103,6 +105,7 @@ export class BlockSchemaComponentPlugin extends Plugin {
|
|||||||
useTableSelectorProps,
|
useTableSelectorProps,
|
||||||
useTableBlockDecoratorProps,
|
useTableBlockDecoratorProps,
|
||||||
useListBlockDecoratorProps,
|
useListBlockDecoratorProps,
|
||||||
|
useTableSelectorDecoratorProps,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import { RecordProvider, useRecord } from '../record-provider';
|
|||||||
import { SchemaComponentOptions } from '../schema-component';
|
import { SchemaComponentOptions } from '../schema-component';
|
||||||
import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider';
|
import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider';
|
||||||
import { useParsedFilter } from './hooks';
|
import { useParsedFilter } from './hooks';
|
||||||
|
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
filter?: any;
|
filter?: any;
|
||||||
@ -141,7 +142,7 @@ const useAssociationNames = (collection) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TableSelectorProvider = (props: TableSelectorProviderProps) => {
|
export const TableSelectorProvider = withDynamicSchemaProps((props: TableSelectorProviderProps) => {
|
||||||
const parentParams = useTableSelectorParams();
|
const parentParams = useTableSelectorParams();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const { getCollectionJoinField, getCollectionFields } = useCollectionManager_deprecated();
|
const { getCollectionJoinField, getCollectionFields } = useCollectionManager_deprecated();
|
||||||
@ -263,7 +264,7 @@ export const TableSelectorProvider = (props: TableSelectorProviderProps) => {
|
|||||||
</BlockProvider>
|
</BlockProvider>
|
||||||
</SchemaComponentOptions>
|
</SchemaComponentOptions>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export const useTableSelectorContext = () => {
|
export const useTableSelectorContext = () => {
|
||||||
return useContext(TableSelectorContext);
|
return useContext(TableSelectorContext);
|
||||||
|
@ -2,7 +2,7 @@ import { FormOutlined } from '@ant-design/icons';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { useCollection_deprecated } from '../../../../collection-manager';
|
import { useCollection_deprecated } from '../../../../collection-manager';
|
||||||
import { createTableSelectorSchema } from '../../../../schema-initializer/utils';
|
import { createTableSelectorUISchema } from './createTableSelectorUISchema';
|
||||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||||
|
|
||||||
export const TableSelectorInitializer = () => {
|
export const TableSelectorInitializer = () => {
|
||||||
@ -16,11 +16,10 @@ export const TableSelectorInitializer = () => {
|
|||||||
{...others}
|
{...others}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
insert(
|
insert(
|
||||||
createTableSelectorSchema({
|
createTableSelectorUISchema({
|
||||||
rowKey: collection.filterTargetKey,
|
rowKey: collection.filterTargetKey,
|
||||||
collection: collection.name,
|
collectionName: collection.name,
|
||||||
dataSource: collection.dataSource,
|
dataSource: collection.dataSource,
|
||||||
resource: collection.name,
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -2,7 +2,7 @@ import { Page, expect, test } from '@nocobase/test/e2e';
|
|||||||
import { createTable } from './utils';
|
import { createTable } from './utils';
|
||||||
|
|
||||||
test.describe('where table data selector can be added', () => {
|
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' });
|
await createTable({ page, mockPage, fieldName: 'manyToOne' });
|
||||||
|
|
||||||
// 选中一行数据之后,弹窗自动关闭,且数据被填充到关联字段中
|
// 选中一行数据之后,弹窗自动关闭,且数据被填充到关联字段中
|
||||||
|
@ -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",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
@ -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',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1 @@
|
|||||||
|
export function useTableSelectorDecoratorProps() {}
|
@ -2,11 +2,7 @@ import { useCollection_deprecated } from '../../../..';
|
|||||||
import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer';
|
import { CompatibleSchemaInitializer } from '../../../../application/schema-initializer/CompatibleSchemaInitializer';
|
||||||
import { gridRowColWrap } from '../../../../schema-initializer/utils';
|
import { gridRowColWrap } from '../../../../schema-initializer/utils';
|
||||||
|
|
||||||
/**
|
const commonOptions = {
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
export const tableSelectorInitializers_deprecated = new CompatibleSchemaInitializer({
|
|
||||||
name: 'TableSelectorInitializers',
|
|
||||||
wrap: gridRowColWrap,
|
wrap: gridRowColWrap,
|
||||||
title: '{{t("Add block")}}',
|
title: '{{t("Add block")}}',
|
||||||
icon: 'PlusOutlined',
|
icon: 'PlusOutlined',
|
||||||
@ -84,88 +80,20 @@ export const tableSelectorInitializers_deprecated = new CompatibleSchemaInitiali
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
export const tableSelectorInitializers_deprecated = new CompatibleSchemaInitializer({
|
||||||
|
name: 'TableSelectorInitializers',
|
||||||
|
...commonOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const tableSelectorInitializers = new CompatibleSchemaInitializer(
|
export const tableSelectorInitializers = new CompatibleSchemaInitializer(
|
||||||
{
|
{
|
||||||
name: 'popup:tableSelector:addBlock',
|
name: 'popup:tableSelector:addBlock',
|
||||||
wrap: gridRowColWrap,
|
...commonOptions,
|
||||||
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**.")}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
tableSelectorInitializers_deprecated,
|
tableSelectorInitializers_deprecated,
|
||||||
);
|
);
|
||||||
|
@ -1415,55 +1415,6 @@ export const createCollapseBlockSchema = (options) => {
|
|||||||
return schema;
|
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 = ({
|
const getChildren = ({
|
||||||
collections,
|
collections,
|
||||||
dataSource,
|
dataSource,
|
||||||
|
Loading…
Reference in New Issue
Block a user