diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 5b158f4a3c..b820fea354 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { Observable, Subscription } from 'rxjs'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; import { CollectionDataService } from '../core/data/collection-data.service'; @@ -19,7 +19,7 @@ import { PaginationComponentOptions } from '../shared/pagination/pagination-comp import { combineLatest, filter, first, flatMap, map } from 'rxjs/operators'; import { SearchService } from '../+search-page/search-service/search.service'; import { PaginatedSearchOptions } from '../+search-page/paginated-search-options.model'; -import { toDSpaceObjectListRD } from '../core/shared/operators'; +import { renderPageNotFoundOn404, toDSpaceObjectListRD } from '../core/shared/operators'; import { DSpaceObjectType } from '../core/shared/dspace-object-type.model'; @Component({ @@ -45,7 +45,8 @@ export class CollectionPageComponent implements OnInit, OnDestroy { private collectionDataService: CollectionDataService, private itemDataService: ItemDataService, private metadata: MetadataService, - private route: ActivatedRoute + private route: ActivatedRoute, + private router: Router ) { this.paginationConfig = new PaginationComponentOptions(); this.paginationConfig.id = 'collection-page-pagination'; @@ -56,7 +57,8 @@ export class CollectionPageComponent implements OnInit, OnDestroy { ngOnInit(): void { this.collectionRD$ = this.route.data.pipe( - map((data) => data.collection), + map((data) => data.collection as RemoteData), + renderPageNotFoundOn404(this.router), first() ); this.logoRD$ = this.collectionRD$.pipe( diff --git a/src/app/+collection-page/collection-page.resolver.ts b/src/app/+collection-page/collection-page.resolver.ts index d4835e2e14..d1c52e3383 100644 --- a/src/app/+collection-page/collection-page.resolver.ts +++ b/src/app/+collection-page/collection-page.resolver.ts @@ -4,7 +4,8 @@ import { Collection } from '../core/shared/collection.model'; import { Observable } from 'rxjs'; import { CollectionDataService } from '../core/data/collection-data.service'; import { RemoteData } from '../core/data/remote-data'; -import { getSucceededRemoteData } from '../core/shared/operators'; +import { find } from 'rxjs/operators'; +import { hasValue } from '../shared/empty.util'; /** * This class represents a resolver that requests a specific collection before the route is activated @@ -22,7 +23,7 @@ export class CollectionPageResolver implements Resolve> { */ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { return this.collectionService.findById(route.params.id).pipe( - getSucceededRemoteData() + find((RD) => hasValue(RD.error) || RD.hasSucceeded), ); } } diff --git a/src/app/+community-page/community-page.component.ts b/src/app/+community-page/community-page.component.ts index 2035faf988..4eb59a8b9e 100644 --- a/src/app/+community-page/community-page.component.ts +++ b/src/app/+community-page/community-page.component.ts @@ -1,6 +1,6 @@ import { mergeMap, filter, map } from 'rxjs/operators'; import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { Subscription, Observable } from 'rxjs'; import { CommunityDataService } from '../core/data/community-data.service'; @@ -13,6 +13,7 @@ import { MetadataService } from '../core/metadata/metadata.service'; import { fadeInOut } from '../shared/animations/fade'; import { hasValue } from '../shared/empty.util'; +import { renderPageNotFoundOn404 } from '../core/shared/operators'; @Component({ selector: 'ds-community-page', @@ -37,13 +38,17 @@ export class CommunityPageComponent implements OnInit { constructor( private communityDataService: CommunityDataService, private metadata: MetadataService, - private route: ActivatedRoute + private route: ActivatedRoute, + private router: Router ) { } ngOnInit(): void { - this.communityRD$ = this.route.data.pipe(map((data) => data.community)); + this.communityRD$ = this.route.data.pipe( + map((data) => data.community as RemoteData), + renderPageNotFoundOn404(this.router) + ); this.logoRD$ = this.communityRD$.pipe( map((rd: RemoteData) => rd.payload), filter((community: Community) => hasValue(community)), diff --git a/src/app/+community-page/community-page.resolver.ts b/src/app/+community-page/community-page.resolver.ts index a32fe78bc5..d8957b740b 100644 --- a/src/app/+community-page/community-page.resolver.ts +++ b/src/app/+community-page/community-page.resolver.ts @@ -2,9 +2,10 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; import { Observable } from 'rxjs'; import { RemoteData } from '../core/data/remote-data'; -import { getSucceededRemoteData } from '../core/shared/operators'; import { Community } from '../core/shared/community.model'; import { CommunityDataService } from '../core/data/community-data.service'; +import { find } from 'rxjs/operators'; +import { hasValue } from '../shared/empty.util'; /** * This class represents a resolver that requests a specific community before the route is activated @@ -22,7 +23,7 @@ export class CommunityPageResolver implements Resolve> { */ resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable> { return this.communityService.findById(route.params.id).pipe( - getSucceededRemoteData() + find((RD) => hasValue(RD.error) || RD.hasSucceeded), ); } } diff --git a/src/app/+item-page/simple/item-page.component.ts b/src/app/+item-page/simple/item-page.component.ts index aebd256943..3b24dfa174 100644 --- a/src/app/+item-page/simple/item-page.component.ts +++ b/src/app/+item-page/simple/item-page.component.ts @@ -15,6 +15,7 @@ import { MetadataService } from '../../core/metadata/metadata.service'; import { fadeInOut } from '../../shared/animations/fade'; import { hasValue } from '../../shared/empty.util'; import { ItemViewMode } from '../../shared/items/item-type-decorator'; +import { renderPageNotFoundOn404 } from '../../core/shared/operators'; /** * This component renders a simple item page. @@ -58,12 +59,10 @@ export class ItemPageComponent implements OnInit { ) { } ngOnInit(): void { - this.itemRD$ = this.route.data.pipe(map((data) => data.item)); - this.itemRD$.pipe(take(1)).subscribe((itemRD: RemoteData) => { - if (itemRD.hasFailed && itemRD.error.statusCode === 404) { - this.router.navigateByUrl('/404', { skipLocationChange: true }); - } - }); + this.itemRD$ = this.route.data.pipe( + map((data) => data.item as RemoteData), + renderPageNotFoundOn404(this.router) + ); this.metadataService.processRemoteData(this.itemRD$); this.thumbnail$ = this.itemRD$.pipe( map((rd: RemoteData) => rd.payload), diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index 29bb2f6b7d..8b85cc6458 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -1,5 +1,5 @@ import { Observable } from 'rxjs'; -import { filter, find, flatMap, map, tap } from 'rxjs/operators'; +import { filter, find, flatMap, map, take, tap } from 'rxjs/operators'; import { hasValue, hasValueOperator, isNotEmpty } from '../../shared/empty.util'; import { DSOSuccessResponse, RestResponse } from '../cache/response.models'; import { RemoteData } from '../data/remote-data'; @@ -10,6 +10,8 @@ import { BrowseDefinition } from './browse-definition.model'; import { DSpaceObject } from './dspace-object.model'; import { PaginatedList } from '../data/paginated-list'; import { SearchResult } from '../../+search-page/search-result.model'; +import { Item } from './item.model'; +import { Router } from '@angular/router'; /** * This file contains custom RxJS operators that can be used in multiple places @@ -62,6 +64,15 @@ export const getSucceededRemoteData = () => (source: Observable>): Observable> => source.pipe(find((rd: RemoteData) => rd.hasSucceeded)); +export const renderPageNotFoundOn404 = (router: Router) => + (source: Observable>): Observable> => + source.pipe( + tap((rd: RemoteData) => { + if (rd.hasFailed && rd.error.statusCode === 404) { + router.navigateByUrl('/404', { skipLocationChange: true }); + } + })); + export const getFinishedRemoteData = () => (source: Observable>): Observable> => source.pipe(find((rd: RemoteData) => !rd.isLoading)); diff --git a/src/app/shared/services/route.service.ts b/src/app/shared/services/route.service.ts index a5e6c5c47b..a94b7e56da 100644 --- a/src/app/shared/services/route.service.ts +++ b/src/app/shared/services/route.service.ts @@ -1,6 +1,12 @@ -import { distinctUntilChanged, map, mergeMap, filter } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, mergeMap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; -import { ActivatedRoute, NavigationEnd, Params, Router, RouterStateSnapshot, } from '@angular/router'; +import { + ActivatedRoute, + NavigationEnd, + Params, + Router, + RouterStateSnapshot, +} from '@angular/router'; import { Observable } from 'rxjs'; import { select, Store } from '@ngrx/store'; @@ -136,5 +142,4 @@ export class RouteService { map((history: string[]) => history[history.length - 2] || '') ); } - }