tests for SearchConfigurationService

This commit is contained in:
lotte
2018-08-02 10:29:37 +02:00
parent 9ebd25709d
commit f04f5a1170
12 changed files with 212 additions and 143 deletions

View File

@@ -66,7 +66,7 @@ describe('SearchFacetFilterComponent', () => {
{ provide: Router, useValue: new RouterStub() }, { provide: Router, useValue: new RouterStub() },
{ provide: FILTER_CONFIG, useValue: new SearchFilterConfig() }, { provide: FILTER_CONFIG, useValue: new SearchFilterConfig() },
{ provide: RemoteDataBuildService, useValue: {aggregate: () => Observable.of({})} }, { provide: RemoteDataBuildService, useValue: {aggregate: () => Observable.of({})} },
{ provide: SearchConfigurationService, useValue: {getSearchOptions: () => Observable.of({})} }, { provide: SearchConfigurationService, useValue: {searchOptions: Observable.of({})} },
{ {
provide: SearchFilterService, useValue: { provide: SearchFilterService, useValue: {
getSelectedValuesForFilter: () => Observable.of(selectedValues), getSelectedValuesForFilter: () => Observable.of(selectedValues),

View File

@@ -82,14 +82,18 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
this.filterValues$ = new BehaviorSubject(new RemoteData(true, false, undefined, undefined, undefined)); this.filterValues$ = new BehaviorSubject(new RemoteData(true, false, undefined, undefined, undefined));
this.currentPage = this.getCurrentPage().distinctUntilChanged(); this.currentPage = this.getCurrentPage().distinctUntilChanged();
this.selectedValues = this.filterService.getSelectedValuesForFilter(this.filterConfig); this.selectedValues = this.filterService.getSelectedValuesForFilter(this.filterConfig);
const searchOptions = this.searchConfigService.getSearchOptions().distinctUntilChanged(); const searchOptions = this.searchConfigService.searchOptions;
this.subs.push(searchOptions.subscribe((options) => this.updateFilterValueList())); this.subs.push(this.searchConfigService.searchOptions.subscribe(() => this.updateFilterValueList()));
const facetValues = Observable.combineLatest(searchOptions, this.currentPage, (options, page) => { const facetValues = Observable.combineLatest(searchOptions, this.currentPage, (options, page) => {
return { return { options, page }
values: this.searchService.getFacetValuesFor(this.filterConfig, page, options), }).switchMap(({ options, page }) => {
page: page return this.searchService.getFacetValuesFor(this.filterConfig, page, options).map((results) => {
}; return {
values: Observable.of(results),
page: page
};
}
);
}); });
let filterValues = []; let filterValues = [];
this.subs.push(facetValues.subscribe((facetOutcome) => { this.subs.push(facetValues.subscribe((facetOutcome) => {
@@ -242,7 +246,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
*/ */
findSuggestions(data): void { findSuggestions(data): void {
if (isNotEmpty(data)) { if (isNotEmpty(data)) {
this.searchConfigService.getSearchOptions().first().subscribe( this.searchConfigService.searchOptions.first().subscribe(
(options) => { (options) => {
this.filterSearchResults = this.searchService.getFacetValuesFor(this.filterConfig, 1, options, data.toLowerCase()) this.filterSearchResults = this.searchService.getFacetValuesFor(this.filterConfig, 1, options, data.toLowerCase())
.first() .first()

View File

@@ -74,7 +74,7 @@ describe('SearchRangeFilterComponent', () => {
{ provide: RemoteDataBuildService, useValue: {aggregate: () => Observable.of({})} }, { provide: RemoteDataBuildService, useValue: {aggregate: () => Observable.of({})} },
{ provide: RouteService, useValue: {getQueryParameterValue: () => Observable.of({})} }, { provide: RouteService, useValue: {getQueryParameterValue: () => Observable.of({})} },
{ provide: SearchConfigurationService, useValue: { { provide: SearchConfigurationService, useValue: {
getSearchOptions: () => Observable.of({}) } searchOptions: Observable.of({}) }
}, },
{ {
provide: SearchFilterService, useValue: { provide: SearchFilterService, useValue: {

View File

@@ -1,6 +1,6 @@
<h3>{{"search.filters.head" | translate}}</h3> <h3>{{"search.filters.head" | translate}}</h3>
<div *ngIf="(filters | async)?.hasSucceeded"> <div *ngIf="(filters | async)?.hasSucceeded">
<div *ngFor="let filter of (filters | async).payload"> <div *ngFor="let filter of (filters | async)?.payload">
<ds-search-filter class="d-block mb-3 p-3" [filter]="filter"></ds-search-filter> <ds-search-filter class="d-block mb-3 p-3" [filter]="filter"></ds-search-filter>
</div> </div>
</div> </div>

View File

@@ -20,6 +20,7 @@ import { NgbCollapseModule } from '@ng-bootstrap/ng-bootstrap';
import { SearchSidebarService } from './search-sidebar/search-sidebar.service'; import { SearchSidebarService } from './search-sidebar/search-sidebar.service';
import { SearchFilterService } from './search-filters/search-filter/search-filter.service'; import { SearchFilterService } from './search-filters/search-filter/search-filter.service';
import { SearchConfigurationService } from './search-service/search-configuration.service'; import { SearchConfigurationService } from './search-service/search-configuration.service';
import { RemoteData } from '../core/data/remote-data';
describe('SearchPageComponent', () => { describe('SearchPageComponent', () => {
let comp: SearchPageComponent; let comp: SearchPageComponent;
@@ -36,7 +37,7 @@ describe('SearchPageComponent', () => {
pagination.currentPage = 1; pagination.currentPage = 1;
pagination.pageSize = 10; pagination.pageSize = 10;
const sort: SortOptions = new SortOptions('score', SortDirection.DESC); const sort: SortOptions = new SortOptions('score', SortDirection.DESC);
const mockResults = Observable.of(['test', 'data']); const mockResults = Observable.of(new RemoteData(false, false, true, null,['test', 'data']));
const searchServiceStub = jasmine.createSpyObj('SearchService', { const searchServiceStub = jasmine.createSpyObj('SearchService', {
search: mockResults, search: mockResults,
getSearchLink: '/search', getSearchLink: '/search',
@@ -45,11 +46,11 @@ describe('SearchPageComponent', () => {
const queryParam = 'test query'; const queryParam = 'test query';
const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f';
const paginatedSearchOptions = { const paginatedSearchOptions = {
query: queryParam, query: queryParam,
scope: scopeParam, scope: scopeParam,
pagination, pagination,
sort sort
}; };
const activatedRouteStub = { const activatedRouteStub = {
queryParams: Observable.of({ queryParams: Observable.of({
query: queryParam, query: queryParam,
@@ -91,17 +92,14 @@ describe('SearchPageComponent', () => {
{ {
provide: SearchFilterService, provide: SearchFilterService,
useValue: {} useValue: {}
},{ }, {
provide: SearchConfigurationService, provide: SearchConfigurationService,
useValue: jasmine.createSpyObj('SearchConfigurationService', { useValue: {
getPaginatedSearchOptions: hot('a', { paginatedSearchOptions: hot('a', {
a: paginatedSearchOptions a: paginatedSearchOptions
}), }),
getCurrentScope: hot('a', { getCurrentScope: (a) => Observable.of('test-id')
a: 'test-id' }
}),
})
}, },
], ],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
@@ -180,4 +178,5 @@ describe('SearchPageComponent', () => {
}); });
}); });
}); })
;

View File

@@ -1,7 +1,6 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { flatMap, } from 'rxjs/operators'; import { flatMap, } from 'rxjs/operators';
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
import { PaginatedList } from '../core/data/paginated-list'; import { PaginatedList } from '../core/data/paginated-list';
import { RemoteData } from '../core/data/remote-data'; import { RemoteData } from '../core/data/remote-data';
import { DSpaceObject } from '../core/shared/dspace-object.model'; import { DSpaceObject } from '../core/shared/dspace-object.model';
@@ -77,11 +76,16 @@ export class SearchPageComponent implements OnInit {
* If something changes, update the list of scopes for the dropdown * If something changes, update the list of scopes for the dropdown
*/ */
ngOnInit(): void { ngOnInit(): void {
this.searchOptions$ = this.searchConfigService.getPaginatedSearchOptions(); this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
this.sub = this.searchOptions$.subscribe((searchOptions) => let subscription;
this.service.search(searchOptions).filter((rd) => !rd.isLoading).first().subscribe((results) => this.resultsRD$.next(results))); this.sub = this.searchOptions$.subscribe((searchOptions) => {
if (hasValue(subscription)) {
this.scopeListRD$ = this.searchConfigService.getCurrentScope().pipe( /** Make sure no race condition is possible with a previous result coming back from the server later */
subscription.unsubscribe();
}
subscription = this.service.search(searchOptions).filter((rd) => !rd.isLoading).first().subscribe((results) => this.resultsRD$.next(results))
});
this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe(
flatMap((scopeId) => this.service.getScopes(scopeId)) flatMap((scopeId) => this.service.getScopes(scopeId))
); );
} }

View File

@@ -2,9 +2,12 @@ import { SearchConfigurationService } from './search-configuration.service';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { ActivatedRouteStub } from '../../shared/testing/active-router-stub'; import { ActivatedRouteStub } from '../../shared/testing/active-router-stub';
import { RemoteData } from '../../core/data/remote-data'; import { RemoteData } from '../../core/data/remote-data';
import { fakeAsync, tick } from '@angular/core/testing'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
import { PaginatedSearchOptions } from '../paginated-search-options.model';
import { cold, hot } from 'jasmine-marbles';
describe('SearchConfigurationService', () => { fdescribe('SearchConfigurationService', () => {
let service: SearchConfigurationService; let service: SearchConfigurationService;
const value1 = 'random value'; const value1 = 'random value';
const value2 = 'another value'; const value2 = 'another value';
@@ -13,13 +16,17 @@ describe('SearchConfigurationService', () => {
'f.date.min': ['2013'], 'f.date.min': ['2013'],
'f.date.max': ['2018'] 'f.date.max': ['2018']
}; };
const defaults = Observable.of(new RemoteData(false, false, true, null, {})) const defaults = Object.assign(new PaginatedSearchOptions(), {
pagination: Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }),
sort: new SortOptions('score', SortDirection.DESC),
query: '',
scope: ''
});
const backendFilters = { 'f.author': ['another value'], 'f.date': ['[2013 TO 2018]'] }; const backendFilters = { 'f.author': ['another value'], 'f.date': ['[2013 TO 2018]'] };
const spy = jasmine.createSpyObj('SearchConfigurationService', { const spy = jasmine.createSpyObj('RouteService', {
getQueryParameterValue: Observable.of([value1, value2]) getQueryParameterValue: cold('a', {a: [value1, value2]}),
, getQueryParamsWithPrefix: cold('a', {a: prefixFilter}),
getQueryParamsWithPrefix: Observable.of(prefixFilter)
}); });
const activatedRoute: any = new ActivatedRouteStub(); const activatedRoute: any = new ActivatedRouteStub();
@@ -28,9 +35,9 @@ describe('SearchConfigurationService', () => {
service = new SearchConfigurationService(spy, activatedRoute); service = new SearchConfigurationService(spy, activatedRoute);
}); });
describe('when getCurrentScope is called', () => { describe('when the scope is called', () => {
beforeEach(() => { beforeEach(() => {
service.getCurrentScope(); service.getCurrentScope('');
}); });
it('should call getQueryParameterValue on the routeService with parameter name \'scope\'', () => { it('should call getQueryParameterValue on the routeService with parameter name \'scope\'', () => {
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('scope'); expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('scope');
@@ -39,7 +46,7 @@ describe('SearchConfigurationService', () => {
describe('when getCurrentQuery is called', () => { describe('when getCurrentQuery is called', () => {
beforeEach(() => { beforeEach(() => {
service.getCurrentQuery(); service.getCurrentQuery('');
}); });
it('should call getQueryParameterValue on the routeService with parameter name \'query\'', () => { it('should call getQueryParameterValue on the routeService with parameter name \'query\'', () => {
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('query'); expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('query');
@@ -81,7 +88,7 @@ describe('SearchConfigurationService', () => {
}); });
describe('when getCurrentPagination is called', () => { describe('when getCurrentPagination is called', () => {
beforeEach(() => { beforeEach(() => {
service.getCurrentPagination({}); service.getCurrentPagination({ currentPage: 1, pageSize: 10 } as any);
}); });
it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => { it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => {
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page'); expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page');
@@ -90,41 +97,38 @@ describe('SearchConfigurationService', () => {
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('pageSize'); expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('pageSize');
}); });
}); });
fdescribe('when getPaginatedSearchOptions or getSearchOptions is called', () => { fdescribe('when updateSearchOptions or updatePaginatedSearchOptions is called', () => {
beforeEach(() => { beforeEach(() => {
spyOn(service, 'getCurrentPagination'); spyOn(service, 'getPaginationPart');
spyOn(service, 'getCurrentSort'); spyOn(service, 'getSortPart');
spyOn(service, 'getCurrentScope'); spyOn(service, 'getScopePart');
spyOn(service, 'getCurrentQuery'); spyOn(service, 'getQueryPart');
spyOn(service, 'getCurrentFilters'); spyOn(service, 'getFiltersPart');
}); });
describe('when getPaginatedSearchOptions is called', () => { describe('when getPaginatedSearchOptions is called', () => {
beforeEach(() => { beforeEach(() => {
service.getPaginatedSearchOptions(defaults); service.subscribeToSearchOptions(defaults);
});
it('should call all getters it needs', fakeAsync(() => {
defaults.subscribe(() => {
tick();
expect(service.getCurrentPagination).toHaveBeenCalled();
expect(service.getCurrentSort).toHaveBeenCalled();
expect(service.getCurrentScope).toHaveBeenCalled();
expect(service.getCurrentQuery).toHaveBeenCalled();
expect(service.getCurrentFilters).toHaveBeenCalled();
}
)
}));
});
describe('when getSearchOptions is called', () => {
beforeEach(() => {
service.getSearchOptions();
}); });
it('should call all getters it needs', () => { it('should call all getters it needs', () => {
expect(service.getCurrentPagination).not.toHaveBeenCalled();
expect(service.getCurrentSort).not.toHaveBeenCalled(); // expect(service.getCurrentPagination).toHaveBeenCalled();
expect(service.getCurrentScope).toHaveBeenCalled(); // expect(service.getCurrentSort).toHaveBeenCalled();
expect(service.getCurrentQuery).toHaveBeenCalled(); expect(service.getScopePart).toHaveBeenCalled();
expect(service.getCurrentFilters).toHaveBeenCalled(); expect(service.getQueryPart).toHaveBeenCalled();
expect(service.getFiltersPart).toHaveBeenCalled();
}); });
}); });
// describe('when searchOptions is called', () => {
// beforeEach(() => {
// service.searchOptions;
// });
// it('should call all getters it needs', () => {
// expect(service.getCurrentPagination).not.toHaveBeenCalled();
// expect(service.getCurrentSort).not.toHaveBeenCalled();
// expect(service.getCurrentScope).toHaveBeenCalled();
// expect(service.getCurrentQuery).toHaveBeenCalled();
// expect(service.getCurrentFilters).toHaveBeenCalled();
// });
// });
}); });
}); });

View File

@@ -5,53 +5,73 @@ import { distinctUntilChanged, map } from 'rxjs/operators';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { ActivatedRoute, Params } from '@angular/router'; import { ActivatedRoute, Params } from '@angular/router';
import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { PaginatedSearchOptions } from '../paginated-search-options.model';
import { Injectable } from '@angular/core'; import { Injectable, OnDestroy } from '@angular/core';
import { RouteService } from '../../shared/services/route.service'; import { RouteService } from '../../shared/services/route.service';
import { hasNoValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { hasNoValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
import { RemoteData } from '../../core/data/remote-data'; import { RemoteData } from '../../core/data/remote-data';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/Subscription';
/** /**
* Service that performs all actions that have to do with the current search configuration * Service that performs all actions that have to do with the current search configuration
*/ */
@Injectable() @Injectable()
export class SearchConfigurationService { export class SearchConfigurationService implements OnDestroy {
private defaultPagination = { id: 'search-page-configuration', pageSize: 10 }; private defaultPagination = Object.assign(new PaginationComponentOptions(), { id: 'search-page-configuration', pageSize: 10, currentPage: 1 });
private defaultSort = new SortOptions('score', SortDirection.DESC); private defaultSort = new SortOptions('score', SortDirection.DESC);
private defaultScope = ''; private defaultScope = '';
private defaultQuery = '';
private _defaults; private _defaults;
public searchOptions: BehaviorSubject<SearchOptions>;
public paginatedSearchOptions: BehaviorSubject<PaginatedSearchOptions>;
private subs: Subscription[] = new Array();
constructor(private routeService: RouteService, constructor(private routeService: RouteService,
private route: ActivatedRoute) { private route: ActivatedRoute) {
this.defaults.first().subscribe((defRD) => {
const defs = defRD.payload;
this.paginatedSearchOptions = new BehaviorSubject<SearchOptions>(defs);
this.searchOptions = new BehaviorSubject<PaginatedSearchOptions>(defs);
this.subs.push(this.subscribeToSearchOptions(defs));
this.subs.push(this.subscribeToPaginatedSearchOptions(defs));
}
)
} }
/** /**
* @returns {Observable<string>} Emits the current scope's identifier * @returns {Observable<string>} Emits the current scope's identifier
*/ */
getCurrentScope() { getCurrentScope(defaultScope: string) {
return this.routeService.getQueryParameterValue('scope'); return this.routeService.getQueryParameterValue('scope').map((scope) => {
return scope || defaultScope;
});
} }
/** /**
* @returns {Observable<string>} Emits the current query string * @returns {Observable<string>} Emits the current query string
*/ */
getCurrentQuery() { getCurrentQuery(defaultQuery: string) {
return this.routeService.getQueryParameterValue('query'); return this.routeService.getQueryParameterValue('query').map((query) => {
return query || defaultQuery;
});
} }
/** /**
* @returns {Observable<string>} Emits the current pagination settings * @returns {Observable<string>} Emits the current pagination settings
*/ */
getCurrentPagination(pagination: any = {}): Observable<PaginationComponentOptions> { getCurrentPagination(defaultPagination: PaginationComponentOptions): Observable<PaginationComponentOptions> {
const page$ = this.routeService.getQueryParameterValue('page'); const page$ = this.routeService.getQueryParameterValue('page');
const size$ = this.routeService.getQueryParameterValue('pageSize'); const size$ = this.routeService.getQueryParameterValue('pageSize');
return Observable.combineLatest(page$, size$, (page, size) => { return Observable.combineLatest(page$, size$, (page, size) => {
return Object.assign(new PaginationComponentOptions(), pagination, { return Object.assign(new PaginationComponentOptions(), defaultPagination, {
currentPage: page || 1, currentPage: page || defaultPagination.currentPage,
pageSize: size || pagination.pageSize pageSize: size || defaultPagination.pageSize
}); });
}); });
} }
@@ -70,7 +90,7 @@ export class SearchConfigurationService {
const direction = SortDirection[sortDirection] || defaultSort.direction; const direction = SortDirection[sortDirection] || defaultSort.direction;
return new SortOptions(field, direction) return new SortOptions(field, direction)
} }
); )
} }
/** /**
@@ -98,77 +118,106 @@ export class SearchConfigurationService {
}); });
} }
/** /**
* @returns {Observable<Params>} Emits the current active filters with their values as they are displayed in the frontend URL * @returns {Observable<Params>} Emits the current active filters with their values as they are displayed in the frontend URL
*/ */
getCurrentFrontendFilters(): Observable<Params> { getCurrentFrontendFilters(): Observable<Params> {
return this.routeService.getQueryParamsWithPrefix('f.'); return this.routeService.getQueryParamsWithPrefix('f.');
} }
/** subscribeToSearchOptions(defaults: SearchOptions): Subscription {
* @param defaults The default values for the search options, that will be used if nothing is explicitly set console.log('scope: ', this.getScopePart(defaults.scope));
* @returns {Observable<PaginatedSearchOptions>} Emits the current paginated search options console.log('query: ', this.getQueryPart(defaults.query));
*/ console.log('filters: ', this.getFiltersPart());
getPaginatedSearchOptions(defaults: Observable<RemoteData<any>> = this.defaults): Observable<PaginatedSearchOptions> { this.getScopePart(defaults.scope).subscribe((y) => console.log('scope: ' + JSON.stringify(y)));
return defaults.flatMap((defaultConfig) => { this.getQueryPart(defaults.query).subscribe((y) => console.log('query: ' + JSON.stringify(y)));
const defaultValues = defaultConfig.payload; this.getFiltersPart().subscribe((y) => console.log('filters: ' + JSON.stringify(y)));
return Observable.combineLatest( return Observable.merge(
this.getCurrentPagination(defaultValues.pagination), this.getScopePart(defaults.scope),
this.getCurrentSort(defaultValues.sort), this.getQueryPart(defaults.query),
this.getCurrentScope(), this.getFiltersPart()
this.getCurrentQuery(), ).subscribe((update) => {
this.getCurrentFilters()).pipe( const currentValue: SearchOptions = this.searchOptions.getValue();
distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), const updatedValue: SearchOptions = Object.assign(new SearchOptions(), currentValue, update);
map(([pagination, sort, scope, query, filters]) => { this.searchOptions.next(updatedValue);
return Object.assign(new PaginatedSearchOptions(),
defaults,
{
pagination: pagination,
sort: sort,
scope: scope || defaultValues.scope,
query: query,
filters: filters
})
})
)
}); });
} }
/** subscribeToPaginatedSearchOptions(defaults: PaginatedSearchOptions): Subscription {
* @param defaults The default values for the search options, that will be used if nothing is explicitly set return Observable.merge(
* @returns {Observable<PaginatedSearchOptions>} Emits the current search options this.getPaginationPart(defaults.pagination),
*/ this.getSortPart(defaults.sort),
getSearchOptions(defaults: Observable<RemoteData<any>> = this.defaults): Observable<SearchOptions> { this.getScopePart(defaults.scope),
return defaults.flatMap((defaultConfig) => { this.getQueryPart(defaults.query),
const defaultValues = defaultConfig.payload; this.getFiltersPart()
return Observable.combineLatest( ).subscribe((update) => {
this.getCurrentScope(), const currentValue: PaginatedSearchOptions = this.paginatedSearchOptions.getValue();
this.getCurrentQuery(), const updatedValue: PaginatedSearchOptions = Object.assign(new PaginatedSearchOptions(), currentValue, update);
this.getCurrentFilters(), this.paginatedSearchOptions.next(updatedValue);
(scope, query, filters) => {
return Object.assign(new SearchOptions(),
{
scope: scope || defaultValues.scope,
query: query,
filters: filters
})
}
)
}); });
} }
/** /**
* Default values for the Search Options * Default values for the Search Options
*/ */
get defaults() { get defaults(): Observable<RemoteData<PaginatedSearchOptions>> {
if (hasNoValue(this._defaults)) { if (hasNoValue(this._defaults)) {
const options = { const options = Object.assign(new PaginatedSearchOptions(), {
pagination: this.defaultPagination, pagination: this.defaultPagination,
sort: this.defaultSort, sort: this.defaultSort,
scope: this.defaultScope scope: this.defaultScope,
}; query: this.defaultQuery
});
this._defaults = Observable.of(new RemoteData(false, false, true, null, options)); this._defaults = Observable.of(new RemoteData(false, false, true, null, options));
} }
return this._defaults; return this._defaults;
} }
ngOnDestroy(): void {
this.subs.forEach((sub) => {
sub.unsubscribe();
});
}
getScopePart(defaultScope: string): Observable<any> {
return this.getCurrentScope(defaultScope).map((scope) => {
return { scope }
});
}
/**
* @returns {Observable<string>} Emits the current query string
*/
getQueryPart(defaultQuery: string): Observable<any> {
return this.getCurrentQuery(defaultQuery).map((query) => {
return { query }
});
}
/**
* @returns {Observable<string>} Emits the current pagination settings
*/
getPaginationPart(defaultPagination: PaginationComponentOptions): Observable<any> {
return this.getCurrentPagination(defaultPagination).map((pagination) => {
return { pagination }
});
}
/**
* @returns {Observable<string>} Emits the current sorting settings
*/
getSortPart(defaultSort: SortOptions): Observable<any> {
return this.getCurrentSort(defaultSort).map((sort) => {
return { sort }
});
}
/**
* @returns {Observable<Params>} Emits the current active filters with their values as they are sent to the backend
*/
getFiltersPart(): Observable<any> {
return this.getCurrentFilters().map((filters) => {
return { filters }
});
}
} }

View File

@@ -73,15 +73,14 @@ describe('SearchSettingsComponent', () => {
}, },
{ {
provide: SearchConfigurationService, provide: SearchConfigurationService,
useValue: jasmine.createSpyObj('SearchConfigurationService', { useValue: {
getPaginatedSearchOptions: hot('a', { paginatedSearchOptions: hot('a', {
a: paginatedSearchOptions a: paginatedSearchOptions
}), }),
getCurrentScope: hot('a', { getCurrentScope: hot('a', {
a: 'test-id' a: 'test-id'
}), }),
}
})
}, },
], ],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]

View File

@@ -38,7 +38,7 @@ export class SearchSettingsComponent implements OnInit {
* Initialize paginated search options * Initialize paginated search options
*/ */
ngOnInit(): void { ngOnInit(): void {
this.searchOptions$ = this.searchConfigurationService.getPaginatedSearchOptions(); this.searchOptions$ = this.searchConfigurationService.paginatedSearchOptions;
} }
/** /**
@@ -50,6 +50,7 @@ export class SearchSettingsComponent implements OnInit {
const navigationExtras: NavigationExtras = { const navigationExtras: NavigationExtras = {
queryParams: { queryParams: {
pageSize: value, pageSize: value,
page: 1
}, },
queryParamsHandling: 'merge' queryParamsHandling: 'merge'
}; };
@@ -65,7 +66,8 @@ export class SearchSettingsComponent implements OnInit {
const navigationExtras: NavigationExtras = { const navigationExtras: NavigationExtras = {
queryParams: { queryParams: {
sortDirection: values[1], sortDirection: values[1],
sortField: values[0] sortField: values[0],
page: 1
}, },
queryParamsHandling: 'merge' queryParamsHandling: 'merge'
}; };

View File

@@ -17,6 +17,7 @@ export class RouteService {
} }
getQueryParameterValue(paramName: string): Observable<string> { getQueryParameterValue(paramName: string): Observable<string> {
this.route.queryParamMap.map((map) => map.get(paramName)).distinctUntilChanged().subscribe((t) => console.log('paramName: ' + paramName + 'values: ' + t));
return this.route.queryParamMap.map((map) => map.get(paramName)).distinctUntilChanged(); return this.route.queryParamMap.map((map) => map.get(paramName)).distinctUntilChanged();
} }
@@ -38,6 +39,7 @@ export class RouteService {
params[key] = [...map.getAll(key)]; params[key] = [...map.getAll(key)];
}); });
return params; return params;
}).distinctUntilChanged(); })
.distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b));
} }
} }

View File

@@ -21,7 +21,10 @@ export class ActivatedRouteStub {
} }
// Test parameters // Test parameters
get testParams() { return this._testParams; } get testParams() {
return this._testParams;
}
set testParams(params: {}) { set testParams(params: {}) {
this._testParams = params; this._testParams = params;
this.subject.next(params); this.subject.next(params);
@@ -29,6 +32,9 @@ export class ActivatedRouteStub {
// ActivatedRoute.snapshot.params // ActivatedRoute.snapshot.params
get snapshot() { get snapshot() {
return { params: this.testParams }; return {
params: this.testParams,
queryParamMap: convertToParamMap(this.testParams)
}
} }
} }