feat: string operators (#215)
* feat: string operators * fix: remove filter Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
a96f76b87a
commit
aa1c84e72a
@ -11,7 +11,6 @@ import { i18n } from '../../../i18n';
|
|||||||
import { ActionBar, ActionContext } from '../action';
|
import { ActionBar, ActionContext } from '../action';
|
||||||
import { CalendarContext, ToolbarContext } from './context';
|
import { CalendarContext, ToolbarContext } from './context';
|
||||||
import { Event } from './Event';
|
import { Event } from './Event';
|
||||||
import { Filter } from './Filter';
|
|
||||||
import { Nav } from './Nav';
|
import { Nav } from './Nav';
|
||||||
import './style.less';
|
import './style.less';
|
||||||
import { Title } from './Title';
|
import { Title } from './Title';
|
||||||
@ -182,5 +181,3 @@ Calendar.Today = Today;
|
|||||||
Calendar.Nav = Nav;
|
Calendar.Nav = Nav;
|
||||||
|
|
||||||
Calendar.ViewSelect = ViewSelect;
|
Calendar.ViewSelect = ViewSelect;
|
||||||
|
|
||||||
Calendar.Filter = Filter;
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
import { createForm } from '@formily/core';
|
|
||||||
import { observer, useFieldSchema } from '@formily/react';
|
|
||||||
import flatten from 'flat';
|
|
||||||
import React, { useMemo, useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { SchemaComponent } from '../../core';
|
|
||||||
import { useDesignable } from '../../hooks';
|
|
||||||
import { useCompile } from '../../hooks/useCompile';
|
|
||||||
import { FilterContext } from '../filter/context';
|
|
||||||
|
|
||||||
export const Filter = observer((props: any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const compile = useCompile();
|
|
||||||
const { properties } = props;
|
|
||||||
const { DesignableBar } = useDesignable();
|
|
||||||
const filedSchema = useFieldSchema();
|
|
||||||
const form = useMemo(() => createForm(), []);
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const obj = flatten(form.values.filter || {});
|
|
||||||
const count = Object.values(obj).filter((i) => (Array.isArray(i) ? i.length : i)).length;
|
|
||||||
const icon = props.icon || 'FilterOutlined';
|
|
||||||
filedSchema.mapProperties((p) => {
|
|
||||||
properties[p.name] = p;
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<FilterContext.Provider value={{ visible, setVisible }}>
|
|
||||||
<SchemaComponent
|
|
||||||
schema={{
|
|
||||||
type: 'void',
|
|
||||||
properties: {
|
|
||||||
filter: {
|
|
||||||
type: 'object',
|
|
||||||
title: t('Filter'),
|
|
||||||
'x-component': 'Filter.Action',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FilterContext.Provider>
|
|
||||||
);
|
|
||||||
});
|
|
@ -1,2 +1,3 @@
|
|||||||
export * from './Calendar';
|
export * from './Calendar';
|
||||||
export * from './context';
|
export * from './context';
|
||||||
|
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
import Database, { Collection, mockDatabase } from '@nocobase/database';
|
||||||
|
|
||||||
|
describe('string operator', () => {
|
||||||
|
let db: Database;
|
||||||
|
|
||||||
|
let User: Collection;
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await db.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
db = mockDatabase({});
|
||||||
|
|
||||||
|
await db.clean({ drop: true });
|
||||||
|
|
||||||
|
User = db.collection({
|
||||||
|
name: 'users',
|
||||||
|
fields: [{ type: 'string', name: 'name' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sync({
|
||||||
|
force: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should query with include operator', async () => {
|
||||||
|
const u1 = await db.getRepository('users').create({
|
||||||
|
values: {
|
||||||
|
name: 'names of u1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const u1Res = await db.getRepository('users').findOne({
|
||||||
|
filter: {
|
||||||
|
'name.$includes': 'u1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(u1Res.get('id')).toEqual(u1.get('id'));
|
||||||
|
});
|
||||||
|
});
|
@ -1,4 +1,5 @@
|
|||||||
import { Op, Sequelize } from 'sequelize';
|
import { Op, Sequelize } from 'sequelize';
|
||||||
|
import { isPg, isMySQL } from './utils';
|
||||||
|
|
||||||
const getFieldName = (ctx) => {
|
const getFieldName = (ctx) => {
|
||||||
const fieldName = ctx.fieldName;
|
const fieldName = ctx.fieldName;
|
||||||
@ -38,18 +39,6 @@ const emptyQuery = (ctx, operator: '=' | '>') => {
|
|||||||
return `(select ${ifNull}(${funcName}(${fieldName}), 0) ${operator} 0)`;
|
return `(select ${ifNull}(${funcName}(${fieldName}), 0) ${operator} 0)`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDialect = (ctx) => {
|
|
||||||
return ctx.db.sequelize.getDialect();
|
|
||||||
};
|
|
||||||
|
|
||||||
const isPg = (ctx) => {
|
|
||||||
return getDialect(ctx) === 'postgres';
|
|
||||||
};
|
|
||||||
|
|
||||||
const isMySQL = (ctx) => {
|
|
||||||
return getDialect(ctx) === 'mysql';
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
$match(value, ctx) {
|
$match(value, ctx) {
|
||||||
const fieldName = getFieldName(ctx);
|
const fieldName = getFieldName(ctx);
|
||||||
|
@ -3,4 +3,5 @@ export default {
|
|||||||
...require('./date').default,
|
...require('./date').default,
|
||||||
...require('./array').default,
|
...require('./array').default,
|
||||||
...require('./empty').default,
|
...require('./empty').default,
|
||||||
|
...require('./string').default,
|
||||||
};
|
};
|
||||||
|
40
packages/database/src/operators/string.ts
Normal file
40
packages/database/src/operators/string.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { isPg } from './utils';
|
||||||
|
import { Op } from 'sequelize';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
$includes(value, ctx) {
|
||||||
|
return {
|
||||||
|
[isPg(ctx) ? Op.iLike : Op.like]: `%${value}%`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
$notIncludes(value, ctx) {
|
||||||
|
return {
|
||||||
|
[isPg(ctx) ? Op.notILike : Op.notLike]: `%${value}%`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
$startsWith(value, ctx) {
|
||||||
|
return {
|
||||||
|
[isPg(ctx) ? Op.iLike : Op.like]: `${value}%`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
$notStartsWith(value, ctx) {
|
||||||
|
return {
|
||||||
|
[isPg(ctx) ? Op.notILike : Op.notLike]: `${value}%`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
$endWith(value, ctx) {
|
||||||
|
return {
|
||||||
|
[isPg(ctx) ? Op.iLike : Op.like]: `%${value}`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
$notEndWith(value, ctx) {
|
||||||
|
return {
|
||||||
|
[isPg(ctx) ? Op.notILike : Op.notLike]: `%${value}`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
13
packages/database/src/operators/utils.ts
Normal file
13
packages/database/src/operators/utils.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const getDialect = (ctx) => {
|
||||||
|
return ctx.db.sequelize.getDialect();
|
||||||
|
};
|
||||||
|
|
||||||
|
const isPg = (ctx) => {
|
||||||
|
return getDialect(ctx) === 'postgres';
|
||||||
|
};
|
||||||
|
|
||||||
|
const isMySQL = (ctx) => {
|
||||||
|
return getDialect(ctx) === 'mysql';
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getDialect, isPg, isMySQL };
|
Loading…
Reference in New Issue
Block a user