diff --git a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts index 9199e010b885bf2b0614165c5b88e72da375580f..805839888419e28ecf8165dab62d1e63a5ce0d98 100644 --- a/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts +++ b/src/app/+collection-page/collection-item-mapper/collection-item-mapper.component.ts @@ -8,7 +8,7 @@ import { Collection } from '../../core/shared/collection.model'; import { SearchConfigurationService } from '../../+search-page/search-service/search-configuration.service'; import { PaginatedSearchOptions } from '../../+search-page/paginated-search-options.model'; import { PaginatedList } from '../../core/data/paginated-list'; -import { map, switchMap, take } from 'rxjs/operators'; +import { map, switchMap, take, tap } from 'rxjs/operators'; import { getSucceededRemoteData, toDSpaceObjectListRD } from '../../core/shared/operators'; import { SearchService } from '../../+search-page/search-service/search.service'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; @@ -20,6 +20,10 @@ import { TranslateService } from '@ngx-translate/core'; import { CollectionDataService } from '../../core/data/collection-data.service'; import { isNotEmpty } from '../../shared/empty.util'; import { RestResponse } from '../../core/cache/response.models'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { Actions, ofType } from '@ngrx/effects'; +import { IndexActionTypes } from '../../core/index/index.actions'; +import { RequestActionTypes } from '../../core/data/request.actions'; @Component({ selector: 'ds-collection-item-mapper', @@ -64,6 +68,8 @@ export class CollectionItemMapperComponent implements OnInit { */ defaultSortOptions: SortOptions = new SortOptions('dc.title', SortDirection.ASC); + shouldUpdate$: BehaviorSubject<boolean>; + constructor(private route: ActivatedRoute, private router: Router, private searchConfigService: SearchConfigurationService, @@ -86,25 +92,31 @@ export class CollectionItemMapperComponent implements OnInit { * TODO: When the API support it, fetch items excluding the collection's scope (currently fetches all items) */ loadItemLists() { + this.shouldUpdate$ = new BehaviorSubject<boolean>(true); const collectionAndOptions$ = observableCombineLatest( this.collectionRD$, - this.searchOptions$ + this.searchOptions$, + this.shouldUpdate$ ); this.collectionItemsRD$ = collectionAndOptions$.pipe( - switchMap(([collectionRD, options]) => { - return this.collectionDataService.getMappedItems(collectionRD.payload.id, Object.assign(options, { - sort: this.defaultSortOptions - })) + switchMap(([collectionRD, options, shouldUpdate]) => { + if (shouldUpdate) { + return this.collectionDataService.getMappedItems(collectionRD.payload.id, Object.assign(options, { + sort: this.defaultSortOptions + })) + } }) ); this.mappingItemsRD$ = collectionAndOptions$.pipe( - switchMap(([collectionRD, options]) => { - return this.searchService.search(Object.assign(new PaginatedSearchOptions(options), { - query: this.buildQuery(collectionRD.payload.id, options.query), - scope: undefined, - dsoType: DSpaceObjectType.ITEM, - sort: this.defaultSortOptions - })); + switchMap(([collectionRD, options, shouldUpdate]) => { + if (shouldUpdate) { + return this.searchService.search(Object.assign(new PaginatedSearchOptions(options), { + query: this.buildQuery(collectionRD.payload.id, options.query), + scope: undefined, + dsoType: DSpaceObjectType.ITEM, + sort: this.defaultSortOptions + })); + } }), toDSpaceObjectListRD() ); @@ -151,10 +163,12 @@ export class CollectionItemMapperComponent implements OnInit { this.notificationsService.error(head, content); }); } + this.shouldUpdate$.next(true); }); this.collectionRD$.pipe(take(1)).subscribe((collectionRD: RemoteData<Collection>) => { this.collectionDataService.clearMappingItemsRequests(collectionRD.payload.id); + this.searchService.clearDiscoveryRequests(); }); } diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index 275b0b3340d1a54e75afcdd37687452393dc612a..049e4b1542ab234591ce05fd8e2c4292faa2962b 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -7,7 +7,7 @@ import { Router, UrlSegmentGroup } from '@angular/router'; -import { map, switchMap, tap } from 'rxjs/operators'; +import { map, switchMap, take, tap } from 'rxjs/operators'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { FacetConfigSuccessResponse, @@ -47,6 +47,9 @@ import { CommunityDataService } from '../../core/data/community-data.service'; import { ViewMode } from '../../core/shared/view-mode.model'; import { ResourceType } from '../../core/shared/resource-type'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; +import { Store } from '@ngrx/store'; +import { IndexName, IndexState } from '../../core/index/index.reducer'; +import { RemoveFromIndexBySubstringAction } from '../../core/index/index.actions'; /** * Service that performs all general actions that have to do with the search page @@ -319,6 +322,12 @@ export class SearchService implements OnDestroy { return '/' + g.toString(); } + clearDiscoveryRequests() { + this.halService.getEndpoint(this.searchLinkPath).pipe(take(1)).subscribe((href: string) => { + this.requestService.removeByHrefSubstring(href); + }); + } + /** * Unsubscribe from the subscription */ diff --git a/src/app/core/cache/builders/remote-data-build.service.ts b/src/app/core/cache/builders/remote-data-build.service.ts index 52ec4382ae1f103bf89601eaa8972a31cc1fcab1..c22b63f618afcc568c4f19dc45cd09c4d4297f38 100644 --- a/src/app/core/cache/builders/remote-data-build.service.ts +++ b/src/app/core/cache/builders/remote-data-build.service.ts @@ -6,7 +6,7 @@ import { } from 'rxjs'; import { Injectable } from '@angular/core'; import { distinctUntilChanged, first, flatMap, map, startWith, switchMap } from 'rxjs/operators'; -import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../../shared/empty.util'; +import { hasValue, hasValueOperator, isEmpty, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util'; import { PaginatedList } from '../../data/paginated-list'; import { RemoteData } from '../../data/remote-data'; import { RemoteDataError } from '../../data/remote-data-error'; @@ -86,8 +86,8 @@ export class RemoteDataBuildService { toRemoteDataObservable<T>(requestEntry$: Observable<RequestEntry>, payload$: Observable<T>) { return observableCombineLatest(requestEntry$, payload$).pipe( map(([reqEntry, payload]) => { - const requestPending = hasValue(reqEntry.requestPending) ? reqEntry.requestPending : true; - const responsePending = hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false; + const requestPending = hasValue(reqEntry) && hasValue(reqEntry.requestPending) ? reqEntry.requestPending : true; + const responsePending = hasValue(reqEntry) && hasValue(reqEntry.responsePending) ? reqEntry.responsePending : false; let isSuccessful: boolean; let error: RemoteDataError; if (hasValue(reqEntry) && hasValue(reqEntry.response)) { diff --git a/src/app/core/data/collection-data.service.ts b/src/app/core/data/collection-data.service.ts index bc28ccc98c67748b9a924aef51bbb24d9a423a5e..e9ae5d38a541adc95cac7e7088ff6151f754740a 100644 --- a/src/app/core/data/collection-data.service.ts +++ b/src/app/core/data/collection-data.service.ts @@ -1,9 +1,9 @@ import { Injectable } from '@angular/core'; -import { MemoizedSelector, select, Store } from '@ngrx/store'; +import { Action, Store } from '@ngrx/store'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { NormalizedCollection } from '../cache/models/normalized-collection.model'; import { ObjectCacheService } from '../cache/object-cache.service'; -import { coreSelector, CoreState } from '../core.reducers'; +import { CoreState } from '../core.reducers'; import { Collection } from '../shared/collection.model'; import { ComColDataService } from './comcol-data.service'; import { CommunityDataService } from './community-data.service'; @@ -12,7 +12,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { Observable } from 'rxjs'; import { RemoteData } from './remote-data'; import { PaginatedList } from './paginated-list'; -import { distinctUntilChanged, map, mergeMap, switchMap, take } from 'rxjs/operators'; +import { distinctUntilChanged, map, take, tap } from 'rxjs/operators'; import { hasValue, isNotEmptyOperator } from '../../shared/empty.util'; import { GetRequest } from './request.models'; import { configureRequest } from '../shared/operators'; @@ -22,9 +22,8 @@ import { ResponseParsingService } from './parsing.service'; import { DSpaceObject } from '../shared/dspace-object.model'; import { DSOResponseParsingService } from './dso-response-parsing.service'; import { IndexName, IndexState } from '../index/index.reducer'; -import { RemoveFromIndexBySubstringAction } from '../index/index.actions'; -import { pathSelector } from '../shared/selectors'; -import { RequestState } from './request.reducer'; +import { IndexActionTypes, RemoveFromIndexBySubstringAction } from '../index/index.actions'; +import { Actions, ofType } from '@ngrx/effects'; @Injectable() export class CollectionDataService extends ComColDataService<NormalizedCollection, Collection> { @@ -50,6 +49,8 @@ export class CollectionDataService extends ComColDataService<NormalizedCollectio } getMappedItems(collectionId: string, searchOptions?: PaginatedSearchOptions): Observable<RemoteData<PaginatedList<DSpaceObject>>> { + const requestUuid = this.requestService.generateRequestId(); + const href$ = this.getMappingItemsEndpoint(collectionId).pipe( isNotEmptyOperator(), distinctUntilChanged(), @@ -58,7 +59,7 @@ export class CollectionDataService extends ComColDataService<NormalizedCollectio href$.pipe( map((endpoint: string) => { - const request = new GetRequest(this.requestService.generateRequestId(), endpoint); + const request = new GetRequest(requestUuid, endpoint); return Object.assign(request, { getResponseParser(): GenericConstructor<ResponseParsingService> { return DSOResponseParsingService; @@ -74,7 +75,6 @@ export class CollectionDataService extends ComColDataService<NormalizedCollectio clearMappingItemsRequests(collectionId: string) { this.getMappingItemsEndpoint(collectionId).pipe(take(1)).subscribe((href: string) => { this.requestService.removeByHrefSubstring(href); - this.indexStore.dispatch(new RemoveFromIndexBySubstringAction(IndexName.REQUEST, href)); }); } diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index 15dc01d03acd87c1d5ab4fb09021eeb4a0d95683..c1a46cde9a630c1dc736accaa66c1e17b779ecaf 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -1,5 +1,5 @@ -import { distinctUntilChanged, map, filter, switchMap } from 'rxjs/operators'; +import { distinctUntilChanged, map, filter, switchMap, tap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; @@ -21,6 +21,7 @@ import { configureRequest, filterSuccessfulResponses, getResponseFromEntry } fro import { RemoteData } from './remote-data'; import { PaginatedList } from './paginated-list'; import { Collection } from '../shared/collection.model'; +import { RequestEntry } from './request.reducer'; @Injectable() export class ItemDataService extends DataService<NormalizedItem, Item> { @@ -66,7 +67,7 @@ export class ItemDataService extends DataService<NormalizedItem, Item> { distinctUntilChanged(), map((endpointURL: string) => new DeleteRequest(this.requestService.generateRequestId(), endpointURL)), configureRequest(this.requestService), - switchMap((request: RestRequest) => this.requestService.getByHref(request.href)), + switchMap((request: RestRequest) => this.requestService.getByUUID(request.uuid)), getResponseFromEntry() ); } @@ -77,7 +78,7 @@ export class ItemDataService extends DataService<NormalizedItem, Item> { distinctUntilChanged(), map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL)), configureRequest(this.requestService), - switchMap((request: RestRequest) => this.requestService.getByHref(request.href)), + switchMap((request: RestRequest) => this.requestService.getByUUID(request.uuid)), getResponseFromEntry() ); } diff --git a/src/app/core/data/request.service.ts b/src/app/core/data/request.service.ts index a447df3051ef4fb45e3730d42b4ef87bee165b54..9e8f28e1b9804c9cc1e8257dd9eea5171d796b52 100644 --- a/src/app/core/data/request.service.ts +++ b/src/app/core/data/request.service.ts @@ -31,7 +31,7 @@ import { RequestEntry } from './request.reducer'; import { CommitSSBAction } from '../cache/server-sync-buffer.actions'; import { RestRequestMethod } from './rest-request-method'; import { getResponseFromEntry } from '../shared/operators'; -import { AddToIndexAction } from '../index/index.actions'; +import { AddToIndexAction, RemoveFromIndexBySubstringAction } from '../index/index.actions'; @Injectable() export class RequestService { @@ -39,7 +39,8 @@ export class RequestService { constructor(private objectCache: ObjectCacheService, private uuidService: UUIDService, - private store: Store<CoreState>) { + private store: Store<CoreState>, + private indexStore: Store<IndexState>) { } private entryFromUUIDSelector(uuid: string): MemoizedSelector<CoreState, RequestEntry> { @@ -138,22 +139,17 @@ export class RequestService { } } - removeByHref(href: string) { - this.store.pipe( - select(this.uuidFromHrefSelector(href)) - ).subscribe((uuid: string) => { - this.removeByUuid(uuid); - }); - } - removeByHrefSubstring(href: string) { this.store.pipe( - select(this.uuidsFromHrefSubstringSelector(pathSelector<CoreState, IndexState>(coreSelector, 'index'), IndexName.REQUEST, href)) + select(this.uuidsFromHrefSubstringSelector(pathSelector<CoreState, IndexState>(coreSelector, 'index'), IndexName.REQUEST, href)), + take(1) ).subscribe((uuids: string[]) => { for (const uuid of uuids) { this.removeByUuid(uuid); } }); + this.requestsOnTheirWayToTheStore = this.requestsOnTheirWayToTheStore.filter((reqHref: string) => reqHref.indexOf(href) < 0); + this.indexStore.dispatch(new RemoveFromIndexBySubstringAction(IndexName.REQUEST, href)); } removeByUuid(uuid: string) { diff --git a/src/app/shared/object-collection/object-collection.component.ts b/src/app/shared/object-collection/object-collection.component.ts index 4e46aeaeab8017fd77e252effb4161ac87236fdc..0018c55c7fc0215be32eac0344294d744d549c1b 100644 --- a/src/app/shared/object-collection/object-collection.component.ts +++ b/src/app/shared/object-collection/object-collection.component.ts @@ -77,7 +77,6 @@ export class ObjectCollectionComponent implements OnChanges, OnInit { this.currentMode = params.view; } }); - console.log(this.objects); } /**