add actions to page header, reset quick filters from page header

This commit is contained in:
Dan Percic 2021-07-07 15:33:37 +03:00
parent bd3c6377b4
commit 53d8406c23
15 changed files with 174 additions and 219 deletions

View File

@ -1,10 +1,12 @@
<section>
<redaction-page-header
(filtersChanged)="filtersChanged()"
(filtersChanged)="filtersChanged($event)"
(filtersReset)="resetFilters()"
(searchChanged)="executeSearch($event)"
[filterConfigs]="filterConfigs"
[buttonConfigs]="buttonConfigs"
[searchPlaceholder]="'dossier-listing.search'"
[showResetFilters]="showResetFilters"
[searchPlaceholder]="'dossier-listing.search' | translate"
></redaction-page-header>
<div class="overlay-shadow"></div>
@ -20,7 +22,7 @@
</span>
<redaction-quick-filters
(filtersChanged)="filtersChanged()"
(filtersChanged)="filtersChanged($event)"
[filters]="quickFilters"
></redaction-quick-filters>
</div>

View File

@ -24,9 +24,9 @@ import {
dossierTemplateChecker,
processFilters
} from '@shared/components/filters/popup-filter/utils/filter-utils';
import { QuickFiltersComponent } from '@shared/components/filters/quick-filters/quick-filters.component';
import { UserPreferenceService } from '../../../../services/user-preference.service';
import { ButtonConfig, FilterConfig } from '@shared/components/page-header/page-header.component';
import { FilterConfig } from '../../../shared/components/page-header/models/filter-config.model';
import { ButtonConfig } from '../../../shared/components/page-header/models/button-config.model';
@Component({
templateUrl: './dossier-listing-screen.component.html',
@ -48,11 +48,10 @@ export class DossierListingScreenComponent
statusFilters: []
};
quickFilters: FilterModel[];
readonly itemSize = 85;
filterConfigs: FilterConfig[];
buttonConfigs: ButtonConfig[] = [
{
label: 'dossier-listing.add-new',
label: this._translateService.instant('dossier-listing.add-new'),
action: () => this.openAddDossierDialog(),
hide: !this.permissionsService.isManager(),
icon: 'red:plus',
@ -60,6 +59,8 @@ export class DossierListingScreenComponent
}
];
readonly itemSize = 85;
protected readonly _searchKey = 'name';
protected readonly _sortKey = 'dossier-listing';
@ -68,8 +69,6 @@ export class DossierListingScreenComponent
private _routerEventsScrollPositionSub: Subscription;
private _fileChangedSub: Subscription;
@ViewChild(QuickFiltersComponent)
protected readonly _quickFiltersComponent: QuickFiltersComponent;
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
private readonly _needsWorkTemplate: TemplateRef<any>;
@ -156,7 +155,6 @@ export class DossierListingScreenComponent
this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top');
}
});
this._filterComponents = [this._quickFiltersComponent];
}
ngOnAttach() {
@ -317,23 +315,23 @@ export class DossierListingScreenComponent
private _createFilterConfigs() {
this.filterConfigs = [
{
label: 'filters.status',
label: this._translateService.instant('filters.status'),
primaryFilters: this.statusFilters,
icon: 'red:status'
},
{
label: 'filters.people',
label: this._translateService.instant('filters.people'),
primaryFilters: this.peopleFilters,
icon: 'red:user'
},
{
label: 'filters.needs-work',
label: this._translateService.instant('filters.needs-work'),
primaryFilters: this.needsWorkFilters,
icon: 'red:needs-work',
filterTemplate: this._needsWorkTemplate
},
{
label: 'filters.dossier-templates',
label: this._translateService.instant('filters.dossier-templates'),
primaryFilters: this.dossierTemplateFilters,
icon: 'red:template',
hide: this.dossierTemplateFilters.length <= 1
@ -342,32 +340,33 @@ export class DossierListingScreenComponent
}
private _createQuickFilters() {
const filters = [
const filters: FilterModel[] = [
{
key: this.user.id,
label: 'dossier-listing.quick-filters.my-dossiers',
label: this._translateService.instant('dossier-listing.quick-filters.my-dossiers'),
checker: (dw: DossierWrapper) => dw.ownerId === this.user.id
},
{
key: this.user.id,
label: 'dossier-listing.quick-filters.to-approve',
label: this._translateService.instant('dossier-listing.quick-filters.to-approve'),
checker: (dw: DossierWrapper) => dw.approverIds.includes(this.user.id)
},
{
key: this.user.id,
label: 'dossier-listing.quick-filters.to-review',
label: this._translateService.instant('dossier-listing.quick-filters.to-review'),
checker: (dw: DossierWrapper) => dw.memberIds.includes(this.user.id)
},
{
key: this.user.id,
label: 'dossier-listing.quick-filters.other',
label: this._translateService.instant('dossier-listing.quick-filters.other'),
checker: (dw: DossierWrapper) => !dw.memberIds.includes(this.user.id)
}
];
this.quickFilters = filters.filter(
f =>
f.label === 'dossier-listing.quick-filters.my-dossiers' ||
f.label ===
this._translateService.instant('dossier-listing.quick-filters.my-dossiers') ||
this._userPreferenceService.areDevFeaturesEnabled
);
}

View File

@ -1,91 +1,41 @@
<section *ngIf="!!activeDossier">
<redaction-page-header
(filtersChanged)="filtersChanged()"
(filtersChanged)="filtersChanged($event)"
(filtersReset)="resetFilters()"
(searchChanged)="executeSearch($event)"
[filterConfigs]="filterConfigs"
[actionConfigs]="actionConfigs"
[searchPlaceholder]="'dossier-overview.search'"
></redaction-page-header>
<!-- <div class="page-header">-->
<!-- <div class="filters">-->
<!-- <div translate="filters.filter-by"></div>-->
<!-- <redaction-popup-filter-->
<!-- (filtersChanged)="filtersChanged()"-->
<!-- [filterLabel]="'filters.status'"-->
<!-- [icon]="'red:status'"-->
<!-- [primaryFilters]="statusFilters"-->
<!-- ></redaction-popup-filter>-->
<!-- <redaction-popup-filter-->
<!-- (filtersChanged)="filtersChanged()"-->
<!-- [filterLabel]="'filters.assigned-people'"-->
<!-- [icon]="'red:user'"-->
<!-- [primaryFilters]="peopleFilters"-->
<!-- ></redaction-popup-filter>-->
<!-- <redaction-popup-filter-->
<!-- (filtersChanged)="filtersChanged()"-->
<!-- [filterLabel]="'filters.needs-work'"-->
<!-- [filterTemplate]="needsWorkTemplate"-->
<!-- [icon]="'red:needs-work'"-->
<!-- [primaryFilters]="needsWorkFilters"-->
<!-- ></redaction-popup-filter>-->
[showResetFilters]="showResetFilters"
[showCloseButton]="true"
[searchPlaceholder]="'dossier-overview.search' | translate"
>
<redaction-file-download-btn
[disabled]="areSomeEntitiesSelected"
[dossier]="activeDossier"
[file]="allEntities"
tooltipPosition="below"
></redaction-file-download-btn>
<!-- <redaction-input-with-action-->
<!-- [form]="searchForm"-->
<!-- [placeholder]="'dossier-overview.search'"-->
<!-- type="search"-->
<!-- ></redaction-input-with-action>-->
<redaction-circle-button
(action)="reanalyseDossier()"
*ngIf="permissionsService.displayReanalyseBtn()"
[disabled]="areSomeEntitiesSelected"
[tooltipClass]="'small ' + (areSomeEntitiesSelected ? '' : 'warn')"
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
icon="red:refresh"
tooltipPosition="below"
type="warn"
></redaction-circle-button>
<!-- <div-->
<!-- (click)="resetFilters()"-->
<!-- *ngIf="hasActiveFilters"-->
<!-- class="reset-filters"-->
<!-- translate="reset-filters"-->
<!-- ></div>-->
<!-- </div>-->
<!-- <div class="actions">-->
<!-- <redaction-circle-button-->
<!-- (action)="openEditDossierDialog($event)"-->
<!-- *ngIf="permissionsService.isManager()"-->
<!-- icon="red:edit"-->
<!-- tooltip="dossier-overview.header-actions.edit"-->
<!-- tooltipPosition="below"-->
<!-- ></redaction-circle-button>-->
<!-- <redaction-file-download-btn-->
<!-- [disabled]="areSomeEntitiesSelected"-->
<!-- [dossier]="activeDossier"-->
<!-- [file]="allEntities"-->
<!-- tooltipPosition="below"-->
<!-- ></redaction-file-download-btn>-->
<!-- <redaction-circle-button-->
<!-- (action)="reanalyseDossier()"-->
<!-- *ngIf="permissionsService.displayReanalyseBtn()"-->
<!-- [disabled]="areSomeEntitiesSelected"-->
<!-- [tooltipClass]="'small ' + (areSomeEntitiesSelected ? '' : 'warn')"-->
<!-- [tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all'"-->
<!-- icon="red:refresh"-->
<!-- tooltipPosition="below"-->
<!-- type="warn"-->
<!-- ></redaction-circle-button>-->
<!-- <redaction-circle-button-->
<!-- (action)="fileInput.click()"-->
<!-- class="ml-14"-->
<!-- icon="red:upload"-->
<!-- tooltip="dossier-overview.header-actions.upload-document"-->
<!-- tooltipPosition="below"-->
<!-- type="primary"-->
<!-- ></redaction-circle-button>-->
<!-- <redaction-circle-button-->
<!-- [routerLink]="['/main/dossiers/']"-->
<!-- class="ml-6"-->
<!-- icon="red:close"-->
<!-- tooltip="common.close"-->
<!-- tooltipPosition="below"-->
<!-- ></redaction-circle-button>-->
<!-- </div>-->
<!-- </div>-->
<redaction-circle-button
(action)="fileInput.click()"
class="ml-14"
icon="red:upload"
[tooltip]="'dossier-overview.header-actions.upload-document' | translate"
tooltipPosition="below"
type="primary"
></redaction-circle-button>
</redaction-page-header>
<div class="overlay-shadow"></div>
@ -113,7 +63,7 @@
></redaction-dossier-overview-bulk-actions>
<redaction-quick-filters
(filtersChanged)="filtersChanged()"
(filtersChanged)="filtersChanged($event)"
[filters]="quickFilters"
></redaction-quick-filters>
</div>

View File

@ -96,10 +96,6 @@ cdk-virtual-scroll-viewport {
}
}
.ml-6 {
margin-left: 6px;
}
.mr-4 {
margin-right: 4px;
}

View File

@ -37,12 +37,9 @@ import {
processFilters
} from '@shared/components/filters/popup-filter/utils/filter-utils';
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
import { QuickFiltersComponent } from '../../../shared/components/filters/quick-filters/quick-filters.component';
import { AppConfigService } from '../../../app-config/app-config.service';
import {
ActionConfig,
FilterConfig
} from '../../../shared/components/page-header/page-header.component';
import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service';
import { FilterConfig } from '@shared/components/page-header/models/filter-config.model';
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
@Component({
selector: 'redaction-dossier-overview-screen',
@ -78,8 +75,6 @@ export class DossierOverviewScreenComponent
private _lastScrollPosition: number;
private _lastOpenedFileId = '';
@ViewChild(QuickFiltersComponent)
protected readonly _quickFiltersComponent: QuickFiltersComponent;
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
private readonly _needsWorkTemplate: TemplateRef<any>;
@ViewChild('fileInput') private _fileInput: ElementRef;
@ -184,8 +179,6 @@ export class DossierOverviewScreenComponent
this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top');
}
});
this._filterComponents = [this._quickFiltersComponent];
}
ngOnDestroy(): void {
@ -317,7 +310,7 @@ export class DossierOverviewScreenComponent
recentlyModifiedChecker = (file: FileStatusWrapper) =>
moment(file.lastUpdated)
.add(this._appConfigService.getConfig('RECENT_PERIOD_IN_HOURS'), 'hours')
.add(this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS), 'hours')
.isAfter(moment());
protected _preFilter() {
@ -403,12 +396,15 @@ export class DossierOverviewScreenComponent
private _createQuickFilters() {
if (this.allEntities.filter(this.recentlyModifiedChecker).length > 0) {
const recentPeriodInHours = this._appConfigService.getConfig('RECENT_PERIOD_IN_HOURS');
const recentPeriod = this._appConfigService.getConfig(
AppConfigKey.RECENT_PERIOD_IN_HOURS
);
this.quickFilters = [
{
key: this.user.id,
label: 'dossier-overview.quick-filters.recent',
labelParams: { hours: recentPeriodInHours },
label: this._translateService.instant('dossier-overview.quick-filters.recent', {
hours: recentPeriod
}),
required: true,
checker: this.recentlyModifiedChecker
}
@ -421,17 +417,21 @@ export class DossierOverviewScreenComponent
...this.quickFilters,
{
key: this.user.id,
label: 'dossier-overview.quick-filters.assigned-to-me',
label: this._translateService.instant(
'dossier-overview.quick-filters.assigned-to-me'
),
checker: (file: FileStatusWrapper) => file.currentReviewer === this.user.id
},
{
key: this.user.id,
label: 'dossier-overview.quick-filters.unassigned',
label: this._translateService.instant('dossier-overview.quick-filters.unassigned'),
checker: (file: FileStatusWrapper) => !file.currentReviewer
},
{
key: this.user.id,
label: 'dossier-overview.quick-filters.assigned-to-others',
label: this._translateService.instant(
'dossier-overview.quick-filters.assigned-to-others'
),
checker: (file: FileStatusWrapper) =>
!!file.currentReviewer && file.currentReviewer !== this.user.id
}
@ -441,17 +441,17 @@ export class DossierOverviewScreenComponent
private _createFilterConfigs() {
this.filterConfigs = [
{
label: 'filters.status',
label: this._translateService.instant('filters.status'),
primaryFilters: this.statusFilters,
icon: 'red:status'
},
{
label: 'filters.assigned-people',
label: this._translateService.instant('filters.assigned-people'),
primaryFilters: this.peopleFilters,
icon: 'red:user'
},
{
label: 'filters.needs-work',
label: this._translateService.instant('filters.needs-work'),
primaryFilters: this.needsWorkFilters,
icon: 'red:needs-work',
filterTemplate: this._needsWorkTemplate
@ -462,13 +462,7 @@ export class DossierOverviewScreenComponent
private _createActionConfigs() {
this.actionConfigs = [
{
label: 'dossier-overview.header-actions.edit',
action: $event => this.openEditDossierDialog($event),
icon: 'red:edit',
hide: !this.permissionsService.isManager()
},
{
label: 'dossier-overview.header-actions.edit',
label: this._translateService.instant('dossier-overview.header-actions.edit'),
action: $event => this.openEditDossierDialog($event),
icon: 'red:edit',
hide: !this.permissionsService.isManager()

View File

@ -3,7 +3,6 @@ import { FormBuilder, FormGroup } from '@angular/forms';
import { debounce } from '@utils/debounce';
import { ScreenName, SortingOption, SortingService } from '@services/sorting.service';
import { FilterModel } from '../components/filters/popup-filter/model/filter.model';
import { PopupFilterComponent } from '../components/filters/popup-filter/popup-filter.component';
import { getFilteredEntities } from '../components/filters/popup-filter/utils/filter-utils';
import { QuickFiltersComponent } from '../components/filters/quick-filters/quick-filters.component';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
@ -19,6 +18,7 @@ export abstract class BaseListingComponent<T = any> {
displayedEntities: T[] = [];
selectedEntitiesIds: string[] = [];
searchForm: FormGroup;
showResetFilters = false;
@ViewChild(CdkVirtualScrollViewport) scrollViewport: CdkVirtualScrollViewport;
protected readonly _formBuilder: FormBuilder;
@ -31,7 +31,8 @@ export abstract class BaseListingComponent<T = any> {
protected readonly _selectionKey: string;
protected readonly _sortKey: ScreenName;
// Overwrite this in ngOnInit
protected _filterComponents: (PopupFilterComponent | QuickFiltersComponent)[] = [];
@ViewChild(QuickFiltersComponent)
protected _quickFilters: QuickFiltersComponent;
private _searchValue = '';
@ -87,26 +88,25 @@ export abstract class BaseListingComponent<T = any> {
return this._sortKey;
}
filtersChanged(filters?: { [key: string]: FilterModel[] }): void {
if (filters) {
for (const key of Object.keys(filters)) {
for (let idx = 0; idx < this[key].length; ++idx) {
filtersChanged(filters?: { [key: string]: FilterModel[] } | FilterModel[]): void {
if (filters instanceof Array) this.showResetFilters = !!filters.find(f => f.checked);
else
for (const key of Object.keys(filters ?? {})) {
for (let idx = 0; idx < this[key]?.length; ++idx) {
this[key][idx] = filters[key][idx];
}
}
}
this._filterEntities();
}
resetFilters() {
for (const filterComponent of this._filterComponents.filter(f => !!f)) {
filterComponent.deactivateFilters();
}
this._quickFilters.deactivateFilters();
this.showResetFilters = false;
this.filtersChanged();
}
// Filter
toggleEntitySelected($event: MouseEvent, entity: T) {
$event.stopPropagation();
const idx = this.selectedEntitiesIds.indexOf(entity[this._getSelectionKey]);

View File

@ -1,5 +1,12 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
export type IconButtonType = 'default' | 'show-bg' | 'primary';
export enum IconButtonTypes {
DEFAULT = 'default',
SHOW_BG = 'show-bg',
PRIMARY = 'primary'
}
@Component({
selector: 'redaction-icon-button',
templateUrl: './icon-button.component.html',
@ -11,6 +18,6 @@ export class IconButtonComponent {
@Input() text: string;
@Input() showDot = false;
@Input() disabled = false;
@Input() type: 'default' | 'show-bg' | 'primary' = 'default';
@Input() type: IconButtonType = IconButtonTypes.DEFAULT;
@Output() action = new EventEmitter<any>();
}

View File

@ -11,6 +11,7 @@ import {
import { FilterModel } from './model/filter.model';
import { handleCheckedValue } from './utils/filter-utils';
import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'redaction-popup-filter',
@ -36,22 +37,20 @@ export class PopupFilterComponent implements OnChanges {
@Input() actionsTemplate: TemplateRef<any>;
@Input() primaryFilters: FilterModel[] = [];
@Input() secondaryFilters: FilterModel[] = [];
@Input() filterLabel = 'filter-menu.label';
@Input() filterLabel = this._translateService.instant('filter-menu.label');
@Input() icon: string;
@Input() chevron = false;
atLeastOneFilterIsExpandable = false;
atLeastOneSecondaryFilterIsExpandable = false;
constructor(private readonly _changeDetectorRef: ChangeDetectorRef) {}
constructor(
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _translateService: TranslateService
) {}
get hasActiveFilters(): boolean {
for (const filter of this._allFilters) {
if (filter.checked || filter.indeterminate) {
return true;
}
}
return false;
return !!this._allFilters.find(f => f.checked || f.indeterminate);
}
private get _allFilters(): FilterModel[] {
@ -90,11 +89,11 @@ export class PopupFilterComponent implements OnChanges {
}
applyFilters() {
this._changeDetectorRef.detectChanges();
this.filtersChanged.emit({
primary: this.primaryFilters,
secondary: this.secondaryFilters
});
this._changeDetectorRef.detectChanges();
}
toggleFilterExpanded($event: MouseEvent, filter: FilterModel) {
@ -103,7 +102,7 @@ export class PopupFilterComponent implements OnChanges {
}
isExpandable(filter: FilterModel) {
return filter.filters && filter.filters.length > 0;
return filter?.filters?.length > 0;
}
_(obj): FilterModel {

View File

@ -0,0 +1,5 @@
import { BaseHeaderConfig } from './base-config.model';
export interface ActionConfig extends BaseHeaderConfig {
action: ($event) => void;
}

View File

@ -0,0 +1,5 @@
export interface BaseHeaderConfig {
label: string;
icon?: string;
hide?: boolean;
}

View File

@ -0,0 +1,7 @@
import { IconButtonType } from '../../buttons/icon-button/icon-button.component';
import { BaseHeaderConfig } from './base-config.model';
export interface ButtonConfig extends BaseHeaderConfig {
action: ($event) => void;
type?: IconButtonType;
}

View File

@ -0,0 +1,8 @@
import { FilterModel } from '../../filters/popup-filter/model/filter.model';
import { TemplateRef } from '@angular/core';
import { BaseHeaderConfig } from './base-config.model';
export interface FilterConfig extends BaseHeaderConfig {
primaryFilters: FilterModel[];
filterTemplate?: TemplateRef<any>;
}

View File

@ -1,5 +1,5 @@
<div class="page-header">
<div *ngIf="pageLabel" class="breadcrumb" translate>{{ pageLabel }}</div>
<div *ngIf="pageLabel" class="breadcrumb">{{ pageLabel }}</div>
<div class="filters" *ngIf="filterConfigs">
<div translate="filters.filter-by"></div>
@ -29,18 +29,6 @@
></div>
</div>
<div class="actions" *ngIf="actionConfigs">
<ng-container *ngFor="let config of actionConfigs; trackBy: trackByLabel">
<redaction-circle-button
(action)="config.action($event)"
*ngIf="!config.hide"
[icon]="config.icon"
[tooltip]="config.label"
tooltipPosition="below"
></redaction-circle-button>
</ng-container>
</div>
<ng-container *ngFor="let config of buttonConfigs; trackBy: trackByLabel">
<redaction-icon-button
(action)="config.action($event)"
@ -51,11 +39,26 @@
></redaction-icon-button>
</ng-container>
<redaction-circle-button
*ngIf="showCloseButton && permissionsService.isUser()"
icon="red:close"
redactionNavigateLastDossiersScreen
tooltip="common.close"
tooltipPosition="below"
></redaction-circle-button>
<div class="actions" *ngIf="actionConfigs">
<ng-container *ngFor="let config of actionConfigs; trackBy: trackByLabel">
<redaction-circle-button
(action)="config.action($event)"
*ngIf="!config.hide"
[icon]="config.icon"
[tooltip]="config.label"
tooltipPosition="below"
></redaction-circle-button>
</ng-container>
<ng-content></ng-content>
<redaction-circle-button
[class.ml-6]="actionConfigs"
*ngIf="showCloseButton && permissionsService.isUser()"
icon="red:close"
redactionNavigateLastDossiersScreen
tooltip="common.close"
tooltipPosition="below"
></redaction-circle-button>
</div>
</div>

View File

@ -1,3 +1,3 @@
.page-header .actions > *:not(:last-child) {
margin-right: 16px;
.ml-6 {
margin-left: 6px;
}

View File

@ -5,33 +5,16 @@ import {
Input,
Output,
QueryList,
TemplateRef,
ViewChildren
} from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
import { PopupFilterComponent } from '@shared/components/filters/popup-filter/popup-filter.component';
import { FormBuilder, FormGroup } from '@angular/forms';
interface BaseHeaderConfig {
label: string;
icon?: string;
hide?: boolean;
}
export interface FilterConfig extends BaseHeaderConfig {
primaryFilters: FilterModel[];
filterTemplate?: TemplateRef<any>;
}
export interface ActionConfig extends BaseHeaderConfig {
action: ($event) => void;
}
export interface ButtonConfig extends BaseHeaderConfig {
action: ($event) => void;
type?: 'default' | 'show-bg' | 'primary';
}
import { FormBuilder } from '@angular/forms';
import { FilterConfig } from '@shared/components/page-header/models/filter-config.model';
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
import { ButtonConfig } from '@shared/components/page-header/models/button-config.model';
import { BaseHeaderConfig } from '@shared/components/page-header/models/base-config.model';
@Component({
selector: 'redaction-page-header',
@ -42,14 +25,21 @@ export interface ButtonConfig extends BaseHeaderConfig {
export class PageHeaderComponent {
@Input() pageLabel: string;
@Input() showCloseButton: boolean;
@Input() showResetFilters: boolean;
@Input() filterConfigs: FilterConfig[];
@Input() actionConfigs: ActionConfig[];
@Input() buttonConfigs: ButtonConfig[];
@Input() searchPlaceholder: string;
@Output() filtersChanged = new EventEmitter<any>();
@Output() filtersChanged = new EventEmitter<{
primary: FilterModel[];
secondary?: FilterModel[];
}>();
@Output() filtersReset = new EventEmitter<never>();
@Output() searchChanged = new EventEmitter<string>();
searchForm: FormGroup;
readonly searchForm = this._formBuilder.group({
query: ['']
});
@ViewChildren(PopupFilterComponent)
private readonly _filterComponents: QueryList<PopupFilterComponent>;
@ -58,34 +48,24 @@ export class PageHeaderComponent {
readonly permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder
) {
this._initSearch();
this.searchForm.valueChanges.subscribe(value => this.searchChanged.emit(value.query));
}
get hasActiveFilters() {
return (
this._filterComponents
?.filter(f => !!f)
.reduce((prev, component) => prev || component?.hasActiveFilters, false) ||
this.searchForm.get('query').value
const hasActiveFilters = this._filterComponents?.reduce(
(acc, component) => acc || component?.hasActiveFilters,
false
);
return hasActiveFilters || this.searchForm.get('query').value || this.showResetFilters;
}
resetFilters() {
for (const filterComponent of this._filterComponents.filter(f => !!f)) {
filterComponent.deactivateFilters();
}
this.filtersChanged.emit();
this._filterComponents.forEach(component => component?.deactivateFilters());
this.filtersReset.emit();
this.searchForm.reset({ query: '' });
}
private _initSearch() {
this.searchForm = this._formBuilder.group({
query: ['']
});
this.searchForm.valueChanges.subscribe(value => this.searchChanged.emit(value.query));
}
trackByLabel(index: number, item: BaseHeaderConfig) {
return item.label;
}