mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
73249: Fix issues with bitstream pagination on item pages.
This commit is contained in:
@@ -1,87 +1,87 @@
|
||||
<ds-metadata-field-wrapper [label]="label | translate">
|
||||
<div *ngVar="(originals$ | async)?.payload as originals">
|
||||
<h5 class="simple-view-element-header">{{"item.page.filesection.original.bundle" | translate}}</h5>
|
||||
<ds-pagination *ngIf="originals?.page?.length > 0"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
[paginationOptions]="originalOptions"
|
||||
[pageInfoState]="originals"
|
||||
[collectionSize]="originals?.totalElements"
|
||||
[disableRouteParameterUpdate]="true"
|
||||
(pageChange)="switchOriginalPage($event)">
|
||||
<div *ngIf="hasValuesInBundle(originals)">
|
||||
<h5 class="simple-view-element-header">{{"item.page.filesection.original.bundle" | translate}}</h5>
|
||||
<ds-pagination *ngIf="originals?.page?.length > 0"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
[paginationOptions]="originalOptions"
|
||||
[pageInfoState]="originals"
|
||||
[collectionSize]="originals?.totalElements"
|
||||
[disableRouteParameterUpdate]="true"
|
||||
(pageChange)="switchOriginalPage($event)">
|
||||
|
||||
|
||||
<div class="file-section row" *ngFor="let file of originals?.page;">
|
||||
<div class="col-3">
|
||||
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<dl class="row">
|
||||
<dt class="col-md-4">{{"item.page.filesection.name" | translate}}</dt>
|
||||
<dd class="col-md-8">{{file.name}}</dd>
|
||||
|
||||
<div class="file-section row" *ngFor="let file of originals?.page;">
|
||||
<div class="col-3">
|
||||
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
|
||||
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
|
||||
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</dd>
|
||||
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.description" | translate}}</dt>
|
||||
<dd class="col-md-8">{{file.firstMetadataValue("dc.description")}}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<ds-file-download-link [href]="file._links.content.href" [download]="file.name">
|
||||
{{"item.page.filesection.download" | translate}}
|
||||
</ds-file-download-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<dl class="row">
|
||||
<dt class="col-md-4">{{"item.page.filesection.name" | translate}}</dt>
|
||||
<dd class="col-md-8">{{file.name}}</dd>
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
|
||||
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</dd>
|
||||
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.description" | translate}}</dt>
|
||||
<dd class="col-md-8">{{file.firstMetadataValue("dc.description")}}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<ds-file-download-link [href]="file._links.content.href" [download]="file.name">
|
||||
{{"item.page.filesection.download" | translate}}
|
||||
</ds-file-download-link>
|
||||
</div>
|
||||
</div>
|
||||
</ds-pagination>
|
||||
</ds-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngVar="(licenses$ | async)?.payload as licenses">
|
||||
<h5 class="simple-view-element-header">{{"item.page.filesection.license.bundle" | translate}}</h5>
|
||||
<ds-pagination *ngIf="licenses?.page?.length > 0"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
[paginationOptions]="licenseOptions"
|
||||
[pageInfoState]="licenses"
|
||||
[collectionSize]="licenses?.totalElements"
|
||||
[disableRouteParameterUpdate]="true"
|
||||
(pageChange)="switchLicensePage($event)">
|
||||
<div *ngIf="hasValuesInBundle(licenses)">
|
||||
<h5 class="simple-view-element-header">{{"item.page.filesection.license.bundle" | translate}}</h5>
|
||||
<ds-pagination *ngIf="licenses?.page?.length > 0"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
[paginationOptions]="licenseOptions"
|
||||
[pageInfoState]="licenses"
|
||||
[collectionSize]="licenses?.totalElements"
|
||||
[disableRouteParameterUpdate]="true"
|
||||
(pageChange)="switchLicensePage($event)">
|
||||
|
||||
|
||||
<div class="file-section row" *ngFor="let file of licenses?.page;">
|
||||
<div class="col-3">
|
||||
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<dl class="row">
|
||||
<dt class="col-md-4">{{"item.page.filesection.name" | translate}}</dt>
|
||||
<dd class="col-md-8">{{file.name}}</dd>
|
||||
|
||||
<div class="file-section row" *ngFor="let file of licenses?.page;">
|
||||
<div class="col-3">
|
||||
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
|
||||
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</dd>
|
||||
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.description" | translate}}</dt>
|
||||
<dd class="col-md-8">{{file.firstMetadataValue("dc.description")}}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<ds-file-download-link [href]="file._links.content.href" [download]="file.name">
|
||||
{{"item.page.filesection.download" | translate}}
|
||||
</ds-file-download-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<dl class="row">
|
||||
<dt class="col-md-4">{{"item.page.filesection.name" | translate}}</dt>
|
||||
<dd class="col-md-8">{{file.name}}</dd>
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
|
||||
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</dd>
|
||||
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.description" | translate}}</dt>
|
||||
<dd class="col-md-8">{{file.firstMetadataValue("dc.description")}}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<ds-file-download-link [href]="file._links.content.href" [download]="file.name">
|
||||
{{"item.page.filesection.download" | translate}}
|
||||
</ds-file-download-link>
|
||||
</div>
|
||||
</div>
|
||||
</ds-pagination>
|
||||
</ds-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</ds-metadata-field-wrapper>
|
||||
|
@@ -14,6 +14,8 @@ import {Bitstream} from '../../../../core/shared/bitstream.model';
|
||||
import {of as observableOf} from 'rxjs';
|
||||
import {MockBitstreamFormat1} from '../../../../shared/mocks/item.mock';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||
|
||||
describe('FullFileSectionComponent', () => {
|
||||
let comp: FullFileSectionComponent;
|
||||
@@ -61,7 +63,8 @@ describe('FullFileSectionComponent', () => {
|
||||
}), BrowserAnimationsModule],
|
||||
declarations: [FullFileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
||||
providers: [
|
||||
{provide: BitstreamDataService, useValue: bitstreamDataService}
|
||||
{provide: BitstreamDataService, useValue: bitstreamDataService},
|
||||
{provide: NotificationsService, useValue: new NotificationsServiceStub()}
|
||||
],
|
||||
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
|
@@ -10,6 +10,10 @@ import { PaginationComponentOptions } from '../../../../shared/pagination/pagina
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
||||
import { tap } from 'rxjs/internal/operators/tap';
|
||||
|
||||
/**
|
||||
* This component renders the file section of the item
|
||||
@@ -31,14 +35,14 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
||||
licenses$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
||||
|
||||
pageSize = 5;
|
||||
originalOptions = Object.assign(new PaginationComponentOptions(),{
|
||||
originalOptions = Object.assign(new PaginationComponentOptions(), {
|
||||
id: 'original-bitstreams-options',
|
||||
currentPage: 1,
|
||||
pageSize: this.pageSize
|
||||
});
|
||||
originalCurrentPage$ = new BehaviorSubject<number>(1);
|
||||
|
||||
licenseOptions = Object.assign(new PaginationComponentOptions(),{
|
||||
licenseOptions = Object.assign(new PaginationComponentOptions(), {
|
||||
id: 'license-bitstreams-options',
|
||||
currentPage: 1,
|
||||
pageSize: this.pageSize
|
||||
@@ -46,9 +50,11 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
||||
licenseCurrentPage$ = new BehaviorSubject<number>(1);
|
||||
|
||||
constructor(
|
||||
bitstreamDataService: BitstreamDataService
|
||||
bitstreamDataService: BitstreamDataService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected translateService: TranslateService
|
||||
) {
|
||||
super(bitstreamDataService);
|
||||
super(bitstreamDataService, notificationsService, translateService);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -57,21 +63,33 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
||||
|
||||
initialize(): void {
|
||||
this.originals$ = this.originalCurrentPage$.pipe(
|
||||
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName(
|
||||
this.item,
|
||||
'ORIGINAL',
|
||||
{ elementsPerPage: this.pageSize, currentPage: pageNumber },
|
||||
followLink( 'format')
|
||||
))
|
||||
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName(
|
||||
this.item,
|
||||
'ORIGINAL',
|
||||
{elementsPerPage: this.pageSize, currentPage: pageNumber},
|
||||
followLink('format')
|
||||
)),
|
||||
tap((rd: RemoteData<PaginatedList<Bitstream>>) => {
|
||||
if (hasValue(rd.error)) {
|
||||
this.notificationsService.error(this.translateService.get('file-section.error.header'), `${rd.error.statusCode} ${rd.error.message}`);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
this.licenses$ = this.licenseCurrentPage$.pipe(
|
||||
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName(
|
||||
this.item,
|
||||
'LICENSE',
|
||||
{ elementsPerPage: this.pageSize, currentPage: pageNumber },
|
||||
followLink( 'format')
|
||||
))
|
||||
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName(
|
||||
this.item,
|
||||
'LICENSE',
|
||||
{elementsPerPage: this.pageSize, currentPage: pageNumber},
|
||||
followLink('format')
|
||||
)),
|
||||
tap((rd: RemoteData<PaginatedList<Bitstream>>) => {
|
||||
if (hasValue(rd.error)) {
|
||||
this.notificationsService.error(this.translateService.get('file-section.error.header'), `${rd.error.statusCode} ${rd.error.message}`);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
@@ -93,4 +111,9 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
||||
this.licenseOptions.currentPage = page;
|
||||
this.licenseCurrentPage$.next(page);
|
||||
}
|
||||
|
||||
hasValuesInBundle(bundle: PaginatedList<Bitstream>) {
|
||||
console.log(bundle, hasValue(bundle), hasValue(bundle) && !isEmpty(bundle.page));
|
||||
return hasValue(bundle) && !isEmpty(bundle.page);
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,8 @@ import {FileSizePipe} from '../../../../shared/utils/file-size-pipe';
|
||||
import {PageInfo} from '../../../../core/shared/page-info.model';
|
||||
import {MetadataFieldWrapperComponent} from '../../../field-components/metadata-field-wrapper/metadata-field-wrapper.component';
|
||||
import {createPaginatedList} from '../../../../shared/testing/utils.test';
|
||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||
|
||||
describe('FileSectionComponent', () => {
|
||||
let comp: FileSectionComponent;
|
||||
@@ -62,7 +64,8 @@ describe('FileSectionComponent', () => {
|
||||
}), BrowserAnimationsModule],
|
||||
declarations: [FileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
||||
providers: [
|
||||
{provide: BitstreamDataService, useValue: bitstreamDataService}
|
||||
{provide: BitstreamDataService, useValue: bitstreamDataService},
|
||||
{provide: NotificationsService, useValue: new NotificationsServiceStub()}
|
||||
],
|
||||
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
|
@@ -4,10 +4,12 @@ import { BitstreamDataService } from '../../../../core/data/bitstream-data.servi
|
||||
|
||||
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||
import { Item } from '../../../../core/shared/item.model';
|
||||
import { filter, takeWhile } from 'rxjs/operators';
|
||||
import { filter, take } from 'rxjs/operators';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { hasNoValue, hasValue } from '../../../../shared/empty.util';
|
||||
import { hasValue } from '../../../../shared/empty.util';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
/**
|
||||
* This component renders the file section of the item
|
||||
@@ -36,7 +38,9 @@ export class FileSectionComponent implements OnInit {
|
||||
pageSize = 5;
|
||||
|
||||
constructor(
|
||||
protected bitstreamDataService: BitstreamDataService
|
||||
protected bitstreamDataService: BitstreamDataService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected translateService: TranslateService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -58,14 +62,22 @@ export class FileSectionComponent implements OnInit {
|
||||
} else {
|
||||
this.currentPage++;
|
||||
}
|
||||
this.bitstreamDataService.findAllByItemAndBundleName(this.item, 'ORIGINAL', { currentPage: this.currentPage, elementsPerPage: this.pageSize }).pipe(
|
||||
filter((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => hasValue(bitstreamsRD)),
|
||||
takeWhile((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => hasNoValue(bitstreamsRD.payload) && hasNoValue(bitstreamsRD.error), true)
|
||||
this.bitstreamDataService.findAllByItemAndBundleName(this.item, 'ORIGINAL', {
|
||||
currentPage: this.currentPage,
|
||||
elementsPerPage: this.pageSize
|
||||
}).pipe(
|
||||
filter((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => hasValue(bitstreamsRD)),
|
||||
filter((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => hasValue(!bitstreamsRD.isLoading)),
|
||||
take(1),
|
||||
).subscribe((bitstreamsRD: RemoteData<PaginatedList<Bitstream>>) => {
|
||||
const current: Bitstream[] = this.bitstreams$.getValue();
|
||||
this.bitstreams$.next([...current, ...bitstreamsRD.payload.page]);
|
||||
this.isLoading = false;
|
||||
this.isLastPage = this.currentPage === bitstreamsRD.payload.totalPages;
|
||||
if (bitstreamsRD.error) {
|
||||
this.notificationsService.error(this.translateService.get('file-section.error.header'), `${bitstreamsRD.error.statusCode} ${bitstreamsRD.error.message}`);
|
||||
} else if (hasValue(bitstreamsRD.payload)) {
|
||||
const current: Bitstream[] = this.bitstreams$.getValue();
|
||||
this.bitstreams$.next([...current, ...bitstreamsRD.payload.page]);
|
||||
this.isLoading = false;
|
||||
this.isLastPage = this.currentPage === bitstreamsRD.payload.totalPages;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,8 @@ import { RestResponse } from '../cache/response.models';
|
||||
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
|
||||
import { configureRequest, getResponseFromEntry } from '../shared/operators';
|
||||
import { combineLatest as observableCombineLatest } from 'rxjs';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { PageInfo } from '../shared/page-info.model';
|
||||
|
||||
/**
|
||||
* A service to retrieve {@link Bitstream}s from the REST API
|
||||
@@ -165,8 +167,10 @@ export class BitstreamDataService extends DataService<Bitstream> {
|
||||
public findAllByItemAndBundleName(item: Item, bundleName: string, options?: FindListOptions, ...linksToFollow: Array<FollowLinkConfig<Bitstream>>): Observable<RemoteData<PaginatedList<Bitstream>>> {
|
||||
return this.bundleService.findByItemAndName(item, bundleName).pipe(
|
||||
switchMap((bundleRD: RemoteData<Bundle>) => {
|
||||
if (hasValue(bundleRD.payload)) {
|
||||
if (bundleRD.hasSucceeded && hasValue(bundleRD.payload)) {
|
||||
return this.findAllByBundle(bundleRD.payload, options, ...linksToFollow);
|
||||
} else if (!bundleRD.hasSucceeded && bundleRD.error.statusCode === 404) {
|
||||
return createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), []))
|
||||
} else {
|
||||
return [bundleRD as any];
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import { FindListOptions, GetRequest } from './request.models';
|
||||
import { RequestService } from './request.service';
|
||||
import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
|
||||
import { Bitstream } from '../shared/bitstream.model';
|
||||
import { RemoteDataError } from './remote-data-error';
|
||||
|
||||
/**
|
||||
* A service to retrieve {@link Bundle}s from the REST API
|
||||
@@ -71,13 +72,17 @@ export class BundleDataService extends DataService<Bundle> {
|
||||
if (hasValue(rd.payload) && hasValue(rd.payload.page)) {
|
||||
const matchingBundle = rd.payload.page.find((bundle: Bundle) =>
|
||||
bundle.name === bundleName);
|
||||
return new RemoteData(
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
undefined,
|
||||
matchingBundle
|
||||
);
|
||||
if (hasValue(matchingBundle)) {
|
||||
return new RemoteData(
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
undefined,
|
||||
matchingBundle
|
||||
);
|
||||
} else {
|
||||
return new RemoteData(false, false, false, new RemoteDataError(404, 'Not found', `The bundle with name ${bundleName} was not found.` ))
|
||||
}
|
||||
} else {
|
||||
return rd as any;
|
||||
}
|
||||
|
Reference in New Issue
Block a user