move popup filter to common lib
This commit is contained in:
parent
4816d97d4a
commit
3bebc49d96
@ -9,11 +9,11 @@
|
||||
class="all-caps-label primary pointer"
|
||||
translate="file-preview.tabs.annotations.select"
|
||||
></div>
|
||||
<redaction-popup-filter
|
||||
<iqser-popup-filter
|
||||
[actionsTemplate]="annotationFilterActionTemplate"
|
||||
[primaryFiltersSlug]="'primaryFilters'"
|
||||
[secondaryFiltersSlug]="'secondaryFilters'"
|
||||
></redaction-popup-filter>
|
||||
></iqser-popup-filter>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -20,12 +20,7 @@ import { DefaultListingServices, ListingComponent, NestedFilter, TableColumnConf
|
||||
import { workloadTranslations } from '../../translations/workload-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import {
|
||||
annotationFilterChecker,
|
||||
dossierMemberChecker,
|
||||
dossierStatusChecker,
|
||||
dossierTemplateChecker
|
||||
} from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
import { annotationFilterChecker, dossierMemberChecker, dossierStatusChecker, dossierTemplateChecker } from '@utils/filter-utils';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { workloadTranslations } from '../../translations/workload-translations';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { annotationFilterChecker } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
import { annotationFilterChecker } from '@utils/filter-utils';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { FileAttributeConfig } from '@redaction/red-ui-http';
|
||||
|
||||
@ -34,7 +34,7 @@ import { LoadingService } from '@services/loading.service';
|
||||
import { clearStamps, stampPDFPage } from '@utils/page-stamper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { handleFilterDelta } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||
import { handleFilterDelta } from '@utils/filter-utils';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
||||
|
||||
@ -1,109 +0,0 @@
|
||||
<ng-container *ngIf="primaryFilterGroup$ | async as primaryGroup">
|
||||
<iqser-icon-button
|
||||
*ngIf="primaryGroup.icon"
|
||||
[icon]="primaryGroup.icon"
|
||||
[label]="primaryGroup.label || ('filter-menu.label' | translate)"
|
||||
[matMenuTriggerFor]="filterMenu"
|
||||
[showDot]="hasActiveFilters$ | async"
|
||||
[attr.aria-expanded]="expanded$ | async"
|
||||
></iqser-icon-button>
|
||||
|
||||
<iqser-chevron-button
|
||||
*ngIf="!primaryGroup.icon"
|
||||
[label]="primaryGroup.label || ('filter-menu.label' | translate)"
|
||||
[matMenuTriggerFor]="filterMenu"
|
||||
[showDot]="hasActiveFilters$ | async"
|
||||
[attr.aria-expanded]="expanded$ | async"
|
||||
></iqser-chevron-button>
|
||||
|
||||
<mat-menu
|
||||
#filterMenu="matMenu"
|
||||
(close)="expanded.next(false)"
|
||||
[class]="(secondaryFilterGroup$ | async)?.filters.length > 0 ? 'padding-bottom-0' : ''"
|
||||
xPosition="before"
|
||||
>
|
||||
<ng-template matMenuContent>
|
||||
<div class="filter-menu-header">
|
||||
<div class="all-caps-label" translate="filter-menu.filter-types"></div>
|
||||
<div class="actions">
|
||||
<div
|
||||
(click)="activatePrimaryFilters(); $event.stopPropagation()"
|
||||
class="all-caps-label primary pointer"
|
||||
translate="actions.all"
|
||||
></div>
|
||||
<div
|
||||
(click)="deactivateFilters(); $event.stopPropagation()"
|
||||
class="all-caps-label primary pointer"
|
||||
translate="actions.none"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-content">
|
||||
<ng-container
|
||||
*ngFor="let filter of primaryGroup.filters"
|
||||
[ngTemplateOutletContext]="{
|
||||
filter: filter,
|
||||
atLeastOneIsExpandable: atLeastOneFilterIsExpandable$ | async
|
||||
}"
|
||||
[ngTemplateOutlet]="defaultFilterTemplate"
|
||||
></ng-container>
|
||||
</div>
|
||||
|
||||
<div *ngIf="secondaryFilterGroup$ | async as secondaryGroup" class="filter-options">
|
||||
<div class="filter-menu-options">
|
||||
<div class="all-caps-label" translate="filter-menu.filter-options"></div>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let filter of secondaryGroup.filters">
|
||||
<ng-container
|
||||
[ngTemplateOutletContext]="{
|
||||
filter: filter,
|
||||
atLeastOneIsExpandable: atLeastOneSecondaryFilterIsExpandable$ | async
|
||||
}"
|
||||
[ngTemplateOutlet]="defaultFilterTemplate"
|
||||
></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-menu>
|
||||
|
||||
<ng-template #defaultFilterLabelTemplate let-filter="filter">
|
||||
{{ filter?.label }}
|
||||
</ng-template>
|
||||
|
||||
<ng-template #defaultFilterTemplate let-atLeastOneIsExpandable="atLeastOneIsExpandable" let-filter="filter">
|
||||
<div (click)="toggleFilterExpanded($event, filter)" class="mat-menu-item flex">
|
||||
<div *ngIf="filter.children?.length > 0" class="arrow-wrapper">
|
||||
<mat-icon *ngIf="filter.expanded" color="accent" svgIcon="iqser:arrow-down"></mat-icon>
|
||||
<mat-icon *ngIf="!filter.expanded" color="accent" svgIcon="red:arrow-right"></mat-icon>
|
||||
</div>
|
||||
<div *ngIf="atLeastOneIsExpandable && filter.children?.length === 0" class="arrow-wrapper spacer"> </div>
|
||||
<mat-checkbox
|
||||
(click)="filterCheckboxClicked($event, filter)"
|
||||
[checked]="filter.checked"
|
||||
[indeterminate]="filter.indeterminate"
|
||||
class="filter-menu-checkbox"
|
||||
>
|
||||
<ng-container
|
||||
[ngTemplateOutletContext]="{ filter: filter }"
|
||||
[ngTemplateOutlet]="primaryGroup.filterTemplate ?? defaultFilterLabelTemplate"
|
||||
></ng-container>
|
||||
</mat-checkbox>
|
||||
<ng-container [ngTemplateOutletContext]="{ filter: filter }" [ngTemplateOutlet]="actionsTemplate"></ng-container>
|
||||
</div>
|
||||
|
||||
<div *ngIf="filter.children?.length && filter.expanded">
|
||||
<div (click)="$event.stopPropagation()" *ngFor="let child of filter.children" class="padding-left mat-menu-item">
|
||||
<mat-checkbox (click)="filterCheckboxClicked($event, child, filter)" [checked]="child.checked">
|
||||
<ng-container
|
||||
[ngTemplateOutletContext]="{ filter: child }"
|
||||
[ngTemplateOutlet]="primaryGroup.filterTemplate ?? defaultFilterLabelTemplate"
|
||||
></ng-container>
|
||||
</mat-checkbox>
|
||||
|
||||
<ng-container [ngTemplateOutletContext]="{ filter: child }" [ngTemplateOutlet]="actionsTemplate"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
@ -1,41 +0,0 @@
|
||||
@import '../../../../../../assets/styles/variables';
|
||||
|
||||
.filter-menu-options,
|
||||
.filter-menu-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 8px 16px 16px 16px;
|
||||
width: 350px;
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
|
||||
> *:not(:last-child) {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
max-height: 570px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.filter-menu-options {
|
||||
margin-top: 8px;
|
||||
padding: 16px 16px 3px;
|
||||
}
|
||||
|
||||
.filter-options {
|
||||
background-color: $grey-2;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
::ng-deep .filter-menu-checkbox {
|
||||
width: 100%;
|
||||
|
||||
label {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
@ -1,102 +0,0 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit, TemplateRef } from '@angular/core';
|
||||
import { FilterGroup, FilterService, handleCheckedValue, NestedFilter } from '@iqser/common-ui';
|
||||
import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox';
|
||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||
import { delay, distinctUntilChanged, map, shareReplay } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-popup-filter',
|
||||
templateUrl: './popup-filter.component.html',
|
||||
styleUrls: ['./popup-filter.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [
|
||||
{
|
||||
provide: MAT_CHECKBOX_DEFAULT_OPTIONS,
|
||||
useValue: {
|
||||
clickAction: 'noop',
|
||||
color: 'primary'
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
export class PopupFilterComponent implements OnInit {
|
||||
@Input() actionsTemplate: TemplateRef<unknown>;
|
||||
@Input() primaryFiltersSlug: string;
|
||||
@Input() secondaryFiltersSlug: string;
|
||||
|
||||
atLeastOneFilterIsExpandable$?: Observable<boolean>;
|
||||
atLeastOneSecondaryFilterIsExpandable$?: Observable<boolean>;
|
||||
hasActiveFilters$?: Observable<boolean>;
|
||||
readonly expanded = new BehaviorSubject<boolean>(null);
|
||||
readonly expanded$ = this.expanded.asObservable().pipe(delay(200));
|
||||
|
||||
primaryFilterGroup$?: Observable<FilterGroup>;
|
||||
secondaryFilterGroup$?: Observable<FilterGroup>;
|
||||
|
||||
constructor(readonly filterService: FilterService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.primaryFilterGroup$ = this.filterService.getGroup$(this.primaryFiltersSlug);
|
||||
this.secondaryFilterGroup$ = this.filterService.getGroup$(this.secondaryFiltersSlug);
|
||||
this.hasActiveFilters$ = combineLatest([this.primaryFilterGroup$, this.secondaryFilterGroup$]).pipe(
|
||||
map(([primary, secondary]) => [...primary.filters, ...(secondary?.filters || [])]),
|
||||
map(filters => filters.some(f => f.checked || f.indeterminate)),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
this.atLeastOneFilterIsExpandable$ = this.primaryFilterGroup$.pipe(
|
||||
map(group => group.filters.some(f => this.isExpandable(f))),
|
||||
distinctUntilChanged(),
|
||||
shareReplay()
|
||||
);
|
||||
this.atLeastOneSecondaryFilterIsExpandable$ = this.secondaryFilterGroup$.pipe(
|
||||
map(group => group?.filters.some(f => this.isExpandable(f))),
|
||||
distinctUntilChanged(),
|
||||
shareReplay()
|
||||
);
|
||||
}
|
||||
|
||||
filterCheckboxClicked($event: MouseEvent, nestedFilter: NestedFilter, parent?: NestedFilter): void {
|
||||
$event.stopPropagation();
|
||||
|
||||
nestedFilter.checked = !nestedFilter.checked;
|
||||
|
||||
if (parent) {
|
||||
handleCheckedValue(parent);
|
||||
} else {
|
||||
if (nestedFilter.indeterminate) nestedFilter.checked = false;
|
||||
nestedFilter.indeterminate = false;
|
||||
nestedFilter.children?.forEach(f => (f.checked = nestedFilter.checked));
|
||||
}
|
||||
|
||||
this.filterService.refresh();
|
||||
}
|
||||
|
||||
activatePrimaryFilters(): void {
|
||||
this._setFilters(this.primaryFiltersSlug, true);
|
||||
}
|
||||
|
||||
deactivateFilters(): void {
|
||||
this._setFilters(this.primaryFiltersSlug);
|
||||
if (this.secondaryFiltersSlug) this._setFilters(this.secondaryFiltersSlug);
|
||||
}
|
||||
|
||||
toggleFilterExpanded($event: MouseEvent, nestedFilter: NestedFilter): void {
|
||||
$event.stopPropagation();
|
||||
nestedFilter.expanded = !nestedFilter.expanded;
|
||||
this.filterService.refresh();
|
||||
}
|
||||
|
||||
isExpandable(nestedFilter: NestedFilter): boolean {
|
||||
return nestedFilter?.children?.length > 0;
|
||||
}
|
||||
|
||||
private _setFilters(filterGroup: string, checked = false) {
|
||||
const filters = this.filterService.getGroup(filterGroup).filters;
|
||||
filters.forEach(f => {
|
||||
f.checked = checked;
|
||||
f.indeterminate = false;
|
||||
f.children?.forEach(ff => (ff.checked = checked));
|
||||
});
|
||||
this.filterService.refresh();
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,7 @@
|
||||
<ng-container *ngIf="searchPosition === searchPositions.beforeFilters" [ngTemplateOutlet]="searchBar"></ng-container>
|
||||
|
||||
<ng-container *ngFor="let config of filters; trackBy: trackByLabel">
|
||||
<redaction-popup-filter *ngIf="!config.hide" [primaryFiltersSlug]="config.slug"></redaction-popup-filter>
|
||||
<iqser-popup-filter *ngIf="!config.hide" [primaryFiltersSlug]="config.slug"></iqser-popup-filter>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="searchPosition === searchPositions.afterFilters" [ngTemplateOutlet]="searchBar"></ng-container>
|
||||
|
||||
@ -24,7 +24,6 @@ import { NavigateLastDossiersScreenDirective } from './directives/navigate-last-
|
||||
import { DictionaryManagerComponent } from './components/dictionary-manager/dictionary-manager.component';
|
||||
import { SideNavComponent } from '@shared/components/side-nav/side-nav.component';
|
||||
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||
import { PopupFilterComponent } from '@shared/components/filters/popup-filter/popup-filter.component';
|
||||
import { AssignUserDropdownComponent } from './components/assign-user-dropdown/assign-user-dropdown.component';
|
||||
import { InputWithActionComponent } from '@shared/components/input-with-action/input-with-action.component';
|
||||
import { PageHeaderComponent } from './components/page-header/page-header.component';
|
||||
@ -42,7 +41,6 @@ const components = [
|
||||
SimpleDoughnutChartComponent,
|
||||
DictionaryAnnotationIconComponent,
|
||||
HiddenActionComponent,
|
||||
PopupFilterComponent,
|
||||
ConfirmationDialogComponent,
|
||||
EmptyStateComponent,
|
||||
SelectComponent,
|
||||
|
||||
@ -36,6 +36,7 @@ $dark: $black;
|
||||
|
||||
$btn-bg-hover: $grey-4;
|
||||
$btn-bg: $grey-6;
|
||||
$filter-bg: $grey-2;
|
||||
$quick-filter-border: $grey-5;
|
||||
|
||||
$separator: rgba(226, 228, 233, 0.9);
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit d31b702c22ac1a9e925db673ef83f56c7137071b
|
||||
Subproject commit c20bac823277e659c1c9797bdd034a9f5b2fc539
|
||||
Loading…
x
Reference in New Issue
Block a user