diff --git a/src/app/+item-page/simple/related-entities/related-entities-search/related-entities-search.component.html b/src/app/+item-page/simple/related-entities/related-entities-search/related-entities-search.component.html index c7e1f77264..ebf3a0fd6e 100644 --- a/src/app/+item-page/simple/related-entities/related-entities-search/related-entities-search.component.html +++ b/src/app/+item-page/simple/related-entities/related-entities-search/related-entities-search.component.html @@ -3,4 +3,4 @@ [configuration$]="configuration$" [searchEnabled]="searchEnabled" [sideBarWidth]="sideBarWidth"> - + \ No newline at end of file diff --git a/src/app/+item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts b/src/app/+item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts index 63982c2a82..28e575634c 100644 --- a/src/app/+item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts +++ b/src/app/+item-page/simple/related-entities/related-entities-search/related-entities-search.component.ts @@ -1,9 +1,9 @@ import { Component, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { SearchFixedFilterService } from '../../../../core/shared/search/search-fixed-filter.service'; import { isNotEmpty } from '../../../../shared/empty.util'; import { of } from 'rxjs/internal/observable/of'; +import { getFilterByRelation } from '../../../../shared/utils/relation-query.utils'; @Component({ selector: 'ds-related-entities-search', @@ -49,12 +49,12 @@ export class RelatedEntitiesSearchComponent implements OnInit { fixedFilter: string; configuration$: Observable; - constructor(private fixedFilterService: SearchFixedFilterService) { + constructor() { } ngOnInit(): void { if (isNotEmpty(this.relationType) && isNotEmpty(this.item)) { - this.fixedFilter = this.fixedFilterService.getFilterByRelation(this.relationType, this.item.id); + this.fixedFilter = getFilterByRelation(this.relationType, this.item.id); } if (isNotEmpty(this.relationEntityType)) { this.configuration$ = of(this.relationEntityType); diff --git a/src/app/+my-dspace-page/my-dspace-configuration.service.ts b/src/app/+my-dspace-page/my-dspace-configuration.service.ts index 97f8f327c9..667668eda9 100644 --- a/src/app/+my-dspace-page/my-dspace-configuration.service.ts +++ b/src/app/+my-dspace-page/my-dspace-configuration.service.ts @@ -11,7 +11,6 @@ import { SearchConfigurationService } from '../core/shared/search/search-configu import { RouteService } from '../shared/services/route.service'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; -import { SearchFixedFilterService } from '../core/shared/search/search-fixed-filter.service'; /** * Service that performs all actions that have to do with the current mydspace configuration @@ -60,11 +59,10 @@ export class MyDSpaceConfigurationService extends SearchConfigurationService { * @param {ActivatedRoute} route */ constructor(protected roleService: RoleService, - protected fixedFilterService: SearchFixedFilterService, protected routeService: RouteService, protected route: ActivatedRoute) { - super(routeService, fixedFilterService, route); + super(routeService, route); // override parent class initialization this._defaults = null; diff --git a/src/app/+search-page/configuration-search-page.component.ts b/src/app/+search-page/configuration-search-page.component.ts index 8bd5724844..2d331d1acb 100644 --- a/src/app/+search-page/configuration-search-page.component.ts +++ b/src/app/+search-page/configuration-search-page.component.ts @@ -3,14 +3,12 @@ import { SearchPageComponent } from './search-page.component'; import { ChangeDetectionStrategy, Component, Inject, Input, OnInit } from '@angular/core'; import { pushInOut } from '../shared/animations/push'; import { RouteService } from '../shared/services/route.service'; -import { Observable } from 'rxjs'; import { SEARCH_CONFIG_SERVICE } from '../+my-dspace-page/my-dspace-page.component'; -import { map } from 'rxjs/operators'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { SearchService } from '../core/shared/search/search.service'; import { SearchSidebarService } from '../core/shared/search/search-sidebar.service'; import { Router } from '@angular/router'; -import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; +import { hasValue } from '../shared/empty.util'; /** * This component renders a search page using a configuration as input. @@ -54,20 +52,8 @@ export class ConfigurationSearchPageComponent extends SearchPageComponent implem */ ngOnInit(): void { super.ngOnInit(); - } - - /** - * Get the current paginated search options after updating the configuration using the configuration input - * This is to make sure the configuration is included in the paginated search options, as it is not part of any - * query or route parameters - * @returns {Observable} - */ - protected getSearchOptions(): Observable { - return this.searchConfigService.paginatedSearchOptions.pipe( - map((options: PaginatedSearchOptions) => { - const config = this.configuration || options.configuration; - return Object.assign(options, { configuration: config }); - }) - ); + if (hasValue(this.configuration )) { + this.routeService.setParameter('configuration', this.configuration); + } } } diff --git a/src/app/+search-page/filtered-search-page.component.ts b/src/app/+search-page/filtered-search-page.component.ts index 1eb3704f30..c2bc2b50c5 100644 --- a/src/app/+search-page/filtered-search-page.component.ts +++ b/src/app/+search-page/filtered-search-page.component.ts @@ -35,7 +35,7 @@ import { hasValue, isNotEmpty, isNotEmptyOperator } from '../shared/empty.util'; export class FilteredSearchPageComponent extends SearchPageComponent implements OnInit { /** * The actual query for the fixed filter. - * If empty, the query will be determined by the route parameter called 'filter' + * If empty, the query will be determined by the route parameter called 'fixedFilterQuery' */ @Input() fixedFilterQuery: string; @@ -58,7 +58,7 @@ export class FilteredSearchPageComponent extends SearchPageComponent implements ngOnInit(): void { super.ngOnInit(); if (hasValue(this.fixedFilterQuery)) { - this.routeService.setParameter('filterQuery', this.fixedFilterQuery); + this.routeService.setParameter('fixedFilterQuery', this.fixedFilterQuery); } } } diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index 70ce9b2906..bb64d0c123 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -4,13 +4,15 @@ import { CoreModule } from '../core/core.module'; import { SharedModule } from '../shared/shared.module'; import { SearchPageRoutingModule } from './search-page-routing.module'; import { SearchPageComponent } from './search-page.component'; -import { FilteredSearchPageComponent } from './filtered-search-page.component'; import { ConfigurationSearchPageGuard } from './configuration-search-page.guard'; +import { ConfigurationSearchPageComponent } from './configuration-search-page.component'; +import { FilteredSearchPageComponent } from './filtered-search-page.component'; const components = [ SearchPageComponent, - FilteredSearchPageComponent + FilteredSearchPageComponent, + ConfigurationSearchPageComponent ]; @NgModule({ diff --git a/src/app/core/core.effects.ts b/src/app/core/core.effects.ts index 9ade23e6c5..11dba82593 100644 --- a/src/app/core/core.effects.ts +++ b/src/app/core/core.effects.ts @@ -1,4 +1,3 @@ - import { ObjectCacheEffects } from './cache/object-cache.effects'; import { UUIDIndexEffects } from './index/index.effects'; import { RequestEffects } from './data/request.effects'; @@ -7,6 +6,7 @@ import { JsonPatchOperationsEffects } from './json-patch/json-patch-operations.e import { ServerSyncBufferEffects } from './cache/server-sync-buffer.effects'; import { ObjectUpdatesEffects } from './data/object-updates/object-updates.effects'; import { RouteEffects } from '../shared/services/route.effects'; +import { RouterEffects } from './router/router.effects'; export const coreEffects = [ RequestEffects, @@ -16,5 +16,6 @@ export const coreEffects = [ JsonPatchOperationsEffects, ServerSyncBufferEffects, ObjectUpdatesEffects, - RouteEffects + RouteEffects, + RouterEffects ]; diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 2536d654c4..d6af9f14cb 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -1,14 +1,13 @@ -import { - ModuleWithProviders, - NgModule, - Optional, - SkipSelf -} from '@angular/core'; +import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; import { CommonModule } from '@angular/common'; import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; -import { DynamicFormLayoutService, DynamicFormService, DynamicFormValidationService } from '@ng-dynamic-forms/core'; +import { + DynamicFormLayoutService, + DynamicFormService, + DynamicFormValidationService +} from '@ng-dynamic-forms/core'; import { coreEffects } from './core.effects'; import { coreReducers } from './core.reducers'; @@ -94,10 +93,9 @@ import { mockResponseMap } from './dspace-rest-v2/mocks/mock-response-map'; import { EndpointMockingRestService } from './dspace-rest-v2/endpoint-mocking-rest.service'; -import { ENV_CONFIG, GLOBAL_CONFIG, GlobalConfig } from '../../config'; +import { GLOBAL_CONFIG, GlobalConfig } from '../../config'; import { SearchSidebarService } from './shared/search/search-sidebar.service'; import { SearchFilterService } from './shared/search/search-filter.service'; -import { SearchFixedFilterService } from './shared/search/search-fixed-filter.service'; import { SearchConfigurationService } from './shared/search/search-configuration.service'; import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service'; @@ -201,7 +199,6 @@ const PROVIDERS = [ SearchService, SearchSidebarService, SearchFilterService, - SearchFixedFilterService, SearchFilterService, SearchConfigurationService, SelectableListService, diff --git a/src/app/core/router/router.actions.ts b/src/app/core/router/router.actions.ts new file mode 100644 index 0000000000..bb9497106e --- /dev/null +++ b/src/app/core/router/router.actions.ts @@ -0,0 +1,29 @@ +import { Action } from '@ngrx/store'; +import { type } from '../../shared/ngrx/type'; +import { Params } from '@angular/router'; + +/** + * The list of HrefIndexAction type definitions + */ +export const RouterActionTypes = { + ROUTE_UPDATE: type('dspace/core/router/ROUTE_UPDATE'), +}; + +/* tslint:disable:max-classes-per-file */ +/** + * An ngrx action to be fired when the route is updated + * Note that, contrary to the router-store.ROUTER_NAVIGATION action, + * this action will only be fired when the path changes, + * not when just the query parameters change + */ +export class RouteUpdateAction implements Action { + type = RouterActionTypes.ROUTE_UPDATE; + + /** + * Create a new RouteUpdateAction + */ + constructor() { + } +} + +/* tslint:enable:max-classes-per-file */ diff --git a/src/app/core/router/router.effects.ts b/src/app/core/router/router.effects.ts new file mode 100644 index 0000000000..2865d54922 --- /dev/null +++ b/src/app/core/router/router.effects.ts @@ -0,0 +1,31 @@ +import { filter, map, pairwise } from 'rxjs/operators'; +import { Injectable } from '@angular/core'; +import { Actions, Effect, ofType } from '@ngrx/effects' +import * as fromRouter from '@ngrx/router-store'; +import { RouterNavigationAction } from '@ngrx/router-store'; +import { Router } from '@angular/router'; +import { RouteUpdateAction } from './router.actions'; + +@Injectable() +export class RouterEffects { + /** + * Effect that fires a new RouteUpdateAction when then path of route is changed + * @type {Observable} + */ + @Effect() routeChange$ = this.actions$ + .pipe( + ofType(fromRouter.ROUTER_NAVIGATION), + pairwise(), + map((actions: RouterNavigationAction[]) => + actions.map((navigateAction) => { + const urlTree = this.router.parseUrl(navigateAction.payload.routerState.url); + return urlTree.root.children['primary'].segments.map(it => it.path).join('/'); + })), + filter((actions: string[]) => actions[0] !== actions[1]), + map(() => new RouteUpdateAction()) + ); + + constructor(private actions$: Actions, private router: Router) { + } + +} 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 d9d3ce98a7..a84f954b65 100644 --- a/src/app/core/shared/search/search-configuration.service.spec.ts +++ b/src/app/core/shared/search/search-configuration.service.spec.ts @@ -167,8 +167,8 @@ describe('SearchConfigurationService', () => { beforeEach(() => { service.getCurrentFixedFilter(); }); - it('should call getRouteParameterValue on the routeService with parameter name \'filter\'', () => { - expect((service as any).routeService.getRouteParameterValue).toHaveBeenCalledWith('filter'); + it('should call getRouteParameterValue on the routeService with parameter name \'fixedFilterQuery\'', () => { + expect((service as any).routeService.getRouteParameterValue).toHaveBeenCalledWith('fixedFilterQuery'); }); }); }); diff --git a/src/app/core/shared/search/search-configuration.service.ts b/src/app/core/shared/search/search-configuration.service.ts index 9ccfc5f320..8d77b2f095 100644 --- a/src/app/core/shared/search/search-configuration.service.ts +++ b/src/app/core/shared/search/search-configuration.service.ts @@ -1,5 +1,5 @@ -import { Injectable, OnDestroy } from '@angular/core'; -import { ActivatedRoute, Params } from '@angular/router'; +import {Injectable, OnDestroy} from '@angular/core'; +import {ActivatedRoute, Params} from '@angular/router'; import { BehaviorSubject, @@ -9,18 +9,17 @@ import { of as observableOf, Subscription } from 'rxjs'; -import { filter, flatMap, map, startWith, switchMap, tap } from 'rxjs/operators'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SearchOptions } from '../../../shared/search/search-options.model'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; -import { RouteService } from '../../../shared/services/route.service'; -import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util'; -import { SearchFilter } from '../../../shared/search/search-filter.model'; -import { SearchFixedFilterService } from './search-fixed-filter.service'; -import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; -import { RemoteData } from '../../data/remote-data'; -import { getSucceededRemoteData } from '../operators'; -import { DSpaceObjectType } from '../dspace-object-type.model'; +import {filter, map, startWith, tap} from 'rxjs/operators'; +import {PaginationComponentOptions} from '../../../shared/pagination/pagination-component-options.model'; +import {SearchOptions} from '../../../shared/search/search-options.model'; +import {PaginatedSearchOptions} from '../../../shared/search/paginated-search-options.model'; +import {RouteService} from '../../../shared/services/route.service'; +import {hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator} from '../../../shared/empty.util'; +import {SearchFilter} from '../../../shared/search/search-filter.model'; +import {RemoteData} from '../../data/remote-data'; +import {getSucceededRemoteData} from '../operators'; +import {DSpaceObjectType} from '../dspace-object-type.model'; +import {SortDirection, SortOptions} from '../../cache/models/sort-options.model'; /** * Service that performs all actions that have to do with the current search configuration @@ -83,7 +82,6 @@ export class SearchConfigurationService implements OnDestroy { * @param {ActivatedRoute} route */ constructor(protected routeService: RouteService, - protected fixedFilterService: SearchFixedFilterService, protected route: ActivatedRoute) { this.initDefaults(); @@ -208,10 +206,7 @@ export class SearchConfigurationService implements OnDestroy { * @returns {Observable} Emits the current fixed filter as a string */ getCurrentFixedFilter(): Observable { - return this.routeService.getRouteParameterValue('filter').pipe( - switchMap((f) => this.fixedFilterService.getQueryByFilterName(f)), - tap((t) => console.log(t)) - ); + return this.routeService.getRouteParameterValue('fixedFilterQuery').pipe(tap((t) => console.log(t))); } /** diff --git a/src/app/core/shared/search/search-filter.service.spec.ts b/src/app/core/shared/search/search-filter.service.spec.ts index 32f3c2dd4c..0a083ea6f9 100644 --- a/src/app/core/shared/search/search-filter.service.spec.ts +++ b/src/app/core/shared/search/search-filter.service.spec.ts @@ -265,7 +265,7 @@ describe('SearchFilterService', () => { }); describe('when the getCurrentFixedFilter method is called', () => { - const filter = 'filter'; + const filter = 'fixedFilterQuery'; beforeEach(() => { spyOn(routeServiceStub, 'getRouteParameterValue').and.returnValue(observableOf(filter)); diff --git a/src/app/core/shared/search/search-filter.service.ts b/src/app/core/shared/search/search-filter.service.ts index 24ce25aa45..22a8ae7c5b 100644 --- a/src/app/core/shared/search/search-filter.service.ts +++ b/src/app/core/shared/search/search-filter.service.ts @@ -1,7 +1,10 @@ import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; -import { mergeMap, map, distinctUntilChanged } from 'rxjs/operators'; +import { distinctUntilChanged, map, mergeMap } from 'rxjs/operators'; import { Injectable, InjectionToken } from '@angular/core'; -import { SearchFiltersState, SearchFilterState } from '../../../shared/search/search-filters/search-filter/search-filter.reducer'; +import { + SearchFiltersState, + SearchFilterState +} from '../../../shared/search/search-filters/search-filter/search-filter.reducer'; import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; import { SearchFilterCollapseAction, @@ -17,12 +20,7 @@ import { SearchFilterConfig } from '../../../shared/search/search-filter-config. import { RouteService } from '../../../shared/services/route.service'; import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SearchOptions } from '../../../shared/search/search-options.model'; -import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; -import { SearchFixedFilterService } from './search-fixed-filter.service'; import { Params } from '@angular/router'; -import * as postcss from 'postcss'; -import prefix = postcss.vendor.prefix; // const spy = create(); const filterStateSelector = (state: SearchFiltersState) => state.searchFilter; @@ -36,8 +34,7 @@ export const IN_PLACE_SEARCH: InjectionToken = new InjectionToken, - private routeService: RouteService, - private fixedFilterService: SearchFixedFilterService) { + private routeService: RouteService) { } /** @@ -122,8 +119,7 @@ export class SearchFilterService { * @returns {Observable} */ getCurrentFixedFilter(): Observable { - const filter: Observable = this.routeService.getRouteParameterValue('filter'); - return filter.pipe(mergeMap((f) => this.fixedFilterService.getQueryByFilterName(f))); + return this.routeService.getRouteParameterValue('fixedFilterQuery'); } /** diff --git a/src/app/core/shared/search/search-fixed-filter.service.spec.ts b/src/app/core/shared/search/search-fixed-filter.service.spec.ts deleted file mode 100644 index 3e3372f7eb..0000000000 --- a/src/app/core/shared/search/search-fixed-filter.service.spec.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { SearchFixedFilterService } from './search-fixed-filter.service'; -import { RouteService } from '../../../shared/services/route.service'; -import { RequestService } from '../../data/request.service'; -import { HALEndpointService } from '../hal-endpoint.service'; -import { of as observableOf } from 'rxjs'; -import { RequestEntry } from '../../data/request.reducer'; -import { FilteredDiscoveryQueryResponse, RestResponse } from '../../cache/response.models'; - -describe('SearchFixedFilterService', () => { - let service: SearchFixedFilterService; - - const filterQuery = 'filter:query'; - - const routeServiceStub = {} as RouteService; - const requestServiceStub = Object.assign({ - /* tslint:disable:no-empty */ - configure: () => {}, - /* tslint:enable:no-empty */ - generateRequestId: () => 'fake-id', - getByHref: () => observableOf(Object.assign(new RequestEntry(), { - response: new FilteredDiscoveryQueryResponse(filterQuery, 200, 'OK') - })) - }) as RequestService; - const halServiceStub = Object.assign(new HALEndpointService(requestServiceStub, undefined), { - getEndpoint: () => observableOf('fake-url') - }); - - beforeEach(() => { - service = new SearchFixedFilterService(routeServiceStub, requestServiceStub, halServiceStub); - }); - - describe('when getQueryByFilterName is called with a filterName', () => { - it('should return the filter query', () => { - service.getQueryByFilterName('filter').subscribe((query) => { - expect(query).toBe(filterQuery); - }); - }); - }); - - describe('when getQueryByFilterName is called without a filterName', () => { - it('should return undefined', () => { - service.getQueryByFilterName(undefined).subscribe((query) => { - expect(query).toBeUndefined(); - }); - }); - }); - - describe('when getQueryByRelations is called', () => { - const relationType = 'isRelationOf'; - const itemUUID = 'c5b277e6-2477-48bb-8993-356710c285f3'; - - it('should contain the relationType and itemUUID', () => { - const query = service.getQueryByRelations(relationType, itemUUID); - expect(query.length).toBeGreaterThan(relationType.length + itemUUID.length); - expect(query).toContain(relationType); - expect(query).toContain(itemUUID); - }); - }); -}); diff --git a/src/app/core/shared/search/search-fixed-filter.service.ts b/src/app/core/shared/search/search-fixed-filter.service.ts deleted file mode 100644 index 5c71770085..0000000000 --- a/src/app/core/shared/search/search-fixed-filter.service.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Injectable } from '@angular/core'; -import { flatMap, map, switchMap, tap } from 'rxjs/operators'; -import { Observable, of as observableOf } from 'rxjs'; -import { HALEndpointService } from '../hal-endpoint.service'; -import { GetRequest, RestRequest } from '../../data/request.models'; -import { RequestService } from '../../data/request.service'; -import { ResponseParsingService } from '../../data/parsing.service'; -import { GenericConstructor } from '../generic-constructor'; -import { FilteredDiscoveryPageResponseParsingService } from '../../data/filtered-discovery-page-response-parsing.service'; -import { hasValue } from '../../../shared/empty.util'; -import { configureRequest, getResponseFromEntry } from '../operators'; -import { RouteService } from '../../../shared/services/route.service'; -import { FilteredDiscoveryQueryResponse } from '../../cache/response.models'; - -/** - * Service for performing actions on the filtered-discovery-pages REST endpoint - */ -@Injectable() -export class SearchFixedFilterService { - private queryByFilterPath = 'filtered-discovery-pages'; - - constructor(private routeService: RouteService, - protected requestService: RequestService, - private halService: HALEndpointService) { - - } - - /** - * Get the filter query for a certain filter by name - * @param {string} filterName Name of the filter - * @returns {Observable} Filter query - */ - getQueryByFilterName(filterName: string): Observable { - if (hasValue(filterName)) { - const requestUuid = this.requestService.generateRequestId(); - const requestObs = this.halService.getEndpoint(this.queryByFilterPath).pipe( - map((url: string) => { - url += ('/' + filterName); - const request = new GetRequest(requestUuid, url); - return Object.assign(request, { - getResponseParser(): GenericConstructor { - return FilteredDiscoveryPageResponseParsingService; - } - }); - }), - configureRequest(this.requestService) - ); - - const requestEntryObs = requestObs.pipe( - switchMap((request: RestRequest) => this.requestService.getByHref(request.href)), - ); - const filterQuery = requestEntryObs.pipe( - getResponseFromEntry(), - map((response: FilteredDiscoveryQueryResponse) => - response.filterQuery - )); - return filterQuery; - } - return observableOf(undefined); - } - - /** - * Get the query for looking up items by relation type - * @param {string} relationType Relation type - * @param {string} itemUUID Item UUID - * @returns {string} Query - */ - getQueryByRelations(relationType: string, itemUUID: string): string { - return `query=relation.${relationType}:${itemUUID}`; - } - - /** - * Get the filter for a relation with the item's UUID - * @param relationType The type of relation e.g. 'isAuthorOfPublication' - * @param itemUUID The item's UUID - */ - getFilterByRelation(relationType: string, itemUUID: string): string { - return `f.${relationType}=${itemUUID}`; - } -} diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts index 1b62fab64d..0d7150389b 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts @@ -3,13 +3,13 @@ import { Observable , of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; -import { SearchFixedFilterService } from '../../../../core/shared/search/search-fixed-filter.service'; import { isNotEmpty } from '../../../../shared/empty.util'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; import { filterRelationsByTypeLabel, relationsToItems } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { getQueryByRelations } from '../../../../shared/utils/relation-query.utils'; @rendersItemType('Person', ItemViewMode.Full) @Component({ @@ -47,8 +47,7 @@ export class PersonComponent extends ItemComponent { fixedFilterQuery: string; constructor( - @Inject(ITEM) public item: Item, - private fixedFilterService: SearchFixedFilterService + @Inject(ITEM) public item: Item ) { super(item); } @@ -71,7 +70,7 @@ export class PersonComponent extends ItemComponent { relationsToItems(this.item.id) ); - this.fixedFilterQuery = this.fixedFilterService.getQueryByRelations('isAuthorOfPublication', this.item.id); + this.fixedFilterQuery = getQueryByRelations('isAuthorOfPublication', this.item.id); this.fixedFilter$ = observableOf('publication'); } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.ts index 8053d3d63b..0709891616 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup-relation/dynamic-lookup-relation-modal.component.ts @@ -52,9 +52,8 @@ export class DsDynamicLookupRelationModalComponent implements OnInit { ngOnInit(): void { this.resetRoute(); this.fixedFilter = RELATION_TYPE_FILTER_PREFIX + this.fieldName; + this.routeService.setParameter('fixedFilterQuery', this.fixedFilter); - ///Throw away, this is just a hack for now - this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe((t) => this.routeService.setParameter('filterQuery', this.fixedFilter)); this.selection = this.selectableListService.getSelectableList(this.listId).pipe(map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : [])); this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe( map((options) => { diff --git a/src/app/shared/search/search-filters/search-filters.component.ts b/src/app/shared/search/search-filters/search-filters.component.ts index 0915d19ea0..5e6584714d 100644 --- a/src/app/shared/search/search-filters/search-filters.component.ts +++ b/src/app/shared/search/search-filters/search-filters.component.ts @@ -56,7 +56,6 @@ export class SearchFiltersComponent implements OnInit { ngOnInit(): void { this.filters = this.searchConfigService.searchOptions.pipe( switchMap((options) => this.searchService.getConfig(options.scope, options.configuration).pipe(getSucceededRemoteData())), - obsLog('searchoptions') ); this.clearParams = this.searchConfigService.getCurrentFrontendFilters().pipe(map((filters) => { diff --git a/src/app/shared/services/route.effects.ts b/src/app/shared/services/route.effects.ts index d3a6381983..f0a9f7521c 100644 --- a/src/app/shared/services/route.effects.ts +++ b/src/app/shared/services/route.effects.ts @@ -1,10 +1,9 @@ -import { filter, map, pairwise } from 'rxjs/operators'; +import { map, tap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Actions, Effect, ofType } from '@ngrx/effects' -import * as fromRouter from '@ngrx/router-store'; -import { RouterNavigationAction } from '@ngrx/router-store'; -import { ResetRouteStateAction } from './route.actions'; -import { Router } from '@angular/router'; +import { ResetRouteStateAction, RouteActionTypes } from './route.actions'; +import { RouterActionTypes } from '../../core/router/router.actions'; +import { RouteService } from './route.service'; @Injectable() export class RouteEffects { @@ -14,19 +13,16 @@ export class RouteEffects { */ @Effect() routeChange$ = this.actions$ .pipe( - ofType(fromRouter.ROUTER_NAVIGATION), - pairwise(), - map((actions: RouterNavigationAction[]) => - actions.map((navigateAction) => { - const urlTree = this.router.parseUrl(navigateAction.payload.routerState.url); - return urlTree.root.children['primary'].segments.map(it => it.path).join('/'); - })), - filter((actions: string[]) => actions[0] !== actions[1]), - map(() => new ResetRouteStateAction()) + ofType(RouterActionTypes.ROUTE_UPDATE), + map(() => new ResetRouteStateAction()), ); - constructor(private actions$: Actions, private router: Router) { + @Effect({dispatch: false }) afterResetChange$ = this.actions$ + .pipe( + ofType(RouteActionTypes.RESET), + tap(() => this.service.setCurrentRouteInfo()), + ); + constructor(private actions$: Actions, private service: RouteService) { } - } diff --git a/src/app/shared/services/route.reducer.ts b/src/app/shared/services/route.reducer.ts index 3a4e957ab4..666e1d655a 100644 --- a/src/app/shared/services/route.reducer.ts +++ b/src/app/shared/services/route.reducer.ts @@ -73,6 +73,7 @@ function addParameter(state: RouteState, action: AddParameterAction | AddQueryPa const newSubstate = Object.assign({}, subState, { [action.payload.key]: newValues }); return Object.assign({}, state, { [paramType]: newSubstate }); } + /** * Set a route or query parameter in the store * @param state The current state @@ -80,7 +81,7 @@ function addParameter(state: RouteState, action: AddParameterAction | AddQueryPa * @param paramType The type of parameter to set: route or query parameter */ function setParameters(state: RouteState, action: SetParametersAction | SetQueryParametersAction, paramType: string): RouteState { - return Object.assign({}, state, { [paramType]: action.payload }); + return Object.assign({}, state, { [paramType]: { [action.payload.key]: action.payload.value } }); } /** @@ -91,6 +92,6 @@ function setParameters(state: RouteState, action: SetParametersAction | SetQuery */ function setParameter(state: RouteState, action: SetParameterAction | SetQueryParameterAction, paramType: string): RouteState { const subState = state[paramType]; - const newSubstate = Object.assign({}, subState, action.payload); + const newSubstate = Object.assign({}, subState, { [action.payload.key]: action.payload.value }); return Object.assign({}, state, { [paramType]: newSubstate }); } \ No newline at end of file diff --git a/src/app/shared/services/route.service.ts b/src/app/shared/services/route.service.ts index d008216301..e99d7245a8 100644 --- a/src/app/shared/services/route.service.ts +++ b/src/app/shared/services/route.service.ts @@ -1,4 +1,4 @@ -import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, take } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { ActivatedRoute, @@ -126,7 +126,7 @@ export class RouteService { } getRouteDataValue(datafield: string): Observable { - return this.route.data.pipe(map((data) => data[datafield]), distinctUntilChanged(),); + return this.route.data.pipe(map((data) => data[datafield]), distinctUntilChanged()); } /** @@ -198,6 +198,7 @@ export class RouteService { public setCurrentRouteInfo() { combineLatest(this.getRouteParams(), this.route.queryParams) + .pipe(take(1)) .subscribe( ([params, queryParams]: [Params, Params]) => { this.store.dispatch(new SetParametersAction(params)); diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 31164b691f..96dfb87321 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -160,7 +160,6 @@ import { SearchFacetSelectedOptionComponent } from './search/search-filters/sear import { SearchFacetRangeOptionComponent } from './search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component'; import { SearchSwitchConfigurationComponent } from './search/search-switch-configuration/search-switch-configuration.component'; import { SearchAuthorityFilterComponent } from './search/search-filters/search-filter/search-authority-filter/search-authority-filter.component'; -import { ConfigurationSearchPageComponent } from '../+search-page/configuration-search-page.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -304,7 +303,6 @@ const COMPONENTS = [ SearchFacetRangeOptionComponent, SearchSwitchConfigurationComponent, SearchAuthorityFilterComponent, - ConfigurationSearchPageComponent ]; const ENTRY_COMPONENTS = [ diff --git a/src/app/shared/utils/relation-query.utils.ts b/src/app/shared/utils/relation-query.utils.ts new file mode 100644 index 0000000000..8f3c8b5cfd --- /dev/null +++ b/src/app/shared/utils/relation-query.utils.ts @@ -0,0 +1,18 @@ +/** + * Get the query for looking up items by relation type + * @param {string} relationType Relation type + * @param {string} itemUUID Item UUID + * @returns {string} Query + */ +export function getQueryByRelations(relationType: string, itemUUID: string): string { + return `query=relation.${relationType}:${itemUUID}`; +} + +/** + * Get the filter for a relation with the item's UUID + * @param relationType The type of relation e.g. 'isAuthorOfPublication' + * @param itemUUID The item's UUID + */ +export function getFilterByRelation(relationType: string, itemUUID: string): string { + return `f.${relationType}=${itemUUID}`; +} \ No newline at end of file