feat: improve field interface filterable parameter

This commit is contained in:
chenos 2022-03-03 15:21:27 +08:00
parent d4bd033917
commit 3ff16e70c0
25 changed files with 254 additions and 136 deletions

View File

@ -27,33 +27,45 @@ export const useCancelFilterAction = () => {
}; };
export const useCollectionFilterOptions = (collectionName: string) => { export const useCollectionFilterOptions = (collectionName: string) => {
const { getCollection, getInterface } = useCollectionManager(); const { getCollectionFields, getInterface } = useCollectionManager();
const options = []; const fields = getCollectionFields(collectionName);
const collection = getCollection(collectionName);
const fields = collection?.fields || [];
const field2option = (field) => { const field2option = (field) => {
if (!field.interface) { if (!field.interface) {
return; return;
} }
const fieldInterface = getInterface(field.interface); const fieldInterface = getInterface(field.interface);
if (!fieldInterface.operators) { if (!fieldInterface.filterable) {
return; return;
} }
const { nested, children, operators } = fieldInterface.filterable;
const option = { const option = {
name: field.name, name: field.name,
title: field?.uiSchema?.title || field.name, title: field?.uiSchema?.title || field.name,
schema: field?.uiSchema, schema: field?.uiSchema,
operators: fieldInterface.operators || [], operators: operators || [],
}; };
if (children?.length) {
option['children'] = children;
}
if (nested) {
const targetFields = getCollectionFields(field.target);
const options = getOptions(targetFields);
option['children'] = option['children'] || [];
option['children'].push(...options);
}
return option; return option;
}; };
fields.forEach((field) => { const getOptions = (fields) => {
const option = field2option(field); const options = [];
if (option) { fields.forEach((field) => {
options.push(option); const option = field2option(field);
} if (option) {
}); options.push(option);
return options; }
});
return options;
};
return getOptions(fields);
}; };
export const useFilterDataSource = (options) => { export const useFilterDataSource = (options) => {

View File

@ -15,6 +15,10 @@ export const useCollectionManager = () => {
getCollection(name: string) { getCollection(name: string) {
return collections?.find((collection) => collection.name === name); return collections?.find((collection) => collection.name === name);
}, },
getCollectionFields(name: string) {
const collection = collections?.find((collection) => collection.name === name);
return collection?.fields || [];
},
getInterface(name: string) { getInterface(name: string) {
return interfaces[name] ? clone(interfaces[name]) : null; return interfaces[name] ? clone(interfaces[name]) : null;
}, },

View File

@ -48,4 +48,21 @@ export const attachment: IField = {
default: true, default: true,
}, },
}, },
filterable: {
children: [
{
name: 'filename',
title: '{{t("Filename")}}',
operators: [
{ label: 'empty', value: '$empty' },
{ label: 'notEmpty', value: '$notEmpty' },
],
schema: {
title: '{{t("Filename")}}',
type: 'string',
'x-component': 'Input',
},
},
],
},
}; };

View File

@ -1,4 +1,4 @@
import { defaultProps } from './properties'; import { defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const checkbox: IField = { export const checkbox: IField = {
@ -18,8 +18,7 @@ export const checkbox: IField = {
properties: { properties: {
...defaultProps, ...defaultProps,
}, },
operators: [ filterable: {
{ label: '{{t("Yes")}}', value: '$isTruly', selected: true, noValue: true }, operators: operators.boolean,
{ label: '{{t("No")}}', value: '$isFalsy', noValue: true }, },
],
}; };

View File

@ -1,4 +1,4 @@
import { dataSource, defaultProps } from './properties'; import { dataSource, defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const checkboxGroup: IField = { export const checkboxGroup: IField = {
@ -20,4 +20,7 @@ export const checkboxGroup: IField = {
...defaultProps, ...defaultProps,
'uiSchema.enum': dataSource, 'uiSchema.enum': dataSource,
}, },
filterable: {
operators: operators.array,
},
}; };

View File

@ -1,5 +1,5 @@
import { uid } from '@formily/shared'; import { uid } from '@formily/shared';
import { defaultProps } from './properties'; import { defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const chinaRegion: IField = { export const chinaRegion: IField = {
@ -74,5 +74,18 @@ export const chinaRegion: IField = {
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
}, },
}, },
operators: [{ label: '{{t("is")}}', value: 'code.$in' }], filterable: {
children: [
{
name: 'name',
title: '名称',
operators: operators.string,
schema: {
title: '名称',
type: 'string',
'x-component': 'Input',
},
},
],
},
}; };

