feat: add filter action to collection table (#953)

* feat: 数据表支持筛选

* feat: 数据表支持筛选

* feat: 数据表支持筛选

* feat: 数据表支持筛选

* fix: format code

Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
katherinehhh 2022-10-24 09:49:16 +08:00 committed by GitHub
parent 40554d8151
commit 2c690a39e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 35 deletions

View File

@ -4,7 +4,7 @@ import { uid } from '@formily/shared';
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { useRequest } from '../../api-client'; import { useRequest } from '../../api-client';
import { useRecord } from '../../record-provider'; import { useRecord } from '../../record-provider';
import { SchemaComponent, useActionContext, useCompile } from '../../schema-component'; import { SchemaComponent, SchemaComponentContext, useActionContext, useCompile } from '../../schema-component';
import { useCollectionManager } from '../hooks/useCollectionManager'; import { useCollectionManager } from '../hooks/useCollectionManager';
import { DataSourceContext } from '../sub-table'; import { DataSourceContext } from '../sub-table';
import { AddSubFieldAction } from './AddSubFieldAction'; import { AddSubFieldAction } from './AddSubFieldAction';
@ -164,11 +164,11 @@ const useCurrentFields = () => {
const { getCollectionFields } = useCollectionManager(); const { getCollectionFields } = useCollectionManager();
const fields = getCollectionFields(record.collectionName || record.name) as any[]; const fields = getCollectionFields(record.collectionName || record.name) as any[];
return fields; return fields;
} };
const useNewId = (prefix) => { const useNewId = (prefix) => {
return `${prefix || ''}${uid()}`; return `${prefix || ''}${uid()}`;
} };
export const ConfigurationTable = () => { export const ConfigurationTable = () => {
const { collections = [] } = useCollectionManager(); const { collections = [] } = useCollectionManager();
@ -179,26 +179,29 @@ export const ConfigurationTable = () => {
value: item.name, value: item.name,
})); }));
}; };
const ctx = useContext(SchemaComponentContext);
return ( return (
<div> <div>
<SchemaComponent <SchemaComponentContext.Provider value={{ ...ctx, designable: false }}>
schema={collectionSchema} <SchemaComponent
components={{ schema={collectionSchema}
AddSubFieldAction, components={{
EditSubFieldAction, AddSubFieldAction,
FieldSummary, EditSubFieldAction,
}} FieldSummary,
scope={{ }}
useDestroySubField, scope={{
useBulkDestroySubField, useDestroySubField,
useSelectedRowKeys, useBulkDestroySubField,
useCollectionValues, useSelectedRowKeys,
useAsyncDataSource, useCollectionValues,
loadCollections, useAsyncDataSource,
useCurrentFields, loadCollections,
useNewId, useCurrentFields,
}} useNewId,
/> }}
/>
</SchemaComponentContext.Provider>
</div> </div>
); );
}; };

View File

