mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
search fixes (#3272)
* "show less" button for search filter container * consistent button styles across widgets * i18n support for facets * page sizes for check list * display page buttons only when needed * page sizes for all facet fields * test fixes * update lib versions * fix angular configuration
This commit is contained in:
committed by
Eugenio Romano
parent
87a464907c
commit
ba35eda2f9
@@ -175,7 +175,8 @@
|
||||
"CLEAR": "Clear",
|
||||
"APPLY": "Apply",
|
||||
"CLEAR-ALL": "Clear all",
|
||||
"SHOW-MORE": "Show more"
|
||||
"SHOW-MORE": "Show more",
|
||||
"SHOW-LESS": "Show less"
|
||||
},
|
||||
"RANGE": {
|
||||
"FROM": "From",
|
||||
|
@@ -5,8 +5,28 @@
|
||||
{{ option.name | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<div>
|
||||
<div class="facet-buttons" *ngIf="options.fitsPage">
|
||||
<button mat-button color="primary" (click)="reset()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.CLEAR-ALL' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="facet-buttons" *ngIf="!options.fitsPage">
|
||||
<button mat-icon-button
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.CLEAR-ALL' | translate }}"
|
||||
(click)="reset()">
|
||||
<mat-icon>clear</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
[disabled]="!options.canShowLessItems"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-LESS' | translate }}"
|
||||
(click)="options.showLessItems()">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
[disabled]="!options.canShowMoreItems"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}"
|
||||
(click)="options.showMoreItems()">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
@@ -15,7 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SearchCheckListComponent } from './search-check-list.component';
|
||||
import { SearchCheckListComponent, SearchListOption } from './search-check-list.component';
|
||||
import { SearchFilterList } from '../search-filter/models/search-filter-list.model';
|
||||
|
||||
describe('SearchCheckListComponent', () => {
|
||||
|
||||
@@ -33,7 +34,7 @@ describe('SearchCheckListComponent', () => {
|
||||
component.settings = <any> { options: options };
|
||||
component.ngOnInit();
|
||||
|
||||
expect(component.options).toEqual(options);
|
||||
expect(component.options.items).toEqual(options);
|
||||
});
|
||||
|
||||
it('should setup operator from the settings', () => {
|
||||
@@ -49,10 +50,10 @@ describe('SearchCheckListComponent', () => {
|
||||
});
|
||||
|
||||
it('should update query builder on checkbox change', () => {
|
||||
component.options = [
|
||||
component.options = new SearchFilterList<SearchListOption>([
|
||||
{ name: 'Folder', value: "TYPE:'cm:folder'", checked: false },
|
||||
{ name: 'Document', value: "TYPE:'cm:content'", checked: false }
|
||||
];
|
||||
]);
|
||||
|
||||
component.id = 'checklist';
|
||||
component.context = <any> {
|
||||
@@ -66,14 +67,14 @@ describe('SearchCheckListComponent', () => {
|
||||
|
||||
component.changeHandler(
|
||||
<any> { checked: true },
|
||||
component.options[0]
|
||||
component.options.items[0]
|
||||
);
|
||||
|
||||
expect(component.context.queryFragments[component.id]).toEqual(`TYPE:'cm:folder'`);
|
||||
|
||||
component.changeHandler(
|
||||
<any> { checked: true },
|
||||
component.options[1]
|
||||
component.options.items[1]
|
||||
);
|
||||
|
||||
expect(component.context.queryFragments[component.id]).toEqual(
|
||||
@@ -82,15 +83,15 @@ describe('SearchCheckListComponent', () => {
|
||||
});
|
||||
|
||||
it('should reset selected boxes', () => {
|
||||
component.options = [
|
||||
component.options = new SearchFilterList<SearchListOption>([
|
||||
{ name: 'Folder', value: "TYPE:'cm:folder'", checked: true },
|
||||
{ name: 'Document', value: "TYPE:'cm:content'", checked: true }
|
||||
];
|
||||
]);
|
||||
|
||||
component.reset();
|
||||
|
||||
expect(component.options[0].checked).toBeFalsy();
|
||||
expect(component.options[1].checked).toBeFalsy();
|
||||
expect(component.options.items[0].checked).toBeFalsy();
|
||||
expect(component.options.items[1].checked).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should update query builder on reset', () => {
|
||||
@@ -104,10 +105,10 @@ describe('SearchCheckListComponent', () => {
|
||||
spyOn(component.context, 'update').and.stub();
|
||||
|
||||
component.ngOnInit();
|
||||
component.options = [
|
||||
component.options = new SearchFilterList<SearchListOption>([
|
||||
{ name: 'Folder', value: "TYPE:'cm:folder'", checked: true },
|
||||
{ name: 'Document', value: "TYPE:'cm:content'", checked: true }
|
||||
];
|
||||
]);
|
||||
|
||||
component.reset();
|
||||
|
||||
|
@@ -20,6 +20,13 @@ import { MatCheckboxChange } from '@angular/material';
|
||||
import { SearchWidget } from '../../search-widget.interface';
|
||||
import { SearchWidgetSettings } from '../../search-widget-settings.interface';
|
||||
import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
||||
import { SearchFilterList } from '../search-filter/models/search-filter-list.model';
|
||||
|
||||
export interface SearchListOption {
|
||||
name: string;
|
||||
value: string;
|
||||
checked: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-check-list',
|
||||
@@ -33,21 +40,27 @@ export class SearchCheckListComponent implements SearchWidget, OnInit {
|
||||
id: string;
|
||||
settings?: SearchWidgetSettings;
|
||||
context?: SearchQueryBuilderService;
|
||||
options: { name: string, value: string, checked: boolean }[] = [];
|
||||
options: SearchFilterList<SearchListOption>;
|
||||
operator: string = 'OR';
|
||||
pageSize = 5;
|
||||
|
||||
constructor() {
|
||||
this.options = new SearchFilterList<SearchListOption>();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.settings) {
|
||||
this.operator = this.settings.operator || 'OR';
|
||||
this.pageSize = this.settings.pageSize || 5;
|
||||
|
||||
if (this.settings.options && this.settings.options.length > 0) {
|
||||
this.options = [...this.settings.options];
|
||||
this.options = new SearchFilterList(this.settings.options, this.pageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.options.forEach(opt => {
|
||||
this.options.items.forEach(opt => {
|
||||
opt.checked = false;
|
||||
});
|
||||
|
||||
@@ -63,7 +76,7 @@ export class SearchCheckListComponent implements SearchWidget, OnInit {
|
||||
}
|
||||
|
||||
flush() {
|
||||
const checkedValues = this.options
|
||||
const checkedValues = this.options.items
|
||||
.filter(option => option.checked)
|
||||
.map(option => option.value);
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
*ngFor="let label of searchFilter.selectedFacetQueries"
|
||||
[removable]="true"
|
||||
(remove)="searchFilter.unselectFacetQuery(label)">
|
||||
{{ label }}
|
||||
{{ label | translate }}
|
||||
<mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
</ng-container>
|
||||
@@ -13,7 +13,7 @@
|
||||
*ngFor="let bucket of searchFilter.selectedBuckets"
|
||||
[removable]="true"
|
||||
(remove)="searchFilter.unselectFacetBucket(bucket)">
|
||||
{{ bucket.display || bucket.label }}
|
||||
{{ (bucket.display || bucket.label) | translate }}
|
||||
<mat-icon matChipRemove>cancel</mat-icon>
|
||||
</mat-chip>
|
||||
</ng-container>
|
||||
|
@@ -1,36 +1,34 @@
|
||||
<form [formGroup]="form" novalidate (ngSubmit)="apply(form.value, form.valid)">
|
||||
<mat-form-field>
|
||||
<input matInput [formControl]="from" [errorStateMatcher]="matcher"
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.FROM-DATE' | translate }}"
|
||||
[matDatepicker]="fromDatepicker"
|
||||
[max]="maxFrom">
|
||||
<mat-datepicker-toggle matSuffix [for]="fromDatepicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #fromDatepicker></mat-datepicker>
|
||||
<mat-error *ngIf="from.hasError('required')">
|
||||
{{ 'SEARCH.FILTER.VALIDATION.REQUIRED-VALUE' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<input matInput [formControl]="from" [errorStateMatcher]="matcher"
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.FROM-DATE' | translate }}"
|
||||
[matDatepicker]="fromDatepicker"
|
||||
[max]="maxFrom">
|
||||
<mat-datepicker-toggle matSuffix [for]="fromDatepicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #fromDatepicker></mat-datepicker>
|
||||
<mat-error *ngIf="from.hasError('required')">
|
||||
{{ 'SEARCH.FILTER.VALIDATION.REQUIRED-VALUE' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<input matInput [formControl]="to" [errorStateMatcher]="matcher"
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.TO-DATE' | translate }}"
|
||||
[matDatepicker]="toDatepicker"
|
||||
[min]="from.value">
|
||||
<mat-datepicker-toggle matSuffix [for]="toDatepicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #toDatepicker></mat-datepicker>
|
||||
<mat-error *ngIf="!hasSelectedDays(from.value, to.value)">
|
||||
{{ 'SEARCH.FILTER.VALIDATION.NO-DAYS' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<div>
|
||||
<button mat-button color="primary" type="button" (click)="reset()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.CLEAR' | translate }}
|
||||
</button>
|
||||
<button mat-button color="primary" type="submit" [disabled]="!form.valid">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.APPLY' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<mat-form-field>
|
||||
<input matInput [formControl]="to" [errorStateMatcher]="matcher"
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.TO-DATE' | translate }}"
|
||||
[matDatepicker]="toDatepicker"
|
||||
[min]="from.value">
|
||||
<mat-datepicker-toggle matSuffix [for]="toDatepicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #toDatepicker></mat-datepicker>
|
||||
<mat-error *ngIf="!hasSelectedDays(from.value, to.value)">
|
||||
{{ 'SEARCH.FILTER.VALIDATION.NO-DAYS' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="facet-buttons">
|
||||
<button mat-button color="primary" type="button" (click)="reset()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.CLEAR' | translate }}
|
||||
</button>
|
||||
<button mat-button color="primary" type="submit" [disabled]="!form.valid">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.APPLY' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -1,8 +1,5 @@
|
||||
.adf-search-date-range > form {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
|
||||
.mat-button {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
width: 100%;
|
||||
}
|
||||
|
@@ -16,43 +16,20 @@
|
||||
*/
|
||||
|
||||
import { ResponseFacetQuery } from '../../../facet-query.interface';
|
||||
import { SearchFilterList } from './search-filter-list.model';
|
||||
|
||||
export class ResponseFacetQueryList {
|
||||
|
||||
items: ResponseFacetQuery[] = [];
|
||||
pageSize: number = 5;
|
||||
currentPageSize: number = 5;
|
||||
|
||||
get visibleItems(): ResponseFacetQuery[] {
|
||||
return this.items.slice(0, this.currentPageSize);
|
||||
}
|
||||
|
||||
get length(): number {
|
||||
return this.items.length;
|
||||
}
|
||||
export class ResponseFacetQueryList extends SearchFilterList<ResponseFacetQuery> {
|
||||
|
||||
constructor(items: ResponseFacetQuery[] = [], pageSize: number = 5) {
|
||||
this.items = items
|
||||
const filtered = items
|
||||
.filter(item => {
|
||||
return item.count > 0;
|
||||
})
|
||||
.map(item => {
|
||||
return <ResponseFacetQuery> { ...item };
|
||||
});
|
||||
this.pageSize = pageSize;
|
||||
this.currentPageSize = pageSize;
|
||||
|
||||
super(filtered, pageSize);
|
||||
}
|
||||
|
||||
hasMoreItems(): boolean {
|
||||
return this.items.length > this.currentPageSize;
|
||||
}
|
||||
|
||||
showMoreItems() {
|
||||
this.currentPageSize += this.pageSize;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.currentPageSize = this.pageSize;
|
||||
this.items = [];
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,86 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export class SearchFilterList<T> implements Iterable<T> {
|
||||
items: T[] = [];
|
||||
pageSize: number = 5;
|
||||
currentPageSize: number = 5;
|
||||
|
||||
get visibleItems(): T[] {
|
||||
return this.items.slice(0, this.currentPageSize);
|
||||
}
|
||||
|
||||
get length(): number {
|
||||
return this.items.length;
|
||||
}
|
||||
|
||||
get canShowMoreItems(): boolean {
|
||||
return this.items.length > this.currentPageSize;
|
||||
}
|
||||
|
||||
get canShowLessItems(): boolean {
|
||||
return this.currentPageSize > this.pageSize;
|
||||
}
|
||||
|
||||
get fitsPage(): boolean {
|
||||
return this.pageSize > this.items.length;
|
||||
}
|
||||
|
||||
constructor(items: T[] = [], pageSize: number = 5) {
|
||||
this.items = items;
|
||||
this.pageSize = pageSize;
|
||||
this.currentPageSize = pageSize;
|
||||
}
|
||||
|
||||
showMoreItems() {
|
||||
if (this.canShowMoreItems) {
|
||||
this.currentPageSize += this.pageSize;
|
||||
}
|
||||
}
|
||||
|
||||
showLessItems() {
|
||||
if (this.canShowLessItems) {
|
||||
this.currentPageSize -= this.pageSize;
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.currentPageSize = this.pageSize;
|
||||
this.items = [];
|
||||
}
|
||||
|
||||
[Symbol.iterator](): Iterator<T> {
|
||||
let pointer = 0;
|
||||
let items = this.visibleItems;
|
||||
|
||||
return {
|
||||
next(): IteratorResult<T> {
|
||||
if (pointer < items.length) {
|
||||
return {
|
||||
done: false,
|
||||
value: items[pointer++]
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
done: true,
|
||||
value: null
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@@ -22,20 +22,28 @@
|
||||
<mat-panel-title>{{ facetQueriesLabel | translate }}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<div class="checklist">
|
||||
<ng-container *ngFor="let query of responseFacetQueries.visibleItems">
|
||||
<ng-container *ngFor="let query of responseFacetQueries">
|
||||
<mat-checkbox
|
||||
[checked]="query.$checked"
|
||||
(change)="onFacetQueryToggle($event, query)">
|
||||
{{ query.label }} ({{ query.count }})
|
||||
{{ query.label | translate }} ({{ query.count }})
|
||||
</mat-checkbox>
|
||||
</ng-container>
|
||||
</div>
|
||||
<button mat-button
|
||||
*ngIf="responseFacetQueries.hasMoreItems()"
|
||||
(click)="responseFacetQueries.showMoreItems()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
<div class="facet-buttons">
|
||||
<button mat-button
|
||||
*ngIf="responseFacetQueries.canShowLessItems"
|
||||
(click)="responseFacetQueries.showLessItems()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.SHOW-LESS' | translate }}
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-button
|
||||
*ngIf="responseFacetQueries.canShowMoreItems"
|
||||
(click)="responseFacetQueries.showMoreItems()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<mat-expansion-panel
|
||||
@@ -44,23 +52,31 @@
|
||||
(opened)="onFacetFieldExpanded(field)"
|
||||
(closed)="onFacetFieldCollapsed(field)">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>{{ field.label }}</mat-panel-title>
|
||||
<mat-panel-title>{{ field.label | translate }}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<div class="checklist">
|
||||
<mat-checkbox
|
||||
*ngFor="let bucket of field.getVisibleBuckets()"
|
||||
*ngFor="let bucket of field.buckets"
|
||||
[checked]="bucket.$checked"
|
||||
(change)="onFacetToggle($event, field, bucket)">
|
||||
{{ bucket.display || bucket.label }} ({{ bucket.count }})
|
||||
{{ (bucket.display || bucket.label) | translate }} ({{ bucket.count }})
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<button mat-button
|
||||
*ngIf="field.hasMoreItems()"
|
||||
(click)="field.showMoreItems()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
<div class="facet-buttons" *ngIf="!field.buckets.fitsPage">
|
||||
<button mat-button
|
||||
*ngIf="field.buckets.canShowLessItems"
|
||||
(click)="field.buckets.showLessItems()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.SHOW-LESS' | translate }}
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-button
|
||||
*ngIf="field.buckets.canShowMoreItems"
|
||||
(click)="field.buckets.showMoreItems()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
|
||||
</mat-accordion>
|
||||
|
@@ -6,3 +6,11 @@
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.facet-buttons {
|
||||
text-align: right;
|
||||
|
||||
.mat-button {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
@@ -307,8 +307,8 @@ describe('SearchSettingsComponent', () => {
|
||||
component.onDataLoaded(data);
|
||||
|
||||
expect(component.responseFacetFields.length).toBe(2);
|
||||
expect(component.responseFacetFields[0].buckets[0].$checked).toBeFalsy();
|
||||
expect(component.responseFacetFields[1].buckets[0].$checked).toBeTruthy();
|
||||
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', () => {
|
||||
|
@@ -24,6 +24,7 @@ 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 { SearchFilterList } from './models/search-filter-list.model';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-filter',
|
||||
@@ -44,6 +45,8 @@ export class SearchFilterComponent implements OnInit {
|
||||
facetQueriesExpanded = false;
|
||||
|
||||
constructor(public queryBuilder: SearchQueryBuilderService, private search: SearchService) {
|
||||
this.responseFacetQueries = new ResponseFacetQueryList();
|
||||
|
||||
if (queryBuilder.config && queryBuilder.config.facetQueries) {
|
||||
this.facetQueriesLabel = queryBuilder.config.facetQueries.label || 'Facet Queries';
|
||||
this.facetQueriesPageSize = queryBuilder.config.facetQueries.pageSize || 5;
|
||||
@@ -158,12 +161,12 @@ export class SearchFilterComponent implements OnInit {
|
||||
const expandedFields = this.responseFacetFields.filter(f => f.expanded).map(f => f.label);
|
||||
|
||||
this.responseFacetFields = (context.facetsFields || []).map(
|
||||
(field: ResponseFacetField) => {
|
||||
field => {
|
||||
field.pageSize = field.pageSize || 5;
|
||||
field.currentPageSize = field.pageSize;
|
||||
field.expanded = expandedFields.includes(field.label);
|
||||
|
||||
(field.buckets || []).forEach(bucket => {
|
||||
const buckets = (field.buckets || []).map(bucket => {
|
||||
bucket.$field = field.label;
|
||||
bucket.$checked = false;
|
||||
|
||||
@@ -173,21 +176,9 @@ export class SearchFilterComponent implements OnInit {
|
||||
if (previousBucket) {
|
||||
bucket.$checked = true;
|
||||
}
|
||||
return bucket;
|
||||
});
|
||||
|
||||
field.hasMoreItems = (): boolean => {
|
||||
return field.buckets && field.buckets.length > 0 && field.buckets.length > field.currentPageSize;
|
||||
};
|
||||
|
||||
field.showMoreItems = () => {
|
||||
field.currentPageSize += field.pageSize;
|
||||
};
|
||||
|
||||
field.getVisibleBuckets = (): FacetFieldBucket[] => {
|
||||
const buckets = field.buckets || [];
|
||||
return buckets.slice(0, field.currentPageSize);
|
||||
};
|
||||
|
||||
field.buckets = new SearchFilterList<FacetFieldBucket>(buckets, field.pageSize);
|
||||
return field;
|
||||
}
|
||||
);
|
||||
|
@@ -3,7 +3,8 @@
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput [formControl]="from" [errorStateMatcher]="matcher"
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.FROM' | translate }}">
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.FROM' | translate }}"
|
||||
autocomplete="off">
|
||||
<mat-error *ngIf="from.hasError('pattern')">
|
||||
{{ 'SEARCH.FILTER.VALIDATION.INVALID-FORMAT' | translate }}
|
||||
</mat-error>
|
||||
@@ -12,17 +13,18 @@
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field >
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput [formControl]="to" [errorStateMatcher]="matcher"
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.TO' | translate }}">
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.TO' | translate }}"
|
||||
autocomplete="off">
|
||||
<mat-error *ngIf="to.invalid">
|
||||
{{ 'SEARCH.FILTER.VALIDATION.INVALID-FORMAT' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
|
||||
<div>
|
||||
<div class="facet-buttons">
|
||||
<button mat-button color="primary" (click)="reset()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.CLEAR' | translate }}
|
||||
</button>
|
||||
|
@@ -1,8 +1,5 @@
|
||||
.adf-search-number-range > form {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
|
||||
.mat-button {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
width: 100%;
|
||||
}
|
||||
|
@@ -1,6 +1,24 @@
|
||||
<mat-radio-group [(ngModel)]="value" (change)="changeHandler($event)">
|
||||
<mat-radio-group
|
||||
[(ngModel)]="value"
|
||||
(change)="changeHandler($event)">
|
||||
<mat-radio-button
|
||||
*ngFor="let option of settings.options" [value]="option.value">
|
||||
{{ option.name }}
|
||||
*ngFor="let option of options"
|
||||
[value]="option.value">
|
||||
{{ option.name | translate }}
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
|
||||
<div class="facet-buttons" *ngIf="!options.fitsPage">
|
||||
<button mat-icon-button
|
||||
[disabled]="!options.canShowLessItems"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-LESS' | translate }}"
|
||||
(click)="options.showLessItems()">
|
||||
<mat-icon>keyboard_arrow_up</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
[disabled]="!options.canShowMoreItems"
|
||||
title="{{ 'SEARCH.FILTER.ACTIONS.SHOW-MORE' | translate }}"
|
||||
(click)="options.showMoreItems()">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
@@ -21,6 +21,12 @@ import { MatRadioChange } from '@angular/material';
|
||||
import { SearchWidget } from '../../search-widget.interface';
|
||||
import { SearchWidgetSettings } from '../../search-widget-settings.interface';
|
||||
import { SearchQueryBuilderService } from '../../search-query-builder.service';
|
||||
import { SearchFilterList } from '../search-filter/models/search-filter-list.model';
|
||||
|
||||
export interface SearchRadioOption {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'adf-search-radio',
|
||||
@@ -37,8 +43,24 @@ export class SearchRadioComponent implements SearchWidget, OnInit {
|
||||
id: string;
|
||||
settings: SearchWidgetSettings;
|
||||
context: SearchQueryBuilderService;
|
||||
options: SearchFilterList<SearchRadioOption>;
|
||||
pageSize = 5;
|
||||
|
||||
constructor() {
|
||||
this.options = new SearchFilterList<SearchRadioOption>();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.settings) {
|
||||
this.pageSize = this.settings.pageSize || 5;
|
||||
|
||||
if (this.settings.options && this.settings.options.length > 0) {
|
||||
this.options = new SearchFilterList<SearchRadioOption>(
|
||||
this.settings.options, this.pageSize
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.setValue(
|
||||
this.getSelectedValue()
|
||||
);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
(change)="onChangedHandler($event)">
|
||||
</mat-slider>
|
||||
|
||||
<div>
|
||||
<div class="facet-buttons">
|
||||
<button mat-button color="primary" (click)="reset()">
|
||||
{{ 'SEARCH.FILTER.ACTIONS.CLEAR' | translate }}
|
||||
</button>
|
||||
|
@@ -16,15 +16,12 @@
|
||||
*/
|
||||
|
||||
import { FacetFieldBucket } from './facet-field-bucket.interface';
|
||||
import { SearchFilterList } from './components/search-filter/models/search-filter-list.model';
|
||||
|
||||
export interface ResponseFacetField {
|
||||
label: string;
|
||||
buckets: Array<FacetFieldBucket>;
|
||||
buckets: SearchFilterList<FacetFieldBucket>;
|
||||
pageSize?: number;
|
||||
currentPageSize?: number;
|
||||
expanded?: boolean;
|
||||
|
||||
hasMoreItems(): boolean;
|
||||
showMoreItems(): void;
|
||||
getVisibleBuckets(): Array<FacetFieldBucket>;
|
||||
}
|
||||
|
@@ -519,7 +519,7 @@
|
||||
"description": "This specifies the facet field."
|
||||
},
|
||||
"mincount": {
|
||||
"type": "integer",
|
||||
"type": "number",
|
||||
"description": "This specifies the minimum count required for a facet field to be included in the response. The default value is 1."
|
||||
},
|
||||
"label": {
|
||||
@@ -531,9 +531,13 @@
|
||||
"description": "This restricts the possible constraints to only indexed values with a specified prefix."
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"type": "number",
|
||||
"description": "Maximum number of results"
|
||||
},
|
||||
"pageSize": {
|
||||
"type": "number",
|
||||
"description": "Display page size"
|
||||
},
|
||||
"offset": { "type": "integer" }
|
||||
}
|
||||
}
|
||||
@@ -583,8 +587,14 @@
|
||||
"type": "object",
|
||||
"required": [ "selector", "settings" ],
|
||||
"properties": {
|
||||
"selector": { "type": "string" },
|
||||
"settings": { "type": "object" }
|
||||
"selector": {
|
||||
"description": "Unique component runtime identifier",
|
||||
"type": "string"
|
||||
},
|
||||
"settings": {
|
||||
"description": "Component-specific settings",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user