Skip to content

Commit

Permalink
111639: Added scope @input() and made the search facets & search resu…
Browse files Browse the repository at this point in the history
…lts use that scope

(cherry picked from commit 22e87a5)
  • Loading branch information
alexandrevryghem authored and github-actions[bot] committed Feb 15, 2024
1 parent b350916 commit 865f489
Show file tree
Hide file tree
Showing 14 changed files with 97 additions and 47 deletions.
1 change: 1 addition & 0 deletions src/app/core/shared/search/search-filter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const filterStateSelector = (state: SearchFiltersState) => state.searchFilter;
export const FILTER_CONFIG: InjectionToken<SearchFilterConfig> = new InjectionToken<SearchFilterConfig>('filterConfig');
export const IN_PLACE_SEARCH: InjectionToken<boolean> = new InjectionToken<boolean>('inPlaceSearch');
export const REFRESH_FILTER: InjectionToken<BehaviorSubject<any>> = new InjectionToken<boolean>('refreshFilters');
export const SCOPE: InjectionToken<string> = new InjectionToken<string>('scope');

/**
* Service that performs all actions that have to do with search filters and facets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FilterType } from '../../../models/filter-type.model';
import { SearchFilterConfig } from '../../../models/search-filter-config.model';
import {
FILTER_CONFIG,
SCOPE,
IN_PLACE_SEARCH,
REFRESH_FILTER
} from '../../../../../core/shared/search/search-filter.service';
Expand Down Expand Up @@ -35,6 +36,11 @@ export class SearchFacetFilterWrapperComponent implements OnInit {
*/
@Input() refreshFilters: BehaviorSubject<boolean>;

/**
* The current scope
*/
@Input() scope: string;

