diff --git a/src/app/core/shared/search/search-configuration.service.spec.ts b/src/app/core/shared/search/search-configuration.service.spec.ts index d0fbd46d3a2..0b1804a3e6f 100644 --- a/src/app/core/shared/search/search-configuration.service.spec.ts +++ b/src/app/core/shared/search/search-configuration.service.spec.ts @@ -20,7 +20,8 @@ describe('SearchConfigurationService', () => { const prefixFilter = { 'f.author': ['another value'], 'f.date.min': ['2013'], - 'f.date.max': ['2018'] + 'f.date.max': ['2018'], + 'f.subject': ['some subject,contains'] }; const defaults = new PaginatedSearchOptions({ pagination: Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 }), @@ -31,8 +32,10 @@ describe('SearchConfigurationService', () => { }); const backendFilters = [ - new SearchFilter('f.author', ['another value']), - new SearchFilter('f.date', ['[2013 TO 2018]'], 'equals') + new SearchFilter('f.author', ['another value'], 'equals'), + new SearchFilter('f.date', ['[2013 TO 2018]'], 'equals'), + // value already carries an operator suffix -> operator must stay unset (not overridden to equals) + new SearchFilter('f.subject', ['some subject,contains']) ]; const routeService = jasmine.createSpyObj('RouteService', { diff --git a/src/app/core/shared/search/search-configuration.service.ts b/src/app/core/shared/search/search-configuration.service.ts index eed93ae201c..8f91e1b4977 100644 --- a/src/app/core/shared/search/search-configuration.service.ts +++ b/src/app/core/shared/search/search-configuration.service.ts @@ -196,7 +196,15 @@ export class SearchConfigurationService implements OnDestroy { filters.push(new SearchFilter(realKey, ['[' + min + ' TO ' + max + ']'], 'equals')); } } else { - filters.push(new SearchFilter(key, filterParams[key])); + // Default to the "equals" operator only when a filter value carries none (e.g. a legacy + // or crawled URL like "f.subject=foo" instead of "f.subject=foo,equals"), which the + // backend would otherwise reject with HTTP 422. Values that already embed an operator + // (contain a comma, e.g. "foo,contains") keep it and leave SearchFilter.operator unset, + // matching SearchOptions.toRestUrl and consumers that read filter.operator directly + // (e.g. CSV export). dspace-customers#781. + const values = filterParams[key]; + const operator = values.every((value) => value.includes(',')) ? undefined : 'equals'; + filters.push(new SearchFilter(key, values, operator)); } }); return filters; diff --git a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts index c388d2d3561..fcbb46c5912 100644 --- a/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts +++ b/src/app/my-dspace-page/my-dspace-configuration.service.spec.ts @@ -30,7 +30,7 @@ describe('MyDSpaceConfigurationService', () => { }); const backendFilters = [ - new SearchFilter('f.namedresourcetype', ['another value']), + new SearchFilter('f.namedresourcetype', ['another value'], 'equals'), new SearchFilter('f.dateSubmitted', ['[2013 TO 2018]'], 'equals') ];