mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
[ADF-3365] search filter fixes (#3594)
* preserve ordering of facet fields and queries * update tests * rework facet queries * rework facet management, update unit tests * remove unused interfaces * fix test * remove deprecated interfaces * expose selection for the chip list
This commit is contained in:
committed by
Eugenio Romano
parent
98243f0450
commit
c63184334f
@@ -1,14 +1,14 @@
|
||||
<mat-chip-list>
|
||||
<ng-container *ngIf="searchFilter && searchFilter.selectedFacetQueries">
|
||||
<ng-container *ngIf="searchFilter && searchFilter.selectedFacetQueries.length">
|
||||
<mat-chip
|
||||
*ngFor="let label of searchFilter.selectedFacetQueries"
|
||||
*ngFor="let query of searchFilter.selectedFacetQueries"
|
||||
[removable]="true"
|
||||
(remove)="searchFilter.unselectFacetQuery(label)">
|
||||
{{ label | translate }}
|
||||
(remove)="searchFilter.unselectFacetQuery(query)">
|
||||
{{ query.label | translate }}
|
||||
<mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="searchFilter && searchFilter.selectedBuckets">
|
||||
<ng-container *ngIf="searchFilter && searchFilter.selectedBuckets.length">
|
||||
<mat-chip
|
||||
*ngFor="let bucket of searchFilter.selectedBuckets"
|
||||
[removable]="true"
|
||||
|
@@ -15,23 +15,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ResponseFacetQuery } from '../../../facet-query.interface';
|
||||
import { FacetQuery } from '../../../facet-query.interface';
|
||||
import { SearchFilterList } from './search-filter-list.model';
|
||||
|
||||
export class ResponseFacetQueryList extends SearchFilterList<ResponseFacetQuery> {
|
||||
constructor(items: ResponseFacetQuery[] = [], pageSize: number = 5) {
|
||||
export class ResponseFacetQueryList extends SearchFilterList<FacetQuery> {
|
||||
constructor(items: FacetQuery[] = [], pageSize: number = 5) {
|
||||
super(
|
||||
items
|
||||
.filter(item => {
|
||||
return item.count > 0;
|
||||
})
|
||||
.map(item => {
|
||||
return <ResponseFacetQuery> { ...item };
|
||||
}),
|
||||
pageSize
|
||||
);
|
||||
|
||||
this.filter = (query: ResponseFacetQuery) => {
|
||||
this.filter = (query: FacetQuery) => {
|
||||
if (this.filterText && query.label) {
|
||||
const pattern = (this.filterText || '').toLowerCase();
|
||||
const label = query.label.toLowerCase();
|
||||
|
@@ -2,9 +2,7 @@
|
||||
|
||||
<mat-expansion-panel
|
||||
*ngFor="let category of queryBuilder.categories"
|
||||
[expanded]="category.expanded"
|
||||
(opened)="onCategoryExpanded(category)"
|
||||
(closed)="onCategoryCollapsed(category)">
|
||||
[(expanded)]="category.expanded">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
{{ category.name | translate }}
|
||||
@@ -17,115 +15,114 @@
|
||||
</adf-search-widget-container>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel *ngIf="isFacetQueriesDefined" [expanded]="facetQueriesExpanded">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>{{ facetQueriesLabel | translate }}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<div class="facet-result-filter">
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'SEARCH.FILTER.ACTIONS.FILTER-CATEGORY' | translate }}"
|
||||
[(ngModel)]="responseFacetQueries.filterText">
|
||||
<button *ngIf="responseFacetQueries.filterText"
|
||||
mat-button matSuffix mat-icon-button
|
||||
(click)="responseFacetQueries.filterText = ''">
|
||||
<mat-icon>close</mat-icon>
|
||||
<ng-container *ngIf="responseFacetQueries">
|
||||
<mat-expansion-panel [expanded]="facetQueriesExpanded">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>{{ facetQueriesLabel | translate }}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<div class="facet-result-filter">
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'SEARCH.FILTER.ACTIONS.FILTER-CATEGORY' | translate }}"
|
||||
[(ngModel)]="responseFacetQueries.filterText">
|
||||
<button *ngIf="responseFacetQueries.filterText"
|
||||
mat-button matSuffix mat-icon-button
|
||||
(click)="responseFacetQueries.filterText = ''">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="checklist">
|
||||
<ng-container *ngFor="let query of responseFacetQueries">
|
||||
<mat-checkbox
|
||||
[checked]="query.checked"
|
||||
(change)="onToggleFacetQuery($event, query)">
|
||||
{{ query.label }} ({{ query.count }})
|
||||
</mat-checkbox>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div class="facet-buttons">
|
||||
<button mat-icon-button
|
||||
*ngIf="canResetSelectedQueries"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.CLEAR-ALL' | translate }}"
|
||||
(click)="resetSelectedQueries()">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="checklist">
|
||||
<ng-container *ngFor="let query of responseFacetQueries">
|
||||
<button mat-icon-button
|
||||
*ngIf="responseFacetQueries.canShowLessItems"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-LESS' | translate }}"
|
||||
(click)="responseFacetQueries.showLessItems()">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
*ngIf="responseFacetQueries.canShowMoreItems"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}"
|
||||
(click)="responseFacetQueries.showMoreItems()">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="responseFacetFields">
|
||||
<mat-expansion-panel *ngFor="let field of responseFacetFields">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>{{ field.label }}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<div class="facet-result-filter">
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'SEARCH.FILTER.ACTIONS.FILTER-CATEGORY' | translate }}"
|
||||
[(ngModel)]="field.buckets.filterText">
|
||||
<button *ngIf="field.buckets.filterText"
|
||||
mat-button matSuffix mat-icon-button
|
||||
(click)="field.buckets.filterText = ''">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="checklist">
|
||||
<mat-checkbox
|
||||
[checked]="query.$checked"
|
||||
(change)="onFacetQueryToggle($event, query)">
|
||||
{{ query.label }} ({{ query.count }})
|
||||
*ngFor="let bucket of field.buckets"
|
||||
[checked]="bucket.checked"
|
||||
(change)="onToggleBucket($event, bucket)">
|
||||
{{ bucket.display || bucket.label }} ({{ bucket.count }})
|
||||
</mat-checkbox>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div class="facet-buttons">
|
||||
<button mat-icon-button
|
||||
*ngIf="canResetSelectedQueries()"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.CLEAR-ALL' | translate }}"
|
||||
(click)="resetSelectedQueries()">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
*ngIf="responseFacetQueries.canShowLessItems"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-LESS' | translate }}"
|
||||
(click)="responseFacetQueries.showLessItems()">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
*ngIf="responseFacetQueries.canShowMoreItems"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}"
|
||||
(click)="responseFacetQueries.showMoreItems()">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</div>
|
||||
|
||||
<mat-expansion-panel
|
||||
*ngFor="let field of responseFacetFields"
|
||||
[expanded]="field.expanded"
|
||||
(opened)="onFacetFieldExpanded(field)"
|
||||
(closed)="onFacetFieldCollapsed(field)">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>{{ field.label }}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<div class="facet-result-filter">
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'SEARCH.FILTER.ACTIONS.FILTER-CATEGORY' | translate }}"
|
||||
[(ngModel)]="field.buckets.filterText">
|
||||
<button *ngIf="field.buckets.filterText"
|
||||
mat-button matSuffix mat-icon-button
|
||||
(click)="field.buckets.filterText = ''">
|
||||
<mat-icon>close</mat-icon>
|
||||
<div class="facet-buttons" *ngIf="field.buckets.fitsPage">
|
||||
<button *ngIf="canResetSelectedBuckets(field)"
|
||||
mat-button
|
||||
color="primary"
|
||||
(click)="resetSelectedBuckets(field)">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.CLEAR-ALL' | translate }}
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="checklist">
|
||||
<mat-checkbox
|
||||
*ngFor="let bucket of field.buckets"
|
||||
[checked]="bucket.$checked"
|
||||
(change)="onFacetToggle($event, field, bucket)">
|
||||
{{ bucket.display || bucket.label }} ({{ bucket.count }})
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="facet-buttons" *ngIf="field.buckets.fitsPage">
|
||||
<button *ngIf="canResetSelectedBuckets(field)"
|
||||
mat-button
|
||||
color="primary"
|
||||
(click)="resetSelectedBuckets(field)">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.CLEAR-ALL' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="facet-buttons" *ngIf="!field.buckets.fitsPage">
|
||||
<button mat-icon-button
|
||||
*ngIf="canResetSelectedBuckets(field)"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.CLEAR-ALL' | translate }}"
|
||||
(click)="resetSelectedBuckets(field)">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
*ngIf="field.buckets.canShowLessItems"
|
||||
(click)="field.buckets.showLessItems()"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-LESS' | translate }}">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
*ngIf="field.buckets.canShowMoreItems"
|
||||
(click)="field.buckets.showMoreItems()"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</div>
|
||||
|
||||
<div class="facet-buttons" *ngIf="!field.buckets.fitsPage">
|
||||
<button mat-icon-button
|
||||
*ngIf="canResetSelectedBuckets(field)"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.CLEAR-ALL' | translate }}"
|
||||
(click)="resetSelectedBuckets(field)">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
*ngIf="field.buckets.canShowLessItems"
|
||||
(click)="field.buckets.showLessItems()"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-LESS' | translate }}">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
*ngIf="field.buckets.canShowMoreItems"
|
||||
(click)="field.buckets.showMoreItems()"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</ng-container>
|
||||
</mat-accordion>
|
||||
|
@@ -17,15 +17,15 @@
|
||||
|
||||
import { SearchFilterComponent } from './search-filter.component';
|
||||
import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
||||
import { SearchConfiguration } from '../../search-configuration.interface';
|
||||
import { AppConfigService, TranslationMock } from '@alfresco/adf-core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { ResponseFacetQueryList } from './models/response-facet-query-list.model';
|
||||
import { ResponseFacetField } from '../../response-facet-field.interface';
|
||||
import { SearchFilterList } from './models/search-filter-list.model';
|
||||
import { FacetFieldBucket } from '../../facet-field-bucket.interface';
|
||||
import { FacetQuery } from '../../facet-query.interface';
|
||||
import { FacetField } from '../../facet-field.interface';
|
||||
import { SearchFilterList } from './models/search-filter-list.model';
|
||||
import { ResponseFacetQueryList } from './models/response-facet-query-list.model';
|
||||
|
||||
describe('SearchSettingsComponent', () => {
|
||||
describe('SearchFilterComponent', () => {
|
||||
|
||||
let component: SearchFilterComponent;
|
||||
let queryBuilder: SearchQueryBuilderService;
|
||||
@@ -52,150 +52,60 @@ describe('SearchSettingsComponent', () => {
|
||||
expect(component.onDataLoaded).toHaveBeenCalledWith(data);
|
||||
});
|
||||
|
||||
it('should update category model on expand', () => {
|
||||
const category: any = { expanded: false };
|
||||
|
||||
component.onCategoryExpanded(category);
|
||||
|
||||
expect(category.expanded).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should update category model on collapse', () => {
|
||||
const category: any = { expanded: true };
|
||||
|
||||
component.onCategoryCollapsed(category);
|
||||
|
||||
expect(category.expanded).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should update facet field model on expand', () => {
|
||||
const field: any = { expanded: false };
|
||||
|
||||
component.onFacetFieldExpanded(field);
|
||||
|
||||
expect(field.expanded).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should update facet field model on collapse', () => {
|
||||
const field: any = { expanded: true };
|
||||
|
||||
component.onFacetFieldCollapsed(field);
|
||||
|
||||
expect(field.expanded).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should update bucket model and query builder on facet toggle', () => {
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
spyOn(queryBuilder, 'addUserFacetBucket').and.callThrough();
|
||||
|
||||
const event: any = { checked: true };
|
||||
const field: any = {};
|
||||
const bucket: any = { $checked: false, filterQuery: 'q1' };
|
||||
const bucket: FacetFieldBucket = { checked: false, filterQuery: 'q1', label: 'q1', count: 1 };
|
||||
|
||||
component.onFacetToggle(event, field, bucket);
|
||||
|
||||
expect(component.selectedBuckets.length).toBe(1);
|
||||
expect(component.selectedBuckets[0]).toEqual(bucket);
|
||||
|
||||
expect(queryBuilder.filterQueries.length).toBe(1);
|
||||
expect(queryBuilder.filterQueries[0].query).toBe('q1');
|
||||
component.onToggleBucket(event, bucket);
|
||||
|
||||
expect(bucket.checked).toBeTruthy();
|
||||
expect(queryBuilder.addUserFacetBucket).toHaveBeenCalledWith(bucket);
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should update bucket model and query builder on facet un-toggle', () => {
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
spyOn(queryBuilder, 'removeUserFacetBucket').and.callThrough();
|
||||
|
||||
const event: any = { checked: false };
|
||||
const field: any = { label: 'f1' };
|
||||
const bucket: any = { $checked: true, filterQuery: 'q1', $field: 'f1', label: 'b1' };
|
||||
const bucket: FacetFieldBucket = { checked: true, filterQuery: 'q1', label: 'q1', count: 1 };
|
||||
|
||||
component.selectedBuckets.push(bucket);
|
||||
queryBuilder.addFilterQuery(bucket.filterQuery);
|
||||
|
||||
component.onFacetToggle(event, field, bucket);
|
||||
|
||||
expect(bucket.$checked).toBeFalsy();
|
||||
expect(component.selectedBuckets.length).toBe(0);
|
||||
expect(queryBuilder.filterQueries.length).toBe(0);
|
||||
component.onToggleBucket(event, bucket);
|
||||
|
||||
expect(queryBuilder.removeUserFacetBucket).toHaveBeenCalledWith(bucket);
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should unselect facet query and update builder', () => {
|
||||
const translationMock = new TranslationMock();
|
||||
const config: SearchConfiguration = {
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: [
|
||||
{ label: 'q1', query: 'query1' }
|
||||
]
|
||||
}
|
||||
};
|
||||
appConfig.config.search = config;
|
||||
queryBuilder = new SearchQueryBuilderService(appConfig, null);
|
||||
component = new SearchFilterComponent(queryBuilder, null, translationMock);
|
||||
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
queryBuilder.filterQueries = [{ query: 'query1' }];
|
||||
component.selectedFacetQueries = ['q1'];
|
||||
spyOn(queryBuilder, 'removeUserFacetQuery').and.callThrough();
|
||||
|
||||
component.unselectFacetQuery('q1');
|
||||
const event: any = { checked: false };
|
||||
const query: FacetQuery = { checked: true, label: 'q1', query: 'query1' };
|
||||
|
||||
expect(component.selectedFacetQueries.length).toBe(0);
|
||||
expect(queryBuilder.filterQueries.length).toBe(0);
|
||||
component.onToggleFacetQuery(event, query);
|
||||
|
||||
expect(query.checked).toBeFalsy();
|
||||
expect(queryBuilder.removeUserFacetQuery).toHaveBeenCalledWith(query);
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should unselect facet bucket and update builder', () => {
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
|
||||
const bucket: any = { $checked: true, filterQuery: 'q1', $field: 'f1', label: 'b1' };
|
||||
component.selectedBuckets.push(bucket);
|
||||
queryBuilder.filterQueries.push({ query: 'q1' });
|
||||
|
||||
component.unselectFacetBucket(bucket);
|
||||
|
||||
expect(component.selectedBuckets.length).toBe(0);
|
||||
expect(queryBuilder.filterQueries.length).toBe(0);
|
||||
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow facetQueries when defined in configuration', () => {
|
||||
component.queryBuilder.config = {
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: [
|
||||
{ label: 'q1', query: 'query1' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
expect(component.isFacetQueriesDefined).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow facetQueries when not defined in configuration', () => {
|
||||
component.queryBuilder.config = {
|
||||
categories: []
|
||||
};
|
||||
|
||||
expect(component.isFacetQueriesDefined).toBe(false);
|
||||
});
|
||||
|
||||
it('should not allow facetQueries when queries are not defined in configuration', () => {
|
||||
component.queryBuilder.config = {
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: []
|
||||
}
|
||||
};
|
||||
|
||||
expect(component.isFacetQueriesDefined).toBe(false);
|
||||
});
|
||||
|
||||
it('should fetch facet queries from response payload', () => {
|
||||
component.responseFacetQueries = new ResponseFacetQueryList();
|
||||
component.responseFacetQueries = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: [
|
||||
{ label: 'q1', query: 'query1' },
|
||||
{ label: 'q2', query: 'query2' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const queries = [
|
||||
{ label: 'q1', query: 'query1', count: 1 },
|
||||
{ label: 'q2', query: 'query2', count: 1 }
|
||||
@@ -214,8 +124,51 @@ describe('SearchSettingsComponent', () => {
|
||||
expect(component.responseFacetQueries.items).toEqual(queries);
|
||||
});
|
||||
|
||||
it('should preserve order after response processing', () => {
|
||||
component.responseFacetQueries = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: [
|
||||
{ label: 'q1', query: 'query1' },
|
||||
{ label: 'q2', query: 'query2' },
|
||||
{ label: 'q3', query: 'query3' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const queries = [
|
||||
{ label: 'q2', query: 'query2', count: 1 },
|
||||
{ label: 'q1', query: 'query1', count: 1 },
|
||||
{ label: 'q3', query: 'query3', count: 1 }
|
||||
|
||||
];
|
||||
const data = {
|
||||
list: {
|
||||
context: {
|
||||
facetQueries: queries
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetQueries.length).toBe(3);
|
||||
expect(component.responseFacetQueries.items[0].label).toBe('q1');
|
||||
expect(component.responseFacetQueries.items[1].label).toBe('q2');
|
||||
expect(component.responseFacetQueries.items[2].label).toBe('q3');
|
||||
});
|
||||
|
||||
it('should not fetch facet queries from response payload', () => {
|
||||
component.responseFacetQueries = new ResponseFacetQueryList();
|
||||
component.responseFacetQueries = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
categories: [],
|
||||
facetQueries: {
|
||||
queries: []
|
||||
}
|
||||
};
|
||||
|
||||
const data = {
|
||||
list: {
|
||||
@@ -227,57 +180,22 @@ describe('SearchSettingsComponent', () => {
|
||||
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetQueries.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should restore checked state for new response facet queries', () => {
|
||||
component.selectedFacetQueries = ['q3'];
|
||||
component.responseFacetQueries = new ResponseFacetQueryList();
|
||||
|
||||
const queries = [
|
||||
{ label: 'q1', query: 'query1', count: 1 },
|
||||
{ label: 'q2', query: 'query2', count: 1 }
|
||||
];
|
||||
const data = {
|
||||
list: {
|
||||
context: {
|
||||
facetQueries: queries
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetQueries.length).toBe(2);
|
||||
expect((<any> component.responseFacetQueries.items[0]).$checked).toBeFalsy();
|
||||
expect((<any> component.responseFacetQueries.items[1]).$checked).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not restore checked state for new response facet queries', () => {
|
||||
component.selectedFacetQueries = ['q2'];
|
||||
component.responseFacetQueries = new ResponseFacetQueryList();
|
||||
|
||||
const queries = [
|
||||
{ label: 'q1', query: 'query1', count: 1 },
|
||||
{ label: 'q2', query: 'query2', count: 1 }
|
||||
];
|
||||
const data = {
|
||||
list: {
|
||||
context: {
|
||||
facetQueries: queries
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetQueries.length).toBe(2);
|
||||
expect((<any> component.responseFacetQueries.items[0]).$checked).toBeFalsy();
|
||||
expect((<any> component.responseFacetQueries.items[1]).$checked).toBeTruthy();
|
||||
expect(component.responseFacetQueries).toBeNull();
|
||||
});
|
||||
|
||||
it('should fetch facet fields from response payload', () => {
|
||||
component.responseFacetFields = [];
|
||||
component.responseFacetFields = null;
|
||||
|
||||
queryBuilder.config = {
|
||||
categories: [],
|
||||
facetFields: [
|
||||
{ label: 'f1', field: 'f1' },
|
||||
{ label: 'f2', field: 'f2' }
|
||||
],
|
||||
facetQueries: {
|
||||
queries: []
|
||||
}
|
||||
};
|
||||
|
||||
const fields: any = [
|
||||
{ label: 'f1', buckets: [] },
|
||||
@@ -293,95 +211,25 @@ describe('SearchSettingsComponent', () => {
|
||||
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetFields).toEqual(fields);
|
||||
});
|
||||
|
||||
it('should restore expanded state for new response facet fields', () => {
|
||||
component.responseFacetFields = <any> [
|
||||
{ label: 'f1', buckets: [] },
|
||||
{ label: 'f2', buckets: [], expanded: true }
|
||||
];
|
||||
|
||||
const fields = [
|
||||
{ label: 'f1', buckets: [] },
|
||||
{ label: 'f2', buckets: [] }
|
||||
];
|
||||
const data = {
|
||||
list: {
|
||||
context: {
|
||||
facetsFields: fields
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetFields.length).toBe(2);
|
||||
expect(component.responseFacetFields[0].expanded).toBeFalsy();
|
||||
expect(component.responseFacetFields[1].expanded).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should restore checked buckets for new response facet fields', () => {
|
||||
const bucket1 = { label: 'b1', $field: 'f1', count: 1, filterQuery: 'q1' };
|
||||
const bucket2 = { label: 'b2', $field: 'f2', count: 1, filterQuery: 'q2' };
|
||||
|
||||
component.selectedBuckets = [bucket2];
|
||||
component.responseFacetFields = <any> [
|
||||
{ label: 'f2', buckets: [] }
|
||||
];
|
||||
|
||||
const data = {
|
||||
list: {
|
||||
context: {
|
||||
facetsFields: [
|
||||
{ label: 'f1', buckets: [bucket1] },
|
||||
{ label: 'f2', buckets: [bucket2] }
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetFields.length).toBe(2);
|
||||
expect(component.responseFacetFields[0].buckets.items[0].$checked).toBeFalsy();
|
||||
expect(component.responseFacetFields[1].buckets.items[0].$checked).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should reset queries and fields on empty response payload', () => {
|
||||
component.responseFacetQueries = new ResponseFacetQueryList([<any> {}, <any> {}]);
|
||||
component.responseFacetFields = [<any> {}, <any> {}];
|
||||
|
||||
const data = {
|
||||
list: {
|
||||
context: {
|
||||
facetQueries: null,
|
||||
facetsFields: null
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetQueries.length).toBe(0);
|
||||
expect(component.responseFacetFields.length).toBe(0);
|
||||
expect(component.responseFacetFields.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should update query builder only when has bucket to unselect', () => {
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
|
||||
component.unselectFacetBucket(null);
|
||||
component.onToggleBucket(<any> { checked: true }, null);
|
||||
|
||||
expect(queryBuilder.update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow to to reset selected buckets', () => {
|
||||
const buckets: FacetFieldBucket[] = [
|
||||
{ label: 'bucket1', $checked: true, count: 1, filterQuery: 'q1' },
|
||||
{ label: 'bucket2', $checked: false, count: 1, filterQuery: 'q2' }
|
||||
{ label: 'bucket1', checked: true, count: 1, filterQuery: 'q1' },
|
||||
{ label: 'bucket2', checked: false, count: 1, filterQuery: 'q2' }
|
||||
];
|
||||
|
||||
const field: ResponseFacetField = {
|
||||
const field: FacetField = {
|
||||
field: 'f1',
|
||||
label: 'field1',
|
||||
buckets: new SearchFilterList<FacetFieldBucket>(buckets)
|
||||
};
|
||||
@@ -391,11 +239,12 @@ describe('SearchSettingsComponent', () => {
|
||||
|
||||
it('should not allow to reset selected buckets', () => {
|
||||
const buckets: FacetFieldBucket[] = [
|
||||
{ label: 'bucket1', $checked: false, count: 1, filterQuery: 'q1' },
|
||||
{ label: 'bucket2', $checked: false, count: 1, filterQuery: 'q2' }
|
||||
{ label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' },
|
||||
{ label: 'bucket2', checked: false, count: 1, filterQuery: 'q2' }
|
||||
];
|
||||
|
||||
const field: ResponseFacetField = {
|
||||
const field: FacetField = {
|
||||
field: 'f1',
|
||||
label: 'field1',
|
||||
buckets: new SearchFilterList<FacetFieldBucket>(buckets)
|
||||
};
|
||||
@@ -405,70 +254,57 @@ describe('SearchSettingsComponent', () => {
|
||||
|
||||
it('should reset selected buckets', () => {
|
||||
const buckets: FacetFieldBucket[] = [
|
||||
{ label: 'bucket1', $checked: false, count: 1, filterQuery: 'q1', $field: 'field1' },
|
||||
{ label: 'bucket2', $checked: true, count: 1, filterQuery: 'q2', $field: 'field1' }
|
||||
{ label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' },
|
||||
{ label: 'bucket2', checked: true, count: 1, filterQuery: 'q2' }
|
||||
];
|
||||
|
||||
const field: ResponseFacetField = {
|
||||
const field: FacetField = {
|
||||
field: 'f1',
|
||||
label: 'field1',
|
||||
buckets: new SearchFilterList<FacetFieldBucket>(buckets)
|
||||
};
|
||||
|
||||
component.selectedBuckets = [buckets[1]];
|
||||
component.resetSelectedBuckets(field);
|
||||
|
||||
expect(buckets[0].$checked).toBeFalsy();
|
||||
expect(buckets[1].$checked).toBeFalsy();
|
||||
expect(component.selectedBuckets.length).toBe(0);
|
||||
expect(buckets[0].checked).toBeFalsy();
|
||||
expect(buckets[1].checked).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should update query builder upon resetting buckets', () => {
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
|
||||
const buckets: FacetFieldBucket[] = [
|
||||
{ label: 'bucket1', $checked: false, count: 1, filterQuery: 'q1', $field: 'field1' },
|
||||
{ label: 'bucket2', $checked: true, count: 1, filterQuery: 'q2', $field: 'field1' }
|
||||
{ label: 'bucket1', checked: false, count: 1, filterQuery: 'q1' },
|
||||
{ label: 'bucket2', checked: true, count: 1, filterQuery: 'q2' }
|
||||
];
|
||||
|
||||
const field: ResponseFacetField = {
|
||||
const field: FacetField = {
|
||||
field: 'f1',
|
||||
label: 'field1',
|
||||
buckets: new SearchFilterList<FacetFieldBucket>(buckets)
|
||||
};
|
||||
|
||||
component.selectedBuckets = [buckets[1]];
|
||||
component.resetSelectedBuckets(field);
|
||||
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow to reset selected queries', () => {
|
||||
component.selectedFacetQueries = ['q1', 'q2'];
|
||||
expect(component.canResetSelectedQueries()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not allow to reset selected queries when nothing selected', () => {
|
||||
component.selectedFacetQueries = [];
|
||||
expect(component.canResetSelectedQueries()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should reset selected queries', () => {
|
||||
const methodSpy = spyOn(component, 'unselectFacetQuery').and.stub();
|
||||
|
||||
component.selectedFacetQueries = ['q1', 'q2'];
|
||||
component.resetSelectedQueries();
|
||||
|
||||
expect(methodSpy.calls.count()).toBe(2);
|
||||
expect(methodSpy.calls.argsFor(0)).toEqual(['q1', false]);
|
||||
expect(methodSpy.calls.argsFor(1)).toEqual(['q2', false]);
|
||||
});
|
||||
|
||||
it('should update query builder upon resetting selected queries', () => {
|
||||
spyOn(queryBuilder, 'update').and.stub();
|
||||
spyOn(queryBuilder, 'removeUserFacetQuery').and.callThrough();
|
||||
|
||||
component.selectedFacetQueries = ['q1', 'q2'];
|
||||
component.canResetSelectedQueries = true;
|
||||
component.responseFacetQueries = new ResponseFacetQueryList([
|
||||
{ label: 'q1', query: 'q1', checked: true, count: 1 },
|
||||
{ label: 'q2', query: 'q2', checked: false, count: 1 },
|
||||
{ label: 'q3', query: 'q3', checked: true, count: 1 }
|
||||
]);
|
||||
component.resetSelectedQueries();
|
||||
|
||||
expect(queryBuilder.removeUserFacetQuery).toHaveBeenCalledTimes(3);
|
||||
expect(queryBuilder.update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
for (let entry of component.responseFacetQueries.items) {
|
||||
expect(entry.checked).toBeFalsy();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -19,11 +19,10 @@ import { Component, ViewEncapsulation, OnInit, OnDestroy } from '@angular/core';
|
||||
import { MatCheckboxChange } from '@angular/material';
|
||||
import { SearchService, TranslationService } from '@alfresco/adf-core';
|
||||
import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
||||
import { ResponseFacetField } from '../../response-facet-field.interface';
|
||||
import { FacetFieldBucket } from '../../facet-field-bucket.interface';
|
||||
import { SearchCategory } from '../../search-category.interface';
|
||||
import { ResponseFacetQuery } from '../../response-facet-query.interface';
|
||||
import { ResponseFacetQueryList } from './models/response-facet-query-list.model';
|
||||
import { FacetQuery } from '../../facet-query.interface';
|
||||
import { FacetField } from '../../facet-field.interface';
|
||||
import { SearchFilterList } from './models/search-filter-list.model';
|
||||
|
||||
@Component({
|
||||
@@ -38,20 +37,20 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
|
||||
private DEFAULT_PAGE_SIZE = 5;
|
||||
|
||||
isAlive = true;
|
||||
selectedFacetQueries: string[] = [];
|
||||
selectedBuckets: FacetFieldBucket[] = [];
|
||||
responseFacetQueries: ResponseFacetQueryList;
|
||||
responseFacetFields: ResponseFacetField[] = [];
|
||||
responseFacetQueries: ResponseFacetQueryList = null;
|
||||
responseFacetFields: FacetField[] = null;
|
||||
|
||||
private facetQueriesPageSize = this.DEFAULT_PAGE_SIZE;
|
||||
facetQueriesLabel: string = 'Facet Queries';
|
||||
facetQueriesPageSize = this.DEFAULT_PAGE_SIZE;
|
||||
facetQueriesExpanded = false;
|
||||
canResetSelectedQueries = false;
|
||||
|
||||
selectedFacetQueries: Array<FacetQuery> = [];
|
||||
selectedBuckets: Array<FacetFieldBucket> = [];
|
||||
|
||||
constructor(public queryBuilder: SearchQueryBuilderService,
|
||||
private searchService: SearchService,
|
||||
private translationService: TranslationService) {
|
||||
this.responseFacetQueries = new ResponseFacetQueryList();
|
||||
|
||||
if (queryBuilder.config && queryBuilder.config.facetQueries) {
|
||||
this.facetQueriesLabel = queryBuilder.config.facetQueries.label || 'Facet Queries';
|
||||
this.facetQueriesPageSize = queryBuilder.config.facetQueries.pageSize || this.DEFAULT_PAGE_SIZE;
|
||||
@@ -60,9 +59,9 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.queryBuilder.updated
|
||||
.takeWhile(() => this.isAlive)
|
||||
.subscribe(query => {
|
||||
this.queryBuilder.execute();
|
||||
});
|
||||
.subscribe(() => {
|
||||
this.queryBuilder.execute();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -70,9 +69,9 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
|
||||
this.queryBuilder.executed
|
||||
.takeWhile(() => this.isAlive)
|
||||
.subscribe(data => {
|
||||
this.onDataLoaded(data);
|
||||
this.searchService.dataLoaded.next(data);
|
||||
});
|
||||
this.onDataLoaded(data);
|
||||
this.searchService.dataLoaded.next(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,125 +79,111 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
|
||||
this.isAlive = false;
|
||||
}
|
||||
|
||||
get isFacetQueriesDefined() {
|
||||
return this.queryBuilder.hasFacetQueries;
|
||||
}
|
||||
|
||||
onCategoryExpanded(category: SearchCategory) {
|
||||
category.expanded = true;
|
||||
}
|
||||
|
||||
onCategoryCollapsed(category: SearchCategory) {
|
||||
category.expanded = false;
|
||||
}
|
||||
|
||||
onFacetFieldExpanded(field: ResponseFacetField) {
|
||||
field.expanded = true;
|
||||
}
|
||||
|
||||
onFacetFieldCollapsed(field: ResponseFacetField) {
|
||||
field.expanded = false;
|
||||
}
|
||||
|
||||
onFacetQueryToggle(event: MatCheckboxChange, query: ResponseFacetQuery) {
|
||||
const facetQuery = this.queryBuilder.getFacetQuery(query.label);
|
||||
|
||||
if (event.checked) {
|
||||
query.$checked = true;
|
||||
this.selectedFacetQueries.push(facetQuery.label);
|
||||
|
||||
if (facetQuery) {
|
||||
this.queryBuilder.addFilterQuery(facetQuery.query);
|
||||
}
|
||||
} else {
|
||||
query.$checked = false;
|
||||
this.selectedFacetQueries = this.selectedFacetQueries.filter(selectedQuery => selectedQuery !== query.label);
|
||||
|
||||
if (facetQuery) {
|
||||
this.queryBuilder.removeFilterQuery(facetQuery.query);
|
||||
onToggleFacetQuery(event: MatCheckboxChange, facetQuery: FacetQuery) {
|
||||
if (event && facetQuery) {
|
||||
if (event.checked) {
|
||||
this.selectFacetQuery(facetQuery);
|
||||
} else {
|
||||
this.unselectFacetQuery(facetQuery);
|
||||
}
|
||||
}
|
||||
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
|
||||
onFacetToggle(event: MatCheckboxChange, field: ResponseFacetField, bucket: FacetFieldBucket) {
|
||||
if (event.checked) {
|
||||
bucket.$checked = true;
|
||||
this.selectedBuckets.push({ ...bucket });
|
||||
this.queryBuilder.addFilterQuery(bucket.filterQuery);
|
||||
} else {
|
||||
bucket.$checked = false;
|
||||
const idx = this.selectedBuckets.findIndex(
|
||||
b => b.$field === bucket.$field && b.label === bucket.label
|
||||
);
|
||||
|
||||
if (idx >= 0) {
|
||||
this.selectedBuckets.splice(idx, 1);
|
||||
}
|
||||
this.queryBuilder.removeFilterQuery(bucket.filterQuery);
|
||||
}
|
||||
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
|
||||
unselectFacetQuery(label: string, reloadQuery: boolean = true) {
|
||||
const facetQuery = this.queryBuilder.getFacetQuery(label);
|
||||
if (facetQuery) {
|
||||
this.queryBuilder.removeFilterQuery(facetQuery.query);
|
||||
}
|
||||
|
||||
this.selectedFacetQueries = this.selectedFacetQueries.filter(selectedQuery => selectedQuery !== label);
|
||||
|
||||
if (reloadQuery) {
|
||||
selectFacetQuery(query: FacetQuery) {
|
||||
if (query) {
|
||||
query.checked = true;
|
||||
this.queryBuilder.addUserFacetQuery(query);
|
||||
this.updateSelectedFields();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
}
|
||||
|
||||
unselectFacetBucket(bucket: FacetFieldBucket, reloadQuery: boolean = true) {
|
||||
if (bucket) {
|
||||
const idx = this.selectedBuckets.findIndex(
|
||||
selectedBucket => selectedBucket.$field === bucket.$field && selectedBucket.label === bucket.label
|
||||
);
|
||||
unselectFacetQuery(query: FacetQuery) {
|
||||
if (query) {
|
||||
query.checked = false;
|
||||
this.queryBuilder.removeUserFacetQuery(query);
|
||||
this.updateSelectedFields();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
}
|
||||
|
||||
if (idx >= 0) {
|
||||
this.selectedBuckets.splice(idx, 1);
|
||||
private updateSelectedBuckets() {
|
||||
if (this.responseFacetFields) {
|
||||
this.selectedBuckets = [];
|
||||
for (let field of this.responseFacetFields) {
|
||||
if (field.buckets) {
|
||||
this.selectedBuckets.push(...field.buckets.items.filter(bucket => bucket.checked));
|
||||
}
|
||||
}
|
||||
this.queryBuilder.removeFilterQuery(bucket.filterQuery);
|
||||
} else {
|
||||
this.selectedBuckets = [];
|
||||
}
|
||||
}
|
||||
|
||||
bucket.$checked = false;
|
||||
private updateSelectedFields() {
|
||||
if (this.responseFacetQueries) {
|
||||
this.selectedFacetQueries = this.responseFacetQueries.items.filter(item => item.checked);
|
||||
this.canResetSelectedQueries = this.selectedFacetQueries.length > 0;
|
||||
} else {
|
||||
this.selectedFacetQueries = [];
|
||||
this.canResetSelectedQueries = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (reloadQuery) {
|
||||
this.queryBuilder.update();
|
||||
onToggleBucket(event: MatCheckboxChange, bucket: FacetFieldBucket) {
|
||||
if (event && bucket) {
|
||||
if (event.checked) {
|
||||
this.selectFacetBucket(bucket);
|
||||
} else {
|
||||
this.unselectFacetBucket(bucket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
canResetSelectedQueries(): boolean {
|
||||
return this.selectedFacetQueries && this.selectedFacetQueries.length > 0;
|
||||
selectFacetBucket(bucket: FacetFieldBucket) {
|
||||
if (bucket) {
|
||||
bucket.checked = true;
|
||||
this.queryBuilder.addUserFacetBucket(bucket);
|
||||
this.updateSelectedBuckets();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
}
|
||||
|
||||
unselectFacetBucket(bucket: FacetFieldBucket) {
|
||||
if (bucket) {
|
||||
bucket.checked = false;
|
||||
this.queryBuilder.removeUserFacetBucket(bucket);
|
||||
this.updateSelectedBuckets();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
}
|
||||
|
||||
resetSelectedQueries() {
|
||||
if (this.canResetSelectedQueries()) {
|
||||
this.selectedFacetQueries.forEach(query => {
|
||||
this.unselectFacetQuery(query, false);
|
||||
});
|
||||
if (this.canResetSelectedQueries) {
|
||||
for (let query of this.responseFacetQueries.items) {
|
||||
query.checked = false;
|
||||
this.queryBuilder.removeUserFacetQuery(query);
|
||||
}
|
||||
this.selectedFacetQueries = [];
|
||||
this.canResetSelectedQueries = false;
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
}
|
||||
|
||||
canResetSelectedBuckets(field: ResponseFacetField): boolean {
|
||||
canResetSelectedBuckets(field: FacetField): boolean {
|
||||
if (field && field.buckets) {
|
||||
return field.buckets.items.some(bucket => bucket.$checked);
|
||||
return field.buckets.items.some(bucket => bucket.checked);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
resetSelectedBuckets(field: ResponseFacetField) {
|
||||
resetSelectedBuckets(field: FacetField) {
|
||||
if (field && field.buckets) {
|
||||
field.buckets.items.forEach(bucket => {
|
||||
this.unselectFacetBucket(bucket, false);
|
||||
});
|
||||
for (let bucket of field.buckets.items) {
|
||||
bucket.checked = false;
|
||||
this.queryBuilder.removeUserFacetBucket(bucket);
|
||||
}
|
||||
this.updateSelectedBuckets();
|
||||
this.queryBuilder.update();
|
||||
}
|
||||
}
|
||||
@@ -207,64 +192,75 @@ export class SearchFilterComponent implements OnInit, OnDestroy {
|
||||
const context = data.list.context;
|
||||
|
||||
if (context) {
|
||||
const facetQueries = (context.facetQueries || []).map(query => {
|
||||
query.label = this.translationService.instant(query.label);
|
||||
query.$checked = this.selectedFacetQueries.includes(query.label);
|
||||
return query;
|
||||
});
|
||||
|
||||
this.responseFacetQueries = new ResponseFacetQueryList(facetQueries, this.facetQueriesPageSize);
|
||||
|
||||
const expandedFields = this.responseFacetFields
|
||||
.filter(field => field.expanded)
|
||||
.map(field => field.label);
|
||||
|
||||
this.responseFacetFields = (context.facetsFields || []).map(
|
||||
field => {
|
||||
const settings = this.queryBuilder.getFacetField(field.label);
|
||||
|
||||
let fallbackPageSize = this.DEFAULT_PAGE_SIZE;
|
||||
if (settings && settings.pageSize) {
|
||||
fallbackPageSize = settings.pageSize;
|
||||
}
|
||||
|
||||
field.label = this.translationService.instant(field.label);
|
||||
field.pageSize = field.pageSize || fallbackPageSize;
|
||||
field.currentPageSize = field.pageSize;
|
||||
field.expanded = expandedFields.includes(field.label);
|
||||
|
||||
const buckets = (field.buckets || []).map(bucket => {
|
||||
bucket.$field = field.label;
|
||||
bucket.$checked = false;
|
||||
bucket.display = this.translationService.instant(bucket.display);
|
||||
bucket.label = this.translationService.instant(bucket.label);
|
||||
|
||||
const previousBucket = this.selectedBuckets.find(
|
||||
selectedBucket => selectedBucket.$field === bucket.$field && selectedBucket.label === bucket.label
|
||||
);
|
||||
if (previousBucket) {
|
||||
bucket.$checked = true;
|
||||
}
|
||||
return bucket;
|
||||
});
|
||||
|
||||
const bucketList = new SearchFilterList<FacetFieldBucket>(buckets, field.pageSize);
|
||||
bucketList.filter = (bucket: FacetFieldBucket): boolean => {
|
||||
if (bucket && bucketList.filterText) {
|
||||
const pattern = (bucketList.filterText || '').toLowerCase();
|
||||
const label = (bucket.display || bucket.label || '').toLowerCase();
|
||||
return label.startsWith(pattern);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
field.buckets = bucketList;
|
||||
return field;
|
||||
}
|
||||
);
|
||||
this.parseFacetFields(context);
|
||||
this.parseFacetQueries(context);
|
||||
} else {
|
||||
this.responseFacetQueries = new ResponseFacetQueryList([], this.facetQueriesPageSize);
|
||||
this.responseFacetFields = [];
|
||||
this.responseFacetQueries = null;
|
||||
this.responseFacetFields = null;
|
||||
}
|
||||
}
|
||||
|
||||
private parseFacetFields(context: any) {
|
||||
if (!this.responseFacetFields) {
|
||||
const configFacetFields = this.queryBuilder.config.facetFields || [];
|
||||
this.responseFacetFields = configFacetFields.map(field => {
|
||||
const responseField = (context.facetsFields || []).find(response => response.label === field.label);
|
||||
const buckets: FacetFieldBucket[] = (responseField.buckets || []).map(bucket => {
|
||||
return <FacetFieldBucket> {
|
||||
...bucket,
|
||||
checked: false,
|
||||
display: this.translationService.instant(bucket.display),
|
||||
label: this.translationService.instant(bucket.label)
|
||||
};
|
||||
});
|
||||
const bucketList = new SearchFilterList<FacetFieldBucket>(buckets, field.pageSize);
|
||||
bucketList.filter = (bucket: FacetFieldBucket): boolean => {
|
||||
if (bucket && bucketList.filterText) {
|
||||
const pattern = (bucketList.filterText || '').toLowerCase();
|
||||
const label = (bucket.display || bucket.label || '').toLowerCase();
|
||||
return label.startsWith(pattern);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return {
|
||||
...field,
|
||||
label: this.translationService.instant(field.label),
|
||||
pageSize: field.pageSize | this.DEFAULT_PAGE_SIZE,
|
||||
currentPageSize: field.pageSize | this.DEFAULT_PAGE_SIZE,
|
||||
buckets: bucketList
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private parseFacetQueries(context: any) {
|
||||
const responseQueries = this.getFacetQueryMap(context);
|
||||
if (!this.responseFacetQueries) {
|
||||
const facetQueries = (this.queryBuilder.config.facetQueries.queries || [])
|
||||
.map(query => {
|
||||
const queryResult = responseQueries[query.label];
|
||||
return <FacetQuery> {
|
||||
...query,
|
||||
label: this.translationService.instant(query.label),
|
||||
count: queryResult.count
|
||||
};
|
||||
});
|
||||
|
||||
if (facetQueries.length > 0) {
|
||||
this.responseFacetQueries = new ResponseFacetQueryList(facetQueries, this.facetQueriesPageSize);
|
||||
} else {
|
||||
this.responseFacetQueries = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getFacetQueryMap(context: any): { [key: string]: any } {
|
||||
const result = {};
|
||||
|
||||
(context.facetQueries || []).forEach(query => {
|
||||
result[query.label] = query;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user