From 8931337d2d12539ee396c43bb6b699c20e9ad124 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 4 Jul 2018 15:56:29 +0200 Subject: [PATCH 1/4] 54053: intermediate commit --- .../search-labels.component.html | 10 +++++++ .../search-labels/search-labels.component.ts | 29 +++++++++++++++++++ .../+search-page/search-page.component.html | 1 + src/app/+search-page/search-page.module.ts | 4 ++- src/app/shared/shared.module.ts | 4 ++- src/app/shared/utils/capitalize.pipe.ts | 18 ++++++++++++ 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/app/+search-page/search-labels/search-labels.component.html create mode 100644 src/app/+search-page/search-labels/search-labels.component.ts create mode 100644 src/app/shared/utils/capitalize.pipe.ts diff --git a/src/app/+search-page/search-labels/search-labels.component.html b/src/app/+search-page/search-labels/search-labels.component.html new file mode 100644 index 0000000000..2a2f63aa09 --- /dev/null +++ b/src/app/+search-page/search-labels/search-labels.component.html @@ -0,0 +1,10 @@ +
+ +
diff --git a/src/app/+search-page/search-labels/search-labels.component.ts b/src/app/+search-page/search-labels/search-labels.component.ts new file mode 100644 index 0000000000..2692322bee --- /dev/null +++ b/src/app/+search-page/search-labels/search-labels.component.ts @@ -0,0 +1,29 @@ +import { Component } from '@angular/core'; +import { SearchService } from '../search-service/search.service'; +import { SearchFilterService } from '../search-filters/search-filter/search-filter.service'; +import { Observable } from 'rxjs/Observable'; +import { Params } from '@angular/router'; + +@Component({ + selector: 'ds-search-labels', + // styleUrls: ['./search-labels.component.scss'], + templateUrl: './search-labels.component.html', +}) + +export class SearchLabelsComponent { + protected appliedFilters: Observable; + + constructor(private searchService: SearchService, private filterService: SearchFilterService) { + this.appliedFilters = this.filterService.getCurrentFilters(); + console.log(this.appliedFilters.toArray()); + } + + getQueryParamsWithout(filterName: string, value: string): Observable { + return this.filterService.getCurrentFilters(); + // return this.filterService.getQueryParamsWithoutByName(filterName, value); + } + + getSearchLink() { + return this.searchService.getSearchLink(); + } +} diff --git a/src/app/+search-page/search-page.component.html b/src/app/+search-page/search-page.component.html index 1a1f379920..1ef45ede4b 100644 --- a/src/app/+search-page/search-page.component.html +++ b/src/app/+search-page/search-page.component.html @@ -10,6 +10,7 @@ [currentUrl]="getSearchLink()" [scopes]="(scopeListRD$ | async)?.payload?.page"> +
Date: Thu, 5 Jul 2018 12:56:39 +0200 Subject: [PATCH 2/4] 54053: Working active filter labels --- .../search-labels.component.html | 8 ++--- .../search-labels/search-labels.component.ts | 29 +++++++++++++------ .../search-service/filter-label.model.ts | 8 +++++ .../search-service/search.service.ts | 26 +++++++++++++++-- 4 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 src/app/+search-page/search-service/filter-label.model.ts diff --git a/src/app/+search-page/search-labels/search-labels.component.html b/src/app/+search-page/search-labels/search-labels.component.html index 2a2f63aa09..e20af58bcc 100644 --- a/src/app/+search-page/search-labels/search-labels.component.html +++ b/src/app/+search-page/search-labels/search-labels.component.html @@ -1,9 +1,9 @@
diff --git a/src/app/+search-page/search-labels/search-labels.component.ts b/src/app/+search-page/search-labels/search-labels.component.ts index 2692322bee..9111ecc2b6 100644 --- a/src/app/+search-page/search-labels/search-labels.component.ts +++ b/src/app/+search-page/search-labels/search-labels.component.ts @@ -1,26 +1,37 @@ import { Component } from '@angular/core'; import { SearchService } from '../search-service/search.service'; -import { SearchFilterService } from '../search-filters/search-filter/search-filter.service'; import { Observable } from 'rxjs/Observable'; import { Params } from '@angular/router'; +import { FilterLabel } from '../search-service/filter-label.model'; +import { map } from 'rxjs/operators'; @Component({ selector: 'ds-search-labels', - // styleUrls: ['./search-labels.component.scss'], templateUrl: './search-labels.component.html', }) export class SearchLabelsComponent { - protected appliedFilters: Observable; + protected appliedFilters: Observable; - constructor(private searchService: SearchService, private filterService: SearchFilterService) { - this.appliedFilters = this.filterService.getCurrentFilters(); - console.log(this.appliedFilters.toArray()); + constructor(private searchService: SearchService) { + this.appliedFilters = this.searchService.getFilterLabels(); } - getQueryParamsWithout(filterName: string, value: string): Observable { - return this.filterService.getCurrentFilters(); - // return this.filterService.getQueryParamsWithoutByName(filterName, value); + getRemoveParams(filterLabel: FilterLabel): Observable { + return this.appliedFilters.pipe( + map((filters) => { + const values = []; + filters.forEach((filter) => { + if (filter.field === filterLabel.field && filter.value !== filterLabel.value) { + values.push(filter.value); + } + }); + return { + [filterLabel.field]: values, + page: 1 + }; + }) + ); } getSearchLink() { diff --git a/src/app/+search-page/search-service/filter-label.model.ts b/src/app/+search-page/search-service/filter-label.model.ts new file mode 100644 index 0000000000..dea351d1c2 --- /dev/null +++ b/src/app/+search-page/search-service/filter-label.model.ts @@ -0,0 +1,8 @@ +export class FilterLabel { + value: string; + field: string; + constructor(value: string, field: string) { + this.value = value; + this.field = field; + } +} diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 774d2287e2..e27b43597b 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -1,6 +1,6 @@ import { Injectable, OnDestroy } from '@angular/core'; import { - ActivatedRoute, NavigationExtras, PRIMARY_OUTLET, Router, + ActivatedRoute, NavigationExtras, Params, PRIMARY_OUTLET, Router, UrlSegmentGroup } from '@angular/router'; import { Observable } from 'rxjs/Observable'; @@ -40,7 +40,8 @@ import { ListableObject } from '../../shared/object-collection/shared/listable-o import { FacetValueResponseParsingService } from '../../core/data/facet-value-response-parsing.service'; import { FacetConfigResponseParsingService } from '../../core/data/facet-config-response-parsing.service'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; -import { observable } from 'rxjs/symbol/observable'; +import { FilterLabel } from './filter-label.model'; +import { combineLatest } from 'rxjs/observable/combineLatest'; @Injectable() export class SearchService implements OnDestroy { @@ -223,6 +224,27 @@ export class SearchService implements OnDestroy { return this.rdb.toRemoteDataObservable(requestEntryObs, responseCacheObs, payloadObs); } + getFilterLabels(): Observable { + return combineLatest(this.getConfig(), this.route.queryParams).pipe( + map(([rd, params]) => { + const filterLabels: FilterLabel[] = []; + rd.payload.forEach((config: SearchFilterConfig) => { + const param = params[config.paramName]; + if (param !== undefined) { + if (param instanceof Array && param.length > 1) { + param.forEach((p: string) => { + filterLabels.push(new FilterLabel(p, config.paramName)) + }); + } else { + filterLabels.push(new FilterLabel(param, config.paramName)); + } + } + }); + return filterLabels.filter((n) => n !== undefined && n.value.length > 0); + }) + ); + } + getViewMode(): Observable { return this.route.queryParams.map((params) => { if (isNotEmpty(params.view) && hasValue(params.view)) { From 307443f5ccc50783e085c2a23850d3a404979a4d Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 5 Jul 2018 15:00:14 +0200 Subject: [PATCH 3/4] 54053: Active filter label tests --- .../search-labels.component.spec.ts | 66 +++++++++++++++++++ .../search-labels/search-labels.component.ts | 2 +- .../search-service/search.service.spec.ts | 33 ++++++++++ src/app/shared/testing/search-service-stub.ts | 4 ++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/app/+search-page/search-labels/search-labels.component.spec.ts diff --git a/src/app/+search-page/search-labels/search-labels.component.spec.ts b/src/app/+search-page/search-labels/search-labels.component.spec.ts new file mode 100644 index 0000000000..60ba8d519a --- /dev/null +++ b/src/app/+search-page/search-labels/search-labels.component.spec.ts @@ -0,0 +1,66 @@ +import { SearchLabelsComponent } from './search-labels.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TranslateModule } from '@ngx-translate/core'; +import { SearchService } from '../search-service/search.service'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { SearchServiceStub } from '../../shared/testing/search-service-stub'; +import { Observable } from 'rxjs/Observable'; +import { FilterLabel } from '../search-service/filter-label.model'; +import { Params } from '@angular/router'; + +describe('SearchLabelsComponent', () => { + let comp: SearchLabelsComponent; + let fixture: ComponentFixture; + + const searchLink = '/search'; + let searchService; + + const field1 = 'author'; + const field2 = 'subject'; + const value1 = 'TestAuthor'; + const value2 = 'TestSubject'; + const filter1 = new FilterLabel(value1, field1); + const filter2 = new FilterLabel(value2, field2); + const mockFilters = [ + filter1, + filter2 + ]; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], + declarations: [SearchLabelsComponent], + providers: [ + { provide: SearchService, useValue: new SearchServiceStub(searchLink) } + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(SearchLabelsComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchLabelsComponent); + comp = fixture.componentInstance; + searchService = (comp as any).searchService; + (comp as any).appliedFilters = Observable.of(mockFilters); + fixture.detectChanges(); + }); + + describe('when getRemoveParams is called', () => { + let obs: Observable; + + beforeEach(() => { + obs = comp.getRemoveParams(filter1); + }); + + it('should return all params but the provided filter', () => { + obs.subscribe((params) => { + // Should contain only filter2 and page: length == 2 + expect(Object.keys(params).length).toBe(2); + }); + }) + }); +}); diff --git a/src/app/+search-page/search-labels/search-labels.component.ts b/src/app/+search-page/search-labels/search-labels.component.ts index 9111ecc2b6..4d6e3c44a8 100644 --- a/src/app/+search-page/search-labels/search-labels.component.ts +++ b/src/app/+search-page/search-labels/search-labels.component.ts @@ -11,7 +11,7 @@ import { map } from 'rxjs/operators'; }) export class SearchLabelsComponent { - protected appliedFilters: Observable; + appliedFilters: Observable; constructor(private searchService: SearchService) { this.appliedFilters = this.searchService.getFilterLabels(); diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index 4b558f8726..d732f2a3c3 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -32,6 +32,8 @@ import { } from '../../core/cache/response-cache.models'; import { SearchQueryResponse } from './search-query-response.model'; import { SearchFilterConfig } from './search-filter-config.model'; +import { FilterLabel } from './filter-label.model'; +import createSpyObj = jasmine.createSpyObj; @Component({ template: '' }) class DummyComponent { @@ -245,5 +247,36 @@ describe('SearchService', () => { expect((searchService as any).responseCache.get).toHaveBeenCalledWith(requestUrl); }); }); + + describe('when getFilterLabels is called', () => { + let obs: Observable; + const value = 'Test'; + const orgField = 'author'; + const field = 'f.' + orgField; + const mockConfig = new RemoteData(false, false, true, null, [ + { + name: orgField, + type: null, + hasFacets: false, + pageSize: 5, + isOpenByDefault: false, + paramName: field + } as SearchFilterConfig + ]); + const mockParams = []; + + beforeEach(() => { + spyOn((searchService as any), 'getConfig').and.returnValue(Observable.of(mockConfig)); + mockParams[field] = value; + (searchService as any).route.queryParams = Observable.of(mockParams); + obs = searchService.getFilterLabels(); + }); + + it('should return the correct labels', () => { + obs.subscribe((filters) => { + expect(filters[0].value).toEqual(value); + }); + }); + }); }); }); diff --git a/src/app/shared/testing/search-service-stub.ts b/src/app/shared/testing/search-service-stub.ts index 7ad0d871ce..6d636b3743 100644 --- a/src/app/shared/testing/search-service-stub.ts +++ b/src/app/shared/testing/search-service-stub.ts @@ -37,4 +37,8 @@ export class SearchServiceStub { getSearchLink() { return this.searchLink; } + + getFilterLabels() { + return Observable.of([]); + } } From bbc1daab3c991978d5eb24cbc267d44928b29688 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 11 Jul 2018 15:51:37 +0200 Subject: [PATCH 4/4] 54053: Search label offset --- src/app/+search-page/search-labels/search-labels.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/+search-page/search-labels/search-labels.component.html b/src/app/+search-page/search-labels/search-labels.component.html index e20af58bcc..e68bb7d7bd 100644 --- a/src/app/+search-page/search-labels/search-labels.component.html +++ b/src/app/+search-page/search-labels/search-labels.component.html @@ -1,5 +1,5 @@
-
+