View File

@ -1,4 +1,4 @@
import { dateTimeProps, defaultProps } from './properties'; import { dateTimeProps, defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const createdAt: IField = { export const createdAt: IField = {
@ -24,4 +24,7 @@ export const createdAt: IField = {
...defaultProps, ...defaultProps,
...dateTimeProps, ...dateTimeProps,
}, },
filterable: {
operators: operators.datetime,
},
}; };

View File

@ -1,4 +1,4 @@
import { defaultProps } from './properties'; import { defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const createdBy: IField = { export const createdBy: IField = {
@ -29,4 +29,18 @@ export const createdBy: IField = {
properties: { properties: {
...defaultProps, ...defaultProps,
}, },
filterable: {
children: [
{
name: 'nickname',
title: '{{t("Nickname")}}',
operators: operators.string,
schema: {
title: '{{t("Nickname")}}',
type: 'string',
'x-component': 'Input',
},
},
],
},
}; };

View File

@ -1,4 +1,4 @@
import { dateTimeProps, defaultProps } from './properties'; import { dateTimeProps, defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const datetime: IField = { export const datetime: IField = {
@ -24,14 +24,7 @@ export const datetime: IField = {
...defaultProps, ...defaultProps,
...dateTimeProps, ...dateTimeProps,
}, },
operators: [ filterable: {
{ label: "{{ t('is') }}", value: '$dateOn', selected: true }, operators: operators.datetime,
{ label: "{{ t('is not') }}", value: '$dateNotOn' }, },
{ label: "{{ t('is before') }}", value: '$dateBefore' },
{ label: "{{ t('is after') }}", value: '$dateAfter' },
{ label: "{{ t('is on or after') }}", value: '$dateNotBefore' },
{ label: "{{ t('is on or before') }}", value: '$dateNotAfter' },
{ label: "{{ t('is empty') }}", value: '$null', noValue: true },
{ label: "{{ t('is not empty') }}", value: '$notNull', noValue: true },
],
}; };

View File

@ -1,5 +1,4 @@
import { input } from './input'; import { defaultProps, operators } from './properties';
import { defaultProps } from './properties';
import { IField } from './types'; import { IField } from './types';
export const email: IField = { export const email: IField = {
@ -22,5 +21,7 @@ export const email: IField = {
properties: { properties: {
...defaultProps, ...defaultProps,
}, },
operators: input.operators, filterable: {
operators: operators.string,
},
}; };

View File

@ -1,4 +1,4 @@
import { defaultProps } from './properties'; import { defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const input: IField = { export const input: IField = {
@ -19,12 +19,7 @@ export const input: IField = {
properties: { properties: {
...defaultProps, ...defaultProps,
}, },
operators: [ filterable: {
{ label: '{{t("contains")}}', value: '$includes', selected: true }, operators: operators.string,
{ label: '{{t("does not contain")}}', value: '$notIncludes' }, },
{ label: '{{t("is")}}', value: '$eq' },
{ label: '{{t("is not")}}', value: '$ne' },
{ label: '{{t("is empty")}}', value: '$empty', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notEmpty', noValue: true },
],
}; };

View File

@ -69,4 +69,7 @@ export const linkTo: IField = {
'x-component': 'Checkbox', 'x-component': 'Checkbox',
}, },
}, },
filterable: {
nested: true,
},
}; };

View File

@ -1,4 +1,4 @@
import { dataSource, defaultProps } from './properties'; import { dataSource, defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const multipleSelect: IField = { export const multipleSelect: IField = {
@ -26,29 +26,7 @@ export const multipleSelect: IField = {
...defaultProps, ...defaultProps,
'uiSchema.enum': dataSource, 'uiSchema.enum': dataSource,
}, },
operators: [ filterable: {
{ operators: operators.array,
label: '{{t("is")}}', },
value: '$match',
selected: true,
schema: { 'x-component': 'Select' },
},
{
label: '{{t("is not")}}',
value: '$notMatch',
schema: { 'x-component': 'Select' },
},
{
label: '{{t("contains")}}',
value: '$anyOf',
schema: { 'x-component': 'Select' },
},
{
label: '{{t("does not contain")}}',
value: '$noneOf',
schema: { 'x-component': 'Select' },
},
{ label: '{{t("is empty")}}', value: '$empty', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notEmpty', noValue: true },
],
}; };

View File

@ -1,4 +1,4 @@
import { defaultProps } from './properties'; import { defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const number: IField = { export const number: IField = {
@ -39,14 +39,7 @@ export const number: IField = {
], ],
}, },
}, },
operations: [ filterable: {
{ label: '{{t("=")}}', value: '$eq', selected: true }, operators: operators.number,
{ label: '{{t("≠")}}', value: '$ne' }, },
{ label: '{{t(">")}}', value: '$gt' },
{ label: '{{t("≥")}}', value: '$gte' },
{ label: '{{t("<")}}', value: '$lt' },
{ label: '{{t("≤")}}', value: '$lte' },
{ label: '{{t("is empty")}}', value: '$null', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notNull', noValue: true },
],
}; };

