diff --git a/src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.html b/src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.html index 324a581ae0..cd5f4f03a2 100644 --- a/src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.html +++ b/src/app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component.html @@ -31,7 +31,6 @@ [sortConfig]="(currentSort$ |async)" [type]="startsWithType" [startsWithOptions]="startsWithOptions" - [enableArrows]="true" (prev)="goPrev()" (next)="goNext()"> diff --git a/src/app/shared/browse-by/browse-by.component.html b/src/app/shared/browse-by/browse-by.component.html index 6d1422293d..3b72ce2d23 100644 --- a/src/app/shared/browse-by/browse-by.component.html +++ b/src/app/shared/browse-by/browse-by.component.html @@ -1,38 +1,15 @@ -

{{title | translate}}

+

{{title | translate}}

-
- - -
-
-
-
-
- -
- - - - -
-
-
-
-
    -
  • - -
  • -
-
- - -
-
+ +
@@ -40,3 +17,4 @@ {{'browse.empty' | translate}}
+ diff --git a/src/app/shared/browse-by/browse-by.component.spec.ts b/src/app/shared/browse-by/browse-by.component.spec.ts index 896537b63a..601c352705 100644 --- a/src/app/shared/browse-by/browse-by.component.spec.ts +++ b/src/app/shared/browse-by/browse-by.component.spec.ts @@ -4,20 +4,17 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { By } from '@angular/platform-browser'; import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; import { of as observableOf } from 'rxjs'; -import { SharedModule } from '../shared.module'; import { CommonModule } from '@angular/common'; import { Item } from '../../core/shared/item.model'; import { buildPaginatedList } from '../../core/data/paginated-list.model'; import { PageInfo } from '../../core/shared/page-info.model'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; -import { StoreModule } from '@ngrx/store'; import { TranslateLoaderMock } from '../mocks/translate-loader.mock'; import { RouterTestingModule } from '@angular/router/testing'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; -import { storeModuleConfig } from '../../app.reducer'; import { PaginationService } from '../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../testing/pagination-service.stub'; import { ListableObjectComponentLoaderComponent } from '../object-collection/shared/listable-object/listable-object-component-loader.component'; @@ -30,6 +27,9 @@ import { import { BrowseEntry } from '../../core/shared/browse-entry.model'; import { ITEM } from '../../core/shared/item.resource-type'; import { ThemeService } from '../theme-support/theme.service'; +import { SelectableListService } from '../object-list/selectable-list/selectable-list.service'; +import { HostWindowServiceStub } from '../testing/host-window-service.stub'; +import { HostWindowService } from '../host-window.service'; import SpyObj = jasmine.SpyObj; @listableObjectComponent(BrowseEntry, ViewMode.ListElement, DEFAULT_CONTEXT, 'custom') @@ -37,7 +37,8 @@ import SpyObj = jasmine.SpyObj; selector: 'ds-browse-entry-list-element', template: '' }) -class MockThemedBrowseEntryListElementComponent {} +class MockThemedBrowseEntryListElementComponent { +} describe('BrowseByComponent', () => { let comp: BrowseByComponent; @@ -83,10 +84,7 @@ describe('BrowseByComponent', () => { TestBed.configureTestingModule({ imports: [ CommonModule, - TranslateModule.forRoot(), - SharedModule, NgbModule, - StoreModule.forRoot({}, storeModuleConfig), TranslateModule.forRoot({ loader: { provide: TranslateLoader, @@ -94,13 +92,15 @@ describe('BrowseByComponent', () => { } }), RouterTestingModule, - BrowserAnimationsModule + NoopAnimationsModule ], declarations: [], providers: [ - {provide: PaginationService, useValue: paginationService}, - {provide: MockThemedBrowseEntryListElementComponent}, + { provide: PaginationService, useValue: paginationService }, + { provide: MockThemedBrowseEntryListElementComponent }, { provide: ThemeService, useValue: themeService }, + { provide: SelectableListService, useValue: {} }, + { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -129,66 +129,7 @@ describe('BrowseByComponent', () => { expect(fixture.debugElement.query(By.css('ds-viewable-collection'))).toBeDefined(); }); - describe('when enableArrows is true and objects are defined', () => { - beforeEach(() => { - comp.enableArrows = true; - comp.objects$ = mockItemsRD$; - - comp.paginationConfig = paginationConfig; - comp.sortConfig = Object.assign(new SortOptions('dc.title', SortDirection.ASC)); - fixture.detectChanges(); - }); - - describe('when clicking the previous arrow button', () => { - beforeEach(() => { - spyOn(comp.prev, 'emit'); - fixture.debugElement.query(By.css('#nav-prev')).triggerEventHandler('click', null); - fixture.detectChanges(); - }); - - it('should emit a signal to the EventEmitter', () => { - expect(comp.prev.emit).toHaveBeenCalled(); - }); - }); - - describe('when clicking the next arrow button', () => { - beforeEach(() => { - spyOn(comp.next, 'emit'); - fixture.debugElement.query(By.css('#nav-next')).triggerEventHandler('click', null); - fixture.detectChanges(); - }); - - it('should emit a signal to the EventEmitter', () => { - expect(comp.next.emit).toHaveBeenCalled(); - }); - }); - - describe('when clicking a different page size', () => { - beforeEach(() => { - spyOn(comp.pageSizeChange, 'emit'); - fixture.debugElement.query(By.css('.page-size-change')).triggerEventHandler('click', null); - fixture.detectChanges(); - }); - - it('should call the updateRoute method from the paginationService', () => { - expect(paginationService.updateRoute).toHaveBeenCalledWith('test-pagination', {pageSize: paginationConfig.pageSizeOptions[0]}); - }); - }); - - describe('when clicking a different sort direction', () => { - beforeEach(() => { - spyOn(comp.sortDirectionChange, 'emit'); - fixture.debugElement.query(By.css('.sort-direction-change')).triggerEventHandler('click', null); - fixture.detectChanges(); - }); - - it('should call the updateRoute method from the paginationService', () => { - expect(paginationService.updateRoute).toHaveBeenCalledWith('test-pagination', {sortDirection: 'ASC'}); - }); - }); - }); - - describe('when enableArrows is true and browseEntries are provided', () => { + describe('when showPaginator is true and browseEntries are provided', () => { let browseEntries; beforeEach(() => { @@ -209,7 +150,7 @@ describe('BrowseByComponent', () => { }), ]; - comp.enableArrows = true; + comp.showPaginator = true; comp.objects$ = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), browseEntries)); comp.paginationConfig = paginationConfig; comp.sortConfig = Object.assign(new SortOptions('dc.title', SortDirection.ASC)); diff --git a/src/app/shared/browse-by/browse-by.component.ts b/src/app/shared/browse-by/browse-by.component.ts index 861e431635..cc99e64bc5 100644 --- a/src/app/shared/browse-by/browse-by.component.ts +++ b/src/app/shared/browse-by/browse-by.component.ts @@ -67,30 +67,30 @@ export class BrowseByComponent implements OnInit { /** * Whether or not the pagination should be rendered as simple previous and next buttons instead of the normal pagination */ - @Input() enableArrows = false; + @Input() showPaginator = false; /** - * If enableArrows is set to true, should it hide the options gear? + * It is used to hide or show gear */ @Input() hideGear = false; /** - * If enableArrows is set to true, emit when the previous button is clicked + * Emits event when prev button clicked */ @Output() prev = new EventEmitter(); /** - * If enableArrows is set to true, emit when the next button is clicked + * Emits event when next button clicked */ @Output() next = new EventEmitter(); /** - * If enableArrows is set to true, emit when the page size is changed + * Emits event when page size is changed */ @Output() pageSizeChange = new EventEmitter(); /** - * If enableArrows is set to true, emit when the sort direction is changed + * Emits event when page sort direction is changed */ @Output() sortDirectionChange = new EventEmitter(); diff --git a/src/app/shared/object-collection/object-collection.component.html b/src/app/shared/object-collection/object-collection.component.html index f2778757ef..999ae9a120 100644 --- a/src/app/shared/object-collection/object-collection.component.html +++ b/src/app/shared/object-collection/object-collection.component.html @@ -6,6 +6,7 @@ [linkType]="linkType" [context]="context" [hidePaginationDetail]="hidePaginationDetail" + [showPaginator]="showPaginator" (paginationChange)="onPaginationChange($event)" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)" @@ -19,6 +20,8 @@ [importConfig]="importConfig" (importObject)="importObject.emit($event)" (contentChange)="contentChange.emit()" + (prev)="goPrev()" + (next)="goNext()" *ngIf="(currentMode$ | async) === viewModeEnum.ListElement"> @@ -29,6 +32,7 @@ [linkType]="linkType" [context]="context" [hidePaginationDetail]="hidePaginationDetail" + [showPaginator]="showPaginator" (paginationChange)="onPaginationChange($event)" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)" @@ -44,6 +48,7 @@ [linkType]="linkType" [context]="context" [hidePaginationDetail]="hidePaginationDetail" + [showPaginator]="showPaginator" *ngIf="(currentMode$ | async) === viewModeEnum.DetailedListElement"> diff --git a/src/app/shared/object-collection/object-collection.component.ts b/src/app/shared/object-collection/object-collection.component.ts index 29fdb37ea1..f2706f1a4c 100644 --- a/src/app/shared/object-collection/object-collection.component.ts +++ b/src/app/shared/object-collection/object-collection.component.ts @@ -88,6 +88,11 @@ export class ObjectCollectionComponent implements OnInit { */ @Input() hidePaginationDetail = false; + /** + * Whether or not the pagination should be rendered as simple previous and next buttons instead of the normal pagination + */ + @Input() showPaginator = true; + /** * the page info of the list */ @@ -122,6 +127,16 @@ export class ObjectCollectionComponent implements OnInit { */ @Output() sortFieldChange: EventEmitter = new EventEmitter(); + /** + * If showPaginator is set to true, emit when the previous button is clicked + */ + @Output() prev = new EventEmitter(); + + /** + * If showPaginator is set to true, emit when the next button is clicked + */ + @Output() next = new EventEmitter(); + /** * Emits the current view mode */ @@ -192,4 +207,18 @@ export class ObjectCollectionComponent implements OnInit { this.paginationChange.emit(event); } + /** + * Go to the previous page + */ + goPrev() { + this.prev.emit(true); + } + + /** + * Go to the next page + */ + goNext() { + this.next.emit(true); + } + } diff --git a/src/app/shared/object-detail/object-detail.component.html b/src/app/shared/object-detail/object-detail.component.html index 7fef7d9689..32728d92e4 100644 --- a/src/app/shared/object-detail/object-detail.component.html +++ b/src/app/shared/object-detail/object-detail.component.html @@ -3,14 +3,19 @@ [pageInfoState]="objects?.payload" [collectionSize]="objects?.payload?.totalElements" [sortOptions]="sortConfig" + [objects]="objects" [hideGear]="hideGear" [hidePaginationDetail]="hidePaginationDetail" [hidePagerWhenSinglePage]="hidePagerWhenSinglePage" + [showPaginator]="showPaginator" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)" (sortDirectionChange)="onSortDirectionChange($event)" (sortFieldChange)="onSortFieldChange($event)" - (paginationChange)="onPaginationChange($event)"> + (paginationChange)="onPaginationChange($event)" + (prev)="goPrev()" + (next)="goNext()" + >
diff --git a/src/app/shared/object-detail/object-detail.component.ts b/src/app/shared/object-detail/object-detail.component.ts index 8b94746fbd..05d2ca4b5b 100644 --- a/src/app/shared/object-detail/object-detail.component.ts +++ b/src/app/shared/object-detail/object-detail.component.ts @@ -66,6 +66,21 @@ export class ObjectDetailComponent { */ @Input() context: Context; + /** + * Whether or not the pagination should be rendered as simple previous and next buttons instead of the normal pagination + */ + @Input() showPaginator = true; + + /** + * If showPaginator is set to true, emit when the previous button is clicked + */ + @Output() prev = new EventEmitter(); + + /** + * If showPaginator is set to true, emit when the next button is clicked + */ + @Output() next = new EventEmitter(); + /** * The list of objects to paginate */ @@ -168,4 +183,18 @@ export class ObjectDetailComponent { this.paginationChange.emit(event); } + /** + * Go to the previous page + */ + goPrev() { + this.prev.emit(true); + } + + /** + * Go to the next page + */ + goNext() { + this.next.emit(true); + } + } diff --git a/src/app/shared/object-grid/object-grid.component.html b/src/app/shared/object-grid/object-grid.component.html index 8f8e5da4d9..07dbcec805 100644 --- a/src/app/shared/object-grid/object-grid.component.html +++ b/src/app/shared/object-grid/object-grid.component.html @@ -4,13 +4,18 @@ [collectionSize]="objects?.payload?.totalElements" [sortOptions]="sortConfig" [hideGear]="hideGear" + [objects]="objects" [hidePagerWhenSinglePage]="hidePagerWhenSinglePage" [hidePaginationDetail]="hidePaginationDetail" + [showPaginator]="showPaginator" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)" (sortDirectionChange)="onSortDirectionChange($event)" (sortFieldChange)="onSortFieldChange($event)" - (paginationChange)="onPaginationChange($event)"> + (paginationChange)="onPaginationChange($event)" + (prev)="goPrev()" + (next)="goNext()" + >
@@ -22,3 +27,4 @@ + diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index 39c3d56f7f..1b5ab075e2 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -49,6 +49,11 @@ export class ObjectGridComponent implements OnInit { */ @Input() sortConfig: SortOptions; + /** + * Whether or not the pagination should be rendered as simple previous and next buttons instead of the normal pagination + */ + @Input() showPaginator = true; + /** * The whether or not the gear is hidden */ @@ -134,6 +139,17 @@ export class ObjectGridComponent implements OnInit { * Event's payload equals to the newly selected sort field. */ @Output() sortFieldChange: EventEmitter = new EventEmitter(); + + /** + * If showPaginator is set to true, emit when the previous button is clicked + */ + @Output() prev = new EventEmitter(); + + /** + * If showPaginator is set to true, emit when the next button is clicked + */ + @Output() next = new EventEmitter(); + data: any = {}; columns$: Observable; @@ -225,4 +241,18 @@ export class ObjectGridComponent implements OnInit { this.paginationChange.emit(event); } + /** + * Go to the previous page + */ + goPrev() { + this.prev.emit(true); + } + + /** + * Go to the next page + */ + goNext() { + this.next.emit(true); + } + } diff --git a/src/app/shared/object-list/object-list.component.html b/src/app/shared/object-list/object-list.component.html index 43d2da77c4..492cb4cf07 100644 --- a/src/app/shared/object-list/object-list.component.html +++ b/src/app/shared/object-list/object-list.component.html @@ -2,15 +2,20 @@ [paginationOptions]="config" [pageInfoState]="objects?.payload" [collectionSize]="objects?.payload?.totalElements" + [objects]="objects" [sortOptions]="sortConfig" [hideGear]="hideGear" [hidePagerWhenSinglePage]="hidePagerWhenSinglePage" [hidePaginationDetail]="hidePaginationDetail" + [showPaginator]="showPaginator" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)" (sortDirectionChange)="onSortDirectionChange($event)" (sortFieldChange)="onSortFieldChange($event)" - (paginationChange)="onPaginationChange($event)"> + (paginationChange)="onPaginationChange($event)" + (prev)="goPrev()" + (next)="goNext()" + >
  • (); + /** + * If showPaginator is set to true, emit when the previous button is clicked + */ + @Output() prev = new EventEmitter(); + + /** + * If showPaginator is set to true, emit when the next button is clicked + */ + @Output() next = new EventEmitter(); + /** * The current listable objects */ @@ -192,4 +207,18 @@ export class ObjectListComponent { onPaginationChange(event) { this.paginationChange.emit(event); } + + /** + * Go to the previous page + */ + goPrev() { + this.prev.emit(true); + } + + /** + * Go to the next page + */ + goNext() { + this.next.emit(true); + } } diff --git a/src/app/shared/pagination/pagination.component.html b/src/app/shared/pagination/pagination.component.html index 2a9aa1a062..9f894c48d9 100644 --- a/src/app/shared/pagination/pagination.component.html +++ b/src/app/shared/pagination/pagination.component.html @@ -20,16 +20,32 @@
- diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts index cf2d1c13fd..d0d1612833 100644 --- a/src/app/shared/pagination/pagination.component.spec.ts +++ b/src/app/shared/pagination/pagination.component.spec.ts @@ -177,132 +177,206 @@ describe('Pagination component', () => { })); - // synchronous beforeEach - beforeEach(() => { - html = ` - -
    -
  • {{item}}
  • -
-
`; + describe('when showPaginator is false', () => { + // synchronous beforeEach + beforeEach(() => { + html = ` + +
    +
  • {{item}}
  • +
+
`; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); - testFixture = createTestComponent(html, TestComponent) as ComponentFixture; - testComp = testFixture.componentInstance; + it('should create Pagination Component', inject([PaginationComponent], (app: PaginationComponent) => { + expect(app).toBeDefined(); + })); - }); + it('should render', () => { + expect(testComp.paginationOptions.id).toEqual('test'); + expect(testComp.paginationOptions.currentPage).toEqual(1); + expect(testComp.paginationOptions.pageSize).toEqual(10); + expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '» Next']); + }); - it('should create Pagination Component', inject([PaginationComponent], (app: PaginationComponent) => { - expect(app).toBeDefined(); - })); - - it('should render', () => { - expect(testComp.paginationOptions.id).toEqual('test'); - expect(testComp.paginationOptions.currentPage).toEqual(1); - expect(testComp.paginationOptions.pageSize).toEqual(10); - expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '» Next']); - }); - - it('should render and respond to page change', () => { - testComp.collectionSize = 30; - testFixture.detectChanges(); - - - currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {currentPage: 3})); - testFixture.detectChanges(); - - expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']); - - currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {currentPage: 2})); - testFixture.detectChanges(); - - expectPages(testFixture, ['« Previous', '1', '+2', '3', '» Next']); - }); - - it('should render and respond to collectionSize change', () => { - - testComp.collectionSize = 30; - testFixture.detectChanges(); - expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); - - testComp.collectionSize = 40; - testFixture.detectChanges(); - expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '» Next']); - }); - - it('should render and respond to pageSize change', () => { - const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; - - testComp.collectionSize = 30; - testFixture.detectChanges(); - expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); - - currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 5})); - testFixture.detectChanges(); - - expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '6', '» Next']); - - currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 10})); - testFixture.detectChanges(); - expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); - - currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 20})); - testFixture.detectChanges(); - expectPages(testFixture, ['-« Previous', '+1', '2', '» Next']); - }); - - it('should emit pageSizeChange event with correct value', fakeAsync(() => { - const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; - - spyOn(testComp, 'pageSizeChanged'); - - testComp.pageSizeChanged(5); - tick(); - - expect(testComp.pageSizeChanged).toHaveBeenCalledWith(5); - })); - - it('should call the updateRoute method on the paginationService with the correct params', fakeAsync(() => { - testComp.collectionSize = 60; - - changePage(testFixture, 3); - tick(); - expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ page: '3'}), {}, false); - - changePage(testFixture, 0); - tick(); - expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ page: '2'}), {}, false); - })); - - it('should set correct pageSize route parameters', fakeAsync(() => { - routerStub = testFixture.debugElement.injector.get(Router) as any; - - testComp.collectionSize = 60; - - changePageSize(testFixture, '20'); - tick(); - expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ pageId: 'test', page: 1, pageSize: 20}), {}, false); - })); - - it('should respond to windows resize', () => { - const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; - hostWindowServiceStub = testFixture.debugElement.injector.get(HostWindowService) as any; - - hostWindowServiceStub.setWidth(400); - - hostWindowServiceStub.isXs().subscribe((status) => { - paginationComponent.isXs = status; + it('should render and respond to page change', () => { + testComp.collectionSize = 30; testFixture.detectChanges(); - expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '-...', '10', '» Next']); - de = testFixture.debugElement.query(By.css('ul.pagination')); - expect(de.nativeElement.classList.contains('pagination-sm')).toBeTruthy(); + + + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {currentPage: 3})); + testFixture.detectChanges(); + + expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']); + + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {currentPage: 2})); + testFixture.detectChanges(); + + expectPages(testFixture, ['« Previous', '1', '+2', '3', '» Next']); + }); + + it('should render and respond to collectionSize change', () => { + + testComp.collectionSize = 30; + testFixture.detectChanges(); + expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); + + testComp.collectionSize = 40; + testFixture.detectChanges(); + expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '» Next']); + }); + + it('should render and respond to pageSize change', () => { + const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; + + testComp.collectionSize = 30; + testFixture.detectChanges(); + expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); + + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 5})); + testFixture.detectChanges(); + + expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '6', '» Next']); + + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 10})); + testFixture.detectChanges(); + expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); + + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 20})); + testFixture.detectChanges(); + expectPages(testFixture, ['-« Previous', '+1', '2', '» Next']); + }); + + it('should emit pageSizeChange event with correct value', fakeAsync(() => { + const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; + + spyOn(testComp, 'pageSizeChanged'); + + testComp.pageSizeChanged(5); + tick(); + + expect(testComp.pageSizeChanged).toHaveBeenCalledWith(5); + })); + + it('should call the updateRoute method on the paginationService with the correct params', fakeAsync(() => { + testComp.collectionSize = 60; + + changePage(testFixture, 3); + tick(); + expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ page: '3'}), {}, false); + + changePage(testFixture, 0); + tick(); + expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ page: '2'}), {}, false); + })); + + it('should set correct pageSize route parameters', fakeAsync(() => { + routerStub = testFixture.debugElement.injector.get(Router) as any; + + testComp.collectionSize = 60; + + changePageSize(testFixture, '20'); + tick(); + expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ pageId: 'test', page: 1, pageSize: 20}), {}, false); + })); + + it('should respond to windows resize', () => { + const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; + hostWindowServiceStub = testFixture.debugElement.injector.get(HostWindowService) as any; + + hostWindowServiceStub.setWidth(400); + + hostWindowServiceStub.isXs().subscribe((status) => { + paginationComponent.isXs = status; + testFixture.detectChanges(); + expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '-...', '10', '» Next']); + de = testFixture.debugElement.query(By.css('ul.pagination')); + expect(de.nativeElement.classList.contains('pagination-sm')).toBeTruthy(); + }); }); }); + + describe('when showPaginator is true', () => { + // synchronous beforeEach + beforeEach(() => { + html = ` + +
    +
  • {{item}}
  • +
+
`; + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + beforeEach(() => { + testComp.showPaginator = false; + testFixture.detectChanges(); + }); + + describe('when clicking the previous arrow button', () => { + beforeEach(() => { + spyOn(testComp, 'goPrev'); + testFixture.detectChanges(); + }); + + it('should call goPrev method', () => { + const prev = testFixture.debugElement.query(By.css('#nav-prev')); + testFixture.detectChanges(); + prev.triggerEventHandler('click', null); + expect(testComp.goPrev).toHaveBeenCalled(); + }); + }); + + describe('when clicking the next arrow button', () => { + beforeEach(() => { + spyOn(testComp, 'goNext'); + testFixture.detectChanges(); + }); + + it('should call goNext method', () => { + const next = testFixture.debugElement.query(By.css('#nav-next')); + testFixture.detectChanges(); + next.triggerEventHandler('click', null); + expect(testComp.goNext).toHaveBeenCalled(); + }); + }); + + describe('check for prev and next button', () => { + it('shoud have a previous button', () => { + const prev = testFixture.debugElement.query(By.css('#nav-prev')); + testFixture.detectChanges(); + expect(prev).toBeTruthy(); + }); + + it('shoud have a next button', () => { + const next = testFixture.debugElement.query(By.css('#nav-next')); + testFixture.detectChanges(); + expect(next).toBeTruthy(); + }); + }); + }); + }); // declare a test component @@ -313,11 +387,19 @@ class TestComponent { collectionSize: number; paginationOptions = new PaginationComponentOptions(); sortOptions = new SortOptions('dc.title', SortDirection.ASC); + showPaginator: boolean; + objects = { + payload: { + currentPage: 2, + totalPages: 100 + } + }; constructor() { this.collection = Array.from(new Array(100), (x, i) => `item ${i + 1}`); this.collectionSize = 100; this.paginationOptions.id = 'test'; + this.showPaginator = false; } pageChanged(page) { @@ -327,4 +409,12 @@ class TestComponent { pageSizeChanged(pageSize) { this.paginationOptions.pageSize = pageSize; } + + goPrev() { + this.objects.payload.currentPage --; + } + + goNext() { + this.objects.payload.currentPage ++; + } } diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index 8f1c6bf26f..6da813cbc7 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -19,7 +19,11 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options import { hasValue } from '../empty.util'; import { PageInfo } from '../../core/shared/page-info.model'; import { PaginationService } from '../../core/pagination/pagination.service'; -import { map } from 'rxjs/operators'; +import { map, take } from 'rxjs/operators'; +import { RemoteData } from '../../core/data/remote-data'; +import { PaginatedList } from '../../core/data/paginated-list.model'; +import { ListableObject } from '../object-collection/shared/listable-object.model'; +import { ViewMode } from '../../core/shared/view-mode.model'; /** * The default pagination controls component. @@ -33,6 +37,11 @@ import { map } from 'rxjs/operators'; encapsulation: ViewEncapsulation.Emulated }) export class PaginationComponent implements OnDestroy, OnInit { + /** + * ViewMode that should be passed to {@link ListableObjectComponentLoaderComponent}. + */ + viewMode: ViewMode = ViewMode.ListElement; + /** * Number of items in collection. */ @@ -53,6 +62,26 @@ export class PaginationComponent implements OnDestroy, OnInit { */ @Input() sortOptions: SortOptions; + /** + * Whether or not the pagination should be rendered as simple previous and next buttons instead of the normal pagination + */ + @Input() showPaginator = true; + + /** + * The current pagination configuration + */ + @Input() config?: PaginationComponentOptions; + + /** + * The list of listable objects to render in this component + */ + @Input() objects: RemoteData>; + + /** + * The current sorting configuration + */ + @Input() sortConfig: SortOptions; + /** * An event fired when the page is changed. * Event's payload equals to the newly selected page. @@ -163,6 +192,15 @@ export class PaginationComponent implements OnDestroy, OnInit { */ private subs: Subscription[] = []; + /** + * If showPaginator is set to true, emit when the previous button is clicked + */ + @Output() prev = new EventEmitter(); + + /** + * If showPaginator is set to true, emit when the next button is clicked + */ + @Output() next = new EventEmitter(); /** * Method provided by Angular. Invoked after the constructor. */ @@ -347,4 +385,31 @@ export class PaginationComponent implements OnDestroy, OnInit { map((hasMultiplePages) => hasMultiplePages || !this.hidePagerWhenSinglePage) ); } + + /** + * Go to the previous page + */ + goPrev() { + this.prev.emit(true); + this.updatePagination(-1); + } + + /** + * Go to the next page + */ + goNext() { + this.next.emit(true); + this.updatePagination(1); + } + + /** + * Update page when next or prev button is clicked + * @param value + */ + updatePagination(value: number) { + this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe(take(1)).subscribe((currentPaginationOptions) => { + this.updateParams({page: (currentPaginationOptions.currentPage + value).toString()}); + }); + } + } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 1be5ac448a..c3c68a6882 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -678,9 +678,9 @@ "browse.metadata.title.breadcrumbs": "Browse by Title", - "browse.next.button": "Next", + "pagination.next.button": "Next", - "browse.previous.button": "Previous", + "pagination.previous.button": "Previous", "browse.startsWith.choose_start": "(Choose start)",