/**
* The constructor of the search facet filter that should be rendered, based on the filter config's type
*/
Expand All @@ -56,7 +62,8 @@ export class SearchFacetFilterWrapperComponent implements OnInit {
providers: [
{ provide: FILTER_CONFIG, useFactory: () => (this.filterConfig), deps: [] },
{ provide: IN_PLACE_SEARCH, useFactory: () => (this.inPlaceSearch), deps: [] },
{ provide: REFRESH_FILTER, useFactory: () => (this.refreshFilters), deps: [] }
{ provide: REFRESH_FILTER, useFactory: () => (this.refreshFilters), deps: [] },
{ provide: SCOPE, useFactory: () => (this.scope), deps: [] },
],
parent: this.injector
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TranslateModule } from '@ngx-translate/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import {
FILTER_CONFIG,
SCOPE,
IN_PLACE_SEARCH,
REFRESH_FILTER,
SearchFilterService
Expand Down Expand Up @@ -99,6 +100,7 @@ describe('SearchFacetFilterComponent', () => {
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() },
{ provide: IN_PLACE_SEARCH, useValue: false },
{ provide: REFRESH_FILTER, useValue: new BehaviorSubject<boolean>(false) },
{ provide: SCOPE, useValue: undefined },
{
provide: SearchFilterService, useValue: {
getSelectedValuesForFilter: () => observableOf(selectedValues),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { SearchFilterConfig } from '../../../models/search-filter-config.model';
import { SearchService } from '../../../../../core/shared/search/search.service';
import {
FILTER_CONFIG,
SCOPE,
IN_PLACE_SEARCH,
REFRESH_FILTER,
SearchFilterService
Expand Down Expand Up @@ -104,7 +105,9 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
@Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean,
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig,
@Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject<boolean>) {
@Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject<boolean>,
@Inject(SCOPE) public scope: string,
) {
}

/**
Expand All @@ -114,8 +117,11 @@ export class SearchFacetFilterComponent implements OnInit, OnDestroy {
this.currentUrl = this.router.url;
this.filterValues$ = new BehaviorSubject(createPendingRemoteDataObject());
this.currentPage = this.getCurrentPage().pipe(distinctUntilChanged());

this.searchOptions$ = this.searchConfigService.searchOptions;
this.searchOptions$ = this.searchConfigService.searchOptions.pipe(
map((options: SearchOptions) => hasNoValue(this.scope) ? options : Object.assign({}, options, {
scope: this.scope,
})),
);
this.subs.push(
this.searchOptions$.subscribe(() => this.updateFilterValueList()),
this.refreshFilters.asObservable().pipe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
(@slide.start)="startSlide($event)" (@slide.done)="finishSlide($event)"
class="search-filter-wrapper" [ngClass]="{ 'closed' : closed, 'notab': notab }">
<ds-search-facet-filter-wrapper
[scope]="scope"
[filterConfig]="filter"
[inPlaceSearch]="inPlaceSearch"
[refreshFilters]="refreshFilters" >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { filter, map, startWith, switchMap, take } from 'rxjs/operators';
import { SearchFilterConfig } from '../../models/search-filter-config.model';
import { SearchFilterService } from '../../../../core/shared/search/search-filter.service';
import { slide } from '../../../animations/slide';
import { isNotEmpty } from '../../../empty.util';
import { isNotEmpty, hasValue } from '../../../empty.util';
import { SearchService } from '../../../../core/shared/search/search.service';
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
import { SEARCH_CONFIG_SERVICE } from '../../../../my-dspace-page/my-dspace-page.component';
Expand Down Expand Up @@ -38,6 +38,11 @@ export class SearchFilterComponent implements OnInit {
*/
@Input() refreshFilters: BehaviorSubject<boolean>;

/**
* The current scope
*/
@Input() scope: string;

/**
* True when the filter is 100% collapsed in the UI
*/
Expand Down Expand Up @@ -171,6 +176,9 @@ export class SearchFilterComponent implements OnInit {
} else {
return this.searchConfigService.searchOptions.pipe(
switchMap((options) => {
if (hasValue(this.scope)) {
options.scope = this.scope;
}
return this.searchService.getFacetValuesFor(this.filter, 1, options).pipe(
filter((RD) => !RD.isLoading),
map((valuesRD) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CommonModule } from '@angular/common';
import { SearchService } from '../../../../../core/shared/search/search.service';
import {
FILTER_CONFIG,
SCOPE,
IN_PLACE_SEARCH,
SearchFilterService,
REFRESH_FILTER
Expand Down Expand Up @@ -75,7 +76,8 @@ describe('SearchHierarchyFilterComponent', () => {
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() },
{ provide: IN_PLACE_SEARCH, useValue: false },
{ provide: FILTER_CONFIG, useValue: Object.assign(new SearchFilterConfig(), { name: testSearchFilter }) },
{ provide: REFRESH_FILTER, useValue: new BehaviorSubject<boolean>(false)}
{ provide: REFRESH_FILTER, useValue: new BehaviorSubject<boolean>(false)},
{ provide: SCOPE, useValue: undefined },
],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { SearchService } from '../../../../../core/shared/search/search.service';
import {
FILTER_CONFIG,
SCOPE,
IN_PLACE_SEARCH,
SearchFilterService, REFRESH_FILTER
} from '../../../../../core/shared/search/search-filter.service';
Expand Down Expand Up @@ -49,9 +50,10 @@ export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent i
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService,
@Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean,
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig,
@Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject<boolean>
@Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject<boolean>,
@Inject(SCOPE) public scope: string,
) {
super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters);
super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters, scope);
}

vocabularyExists$: Observable<boolean>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TranslateModule } from '@ngx-translate/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import {
FILTER_CONFIG,
SCOPE,
IN_PLACE_SEARCH,
REFRESH_FILTER,
SearchFilterService
Expand Down Expand Up @@ -105,6 +106,7 @@ describe('SearchRangeFilterComponent', () => {
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() },
{ provide: IN_PLACE_SEARCH, useValue: false },
{ provide: REFRESH_FILTER, useValue: new BehaviorSubject<boolean>(false) },
{ provide: SCOPE, useValue: undefined },
{
provide: SearchFilterService, useValue: {
getSelectedValuesForFilter: () => selectedValues,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/se
import { SearchFilterConfig } from '../../../models/search-filter-config.model';
import {
FILTER_CONFIG,
SCOPE,
IN_PLACE_SEARCH,
REFRESH_FILTER,
SearchFilterService
Expand Down Expand Up @@ -101,8 +102,9 @@ export class SearchRangeFilterComponent extends SearchFacetFilterComponent imple
@Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig,
@Inject(PLATFORM_ID) private platformId: any,
@Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject<boolean>,
@Inject(SCOPE) public scope: string,
private route: RouteService) {
super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters);
super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters, scope);

}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h3>{{"search.filters.head" | translate}}</h3>
<div *ngIf="(filters | async)?.hasSucceeded">
<div *ngFor="let filter of (filters | async)?.payload; trackBy: trackUpdate">
<ds-search-filter [filter]="filter" [inPlaceSearch]="inPlaceSearch" [refreshFilters]="refreshFilters"></ds-search-filter>
<ds-search-filter [scope]="currentScope" [filter]="filter" [inPlaceSearch]="inPlaceSearch" [refreshFilters]="refreshFilters"></ds-search-filter>
</div>
</div>
<a class="btn btn-primary" [routerLink]="[searchLink]" [queryParams]="clearParams | async" queryParamsHandling="merge" role="button"><i class="fas fa-undo"></i> {{"search.filters.reset" | translate}}</a>
26 changes: 2 additions & 24 deletions src/app/shared/search/search.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ import { getCollectionPageRoute } from '../../collection-page/collection-page-ro

let comp: SearchComponent;
let fixture: ComponentFixture<SearchComponent>;
let searchServiceObject: SearchService;
let searchConfigurationServiceObject: SearchConfigurationService;
const store: Store<SearchComponent> = jasmine.createSpyObj('store', {
/* eslint-disable no-empty,@typescript-eslint/no-empty-function */
dispatch: {},
Expand Down Expand Up @@ -93,7 +91,6 @@ const mockDso2 = Object.assign(new Item(), {
}
}
});
const sort: SortOptions = new SortOptions('score', SortDirection.DESC);
const mockSearchResults: SearchObjects<DSpaceObject> = Object.assign(new SearchObjects(), {
page: [mockDso, mockDso2]
});
Expand All @@ -106,23 +103,13 @@ const searchServiceStub = jasmine.createSpyObj('SearchService', {
getSearchConfigurationFor: createSuccessfulRemoteDataObject$(searchConfig),
trackSearch: {},
}) as SearchService;
const configurationParam = 'default';
const queryParam = 'test query';
const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f';
const fixedFilter = 'fixed filter';

const defaultSearchOptions = new PaginatedSearchOptions({ pagination });

const paginatedSearchOptions$ = new BehaviorSubject(defaultSearchOptions);

const paginatedSearchOptions = new PaginatedSearchOptions({
configuration: configurationParam,
query: queryParam,
scope: scopeParam,
fixedFilter: fixedFilter,
pagination,
sort
});
const activatedRouteStub = {
snapshot: {
queryParamMap: new Map([
Expand Down Expand Up @@ -155,14 +142,11 @@ const filtersConfigRD = createSuccessfulRemoteDataObject([mockFilterConfig, mock
const filtersConfigRD$ = observableOf(filtersConfigRD);

const routeServiceStub = {
getRouteParameterValue: () => {
return observableOf('');
},
getQueryParameterValue: () => {
return observableOf('');
return observableOf(null);
},
getQueryParamsWithPrefix: () => {
return observableOf('');
return observableOf(null);
},
setParameter: () => {
return;
Expand Down Expand Up @@ -252,16 +236,10 @@ describe('SearchComponent', () => {
comp.paginationId = paginationId;

spyOn((comp as any), 'getSearchOptions').and.returnValue(paginatedSearchOptions$.asObservable());

searchServiceObject = TestBed.inject(SearchService);
searchConfigurationServiceObject = TestBed.inject(SEARCH_CONFIG_SERVICE);

});

afterEach(() => {
comp = null;
searchServiceObject = null;
searchConfigurationServiceObject = null;
});

it('should init search parameters properly and call retrieveSearchResults', fakeAsync(() => {
Expand Down
31 changes: 21 additions & 10 deletions src/app/shared/search/search.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, OnInit, Output, OnDestroy } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';

import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
Expand All @@ -11,7 +11,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { pushInOut } from '../animations/push';
import { HostWindowService } from '../host-window.service';
import { SidebarService } from '../sidebar/sidebar.service';
import { hasValue, hasValueOperator, isNotEmpty } from '../empty.util';
import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../empty.util';
import { RouteService } from '../../core/services/route.service';
import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component';
import { PaginatedSearchOptions } from './models/paginated-search-options.model';
Expand All @@ -34,7 +34,7 @@ import { CollectionElementLinkType } from '../object-collection/collection-eleme
import { environment } from 'src/environments/environment';
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
import { SearchFilterConfig } from './models/search-filter-config.model';
import { WorkspaceItem } from '../..//core/submission/models/workspaceitem.model';
import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model';
import { ITEM_MODULE_PATH } from '../../item-page/item-page-routing-paths';
import { COLLECTION_MODULE_PATH } from '../../collection-page/collection-page-routing-paths';
import { COMMUNITY_MODULE_PATH } from '../../community-page/community-page-routing-paths';
Expand All @@ -50,7 +50,7 @@ import { COMMUNITY_MODULE_PATH } from '../../community-page/community-page-routi
/**
* This component renders a sidebar, a search input bar and the search results.
*/
export class SearchComponent implements OnInit {
export class SearchComponent implements OnDestroy, OnInit {

/**
* The list of available configuration options
Expand Down Expand Up @@ -166,6 +166,11 @@ export class SearchComponent implements OnInit {
*/
@Input() query: string;

/**
* The fallback scope when no scope is defined in the url, if this is also undefined no scope will be set
*/
@Input() scope: string;

/**
* The current configuration used during the search
*/
Expand All @@ -179,7 +184,7 @@ export class SearchComponent implements OnInit {
/**
* The current sort options used
*/
currentScope$: BehaviorSubject<string> = new BehaviorSubject<string>('');
currentScope$: Observable<string>;

/**
* The current sort options used
Expand Down Expand Up @@ -299,6 +304,10 @@ export class SearchComponent implements OnInit {
this.routeService.setParameter('fixedFilterQuery', this.fixedFilterQuery);
}

this.currentScope$ = this.routeService.getQueryParameterValue('scope').pipe(
map((routeValue: string) => hasValue(routeValue) ? routeValue : this.scope),
);

this.isSidebarCollapsed$ = this.isSidebarCollapsed();
this.searchLink = this.getSearchLink();
this.currentContext$.next(this.context);
Expand All @@ -321,13 +330,13 @@ export class SearchComponent implements OnInit {
);
const searchOptions$: Observable<PaginatedSearchOptions> = this.getSearchOptions().pipe(distinctUntilChanged());

this.subs.push(combineLatest([configuration$, searchSortOptions$, searchOptions$, sortOption$]).pipe(
filter(([configuration, searchSortOptions, searchOptions, sortOption]: [string, SortOptions[], PaginatedSearchOptions, SortOptions]) => {
this.subs.push(combineLatest([configuration$, searchSortOptions$, searchOptions$, sortOption$, this.currentScope$]).pipe(
filter(([configuration, searchSortOptions, searchOptions, sortOption, scope]: [string, SortOptions[], PaginatedSearchOptions, SortOptions, string]) => {
// filter for search options related to instanced paginated id
return searchOptions.pagination.id === this.paginationId;
}),
debounceTime(100)
).subscribe(([configuration, searchSortOptions, searchOptions, sortOption]: [string, SortOptions[], PaginatedSearchOptions, SortOptions]) => {
).subscribe(([configuration, searchSortOptions, searchOptions, sortOption, scope]: [string, SortOptions[], PaginatedSearchOptions, SortOptions, string]) => {
// Build the PaginatedSearchOptions object
const combinedOptions = Object.assign({}, searchOptions,
{
Expand All @@ -337,20 +346,22 @@ export class SearchComponent implements OnInit {
if (combinedOptions.query === '') {
combinedOptions.query = this.query;
}
if (isEmpty(combinedOptions.scope)) {
combinedOptions.scope = scope;
}
const newSearchOptions = new PaginatedSearchOptions(combinedOptions);
// check if search options are changed
// if so retrieve new related results otherwise skip it
if (JSON.stringify(newSearchOptions) !== JSON.stringify(this.searchOptions$.value)) {
// Initialize variables
this.currentConfiguration$.next(configuration);
this.currentSortOptions$.next(newSearchOptions.sort);
this.currentScope$.next(newSearchOptions.scope);
this.sortOptionsList$.next(searchSortOptions);
this.searchOptions$.next(newSearchOptions);
this.initialized$.next(true);
// retrieve results
this.retrieveSearchResults(newSearchOptions);
this.retrieveFilters(searchOptions);
this.retrieveFilters(newSearchOptions);
}
}));

Expand Down
Loading

0 comments on commit 865f489

Please sign in to comment.