From 780ffd94dc4ec4482993e157a74e1715163311a9 Mon Sep 17 00:00:00 2001 From: Rakhee Singh Date: Fri, 8 Dec 2023 08:38:15 +0530 Subject: [PATCH] feat(core): added new filter for last n days (#5167) Co-authored-by: rakhee28 Co-authored-by: EYHN --- .../filter/filter-tag-translation.tsx | 2 + .../page-list/filter/literal-matcher.tsx | 37 ++++++++++++++++++- .../page-list/filter/logical/custom-type.ts | 4 ++ .../src/components/page-list/filter/vars.tsx | 20 +++++++++- packages/frontend/i18n/src/resources/en.json | 1 + .../frontend/i18n/src/resources/zh-Hans.json | 1 + 6 files changed, 62 insertions(+), 3 deletions(-) diff --git a/packages/frontend/component/src/components/page-list/filter/filter-tag-translation.tsx b/packages/frontend/component/src/components/page-list/filter/filter-tag-translation.tsx index 587ca00d75..1c3d8c27b6 100644 --- a/packages/frontend/component/src/components/page-list/filter/filter-tag-translation.tsx +++ b/packages/frontend/component/src/components/page-list/filter/filter-tag-translation.tsx @@ -19,6 +19,8 @@ const useFilterTag = ({ name }: FilterTagProps) => { return t['com.affine.filter.after'](); case 'before': return t['com.affine.filter.before'](); + case 'last': + return t['com.affine.filter.last'](); case 'is': return t['com.affine.filter.is'](); case 'is not empty': diff --git a/packages/frontend/component/src/components/page-list/filter/literal-matcher.tsx b/packages/frontend/component/src/components/page-list/filter/literal-matcher.tsx index 132fed81d5..6a4a77e1dc 100644 --- a/packages/frontend/component/src/components/page-list/filter/literal-matcher.tsx +++ b/packages/frontend/component/src/components/page-list/filter/literal-matcher.tsx @@ -1,11 +1,13 @@ import type { LiteralValue, Tag } from '@affine/env/filter'; import dayjs from 'dayjs'; -import type { ReactNode } from 'react'; +import { type ReactNode } from 'react'; +import Input from '../../../ui/input'; +import { Menu, MenuItem } from '../../../ui/menu'; import { AFFiNEDatePicker } from '../../date-picker'; import { FilterTag } from './filter-tag-translation'; import { inputStyle } from './index.css'; -import { tBoolean, tDate, tTag } from './logical/custom-type'; +import { tBoolean, tDate, tDateRange, tTag } from './logical/custom-type'; import { Matcher } from './logical/matcher'; import type { TType } from './logical/typesystem'; import { tArray, typesystem } from './logical/typesystem'; @@ -21,6 +23,37 @@ export const literalMatcher = new Matcher<{ return typesystem.isSubtype(type, target); }); +literalMatcher.register(tDateRange.create(), { + render: ({ value, onChange }) => ( + + (i ? onChange(parseInt(i)) : onChange(0))} + /> + {[1, 2, 3, 7, 14, 30].map(i => ( + { + // Handle the menu item click and update the value accordingly + onChange(i); + }} + > + {i} {i > 1 ? 'days' : 'day'} + + ))} + + } + > +
+ {value.toString()} {(value as number) > 1 ? 'days' : 'day'} +
+
+ ), +}); + literalMatcher.register(tBoolean.create(), { render: ({ value, onChange }) => (
({ name: 'Tag', supers: [], }); + +export const tDateRange = typesystem.defineData( + DataHelper.create<{ value: number }>('DateRange') +); diff --git a/packages/frontend/component/src/components/page-list/filter/vars.tsx b/packages/frontend/component/src/components/page-list/filter/vars.tsx index 8bb53ab57d..a1b36cf8b0 100644 --- a/packages/frontend/component/src/components/page-list/filter/vars.tsx +++ b/packages/frontend/component/src/components/page-list/filter/vars.tsx @@ -11,7 +11,7 @@ import type { ReactNode } from 'react'; import { MenuIcon, MenuItem, MenuSeparator } from '../../../ui/menu'; import { FilterTag } from './filter-tag-translation'; import * as styles from './index.css'; -import { tBoolean, tDate, tTag } from './logical/custom-type'; +import { tBoolean, tDate, tDateRange, tTag } from './logical/custom-type'; import { Matcher } from './logical/matcher'; import type { TFunction } from './logical/typesystem'; import { @@ -161,6 +161,24 @@ filterMatcher.register( } ); +filterMatcher.register( + tFunction({ + args: [tDate.create(), tDateRange.create()], + rt: tBoolean.create(), + }), + { + name: 'last', + defaultArgs: () => [30], // Default to the last 30 days + impl: (date, n) => { + if (typeof date !== 'number' || typeof n !== 'number') { + throw new Error('Argument type error: date and n must be numbers'); + } + const startDate = dayjs().subtract(n, 'day').startOf('day').valueOf(); + return date > startDate; + }, + } +); + filterMatcher.register( tFunction({ args: [tDate.create(), tDate.create()], diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json index 32aa077c25..4aa27db82a 100644 --- a/packages/frontend/i18n/src/resources/en.json +++ b/packages/frontend/i18n/src/resources/en.json @@ -608,6 +608,7 @@ "com.affine.filter": "Filter", "com.affine.filter.after": "after", "com.affine.filter.before": "before", + "com.affine.filter.last": "last", "com.affine.filter.contains all": "contains all", "com.affine.filter.contains one of": "contains one of", "com.affine.filter.does not contains all": "does not contains all", diff --git a/packages/frontend/i18n/src/resources/zh-Hans.json b/packages/frontend/i18n/src/resources/zh-Hans.json index 47833ee09c..54a6b9c7a7 100644 --- a/packages/frontend/i18n/src/resources/zh-Hans.json +++ b/packages/frontend/i18n/src/resources/zh-Hans.json @@ -593,6 +593,7 @@ "com.affine.filter": "筛选", "com.affine.filter.after": "晚于", "com.affine.filter.before": "早于", + "com.affine.filter.last": "最近", "com.affine.filter.contains all": "包含以下所有", "com.affine.filter.contains one of": "包含以下之一", "com.affine.filter.does not contains all": "不包含以下所有",