View File

@ -1,5 +1,4 @@
import { number } from './number'; import { defaultProps, operators } from './properties';
import { defaultProps } from './properties';
import { IField } from './types'; import { IField } from './types';
export const percent: IField = { export const percent: IField = {
@ -43,5 +42,7 @@ export const percent: IField = {
], ],
}, },
}, },
operators: number.operators, filterable: {
operators: operators.number,
},
}; };

View File

@ -1,5 +1,4 @@
import { input } from './input'; import { defaultProps, operators } from './properties';
import { defaultProps } from './properties';
import { IField } from './types'; import { IField } from './types';
export const phone: IField = { export const phone: IField = {
@ -24,5 +23,7 @@ export const phone: IField = {
properties: { properties: {
...defaultProps, ...defaultProps,
}, },
operators: input.operators, filterable: {
operators: operators.string,
},
}; };

View File

@ -196,3 +196,6 @@ export const defaultProps = {
}, },
type, type,
}; };
export * as operators from './operators';

View File

@ -0,0 +1,100 @@
export const string = [
{ label: '{{t("contains")}}', value: '$includes', selected: true },
{ label: '{{t("does not contain")}}', value: '$notIncludes' },
{ label: '{{t("is")}}', value: '$eq' },
{ label: '{{t("is not")}}', value: '$ne' },
{ label: '{{t("is empty")}}', value: '$empty', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notEmpty', noValue: true },
];
export const array = [
{
label: '{{t("is")}}',
value: '$match',
selected: true,
schema: { 'x-component': 'Select' },
},
{
label: '{{t("is not")}}',
value: '$notMatch',
schema: { 'x-component': 'Select' },
},
{
label: '{{t("contains")}}',
value: '$anyOf',
schema: { 'x-component': 'Select' },
},
{
label: '{{t("does not contain")}}',
value: '$noneOf',
schema: { 'x-component': 'Select' },
},
{ label: '{{t("is empty")}}', value: '$empty', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notEmpty', noValue: true },
];
export const datetime = [
{ label: "{{ t('is') }}", value: '$dateOn', selected: true },
{ label: "{{ t('is not') }}", value: '$dateNotOn' },
{ label: "{{ t('is before') }}", value: '$dateBefore' },
{ label: "{{ t('is after') }}", value: '$dateAfter' },
{ label: "{{ t('is on or after') }}", value: '$dateNotBefore' },
{ label: "{{ t('is on or before') }}", value: '$dateNotAfter' },
{ label: "{{ t('is empty') }}", value: '$null', noValue: true },
{ label: "{{ t('is not empty') }}", value: '$notNull', noValue: true },
];
export const number = [
{ label: '{{t("=")}}', value: '$eq', selected: true },
{ label: '{{t("≠")}}', value: '$ne' },
{ label: '{{t(">")}}', value: '$gt' },
{ label: '{{t("≥")}}', value: '$gte' },
{ label: '{{t("<")}}', value: '$lt' },
{ label: '{{t("≤")}}', value: '$lte' },
{ label: '{{t("is empty")}}', value: '$empty', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notEmpty', noValue: true },
];
export const enumType = [
{
label: '{{t("is")}}',
value: '$eq',
selected: true,
schema: { 'x-component': 'Select' },
},
{
label: '{{t("is not")}}',
value: '$ne',
schema: { 'x-component': 'Select' },
},
{
label: '{{t("contains")}}',
value: '$in',
schema: {
'x-component': 'Select',
'x-component-props': { mode: 'tags' },
},
},
{
label: '{{t("does not contain")}}',
value: '$notIn',
schema: {
'x-component': 'Select',
'x-component-props': { mode: 'tags' },
},
},
{ label: '{{t("is empty")}}', value: '$empty', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notEmpty', noValue: true },
];
export const time = [
{ label: '{{t("is")}}', value: '$eq', selected: true },
{ label: '{{t("is not")}}', value: '$neq' },
{ label: '{{t("is empty")}}', value: '$null', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notNull', noValue: true },
];
export const boolean = [
{ label: '{{t("Yes")}}', value: '$isTruly', selected: true, noValue: true },
{ label: '{{t("No")}}', value: '$isFalsy', noValue: true },
];

View File

@ -1,5 +1,4 @@
import { dataSource, defaultProps } from './properties'; import { dataSource, defaultProps, operators } from './properties';
import { select } from './select';
import { IField } from './types'; import { IField } from './types';
export const radioGroup: IField = { export const radioGroup: IField = {
@ -21,5 +20,7 @@ export const radioGroup: IField = {
...defaultProps, ...defaultProps,
'uiSchema.enum': dataSource, 'uiSchema.enum': dataSource,
}, },
operators: select.operators, filterable: {
operators: operators.enumType,
},
}; };

View File

@ -1,4 +1,4 @@
import { dataSource, defaultProps } from './properties'; import { dataSource, defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const select: IField = { export const select: IField = {
@ -21,35 +21,7 @@ export const select: IField = {
...defaultProps, ...defaultProps,
'uiSchema.enum': dataSource, 'uiSchema.enum': dataSource,
}, },
operators: [ filterable: {
{ operators: operators.enumType,
label: '{{t("is")}}', },
value: '$eq',
selected: true,
schema: { 'x-component': 'Select' },
},
{
label: '{{t("is not")}}',
value: '$ne',
schema: { 'x-component': 'Select' },
},
{
label: '{{t("contains")}}',
value: '$in',
schema: {
'x-component': 'Select',
'x-component-props': { mode: 'tags' },
},
},
{
label: '{{t("does not contain")}}',
value: '$notIn',
schema: {
'x-component': 'Select',
'x-component-props': { mode: 'tags' },
},
},
{ label: '{{t("is empty")}}', value: '$empty', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notEmpty', noValue: true },
],
}; };

View File

@ -9,7 +9,6 @@ export const subTable: IField = {
order: 2, order: 2,
title: '{{t("Sub-table")}}', title: '{{t("Sub-table")}}',
isAssociation: true, isAssociation: true,
disabled: true,
default: { default: {
type: 'hasMany', type: 'hasMany',
// name, // name,

View File

@ -1,4 +1,4 @@
import { defaultProps } from './properties'; import { defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const time: IField = { export const time: IField = {
@ -36,10 +36,7 @@ export const time: IField = {
], ],
}, },
}, },
operators: [ filterable: {
{ label: '{{t("is")}}', value: '$eq', selected: true }, operators: operators.time,
{ label: '{{t("is not")}}', value: '$neq' }, },
{ label: '{{t("is empty")}}', value: '$null', noValue: true },
{ label: '{{t("is not empty")}}', value: '$notNull', noValue: true },
],
}; };

View File

@ -9,5 +9,6 @@ interface IDefault {
export interface IField extends ISchema { export interface IField extends ISchema {
default?: IDefault; default?: IDefault;
operators?: any[]; operators?: any[];
filterable?: any,
[key: string]: any; [key: string]: any;
} }

View File

@ -1,5 +1,4 @@
import { datetime } from './datetime'; import { dateTimeProps, defaultProps, operators } from './properties';
import { dateTimeProps, defaultProps } from './properties';
import { IField } from './types'; import { IField } from './types';
export const updatedAt: IField = { export const updatedAt: IField = {
@ -25,5 +24,7 @@ export const updatedAt: IField = {
...defaultProps, ...defaultProps,
...dateTimeProps, ...dateTimeProps,
}, },
operators: datetime.operators, filterable: {
operators: operators.datetime,
},
}; };

View File

@ -1,4 +1,4 @@
import { defaultProps } from './properties'; import { defaultProps, operators } from './properties';
import { IField } from './types'; import { IField } from './types';
export const updatedBy: IField = { export const updatedBy: IField = {
@ -28,4 +28,18 @@ export const updatedBy: IField = {
properties: { properties: {
...defaultProps, ...defaultProps,
}, },
filterable: {
children: [
{
name: 'nickname',
title: '{{t("Nickname")}}',
operators: operators.string,
schema: {
title: '{{t("Nickname")}}',
type: 'string',
'x-component': 'Input',
},
},
],
},
}; };