Enhancement: date picker and date filter dropdown improvements (#9033)

This commit is contained in:
shamoon
2025-02-06 23:01:48 -08:00
committed by GitHub
parent 52ab07c673
commit e08606af6e
20 changed files with 561 additions and 254 deletions

View File

@@ -29,10 +29,17 @@
<input class="form-control" placeholder="yyyy-mm-dd"
[(ngModel)]="atom.value"
ngbDatepicker
#d="ngbDatepicker" />
#d="ngbDatepicker"
[footerTemplate]="datePickerFooterTemplate" />
<button class="btn btn-sm btn-outline-secondary rounded-end" (click)="d.toggle()" type="button">
<i-bs name="calendar-event"></i-bs>
</button>
<ng-template #datePickerFooterTemplate>
<div class="btn-group-xs border-top p-2 d-flex">
<button type="button" class="btn btn-primary" (click)="atom.value = today; d.close()" i18n>Today</button>
<button type="button" class="btn btn-secondary ms-auto" (click)="d.close()" i18n>Close</button>
</div>
</ng-template>
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Float || getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Integer) {
<input class="w-25 form-control rounded-end" type="number" [(ngModel)]="atom.value" [disabled]="disabled">
} @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Boolean) {

View File

@@ -41,3 +41,9 @@
min-width: 140px;
}
}
.btn-group-xs {
> .btn {
border-radius: 0.15rem;
}
}

View File

