filter search results by dossier
This commit is contained in:
parent
e50e5cbfb2
commit
c61e6e1aa5
@ -9,7 +9,6 @@
|
|||||||
<redaction-popup-filter
|
<redaction-popup-filter
|
||||||
(filtersChanged)="filtersChanged($event)"
|
(filtersChanged)="filtersChanged($event)"
|
||||||
[actionsTemplate]="annotationFilterActionTemplate"
|
[actionsTemplate]="annotationFilterActionTemplate"
|
||||||
[chevron]="true"
|
|
||||||
[filterTemplate]="annotationFilterTemplate"
|
[filterTemplate]="annotationFilterTemplate"
|
||||||
[primaryFilters]="primaryFilters"
|
[primaryFilters]="primaryFilters"
|
||||||
[secondaryFilters]="secondaryFilters"
|
[secondaryFilters]="secondaryFilters"
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
[searchPlaceholder]="'search.placeholder' | translate"
|
[searchPlaceholder]="'search.placeholder' | translate"
|
||||||
[searchWidth]="600"
|
[searchWidth]="600"
|
||||||
[showCloseButton]="true"
|
[showCloseButton]="true"
|
||||||
|
[searchPosition]="searchPositions.beforeFilters"
|
||||||
></redaction-page-header>
|
></redaction-page-header>
|
||||||
|
|
||||||
<div class="overlay-shadow"></div>
|
<div class="overlay-shadow"></div>
|
||||||
@ -25,13 +26,13 @@
|
|||||||
class="table-item"
|
class="table-item"
|
||||||
>
|
>
|
||||||
<div class="filename">
|
<div class="filename">
|
||||||
<div [matTooltip]="item.fileName" class="table-item-title heading" matTooltipPosition="above">
|
<div [matTooltip]="item.filename" class="table-item-title heading" matTooltipPosition="above">
|
||||||
<span
|
<span
|
||||||
*ngIf="item.highlights.filename; else defaultFilename"
|
*ngIf="item.highlights.filename; else defaultFilename"
|
||||||
[innerHTML]="item.highlights.filename[0]"
|
[innerHTML]="item.highlights.filename[0]"
|
||||||
class="highlights"
|
class="highlights"
|
||||||
></span>
|
></span>
|
||||||
<ng-template #defaultFilename>{{ item.fileName }}</ng-template>
|
<ng-template #defaultFilename>{{ item.filename }}</ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="item.highlights['sections.text'] as highlights">
|
<ng-container *ngIf="item.highlights['sections.text'] as highlights">
|
||||||
@ -49,7 +50,7 @@
|
|||||||
> <s>{{ term }}</s></span
|
> <s>{{ term }}</s></span
|
||||||
>. {{ 'search-screen.must-contain' | translate }}:
|
>. {{ 'search-screen.must-contain' | translate }}:
|
||||||
<span
|
<span
|
||||||
(click)="$event.stopPropagation(); updateNavigation({ query: search$.getValue(), mustContain: term })"
|
(click)="$event.stopPropagation(); updateNavigation(search$.getValue(), term)"
|
||||||
*ngFor="let term of unmatched"
|
*ngFor="let term of unmatched"
|
||||||
> <u>{{ term }}</u></span
|
> <u>{{ term }}</u></span
|
||||||
>
|
>
|
||||||
@ -78,7 +79,7 @@
|
|||||||
<div class="small-label stats-subtitle">
|
<div class="small-label stats-subtitle">
|
||||||
<div>
|
<div>
|
||||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||||
{{ item.pages }}
|
{{ item.numberOfPages }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -87,7 +88,7 @@
|
|||||||
</cdk-virtual-scroll-viewport>
|
</cdk-virtual-scroll-viewport>
|
||||||
|
|
||||||
<redaction-scroll-button
|
<redaction-scroll-button
|
||||||
*ngIf="(screenStateService.noData$ | async) === false"
|
*ngIf="searchResult.length"
|
||||||
[itemSize]="itemSize"
|
[itemSize]="itemSize"
|
||||||
[scrollViewport]="scrollViewport"
|
[scrollViewport]="scrollViewport"
|
||||||
></redaction-scroll-button>
|
></redaction-scroll-button>
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Component, Injector, OnDestroy } from '@angular/core';
|
|||||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||||
import { MatchedDocument, SearchControllerService, SearchResult } from '@redaction/red-ui-http';
|
import { MatchedDocument, SearchControllerService, SearchResult } from '@redaction/red-ui-http';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { debounceTime, map, switchMap, tap } from 'rxjs/operators';
|
import { debounceTime, map, skip, switchMap, tap } from 'rxjs/operators';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { TableColConfig } from '../../../shared/components/table-col-name/table-col-name.component';
|
import { TableColConfig } from '../../../shared/components/table-col-name/table-col-name.component';
|
||||||
import { FilterService } from '../../../shared/services/filter.service';
|
import { FilterService } from '../../../shared/services/filter.service';
|
||||||
@ -14,16 +14,20 @@ import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
|
|||||||
import { LoadingService } from '../../../../services/loading.service';
|
import { LoadingService } from '../../../../services/loading.service';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||||
|
import { searchPositions } from '../../../shared/components/page-header/models/search-positions.type';
|
||||||
|
import { keyChecker } from '../../../shared/components/filters/popup-filter/utils/filter-utils';
|
||||||
|
import { DossierWrapper } from '../../../../state/model/dossier.wrapper';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
interface ListItem {
|
interface ListItem {
|
||||||
fileName: string;
|
readonly dossierId: string;
|
||||||
matchedDocument: MatchedDocument;
|
readonly filename: string;
|
||||||
unmatched: string[] | null;
|
readonly unmatched: string[] | null;
|
||||||
highlights: { [key: string]: string[] };
|
readonly highlights: { [key: string]: string[] };
|
||||||
routerLink: string;
|
readonly routerLink: string;
|
||||||
status: string;
|
readonly status: string;
|
||||||
dossierName: string;
|
readonly dossierName: string;
|
||||||
pages: number;
|
readonly numberOfPages: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -32,14 +36,15 @@ interface ListItem {
|
|||||||
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
providers: [FilterService, SearchService, ScreenStateService, SortingService]
|
||||||
})
|
})
|
||||||
export class SearchScreenComponent extends BaseListingComponent<ListItem> implements OnDestroy {
|
export class SearchScreenComponent extends BaseListingComponent<ListItem> implements OnDestroy {
|
||||||
fileStatusTranslations = fileStatusTranslations;
|
readonly fileStatusTranslations = fileStatusTranslations;
|
||||||
|
readonly searchPositions = searchPositions;
|
||||||
|
|
||||||
readonly itemSize = 85;
|
readonly itemSize = 85;
|
||||||
readonly search$ = new BehaviorSubject<string>(null);
|
readonly search$ = new BehaviorSubject<string>(null);
|
||||||
readonly searchResults$: Observable<ListItem[]> = this.search$.asObservable().pipe(
|
readonly searchResults$: Observable<ListItem[]> = this.search$.asObservable().pipe(
|
||||||
switchMap(query => this._search(query)),
|
switchMap(query => this._search(query)),
|
||||||
map(searchResult => this._toMatchedDocuments(searchResult)),
|
map(searchResult => this._toMatchedDocuments(searchResult)),
|
||||||
map(documents => this._toListItems(documents)),
|
map(docs => this._toListItems(docs)),
|
||||||
tap(result => this.screenStateService.setEntities(result)),
|
tap(result => this.screenStateService.setEntities(result)),
|
||||||
tap(() => this._loadingService.stop())
|
tap(() => this._loadingService.stop())
|
||||||
);
|
);
|
||||||
@ -58,7 +63,7 @@ export class SearchScreenComponent extends BaseListingComponent<ListItem> implem
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
protected readonly _primaryKey = 'fileName';
|
protected readonly _primaryKey = 'fileName';
|
||||||
protected _tableHeaderLabel = _('search-screen.table-header');
|
protected readonly _tableHeaderLabel = _('search-screen.table-header');
|
||||||
private _dossierId: string;
|
private _dossierId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -67,38 +72,47 @@ export class SearchScreenComponent extends BaseListingComponent<ListItem> implem
|
|||||||
private readonly _activatedRoute: ActivatedRoute,
|
private readonly _activatedRoute: ActivatedRoute,
|
||||||
private readonly _appStateService: AppStateService,
|
private readonly _appStateService: AppStateService,
|
||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
|
private readonly _translateService: TranslateService,
|
||||||
private readonly _router: Router
|
private readonly _router: Router
|
||||||
) {
|
) {
|
||||||
super(_injector);
|
super(_injector);
|
||||||
|
|
||||||
|
this.filterService.addFilterGroup({
|
||||||
|
slug: 'dossiers',
|
||||||
|
label: this._translateService.instant('search-screen.filters.by-dossier'),
|
||||||
|
icon: 'red:folder',
|
||||||
|
values: this._appStateService.allDossiers.map(dossier => ({
|
||||||
|
key: dossier.dossierId,
|
||||||
|
label: dossier.dossierName
|
||||||
|
})),
|
||||||
|
checker: keyChecker('dossierId')
|
||||||
|
});
|
||||||
|
|
||||||
this.addSubscription = _activatedRoute.queryParamMap
|
this.addSubscription = _activatedRoute.queryParamMap
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(() => this._loadingService.start()),
|
tap(() => this._loadingService.start()),
|
||||||
map(value => ({ query: value.get('query'), dossierId: value.get('dossierId') })),
|
map(value => ({ query: value.get('query'), dossierId: value.get('dossierId') }))
|
||||||
tap(mappedValue => this._updateValues(mappedValue))
|
|
||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe(mappedValue => this._updateValues(mappedValue));
|
||||||
|
|
||||||
this.addSubscription = this.searchService.searchForm
|
this.addSubscription = this.searchService.searchForm
|
||||||
.get('query')
|
.get('query')
|
||||||
.valueChanges.pipe(debounceTime(300))
|
.valueChanges.pipe(debounceTime(300))
|
||||||
.subscribe(value => this.updateNavigation({ query: value }));
|
.subscribe(value => this.updateNavigation(value));
|
||||||
|
|
||||||
|
this.addSubscription = this.filterService.filterGroups$
|
||||||
|
.pipe(skip(1))
|
||||||
|
.subscribe(() => this.updateNavigation(this.search$.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
setInitialConfig() {
|
setInitialConfig() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNavigation({ query, mustContain }: { readonly query: string; readonly mustContain?: string }) {
|
updateNavigation(query: string, mustContain?: string) {
|
||||||
const newQuery = query?.replace(mustContain, `"${mustContain}"`);
|
const newQuery = query?.replace(mustContain, `"${mustContain}"`);
|
||||||
const queryParams = newQuery && newQuery !== '' ? { query: newQuery } : {};
|
const queryParams = newQuery && newQuery !== '' ? { query: newQuery } : {};
|
||||||
const queryParamsHandling = this._dossierId ? 'merge' : '';
|
this._router.navigate([], { queryParams }).then();
|
||||||
this._router
|
|
||||||
.navigate([], {
|
|
||||||
queryParams,
|
|
||||||
queryParamsHandling
|
|
||||||
})
|
|
||||||
.then();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _search(query: string): Observable<SearchResult> {
|
private _search(query: string): Observable<SearchResult> {
|
||||||
@ -112,6 +126,7 @@ export class SearchScreenComponent extends BaseListingComponent<ListItem> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _updateValues({ query, dossierId }: { readonly query: string; readonly dossierId: string }) {
|
private _updateValues({ query, dossierId }: { readonly query: string; readonly dossierId: string }) {
|
||||||
|
if (dossierId) this.filterService.toggleFilter('dossiers', dossierId);
|
||||||
this._dossierId = dossierId;
|
this._dossierId = dossierId;
|
||||||
this.searchService.searchValue = query;
|
this.searchService.searchValue = query;
|
||||||
this.search$.next(query);
|
this.search$.next(query);
|
||||||
@ -121,34 +136,31 @@ export class SearchScreenComponent extends BaseListingComponent<ListItem> implem
|
|||||||
return this._appStateService.getFileById(dossierId, fileId);
|
return this._appStateService.getFileById(dossierId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getDossierWrapper(dossierId: string) {
|
private _getDossierWrapper(dossierId: string): DossierWrapper {
|
||||||
return this._appStateService.getDossierById(dossierId);
|
return this._appStateService.getDossierById(dossierId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _toMatchedDocuments({ matchedDocuments }: SearchResult) {
|
private _toMatchedDocuments({ matchedDocuments }: SearchResult): MatchedDocument[] {
|
||||||
return matchedDocuments.filter(doc => doc.score > 0 && doc.matchedTerms.length > 0);
|
return matchedDocuments.filter(doc => doc.score > 0 && doc.matchedTerms.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _toListItems(matchedDocuments: MatchedDocument[]) {
|
private _toListItems(matchedDocuments: MatchedDocument[]): ListItem[] {
|
||||||
return matchedDocuments
|
return matchedDocuments.map(document => this._toListItem(document)).filter(value => value);
|
||||||
.map<ListItem>(document => {
|
}
|
||||||
const fileStatus = this._getFileWrapper(document.dossierId, document.fileId);
|
|
||||||
if (!fileStatus) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { dossierId, dossierName } = this._getDossierWrapper(document.dossierId);
|
private _toListItem({ dossierId, fileId, unmatchedTerms, highlights }: MatchedDocument): ListItem {
|
||||||
return {
|
const fileWrapper = this._getFileWrapper(dossierId, fileId);
|
||||||
matchedDocument: document,
|
if (!fileWrapper) return undefined;
|
||||||
unmatched: document.unmatchedTerms.length ? document.unmatchedTerms : null,
|
|
||||||
highlights: document.highlights,
|
return {
|
||||||
status: fileStatus.status,
|
dossierId,
|
||||||
pages: fileStatus.numberOfPages,
|
unmatched: unmatchedTerms || null,
|
||||||
dossierName: dossierName,
|
highlights,
|
||||||
fileName: fileStatus.filename,
|
status,
|
||||||
routerLink: `/main/dossiers/${dossierId}/file/${fileStatus.fileId}`
|
numberOfPages: fileWrapper.numberOfPages,
|
||||||
} as ListItem;
|
dossierName: this._getDossierWrapper(dossierId).dossierName,
|
||||||
})
|
filename: fileWrapper.filename,
|
||||||
.filter(value => value);
|
routerLink: `/main/dossiers/${dossierId}/file/${fileId}`
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<redaction-icon-button
|
<redaction-icon-button
|
||||||
*ngIf="!chevron"
|
*ngIf="icon"
|
||||||
[icon]="icon"
|
[icon]="icon"
|
||||||
[label]="filterLabel || ('filter-menu.label' | translate)"
|
[label]="filterLabel || ('filter-menu.label' | translate)"
|
||||||
[matMenuTriggerFor]="filterMenu"
|
[matMenuTriggerFor]="filterMenu"
|
||||||
@ -7,7 +7,7 @@
|
|||||||
></redaction-icon-button>
|
></redaction-icon-button>
|
||||||
|
|
||||||
<redaction-chevron-button
|
<redaction-chevron-button
|
||||||
*ngIf="chevron"
|
*ngIf="!icon"
|
||||||
[label]="filterLabel || ('filter-menu.label' | translate)"
|
[label]="filterLabel || ('filter-menu.label' | translate)"
|
||||||
[matMenuTriggerFor]="filterMenu"
|
[matMenuTriggerFor]="filterMenu"
|
||||||
[showDot]="hasActiveFilters"
|
[showDot]="hasActiveFilters"
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, T
|
|||||||
import { FilterModel } from './model/filter.model';
|
import { FilterModel } from './model/filter.model';
|
||||||
import { handleCheckedValue } from './utils/filter-utils';
|
import { handleCheckedValue } from './utils/filter-utils';
|
||||||
import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox';
|
import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-popup-filter',
|
selector: 'redaction-popup-filter',
|
||||||
@ -29,12 +28,11 @@ export class PopupFilterComponent implements OnChanges {
|
|||||||
@Input() secondaryFilters: FilterModel[] = [];
|
@Input() secondaryFilters: FilterModel[] = [];
|
||||||
@Input() filterLabel;
|
@Input() filterLabel;
|
||||||
@Input() icon: string;
|
@Input() icon: string;
|
||||||
@Input() chevron = false;
|
|
||||||
|
|
||||||
atLeastOneFilterIsExpandable = false;
|
atLeastOneFilterIsExpandable = false;
|
||||||
atLeastOneSecondaryFilterIsExpandable = false;
|
atLeastOneSecondaryFilterIsExpandable = false;
|
||||||
|
|
||||||
constructor(private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _translateService: TranslateService) {}
|
constructor(private readonly _changeDetectorRef: ChangeDetectorRef) {}
|
||||||
|
|
||||||
get hasActiveFilters(): boolean {
|
get hasActiveFilters(): boolean {
|
||||||
return !!this._allFilters.find(f => f.checked || f.indeterminate);
|
return !!this._allFilters.find(f => f.checked || f.indeterminate);
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
export const searchPositions = {
|
||||||
|
beforeFilters: 'beforeFilters',
|
||||||
|
afterFilters: 'afterFilters'
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type SearchPosition = keyof typeof searchPositions;
|
||||||
@ -1,8 +1,10 @@
|
|||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<div *ngIf="pageLabel" class="breadcrumb">{{ pageLabel }}</div>
|
<div *ngIf="pageLabel" class="breadcrumb">{{ pageLabel }}</div>
|
||||||
|
|
||||||
<div *ngIf="filters$ | async as filters" [style.max-width]="computedWidth" [style.width]="computedWidth" class="filters">
|
<div *ngIf="filters$ | async as filters" class="filters">
|
||||||
<div *ngIf="filters.length" translate="filters.filter-by"></div>
|
<div *ngIf="filters.length && searchPosition !== searchPositions.beforeFilters" translate="filters.filter-by"></div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="searchPosition === searchPositions.beforeFilters" [ngTemplateOutlet]="searchBar"></ng-container>
|
||||||
|
|
||||||
<ng-container *ngFor="let config of filters; trackBy: trackByLabel">
|
<ng-container *ngFor="let config of filters; trackBy: trackByLabel">
|
||||||
<redaction-popup-filter
|
<redaction-popup-filter
|
||||||
@ -15,13 +17,7 @@
|
|||||||
></redaction-popup-filter>
|
></redaction-popup-filter>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<redaction-input-with-action
|
<ng-container *ngIf="searchPosition === searchPositions.afterFilters" [ngTemplateOutlet]="searchBar"></ng-container>
|
||||||
*ngIf="searchPlaceholder"
|
|
||||||
[form]="searchService.searchForm"
|
|
||||||
[placeholder]="searchPlaceholder"
|
|
||||||
[width]="searchWidth"
|
|
||||||
type="search"
|
|
||||||
></redaction-input-with-action>
|
|
||||||
|
|
||||||
<div (click)="resetFilters()" *ngIf="showResetFilters$ | async" class="reset-filters" translate="reset-filters"></div>
|
<div (click)="resetFilters()" *ngIf="showResetFilters$ | async" class="reset-filters" translate="reset-filters"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -60,3 +56,14 @@
|
|||||||
></redaction-circle-button>
|
></redaction-circle-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ng-template #searchBar>
|
||||||
|
<redaction-input-with-action
|
||||||
|
*ngIf="searchPlaceholder && searchService"
|
||||||
|
[form]="searchService.searchForm"
|
||||||
|
[placeholder]="searchPlaceholder"
|
||||||
|
[width]="searchWidth"
|
||||||
|
[class.mr-8]="searchPosition === searchPositions.beforeFilters"
|
||||||
|
type="search"
|
||||||
|
></redaction-input-with-action>
|
||||||
|
</ng-template>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { FilterService } from '@shared/services/filter.service';
|
|||||||
import { SearchService } from '@shared/services/search.service';
|
import { SearchService } from '@shared/services/search.service';
|
||||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||||
import { combineLatest, Observable, of } from 'rxjs';
|
import { combineLatest, Observable, of } from 'rxjs';
|
||||||
|
import { SearchPosition, searchPositions } from '@shared/components/page-header/models/search-positions.type';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-page-header',
|
selector: 'redaction-page-header',
|
||||||
@ -12,12 +13,15 @@ import { combineLatest, Observable, of } from 'rxjs';
|
|||||||
styleUrls: ['./page-header.component.scss']
|
styleUrls: ['./page-header.component.scss']
|
||||||
})
|
})
|
||||||
export class PageHeaderComponent {
|
export class PageHeaderComponent {
|
||||||
|
readonly searchPositions = searchPositions;
|
||||||
|
|
||||||
@Input() pageLabel: string;
|
@Input() pageLabel: string;
|
||||||
@Input() showCloseButton: boolean;
|
@Input() showCloseButton: boolean;
|
||||||
@Input() actionConfigs: ActionConfig[];
|
@Input() actionConfigs: ActionConfig[];
|
||||||
@Input() buttonConfigs: ButtonConfig[];
|
@Input() buttonConfigs: ButtonConfig[];
|
||||||
@Input() searchPlaceholder: string;
|
@Input() searchPlaceholder: string;
|
||||||
@Input() searchWidth: number | 'full';
|
@Input() searchWidth: number | 'full';
|
||||||
|
@Input() searchPosition: SearchPosition = this.searchPositions.afterFilters;
|
||||||
|
|
||||||
readonly filters$ = this.filterService?.filterGroups$.pipe(map(all => all.filter(f => f.icon)));
|
readonly filters$ = this.filterService?.filterGroups$.pipe(map(all => all.filter(f => f.icon)));
|
||||||
readonly showResetFilters$ = this._showResetFilters$;
|
readonly showResetFilters$ = this._showResetFilters$;
|
||||||
@ -37,10 +41,6 @@ export class PageHeaderComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get computedWidth() {
|
|
||||||
return this.searchWidth === 'full' ? '100%' : `${this.searchWidth}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetFilters(): void {
|
resetFilters(): void {
|
||||||
this.filterService.reset();
|
this.filterService.reset();
|
||||||
this.searchService.reset();
|
this.searchService.reset();
|
||||||
|
|||||||
@ -2,14 +2,17 @@ import { Injectable } from '@angular/core';
|
|||||||
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
|
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
|
||||||
import { processFilters } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
import { processFilters } from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||||
import { FilterGroup } from '@shared/components/filters/popup-filter/model/filter-wrapper.model';
|
import { FilterGroup } from '@shared/components/filters/popup-filter/model/filter-wrapper.model';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||||
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
|
import { distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FilterService {
|
export class FilterService {
|
||||||
private readonly _filterGroups$ = new BehaviorSubject<FilterGroup[]>([]);
|
private readonly _filterGroups$ = new BehaviorSubject<FilterGroup[]>([]);
|
||||||
private readonly _refresh$ = new BehaviorSubject(null);
|
private readonly _refresh$ = new Subject();
|
||||||
readonly filterGroups$ = this._refresh$.pipe(switchMap(() => this._filterGroups$.asObservable()));
|
readonly filterGroups$ = this._refresh$.pipe(
|
||||||
|
startWith(''),
|
||||||
|
switchMap(() => this._filterGroups$.asObservable())
|
||||||
|
);
|
||||||
readonly showResetFilters$ = this._showResetFilters$;
|
readonly showResetFilters$ = this._showResetFilters$;
|
||||||
|
|
||||||
get filterGroups(): FilterGroup[] {
|
get filterGroups(): FilterGroup[] {
|
||||||
@ -25,7 +28,7 @@ export class FilterService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
refresh(): void {
|
refresh(): void {
|
||||||
this._refresh$.next(null);
|
this._refresh$.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleFilter(slug: string, key: string) {
|
toggleFilter(slug: string, key: string) {
|
||||||
|
|||||||
@ -1205,6 +1205,9 @@
|
|||||||
"pages": "Pages",
|
"pages": "Pages",
|
||||||
"status": "Status"
|
"status": "Status"
|
||||||
},
|
},
|
||||||
|
"filters": {
|
||||||
|
"by-dossier": "Filter by Dossier"
|
||||||
|
},
|
||||||
"missing": "Missing",
|
"missing": "Missing",
|
||||||
"must-contain": "Must contain",
|
"must-contain": "Must contain",
|
||||||
"no-data": "Please enter a keyword in the search input to look for documents or document content.",
|
"no-data": "Please enter a keyword in the search input to look for documents or document content.",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user