collections.component.ts (dspace-angular-dspace-7.0) | : | collections.component.ts (dspace-angular-dspace-7.1) | ||
---|---|---|---|---|
import { Component, Input, OnInit } from '@angular/core'; | import { Component, Input, OnInit } from '@angular/core'; | |||
import { Observable } from 'rxjs'; | import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; | |||
import { map } from 'rxjs/operators'; | import {map, scan, startWith, switchMap, tap, withLatestFrom} from 'rxjs/operato | |||
rs'; | ||||
import { CollectionDataService } from '../../../core/data/collection-data.servic e'; | import { CollectionDataService } from '../../../core/data/collection-data.servic e'; | |||
import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated- | import { PaginatedList } from '../../../core/data/paginated-list.model'; | |||
list.model'; | ||||
import { RemoteData } from '../../../core/data/remote-data'; | ||||
import { Collection } from '../../../core/shared/collection.model'; | import { Collection } from '../../../core/shared/collection.model'; | |||
import { Item } from '../../../core/shared/item.model'; | import { Item } from '../../../core/shared/item.model'; | |||
import { PageInfo } from '../../../core/shared/page-info.model'; | ||||
import { hasValue } from '../../../shared/empty.util'; | import { hasValue } from '../../../shared/empty.util'; | |||
import { FindListOptions } from '../../../core/data/request.models'; | ||||
import { | ||||
getAllCompletedRemoteData, | ||||
getAllSucceededRemoteDataPayload, | ||||
getFirstSucceededRemoteDataPayload, | ||||
getPaginatedListPayload, | ||||
} from '../../../core/shared/operators'; | ||||
/** | /** | |||
* This component renders the parent collections section of the item | * This component renders the parent collections section of the item | |||
* inside a 'ds-metadata-field-wrapper' component. | * inside a 'ds-metadata-field-wrapper' component. | |||
*/ | */ | |||
@Component({ | @Component({ | |||
selector: 'ds-item-page-collections', | selector: 'ds-item-page-collections', | |||
templateUrl: './collections.component.html' | templateUrl: './collections.component.html' | |||
}) | }) | |||
export class CollectionsComponent implements OnInit { | export class CollectionsComponent implements OnInit { | |||
@Input() item: Item; | @Input() item: Item; | |||
label = 'item.page.collections'; | label = 'item.page.collections'; | |||
separator = '<br/>'; | separator = '<br/>'; | |||
collectionsRD$: Observable<RemoteData<PaginatedList<Collection>>>; | /** | |||
* Amount of mapped collections that should be fetched at once. | ||||
*/ | ||||
pageSize = 5; | ||||
/** | ||||
* Last page of the mapped collections that has been fetched. | ||||
*/ | ||||
lastPage$: BehaviorSubject<number> = new BehaviorSubject<number>(0); | ||||
/** | ||||
* Push an event to this observable to fetch the next page of mapped collectio | ||||
ns. | ||||
* Because this observable is a behavior subject, the first page will be reque | ||||
sted | ||||
* immediately after subscription. | ||||
*/ | ||||
loadMore$: BehaviorSubject<void> = new BehaviorSubject(undefined); | ||||
/** | ||||
* Whether or not a page of mapped collections is currently being loaded. | ||||
*/ | ||||
isLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true); | ||||
/** | ||||
* Whether or not more pages of mapped collections are available. | ||||
*/ | ||||
hasMore$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true); | ||||
/** | ||||
* All collections that have been retrieved so far. This includes the owning c | ||||
ollection, | ||||
* as well as any number of pages of mapped collections. | ||||
*/ | ||||
collections$: Observable<Collection[]>; | ||||
constructor(private cds: CollectionDataService) { | constructor(private cds: CollectionDataService) { | |||
} | } | |||
ngOnInit(): void { | ngOnInit(): void { | |||
// this.collections = this.item.parents.payload; | const owningCollection$: Observable<Collection> = this.cds.findOwningCollect | |||
ionFor(this.item).pipe( | ||||
getFirstSucceededRemoteDataPayload(), | ||||
startWith(null as Collection), | ||||
); | ||||
const mappedCollections$: Observable<Collection[]> = this.loadMore$.pipe( | ||||
// update isLoading$ | ||||
tap(() => this.isLoading$.next(true)), | ||||
// request next batch of mapped collections | ||||
withLatestFrom(this.lastPage$), | ||||
switchMap(([_, lastPage]: [void, number]) => { | ||||
return this.cds.findMappedCollectionsFor(this.item, Object.assign(new Fi | ||||
ndListOptions(), { | ||||
elementsPerPage: this.pageSize, | ||||
currentPage: lastPage + 1, | ||||
})); | ||||
}), | ||||
getAllCompletedRemoteData<PaginatedList<Collection>>(), | ||||
// update isLoading$ | ||||
tap(() => this.isLoading$.next(false)), | ||||
getAllSucceededRemoteDataPayload(), | ||||
// update hasMore$ | ||||
tap((response: PaginatedList<Collection>) => this.hasMore$.next(response.c | ||||
urrentPage < response.totalPages)), | ||||
// TODO: this should use parents, but the collections | // update lastPage$ | |||
// for an Item aren't returned by the REST API yet, | tap((response: PaginatedList<Collection>) => this.lastPage$.next(response. | |||
// only the owning collection | currentPage)), | |||
this.collectionsRD$ = this.cds.findOwningCollectionFor(this.item).pipe( | ||||
map((rd: RemoteData<Collection>) => { | getPaginatedListPayload<Collection>(), | |||
if (hasValue(rd.payload)) { | ||||
return new RemoteData( | // add current batch to list of collections | |||
rd.timeCompleted, | scan((prev: Collection[], current: Collection[]) => [...prev, ...current], | |||
rd.msToLive, | []), | |||
rd.lastUpdated, | ||||
rd.state, | startWith([]), | |||
rd.errorMessage, | ) as Observable<Collection[]>; | |||
buildPaginatedList({ | ||||
elementsPerPage: 10, | this.collections$ = combineLatest([owningCollection$, mappedCollections$]).p | |||
totalPages: 1, | ipe( | |||
currentPage: 1, | map(([owningCollection, mappedCollections]: [Collection, Collection[]]) => | |||
totalElements: 1, | { | |||
_links: { | return [owningCollection, ...mappedCollections].filter(collection => has | |||
self: rd.payload._links.self | Value(collection)); | |||
} | }), | |||
} as PageInfo, [rd.payload]), | ||||
rd.statusCode | ||||
); | ||||
} else { | ||||
return rd as any; | ||||
} | ||||
}) | ||||
); | ); | |||
} | } | |||
handleLoadMore() { | ||||
this.loadMore$.next(); | ||||
} | ||||
} | } | |||
End of changes. 8 change blocks. | ||||
35 lines changed or deleted | 101 lines changed or added |