Skip to content

Commit

Permalink
111731: Moved common remove/add queryParam logic for facet option/lab…
Browse files Browse the repository at this point in the history
…el to routeService
  • Loading branch information
alexandrevryghem committed Feb 15, 2024
1 parent dca62d6 commit 47f89a6
Show file tree
Hide file tree
Showing 24 changed files with 438 additions and 418 deletions.
49 changes: 41 additions & 8 deletions src/app/core/services/route.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { RouteService } from './route.service';
import { RouterMock } from '../../shared/mocks/router.mock';
import { TestScheduler } from 'rxjs/testing';
import { AddUrlToHistoryAction } from '../history/history.actions';
import { ActivatedRouteStub } from 'src/app/shared/testing/active-router.stub';
import { take } from 'rxjs/operators';

describe('RouteService', () => {
let scheduler: TestScheduler;
Expand All @@ -29,23 +31,19 @@ describe('RouteService', () => {
select: jasmine.createSpy('select')
});

let route: ActivatedRouteStub;
const router = new RouterMock();
router.setParams(convertToParamMap(paramObject));

paramObject[paramName1] = paramValue1;
paramObject[paramName2] = [paramValue2a, paramValue2b];

beforeEach(waitForAsync(() => {
route = new ActivatedRouteStub(paramObject);

return TestBed.configureTestingModule({
providers: [
{
provide: ActivatedRoute,
useValue: {
queryParams: observableOf(paramObject),
params: observableOf(paramObject),
queryParamMap: observableOf(convertToParamMap(paramObject))
},
},
{ provide: ActivatedRoute, useValue: route },
{ provide: Router, useValue: router },
{ provide: Store, useValue: store },
]
Expand Down Expand Up @@ -181,4 +179,39 @@ describe('RouteService', () => {
});
});
});

describe('getParamsWithoutAppliedFilter', () => {
beforeEach(() => {
route.testParams = {
'query': '',
'spc.page': '1',
'f.author': '1282121b-5394-4689-ab93-78d537764052,authority',
'f.has_content_in_original_bundle': 'true,equals',
};
});

it('should remove the parameter completely if only one value is defined', (done: DoneFn) => {
service.getParamsExceptValue('f.author', '1282121b-5394-4689-ab93-78d537764052,authority').pipe(take(1)).subscribe((params: Params) => {
expect(params).toEqual({
'query': '',
'spc.page': '1',
'f.has_content_in_original_bundle': 'true,equals',
});
done();
});
});

it('should return all params except the applied filter even when multiple filters of the same type are selected', (done: DoneFn) => {
route.testParams['f.author'] = ['1282121b-5394-4689-ab93-78d537764052,authority', '71b91a28-c280-4352-a199-bd7fc3312501,authority'];
service.getParamsExceptValue('f.author', '1282121b-5394-4689-ab93-78d537764052,authority').pipe(take(1)).subscribe((params: Params) => {
expect(params).toEqual({
'query': '',
'spc.page': '1',
'f.author': ['71b91a28-c280-4352-a199-bd7fc3312501,authority'],
'f.has_content_in_original_bundle': 'true,equals',
});
done();
});
});
});
});
49 changes: 49 additions & 0 deletions src/app/core/services/route.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,53 @@ export class RouteService {
}
);
}

/**
* Returns all the query parameters except for the one with the given name & value.
*
* @param name The name of the query param to exclude
* @param value The optional value that the query param needs to have to be excluded
*/
getParamsExceptValue(name: string, value?: string): Observable<Params> {
return this.route.queryParams.pipe(
map((params: Params) => {
const newParams: Params = Object.assign({}, params);
const queryParamValues: string | string[] = newParams[name];

if (queryParamValues === value || value === undefined) {
delete newParams[name];
} else if (Array.isArray(queryParamValues) && queryParamValues.includes(value)) {
newParams[name] = (queryParamValues as string[]).filter((paramValue: string) => paramValue !== value);
}
return newParams;
}),
);
}

/**
* Returns all the existing query parameters and the new value pair with the given name & value.
*
* @param name The name of the query param for which you need to add the value
* @param value The optional value that the query param needs to have in addition to the current ones
*/
getParamsWithAdditionalValue(name: string, value: string): Observable<Params> {
return this.route.queryParams.pipe(
map((params: Params) => {
const newParams: Params = Object.assign({}, params);
const queryParamValues: string | string[] = newParams[name];

if (queryParamValues === undefined) {
newParams[name] = value;
} else {
if (Array.isArray(queryParamValues)) {
newParams[name] = [...queryParamValues, value];
} else {
newParams[name] = [queryParamValues, value];
}
}
return newParams;
}),
);
}

}
56 changes: 11 additions & 45 deletions src/app/core/shared/search/search-configuration.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.u
import { getMockRequestService } from '../../../shared/mocks/request.service.mock';
import { RequestEntry } from '../../data/request-entry.model';
import { SearchObjects } from '../../../shared/search/models/search-objects.model';
import { Params } from '@angular/router';
import { addOperatorToFilterValue } from '../../../shared/search/search.utils';
import { AppliedFilter } from '../../../shared/search/models/applied-filter.model';

