74606: Ensure the correct operators are used for filter queries

This commit is contained in:
Kristof De Langhe
2020-11-17 13:15:24 +01:00
parent 2ee815908f
commit 6f9e8bd3bf
8 changed files with 86 additions and 49 deletions

View File

@@ -1,9 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { FilterType } from '../../../filter-type.model';
import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component';
import { renderFacetFor } from '../search-filter-type-decorator';
import { FacetValue } from '../../../facet-value.model';
@Component({
selector: 'ds-search-authority-filter',
@@ -17,20 +15,4 @@ import { FacetValue } from '../../../facet-value.model';
*/
@renderFacetFor(FilterType.authority)
export class SearchAuthorityFilterComponent extends SearchFacetFilterComponent implements OnInit {
/**
* TODO to review after https://github.com/DSpace/dspace-angular/issues/368 is resolved
* Retrieve facet value from search link
*/
protected getFacetValue(facet: FacetValue): string {
const search = facet._links.search.href;
const hashes = search.slice(search.indexOf('?') + 1).split('&');
const params = {};
hashes.map((hash) => {
const [key, val] = hash.split('=');
params[key] = decodeURIComponent(val)
});
return params[this.filterConfig.paramName];
}
}

View File

@@ -10,6 +10,7 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
import { hasValue } from '../../../../../empty.util';
import { FilterType } from '../../../../filter-type.model';
import { currentPath } from '../../../../../utils/route.utils';
import { getFacetValueForType } from '../../../../search.utils';
@Component({
selector: 'ds-search-facet-option',
@@ -102,7 +103,7 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy {
*/
private updateAddParams(selectedValues: FacetValue[]): void {
this.addQueryParams = {
[this.filterConfig.paramName]: [...selectedValues.map((facetValue: FacetValue) => facetValue.label), this.getFacetValue()],
[this.filterConfig.paramName]: [...selectedValues.map((facetValue: FacetValue) => getFacetValueForType(facetValue, this.filterConfig)), this.getFacetValue()],
page: 1
};
}
@@ -112,19 +113,7 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy {
* Retrieve facet value related to facet type
*/
private getFacetValue(): string {
if (this.filterConfig.type === FilterType.authority) {
const search = this.filterValue._links.search.href;
const hashes = search.slice(search.indexOf('?') + 1).split('&');
const params = {};
hashes.map((hash) => {
const [key, val] = hash.split('=');
params[key] = decodeURIComponent(val)
});
return params[this.filterConfig.paramName];
} else {
return this.filterValue.value;
}
return getFacetValueForType(this.filterValue, this.filterConfig);
}
/**

View File

@@ -3,6 +3,6 @@
[queryParams]="removeQueryParams" queryParamsHandling="merge">
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch"/>
<span class="filter-value pl-1 text-capitalize">
{{ 'search.filters.' + filterConfig.name + '.' + selectedValue.value | translate: {default: selectedValue.value} }}
{{ 'search.filters.' + filterConfig.name + '.' + selectedValue.value | translate: {default: selectedValue.label} }}
</span>
</a>

View File

@@ -9,6 +9,7 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
import { FacetValue } from '../../../../facet-value.model';
import { FilterType } from '../../../../filter-type.model';
import { currentPath } from '../../../../../utils/route.utils';
import { getFacetValueForType } from '../../../../search.utils';
@Component({
selector: 'ds-search-facet-selected-option',
@@ -101,19 +102,7 @@ export class SearchFacetSelectedOptionComponent implements OnInit, OnDestroy {
* Retrieve facet value related to facet type
*/
private getFacetValue(facetValue: FacetValue): string {
if (this.filterConfig.type === FilterType.authority) {
const search = facetValue._links.search.href;
const hashes = search.slice(search.indexOf('?') + 1).split('&');
const params = {};
hashes.map((hash) => {
const [key, val] = hash.split('=');
params[key] = decodeURIComponent(val)
});
return params[this.filterConfig.paramName];
} else {
return facetValue.value;
}
return getFacetValueForType(facetValue, this.filterConfig);
}
/**

View File

@@ -25,6 +25,7 @@ import { InputSuggestion } from '../../../../input-suggestions/input-suggestions
import { SearchOptions } from '../../../search-options.model';
import { SEARCH_CONFIG_SERVICE } from '../../../../../+my-dspace-page/my-dspace-page.component';
import { currentPath } from '../../../../utils/route.utils';
import { getFacetValueForType, stripOperatorFromFilterValue } from '../../../search.utils';
@Component({
selector: 'ds-search-facet-filter',
@@ -148,7 +149,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
if (hasValue(fValue)) {
return fValue;
}
return Object.assign(new FacetValue(), { label: value, value: value });
return Object.assign(new FacetValue(), { label: stripOperatorFromFilterValue(value), value: value });
});
})
);
@@ -303,7 +304,7 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
* Retrieve facet value
*/
protected getFacetValue(facet: FacetValue): string {
return facet.value;
return getFacetValueForType(facet, this.filterConfig);
}
/**

View File

@@ -5,6 +5,10 @@ import {
SearchFacetFilterComponent
} from '../search-facet-filter/search-facet-filter.component';
import { renderFacetFor } from '../search-filter-type-decorator';
import {
addOperatorToFilterValue,
stripOperatorFromFilterValue
} from '../../../search.utils';
/**
* This component renders a simple item page.
@@ -24,4 +28,21 @@ import { renderFacetFor } from '../search-filter-type-decorator';
*/
@renderFacetFor(FilterType.text)
export class SearchTextFilterComponent extends SearchFacetFilterComponent implements OnInit {
/**
* Submits a new active custom value to the filter from the input field
* Overwritten method from parent component, adds the "query" operator to the received data before passing it on
* @param data The string from the input field
*/
onSubmit(data: any) {
super.onSubmit(addOperatorToFilterValue(data, 'query'));
}
/**
* On click, set the input's value to the clicked data
* Overwritten method from parent component, strips any operator from the received data before passing it on
* @param data The value of the option that was clicked
*/
onClick(data: any) {
super.onClick(stripOperatorFromFilterValue(data));
}
}

View File

@@ -3,6 +3,8 @@ import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.c
import { Observable } from 'rxjs';
import { Params, Router } from '@angular/router';
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
import { map } from 'rxjs/operators';
import { stripOperatorFromFilterValue } from '../search.utils';
@Component({
selector: 'ds-search-labels',
@@ -30,6 +32,15 @@ export class SearchLabelsComponent {
constructor(
protected router: Router,
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService) {
this.appliedFilters = this.searchConfigService.getCurrentFrontendFilters();
this.appliedFilters = this.searchConfigService.getCurrentFrontendFilters().pipe(
map((params) => {
const labels = {};
Object.keys(params)
.forEach((key) => {
labels[key] = [...params[key].map((value) => stripOperatorFromFilterValue(value))];
});
return labels;
})
);
}
}

View File

@@ -0,0 +1,44 @@
import { FacetValue } from './facet-value.model';
import { SearchFilterConfig } from './search-filter-config.model';
import { isNotEmpty } from '../empty.util';
/**
* Get a facet's value by matching its parameter in the search href, this will include the operator of the facet value
* If the {@link FacetValue} doesn't contain a search link, its raw value will be returned as a fallback
* @param facetValue
* @param searchFilterConfig
*/
export function getFacetValueForType(facetValue: FacetValue, searchFilterConfig: SearchFilterConfig): string {
const regex = new RegExp(`[?|&]${searchFilterConfig.paramName}=(${facetValue.value}[^&]*)`, 'g');
if (isNotEmpty(facetValue._links)) {
const values = regex.exec(facetValue._links.search.href);
if (isNotEmpty(values)) {
return values[1];
}
}
return addOperatorToFilterValue(facetValue.value, 'equals');
}
/**
* Strip the operator from a filter value
* Warning: This expects the value to end with an operator, otherwise it might strip unwanted content
* @param value
*/
export function stripOperatorFromFilterValue(value: string) {
if (value.lastIndexOf(',') > -1) {
return value.substring(0, value.lastIndexOf(','));
}
return value;
}
/**
* Add an operator to a string
* @param value
* @param operator
*/
export function addOperatorToFilterValue(value: string, operator: string) {
if (!value.endsWith(`,${operator}`)) {
return `${value},${operator}`;
}
return value;
}