add single filters

This commit is contained in:
Dan Percic 2022-03-04 17:42:37 +02:00
parent 0157507f66
commit c11f73ba9e
8 changed files with 116 additions and 14 deletions

View File

@ -7,11 +7,13 @@ import { INestedFilter } from './models/nested-filter.model';
import { get, shareDistinctLast, shareLast } from '../utils';
import { NestedFilter } from './models/nested-filter';
import { Filter } from './models/filter';
import { IFilter } from './models/filter.model';
@Injectable()
export class FilterService {
readonly showResetFilters$: Observable<boolean>;
readonly filterGroups$: Observable<IFilterGroup[]>;
readonly #singleFilters = new Map<string, BehaviorSubject<IFilter | undefined>>();
private readonly _filterGroups$ = new BehaviorSubject<IFilterGroup[]>([]);
private readonly _refresh$ = new Subject();
@ -29,6 +31,10 @@ export class FilterService {
return toFlatFilters(this.filterGroups, filters => filters.filter(f => f.checked));
}
get singleFilters() {
return Array.from(this.#singleFilters.values());
}
private get _showResetFilters$(): Observable<boolean> {
return this.filterGroups$.pipe(
map(value => toFlatFilters(value)),
@ -92,6 +98,23 @@ export class FilterService {
);
}
addSingleFilter(filter: IFilter) {
if (!this.#singleFilters.has(filter.id)) {
return this.#singleFilters.set(filter.id, new BehaviorSubject<IFilter | undefined>(filter));
}
return this.#singleFilters.get(filter.id)?.next(filter);
}
getSingleFilter(filterId: string) {
if (!this.#singleFilters.has(filterId)) {
this.#singleFilters.set(filterId, new BehaviorSubject<IFilter | undefined>(undefined));
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.#singleFilters.get(filterId)!.asObservable();
}
getGroup(slug: string): IFilterGroup | undefined {
return this.filterGroups.find(group => group.slug === slug);
}
@ -131,6 +154,30 @@ export class FilterService {
});
});
this.resetSingleFilters();
this.refresh();
}
resetSingleFilters() {
this.#singleFilters.forEach(filter$ => {
const filter = filter$.value;
if (filter) {
filter$.next({ ...filter$.value, checked: !filter$.value?.checked });
}
});
}
toggleSingleFilter(filterId: string) {
const filter$ = this.#singleFilters.get(filterId);
if (!filter$) {
return;
}
const filter = filter$.value;
if (filter) {
filter.checked = !filter.checked;
this.addSingleFilter(filter);
}
}
}

View File