describe('SearchConfigurationService', () => {
Expand All @@ -41,7 +39,8 @@ describe('SearchConfigurationService', () => {
const routeService = jasmine.createSpyObj('RouteService', {
getQueryParameterValue: observableOf(value1),
getQueryParamsWithPrefix: observableOf(prefixFilter),
getRouteParameterValue: observableOf('')
getRouteParameterValue: observableOf(''),
getParamsExceptValue: observableOf({}),
});

const paginationService = new PaginationServiceStub();
Expand Down Expand Up @@ -283,7 +282,7 @@ describe('SearchConfigurationService', () => {
});
});

describe('getParamsWithoutAppliedFilter', () => {
describe('unselectAppliedFilterParams', () => {
let appliedFilter: AppliedFilter;

beforeEach(() => {
Expand All @@ -293,51 +292,18 @@ describe('SearchConfigurationService', () => {
value: '1282121b-5394-4689-ab93-78d537764052',
label: 'Odinson, Thor',
});
activatedRoute.testParams = {
'query': '',
'spc.page': '1',
'f.author': addOperatorToFilterValue(appliedFilter.value, appliedFilter.operator),
'f.has_content_in_original_bundle': addOperatorToFilterValue('true', 'equals'),
'f.dateIssued.max': '2000',
};
});

it('should return all params except the applied filter', (done: DoneFn) => {
service.getParamsWithoutAppliedFilter(appliedFilter.filter, appliedFilter.value, appliedFilter.operator).pipe(take(1)).subscribe((params: Params) => {
expect(params).toEqual({
'query': '',
'spc.page': '1',
'f.has_content_in_original_bundle': addOperatorToFilterValue('true', 'equals'),
'f.dateIssued.max': '2000',
});
done();
});
});

it('should return all params except the applied filter even when multiple filters of the same type are selected', (done: DoneFn) => {
activatedRoute.testParams['f.author'] = [addOperatorToFilterValue(appliedFilter.value, appliedFilter.operator), addOperatorToFilterValue('71b91a28-c280-4352-a199-bd7fc3312501', 'authority')];
service.getParamsWithoutAppliedFilter(appliedFilter.filter, appliedFilter.value, appliedFilter.operator).pipe(take(1)).subscribe((params: Params) => {
expect(params).toEqual({
'query': '',
'spc.page': '1',
'f.author': [addOperatorToFilterValue('71b91a28-c280-4352-a199-bd7fc3312501', 'authority')],
'f.has_content_in_original_bundle': addOperatorToFilterValue('true', 'equals'),
'f.dateIssued.max': '2000',
});
done();
});
it('should return all params except the applied filter', () => {
service.unselectAppliedFilterParams(appliedFilter.filter, appliedFilter.value, appliedFilter.operator);

expect(routeService.getParamsExceptValue).toHaveBeenCalledWith('f.author', '1282121b-5394-4689-ab93-78d537764052,authority');
});

it('should be able to remove AppliedFilter without operator', (done: DoneFn) => {
service.getParamsWithoutAppliedFilter('dateIssued.max', '2000').pipe(take(1)).subscribe((params: Params) => {
expect(params).toEqual({
'query': '',
'spc.page': '1',
'f.author': addOperatorToFilterValue(appliedFilter.value, appliedFilter.operator),
'f.has_content_in_original_bundle': addOperatorToFilterValue('true', 'equals'),
});
done();
});
it('should be able to remove AppliedFilter without operator', () => {
service.unselectAppliedFilterParams('dateIssued.max', '2000');

expect(routeService.getParamsExceptValue).toHaveBeenCalledWith('f.dateIssued.max', '2000');
});
});
});
36 changes: 20 additions & 16 deletions src/app/core/shared/search/search-configuration.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,22 +526,26 @@ export class SearchConfigurationService implements OnDestroy {
);
}

getParamsWithoutAppliedFilter(filterName: string, value: string, operator?: string): Observable<Params> {
return this.route.queryParams.pipe(
map((params: Params) => {
const newParams: Params = Object.assign({}, params);
const queryParamValues: string | string[] = newParams[`f.${filterName}`];
const excludeValue = hasValue(operator) ? addOperatorToFilterValue(value, operator) : value;

if (queryParamValues === excludeValue) {
delete newParams[`f.${filterName}`];
} else if (queryParamValues?.includes(excludeValue)) {
newParams[`f.${filterName}`] = (queryParamValues as string[])
.filter((paramValue: string) => paramValue !== excludeValue);
}
return newParams;
}),
);
/**
* Calculates the {@link Params} of the search after removing a filter with a certain value
*
* @param filterName The {@link AppliedFilter}'s name
* @param value The {@link AppliedFilter}'s value
* @param operator The {@link AppliedFilter}'s optional operator
*/
unselectAppliedFilterParams(filterName: string, value: string, operator?: string): Observable<Params> {
return this.routeService.getParamsExceptValue(`f.${filterName}`, hasValue(operator) ? addOperatorToFilterValue(value, operator) : value);
}

/**
* Calculates the {@link Params} of the search after removing a filter with a certain value
*
* @param filterName The {@link AppliedFilter}'s name
* @param value The {@link AppliedFilter}'s value
* @param operator The {@link AppliedFilter}'s optional operator
*/
selectNewAppliedFilterParams(filterName: string, value: string, operator?: string): Observable<Params> {
return this.routeService.getParamsWithAdditionalValue(`f.${filterName}`, hasValue(operator) ? addOperatorToFilterValue(value, operator) : value);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/app/core/shared/search/search-filter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ export class SearchFilterService {
* Fetch the current active scope from the query parameters
* @returns {Observable<string>}
*/
getCurrentScope() {
getCurrentScope(): Observable<string> {
return this.routeService.getQueryParameterValue('scope');
}

/**
* Fetch the current query from the query parameters
* @returns {Observable<string>}
*/
getCurrentQuery() {
getCurrentQuery(): Observable<string> {
return this.routeService.getQueryParameterValue('query');
}

Expand Down Expand Up @@ -113,15 +113,15 @@ export class SearchFilterService {
* Fetch the current active filters from the query parameters
* @returns {Observable<Params>}
*/
getCurrentFilters() {
getCurrentFilters(): Observable<Params> {
return this.routeService.getQueryParamsWithPrefix('f.');
}

/**
* Fetch the current view from the query parameters
* @returns {Observable<string>}
*/
getCurrentView() {
getCurrentView(): Observable<string> {
return this.routeService.getQueryParameterValue('view');
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div>
<div class="filters py-2">
<ds-search-facet-selected-option *ngFor="let value of (selectedAppliedFilters$ | async)" [selectedValue]="value" [filterConfig]="filterConfig" [selectedValues$]="selectedAppliedFilters$" [inPlaceSearch]="inPlaceSearch"></ds-search-facet-selected-option>
<ds-search-facet-selected-option *ngFor="let value of (selectedAppliedFilters$ | async)" [selectedValue]="value" [filterConfig]="filterConfig" [inPlaceSearch]="inPlaceSearch"></ds-search-facet-selected-option>
<ng-container *ngFor="let page of (facetValues$ | async)">
<div [@facetLoad]="animationState">
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value" [selectedValues$]="selectedAppliedFilters$" [inPlaceSearch]="inPlaceSearch"></ds-search-facet-option>
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value" [inPlaceSearch]="inPlaceSearch"></ds-search-facet-option>
</div>
</ng-container>
<div class="clearfix toggle-more-filters">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div>
<div class="filters py-2">
<ds-search-facet-selected-option *ngFor="let value of (selectedAppliedFilters$ | async)" [selectedValue]="value" [filterConfig]="filterConfig" [selectedValues$]="selectedAppliedFilters$" [inPlaceSearch]="inPlaceSearch"></ds-search-facet-selected-option>
<ds-search-facet-selected-option *ngFor="let value of (selectedAppliedFilters$ | async)" [selectedValue]="value" [filterConfig]="filterConfig" [inPlaceSearch]="inPlaceSearch"></ds-search-facet-selected-option>
<ng-container *ngFor="let page of (facetValues$ | async)">
<div [@facetLoad]="animationState">
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value" [selectedValues$]="selectedAppliedFilters$" [inPlaceSearch]="inPlaceSearch"></ds-search-facet-option>
<ds-search-facet-option *ngFor="let value of page.page; trackBy: trackUpdate" [filterConfig]="filterConfig" [filterValue]="value" [inPlaceSearch]="inPlaceSearch"></ds-search-facet-option>
</div>
</ng-container>
<div class="clearfix toggle-more-filters">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<a *ngIf="isVisible | async" class="d-flex flex-row"
[tabIndex]="-1"
[routerLink]="[searchLink]"
[queryParams]="addQueryParams" queryParamsHandling="merge">
[queryParams]="addQueryParams$ | async">
<label class="mb-0">
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch"/>
<span class="filter-value px-1">
Expand Down
Loading

0 comments on commit 47f89a6

Please sign in to comment.