mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Added more optimalisations and fixed tests
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
<div>
|
||||
<div class="filters py-2">
|
||||
<ds-search-facet-selected-option *ngFor="let value of (selectedValues | async)" [selectedValue]="value" [filterConfig]="filterConfig"></ds-search-facet-selected-option>
|
||||
<ds-search-facet-selected-option *ngFor="let value of (selectedValues$ | async)" [selectedValue]="value" [filterConfig]="filterConfig" [selectedValues$]="selectedValues$"></ds-search-facet-selected-option>
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)?.payload">
|
||||
<div [@facetLoad]="animationState">
|
||||
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value">
|
||||
</ds-search-facet-option>
|
||||
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value" [selectedValues$]="selectedValues$"></ds-search-facet-option>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="clearfix toggle-more-filters">
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<a *ngIf="isVisible" class="d-flex flex-row"
|
||||
<script src="search-facet-option.component.ts"></script><a *ngIf="isVisible | async" class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="addQueryParams | async" queryParamsHandling="merge">
|
||||
[queryParams]="addQueryParams" queryParamsHandling="merge">
|
||||
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value px-1">{{filterValue.value}}</span>
|
||||
<span class="float-right filter-value-count ml-auto">
|
||||
|
@@ -1,11 +1,13 @@
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs';
|
||||
import { map, take } from 'rxjs/operators';
|
||||
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { FacetValue } from '../../../../search-service/facet-value.model';
|
||||
import { SearchFilterConfig } from '../../../../search-service/search-filter-config.model';
|
||||
import { SearchService } from '../../../../search-service/search.service';
|
||||
import { SearchFilterService } from '../../search-filter.service';
|
||||
import { SearchConfigurationService } from '../../../../search-service/search-configuration.service';
|
||||
import { hasValue } from '../../../../../shared/empty.util';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-facet-option',
|
||||
@@ -15,24 +17,22 @@ import { SearchFilterService } from '../../search-filter.service';
|
||||
/**
|
||||
* Represents a single option in a filter facet
|
||||
*/
|
||||
export class SearchFacetOptionComponent implements OnInit {
|
||||
export class SearchFacetOptionComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* A single value for this component
|
||||
*/
|
||||
@Input() filterValue: FacetValue;
|
||||
@Input() filterConfig: SearchFilterConfig;
|
||||
|
||||
/**
|
||||
* Emits the active values for this filter
|
||||
*/
|
||||
selectedValues$: Observable<string[]>;
|
||||
@Input() selectedValues$: Observable<string[]>;
|
||||
|
||||
isVisible: Observable<boolean>;
|
||||
|
||||
addQueryParams;
|
||||
sub: Subscription;
|
||||
|
||||
constructor(protected searchService: SearchService,
|
||||
protected filterService: SearchFilterService,
|
||||
protected searchConfigService: SearchConfigurationService,
|
||||
protected router: Router
|
||||
) {
|
||||
}
|
||||
@@ -41,9 +41,11 @@ export class SearchFacetOptionComponent implements OnInit {
|
||||
* Initializes all observable instance variables and starts listening to them
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.selectedValues$ = this.filterService.getSelectedValuesForFilter(this.filterConfig);
|
||||
this.isVisible = this.isChecked().pipe(map((checked: boolean) => !checked));
|
||||
this.addQueryParams = this.getAddParams();
|
||||
this.sub = observableCombineLatest(this.selectedValues$, this.searchConfigService.searchOptions)
|
||||
.subscribe(([selectedValues, searchOptions]) => {
|
||||
this.updateAddParams(selectedValues)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,16 +65,17 @@ export class SearchFacetOptionComponent implements OnInit {
|
||||
/**
|
||||
* Calculates the parameters that should change if a given value for this filter would be added to the active filters
|
||||
* @param {string} value The value that is added for this filter
|
||||
* @returns {Observable<any>} The changed filter parameters
|
||||
*/
|
||||
private getAddParams(): Observable<any> {
|
||||
return this.selectedValues$.pipe(map((selectedValues) => {
|
||||
return {
|
||||
private updateAddParams(selectedValues: string[]): void {
|
||||
this.addQueryParams = {
|
||||
[this.filterConfig.paramName]: [...selectedValues, this.filterValue.value],
|
||||
page: 1
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (hasValue(this.sub)) {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<a *ngIf="isVisible" class="d-flex flex-row"
|
||||
<a *ngIf="isVisible | async" class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="changeQueryParams | async" queryParamsHandling="merge">
|
||||
[queryParams]="changeQueryParams" queryParamsHandling="merge">
|
||||
<span class="filter-value px-1">{{filterValue.value}}</span>
|
||||
<span class="float-right filter-value-count ml-auto">
|
||||
<span class="badge badge-secondary badge-pill">{{filterValue.count}}</span>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { FacetValue } from '../../../../search-service/facet-value.model';
|
||||
import { SearchFilterConfig } from '../../../../search-service/search-filter-config.model';
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
RANGE_FILTER_MAX_SUFFIX,
|
||||
RANGE_FILTER_MIN_SUFFIX
|
||||
} from '../../search-range-filter/search-range-filter.component';
|
||||
import { SearchConfigurationService } from '../../../../search-service/search-configuration.service';
|
||||
import { hasValue } from '../../../../../shared/empty.util';
|
||||
|
||||
const rangeDelimiter = '-';
|
||||
|
||||
@@ -21,24 +23,21 @@ const rangeDelimiter = '-';
|
||||
/**
|
||||
* Represents a single option in a filter facet
|
||||
*/
|
||||
export class SearchFacetRangeOptionComponent implements OnInit {
|
||||
export class SearchFacetRangeOptionComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* A single value for this component
|
||||
*/
|
||||
@Input() filterValue: FacetValue;
|
||||
@Input() filterConfig: SearchFilterConfig;
|
||||
|
||||
/**
|
||||
* Emits the active values for this filter
|
||||
*/
|
||||
selectedValues$: Observable<string[]>;
|
||||
|
||||
isVisible: Observable<boolean>;
|
||||
|
||||
changeQueryParams;
|
||||
sub: Subscription;
|
||||
|
||||
constructor(protected searchService: SearchService,
|
||||
protected filterService: SearchFilterService,
|
||||
protected searchConfigService: SearchConfigurationService,
|
||||
protected router: Router
|
||||
) {
|
||||
}
|
||||
@@ -47,9 +46,10 @@ export class SearchFacetRangeOptionComponent implements OnInit {
|
||||
* Initializes all observable instance variables and starts listening to them
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.selectedValues$ = this.filterService.getSelectedValuesForFilter(this.filterConfig);
|
||||
this.isVisible = this.isChecked().pipe(map((checked: boolean) => !checked));
|
||||
this.changeQueryParams = this.getChangeParams();
|
||||
this.sub = this.searchConfigService.searchOptions.subscribe(() => {
|
||||
this.updateChangeParams()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,23 +66,24 @@ export class SearchFacetRangeOptionComponent implements OnInit {
|
||||
return this.searchService.getSearchLink();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the parameters that should change if a given values for this range filter would be changed
|
||||
* @param {string} value The values that are changed for this filter
|
||||
* @returns {Observable<any>} The changed filter parameters
|
||||
*/
|
||||
getChangeParams() {
|
||||
updateChangeParams(): void {
|
||||
const parts = this.filterValue.value.split(rangeDelimiter);
|
||||
const min = parts.length > 1 ? parts[0].trim() : this.filterValue.value;
|
||||
const max = parts.length > 1 ? parts[1].trim() : this.filterValue.value;
|
||||
return observableOf(
|
||||
{
|
||||
this.changeQueryParams = {
|
||||
[this.filterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: [min],
|
||||
[this.filterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: [max],
|
||||
page: 1
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (hasValue(this.sub)) {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<a class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="removeQueryParams | async" queryParamsHandling="merge">
|
||||
[queryParams]="removeQueryParams" queryParamsHandling="merge">
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1">{{selectedValue}}</span>
|
||||
</a>
|
@@ -1,11 +1,19 @@
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import {
|
||||
combineLatest as observableCombineLatest,
|
||||
Observable,
|
||||
of as observableOf,
|
||||
Subscription
|
||||
} from 'rxjs';
|
||||
import { delay, map } from 'rxjs/operators';
|
||||
import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { FacetValue } from '../../../../search-service/facet-value.model';
|
||||
import { SearchFilterConfig } from '../../../../search-service/search-filter-config.model';
|
||||
import { SearchService } from '../../../../search-service/search.service';
|
||||
import { SearchFilterService } from '../../search-filter.service';
|
||||
import { hasValue } from '../../../../../shared/empty.util';
|
||||
import { SearchOptions } from '../../../../search-options.model';
|
||||
import { SearchConfigurationService } from '../../../../search-service/search-configuration.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-facet-selected-option',
|
||||
@@ -15,7 +23,7 @@ import { SearchFilterService } from '../../search-filter.service';
|
||||
/**
|
||||
* Represents a single option in a filter facet
|
||||
*/
|
||||
export class SearchFacetSelectedOptionComponent implements OnInit {
|
||||
export class SearchFacetSelectedOptionComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* A single value for this component
|
||||
*/
|
||||
@@ -25,12 +33,14 @@ export class SearchFacetSelectedOptionComponent implements OnInit {
|
||||
/**
|
||||
* Emits the active values for this filter
|
||||
*/
|
||||
selectedValues$: Observable<string[]>;
|
||||
@Input() selectedValues$: Observable<string[]>;
|
||||
|
||||
removeQueryParams;
|
||||
sub: Subscription;
|
||||
|
||||
constructor(protected searchService: SearchService,
|
||||
protected filterService: SearchFilterService,
|
||||
protected searchConfigService: SearchConfigurationService,
|
||||
protected router: Router
|
||||
) {
|
||||
}
|
||||
@@ -39,8 +49,10 @@ export class SearchFacetSelectedOptionComponent implements OnInit {
|
||||
* Initializes all observable instance variables and starts listening to them
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.selectedValues$ = this.filterService.getSelectedValuesForFilter(this.filterConfig);
|
||||
this.removeQueryParams = this.getRemoveParams();
|
||||
this.sub = observableCombineLatest(this.selectedValues$, this.searchConfigService.searchOptions)
|
||||
.subscribe(([selectedValues, searchOptions]) => {
|
||||
this.updateRemoveParams(selectedValues)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,13 +67,16 @@ export class SearchFacetSelectedOptionComponent implements OnInit {
|
||||
* @param {string} value The value that is removed for this filter
|
||||
* @returns {Observable<any>} The changed filter parameters
|
||||
*/
|
||||
private getRemoveParams(): Observable<any> {
|
||||
return this.selectedValues$.pipe(map((selectedValues) => {
|
||||
return {
|
||||
private updateRemoveParams(selectedValues: string[]): void {
|
||||
this.removeQueryParams = {
|
||||
[this.filterConfig.paramName]: selectedValues.filter((v) => v !== this.selectedValue),
|
||||
page: 1
|
||||
};
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (hasValue(this.sub)) {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -120,20 +120,6 @@ describe('SearchFacetFilterComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the getAddParams method is called wih a value', () => {
|
||||
it('should return the selectedValue list with the new parameter value', () => {
|
||||
const result = comp.getAddParams(value3);
|
||||
result.subscribe((r) => expect(r[mockFilterConfig.paramName]).toEqual([value1, value2, value3]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the getRemoveParams method is called wih a value', () => {
|
||||
it('should return the selectedValue list with the parameter value left out', () => {
|
||||
const result = comp.getRemoveParams(value1);
|
||||
result.subscribe((r) => expect(r[mockFilterConfig.paramName]).toEqual([value2]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the showMore method is called', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(filterService, 'incrementPage');
|
||||
|
@@ -22,6 +22,7 @@ import { FILTER_CONFIG, SearchFilterService } from '../search-filter.service';
|
||||
import { SearchConfigurationService } from '../../../search-service/search-configuration.service';
|
||||
import { getSucceededRemoteData } from '../../../../core/shared/operators';
|
||||
import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model';
|
||||
import { SearchOptions } from '../../../search-options.model';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-facet-filter',
|
||||
@@ -65,13 +66,14 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Emits the active values for this filter
|
||||
*/
|
||||
selectedValues: Observable<string[]>;
|
||||
selectedValues$: Observable<string[]>;
|
||||
private collapseNextUpdate = true;
|
||||
|
||||
/**
|
||||
* State of the requested facets used to time the animation
|
||||
*/
|
||||
animationState = 'loading';
|
||||
searchOptions$: Observable<SearchOptions>;
|
||||
|
||||
constructor(protected searchService: SearchService,
|
||||
protected filterService: SearchFilterService,
|
||||
@@ -85,15 +87,13 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
* Initializes all observable instance variables and starts listening to them
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
console.log('renderSearchFacetFilterComponent')
|
||||
|
||||
this.filterValues$ = new BehaviorSubject(new RemoteData(true, false, undefined, undefined, undefined));
|
||||
this.currentPage = this.getCurrentPage().pipe(distinctUntilChanged());
|
||||
|
||||
this.selectedValues = this.filterService.getSelectedValuesForFilter(this.filterConfig);
|
||||
const searchOptions = this.searchConfigService.searchOptions;
|
||||
this.subs.push(this.searchConfigService.searchOptions.subscribe(() => this.updateFilterValueList()));
|
||||
const facetValues = observableCombineLatest(searchOptions, this.currentPage).pipe(
|
||||
this.selectedValues$ = this.filterService.getSelectedValuesForFilter(this.filterConfig);
|
||||
this.searchOptions$ = this.searchConfigService.searchOptions;
|
||||
this.subs.push(this.searchOptions$.subscribe(() => this.updateFilterValueList()));
|
||||
const facetValues = observableCombineLatest(this.searchOptions$, this.currentPage).pipe(
|
||||
map(([options, page]) => {
|
||||
return { options, page }
|
||||
}),
|
||||
@@ -193,8 +193,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
* @param data The string from the input field
|
||||
*/
|
||||
onSubmit(data: any) {
|
||||
console.log('onsubmit');
|
||||
this.selectedValues.pipe(take(1)).subscribe((selectedValues) => {
|
||||
this.selectedValues$.pipe(take(1)).subscribe((selectedValues) => {
|
||||
if (isNotEmpty(data)) {
|
||||
this.router.navigate([this.getSearchLink()], {
|
||||
queryParams:
|
||||
@@ -219,34 +218,6 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
return hasValue(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the parameters that should change if a given value for this filter would be removed from the active filters
|
||||
* @param {string} value The value that is removed for this filter
|
||||
* @returns {Observable<any>} The changed filter parameters
|
||||
*/
|
||||
getRemoveParams(value: string): Observable<any> {
|
||||
return this.selectedValues.pipe(map((selectedValues) => {
|
||||
return {
|
||||
[this.filterConfig.paramName]: selectedValues.filter((v) => v !== value),
|
||||
page: 1
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the parameters that should change if a given value for this filter would be added to the active filters
|
||||
* @param {string} value The value that is added for this filter
|
||||
* @returns {Observable<any>} The changed filter parameters
|
||||
*/
|
||||
getAddParams(value: string): Observable<any> {
|
||||
return this.selectedValues.pipe(map((selectedValues) => {
|
||||
return {
|
||||
[this.filterConfig.paramName]: [...selectedValues, value],
|
||||
page: 1
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from all subscriptions
|
||||
*/
|
||||
@@ -263,7 +234,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
findSuggestions(data): void {
|
||||
if (isNotEmpty(data)) {
|
||||
this.searchConfigService.searchOptions.pipe(take(1)).subscribe(
|
||||
this.searchOptions$.pipe(take(1)).subscribe(
|
||||
(options) => {
|
||||
this.filterSearchResults = this.searchService.getFacetValuesFor(this.filterConfig, 1, options, data.toLowerCase())
|
||||
.pipe(
|
||||
@@ -295,7 +266,6 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
|
||||
return new EmphasizePipe().transform(facet.value, query) + ' (' + facet.count + ')';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prevent unnecessary rerendering
|
||||
*/
|
||||
|
@@ -10,6 +10,7 @@ import { SearchService } from '../../search-service/search.service';
|
||||
import { SearchFilterComponent } from './search-filter.component';
|
||||
import { SearchFilterConfig } from '../../search-service/search-filter-config.model';
|
||||
import { FilterType } from '../../search-service/filter-type.model';
|
||||
import { SearchConfigurationService } from '../../search-service/search-configuration.service';
|
||||
|
||||
describe('SearchFilterComponent', () => {
|
||||
let comp: SearchFilterComponent;
|
||||
@@ -33,9 +34,7 @@ describe('SearchFilterComponent', () => {
|
||||
},
|
||||
expand: (filter) => {
|
||||
},
|
||||
initialCollapse: (filter) => {
|
||||
},
|
||||
initialExpand: (filter) => {
|
||||
initializeFilter: (filter) => {
|
||||
},
|
||||
getSelectedValuesForFilter: (filter) => {
|
||||
return observableOf([filterName1, filterName2, filterName3])
|
||||
@@ -55,6 +54,8 @@ describe('SearchFilterComponent', () => {
|
||||
getFacetValuesFor: (filter) => mockResults
|
||||
};
|
||||
|
||||
const searchConfigServiceStub = {};
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), NoopAnimationsModule],
|
||||
@@ -65,6 +66,7 @@ describe('SearchFilterComponent', () => {
|
||||
provide: SearchFilterService,
|
||||
useValue: mockFilterService
|
||||
},
|
||||
{ provide: SearchConfigurationService, useValue: searchConfigServiceStub },
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).overrideComponent(SearchFilterComponent, {
|
||||
@@ -91,32 +93,21 @@ describe('SearchFilterComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the initialCollapse method is triggered', () => {
|
||||
describe('when the initializeFilter method is triggered', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(filterService, 'initialCollapse');
|
||||
comp.initialCollapse();
|
||||
spyOn(filterService, 'initializeFilter');
|
||||
comp.initializeFilter();
|
||||
});
|
||||
|
||||
it('should call initialCollapse with the correct filter configuration name', () => {
|
||||
expect(filterService.initialCollapse).toHaveBeenCalledWith(mockFilterConfig.name)
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the initialExpand method is triggered', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(filterService, 'initialExpand');
|
||||
comp.initialExpand();
|
||||
});
|
||||
|
||||
it('should call initialCollapse with the correct filter configuration name', () => {
|
||||
expect(filterService.initialExpand).toHaveBeenCalledWith(mockFilterConfig.name)
|
||||
expect(filterService.initializeFilter).toHaveBeenCalledWith(mockFilterConfig)
|
||||
});
|
||||
});
|
||||
|
||||
describe('when getSelectedValues is called', () => {
|
||||
let valuesObservable: Observable<string[]>;
|
||||
beforeEach(() => {
|
||||
valuesObservable = comp.getSelectedValues();
|
||||
valuesObservable = (comp as any).getSelectedValues();
|
||||
});
|
||||
|
||||
it('should return an observable containing the existing filters', () => {
|
||||
@@ -141,7 +132,7 @@ describe('SearchFilterComponent', () => {
|
||||
let isActive: Observable<boolean>;
|
||||
beforeEach(() => {
|
||||
filterService.isCollapsed = () => observableOf(true);
|
||||
isActive = comp.isCollapsed();
|
||||
isActive = (comp as any).isCollapsed();
|
||||
});
|
||||
|
||||
it('should return an observable containing true', () => {
|
||||
@@ -156,7 +147,7 @@ describe('SearchFilterComponent', () => {
|
||||
let isActive: Observable<boolean>;
|
||||
beforeEach(() => {
|
||||
filterService.isCollapsed = () => observableOf(false);
|
||||
isActive = comp.isCollapsed();
|
||||
isActive = (comp as any).isCollapsed();
|
||||
});
|
||||
|
||||
it('should return an observable containing false', () => {
|
||||
|
@@ -1,10 +1,8 @@
|
||||
import * as deepFreeze from 'deep-freeze';
|
||||
import {
|
||||
SearchFilterCollapseAction, SearchFilterExpandAction, SearchFilterIncrementPageAction,
|
||||
SearchFilterInitialCollapseAction,
|
||||
SearchFilterInitialExpandAction,
|
||||
SearchFilterToggleAction,
|
||||
SearchFilterDecrementPageAction, SearchFilterResetPageAction
|
||||
SearchFilterDecrementPageAction, SearchFilterResetPageAction, SearchFilterInitializeAction
|
||||
} from './search-filter.actions';
|
||||
import { filterReducer } from './search-filter.reducer';
|
||||
|
||||
@@ -98,35 +96,39 @@ describe('filterReducer', () => {
|
||||
filterReducer(state, action);
|
||||
});
|
||||
|
||||
it('should set filterCollapsed to true in response to the INITIAL_COLLAPSE action when no state has been set for this filter', () => {
|
||||
it('should set filterCollapsed to true in response to the INITIALIZE action with isOpenByDefault to false when no state has been set for this filter', () => {
|
||||
const state = {};
|
||||
state[filterName2] = { filterCollapsed: false, page: 1 };
|
||||
const action = new SearchFilterInitialCollapseAction(filterName1);
|
||||
const filterConfig = {isOpenByDefault: false, name: filterName1} as any;
|
||||
const action = new SearchFilterInitializeAction(filterConfig);
|
||||
const newState = filterReducer(state, action);
|
||||
|
||||
expect(newState[filterName1].filterCollapsed).toEqual(true);
|
||||
});
|
||||
|
||||
it('should set filterCollapsed to true in response to the INITIAL_EXPAND action when no state has been set for this filter', () => {
|
||||
it('should set filterCollapsed to false in response to the INITIALIZE action with isOpenByDefault to true when no state has been set for this filter', () => {
|
||||
const state = {};
|
||||
state[filterName2] = { filterCollapsed: true, page: 1 };
|
||||
const action = new SearchFilterInitialExpandAction(filterName1);
|
||||
const filterConfig = {isOpenByDefault: true, name: filterName1} as any;
|
||||
const action = new SearchFilterInitializeAction(filterConfig);
|
||||
const newState = filterReducer(state, action);
|
||||
expect(newState[filterName1].filterCollapsed).toEqual(false);
|
||||
});
|
||||
|
||||
it('should not change the state in response to the INITIAL_COLLAPSE action when the state has already been set for this filter', () => {
|
||||
it('should not change the state in response to the INITIALIZE action with isOpenByDefault to false when the state has already been set for this filter', () => {
|
||||
const state = {};
|
||||
state[filterName1] = { filterCollapsed: false, page: 1 };
|
||||
const action = new SearchFilterInitialCollapseAction(filterName1);
|
||||
const filterConfig = { isOpenByDefault: true, name: filterName1 } as any;
|
||||
const action = new SearchFilterInitializeAction(filterConfig);
|
||||
const newState = filterReducer(state, action);
|
||||
expect(newState).toEqual(state);
|
||||
});
|
||||
|
||||
it('should not change the state in response to the INITIAL_EXPAND action when the state has already been set for this filter', () => {
|
||||
it('should not change the state in response to the INITIALIZE action with isOpenByDefault to true when the state has already been set for this filter', () => {
|
||||
const state = {};
|
||||
state[filterName1] = { filterCollapsed: true, page: 1 };
|
||||
const action = new SearchFilterInitialExpandAction(filterName1);
|
||||
const filterConfig = { isOpenByDefault: false, name: filterName1 } as any;
|
||||
const action = new SearchFilterInitializeAction(filterConfig);
|
||||
const newState = filterReducer(state, action);
|
||||
expect(newState).toEqual(state);
|
||||
});
|
||||
|
@@ -71,7 +71,6 @@ describe('SearchFilterService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('when the collapse method is triggered', () => {
|
||||
beforeEach(() => {
|
||||
service.collapse(mockFilterConfig.name);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
||||
import { Injectable, InjectionToken } from '@angular/core';
|
||||
import { distinctUntilChanged, map, tap } from 'rxjs/operators';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { SearchFiltersState, SearchFilterState } from './search-filter.reducer';
|
||||
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
|
||||
import {
|
||||
@@ -16,9 +16,8 @@ import { hasValue, isNotEmpty, } from '../../../shared/empty.util';
|
||||
import { SearchFilterConfig } from '../../search-service/search-filter-config.model';
|
||||
import { RouteService } from '../../../shared/services/route.service';
|
||||
import { Params } from '@angular/router';
|
||||
import { tag } from 'rxjs-spy/operators';
|
||||
import { create, detect } from "rxjs-spy";
|
||||
const spy = create();
|
||||
import { SearchOptions } from '../../search-options.model';
|
||||
// const spy = create();
|
||||
const filterStateSelector = (state: SearchFiltersState) => state.searchFilter;
|
||||
|
||||
export const FILTER_CONFIG: InjectionToken<SearchFilterConfig> = new InjectionToken<SearchFilterConfig>('filterConfig');
|
||||
@@ -59,17 +58,10 @@ export class SearchFilterService {
|
||||
* @returns {Observable<string[]>} Emits the active filters for the given filter configuration
|
||||
*/
|
||||
getSelectedValuesForFilter(filterConfig: SearchFilterConfig): Observable<string[]> {
|
||||
const values$ = this.routeService.getQueryParameterValues(filterConfig.paramName).pipe(
|
||||
tag("parameter")
|
||||
);
|
||||
const values$ = this.routeService.getQueryParameterValues(filterConfig.paramName);
|
||||
const prefixValues$ = this.routeService.getQueryParamsWithPrefix(filterConfig.paramName + '.').pipe(
|
||||
map((params: Params) => [].concat(...Object.values(params))),
|
||||
tag("prefix-tag")
|
||||
|
||||
|
||||
);
|
||||
spy.log();
|
||||
detect('prefix-tag');
|
||||
|
||||
return observableCombineLatest(values$, prefixValues$).pipe(
|
||||
map(([values, prefixValues]) => {
|
||||
|
@@ -1,15 +1,9 @@
|
||||
<div>
|
||||
<div class="filters py-2">
|
||||
<a *ngFor="let value of (selectedValues | async)" class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="getRemoveParams(value) | async" queryParamsHandling="merge">
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1">{{value}}</span>
|
||||
</a>
|
||||
<ds-search-facet-selected-option *ngFor="let value of (selectedValues$ | async)" [selectedValue]="value" [filterConfig]="filterConfig" [selectedValues$]="selectedValues$"></ds-search-facet-selected-option>
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)?.payload">
|
||||
<div [@facetLoad]="animationState">
|
||||
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value">
|
||||
</ds-search-facet-option>
|
||||
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value" [selectedValues$]="selectedValues$"></ds-search-facet-option>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="clearfix toggle-more-filters">
|
||||
|
@@ -24,9 +24,7 @@
|
||||
</ng-container>
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)?.payload">
|
||||
<div [@facetLoad]="animationState">
|
||||
<ng-container *ngFor="let value of page.page; trackBy: trackUpdate">
|
||||
|
||||
</ng-container>
|
||||
<ds-search-facet-range-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value"></ds-search-facet-range-option>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
@@ -106,16 +106,6 @@ describe('SearchRangeFilterComponent', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
describe('when the getChangeParams method is called wih a value', () => {
|
||||
it('should return the selectedValue list with the new parameter value', () => {
|
||||
const result$ = comp.getChangeParams(value3);
|
||||
result$.subscribe((result) => {
|
||||
expect(result[mockFilterConfig.paramName + minSuffix]).toEqual(['1990']);
|
||||
expect(result[mockFilterConfig.paramName + maxSuffix]).toEqual(['1992']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the onSubmit method is called with data', () => {
|
||||
const searchUrl = '/search/path';
|
||||
// const data = { [mockFilterConfig.paramName + minSuffix]: '1900', [mockFilterConfig.paramName + maxSuffix]: '1950' };
|
||||
|
@@ -95,8 +95,6 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple
|
||||
).subscribe((minmax) => this.range = minmax);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Submits new custom range values to the range filter from the widget
|
||||
*/
|
||||
|
@@ -1,19 +1,9 @@
|
||||
<div>
|
||||
<div class="filters py-2">
|
||||
<a *ngFor="let value of (selectedValues | async)" class="d-flex flex-row"
|
||||
[routerLink]="[getSearchLink()]"
|
||||
[queryParams]="getRemoveParams(value) | async" queryParamsHandling="merge">
|
||||
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
|
||||
<span class="filter-value pl-1">{{value}}</span>
|
||||
</a>
|
||||
<ng-container *ngVar="(filterValues$ | async) as filterValuesRD">
|
||||
<ds-search-facet-selected-option *ngFor="let value of (selectedValues$ | async)" [selectedValue]="value" [filterConfig]="filterConfig" [selectedValues$]="selectedValues$"></ds-search-facet-selected-option>
|
||||
<ng-container *ngFor="let page of (filterValues$ | async)?.payload">
|
||||
<div [@facetLoad]="animationState">
|
||||
<ng-container *ngFor="let page of filterValuesRD?.payload">
|
||||
<ng-container *ngFor="let value of page.page; trackBy: trackUpdate">
|
||||
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value">
|
||||
</ds-search-facet-option>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value" [selectedValues$]="selectedValues$"></ds-search-facet-option>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="clearfix toggle-more-filters">
|
||||
|
@@ -117,7 +117,7 @@ describe('SearchConfigurationService', () => {
|
||||
|
||||
describe('when subscribeToSearchOptions is called', () => {
|
||||
beforeEach(() => {
|
||||
service.subscribeToSearchOptions(defaults)
|
||||
(service as any).subscribeToSearchOptions(defaults)
|
||||
});
|
||||
it('should call all getters it needs, but not call any others', () => {
|
||||
expect(service.getCurrentPagination).not.toHaveBeenCalled();
|
||||
@@ -131,7 +131,7 @@ describe('SearchConfigurationService', () => {
|
||||
|
||||
describe('when subscribeToPaginatedSearchOptions is called', () => {
|
||||
beforeEach(() => {
|
||||
service.subscribeToPaginatedSearchOptions(defaults);
|
||||
(service as any).subscribeToPaginatedSearchOptions(defaults);
|
||||
});
|
||||
it('should call all getters it needs', () => {
|
||||
expect(service.getCurrentPagination).toHaveBeenCalled();
|
||||
|
@@ -186,7 +186,7 @@ export class SearchConfigurationService implements OnDestroy {
|
||||
* @param {SearchOptions} defaults Default values for when no parameters are available
|
||||
* @returns {Subscription} The subscription to unsubscribe from
|
||||
*/
|
||||
subscribeToSearchOptions(defaults: SearchOptions): Subscription {
|
||||
private subscribeToSearchOptions(defaults: SearchOptions): Subscription {
|
||||
return observableMerge(
|
||||
this.getScopePart(defaults.scope),
|
||||
this.getQueryPart(defaults.query),
|
||||
@@ -204,7 +204,7 @@ export class SearchConfigurationService implements OnDestroy {
|
||||
* @param {PaginatedSearchOptions} defaults Default values for when no parameters are available
|
||||
* @returns {Subscription} The subscription to unsubscribe from
|
||||
*/
|
||||
subscribeToPaginatedSearchOptions(defaults: PaginatedSearchOptions): Subscription {
|
||||
private subscribeToPaginatedSearchOptions(defaults: PaginatedSearchOptions): Subscription {
|
||||
return observableMerge(
|
||||
this.getPaginationPart(defaults.pagination),
|
||||
this.getSortPart(defaults.sort),
|
||||
|
@@ -15,7 +15,6 @@ export class RouteService {
|
||||
}
|
||||
|
||||
getQueryParameterValues(paramName: string): Observable<string[]> {
|
||||
console.log('called');
|
||||
return this.route.queryParamMap.pipe(
|
||||
map((params) => [...params.getAll(paramName)]),
|
||||
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
|
||||
@@ -46,7 +45,6 @@ export class RouteService {
|
||||
getQueryParamsWithPrefix(prefix: string): Observable<Params> {
|
||||
return this.route.queryParamMap.pipe(
|
||||
map((qparams) => {
|
||||
console.log('map');
|
||||
const params = {};
|
||||
qparams.keys
|
||||
.filter((key) => key.startsWith(prefix))
|
||||
@@ -55,8 +53,7 @@ export class RouteService {
|
||||
});
|
||||
return params;
|
||||
}),
|
||||
distinctUntilChanged((a, b) => { console.log('changed?', a, b, JSON.stringify(a) === JSON.stringify(b)); return JSON.stringify(a) === JSON.stringify(b)}),
|
||||
tap((t) => console.log('changed'))
|
||||
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,6 @@ import { BrowserAppModule } from './modules/app/browser-app.module';
|
||||
|
||||
import { ENV_CONFIG } from './config';
|
||||
|
||||
|
||||
if (ENV_CONFIG.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
Reference in New Issue
Block a user