katherinehhh 2c690a39e0
feat: add filter action to collection table (#953)
* feat: 数据表支持筛选

* feat: 数据表支持筛选

* feat: 数据表支持筛选

* feat: 数据表支持筛选

* fix: format code

Co-authored-by: chenos <chenlinxh@gmail.com>
2022-10-24 09:49:16 +08:00

354 lines
9.3 KiB
TypeScript

import { message } from 'antd';
import omit from 'lodash/omit';
import { useEffect } from 'react';
import { useForm } from '@formily/react';
import { useCollection, useCollectionManager } from '.';
import { useRequest } from '../api-client';
import { useRecord } from '../record-provider';
import { useActionContext } from '../schema-component';
import { useResourceActionContext, useResourceContext } from './ResourceActionProvider';
import { useFilterFieldProps, useFilterFieldOptions } from '../schema-component/antd/filter/useFilterActionProps';
export const useCancelAction = () => {
const form = useForm();
const ctx = useActionContext();
return {
async run() {
ctx.setVisible(false);
form.reset();
},
};
};
export const useResetFilterAction = () => {
const { run } = useResourceActionContext();
const form = useForm();
const ctx = useActionContext();
return {
async run() {
form.reset();
run();
ctx.setVisible(false);
},
};
};
export const useKanbanEvents = () => {
const { resource } = useCollection();
return {
async onCardDragEnd({ columns, groupField }, { fromColumnId, fromPosition }, { toColumnId, toPosition }) {
const sourceColumn = columns.find((column) => column.id === fromColumnId);
const destinationColumn = columns.find((column) => column.id === toColumnId);
const sourceCard = sourceColumn?.cards?.[fromPosition];
const targetCard = destinationColumn?.cards?.[toPosition];
const values = {
sourceId: sourceCard.id,
sortField: `${groupField.name}_sort`,
};
if (targetCard) {
values['targetId'] = targetCard.id;
} else {
values['targetScope'] = {
[groupField.name]: toColumnId,
};
}
await resource.move(values);
},
};
};
export const useSortFields = (collectionName: string) => {
const { getCollectionFields, getInterface } = useCollectionManager();
const fields = getCollectionFields(collectionName);
return fields
.filter((field: any) => {
if (!field.interface) {
return false;
}
const fieldInterface = getInterface(field.interface);
if (fieldInterface.sortable) {
return true;
}
return false;
})
.map((field: any) => {
return {
value: field.name,
label: field?.uiSchema?.title || field.name,
};
});
};
export const useCollectionFilterOptions = (collectionName: string) => {
const { getCollectionFields, getInterface } = useCollectionManager();
const fields = getCollectionFields(collectionName);
const field2option = (field, depth) => {
if (!field.interface) {
return;
}
const fieldInterface = getInterface(field.interface);
if (!fieldInterface.filterable) {
return;
}
const { nested, children, operators } = fieldInterface.filterable;
const option = {
name: field.name,
title: field?.uiSchema?.title || field.name,
schema: field?.uiSchema,
operators:
operators?.filter?.((operator) => {
return !operator?.visible || operator.visible(field);
}) || [],
};
if (field.target && depth > 2) {
return;
}
if (depth > 2) {
return option;
}
if (children?.length) {
option['children'] = children;
}
if (nested) {
const targetFields = getCollectionFields(field.target);
const options = getOptions(targetFields, depth + 1).filter(Boolean);
option['children'] = option['children'] || [];
option['children'].push(...options);
}
return option;
};
const getOptions = (fields, depth) => {
const options = [];
fields.forEach((field) => {
const option = field2option(field, depth);
if (option) {
options.push(option);
}
});
return options;
};
return getOptions(fields, 1);
};
export const useFilterDataSource = (options) => {
const { name } = useCollection();
const data = useCollectionFilterOptions(name);
return useRequest(
() =>
Promise.resolve({
data,
}),
options,
);
};
export const useFilterAction = () => {
const { run, params, defaultRequest } = useResourceActionContext();
const form = useForm();
const ctx = useActionContext();
const [first, ...others] = params;
return {
async run() {
const prevFilter = defaultRequest?.params?.filter;
const filter = prevFilter ? { $and: [prevFilter, form.values.filter] } : form.values.filter;
run({ ...first, filter }, ...others);
ctx.setVisible(false);
},
};
};
export const useCreateAction = () => {
const form = useForm();
const ctx = useActionContext();
const { refresh } = useResourceActionContext();
const { resource } = useResourceContext();
return {
async run() {
await form.submit();
await resource.create({ values: form.values });
ctx.setVisible(false);
await form.reset();
refresh();
},
};
};
export const useCreateActionWithoutRefresh = () => {
const form = useForm();
const { resource } = useResourceContext();
return {
async run() {
await form.submit();
await resource.create({ values: form.values });
await form.reset();
},
};
};
export const useUpdateViewAction = () => {
const form = useForm();
const ctx = useActionContext();
// const { refresh } = useResourceActionContext();
const { resource, targetKey } = useResourceContext();
const { [targetKey]: filterByTk } = useRecord();
return {
async run() {
await form.submit();
await resource.update({ filterByTk, values: form.values });
// refresh();
message.success('保存成功');
},
};
};
export const useMoveAction = () => {
const { resource } = useResourceContext();
const { refresh } = useResourceActionContext();
return {
async move(from, to) {
await resource.move({
sourceId: from.id,
targetId: to.id,
});
refresh();
},
};
};
export const useUpdateAction = () => {
const form = useForm();
const ctx = useActionContext();
const { refresh } = useResourceActionContext();
const { resource, targetKey } = useResourceContext();
const { [targetKey]: filterByTk } = useRecord();
return {
async run() {
await form.submit();
await resource.update({ filterByTk, values: form.values });
ctx.setVisible(false);
await form.reset();
refresh();
},
};
};
export const useDestroyAction = () => {
const { refresh } = useResourceActionContext();
const { resource, targetKey } = useResourceContext();
const { [targetKey]: filterByTk } = useRecord();
return {
async run() {
await resource.destroy({ filterByTk });
refresh();
},
};
};
export const useBulkDestroyAction = () => {
const { state, setState, refresh } = useResourceActionContext();
const { resource, targetKey } = useResourceContext();
return {
async run() {
await resource.destroy({
filterByTk: state?.selectedRowKeys || [],
});
setState?.({ selectedRowKeys: [] });
refresh();
},
};
};
export const useUpdateCollectionActionAndRefreshCM = (options) => {
const { refreshCM } = useCollectionManager();
const form = useForm();
const ctx = useActionContext();
const { refresh } = useResourceActionContext();
const { resource, targetKey } = useResourceContext();
const { [targetKey]: filterByTk } = useRecord();
return {
async run() {
await form.submit();
await resource.update({ filterByTk, values: omit(form.values, ['fields']) });
ctx.setVisible(false);
await form.reset();
refresh();
await refreshCM();
},
};
};
export const useValuesFromRecord = (options) => {
const record = useRecord();
const result = useRequest(() => Promise.resolve({ data: record }), {
...options,
manual: true,
});
const ctx = useActionContext();
useEffect(() => {
if (ctx.visible) {
result.run();
}
}, [ctx.visible]);
return result;
};
export const useValuesFromRA = (options) => {
const ctx = useResourceActionContext();
return useRequest(() => Promise.resolve(ctx.data), {
...options,
refreshDeps: [ctx.data],
});
};
export const useCreateActionAndRefreshCM = () => {
const { run } = useCreateAction();
const { refreshCM } = useCollectionManager();
return {
async run() {
await run();
await refreshCM();
},
};
};
export const useUpdateActionAndRefreshCM = () => {
const { run } = useUpdateAction();
const { refreshCM } = useCollectionManager();
return {
async run() {
await run();
await refreshCM();
},
};
};
export const useDestroyActionAndRefreshCM = () => {
const { run } = useDestroyAction();
const { refreshCM } = useCollectionManager();
return {
async run() {
await run();
await refreshCM();
},
};
};
export const useBulkDestroyActionAndRefreshCM = () => {
const { run } = useBulkDestroyAction();
const { refreshCM } = useCollectionManager();
return {
async run() {
await run();
await refreshCM();
},
};
};
export const useFilterActionProps = () => {
const { collection } = useResourceContext();
const options = useFilterFieldOptions(collection.fields);
const service = useResourceActionContext();
return useFilterFieldProps({ options, params: service.params, service });
};