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 { 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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
|
@ -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' });
|
||||
|
||||
// 选中一行数据之后,弹窗自动关闭,且数据被填充到关联字段中
|
||||
|
@ -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,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,
|
||||
);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user