mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 05:36:05 +00:00
feat: date-only operators (#50)
* feat: date-only operators * feat: add opposite operators * fix: use moment to parse date string * fix: remove additional moment dependency. * modify date filter operators Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
d74eda3f23
commit
435cd9a7c9
@ -171,12 +171,12 @@ const OP_MAP = {
|
||||
{label: '为空', value: '$null'},
|
||||
],
|
||||
datetime: [
|
||||
{label: '等于', value: 'eq', selected: true},
|
||||
{label: '不等于', value: 'neq'},
|
||||
{label: '大于', value: 'gt'},
|
||||
{label: '大于等于', value: 'gte'},
|
||||
{label: '小于', value: 'lt'},
|
||||
{label: '小于等于', value: 'lte'},
|
||||
{label: '等于', value: '$dateOn', selected: true},
|
||||
{label: '不等于', value: '$dateNotOn'},
|
||||
{label: '早于', value: '$dateBefore'},
|
||||
{label: '晚于', value: '$dateAfter'},
|
||||
{label: '不早于', value: '$dateNotBefore'},
|
||||
{label: '不晚于', value: '$dateNotAfter'},
|
||||
// {label: '介于', value: 'between'},
|
||||
{label: '非空', value: '$notNull'},
|
||||
{label: '为空', value: '$null'},
|
||||
@ -257,15 +257,20 @@ const controls = {
|
||||
function DateControl(props: any) {
|
||||
const { field, value, onChange, ...restProps } = props;
|
||||
let format = field.dateFormat;
|
||||
if (field.showTime) {
|
||||
format += ` ${field.timeFormat}`;
|
||||
}
|
||||
// if (field.showTime) {
|
||||
// format += ` ${field.timeFormat}`;
|
||||
// }
|
||||
const m = moment(value, format);
|
||||
return (
|
||||
<DatePicker format={format} showTime={field.showTime} value={m.isValid() ? m : null} onChange={(value) => {
|
||||
onChange(value ? value.format(field.showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD') : null)
|
||||
<DatePicker format={format} value={m.isValid() ? m : null} onChange={(value) => {
|
||||
onChange(value ? value.format('YYYY-MM-DD') : null)
|
||||
}}/>
|
||||
);
|
||||
// return (
|
||||
// <DatePicker format={format} showTime={field.showTime} value={m.isValid() ? m : null} onChange={(value) => {
|
||||
// onChange(value ? value.format(field.showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD') : null)
|
||||
// }}/>
|
||||
// );
|
||||
}
|
||||
|
||||
function TimeControl(props: any) {
|
||||
|
@ -4,8 +4,7 @@
|
||||
"description": "",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"scripts": {
|
||||
},
|
||||
"scripts": {},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bcrypt": "^5.0.0",
|
||||
|
@ -24,7 +24,7 @@ const config = {
|
||||
},
|
||||
},
|
||||
},
|
||||
logging: process.env.DB_LOG_SQL === 'on'
|
||||
logging: process.env.DB_LOG_SQL === 'on' ? console.log : false
|
||||
};
|
||||
|
||||
export function getDatabase() {
|
||||
|
197
packages/database/src/__tests__/utils/op.test.ts
Normal file
197
packages/database/src/__tests__/utils/op.test.ts
Normal file
@ -0,0 +1,197 @@
|
||||
import { Op } from 'sequelize';
|
||||
import Database from '../../database';
|
||||
import { toWhere } from '../../utils';
|
||||
import { getDatabase } from '..';
|
||||
|
||||
describe('utils.toWhere', () => {
|
||||
let db: Database;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = getDatabase();
|
||||
|
||||
db.table({
|
||||
name: 'users',
|
||||
fields: [
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'posts',
|
||||
}
|
||||
],
|
||||
});
|
||||
db.table({
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'title'
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'user',
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await db.sync({ force: true });
|
||||
|
||||
const Post = db.getModel('posts');
|
||||
await Post.bulkCreate(Array(5).fill(null).map((_, i) => ({
|
||||
title: `title${i}`,
|
||||
created_at: new Date(2020, 11, 29 + i)
|
||||
})));
|
||||
});
|
||||
|
||||
afterEach(async () => await db.close());
|
||||
|
||||
describe('date', () => {
|
||||
it('$dateOn', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateOn': '2020-12-31'
|
||||
})
|
||||
});
|
||||
expect(posts[0].created_at).toEqual(new Date(2020, 11,31));
|
||||
});
|
||||
|
||||
it('$dateNotOn', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateNotOn': '2020-12-31'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(4);
|
||||
});
|
||||
|
||||
it('Op.$dateBefore', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateBefore': '2020-12-29'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(0);
|
||||
});
|
||||
|
||||
it('Op.$dateBefore', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateBefore': '2021-01-02'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(4);
|
||||
});
|
||||
|
||||
it('Op.$dateBefore', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateBefore': '2021-01-03'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(5);
|
||||
});
|
||||
|
||||
it('Op.$dateAfter', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateAfter': '2021-01-03'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(0);
|
||||
});
|
||||
|
||||
it('Op.$dateAfter', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateAfter': '2021-01-03'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(0);
|
||||
});
|
||||
|
||||
it('Op.$dateAfter', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateAfter': '2020-12-29'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(4);
|
||||
});
|
||||
|
||||
it('Op.$dateNotBefore', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateNotBefore': '2020-12-29'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(5);
|
||||
});
|
||||
|
||||
it('Op.$dateNotAfter', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateNotAfter': '2020-12-29'
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(1);
|
||||
});
|
||||
|
||||
it('Op.$dateBetween', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateBetween': ['2020-12-29', '2021-01-01']
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(4);
|
||||
});
|
||||
|
||||
it('Op.$dateBetween', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateBetween': ['2020-12-28', '2020-12-29']
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(1);
|
||||
});
|
||||
|
||||
it('Op.$dateBetween', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateBetween': ['2021-01-03', '2021-01-04']
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(0);
|
||||
});
|
||||
|
||||
it('Op.$dateNotBetween', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateNotBetween': ['2020-12-28', '2020-12-29']
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(4);
|
||||
});
|
||||
|
||||
it('Op.$dateNotBetween', async () => {
|
||||
const Post = db.getModel('posts');
|
||||
const posts = await Post.findAll({
|
||||
where: toWhere({
|
||||
'created_at.$dateNotBetween': ['2020-12-28', '2021-01-04']
|
||||
})
|
||||
});
|
||||
expect(posts.length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,4 +1,5 @@
|
||||
import { Op, Utils, Sequelize } from 'sequelize';
|
||||
import moment, { MomentInput } from 'moment';
|
||||
|
||||
function toArray(value: any): any[] {
|
||||
if (value == null) {
|
||||
@ -7,6 +8,14 @@ function toArray(value: any): any[] {
|
||||
return Array.isArray(value) ? value : [value];
|
||||
}
|
||||
|
||||
function stringToDate(value: string): Date {
|
||||
return moment(value).toDate();
|
||||
}
|
||||
|
||||
function getNextDay(value: MomentInput): Date {
|
||||
return moment(value).add(1, 'd').toDate();
|
||||
}
|
||||
|
||||
const op = new Map<string, typeof Op | Function>();
|
||||
|
||||
// Sequelize 内置
|
||||
@ -56,6 +65,25 @@ op.set('$endsWith', (value: string) => ({ [Op.iLike]: `%${value}` }));
|
||||
// 不以之结束
|
||||
op.set('$notEndsWith', (value: string) => ({ [Op.notILike]: `%${value}` }));
|
||||
|
||||
// 仅日期
|
||||
|
||||
// 在某日
|
||||
op.set('$dateOn', (value: string) => ({ [Op.and]: [{ [Op.gte]: stringToDate(value) }, { [Op.lt]: getNextDay(value) }] }));
|
||||
// 不在某日
|
||||
op.set('$dateNotOn', (value: string) => ({ [Op.or]: [{ [Op.lt]: stringToDate(value) }, { [Op.gte]: getNextDay(value) }] }));
|
||||
// 某日前
|
||||
op.set('$dateBefore', (value: string) => ({ [Op.lt]: stringToDate(value) }));
|
||||
// 某日后
|
||||
op.set('$dateAfter', (value: string) => ({ [Op.gte]: getNextDay(value) }));
|
||||
// 不早于(含当天)
|
||||
op.set('$dateNotBefore', (value: string) => ({ [Op.gte]: stringToDate(value) }));
|
||||
// 不晚于(含当天)
|
||||
op.set('$dateNotAfter', (value: string) => ({ [Op.lt]: getNextDay(value) }));
|
||||
// 在期间
|
||||
op.set('$dateBetween', ([from, to]: string[]) => ({ [Op.and]: [{ [Op.gte]: stringToDate(from) }, { [Op.lt]: getNextDay(to) }] }));
|
||||
// 不在期间
|
||||
op.set('$dateNotBetween', ([from, to]: string[]) => ({ [Op.or]: [{ [Op.lt]: stringToDate(from) }, { [Op.gte]: getNextDay(to) }] }));
|
||||
|
||||
// 多选(JSON)类型
|
||||
|
||||
// 包含组中任意值(命名来源:`Array.prototype.some`)
|
||||
|
@ -351,7 +351,7 @@ export const createdAt = {
|
||||
type: 'date',
|
||||
// name: 'created_at',
|
||||
field: 'created_at',
|
||||
showTime: true,
|
||||
showTime: false,
|
||||
dateFormat: 'YYYY-MM-DD',
|
||||
timeFormat: 'HH:mm:ss',
|
||||
required: true,
|
||||
@ -370,7 +370,7 @@ export const updatedAt = {
|
||||
type: 'date',
|
||||
// name: 'updated_at',
|
||||
field: 'updated_at',
|
||||
showTime: true,
|
||||
showTime: false,
|
||||
dateFormat: 'YYYY-MM-DD',
|
||||
timeFormat: 'HH:mm:ss',
|
||||
required: true,
|
||||
|
Loading…
Reference in New Issue
Block a user