1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-15 01:28:30 +00:00

Resolve "Add new date filter types 'is within X days', 'is within X weeks' and 'is within X months'"

This commit is contained in:
Davide Silvestri 2023-05-18 12:38:53 +00:00
parent 85dcc341e0
commit 4b9be991cc
8 changed files with 602 additions and 38 deletions
backend
src/baserow/contrib/database
tests/baserow/contrib/database/view
changelog/entries/unreleased/feature
web-frontend
locales
modules/database
test/unit/database

View file

@ -285,6 +285,9 @@ class DatabaseConfig(AppConfig):
DateEqualsTodayViewFilterType,
DateEqualsYearsAgoViewFilterType,
DateEqualViewFilterType,
DateIsWithinXDaysViewFilterType,
DateIsWithinXMonthsViewFilterType,
DateIsWithinXWeeksViewFilterType,
DateNotEqualViewFilterType,
DoesntContainWordViewFilterType,
EmptyViewFilterType,
@ -326,6 +329,9 @@ class DatabaseConfig(AppConfig):
view_filter_type_registry.register(DateEqualsTodayViewFilterType())
view_filter_type_registry.register(DateBeforeTodayViewFilterType())
view_filter_type_registry.register(DateAfterTodayViewFilterType())
view_filter_type_registry.register(DateIsWithinXDaysViewFilterType())
view_filter_type_registry.register(DateIsWithinXWeeksViewFilterType())
view_filter_type_registry.register(DateIsWithinXMonthsViewFilterType())
view_filter_type_registry.register(DateEqualsDaysAgoViewFilterType())
view_filter_type_registry.register(DateEqualsMonthsAgoViewFilterType())
view_filter_type_registry.register(DateEqualsYearsAgoViewFilterType())

View file

