diff --git a/package.json b/package.json index e3e1d294d1..f305f319ab 100644 --- a/package.json +++ b/package.json @@ -104,9 +104,9 @@ "methods": "1.1.2", "moment": "^2.22.1", "morgan": "1.9.0", - "ng2-nouislider": "^1.7.7", + "ng2-nouislider": "1.7.8", "ngx-pagination": "3.0.3", - "nouislider": "^10.0.0", + "nouislider": "^11.0.0", "pem": "1.12.3", "reflect-metadata": "0.1.12", "rxjs": "5.5.6", diff --git a/src/app/+search-page/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts index bac4a49d79..d1f7eeab5c 100644 --- a/src/app/+search-page/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter-wrapper/search-facet-filter-wrapper.component.ts @@ -1,8 +1,7 @@ -import { Component, InjectionToken, Injector, Input, OnInit } from '@angular/core'; +import { Component, Injector, Input, OnInit } from '@angular/core'; import { renderFilterType } from '../search-filter-type-decorator'; import { FilterType } from '../../../search-service/filter-type.model'; import { SearchFilterConfig } from '../../../search-service/search-filter-config.model'; -import { GlobalConfig } from '../../../../../config/global-config.interface'; import { FILTER_CONFIG, SELECTED_VALUES } from '../search-filter.service'; import { Observable } from 'rxjs/Observable'; diff --git a/src/app/+search-page/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts similarity index 96% rename from src/app/+search-page/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component.spec.ts rename to src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts index e1e34b47e6..0fddc58183 100644 --- a/src/app/+search-page/search-filters/search-filter/search-boolean-filter/search-boolean-filter.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filter/search-facet-filter/search-facet-filter.component.spec.ts @@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { SearchFilterService } from '../search-filter.service'; +import { FILTER_CONFIG, SearchFilterService, SELECTED_VALUES } from '../search-filter.service'; import { SearchFilterConfig } from '../../../search-service/search-filter-config.model'; import { FilterType } from '../../../search-service/filter-type.model'; import { FacetValue } from '../../../search-service/facet-value.model'; @@ -17,7 +17,7 @@ import { RouterStub } from '../../../../shared/testing/router-stub'; import { Router } from '@angular/router'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { PageInfo } from '../../../../core/shared/page-info.model'; -import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; +import { SearchFacetFilterComponent } from './search-facet-filter.component'; describe('SearchFacetFilterComponent', () => { let comp: SearchFacetFilterComponent; @@ -64,6 +64,8 @@ describe('SearchFacetFilterComponent', () => { providers: [ { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, { provide: Router, useValue: new RouterStub() }, + { provide: FILTER_CONFIG, useValue: new SearchFilterConfig()}, + { provide: SELECTED_VALUES, useValue: {} }, { provide: SearchFilterService, useValue: { isFilterActiveWithValue: (paramName: string, filterValue: string) => true, diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-filter.component.html index 857b03a38f..b0be42b215 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.html @@ -1,7 +1,7 @@
{{'search.filters.filter.' + filter.name + '.head'| translate}}
-
+
\ No newline at end of file diff --git a/src/app/+search-page/search-filters/search-filter/search-filter.component.scss b/src/app/+search-page/search-filters/search-filter/search-filter.component.scss index f694e9e167..6e49172a48 100644 --- a/src/app/+search-page/search-filters/search-filter/search-filter.component.scss +++ b/src/app/+search-page/search-filters/search-filter/search-filter.component.scss @@ -3,7 +3,7 @@ :host { border: 1px solid map-get($theme-colors, light); - .search-filter-wrapper { + .search-filter-wrapper.closed { overflow: hidden; } .filter-toggle { diff --git a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts deleted file mode 100644 index e1e34b47e6..0000000000 --- a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ /dev/null @@ -1,241 +0,0 @@ -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { TranslateModule } from '@ngx-translate/core'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { SearchFilterService } from '../search-filter.service'; -import { SearchFilterConfig } from '../../../search-service/search-filter-config.model'; -import { FilterType } from '../../../search-service/filter-type.model'; -import { FacetValue } from '../../../search-service/facet-value.model'; -import { FormsModule } from '@angular/forms'; -import { Observable } from 'rxjs/Observable'; -import { SearchService } from '../../../search-service/search.service'; -import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { PaginatedList } from '../../../../core/data/paginated-list'; -import { SearchOptions } from '../../../search-options.model'; -import { RouterStub } from '../../../../shared/testing/router-stub'; -import { Router } from '@angular/router'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; -import { PageInfo } from '../../../../core/shared/page-info.model'; -import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; - -describe('SearchFacetFilterComponent', () => { - let comp: SearchFacetFilterComponent; - let fixture: ComponentFixture; - const filterName1 = 'test name'; - const value1 = 'testvalue1'; - const value2 = 'test2'; - const value3 = 'another value3'; - const mockFilterConfig: SearchFilterConfig = Object.assign(new SearchFilterConfig(), { - name: filterName1, - type: FilterType.text, - hasFacets: false, - isOpenByDefault: false, - pageSize: 2 - }); - const values: FacetValue[] = [ - { - value: value1, - count: 52, - search: '' - }, { - value: value2, - count: 20, - search: '' - }, { - value: value3, - count: 5, - search: '' - } - ]; - - const searchLink = '/search'; - const selectedValues = [value1, value2]; - let filterService; - let searchService; - let router; - const page = Observable.of(0); - - const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values))); - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], - declarations: [SearchFacetFilterComponent], - providers: [ - { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, - { provide: Router, useValue: new RouterStub() }, - { - provide: SearchFilterService, useValue: { - isFilterActiveWithValue: (paramName: string, filterValue: string) => true, - getPage: (paramName: string) => page, - /* tslint:disable:no-empty */ - incrementPage: (filterName: string) => { - }, - resetPage: (filterName: string) => { - }, - getSearchOptions: () => Observable.of({}), - /* tslint:enable:no-empty */ - } - } - ], - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(SearchFacetFilterComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(SearchFacetFilterComponent); - comp = fixture.componentInstance; // SearchPageComponent test instance - comp.filterConfig = mockFilterConfig; - comp.filterValues = [mockValues]; - comp.filterValues$ = new BehaviorSubject(comp.filterValues); - comp.selectedValues = selectedValues; - filterService = (comp as any).filterService; - searchService = (comp as any).searchService; - spyOn(searchService, 'getFacetValuesFor').and.returnValue(mockValues); - router = (comp as any).router; - fixture.detectChanges(); - }); - - describe('when the isChecked method is called with a value', () => { - beforeEach(() => { - spyOn(filterService, 'isFilterActiveWithValue'); - comp.isChecked(values[1]); - }); - - it('should call isFilterActiveWithValue on the filterService with the correct filter parameter name and the passed value', () => { - expect(filterService.isFilterActiveWithValue).toHaveBeenCalledWith(mockFilterConfig.paramName, values[1].value) - }); - }); - - describe('when the getSearchLink method is triggered', () => { - let link: string; - beforeEach(() => { - link = comp.getSearchLink(); - }); - - it('should return the value of the searchLink variable in the filter service', () => { - expect(link).toEqual(searchLink); - }); - }); - - 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); - expect(result[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); - expect(result[mockFilterConfig.paramName]).toEqual([value2]); - }); - }); - - describe('when the showMore method is called', () => { - beforeEach(() => { - spyOn(filterService, 'incrementPage'); - comp.showMore(); - }); - - it('should call incrementPage on the filterService with the correct filter parameter name', () => { - expect(filterService.incrementPage).toHaveBeenCalledWith(mockFilterConfig.name) - }); - }); - - describe('when the showFirstPageOnly method is called', () => { - beforeEach(() => { - spyOn(filterService, 'resetPage'); - comp.showFirstPageOnly(); - }); - - it('should call resetPage on the filterService with the correct filter parameter name', () => { - expect(filterService.resetPage).toHaveBeenCalledWith(mockFilterConfig.name); - }); - }); - - describe('when the getCurrentPage method is called', () => { - beforeEach(() => { - spyOn(filterService, 'getPage'); - comp.getCurrentPage(); - }); - - it('should call getPage on the filterService with the correct filter parameter name', () => { - expect(filterService.getPage).toHaveBeenCalledWith(mockFilterConfig.name) - }); - }); - - describe('when the getCurrentUrl method is called', () => { - const url = 'test.url/test' - beforeEach(() => { - router.navigateByUrl(url); - }); - - it('should call getPage on the filterService with the correct filter parameter name', () => { - expect(router.url).toEqual(url); - }); - }); - - describe('when the onSubmit method is called with data', () => { - const searchUrl = '/search/path'; - const testValue = 'test'; - const data = { [mockFilterConfig.paramName]: testValue }; - beforeEach(() => { - spyOn(comp, 'getSearchLink').and.returnValue(searchUrl); - comp.onSubmit(data); - }); - - it('should call navigate on the router with the right searchlink and parameters', () => { - expect(router.navigate).toHaveBeenCalledWith([searchUrl], { - queryParams: { [mockFilterConfig.paramName]: [...selectedValues, testValue] }, - queryParamsHandling: 'merge' - }); - }); - }); - - describe('when updateFilterValueList is called', () => { - const cPage = 10; - const searchOptions = new SearchOptions(); - beforeEach(() => { - // spyOn(searchService, 'getFacetValuesFor'); Already spied upon - comp.currentPage = Observable.of(cPage); - comp.updateFilterValueList(searchOptions); - }); - - it('should call getFacetValuesFor on the searchService with the correct parameters', () => { - expect(searchService.getFacetValuesFor).toHaveBeenCalledWith(mockFilterConfig, cPage, searchOptions); - }); - }); - - describe('when updateFilterValueList is called and pageChange is set to true', () => { - const searchOptions = new SearchOptions(); - beforeEach(() => { - comp.pageChange = true; - spyOn(comp, 'showFirstPageOnly'); - comp.updateFilterValueList(searchOptions); - }); - - it('should not call showFirstPageOnly on the component', () => { - expect(comp.showFirstPageOnly).not.toHaveBeenCalled(); - }); - - it('should set pageChange to false', () => { - expect(comp.pageChange).toBeFalsy(); - }); - }); - - describe('when updateFilterValueList is called and pageChange is set to false', () => { - const searchOptions = new SearchOptions(); - beforeEach(() => { - comp.pageChange = false; - spyOn(comp, 'showFirstPageOnly'); - comp.updateFilterValueList(searchOptions); - }); - - it('should call showFirstPageOnly on the component', () => { - expect(comp.showFirstPageOnly).toHaveBeenCalled(); - }); - }); -}); diff --git a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts index 23ac40fde1..5e8966cdb4 100644 --- a/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts @@ -20,6 +20,4 @@ import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet- @renderFacetFor(FilterType.hierarchy) export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent implements OnInit { currentPage: Observable; - - } diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.html b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.html index 06d084adf5..5760f20c5b 100644 --- a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.html +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.html @@ -1,3 +1,4 @@ +
+ [(ngModel)]="range" (mouseup)="onSubmit(form.value)" ngDefaultControl> diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.scss b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.scss index ad36c7b8d3..2bb89c0b14 100644 --- a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.scss +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.scss @@ -1,14 +1,38 @@ @import '../../../../../styles/variables.scss'; @import '../../../../../styles/mixins.scss'; + .filters { + margin-top: $spacer/2; + margin-bottom: $spacer/2; + a { + color: $link-color; + &:hover { + text-decoration: underline; + color: $link-hover-color; - a { - color: $link-color; - &:hover { - text-decoration: underline; - color: $link-hover-color; + } + } + .toggle-more-filters a { + color: $link-color; + text-decoration: underline; + cursor: pointer; + } + } +$slider-handle-width: 18px; +::ng-deep +{ + html:not([dir=rtl]) .noUi-horizontal .noUi-handle { + right: -$slider-handle-width/2; + } + .noUi-horizontal .noUi-handle { + width: $slider-handle-width; + &:before { + left: ($slider-handle-width - 2)/2 - 2; + } + &:after { + left: ($slider-handle-width - 2)/2 + 2; } } } \ No newline at end of file diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts new file mode 100644 index 0000000000..e4aa887caa --- /dev/null +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.spec.ts @@ -0,0 +1,139 @@ +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { FILTER_CONFIG, SearchFilterService, SELECTED_VALUES } from '../search-filter.service'; +import { SearchFilterConfig } from '../../../search-service/search-filter-config.model'; +import { FilterType } from '../../../search-service/filter-type.model'; +import { FacetValue } from '../../../search-service/facet-value.model'; +import { FormsModule } from '@angular/forms'; +import { Observable } from 'rxjs/Observable'; +import { SearchService } from '../../../search-service/search.service'; +import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { PaginatedList } from '../../../../core/data/paginated-list'; +import { RouterStub } from '../../../../shared/testing/router-stub'; +import { ActivatedRoute, Router } from '@angular/router'; +import { BehaviorSubject } from 'rxjs/BehaviorSubject'; +import { PageInfo } from '../../../../core/shared/page-info.model'; +import { SearchRangeFilterComponent } from './search-range-filter.component'; +import { MockActivatedRoute } from '../../../../shared/mocks/mock-active-router'; + +describe('SearchFacetFilterComponent', () => { + let comp: SearchRangeFilterComponent; + let fixture: ComponentFixture; + const minSuffix = '.min'; + const maxSuffix = '.max'; + const dateFormats = ['YYYY', 'YYYY-MM', 'YYYY-MM-DD']; + const filterName1 = 'test name'; + const value1 = '2000 - 2012'; + const value2 = '1992 - 2000'; + const value3 = '1990 - 1992'; + const mockFilterConfig: SearchFilterConfig = Object.assign(new SearchFilterConfig(), { + name: filterName1, + type: FilterType.range, + hasFacets: false, + isOpenByDefault: false, + pageSize: 2, + minValue: 200, + maxValue: 3000, + }); + const values: FacetValue[] = [ + { + value: value1, + count: 52, + search: '' + }, { + value: value2, + count: 20, + search: '' + }, { + value: value3, + count: 5, + search: '' + } + ]; + + const searchLink = '/search'; + const selectedValues = [value1]; + let filterService; + let searchService; + let router; + const page = Observable.of(0); + const activatedRouteStub = new MockActivatedRoute(); + + const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values))); + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], + declarations: [SearchRangeFilterComponent], + providers: [ + { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, + { provide: Router, useValue: new RouterStub() }, + { provide: FILTER_CONFIG, useValue: mockFilterConfig}, + { provide: SELECTED_VALUES, useValue: selectedValues }, + { provide: ActivatedRoute, useValue: activatedRouteStub }, + { + provide: SearchFilterService, useValue: { + isFilterActiveWithValue: (paramName: string, filterValue: string) => true, + getPage: (paramName: string) => page, + /* tslint:disable:no-empty */ + incrementPage: (filterName: string) => { + }, + resetPage: (filterName: string) => { + }, + getSearchOptions: () => Observable.of({}), + /* tslint:enable:no-empty */ + } + } + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(SearchRangeFilterComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchRangeFilterComponent); + comp = fixture.componentInstance; // SearchPageComponent test instance + comp.filterValues = [mockValues]; + comp.filterValues$ = new BehaviorSubject(comp.filterValues); + filterService = (comp as any).filterService; + searchService = (comp as any).searchService; + spyOn(searchService, 'getFacetValuesFor').and.returnValue(mockValues); + router = (comp as any).router; + fixture.detectChanges(); + }); + + 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); + expect(result[mockFilterConfig.paramName + minSuffix]).toEqual(['1990']); + expect(result[mockFilterConfig.paramName + maxSuffix]).toEqual(['1992']); + }); + }); + + 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); + expect(result[mockFilterConfig.paramName + minSuffix]).toBeNull(); + expect(result[mockFilterConfig.paramName + maxSuffix]).toBeNull(); + }); + }); + + describe('when the onSubmit method is called with data', () => { + const searchUrl = '/search/path'; + const data = { [mockFilterConfig.paramName + minSuffix]: '1900', [mockFilterConfig.paramName + maxSuffix]: '1950' }; + beforeEach(() => { + spyOn(comp, 'getSearchLink').and.returnValue(searchUrl); + comp.onSubmit(data); + }); + + it('should call navigate on the router with the right searchlink and parameters', () => { + expect(router.navigate).toHaveBeenCalledWith([searchUrl], { + queryParams: { [mockFilterConfig.paramName + minSuffix]: ['1900'], [mockFilterConfig.paramName + maxSuffix]: ['1950']}, + queryParamsHandling: 'merge' + }); + }); + }); +}); diff --git a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts index 1f0e16600f..790ec93453 100644 --- a/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts +++ b/src/app/+search-page/search-filters/search-filter/search-range-filter/search-range-filter.component.ts @@ -14,6 +14,10 @@ import * as moment from 'moment'; * The route parameter 'id' is used to request the item it represents. * All fields of the item that should be displayed, are defined in its template. */ +const minSuffix = '.min'; +const maxSuffix = '.max'; +const dateFormats = ['YYYY', 'YYYY-MM', 'YYYY-MM-DD']; +const rangeDelimiter = '-'; @Component({ selector: 'ds-search-range-filter', @@ -23,11 +27,9 @@ import * as moment from 'moment'; @renderFacetFor(FilterType.range) export class SearchRangeFilterComponent extends SearchFacetFilterComponent implements OnInit { - rangeDelimiter = '-'; min = 1950; max = 2018; range; - dateFormats = ['YYYY', 'YYYY-MM', 'YYYY-MM-DD'] constructor(protected searchService: SearchService, protected filterService: SearchFilterService, @@ -40,29 +42,29 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple ngOnInit(): void { super.ngOnInit(); - this.min = moment(this.filterConfig.minValue, this.dateFormats).year() || this.min; - this.max = moment(this.filterConfig.maxValue, this.dateFormats).year() || this.max; - const iniMin = this.route.snapshot.queryParams[this.filterConfig.paramName + '.min'] || this.min; - const iniMax = this.route.snapshot.queryParams[this.filterConfig.paramName + '.max'] || this.max; + this.min = moment(this.filterConfig.minValue, dateFormats).year() || this.min; + this.max = moment(this.filterConfig.maxValue, dateFormats).year() || this.max; + const iniMin = this.route.snapshot.queryParams[this.filterConfig.paramName + minSuffix] || this.min; + const iniMax = this.route.snapshot.queryParams[this.filterConfig.paramName + maxSuffix] || this.max; this.range = [iniMin, iniMax]; } getAddParams(value: string) { - const parts = value.split(this.rangeDelimiter); + const parts = value.split(rangeDelimiter); const min = parts.length > 1 ? parts[0].trim() : value; const max = parts.length > 1 ? parts[1].trim() : value; return { - [this.filterConfig.paramName + '.min']: [min], - [this.filterConfig.paramName + '.max']: [max], + [this.filterConfig.paramName + minSuffix]: [min], + [this.filterConfig.paramName + maxSuffix]: [max], page: 1 }; } getRemoveParams(value: string) { return { - [this.filterConfig.paramName + '.min']: null, - [this.filterConfig.paramName + '.max']: null, + [this.filterConfig.paramName + minSuffix]: null, + [this.filterConfig.paramName + maxSuffix]: null, page: 1 }; } @@ -72,8 +74,8 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple this.router.navigate([this.getSearchLink()], { queryParams: { - [this.filterConfig.paramName + '.min']: [data[this.filterConfig.paramName + '.min']], - [this.filterConfig.paramName + '.max']: [data[this.filterConfig.paramName + '.max']] + [this.filterConfig.paramName + minSuffix]: [data[this.filterConfig.paramName + minSuffix]], + [this.filterConfig.paramName + maxSuffix]: [data[this.filterConfig.paramName + maxSuffix]] }, queryParamsHandling: 'merge' }); diff --git a/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.spec.ts b/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.spec.ts deleted file mode 100644 index c44519743e..0000000000 --- a/src/app/+search-page/search-filters/search-filter/search-text-filter/search-text-filter.component.spec.ts +++ /dev/null @@ -1,242 +0,0 @@ -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { TranslateModule } from '@ngx-translate/core'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { SearchFilterService } from '../search-filter.service'; -import { SearchFilterConfig } from '../../../search-service/search-filter-config.model'; -import { FilterType } from '../../../search-service/filter-type.model'; -import { FacetValue } from '../../../search-service/facet-value.model'; -import { FormsModule } from '@angular/forms'; -import { Observable } from 'rxjs/Observable'; -import { SearchService } from '../../../search-service/search.service'; -import { SearchServiceStub } from '../../../../shared/testing/search-service-stub'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { PaginatedList } from '../../../../core/data/paginated-list'; -import { SearchOptions } from '../../../search-options.model'; -import { RouterStub } from '../../../../shared/testing/router-stub'; -import { Router } from '@angular/router'; -import { BehaviorSubject } from 'rxjs/BehaviorSubject'; -import { PageInfo } from '../../../../core/shared/page-info.model'; -import { SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; - -describe('SearchFacetFilterComponent', () => { - let comp: SearchFacetFilterComponent; - let fixture: ComponentFixture; - const filterName1 = 'test name'; - const value1 = 'testvalue1'; - const value2 = 'test2'; - const value3 = 'another value3'; - const mockFilterConfig: SearchFilterConfig = Object.assign(new SearchFilterConfig(), { - name: filterName1, - type: FilterType.text, - hasFacets: false, - isOpenByDefault: false, - pageSize: 2 - }); - const values: FacetValue[] = [ - { - value: value1, - count: 52, - search: '' - }, { - value: value2, - count: 20, - search: '' - }, { - value: value3, - count: 5, - search: '' - } - ]; - - const searchLink = '/search'; - const selectedValues = [value1, value2]; - let filterService; - let searchService; - let router; - const page = Observable.of(0); - - const mockValues = Observable.of(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), values))); - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], - declarations: [SearchFacetFilterComponent], - providers: [ - { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, - { provide: Router, useValue: new RouterStub() }, - { - provide: SearchFilterService, useValue: { - isFilterActiveWithValue: (paramName: string, filterValue: string) => true, - getPage: (paramName: string) => page, - /* tslint:disable:no-empty */ - incrementPage: (filterName: string) => { - }, - resetPage: (filterName: string) => { - }, - getSearchOptions: () => Observable.of({}), - /* tslint:enable:no-empty */ - } - } - ], - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(SearchFacetFilterComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(SearchFacetFilterComponent); - comp = fixture.componentInstance; // SearchPageComponent test instance - comp.filterConfig = mockFilterConfig; - comp.filterValues = [mockValues]; - comp.filterValues$ = new BehaviorSubject(comp.filterValues); - comp.selectedValues = selectedValues; - filterService = (comp as any).filterService; - searchService = (comp as any).searchService; - spyOn(searchService, 'getFacetValuesFor').and.returnValue(mockValues); - router = (comp as any).router; - fixture.detectChanges(); - }); - - describe('when the isChecked method is called with a value', () => { - beforeEach(() => { - spyOn(filterService, 'isFilterActiveWithValue'); - comp.isChecked(values[1]); - }); - - it('should call isFilterActiveWithValue on the filterService with the correct filter parameter name and the passed value', () => { - expect(filterService.isFilterActiveWithValue).toHaveBeenCalledWith(mockFilterConfig.paramName, values[1].value) - }); - }); - - describe('when the getSearchLink method is triggered', () => { - let link: string; - beforeEach(() => { - link = comp.getSearchLink(); - }); - - it('should return the value of the searchLink variable in the filter service', () => { - expect(link).toEqual(searchLink); - }); - }); - - 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); - expect(result[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); - expect(result[mockFilterConfig.paramName]).toEqual([value2]); - }); - }); - - describe('when the showMore method is called', () => { - beforeEach(() => { - spyOn(filterService, 'incrementPage'); - comp.showMore(); - }); - - it('should call incrementPage on the filterService with the correct filter parameter name', () => { - expect(filterService.incrementPage).toHaveBeenCalledWith(mockFilterConfig.name) - }); - }); - - describe('when the showFirstPageOnly method is called', () => { - beforeEach(() => { - spyOn(filterService, 'resetPage'); - comp.showFirstPageOnly(); - }); - - it('should call resetPage on the filterService with the correct filter parameter name', () => { - expect(filterService.resetPage).toHaveBeenCalledWith(mockFilterConfig.name); - }); - }); - - describe('when the getCurrentPage method is called', () => { - beforeEach(() => { - spyOn(filterService, 'getPage'); - comp.getCurrentPage(); - }); - - it('should call getPage on the filterService with the correct filter parameter name', () => { - expect(filterService.getPage).toHaveBeenCalledWith(mockFilterConfig.name) - }); - }); - - describe('when the getCurrentUrl method is called', () => { - const url = 'test.url/test' - beforeEach(() => { - router.navigateByUrl(url); - }); - - it('should call getPage on the filterService with the correct filter parameter name', () => { - expect(router.url).toEqual(url); - }); - }); - - describe('when the onSubmit method is called with data', () => { - const searchUrl = '/search/path'; - const testValue = 'test'; - const data = { [mockFilterConfig.paramName]: testValue }; - beforeEach(() => { - spyOn(comp, 'getSearchLink').and.returnValue(searchUrl); - comp.onSubmit(data); - }); - - it('should call navigate on the router with the right searchlink and parameters', () => { - expect(router.navigate).toHaveBeenCalledWith([searchUrl], { - queryParams: { [mockFilterConfig.paramName]: [...selectedValues, testValue] }, - queryParamsHandling: 'merge' - }); - }); - }); - - describe('when updateFilterValueList is called', () => { - const cPage = 10; - const searchOptions = new SearchOptions(); - beforeEach(() => { - // spyOn(searchService, 'getFacetValuesFor'); Already spied upon - comp.currentPage = Observable.of(cPage); - comp.updateFilterValueList(searchOptions); - }); - - it('should call getFacetValuesFor on the searchService with the correct parameters', () => { - expect(searchService.getFacetValuesFor).toHaveBeenCalledWith(mockFilterConfig, cPage, searchOptions); - }); - }); - - describe('when updateFilterValueList is called and pageChange is set to true', () => { - const searchOptions = new SearchOptions(); - beforeEach(() => { - comp.pageChange = true; - spyOn(comp, 'showFirstPageOnly'); - comp.updateFilterValueList(searchOptions); - }); - - it('should not call showFirstPageOnly on the component', () => { - expect(comp.showFirstPageOnly).not.toHaveBeenCalled(); - }); - - it('should set pageChange to false', () => { - expect(comp.pageChange).toBeFalsy(); - }); - }); - - describe('when updateFilterValueList is called and pageChange is set to false', () => { - const searchOptions = new SearchOptions(); - beforeEach(() => { - comp.pageChange = false; - spyOn(comp, 'showFirstPageOnly'); - comp.updateFilterValueList(searchOptions); - }); - - it('should call showFirstPageOnly on the component', () => { - expect(comp.showFirstPageOnly).toHaveBeenCalled(); - }); - }); -}); diff --git a/src/app/+search-page/search-filters/search-filters.component.spec.ts b/src/app/+search-page/search-filters/search-filters.component.spec.ts index 64c2ea5332..6557c5e55f 100644 --- a/src/app/+search-page/search-filters/search-filters.component.spec.ts +++ b/src/app/+search-page/search-filters/search-filters.component.spec.ts @@ -24,7 +24,7 @@ describe('SearchFiltersComponent', () => { /* tslint:enable:no-empty */ }; const searchFilterServiceStub = jasmine.createSpyObj('SearchFilterService', { - getCurrentFilters: Observable.of({}) + getCurrentFrontendFilters: Observable.of({}) }); beforeEach(async(() => { diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index 4b28689910..94083d9936 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -72,6 +72,7 @@ const effects = [ ItemSearchResultGridElementComponent, CollectionSearchResultGridElementComponent, CommunitySearchResultGridElementComponent, + SearchFacetFilterComponent, SearchRangeFilterComponent, SearchTextFilterComponent, SearchHierarchyFilterComponent, diff --git a/src/app/+search-page/search-service/search-filter-config.model.ts b/src/app/+search-page/search-service/search-filter-config.model.ts index 000e06e1a8..ced1f7a8eb 100644 --- a/src/app/+search-page/search-service/search-filter-config.model.ts +++ b/src/app/+search-page/search-service/search-filter-config.model.ts @@ -17,7 +17,7 @@ @autoserialize isOpenByDefault: boolean; - + @autoserialize maxValue: string; diff --git a/src/app/core/data/search-response-parsing.service.ts b/src/app/core/data/search-response-parsing.service.ts index efecccf54a..06e1d741b0 100644 --- a/src/app/core/data/search-response-parsing.service.ts +++ b/src/app/core/data/search-response-parsing.service.ts @@ -5,8 +5,7 @@ import { ResponseParsingService } from './parsing.service'; import { RestRequest } from './request.models'; import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; -import { PageInfo } from '../shared/page-info.model'; -import { hasValue, isNotEmpty } from '../../shared/empty.util'; +import { hasValue } from '../../shared/empty.util'; import { SearchQueryResponse } from '../../+search-page/search-service/search-query-response.model'; import { Metadatum } from '../shared/metadatum.model'; @@ -17,7 +16,6 @@ export class SearchResponseParsingService implements ResponseParsingService { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { const payload = data.payload; - console.log(payload); const hitHighlights = payload._embedded.objects .map((object) => object.hitHighlights) .map((hhObject) => { diff --git a/src/app/shared/mocks/mock-active-router.ts b/src/app/shared/mocks/mock-active-router.ts index 391b9c3426..183d6c13d0 100644 --- a/src/app/shared/mocks/mock-active-router.ts +++ b/src/app/shared/mocks/mock-active-router.ts @@ -29,6 +29,6 @@ export class MockActivatedRoute { // ActivatedRoute.snapshot.params get snapshot() { - return { params: this.testParams }; + return { params: this.testParams, queryParams: this.testParams }; } } diff --git a/yarn.lock b/yarn.lock index c67f761b40..fd03a7c8ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5591,9 +5591,9 @@ netmask@~1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35" -ng2-nouislider@^1.7.7: - version "1.7.7" - resolved "https://registry.yarnpkg.com/ng2-nouislider/-/ng2-nouislider-1.7.7.tgz#b841f4b313c8c9c8a763c80f3a59d5aa4c3a70c8" +ng2-nouislider@1.7.8: + version "1.7.8" + resolved "https://registry.yarnpkg.com/ng2-nouislider/-/ng2-nouislider-1.7.8.tgz#5fd6de120f9ca5b5d9c4b377f884944b74c06855" ngrx-store-freeze@^0.2.1: version "0.2.1" @@ -5814,9 +5814,9 @@ normalize-url@^1.4.0: query-string "^4.1.0" sort-keys "^1.0.0" -nouislider@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/nouislider/-/nouislider-10.1.0.tgz#7bdd0411fd62d4584bfe88cb92bb8d06e64c6b47" +nouislider@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/nouislider/-/nouislider-11.1.0.tgz#1768eb5b854917325d41b96f2dc4eb3757d73381" npm-run-all@4.1.2: version "4.1.2"