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:
parent
40554d8151
commit
2c690a39e0
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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") }}',
|
||||||
|
@ -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 });
|
||||||
|
};
|
||||||
|
@ -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');
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user