@@ -241,6 +241,8 @@ export class CustomFieldsQueryDropdownComponent extends LoadingComponentWithPerm
customFields: CustomField[] = []
public readonly today: string = new Date().toISOString().split('T')[0]
constructor(protected customFieldsService: CustomFieldsService) {
super()
this.selectionModel = new CustomFieldQueriesModel()

View File

@@ -1,5 +1,5 @@
<div class="btn-group w-100" ngbDropdown role="group" [popperOptions]="popperOptions">
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="createdDateBefore || createdDateAfter ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="createdDateTo || createdDateFrom ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
<i-bs width="1em" height="1em" name="calendar-event-fill"></i-bs>
<div class="d-none d-sm-inline">&nbsp;{{title}}</div>
<pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
@@ -31,40 +31,52 @@
<div class="list-group-item d-flex p-2" role="menuitem">
<div class="selected-icon">
@if (createdDateAfter) {
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedAfter()">
@if (createdDateFrom) {
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedFrom()">
<i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
<i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
</a>
}
</div>
<div class="input-group input-group-sm small ps-1 pe-2">
<span class="input-group-text w-25 small text-muted" i18n>After</span>
<span class="input-group-text w-25 small text-muted" i18n>From</span>
<input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
maxlength="10" [(ngModel)]="createdDateAfter" ngbDatepicker #createdDateAfterPicker="ngbDatepicker">
<button class="btn btn-outline-secondary" (click)="createdDateAfterPicker.toggle()" type="button">
maxlength="10" [(ngModel)]="createdDateFrom" ngbDatepicker #createdDateFromPicker="ngbDatepicker" [footerTemplate]="createdFromFooterTemplate">
<button class="btn btn-outline-secondary" (click)="createdDateFromPicker.toggle()" type="button">
<i-bs width="1em" height="1em" name="calendar"></i-bs>
</button>
<ng-template #createdFromFooterTemplate>
<div class="btn-group-xs border-top p-2 d-flex">
<button class="btn btn-primary" (click)="createdDateFrom = today; onChangeDebounce()" i18n>Today</button>
<button class="btn btn-secondary ms-auto" (click)="createdDateFromPicker.close()" i18n>Close</button>
</div>
</ng-template>
</div>
</div>
<div class="list-group-item d-flex p-2" role="menuitem">
<div class="selected-icon">
@if (createdDateBefore) {
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedBefore()">
@if (createdDateTo) {
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedTo()">
<i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
<i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
</a>
}
</div>
<div class="input-group input-group-sm small ps-1 pe-2">
<span class="input-group-text w-25 small text-muted" i18n>Before</span>
<span class="input-group-text w-25 small text-muted" i18n>To</span>
<input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
maxlength="10" [(ngModel)]="createdDateBefore" ngbDatepicker #createdDateBeforePicker="ngbDatepicker">
<button class="btn btn-outline-secondary" (click)="createdDateBeforePicker.toggle()" type="button">
maxlength="10" [(ngModel)]="createdDateTo" ngbDatepicker #createdDateToPicker="ngbDatepicker" [footerTemplate]="createdToFooterTemplate">
<button class="btn btn-outline-secondary" (click)="createdDateToPicker.toggle()" type="button">
<i-bs width="1em" height="1em" name="calendar"></i-bs>
</button>
<ng-template #createdToFooterTemplate>
<div class="btn-group-xs border-top p-2 d-flex">
<button class="btn btn-primary" (click)="createdDateTo = today; onChangeDebounce()" i18n>Today</button>
<button class="btn btn-secondary ms-auto" (click)="createdDateToPicker.close()" i18n>Close</button>
</div>
</ng-template>
</div>
</div>
@@ -95,40 +107,52 @@
<div class="list-group-item d-flex p-2" role="menuitem">
<div class="selected-icon">
@if (addedDateAfter) {
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedAfter()">
@if (addedDateFrom) {
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedFrom()">
<i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
<i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
</a>
}
</div>
<div class="input-group input-group-sm small ps-1 pe-2">
<span class="input-group-text w-25 small text-muted" i18n>After</span>
<span class="input-group-text w-25 small text-muted" i18n>From</span>
<input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
maxlength="10" [(ngModel)]="addedDateAfter" ngbDatepicker #addedDateAfterPicker="ngbDatepicker">
<button class="btn btn-outline-secondary" (click)="addedDateAfterPicker.toggle()" type="button">
maxlength="10" [(ngModel)]="addedDateFrom" ngbDatepicker #addedDateFromPicker="ngbDatepicker" [footerTemplate]="addedFromFooterTemplate">
<button class="btn btn-outline-secondary" (click)="addedDateFromPicker.toggle()" type="button">
<i-bs width="1em" height="1em" name="calendar"></i-bs>
</button>
<ng-template #addedFromFooterTemplate>
<div class="btn-group-xs border-top p-2 d-flex">
<button class="btn btn-primary" (click)="addedDateFrom = today; onChangeDebounce()" i18n>Today</button>
<button class="btn btn-secondary ms-auto" (click)="addedDateFromPicker.close()" i18n>Close</button>
</div>
</ng-template>
</div>
</div>
<div class="list-group-item d-flex p-2" role="menuitem">
<div class="selected-icon">
@if (addedDateBefore) {
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedBefore()">
@if (addedDateTo) {
<a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedTo()">
<i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
<i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
</a>
}
</div>
<div class="input-group input-group-sm small ps-1 pe-2">
<span class="input-group-text w-25 small text-muted" i18n>Before</span>
<span class="input-group-text w-25 small text-muted" i18n>To</span>
<input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
maxlength="10" [(ngModel)]="addedDateBefore" ngbDatepicker #addedDateBeforePicker="ngbDatepicker">
<button class="btn btn-outline-secondary" (click)="addedDateBeforePicker.toggle()" type="button">
maxlength="10" [(ngModel)]="addedDateTo" ngbDatepicker #addedDateToPicker="ngbDatepicker" [footerTemplate]="addedToFooterTemplate">
<button class="btn btn-outline-secondary" (click)="addedDateToPicker.toggle()" type="button">
<i-bs width="1em" height="1em" name="calendar"></i-bs>
</button>
<ng-template #addedToFooterTemplate>
<div class="btn-group-xs border-top p-2 d-flex">
<button class="btn btn-primary" (click)="addedDateTo = today; onChangeDebounce()" i18n>Today</button>
<button class="btn btn-secondary ms-auto" (click)="addedDateToPicker.close()" i18n>Close</button>
</div>
</ng-template>
</div>
</div>

View File

@@ -41,3 +41,9 @@
}
}
}
.btn-group-xs {
> .btn {
border-radius: 0.15rem;
}
}

View File

@@ -61,7 +61,7 @@ describe('DatesDropdownComponent', () => {
it('should support date input, emit change', fakeAsync(() => {
let result: string
component.createdDateAfterChange.subscribe((date) => (result = date))
component.createdDateFromChange.subscribe((date) => (result = date))
const input: HTMLInputElement = fixture.nativeElement.querySelector('input')
input.value = '5/30/2023'
input.dispatchEvent(new Event('change'))
@@ -83,68 +83,68 @@ describe('DatesDropdownComponent', () => {
let result: DateSelection
component.datesSet.subscribe((date) => (result = date))
component.setCreatedRelativeDate(null)
component.setCreatedRelativeDate(RelativeDate.LAST_7_DAYS)
component.setCreatedRelativeDate(RelativeDate.WITHIN_1_WEEK)
component.setAddedRelativeDate(null)
component.setAddedRelativeDate(RelativeDate.LAST_7_DAYS)
component.setAddedRelativeDate(RelativeDate.WITHIN_1_WEEK)
tick(500)
expect(result).toEqual({
createdAfter: null,
createdBefore: null,
createdRelativeDateID: RelativeDate.LAST_7_DAYS,
addedAfter: null,
addedBefore: null,
addedRelativeDateID: RelativeDate.LAST_7_DAYS,
createdFrom: null,
createdTo: null,
createdRelativeDateID: RelativeDate.WITHIN_1_WEEK,
addedFrom: null,
addedTo: null,
addedRelativeDateID: RelativeDate.WITHIN_1_WEEK,
})
}))
it('should support report if active', () => {
component.createdRelativeDate = RelativeDate.LAST_7_DAYS
component.createdRelativeDate = RelativeDate.WITHIN_1_WEEK
expect(component.isActive).toBeTruthy()
component.createdRelativeDate = null
component.createdDateAfter = '2023-05-30'
component.createdDateFrom = '2023-05-30'
expect(component.isActive).toBeTruthy()
component.createdDateAfter = null
component.createdDateBefore = '2023-05-30'
component.createdDateFrom = null
component.createdDateTo = '2023-05-30'
expect(component.isActive).toBeTruthy()
component.createdDateBefore = null
component.createdDateTo = null
component.addedRelativeDate = RelativeDate.LAST_7_DAYS
component.addedRelativeDate = RelativeDate.WITHIN_1_WEEK
expect(component.isActive).toBeTruthy()
component.addedRelativeDate = null
component.addedDateAfter = '2023-05-30'
component.addedDateFrom = '2023-05-30'
expect(component.isActive).toBeTruthy()
component.addedDateAfter = null
component.addedDateBefore = '2023-05-30'
component.addedDateFrom = null
component.addedDateTo = '2023-05-30'
expect(component.isActive).toBeTruthy()
component.addedDateBefore = null
component.addedDateTo = null
expect(component.isActive).toBeFalsy()
})
it('should support reset', () => {
component.createdDateAfter = '2023-05-30'
component.createdDateFrom = '2023-05-30'
component.reset()
expect(component.createdDateAfter).toBeNull()
expect(component.createdDateFrom).toBeNull()
})
it('should support clearAfter', () => {
component.createdDateAfter = '2023-05-30'
component.clearCreatedAfter()
expect(component.createdDateAfter).toBeNull()
it('should support clearFrom', () => {
component.createdDateFrom = '2023-05-30'
component.clearCreatedFrom()
expect(component.createdDateFrom).toBeNull()
component.addedDateAfter = '2023-05-30'
component.clearAddedAfter()
expect(component.addedDateAfter).toBeNull()
component.addedDateFrom = '2023-05-30'
component.clearAddedFrom()
expect(component.addedDateFrom).toBeNull()
})
it('should support clearBefore', () => {
component.createdDateBefore = '2023-05-30'
component.clearCreatedBefore()
expect(component.createdDateBefore).toBeNull()
it('should support clearTo', () => {
component.createdDateTo = '2023-05-30'
component.clearCreatedTo()
expect(component.createdDateTo).toBeNull()
component.addedDateBefore = '2023-05-30'
component.clearAddedBefore()
expect(component.addedDateBefore).toBeNull()
component.addedDateTo = '2023-05-30'
component.clearAddedTo()
expect(component.addedDateTo).toBeNull()
})
it('should limit keyboard events', () => {

View File

@@ -23,19 +23,19 @@ import { popperOptionsReenablePreventOverflow } from 'src/app/utils/popper-optio
import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
export interface DateSelection {
createdBefore?: string
createdAfter?: string
createdTo?: string
createdFrom?: string
createdRelativeDateID?: number
addedBefore?: string
addedAfter?: string
addedTo?: string
addedFrom?: string
addedRelativeDateID?: number
}
export enum RelativeDate {
LAST_7_DAYS = 0,
LAST_MONTH = 1,
LAST_3_MONTHS = 2,
LAST_YEAR = 3,
WITHIN_1_WEEK = 0,
WITHIN_1_MONTH = 1,
WITHIN_3_MONTHS = 2,
WITHIN_1_YEAR = 3,
}
@Component({
@@ -63,23 +63,23 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
relativeDates = [
{
id: RelativeDate.LAST_7_DAYS,
name: $localize`Last 7 days`,
id: RelativeDate.WITHIN_1_WEEK,
name: $localize`Within 1 week`,
date: new Date().setDate(new Date().getDate() - 7),
},
{
id: RelativeDate.LAST_MONTH,
name: $localize`Last month`,
id: RelativeDate.WITHIN_1_MONTH,
name: $localize`Within 1 month`,
date: new Date().setMonth(new Date().getMonth() - 1),
},
{
id: RelativeDate.LAST_3_MONTHS,
name: $localize`Last 3 months`,
id: RelativeDate.WITHIN_3_MONTHS,
name: $localize`Within 3 months`,
date: new Date().setMonth(new Date().getMonth() - 3),
},
{
id: RelativeDate.LAST_YEAR,
name: $localize`Last year`,
id: RelativeDate.WITHIN_1_YEAR,
name: $localize`Within 1 year`,
date: new Date().setFullYear(new Date().getFullYear() - 1),
},
]
@@ -88,16 +88,16 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
// created
@Input()
createdDateBefore: string
createdDateTo: string
@Output()
createdDateBeforeChange = new EventEmitter<string>()
createdDateToChange = new EventEmitter<string>()
@Input()
createdDateAfter: string
createdDateFrom: string
@Output()
createdDateAfterChange = new EventEmitter<string>()
createdDateFromChange = new EventEmitter<string>()
@Input()
createdRelativeDate: RelativeDate
@@ -107,16 +107,16 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
// added
@Input()
addedDateBefore: string
addedDateTo: string
@Output()
addedDateBeforeChange = new EventEmitter<string>()
addedDateToChange = new EventEmitter<string>()
@Input()
addedDateAfter: string
addedDateFrom: string
@Output()
addedDateAfterChange = new EventEmitter<string>()
addedDateFromChange = new EventEmitter<string>()
@Input()
addedRelativeDate: RelativeDate
@@ -133,14 +133,16 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
@Input()
disabled: boolean = false
public readonly today: string = new Date().toISOString().split('T')[0]
get isActive(): boolean {
return (
this.createdRelativeDate !== null ||
this.createdDateAfter?.length > 0 ||
this.createdDateBefore?.length > 0 ||
this.createdDateFrom?.length > 0 ||
this.createdDateTo?.length > 0 ||
this.addedRelativeDate !== null ||
this.addedDateAfter?.length > 0 ||
this.addedDateBefore?.length > 0
this.addedDateFrom?.length > 0 ||
this.addedDateTo?.length > 0
)
}
@@ -161,42 +163,42 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
}
reset() {
this.createdDateBefore = null
this.createdDateAfter = null
this.createdDateTo = null
this.createdDateFrom = null
this.createdRelativeDate = null
this.addedDateBefore = null
this.addedDateAfter = null
this.addedDateTo = null
this.addedDateFrom = null
this.addedRelativeDate = null
this.onChange()
}
setCreatedRelativeDate(rd: RelativeDate) {
this.createdDateBefore = null
this.createdDateAfter = null
this.createdDateTo = null
this.createdDateFrom = null
this.createdRelativeDate = this.createdRelativeDate == rd ? null : rd
this.onChange()
}
setAddedRelativeDate(rd: RelativeDate) {
this.addedDateBefore = null
this.addedDateAfter = null
this.addedDateTo = null
this.addedDateFrom = null
this.addedRelativeDate = this.addedRelativeDate == rd ? null : rd
this.onChange()
}
onChange() {
this.createdDateBeforeChange.emit(this.createdDateBefore)
this.createdDateAfterChange.emit(this.createdDateAfter)
this.createdDateToChange.emit(this.createdDateTo)
this.createdDateFromChange.emit(this.createdDateFrom)
this.createdRelativeDateChange.emit(this.createdRelativeDate)
this.addedDateBeforeChange.emit(this.addedDateBefore)
this.addedDateAfterChange.emit(this.addedDateAfter)
this.addedDateToChange.emit(this.addedDateTo)
this.addedDateFromChange.emit(this.addedDateFrom)
this.addedRelativeDateChange.emit(this.addedRelativeDate)
this.datesSet.emit({
createdAfter: this.createdDateAfter,
createdBefore: this.createdDateBefore,
createdFrom: this.createdDateFrom,
createdTo: this.createdDateTo,
createdRelativeDateID: this.createdRelativeDate,
addedAfter: this.addedDateAfter,
addedBefore: this.addedDateBefore,
addedFrom: this.addedDateFrom,
addedTo: this.addedDateTo,
addedRelativeDateID: this.addedRelativeDate,
})
}
@@ -205,30 +207,30 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
this.createdRelativeDate = null
this.addedRelativeDate = null
this.datesSetDebounce$.next({
createdAfter: this.createdDateAfter,
createdBefore: this.createdDateBefore,
addedAfter: this.addedDateAfter,
addedBefore: this.addedDateBefore,
createdAfter: this.createdDateFrom,
createdBefore: this.createdDateTo,
addedAfter: this.addedDateFrom,
addedBefore: this.addedDateTo,
})
}
clearCreatedBefore() {
this.createdDateBefore = null
clearCreatedTo() {
this.createdDateTo = null
this.onChange()
}
clearCreatedAfter() {
this.createdDateAfter = null
clearCreatedFrom() {
this.createdDateFrom = null
this.onChange()
}
clearAddedBefore() {
this.addedDateBefore = null
clearAddedTo() {
this.addedDateTo = null
this.onChange()
}
clearAddedAfter() {
this.addedDateAfter = null
clearAddedFrom() {
this.addedDateFrom = null
this.onChange()
}

View File

@@ -12,10 +12,16 @@
<div class="input-group" [class.is-invalid]="error">
<input #inputField class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" maxlength="10"
(dateSelect)="onChange(value)" (change)="onChange(value)" (keypress)="onKeyPress($event)" (paste)="onPaste($event)"
name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel" [disabled]="disabled">
name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel" [disabled]="disabled" [footerTemplate]="datePickerFooterTemplate">
<button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button" [disabled]="disabled">
<i-bs width="1.2em" height="1.2em" name="calendar"></i-bs>
</button>
<ng-template #datePickerFooterTemplate>
<div class="btn-group-xs border-top p-2 d-flex">
<button type="button" class="btn btn-primary" (click)="value = today; onChange(value); datePicker.close()" i18n>Today</button>
<button type="button" class="btn btn-secondary ms-auto" (click)="datePicker.close()" i18n>Close</button>
</div>
</ng-template>
@if (showFilter) {
<button class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="this.value === null" title="{{ filterButtonTitle }}">
<i-bs width="1.2em" height="1.2em" name="filter"></i-bs>

View File

@@ -0,0 +1,5 @@
.btn-group-xs {
> .btn {
border-radius: 0.15rem;
}
}

View File

@@ -62,6 +62,8 @@ export class DateComponent
@Output()
filterDocuments = new EventEmitter<NgbDateStruct[]>()
public readonly today: string = new Date().toISOString().split('T')[0]
getSuggestions() {
return this.suggestions == null
? []

View File

@@ -94,11 +94,11 @@
<pngx-dates-dropdown class="flex-fill fade" [class.show]="show"
title="Dates" i18n-title
(datesSet)="updateRules()"
[(createdDateBefore)]="dateCreatedBefore"
[(createdDateAfter)]="dateCreatedAfter"
[(createdDateTo)]="dateCreatedTo"
[(createdDateFrom)]="dateCreatedFrom"
[(createdRelativeDate)]="dateCreatedRelativeDate"
[(addedDateBefore)]="dateAddedBefore"
[(addedDateAfter)]="dateAddedAfter"
[(addedDateTo)]="dateAddedTo"
[(addedDateFrom)]="dateAddedFrom"
[(addedRelativeDate)]="dateAddedRelativeDate">
</pngx-dates-dropdown>
<pngx-permissions-filter-dropdown class="flex-fill fade" [class.show]="show"

View File

@@ -32,6 +32,8 @@ import { DocumentType } from 'src/app/data/document-type'
import {
FILTER_ADDED_AFTER,
FILTER_ADDED_BEFORE,
FILTER_ADDED_FROM,
FILTER_ADDED_TO,
FILTER_ASN,
FILTER_ASN_GT,
FILTER_ASN_ISNULL,
@@ -39,6 +41,8 @@ import {
FILTER_CORRESPONDENT,
FILTER_CREATED_AFTER,
FILTER_CREATED_BEFORE,
FILTER_CREATED_FROM,
FILTER_CREATED_TO,
FILTER_CUSTOM_FIELDS_QUERY,
FILTER_CUSTOM_FIELDS_TEXT,
FILTER_DOCUMENT_TYPE,
@@ -465,48 +469,92 @@ describe('FilterEditorComponent', () => {
])
}))
it('should ingest filter rules for date created after', fakeAsync(() => {
expect(component.dateCreatedAfter).toBeNull()
it('should ingest filter rules for date created after and adjust date by 1 day', fakeAsync(() => {
expect(component.dateCreatedFrom).toBeNull()
component.filterRules = [
{
rule_type: FILTER_CREATED_AFTER,
value: '2023-05-14',
},
]
expect(component.dateCreatedAfter).toEqual('2023-05-14')
expect(component.dateCreatedFrom).toEqual('2023-05-15')
}))
it('should ingest filter rules for date created before', fakeAsync(() => {
expect(component.dateCreatedBefore).toBeNull()
it('should ingest filter rules for date created from', fakeAsync(() => {
expect(component.dateCreatedFrom).toBeNull()
component.filterRules = [
{
rule_type: FILTER_CREATED_FROM,
value: '2023-05-14',
},
]
expect(component.dateCreatedFrom).toEqual('2023-05-14')
}))
it('should ingest filter rules for date created before and adjust date by 1 day', fakeAsync(() => {
expect(component.dateCreatedTo).toBeNull()
component.filterRules = [
{
rule_type: FILTER_CREATED_BEFORE,
value: '2023-05-14',
},
]
expect(component.dateCreatedBefore).toEqual('2023-05-14')
expect(component.dateCreatedTo).toEqual('2023-05-13')
}))
it('should ingest filter rules for date added after', fakeAsync(() => {
expect(component.dateAddedAfter).toBeNull()
it('should ingest filter rules for date created to', fakeAsync(() => {
expect(component.dateCreatedTo).toBeNull()
component.filterRules = [
{
rule_type: FILTER_CREATED_TO,
value: '2023-05-14',
},
]
expect(component.dateCreatedTo).toEqual('2023-05-14')
}))
it('should ingest filter rules for date added after and adjust date by 1 day', fakeAsync(() => {
expect(component.dateAddedFrom).toBeNull()
component.filterRules = [
{
rule_type: FILTER_ADDED_AFTER,
value: '2023-05-14',
},
]
expect(component.dateAddedAfter).toEqual('2023-05-14')
expect(component.dateAddedFrom).toEqual('2023-05-15')
}))
it('should ingest filter rules for date added before', fakeAsync(() => {
expect(component.dateAddedBefore).toBeNull()
it('should ingest filter rules for date added from', fakeAsync(() => {
expect(component.dateAddedFrom).toBeNull()
component.filterRules = [
{
rule_type: FILTER_ADDED_FROM,
value: '2023-05-14',
},
]
expect(component.dateAddedFrom).toEqual('2023-05-14')
}))
it('should ingest filter rules for date added before and adjust date by 1 day', fakeAsync(() => {
expect(component.dateAddedTo).toBeNull()
component.filterRules = [
{
rule_type: FILTER_ADDED_BEFORE,
value: '2023-05-14',
},
]
expect(component.dateAddedBefore).toEqual('2023-05-14')
expect(component.dateAddedTo).toEqual('2023-05-13')
}))
it('should ingest filter rules for date added to', fakeAsync(() => {
expect(component.dateAddedTo).toBeNull()
component.filterRules = [
{
rule_type: FILTER_ADDED_TO,
value: '2023-05-14',
},
]
expect(component.dateAddedTo).toEqual('2023-05-14')
}))
it('should ingest filter rules for has all tags', fakeAsync(() => {
@@ -1464,7 +1512,7 @@ describe('FilterEditorComponent', () => {
])
}))
it('should convert user input to correct filter rules on date created after', fakeAsync(() => {
it('should convert user input to correct filter rules on date created from', fakeAsync(() => {
const dateCreatedDropdown = fixture.debugElement.queryAll(
By.directive(DatesDropdownComponent)
)[0]
@@ -1473,18 +1521,18 @@ describe('FilterEditorComponent', () => {
dateCreatedAfter.nativeElement.value = '05/14/2023'
// dateCreatedAfter.triggerEventHandler('change')
// TODO: why isn't ngModel triggering this on change?
component.dateCreatedAfter = '2023-05-14'
component.dateCreatedFrom = '2023-05-14'
fixture.detectChanges()
tick(400)
expect(component.filterRules).toEqual([
{
rule_type: FILTER_CREATED_AFTER,
rule_type: FILTER_CREATED_FROM,
value: '2023-05-14',
},
])
}))
it('should convert user input to correct filter rules on date created before', fakeAsync(() => {
it('should convert user input to correct filter rules on date created to', fakeAsync(() => {
const dateCreatedDropdown = fixture.debugElement.queryAll(
By.directive(DatesDropdownComponent)
)[0]
@@ -1493,12 +1541,12 @@ describe('FilterEditorComponent', () => {
dateCreatedBefore.nativeElement.value = '05/14/2023'
// dateCreatedBefore.triggerEventHandler('change')
// TODO: why isn't ngModel triggering this on change?
component.dateCreatedBefore = '2023-05-14'
component.dateCreatedTo = '2023-05-14'
fixture.detectChanges()
tick(400)
expect(component.filterRules).toEqual([
{
rule_type: FILTER_CREATED_BEFORE,
rule_type: FILTER_CREATED_TO,
value: '2023-05-14',
},
])
@@ -1578,12 +1626,12 @@ describe('FilterEditorComponent', () => {
dateAddedAfter.nativeElement.value = '05/14/2023'
// dateAddedAfter.triggerEventHandler('change')
// TODO: why isn't ngModel triggering this on change?
component.dateAddedAfter = '2023-05-14'
component.dateAddedFrom = '2023-05-14'
fixture.detectChanges()
tick(400)
expect(component.filterRules).toEqual([
{
rule_type: FILTER_ADDED_AFTER,
rule_type: FILTER_ADDED_FROM,
value: '2023-05-14',
},
])
@@ -1598,12 +1646,12 @@ describe('FilterEditorComponent', () => {
dateAddedBefore.nativeElement.value = '05/14/2023'
// dateAddedBefore.triggerEventHandler('change')
// TODO: why isn't ngModel triggering this on change?
component.dateAddedBefore = '2023-05-14'
component.dateAddedTo = '2023-05-14'
fixture.detectChanges()
tick(400)
expect(component.filterRules).toEqual([
{
rule_type: FILTER_ADDED_BEFORE,
rule_type: FILTER_ADDED_TO,
value: '2023-05-14',
},
])

View File

@@ -38,6 +38,8 @@ import { FilterRule } from 'src/app/data/filter-rule'
import {
FILTER_ADDED_AFTER,
FILTER_ADDED_BEFORE,
FILTER_ADDED_FROM,
FILTER_ADDED_TO,
FILTER_ASN,
FILTER_ASN_GT,
FILTER_ASN_ISNULL,
@@ -45,6 +47,8 @@ import {
FILTER_CORRESPONDENT,
FILTER_CREATED_AFTER,
FILTER_CREATED_BEFORE,
FILTER_CREATED_FROM,
FILTER_CREATED_TO,
FILTER_CUSTOM_FIELDS_QUERY,
FILTER_CUSTOM_FIELDS_TEXT,
FILTER_DOCUMENT_TYPE,
@@ -133,19 +137,19 @@ const RELATIVE_DATE_QUERY_REGEXP_CREATED = /created:\[([^\]]+)\]/g
const RELATIVE_DATE_QUERY_REGEXP_ADDED = /added:\[([^\]]+)\]/g
const RELATIVE_DATE_QUERYSTRINGS = [
{
relativeDate: RelativeDate.LAST_7_DAYS,
relativeDate: RelativeDate.WITHIN_1_WEEK,
dateQuery: '-1 week to now',
},
{
relativeDate: RelativeDate.LAST_MONTH,
relativeDate: RelativeDate.WITHIN_1_MONTH,
dateQuery: '-1 month to now',
},
{
relativeDate: RelativeDate.LAST_3_MONTHS,
relativeDate: RelativeDate.WITHIN_3_MONTHS,
dateQuery: '-3 month to now',
},
{
relativeDate: RelativeDate.LAST_YEAR,
relativeDate: RelativeDate.WITHIN_1_YEAR,
dateQuery: '-1 year to now',
},
]
@@ -349,10 +353,10 @@ export class FilterEditorComponent
storagePathSelectionModel = new FilterableDropdownSelectionModel()
customFieldQueriesModel = new CustomFieldQueriesModel()
dateCreatedBefore: string
dateCreatedAfter: string
dateAddedBefore: string
dateAddedAfter: string
dateCreatedTo: string
dateCreatedFrom: string
dateAddedTo: string
dateAddedFrom: string
dateCreatedRelativeDate: RelativeDate
dateAddedRelativeDate: RelativeDate
@@ -385,10 +389,10 @@ export class FilterEditorComponent
this.customFieldQueriesModel.clear(false)
this._textFilter = null
this._moreLikeId = null
this.dateAddedBefore = null
this.dateAddedAfter = null
this.dateCreatedBefore = null
this.dateCreatedAfter = null
this.dateAddedTo = null
this.dateAddedFrom = null
this.dateCreatedTo = null
this.dateCreatedFrom = null
this.dateCreatedRelativeDate = null
this.dateAddedRelativeDate = null
this.textFilterModifier = TEXT_FILTER_MODIFIER_EQUALS
@@ -458,16 +462,40 @@ export class FilterEditorComponent
})
break
case FILTER_CREATED_AFTER:
this.dateCreatedAfter = rule.value
// Old rules require adjusting date by a day
const createdAfter = new Date(rule.value)
createdAfter.setDate(createdAfter.getDate() + 1)
this.dateCreatedFrom = createdAfter.toISOString().split('T')[0]
break
case FILTER_CREATED_BEFORE:
this.dateCreatedBefore = rule.value
// Old rules require adjusting date by a day
const createdBefore = new Date(rule.value)
createdBefore.setDate(createdBefore.getDate() - 1)
this.dateCreatedTo = createdBefore.toISOString().split('T')[0]
break
case FILTER_ADDED_AFTER:
this.dateAddedAfter = rule.value
// Old rules require adjusting date by a day
const addedAfter = new Date(rule.value)
addedAfter.setDate(addedAfter.getDate() + 1)
this.dateAddedFrom = addedAfter.toISOString().split('T')[0]
break
case FILTER_ADDED_BEFORE:
this.dateAddedBefore = rule.value
// Old rules require adjusting date by a day
const addedBefore = new Date(rule.value)
addedBefore.setDate(addedBefore.getDate() - 1)
this.dateAddedTo = addedBefore.toISOString().split('T')[0]
break
case FILTER_CREATED_FROM:
this.dateCreatedFrom = rule.value
break
case FILTER_CREATED_TO:
this.dateCreatedTo = rule.value
break
case FILTER_ADDED_FROM:
this.dateAddedFrom = rule.value
break
case FILTER_ADDED_TO:
this.dateAddedTo = rule.value
break
case FILTER_HAS_TAGS_ALL:
this.tagSelectionModel.logicalOperator = LogicalOperator.And
@@ -814,28 +842,28 @@ export class FilterEditorComponent
value: JSON.stringify(queries[0]),
})
}
if (this.dateCreatedBefore) {
if (this.dateCreatedTo) {
filterRules.push({
rule_type: FILTER_CREATED_BEFORE,
value: this.dateCreatedBefore,
rule_type: FILTER_CREATED_TO,
value: this.dateCreatedTo,
})
}
if (this.dateCreatedAfter) {
if (this.dateCreatedFrom) {
filterRules.push({
rule_type: FILTER_CREATED_AFTER,
value: this.dateCreatedAfter,
rule_type: FILTER_CREATED_FROM,
value: this.dateCreatedFrom,
})
}
if (this.dateAddedBefore) {
if (this.dateAddedTo) {
filterRules.push({
rule_type: FILTER_ADDED_BEFORE,
value: this.dateAddedBefore,
rule_type: FILTER_ADDED_TO,
value: this.dateAddedTo,
})
}
if (this.dateAddedAfter) {
if (this.dateAddedFrom) {
filterRules.push({
rule_type: FILTER_ADDED_AFTER,
value: this.dateAddedAfter,
rule_type: FILTER_ADDED_FROM,
value: this.dateAddedFrom,
})
}
if (

View File

@@ -36,6 +36,11 @@ export const FILTER_CREATED_DAY = 12
export const FILTER_ADDED_BEFORE = 13
export const FILTER_ADDED_AFTER = 14
export const FILTER_CREATED_TO = 43
export const FILTER_CREATED_FROM = 44
export const FILTER_ADDED_TO = 45
export const FILTER_ADDED_FROM = 46
export const FILTER_MODIFIED_BEFORE = 15
export const FILTER_MODIFIED_AFTER = 16
@@ -179,6 +184,18 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
datatype: 'date',
multi: false,
},
{
id: FILTER_CREATED_TO,
filtervar: 'created__date__lte',
datatype: 'date',
multi: false,
},
{
id: FILTER_CREATED_FROM,
filtervar: 'created__date__gte',
datatype: 'date',
multi: false,
},
{
id: FILTER_CREATED_YEAR,
filtervar: 'created__year',
@@ -210,6 +227,18 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
datatype: 'date',
multi: false,
},
{
id: FILTER_ADDED_TO,
filtervar: 'added__date__lte',
datatype: 'date',
multi: false,
},
{
id: FILTER_ADDED_FROM,
filtervar: 'added__date__gte',
datatype: 'date',
multi: false,
},
{
id: FILTER_MODIFIED_BEFORE,
filtervar: 'modified__date__lt',