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 { CalendarContext, ToolbarContext } from './context';
|
||||
import { Event } from './Event';
|
||||
import { Filter } from './Filter';
|
||||
import { Nav } from './Nav';
|
||||
import './style.less';
|
||||
import { Title } from './Title';
|
||||
@ -182,5 +181,3 @@ Calendar.Today = Today;
|
||||
Calendar.Nav = Nav;
|
||||
|
||||
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 './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 { isPg, isMySQL } from './utils';
|
||||
|
||||
const getFieldName = (ctx) => {
|
||||
const fieldName = ctx.fieldName;
|
||||
@ -38,18 +39,6 @@ const emptyQuery = (ctx, operator: '=' | '>') => {
|
||||
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 {
|
||||
$match(value, ctx) {
|
||||
const fieldName = getFieldName(ctx);
|
||||
|
@ -3,4 +3,5 @@ export default {
|
||||
...require('./date').default,
|
||||
...require('./array').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