Skip to content

Commit

Permalink
feat(admin-ui): Implement relative date filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Aug 28, 2023
1 parent 8b52e6f commit d07a5f3
Show file tree
Hide file tree
Showing 21 changed files with 327 additions and 116 deletions.
92 changes: 46 additions & 46 deletions packages/admin-ui/i18n-coverage.json
Original file line number Diff line number Diff line change
@@ -1,81 +1,81 @@
{
"generatedOn": "2023-08-28T07:56:15.924Z",
"lastCommit": "0c5ce7d43ecbaf67da4254c25fe3562626072844",
"generatedOn": "2023-08-28T09:13:19.132Z",
"lastCommit": "8b52e6fc44c9ebe04d9f012c39b0d9ea4961c215",
"translationStatus": {
"ar": {
"tokenCount": 746,
"translatedCount": 745,
"percentage": 100
"tokenCount": 755,
"translatedCount": 746,
"percentage": 99
},
"cs": {
"tokenCount": 746,
"translatedCount": 550,
"percentage": 74
"tokenCount": 755,
"translatedCount": 551,
"percentage": 73
},
"de": {
"tokenCount": 746,
"translatedCount": 745,
"percentage": 100
"tokenCount": 755,
"translatedCount": 746,
"percentage": 99
},
"en": {
"tokenCount": 746,
"translatedCount": 745,
"tokenCount": 755,
"translatedCount": 754,
"percentage": 100
},
"es": {
"tokenCount": 746,
"translatedCount": 745,
"percentage": 100
"tokenCount": 755,
"translatedCount": 746,
"percentage": 99
},
"fr": {
"tokenCount": 746,
"translatedCount": 741,
"percentage": 99
"tokenCount": 755,
"translatedCount": 742,
"percentage": 98
},
"he": {
"tokenCount": 746,
"translatedCount": 745,
"percentage": 100
"tokenCount": 755,
"translatedCount": 746,
"percentage": 99
},
"it": {
"tokenCount": 746,
"translatedCount": 575,
"percentage": 77
"tokenCount": 755,
"translatedCount": 576,
"percentage": 76
},
"pl": {
"tokenCount": 746,
"translatedCount": 385,
"percentage": 52
"tokenCount": 755,
"translatedCount": 386,
"percentage": 51
},
"pt_BR": {
"tokenCount": 746,
"translatedCount": 744,
"percentage": 100
"tokenCount": 755,
"translatedCount": 745,
"percentage": 99
},
"pt_PT": {
"tokenCount": 746,
"translatedCount": 584,
"percentage": 78
"tokenCount": 755,
"translatedCount": 585,
"percentage": 77
},
"ru": {
"tokenCount": 746,
"translatedCount": 745,
"percentage": 100
"tokenCount": 755,
"translatedCount": 746,
"percentage": 99
},
"uk": {
"tokenCount": 746,
"translatedCount": 574,
"percentage": 77
"tokenCount": 755,
"translatedCount": 575,
"percentage": 76
},
"zh_Hans": {
"tokenCount": 746,
"translatedCount": 520,
"percentage": 70
"tokenCount": 755,
"translatedCount": 521,
"percentage": 69
},
"zh_Hant": {
"tokenCount": 746,
"translatedCount": 365,
"percentage": 49
"tokenCount": 755,
"translatedCount": 366,
"percentage": 48
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,13 @@ export class DataTableFilterCollection<FilterInput extends Record<string, any> =
return val ? '1' : '0';
} else if (filterWithValue.isDateRange()) {
const val = filterWithValue.value;
const start = val.start ? new Date(val.start).getTime() : '';
const end = val.end ? new Date(val.end).getTime() : '';
return `${start},${end}`;
if (val.mode === 'relative') {
return `${val.mode},${val.relativeValue},${val.relativeUnit}`;
} else {
const start = val.start ? new Date(val.start).getTime() : '';
const end = val.end ? new Date(val.end).getTime() : '';
return `${start},${end}`;
}
} else if (filterWithValue.isCustom()) {
return filterWithValue.filter.type.serializeValue(filterWithValue.value);
}
Expand Down Expand Up @@ -316,10 +320,23 @@ export class DataTableFilterCollection<FilterInput extends Record<string, any> =
case 'boolean':
return value === '1';
case 'dateRange':
const [startTimestamp, endTimestamp] = value.split(',');
const start = startTimestamp ? new Date(Number(startTimestamp)).toISOString() : '';
const end = endTimestamp ? new Date(Number(endTimestamp)).toISOString() : '';
return { start, end };
let mode = 'relative';
let relativeValue: number | undefined;
let relativeUnit: 'day' | 'month' | 'year' | undefined;
let start: string | undefined;
let end: string | undefined;
if (value.startsWith('relative')) {
mode = 'relative';
const [_, relativeValueStr, relativeUnitStr] = value.split(',');
relativeValue = Number(relativeValueStr);
relativeUnit = relativeUnitStr as 'day' | 'month' | 'year';
} else {
mode = 'range';
const [startTimestamp, endTimestamp] = value.split(',');
start = startTimestamp ? new Date(Number(startTimestamp)).toISOString() : '';
end = endTimestamp ? new Date(Number(endTimestamp)).toISOString() : '';
}
return { mode, relativeValue, relativeUnit, start, end };
case 'custom':
return filter.type.deserializeValue(value);
default:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Type as ComponentType } from '@angular/core';
import { LocalizedString } from '@vendure/common/lib/generated-types';
import { assertNever } from '@vendure/common/lib/shared-utils';
import dayjs from 'dayjs';
import { FormInputComponent } from '../../common/component-registry-types';
import {
BooleanOperators,
Expand Down Expand Up @@ -62,7 +63,16 @@ export type KindValueMap = {
};
select: { raw: string[]; input: StringOperators };
boolean: { raw: boolean; input: BooleanOperators };
dateRange: { raw: { start?: string; end?: string }; input: DateOperators };
dateRange: {
raw: {
mode: 'relative' | 'range';
relativeValue: number;
relativeUnit: 'day' | 'month' | 'year';
start?: string;
end?: string;
};
input: DateOperators;
};
number: { raw: { operator: keyof NumberOperators; amount: number }; input: NumberOperators };
custom: { raw: any; input: any };
};
Expand Down Expand Up @@ -122,20 +132,29 @@ export class DataTableFilter<
};
case 'dateRange': {
let dateOperators: DateOperators;
const start = value.start ?? undefined;
const end = value.end ?? undefined;
if (start && end) {
const mode = value.mode ?? 'relative';
if (mode === 'relative') {
const relativeValue = value.relativeValue ?? 30;
const relativeUnit = value.relativeUnit ?? 'day';
dateOperators = {
between: { start, end },
};
} else if (start) {
dateOperators = {
after: start,
after: dayjs().subtract(relativeValue, relativeUnit).startOf('day').toISOString(),
};
} else {
dateOperators = {
before: end,
};
const start = value.start ?? undefined;
const end = value.end ?? undefined;
if (start && end) {
dateOperators = {
between: { start, end },
};
} else if (start) {
dateOperators = {
after: start,
};
} else {
dateOperators = {
before: end,
};
}
}
return dateOperators;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,29 @@
<span *ngIf="!filterWithValue?.value">{{ 'common.boolean-false' | translate }}</span>
</ng-container>
<ng-container *ngIf="filterWithValue.isDateRange()">
<span *ngIf="filterWithValue.value?.start && filterWithValue.value?.end">
{{ filterWithValue.value?.start | localeDate : 'shortDate' }} -
{{ filterWithValue.value?.end | localeDate : 'shortDate' }}
</span>
<span *ngIf="filterWithValue.value?.start && !filterWithValue.value?.end">
> {{ filterWithValue.value?.start | localeDate : 'shortDate' }}
</span>
<span *ngIf="filterWithValue.value?.end && !filterWithValue.value?.start">
< {{ filterWithValue.value?.end | localeDate : 'shortDate' }}
</span>
<ng-container *ngIf="filterWithValue.value.mode === 'relative'">
<span *ngIf="filterWithValue.value.relativeUnit === 'day'">
{{ 'datetime.relative-past-days' | translate: { count: filterWithValue.value.relativeValue } }}
</span>
<span *ngIf="filterWithValue.value.relativeUnit === 'month'">
{{ 'datetime.relative-past-months' | translate: { count: filterWithValue.value.relativeValue } }}
</span>
<span *ngIf="filterWithValue.value.relativeUnit === 'year'">
{{ 'datetime.relative-past-years' | translate: { count: filterWithValue.value.relativeValue } }}
</span>
</ng-container>
<ng-container *ngIf="filterWithValue.value.mode === 'range'">
<span *ngIf="filterWithValue.value?.start && filterWithValue.value?.end">
{{ filterWithValue.value?.start | localeDate : 'shortDate' }} -
{{ filterWithValue.value?.end | localeDate : 'shortDate' }}
</span>
<span *ngIf="filterWithValue.value?.start && !filterWithValue.value?.end">
> {{ filterWithValue.value?.start | localeDate : 'shortDate' }}
</span>
<span *ngIf="filterWithValue.value?.end && !filterWithValue.value?.start">
< {{ filterWithValue.value?.end | localeDate : 'shortDate' }}
</span>
</ng-container>
</ng-container>
<ng-container *ngIf="filterWithValue.isNumber()">
<span *ngIf="filterWithValue.value?.operator === 'eq'"> = </span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
<clr-icon shape="times" size="12"></clr-icon>
</button>
<button vdrDropdownTrigger class="">
<span *ngIf="state === 'new'">{{ 'common.add-filter' | translate }} <span class="filter-hotkey">f</span></span>
<span *ngIf="state === 'new'"
>{{ 'common.add-filter' | translate }} <span class="filter-hotkey">f</span></span
>
<span *ngIf="state === 'active'">
<vdr-data-table-filter-label
[filterWithValue]="filterWithValue"
Expand Down Expand Up @@ -97,14 +99,40 @@
</div>
<div *ngSwitchCase="'dateRange'">
<div [formGroup]="formControl">
<label>
<div>{{ 'common.start-date' | translate }}</div>
</label>
<vdr-datetime-picker formControlName="start"></vdr-datetime-picker>
<label>
<div>{{ 'common.end-date' | translate }}</div>
</label>
<vdr-datetime-picker formControlName="end"></vdr-datetime-picker>
<vdr-form-field [label]="'common.data-table-filter-date-mode' | translate">
<select name="mode" formControlName="mode" class="mb-1">
<option value="relative">
{{ 'common.data-table-filter-date-relative' | translate }}
</option>
<option value="range">
{{ 'common.data-table-filter-date-range' | translate }}
</option>
</select>
</vdr-form-field>
<ng-container *ngIf="formControl.get('mode')?.value === 'relative'">
<div class="flex mt-2">
<vdr-form-field class="mr-1">
<input type="number" min="1" formControlName="relativeValue" />
</vdr-form-field>
<vdr-form-field>
<select name="mode" formControlName="relativeUnit">
<option value="day">{{ 'datetime.day' | translate }}</option>
<option value="month">{{ 'datetime.month' | translate }}</option>
<option value="year">{{ 'datetime.year' | translate }}</option>
</select>
</vdr-form-field>
</div>
</ng-container>
<ng-container *ngIf="formControl.get('mode')?.value === 'range'">
<label>
<div>{{ 'common.start-date' | translate }}</div>
</label>
<vdr-datetime-picker formControlName="start"></vdr-datetime-picker>
<label>
<div>{{ 'common.end-date' | translate }}</div>
</label>
<vdr-datetime-picker formControlName="end"></vdr-datetime-picker>
</ng-container>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,19 @@ export class DataTableFiltersComponent implements AfterViewInit {
} else if (filter.isDateRange()) {
this.formControl = new FormGroup(
{
mode: new FormControl('relative'),
relativeValue: new FormControl(value?.relativeValue ?? 30),
relativeUnit: new FormControl(value?.relativeUnit ?? 'day'),
start: new FormControl(value?.start ?? null),
end: new FormControl(value?.end ?? null),
},
control => {
const val = control.value;
if (val.start && val.end && val.start > val.end) {
const mode = val.mode;
if (mode === 'range' && val.start && val.end && val.start > val.end) {
return { invalidRange: true };
}
if (!val.start && !val.end) {
if (mode === 'range' && !val.start && !val.end) {
return { noSelection: true };
}
return null;
Expand Down Expand Up @@ -158,23 +162,18 @@ export class DataTableFiltersComponent implements AfterViewInit {
value = !!this.formControl.value as KindValueMap[typeof type.kind]['raw'];
break;
case 'dateRange': {
let dateOperators: DateOperators;
const mode = this.formControl.value.mode ?? 'relative';
const relativeValue = this.formControl.value.relativeValue ?? 30;
const relativeUnit = this.formControl.value.relativeUnit ?? 'day';
const start = this.formControl.value.start ?? undefined;
const end = this.formControl.value.end ?? undefined;
if (start && end) {
dateOperators = {
between: { start, end },
};
} else if (start) {
dateOperators = {
after: start,
};
} else {
dateOperators = {
before: end,
};
}
value = { start, end } as KindValueMap[typeof type.kind]['raw'];
value = {
mode,
relativeValue,
relativeUnit,
start,
end,
} as KindValueMap[typeof type.kind]['raw'];
break;
}
case 'number':
Expand Down
Loading

0 comments on commit d07a5f3

Please sign in to comment.