@ -9,10 +9,11 @@ import { QuickFiltersComponent } from './quick-filters/quick-filters.component';
import { IqserIconsModule } from '../icons';
import { IqserInputsModule } from '../inputs';
import { IqserHelpModeModule } from '../help-mode';
import { SingleFilterComponent } from './single-filter/single-filter.component';
const matModules = [MatCheckboxModule, MatMenuModule];
const modules = [TranslateModule, IqserButtonsModule, IqserIconsModule, IqserInputsModule, IqserHelpModeModule];
const components = [QuickFiltersComponent, PopupFilterComponent];
const components = [QuickFiltersComponent, PopupFilterComponent, SingleFilterComponent];
@NgModule({
declarations: [...components],

View File

@ -0,0 +1,3 @@
<mat-checkbox (click)="checkboxClicked($event)" [checked]="filter.checked" class="filter-menu-checkbox">
{{ filter.label }}
</mat-checkbox>

View File

@ -0,0 +1,8 @@
::ng-deep .filter-menu-checkbox {
width: 100%;
label {
width: 100%;
height: 100%;
}
}

View File

@ -0,0 +1,19 @@
import { Component, Input } from '@angular/core';
import { FilterService } from '../filter.service';
import { IFilter } from '../models/filter.model';
@Component({
selector: 'iqser-single-filter',
templateUrl: './single-filter.component.html',
styleUrls: ['./single-filter.component.scss'],
})
export class SingleFilterComponent {
@Input() filter!: IFilter;
constructor(readonly filterService: FilterService) {}
checkboxClicked($event: MouseEvent) {
$event.preventDefault();
this.filterService.toggleSingleFilter(this.filter.id);
}
}

View File

@ -7,7 +7,15 @@
<ng-container *ngIf="searchPosition === searchPositions.beforeFilters" [ngTemplateOutlet]="searchBar"></ng-container>
<ng-container *ngFor="let config of filters; trackBy: trackByLabel">
<iqser-popup-filter *ngIf="!config.hide" [primaryFiltersSlug]="config.slug" [iqserHelpMode]="filterHelpModeKey"></iqser-popup-filter>
<iqser-popup-filter
*ngIf="!config.hide"
[iqserHelpMode]="filterHelpModeKey"
[primaryFiltersSlug]="config.slug"
></iqser-popup-filter>
</ng-container>
<ng-container *ngFor="let filter$ of filterService.singleFilters">
<iqser-single-filter *ngIf="filter$ | async as filter" [filter]="filter"></iqser-single-filter>
</ng-container>
<ng-container *ngIf="searchPosition === searchPositions.afterFilters" [ngTemplateOutlet]="searchBar"></ng-container>
@ -15,9 +23,9 @@
<div
(click)="resetFilters()"
*ngIf="showResetFilters$ | async"
[iqserHelpMode]="resetFiltersHelpModeKey"
class="reset-filters"
translate="reset-filters"
[iqserHelpMode]="resetFiltersHelpModeKey"
></div>
</div>
@ -30,9 +38,9 @@
*ngIf="!config.hide"
[icon]="config.icon"
[id]="config.label.replace('.', '-')"
[iqserHelpMode]="config.helpModeKey"
[label]="config.label | translate"
[type]="config.type"
[iqserHelpMode]="config.helpModeKey"
></iqser-icon-button>
</ng-container>
@ -43,9 +51,9 @@
*ngIf="!config.hide"
[disabled]="config.disabled$ && (config.disabled$ | async)"
[icon]="config.icon"
[iqserHelpMode]="config.helpModeKey"
[tooltip]="config.label"
tooltipPosition="below"
[iqserHelpMode]="config.helpModeKey"
></iqser-circle-button>
</ng-container>
@ -58,8 +66,8 @@
[class.ml-6]="actionConfigs"
[tooltip]="'common.close' | translate"
icon="iqser:close"
tooltipPosition="below"
iqserHelpMode="edit_dossier_in_dossier"
tooltipPosition="below"
></iqser-circle-button>
</div>
</div>

View File

@ -45,6 +45,14 @@ export class PageHeaderComponent<T extends IListable> {
);
}
get filterHelpModeKey() {
return this.helpModeKey ? `filter_${this.helpModeKey}_list` : '';
}
get resetFiltersHelpModeKey() {
return this.helpModeKey === 'dossier' ? 'reset_filters' : 'delete_document_filter';
}
resetFilters(): void {
this.filterService.reset();
this.searchService.reset();
@ -53,12 +61,4 @@ export class PageHeaderComponent<T extends IListable> {
trackByLabel<K extends { label?: string }>(index: number, item: K): string | undefined {
return item.label;
}
get filterHelpModeKey() {
return !!this.helpModeKey ? `filter_${this.helpModeKey}_list` : '';
}
get resetFiltersHelpModeKey() {
return this.helpModeKey === 'dossier' ? 'reset_filters' : `delete_document_filter`;
}
}

View File

@ -68,3 +68,19 @@ export function hasFormChanged(form: FormGroup, initialFormValue): boolean {
}
return false;
}
const HOURS_IN_A_DAY = 24;
const MINUTES_IN_AN_HOUR = 60;
export function getLeftDateTime(ISOString: string) {
const date = moment(ISOString);
const now = new Date(Date.now());
const daysLeft = date.diff(now, 'days');
const hoursFromNow = date.diff(now, 'hours');
const hoursLeft = hoursFromNow - HOURS_IN_A_DAY * daysLeft;
const minutesFromNow = date.diff(now, 'minutes');
const minutesLeft = minutesFromNow - HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR * daysLeft;
return { daysLeft, hoursLeft, minutesLeft };
}