@ -356,14 +356,17 @@ class TimezoneAwareDateViewFilterType(ViewFilterType):
return datetime_value.astimezone(timezone)
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[datetime, date]
self, field_name: str, aware_filter_date: Union[datetime, date], now: datetime
) -> Dict:
"""
Returns a dictionary that can be used to create a Q object.
:param field_name: The name of the field that should be used in the query.
:param aware_filter_date: The date that should be used to compare with the
field value.
:param field_name: The name of the field that should be used in the
query.
:param aware_filter_date: The date that should be used to compare with
the field value.
:param now: The current aware datetime that can be used to compare with
the field value.
"""
raise NotImplementedError()
@ -465,7 +468,9 @@ class TimezoneAwareDateViewFilterType(ViewFilterType):
query_dict = {
f"{field_name}__isnull": False, # makes `NotViewFilterTypeMixin` work with timezones
**self.get_filter_query_dict(query_field_name, filter_date),
**self.get_filter_query_dict(
query_field_name, filter_date, datetime.now(timezone)
),
}
return AnnotatedQ(annotation=annotation, q=query_dict)
@ -480,7 +485,7 @@ class DateEqualViewFilterType(TimezoneAwareDateViewFilterType):
type = "date_equal"
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {field_name: aware_filter_date}
@ -495,7 +500,7 @@ class DateBeforeViewFilterType(TimezoneAwareDateViewFilterType):
type = "date_before"
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict[str, Any]:
return {f"{field_name}__lt": aware_filter_date}
@ -510,7 +515,7 @@ class DateAfterViewFilterType(TimezoneAwareDateViewFilterType):
type = "date_after"
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict[str, Any]:
return {f"{field_name}__gt": aware_filter_date}
@ -570,7 +575,7 @@ class DateEqualsTodayViewFilterType(
return datetime.now(tz=timezone).date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {field_name: aware_filter_date}
@ -590,7 +595,7 @@ class DateBeforeTodayViewFilterType(
return (datetime.now(tz=timezone) - timedelta(days=1)).date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {f"{field_name}__lte": aware_filter_date}
@ -610,7 +615,7 @@ class DateAfterTodayViewFilterType(
return (datetime.now(tz=timezone) + timedelta(days=1)).date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {f"{field_name}__gte": aware_filter_date}
@ -631,7 +636,7 @@ class DateEqualsCurrentWeekViewFilterType(
return datetime.now(tz=timezone).date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
week_of_year = aware_filter_date.isocalendar().week
return {
@ -656,7 +661,7 @@ class DateEqualsCurrentMonthViewFilterType(
return datetime.now(tz=timezone).date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {
f"{field_name}__month": aware_filter_date.month,
@ -680,11 +685,124 @@ class DateEqualsCurrentYearViewFilterType(
return datetime.now(tz=timezone).date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {f"{field_name}__year": aware_filter_date.year}
def get_is_within_filter_query_dict(
field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
"""
The utility function checks if the field value is between today's date and
the date specified in the filter value and returns the query dict.
It ensure that the filter works correctly even if the filter date is before
today's date.
"""
op1, op2 = ("lte", "gte") if aware_filter_date >= now.date() else ("gte", "lte")
return {
f"{field_name}__{op1}": aware_filter_date,
f"{field_name}__{op2}": now.date(),
}
class DateIsWithinXDaysViewFilterType(TimezoneAwareDateViewFilterType):
"""
Is within X days filter checks if the field value is between today's date
and the number of days specified in the filter.
The value of the filter is expected to be a string like "Europe/Rome?1". It
uses character ? as separator between the timezone and the number of days.
"""
type = "date_within_days"
def get_filter_date(
self, filter_value: str, timezone: pytz.BaseTzInfo
) -> Union[datetime, date]:
"""
Zero days means today, one day means today and tomorrow, and so on.
"""
number_of_days = int(filter_value)
filter_date = datetime.now(tz=timezone) + relativedelta(days=number_of_days)
return filter_date.date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return get_is_within_filter_query_dict(field_name, aware_filter_date, now)
class DateIsWithinXWeeksViewFilterType(TimezoneAwareDateViewFilterType):
"""
Is within X weeks filter checks if the field value is between today's date
and the number of weeks specified in the filter.
The value of the filter is expected to be a string like "Europe/Rome?1". It
uses character ? as separator between the timezone and the number of days.
"""
type = "date_within_weeks"
def get_filter_date(
self, filter_value: str, timezone: pytz.BaseTzInfo
) -> Union[datetime, date]:
"""
Since zero weeks can be confusing, we raise an error if the number of
weeks is 0. One week means today + 1 week inclusive, and so on.
"""
number_of_weeks = int(filter_value)
if number_of_weeks == 0:
raise ValueError("Number of weeks cannot be 0")
filter_date = datetime.now(tz=timezone) + relativedelta(weeks=number_of_weeks)
return filter_date.date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return get_is_within_filter_query_dict(field_name, aware_filter_date, now)
class DateIsWithinXMonthsViewFilterType(TimezoneAwareDateViewFilterType):
"""
Is within X months filter checks if the field value is between today's date
and the number of months specified in the filter.
The value of the filter is expected to be a string like "Europe/Rome?1". It
uses character ? as separator between the timezone and the number of days.
"""
type = "date_within_months"
def get_filter_date(
self, filter_value: str, timezone: pytz.BaseTzInfo
) -> Union[datetime, date]:
"""
Since zero months can be confusing, we raise an error if the number of
months is 0. One month means today + 1 month inclusive, and so on. E.g.
if today is 2023-01-31, within 1 month means within 2020-02-28
inclusive.
"""
number_of_months = int(filter_value)
if number_of_months == 0:
raise ValueError("Number of months cannot be 0")
filter_date = datetime.now(tz=timezone) + relativedelta(months=number_of_months)
return filter_date.date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return get_is_within_filter_query_dict(field_name, aware_filter_date, now)
class DateEqualsDaysAgoViewFilterType(TimezoneAwareDateViewFilterType):
"""
The "number of days ago" filter checks if the field value matches with today's
@ -703,7 +821,7 @@ class DateEqualsDaysAgoViewFilterType(TimezoneAwareDateViewFilterType):
return filter_date.date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {field_name: aware_filter_date}
@ -728,7 +846,7 @@ class DateEqualsMonthsAgoViewFilterType(TimezoneAwareDateViewFilterType):
return filter_date.date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {
f"{field_name}__year": aware_filter_date.year,
@ -756,7 +874,7 @@ class DateEqualsYearsAgoViewFilterType(TimezoneAwareDateViewFilterType):
return filter_date.date()
def get_filter_query_dict(
self, field_name: str, aware_filter_date: Union[date, datetime]
self, field_name: str, aware_filter_date: Union[date, datetime], now: datetime
) -> Dict:
return {f"{field_name}__year": aware_filter_date.year}

View file

@ -1,4 +1,5 @@
import random
from contextlib import contextmanager
from datetime import date
from django.db.models import Q
@ -6,6 +7,7 @@ from django.utils import timezone as django_timezone
from django.utils.timezone import datetime, make_aware
import pytest
import pytz
from freezegun import freeze_time
from pyinstrument import Profiler
from pytest_unordered import unordered
@ -5662,3 +5664,174 @@ def test_multiple_collaborators_has_filter_type_export_import(data_fixture):
assert view_filter_type.set_import_serialized_value(user.email, {}) == ""
assert view_filter_type.set_import_serialized_value("", id_mapping) == ""
assert view_filter_type.set_import_serialized_value("wrong", id_mapping) == ""
@contextmanager
def rows_with_dates(data_fixture, dates, filter_type):
user = data_fixture.create_user()
table = data_fixture.create_database_table(user=user)
grid_view = data_fixture.create_grid_view(table=table)
date_field = data_fixture.create_date_field(table=table)
handler = ViewHandler()
model = table.get_model()
rows = model.objects.bulk_create(
[model(**{f"field_{date_field.id}": d}) for d in dates]
)
view_filter = data_fixture.create_view_filter(
view=grid_view,
field=date_field,
type=filter_type,
value="",
)
def get_filtered_row_ids():
return [
r.id for r in handler.apply_filters(grid_view, model.objects.all()).all()
]
yield rows, view_filter, get_filtered_row_ids
@pytest.mark.django_db
def test_date_within_days_view_filter(data_fixture):
dates = [
date(2020, 12, 1), # 0
date(2021, 1, 1), # 1
date(2021, 1, 2), # 2
date(2021, 1, 3), # 3
date(2021, 1, 4), # 4
date(2021, 1, 5), # 5
date(2021, 1, 6), # 6
date(2021, 2, 1), # 7
date(2022, 1, 1), # 8
]
with rows_with_dates(data_fixture, dates, "date_within_days") as (
rows,
view_filter,
get_filtered_row_ids,
):
with freeze_time("2021-01-02"):
assert len(get_filtered_row_ids()) == len(dates)
view_filter.value = "1"
view_filter.save()
with freeze_time("2021-01-02"):
assert get_filtered_row_ids() == [rows[2].id, rows[3].id]
view_filter.value = "Europe/Rome?1"
view_filter.save()
with freeze_time("2021-01-04"):
assert get_filtered_row_ids() == [rows[4].id, rows[5].id]
with freeze_time(
datetime(2021, 1, 4, 0, 0, 0, tzinfo=pytz.timezone("Pacific/Apia"))
):
assert get_filtered_row_ids() == [rows[3].id, rows[4].id]
@pytest.mark.django_db
def test_date_within_weeks_view_filter(data_fixture):
dates = [
date(2020, 12, 1), # 0
date(2021, 1, 1), # 1
date(2021, 1, 7), # 2
date(2021, 1, 8), # 3
date(2021, 1, 14), # 4
date(2021, 1, 15), # 5
date(2021, 1, 18), # 6
date(2021, 2, 1), # 7
date(2022, 1, 1), # 8
]
with rows_with_dates(data_fixture, dates, "date_within_weeks") as (
rows,
view_filter,
get_filtered_row_ids,
):
with freeze_time("2021-01-02"):
assert len(get_filtered_row_ids()) == len(dates)
view_filter.value = "1"
view_filter.save()
with freeze_time("2021-01-01"):
assert get_filtered_row_ids() == [rows[1].id, rows[2].id, rows[3].id]
view_filter.value = "Europe/Rome?2"
view_filter.save()
with freeze_time("2021-01-08"):
assert get_filtered_row_ids() == [
rows[3].id,
rows[4].id,
rows[5].id,
rows[6].id,
]
with freeze_time(
datetime(2021, 1, 8, 0, 0, 0, tzinfo=pytz.timezone("Pacific/Apia"))
):
assert get_filtered_row_ids() == [
rows[2].id,
rows[3].id,
rows[4].id,
rows[5].id,
rows[6].id,
]
@pytest.mark.django_db
def test_date_within_months_view_filter(data_fixture):
dates = [
date(2020, 12, 1), # 0
date(2021, 1, 1), # 1
date(2021, 1, 7), # 2
date(2021, 1, 31), # 3
date(2021, 2, 1), # 4
date(2021, 2, 15), # 5
date(2021, 3, 1), # 6
date(2021, 3, 21), # 7
date(2022, 1, 1), # 8
]
with rows_with_dates(data_fixture, dates, "date_within_months") as (
rows,
view_filter,
get_filtered_row_ids,
):
with freeze_time("2021-01-02"):
assert len(get_filtered_row_ids()) == len(dates)
view_filter.value = "1"
view_filter.save()
with freeze_time("2021-01-02"):
assert get_filtered_row_ids() == [rows[2].id, rows[3].id, rows[4].id]
view_filter.value = "Europe/Rome?2"
view_filter.save()
with freeze_time("2021-01-08"):
assert get_filtered_row_ids() == [
rows[3].id,
rows[4].id,
rows[5].id,
rows[6].id,
]
with freeze_time(
datetime(2021, 1, 8, 0, 0, 0, tzinfo=pytz.timezone("Pacific/Apia"))
):
assert get_filtered_row_ids() == [
rows[2].id,
rows[3].id,
rows[4].id,
rows[5].id,
rows[6].id,
]

View file

@ -0,0 +1,7 @@
{
"type": "feature",
"message": "Add new view filter type for dates 'is within x days', 'is within x weeks' and 'is within x months'",
"issue_number": 1094,
"bullet_points": [],
"created_at": "2023-05-16"
}

View file

@ -157,6 +157,9 @@
"inThisWeek": "in this week",
"inThisMonth": "in this month",
"inThisYear": "in this year",
"isWithinDays": "is within days",
"isWithinWeeks": "is within weeks",
"isWithinMonths": "is within months",
"lowerThan": "lower than",
"lengthIsLowerThan": "length is lower than",
"hasFileType": "has file type"

View file

@ -45,6 +45,9 @@ import {
DateEqualsTodayViewFilterType,
DateBeforeTodayViewFilterType,
DateAfterTodayViewFilterType,
DateWithinDaysViewFilterType,
DateWithinWeeksViewFilterType,
DateWithinMonthsViewFilterType,
DateEqualsDaysAgoViewFilterType,
DateEqualsMonthsAgoViewFilterType,
DateEqualsYearsAgoViewFilterType,
@ -279,6 +282,18 @@ export default (context) => {
'viewFilter',
new DateAfterTodayViewFilterType(context)
)
app.$registry.register(
'viewFilter',
new DateWithinDaysViewFilterType(context)
)
app.$registry.register(
'viewFilter',
new DateWithinWeeksViewFilterType(context)
)
app.$registry.register(
'viewFilter',
new DateWithinMonthsViewFilterType(context)
)
app.$registry.register(
'viewFilter',
new DateEqualsDaysAgoViewFilterType(context)

View file

@ -821,7 +821,7 @@ export class DateEqualsCurrentYearViewFilterType extends DateEqualsTodayViewFilt
/**
* Base class for days, months, years ago filters.
*/
export class DateEqualsXAgoViewFilterType extends LocalizedDateViewFilterType {
export class LocalizedDateCompareViewFilterType extends LocalizedDateViewFilterType {
getInputComponent() {
return ViewFilterTypeNumberWithTimeZone
}
@ -841,7 +841,7 @@ export class DateEqualsXAgoViewFilterType extends LocalizedDateViewFilterType {
return `${tzone}${this.getSeparator()}${xAgo}`
}
splitTimezoneAndXago(field, rawValue) {
splitTimezoneAndXToCompare(field, rawValue) {
const [timezone, value] = this.splitTimezoneAndValue(rawValue)
let filterValue = value
@ -854,7 +854,10 @@ export class DateEqualsXAgoViewFilterType extends LocalizedDateViewFilterType {
}
getValidNumberWithTimezone(rawValue, field) {
const [timezone, filterValue] = this.splitTimezoneAndXago(field, rawValue)
const [timezone, filterValue] = this.splitTimezoneAndXToCompare(
field,
rawValue
)
return `${timezone}${this.getSeparator()}${filterValue}`
}
@ -866,11 +869,11 @@ export class DateEqualsXAgoViewFilterType extends LocalizedDateViewFilterType {
return this.getValidNumberWithTimezone(value, field)
}
getDateToCompare(xAgo) {
getDateToCompare(xToCompare) {
throw new Error('Not implemented')
}
isDateMatching(rowValue, dateToCompare) {
isDateMatching(rowValue, dateToCompare, today) {
throw new Error('Not implemented')
}
@ -879,24 +882,107 @@ export class DateEqualsXAgoViewFilterType extends LocalizedDateViewFilterType {
rowValue = ''
}
const [timezone, xAgo] = this.splitTimezoneAndXago(field, filterValue)
const [timezone, xToCompare] = this.splitTimezoneAndXToCompare(
field,
filterValue
)
// an invalid daysAgo will result in an empty filter
if (xAgo === '') {
if (xToCompare === '') {
return true
}
const dateToCompare = this.getDateToCompare(xAgo)
let dateToCompare
try {
dateToCompare = this.getDateToCompare(xToCompare)
} catch (e) {
return false
}
const rowDate = moment.utc(rowValue)
const today = moment.utc()
if (timezone) {
dateToCompare.tz(timezone)
rowDate.tz(timezone)
today.tz(timezone)
}
return this.isDateMatching(rowDate, dateToCompare)
return this.isDateMatching(rowDate, dateToCompare, today)
}
}
export class DateEqualsDaysAgoViewFilterType extends DateEqualsXAgoViewFilterType {
function isRowValueBetweenDays(rowValue, dateToCompare, today) {
const [firstDay, lastDay] = dateToCompare.isSameOrBefore(today)
? [dateToCompare, today]
: [today, dateToCompare]
return rowValue.isBetween(firstDay, lastDay, 'days', '[]')
}
export class DateWithinDaysViewFilterType extends LocalizedDateCompareViewFilterType {
static getType() {
return 'date_within_days'
}
getName() {
const { i18n } = this.app
return i18n.t('viewFilter.isWithinDays')
}
getDateToCompare(xToCompare) {
return moment.utc().add(parseInt(xToCompare), 'days')
}
isDateMatching(rowValue, dateToCompare, today) {
return isRowValueBetweenDays(rowValue, dateToCompare, today)
}
}
export class DateWithinWeeksViewFilterType extends LocalizedDateCompareViewFilterType {
static getType() {
return 'date_within_weeks'
}
getName() {
const { i18n } = this.app
return i18n.t('viewFilter.isWithinWeeks')
}
getDateToCompare(xToCompare) {
const numberOfWeeks = parseInt(xToCompare)
if (numberOfWeeks === 0) {
throw new Error('Number of weeks cannot be 0')
}
return moment.utc().add(numberOfWeeks, 'weeks')
}
isDateMatching(rowValue, dateToCompare, today) {
return isRowValueBetweenDays(rowValue, dateToCompare, today)
}
}
export class DateWithinMonthsViewFilterType extends LocalizedDateCompareViewFilterType {
static getType() {
return 'date_within_months'
}
getName() {
const { i18n } = this.app
return i18n.t('viewFilter.isWithinMonths')
}
getDateToCompare(xToCompare) {
const numberOfMonths = parseInt(xToCompare)
if (numberOfMonths === 0) {
throw new Error('Number of months cannot be 0')
}
return moment.utc().add(numberOfMonths, 'month')
}
isDateMatching(rowValue, dateToCompare, today) {
return isRowValueBetweenDays(rowValue, dateToCompare, today)
}
}
export class DateEqualsDaysAgoViewFilterType extends LocalizedDateCompareViewFilterType {
static getType() {
return 'date_equals_days_ago'
}
@ -906,16 +992,16 @@ export class DateEqualsDaysAgoViewFilterType extends DateEqualsXAgoViewFilterTyp
return i18n.t('viewFilter.isDaysAgo')
}
getDateToCompare(xAgo) {
return moment.utc().subtract(parseInt(xAgo), 'days')
getDateToCompare(xToCompare) {
return moment.utc().subtract(parseInt(xToCompare), 'days')
}
isDateMatching(rowValue, dateToCompare) {
isDateMatching(rowValue, dateToCompare, today) {
return rowValue.isSame(dateToCompare, 'day')
}
}
export class DateEqualsMonthsAgoViewFilterType extends DateEqualsXAgoViewFilterType {
export class DateEqualsMonthsAgoViewFilterType extends LocalizedDateCompareViewFilterType {
static getType() {
return 'date_equals_months_ago'
}
@ -925,16 +1011,16 @@ export class DateEqualsMonthsAgoViewFilterType extends DateEqualsXAgoViewFilterT
return i18n.t('viewFilter.isMonthsAgo')
}
getDateToCompare(xAgo) {
return moment.utc().subtract(parseInt(xAgo), 'months')
getDateToCompare(xToCompare) {
return moment.utc().subtract(parseInt(xToCompare), 'months')
}
isDateMatching(rowValue, dateToCompare) {
isDateMatching(rowValue, dateToCompare, today) {
return rowValue.isSame(dateToCompare, 'month')
}
}
export class DateEqualsYearsAgoViewFilterType extends DateEqualsXAgoViewFilterType {
export class DateEqualsYearsAgoViewFilterType extends LocalizedDateCompareViewFilterType {
static getType() {
return 'date_equals_years_ago'
}
@ -944,11 +1030,11 @@ export class DateEqualsYearsAgoViewFilterType extends DateEqualsXAgoViewFilterTy
return i18n.t('viewFilter.isYearsAgo')
}
getDateToCompare(xAgo) {
return moment.utc().subtract(parseInt(xAgo), 'years')
getDateToCompare(xToCompare) {
return moment.utc().subtract(parseInt(xToCompare), 'years')
}
isDateMatching(rowValue, dateToCompare) {
isDateMatching(rowValue, dateToCompare, today) {
return rowValue.isSame(dateToCompare, 'year')
}
}

View file

@ -8,6 +8,9 @@ import {
DateEqualViewFilterType,
DateNotEqualViewFilterType,
DateEqualsTodayViewFilterType,
DateWithinDaysViewFilterType,
DateWithinWeeksViewFilterType,
DateWithinMonthsViewFilterType,
DateEqualsDaysAgoViewFilterType,
DateEqualsMonthsAgoViewFilterType,
DateEqualsYearsAgoViewFilterType,
@ -387,6 +390,135 @@ const dateInThisYear = [
},
]
const dateWithinDays = [
{
rowValue: moment().tz('Europe/Berlin').add(1, 'days').format(),
filterValue: 'Europe/Berlin?1',
expected: true,
},
{
rowValue: '1970-08-11T23:30:37.940086Z',
filterValue: 'Europe/Berlin?2',
expected: false,
},
{
rowValue: moment().utc().add(2, 'days').format(),
filterValue: 'UTC?3',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: '?1',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: 'Mars/Noland?1',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: '?',
expected: true,
},
{
rowValue: moment().utc().subtract(1, 'days').format(),
filterValue: '?',
expected: true,
},
{
rowValue: moment().utc().subtract(1, 'days').format(),
filterValue: '',
expected: true,
},
]
const dateWithinWeeks = [
{
rowValue: moment().tz('Europe/Berlin').add(5, 'days').format(),
filterValue: 'Europe/Berlin?1',
expected: true,
},
{
rowValue: '1970-08-11T23:30:37.940086Z',
filterValue: 'Europe/Berlin?2',
expected: false,
},
{
rowValue: moment().utc().add(20, 'days').format(),
filterValue: 'UTC?3',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: '?1',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: 'Mars/Noland?1',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: '?',
expected: true,
},
{
rowValue: moment().utc().subtract(1, 'days').format(),
filterValue: '?',
expected: true,
},
{
rowValue: moment().utc().subtract(1, 'days').format(),
filterValue: '',
expected: true,
},
]
const dateWithinMonths = [
{
rowValue: moment().tz('Europe/Berlin').add(20, 'days').format(),
filterValue: 'Europe/Berlin?1',
expected: true,
},
{
rowValue: '1970-08-11T23:30:37.940086Z',
filterValue: 'Europe/Berlin?2',
expected: false,
},
{
rowValue: moment().utc().add(80, 'days').format(),
filterValue: 'UTC?3',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: '?1',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: 'Mars/Noland?1',
expected: true,
},
{
rowValue: moment().utc().format(),
filterValue: '?',
expected: true,
},
{
rowValue: moment().utc().subtract(1, 'days').format(),
filterValue: '?',
expected: true,
},
{
rowValue: moment().utc().subtract(1, 'days').format(),
filterValue: '',
expected: true,
},
]
const dateDaysAgo = [
{
rowValue: moment().tz('Europe/Berlin').subtract(1, 'days').format(),
@ -786,6 +918,30 @@ describe('All Tests', () => {
expect(result).toBe(values.expected)
})
test.each(dateWithinDays)('DateWithinDays', (values) => {
const result = new DateWithinDaysViewFilterType({
app: testApp,
}).matches(values.rowValue, values.filterValue, {})
if (result !== values.expected) console.log('days', values)
expect(result).toBe(values.expected)
})
test.each(dateWithinWeeks)('DateWithinWeeks', (values) => {
const result = new DateWithinWeeksViewFilterType({
app: testApp,
}).matches(values.rowValue, values.filterValue, {})
if (result !== values.expected) console.log('weeks', values)
expect(result).toBe(values.expected)
})
test.each(dateWithinMonths)('DateWithinMonths', (values) => {
const result = new DateWithinMonthsViewFilterType({
app: testApp,
}).matches(values.rowValue, values.filterValue, {})
if (result !== values.expected) console.log('months', values)
expect(result).toBe(values.expected)
})
test.each(dateDaysAgo)('DateDaysAgo', (values) => {
const result = new DateEqualsDaysAgoViewFilterType({
app: testApp,