mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge pull request #838 from atmire/file-pagination-simple-and-full-item-pages
File pagination simple and full item pages
This commit is contained in:
@@ -1,29 +1,87 @@
|
||||
<ds-metadata-field-wrapper [label]="label | translate">
|
||||
<div class="file-section row" *ngFor="let file of (bitstreams$ | async); let last=last;">
|
||||
<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>
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
|
||||
<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)">
|
||||
|
||||
|
||||
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
|
||||
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</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>
|
||||
</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.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>
|
||||
<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>
|
||||
</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 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>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
</ds-metadata-field-wrapper>
|
||||
|
@@ -0,0 +1,117 @@
|
||||
import {FullFileSectionComponent} from './full-file-section.component';
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {createSuccessfulRemoteDataObject$} from '../../../../shared/remote-data.utils';
|
||||
import {createPaginatedList} from '../../../../shared/testing/utils.test';
|
||||
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
|
||||
import {TranslateLoaderMock} from '../../../../shared/mocks/translate-loader.mock';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {VarDirective} from '../../../../shared/utils/var.directive';
|
||||
import {FileSizePipe} from '../../../../shared/utils/file-size-pipe';
|
||||
import {MetadataFieldWrapperComponent} from '../../../field-components/metadata-field-wrapper/metadata-field-wrapper.component';
|
||||
import {BitstreamDataService} from '../../../../core/data/bitstream-data.service';
|
||||
import {NO_ERRORS_SCHEMA} from '@angular/core';
|
||||
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';
|
||||
|
||||
describe('FullFileSectionComponent', () => {
|
||||
let comp: FullFileSectionComponent;
|
||||
let fixture: ComponentFixture<FullFileSectionComponent>;
|
||||
|
||||
const mockBitstream: Bitstream = Object.assign(new Bitstream(),
|
||||
{
|
||||
sizeBytes: 10201,
|
||||
content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content',
|
||||
format: observableOf(MockBitstreamFormat1),
|
||||
bundleName: 'ORIGINAL',
|
||||
_links: {
|
||||
self: {
|
||||
href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713'
|
||||
},
|
||||
content: {
|
||||
href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content'
|
||||
}
|
||||
},
|
||||
id: 'cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
||||
uuid: 'cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
||||
type: 'bitstream',
|
||||
metadata: {
|
||||
'dc.title': [
|
||||
{
|
||||
language: null,
|
||||
value: 'test_word.docx'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const bitstreamDataService = jasmine.createSpyObj('bitstreamDataService', {
|
||||
findAllByItemAndBundleName: createSuccessfulRemoteDataObject$(createPaginatedList([mockBitstream, mockBitstream, mockBitstream]))
|
||||
});
|
||||
|
||||
beforeEach(async(() => {
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderMock
|
||||
}
|
||||
}), BrowserAnimationsModule],
|
||||
declarations: [FullFileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
||||
providers: [
|
||||
{provide: BitstreamDataService, useValue: bitstreamDataService}
|
||||
],
|
||||
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(async(() => {
|
||||
fixture = TestBed.createComponent(FullFileSectionComponent);
|
||||
comp = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
describe('when the full file section gets loaded with bitstreams available', () => {
|
||||
it ('should contain a list with bitstreams', () => {
|
||||
const fileSection = fixture.debugElement.queryAll(By.css('.file-section'));
|
||||
expect(fileSection.length).toEqual(6);
|
||||
});
|
||||
|
||||
describe('when we press the pageChange button for original bundle', () => {
|
||||
beforeEach(() => {
|
||||
comp.switchOriginalPage(2);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it ('should give the value to the currentpage', () => {
|
||||
expect(comp.originalOptions.currentPage).toBe(2);
|
||||
})
|
||||
it ('should call the next function on the originalCurrentPage', (done) => {
|
||||
comp.originalCurrentPage$.subscribe((event) => {
|
||||
expect(event).toEqual(2);
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when we press the pageChange button for license bundle', () => {
|
||||
beforeEach(() => {
|
||||
comp.switchLicensePage(2);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it ('should give the value to the currentpage', () => {
|
||||
expect(comp.licenseOptions.currentPage).toBe(2);
|
||||
})
|
||||
it ('should call the next function on the licenseCurrentPage', (done) => {
|
||||
comp.licenseCurrentPage$.subscribe((event) => {
|
||||
expect(event).toEqual(2);
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@@ -1,13 +1,15 @@
|
||||
import { Component, Injector, Input, OnInit } from '@angular/core';
|
||||
import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||
|
||||
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||
import { Item } from '../../../../core/shared/item.model';
|
||||
import { getFirstSucceededRemoteListPayload } from '../../../../core/shared/operators';
|
||||
import { followLink } from '../../../../shared/utils/follow-link-config.model';
|
||||
import { FileSectionComponent } from '../../../simple/field-components/file-section/file-section.component';
|
||||
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
|
||||
/**
|
||||
* This component renders the file section of the item
|
||||
@@ -25,7 +27,23 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
||||
|
||||
label: string;
|
||||
|
||||
bitstreams$: Observable<Bitstream[]>;
|
||||
originals$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
||||
licenses$: Observable<RemoteData<PaginatedList<Bitstream>>>;
|
||||
|
||||
pageSize = 5;
|
||||
originalOptions = Object.assign(new PaginationComponentOptions(),{
|
||||
id: 'original-bitstreams-options',
|
||||
currentPage: 1,
|
||||
pageSize: this.pageSize
|
||||
});
|
||||
originalCurrentPage$ = new BehaviorSubject<number>(1);
|
||||
|
||||
licenseOptions = Object.assign(new PaginationComponentOptions(),{
|
||||
id: 'license-bitstreams-options',
|
||||
currentPage: 1,
|
||||
pageSize: this.pageSize
|
||||
});
|
||||
licenseCurrentPage$ = new BehaviorSubject<number>(1);
|
||||
|
||||
constructor(
|
||||
bitstreamDataService: BitstreamDataService
|
||||
@@ -34,40 +52,45 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize(): void {
|
||||
// TODO pagination
|
||||
const originals$ = this.bitstreamDataService.findAllByItemAndBundleName(
|
||||
this.item,
|
||||
'ORIGINAL',
|
||||
{ elementsPerPage: Number.MAX_SAFE_INTEGER },
|
||||
followLink( 'format')
|
||||
).pipe(
|
||||
getFirstSucceededRemoteListPayload(),
|
||||
startWith([])
|
||||
this.originals$ = this.originalCurrentPage$.pipe(
|
||||
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName(
|
||||
this.item,
|
||||
'ORIGINAL',
|
||||
{ elementsPerPage: this.pageSize, currentPage: pageNumber },
|
||||
followLink( 'format')
|
||||
))
|
||||
);
|
||||
const licenses$ = this.bitstreamDataService.findAllByItemAndBundleName(
|
||||
this.item,
|
||||
'LICENSE',
|
||||
{ elementsPerPage: Number.MAX_SAFE_INTEGER },
|
||||
followLink( 'format')
|
||||
).pipe(
|
||||
getFirstSucceededRemoteListPayload(),
|
||||
startWith([])
|
||||
);
|
||||
this.bitstreams$ = observableCombineLatest(originals$, licenses$).pipe(
|
||||
map(([o, l]) => [...o, ...l]),
|
||||
map((files: Bitstream[]) =>
|
||||
files.map(
|
||||
(original) => {
|
||||
original.thumbnail = this.bitstreamDataService.getMatchingThumbnail(this.item, original);
|
||||
return original;
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
this.licenses$ = this.licenseCurrentPage$.pipe(
|
||||
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName(
|
||||
this.item,
|
||||
'LICENSE',
|
||||
{ elementsPerPage: this.pageSize, currentPage: pageNumber },
|
||||
followLink( 'format')
|
||||
))
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current page for the original bundle bitstreams
|
||||
* @param page
|
||||
*/
|
||||
switchOriginalPage(page: number) {
|
||||
this.originalOptions.currentPage = page;
|
||||
this.originalCurrentPage$.next(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current page for the license bundle bitstreams
|
||||
* @param page
|
||||
*/
|
||||
switchLicensePage(page: number) {
|
||||
this.licenseOptions.currentPage = page;
|
||||
this.licenseCurrentPage$.next(page);
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,13 @@
|
||||
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
|
||||
<span *ngIf="!last" innerHTML="{{separator}}"></span>
|
||||
</ds-file-download-link>
|
||||
<ds-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-loading>
|
||||
<div *ngIf="!isLastPage" class="mt-1" id="view-more">
|
||||
<a class="bitstream-view-more btn btn-outline-secondary btn-sm" [routerLink]="" (click)="getNextPage()">{{'item.page.bitstreams.view-more' | translate}}</a>
|
||||
</div>
|
||||
<div *ngIf="isLastPage && currentPage != 1" class="mt-1" id="collapse">
|
||||
<a class="bitstream-collapse btn btn-outline-secondary btn-sm" [routerLink]="" (click)="currentPage = undefined; getNextPage();">{{'item.page.bitstreams.collapse' | translate}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</ds-metadata-field-wrapper>
|
||||
</ng-container>
|
||||
|
@@ -0,0 +1,169 @@
|
||||
import {FileSectionComponent} from './file-section.component';
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
|
||||
import {TranslateLoaderMock} from '../../../../shared/mocks/translate-loader.mock';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {VarDirective} from '../../../../shared/utils/var.directive';
|
||||
import {NO_ERRORS_SCHEMA} from '@angular/core';
|
||||
import {BitstreamDataService} from '../../../../core/data/bitstream-data.service';
|
||||
import {createSuccessfulRemoteDataObject$} from '../../../../shared/remote-data.utils';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {Bitstream} from '../../../../core/shared/bitstream.model';
|
||||
import {of as observableOf} from 'rxjs';
|
||||
import {MockBitstreamFormat1} from '../../../../shared/mocks/item.mock';
|
||||
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';
|
||||
|
||||
describe('FileSectionComponent', () => {
|
||||
let comp: FileSectionComponent;
|
||||
let fixture: ComponentFixture<FileSectionComponent>;
|
||||
|
||||
const bitstreamDataService = jasmine.createSpyObj('bitstreamDataService', {
|
||||
findAllByItemAndBundleName: createSuccessfulRemoteDataObject$(createPaginatedList([]))
|
||||
});
|
||||
|
||||
const mockBitstream: Bitstream = Object.assign(new Bitstream(),
|
||||
{
|
||||
sizeBytes: 10201,
|
||||
content: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content',
|
||||
format: observableOf(MockBitstreamFormat1),
|
||||
bundleName: 'ORIGINAL',
|
||||
_links: {
|
||||
self: {
|
||||
href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713'
|
||||
},
|
||||
content: {
|
||||
href: 'https://dspace7.4science.it/dspace-spring-rest/api/core/bitstreams/cf9b0c8e-a1eb-4b65-afd0-567366448713/content'
|
||||
}
|
||||
},
|
||||
id: 'cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
||||
uuid: 'cf9b0c8e-a1eb-4b65-afd0-567366448713',
|
||||
type: 'bitstream',
|
||||
metadata: {
|
||||
'dc.title': [
|
||||
{
|
||||
language: null,
|
||||
value: 'test_word.docx'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(async(() => {
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderMock
|
||||
}
|
||||
}), BrowserAnimationsModule],
|
||||
declarations: [FileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
||||
providers: [
|
||||
{provide: BitstreamDataService, useValue: bitstreamDataService}
|
||||
],
|
||||
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(async(() => {
|
||||
fixture = TestBed.createComponent(FileSectionComponent);
|
||||
comp = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
describe('when the bitstreams are loading', () => {
|
||||
beforeEach(() => {
|
||||
comp.bitstreams$.next([mockBitstream]);
|
||||
comp.isLoading = true;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should display a loading component', () => {
|
||||
const loading = fixture.debugElement.query(By.css('ds-loading'));
|
||||
expect(loading.nativeElement).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the "Show more" button is clicked', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
comp.bitstreams$.next([mockBitstream]);
|
||||
comp.currentPage = 1;
|
||||
comp.isLastPage = false;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should call the service to retrieve more bitstreams', () => {
|
||||
const viewMore = fixture.debugElement.query(By.css('.bitstream-view-more'));
|
||||
viewMore.triggerEventHandler('click', null);
|
||||
expect(bitstreamDataService.findAllByItemAndBundleName).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('one bitstream should be on the page', () => {
|
||||
const viewMore = fixture.debugElement.query(By.css('.bitstream-view-more'));
|
||||
viewMore.triggerEventHandler('click', null);
|
||||
const fileDownloadLink = fixture.debugElement.queryAll(By.css('ds-file-download-link'));
|
||||
expect(fileDownloadLink.length).toEqual(1);
|
||||
})
|
||||
|
||||
describe('when it is then clicked again', () => {
|
||||
beforeEach(() => {
|
||||
bitstreamDataService.findAllByItemAndBundleName.and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList([mockBitstream])));
|
||||
const viewMore = fixture.debugElement.query(By.css('.bitstream-view-more'));
|
||||
viewMore.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
})
|
||||
it('should contain another bitstream', () => {
|
||||
const fileDownloadLink = fixture.debugElement.queryAll(By.css('ds-file-download-link'));
|
||||
expect(fileDownloadLink.length).toEqual(2);
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
describe('when its the last page of bitstreams', () => {
|
||||
beforeEach(() => {
|
||||
comp.bitstreams$.next([mockBitstream]);
|
||||
comp.isLastPage = true;
|
||||
comp.currentPage = 2;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should not contain a view more link', () => {
|
||||
const viewMore = fixture.debugElement.query(By.css('.bitstream-view-more'));
|
||||
expect(viewMore).toBeNull();
|
||||
})
|
||||
|
||||
it('should contain a view less link', () => {
|
||||
const viewLess = fixture.debugElement.query(By.css('.bitstream-collapse'));
|
||||
expect(viewLess).toBeDefined();
|
||||
})
|
||||
|
||||
it('clicking on the view less link should reset the pages and call getNextPage()', () => {
|
||||
const pageInfo = Object.assign(new PageInfo(), {
|
||||
elementsPerPage: 3,
|
||||
totalElements: 5,
|
||||
totalPages: 2,
|
||||
currentPage: 1,
|
||||
_links: {
|
||||
self: {href: 'https://rest.api/core/bitstreams/'},
|
||||
next: {href: 'https://rest.api/core/bitstreams?page=2'}
|
||||
}
|
||||
});
|
||||
const PaginatedList = Object.assign(createPaginatedList([mockBitstream]), {
|
||||
pageInfo: pageInfo
|
||||
});
|
||||
bitstreamDataService.findAllByItemAndBundleName.and.returnValue(createSuccessfulRemoteDataObject$(PaginatedList));
|
||||
const viewLess = fixture.debugElement.query(By.css('.bitstream-collapse'));
|
||||
viewLess.triggerEventHandler('click', null);
|
||||
expect(bitstreamDataService.findAllByItemAndBundleName).toHaveBeenCalled();
|
||||
expect(comp.currentPage).toBe(1);
|
||||
expect(comp.isLastPage).toBeFalse();
|
||||
})
|
||||
|
||||
})
|
||||
})
|
@@ -1,10 +1,13 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||
|
||||
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||
import { Item } from '../../../../core/shared/item.model';
|
||||
import { getFirstSucceededRemoteListPayload } from '../../../../core/shared/operators';
|
||||
import { filter, takeWhile } from 'rxjs/operators';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { hasNoValue, hasValue } from '../../../../shared/empty.util';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||
|
||||
/**
|
||||
* This component renders the file section of the item
|
||||
@@ -22,7 +25,15 @@ export class FileSectionComponent implements OnInit {
|
||||
|
||||
separator = '<br/>';
|
||||
|
||||
bitstreams$: Observable<Bitstream[]>;
|
||||
bitstreams$: BehaviorSubject<Bitstream[]>;
|
||||
|
||||
currentPage: number;
|
||||
|
||||
isLoading: boolean;
|
||||
|
||||
isLastPage: boolean;
|
||||
|
||||
pageSize = 5;
|
||||
|
||||
constructor(
|
||||
protected bitstreamDataService: BitstreamDataService
|
||||
@@ -30,13 +41,31 @@ export class FileSectionComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initialize();
|
||||
this.getNextPage();
|
||||
}
|
||||
|
||||
initialize(): void {
|
||||
this.bitstreams$ = this.bitstreamDataService.findAllByItemAndBundleName(this.item, 'ORIGINAL').pipe(
|
||||
getFirstSucceededRemoteListPayload()
|
||||
);
|
||||
/**
|
||||
* This method will retrieve the next page of Bitstreams from the external BitstreamDataService call.
|
||||
* It'll retrieve the currentPage from the class variables and it'll add the next page of bitstreams with the
|
||||
* already existing one.
|
||||
* If the currentPage variable is undefined, we'll set it to 1 and retrieve the first page of Bitstreams
|
||||
*/
|
||||
getNextPage(): void {
|
||||
this.isLoading = true;
|
||||
if (this.currentPage === undefined) {
|
||||
this.currentPage = 1;
|
||||
this.bitstreams$ = new BehaviorSubject([]);
|
||||
} 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)
|
||||
).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;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -139,8 +139,8 @@ export class RemoteDataBuildService {
|
||||
const pageInfo$ = requestEntry$.pipe(
|
||||
filterSuccessfulResponses(),
|
||||
map((response: DSOSuccessResponse) => {
|
||||
if (hasValue((response as DSOSuccessResponse).pageInfo)) {
|
||||
return (response as DSOSuccessResponse).pageInfo;
|
||||
if (hasValue(response.pageInfo)) {
|
||||
return Object.assign(new PageInfo(), response.pageInfo);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@@ -1600,6 +1600,13 @@
|
||||
|
||||
"item.page.uri": "URI",
|
||||
|
||||
"item.page.bitstreams.view-more": "Show more",
|
||||
|
||||
"item.page.bitstreams.collapse": "Collapse",
|
||||
|
||||
"item.page.filesection.original.bundle" : "Original bundle",
|
||||
|
||||
"item.page.filesection.license.bundle" : "License bundle",
|
||||
|
||||
|
||||
"item.select.confirm": "Confirm selected",
|
||||
|
Reference in New Issue
Block a user