@ -5,9 +5,9 @@ import { collectionFieldSchema } from './collectionFields';
const compile = (source) => { const compile = (source) => {
return Schema.compile(source, { t: i18n.t }); return Schema.compile(source, { t: i18n.t });
} };
const collection: CollectionOptions = { export const collection: CollectionOptions = {
name: 'collections', name: 'collections',
filterTargetKey: 'name', filterTargetKey: 'name',
targetKey: 'name', targetKey: 'name',
@ -31,7 +31,8 @@ const collection: CollectionOptions = {
title: '{{ t("Collection name") }}', title: '{{ t("Collection name") }}',
type: 'string', type: 'string',
'x-component': 'Input', 'x-component': 'Input',
description: '{{t("Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.")}}', description:
'{{t("Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.")}}',
}, },
}, },
{ {
@ -82,6 +83,20 @@ export const collectionSchema: ISchema = {
}, },
}, },
properties: { properties: {
filter: {
type: 'void',
title: '{{ t("Filter") }}',
default: {
$and: [{ title: { $includes: '' } }, { name: { $includes: '' } }],
},
'x-action': 'filter',
'x-component': 'Filter.Action',
'x-component-props': {
icon: 'FilterOutlined',
useProps: '{{ cm.useFilterActionProps }}',
},
'x-align': 'left',
},
delete: { delete: {
type: 'void', type: 'void',
title: '{{ t("Delete") }}', title: '{{ t("Delete") }}',

View File

@ -1,12 +1,13 @@
import { useForm } from '@formily/react';
import { message } from 'antd'; import { message } from 'antd';
import omit from 'lodash/omit'; import omit from 'lodash/omit';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useForm } from '@formily/react';
import { useCollection, useCollectionManager } from '.'; import { useCollection, useCollectionManager } from '.';
import { useRequest } from '../api-client'; import { useRequest } from '../api-client';
import { useRecord } from '../record-provider'; import { useRecord } from '../record-provider';
import { useActionContext } from '../schema-component'; import { useActionContext } from '../schema-component';
import { useResourceActionContext, useResourceContext } from './ResourceActionProvider'; import { useResourceActionContext, useResourceContext } from './ResourceActionProvider';
import { useFilterFieldProps, useFilterFieldOptions } from '../schema-component/antd/filter/useFilterActionProps';
export const useCancelAction = () => { export const useCancelAction = () => {
const form = useForm(); const form = useForm();
@ -111,7 +112,7 @@ export const useCollectionFilterOptions = (collectionName: string) => {
} }
if (nested) { if (nested) {
const targetFields = getCollectionFields(field.target); const targetFields = getCollectionFields(field.target);
const options = getOptions(targetFields, depth+1).filter(Boolean); const options = getOptions(targetFields, depth + 1).filter(Boolean);
option['children'] = option['children'] || []; option['children'] = option['children'] || [];
option['children'].push(...options); option['children'].push(...options);
} }
@ -275,7 +276,7 @@ export const useUpdateCollectionActionAndRefreshCM = (options) => {
await refreshCM(); await refreshCM();
}, },
}; };
} };
export const useValuesFromRecord = (options) => { export const useValuesFromRecord = (options) => {
const record = useRecord(); const record = useRecord();
@ -305,7 +306,7 @@ export const useCreateActionAndRefreshCM = () => {
const { refreshCM } = useCollectionManager(); const { refreshCM } = useCollectionManager();
return { return {
async run() { async run() {
await run(); await run();
await refreshCM(); await refreshCM();
}, },
}; };
@ -337,9 +338,16 @@ export const useBulkDestroyActionAndRefreshCM = () => {
const { run } = useBulkDestroyAction(); const { run } = useBulkDestroyAction();
const { refreshCM } = useCollectionManager(); const { refreshCM } = useCollectionManager();
return { return {
async run() { async run() {
await run(); await run();
await refreshCM(); await refreshCM();
}, },
}; };
}; };
export const useFilterActionProps = () => {
const { collection } = useResourceContext();
const options = useFilterFieldOptions(collection.fields);
const service = useResourceActionContext();
return useFilterFieldProps({ options, params: service.params, service });
};

View File

@ -6,10 +6,15 @@ import { useBlockRequestContext } from '../../../block-provider';
import { useCollection, useCollectionManager } from '../../../collection-manager'; import { useCollection, useCollectionManager } from '../../../collection-manager';
export const useFilterOptions = (collectionName: string) => { export const useFilterOptions = (collectionName: string) => {
const { getCollectionFields } = useCollectionManager();
const fields = getCollectionFields(collectionName);
return useFilterFieldOptions(fields);
};
export const useFilterFieldOptions = (fields) => {
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const nonfilterable = fieldSchema?.['x-component-props']?.nonfilterable || []; const nonfilterable = fieldSchema?.['x-component-props']?.nonfilterable || [];
const { getCollectionFields, getInterface } = useCollectionManager(); const { getCollectionFields, getInterface } = useCollectionManager();
const fields = getCollectionFields(collectionName);
const field2option = (field, depth) => { const field2option = (field, depth) => {
if (nonfilterable.length && depth === 1 && nonfilterable.includes(field.name)) { if (nonfilterable.length && depth === 1 && nonfilterable.includes(field.name)) {
return; return;
@ -44,7 +49,7 @@ export const useFilterOptions = (collectionName: string) => {
} }
if (nested) { if (nested) {
const targetFields = getCollectionFields(field.target); const targetFields = getCollectionFields(field.target);
const options = getOptions(targetFields, depth+1).filter(Boolean); const options = getOptions(targetFields, depth + 1).filter(Boolean);
option['children'] = option['children'] || []; option['children'] = option['children'] || [];
option['children'].push(...options); option['children'].push(...options);
} }
@ -67,7 +72,7 @@ const isEmpty = (obj) => {
return obj && Object.keys(obj).length === 0 && Object.getPrototypeOf(obj) === Object.prototype; return obj && Object.keys(obj).length === 0 && Object.getPrototypeOf(obj) === Object.prototype;
}; };
const removeNullCondition = (filter) => { export const removeNullCondition = (filter) => {
const items = flat(filter || {}); const items = flat(filter || {});
const values = {}; const values = {};
for (const key in items) { for (const key in items) {
@ -96,13 +101,17 @@ export const useFilterActionProps = () => {
const { name } = useCollection(); const { name } = useCollection();
const options = useFilterOptions(name); const options = useFilterOptions(name);
const { service, props } = useBlockRequestContext(); const { service, props } = useBlockRequestContext();
const field = useField<Field>(); return useFilterFieldProps({ options, service, params: props.params });
};
export const useFilterFieldProps = ({ options, service, params }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const field = useField<Field>();
return { return {
options, options,
onSubmit(values) { onSubmit(values) {
// filter parameter for the block // filter parameter for the block
const defaultFilter = removeNullCondition(props.params.filter); const defaultFilter = removeNullCondition(params.filter);
// filter parameter for the filter action // filter parameter for the filter action
const filter = removeNullCondition(values?.filter); const filter = removeNullCondition(values?.filter);
service.run({ ...service.params?.[0], page: 1, filter: mergeFilter(defaultFilter, filter) }); service.run({ ...service.params?.[0], page: 1, filter: mergeFilter(defaultFilter, filter) });
@ -114,7 +123,7 @@ export const useFilterActionProps = () => {
} }
}, },
onReset() { onReset() {
const filter = removeNullCondition(props.params.filter); const filter = removeNullCondition(params.filter);
service.run({ ...service.params?.[0], filter, page: 1 }); service.run({ ...service.params?.[0], filter, page: 1 });
field.title = t('Filter'); field.title = t('Filter');
}, },