From fab226912fc7c1008f7d75326772b4372502be41 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Fri, 5 Feb 2021 15:47:07 +0100 Subject: [PATCH 01/14] 76654: PaginationService --- .../epeople-registry.component.html | 3 +- .../epeople-registry.component.ts | 96 +++--- .../eperson-form/eperson-form.component.ts | 88 +++--- .../members-list/members-list.component.html | 6 +- .../members-list/members-list.component.ts | 62 ++-- .../subgroups-list.component.html | 6 +- .../subgroup-list/subgroups-list.component.ts | 55 ++-- .../groups-registry.component.html | 3 +- .../groups-registry.component.ts | 117 ++++---- .../bitstream-formats.component.html | 3 +- .../bitstream-formats.component.ts | 46 +-- .../metadata-registry.component.html | 3 +- .../metadata-registry.component.ts | 19 +- .../metadata-schema.component.html | 3 +- .../metadata-schema.component.ts | 26 +- .../browse-by-date-page.component.ts | 39 +-- .../browse-by-metadata-page.component.html | 4 +- .../browse-by-metadata-page.component.ts | 59 +--- .../browse-by-title-page.component.ts | 31 +- .../collection-page.component.html | 3 +- .../collection-page.component.ts | 36 +-- ...ty-page-sub-collection-list.component.html | 3 +- ...nity-page-sub-collection-list.component.ts | 45 ++- ...ity-page-sub-community-list.component.html | 3 +- ...unity-page-sub-community-list.component.ts | 42 +-- .../top-level-community-list.component.html | 3 +- .../top-level-community-list.component.ts | 42 ++- ...rag-and-drop-bitstream-list.component.html | 4 +- ...-drag-and-drop-bitstream-list.component.ts | 4 +- .../my-dspace-configuration.service.ts | 4 +- src/app/core/pagination/pagination.service.ts | 190 ++++++++++++ .../search/search-configuration.service.ts | 50 ++-- src/app/core/shared/search/search.service.ts | 32 +- .../overview/process-overview.component.html | 3 +- .../overview/process-overview.component.ts | 22 +- .../search-navbar/search-navbar.component.ts | 11 +- .../shared/browse-by/browse-by.component.ts | 16 +- .../page-size-selector.component.ts | 20 +- ...-paginated-drag-and-drop-list.component.ts | 27 +- .../pagination/pagination.component.html | 14 +- .../shared/pagination/pagination.component.ts | 273 +++++------------- .../eperson-group-list.component.html | 3 +- .../eperson-group-list.component.ts | 33 ++- .../search-form/search-form.component.ts | 15 +- .../search-settings.component.ts | 16 +- .../date/starts-with-date.component.ts | 5 +- .../starts-with-abstract.component.ts | 3 + .../submission-import-external.component.html | 3 +- .../submission-import-external.component.ts | 58 ++-- 49 files changed, 826 insertions(+), 826 deletions(-) create mode 100644 src/app/core/pagination/pagination.service.ts diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html index f478557e00..8466ff1817 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html +++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html @@ -45,8 +45,7 @@ [pageInfoState]="pageInfoState$" [collectionSize]="(pageInfoState$ | async)?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChange($event)"> + [hidePagerWhenSinglePage]="true">
diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts index 11b146b294..cb8a76d627 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts @@ -4,7 +4,7 @@ import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs'; import { map, switchMap, take } from 'rxjs/operators'; -import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model'; +import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model'; import { RemoteData } from '../../../core/data/remote-data'; import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; import { EPerson } from '../../../core/eperson/models/eperson.model'; @@ -14,15 +14,13 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { EpersonDtoModel } from '../../../core/eperson/models/eperson-dto.model'; import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { - getFirstCompletedRemoteData, - getAllSucceededRemoteData -} from '../../../core/shared/operators'; +import { getAllSucceededRemoteData, getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { RequestService } from '../../../core/data/request.service'; import { PageInfo } from '../../../core/shared/page-info.model'; import { NoContent } from '../../../core/shared/NoContent.model'; +import { PaginationService } from '../../../core/pagination/pagination.service'; @Component({ selector: 'ds-epeople-registry', @@ -55,7 +53,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { * Pagination config used to display the list of epeople */ config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'epeople-list-pagination', + id: 'elp', pageSize: 5, currentPage: 1 }); @@ -77,6 +75,11 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { */ searchSub: Subscription; + /** + * FindListOptions + */ + findListOptionsSub: Subscription; + /** * List of subscriptions */ @@ -89,6 +92,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { private formBuilder: FormBuilder, private router: Router, private modalService: NgbModal, + private paginationService: PaginationService, public requestService: RequestService) { this.currentSearchQuery = ''; this.currentSearchScope = 'metadata'; @@ -107,7 +111,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { */ initialisePage() { this.isEPersonFormShown = false; - this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery }); + this.search({scope: this.currentSearchScope, query: this.currentSearchQuery}); this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => { if (eperson != null && eperson.id) { this.isEPersonFormShown = true; @@ -133,54 +137,54 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { return [epeople]; } })).subscribe((value: PaginatedList) => { - this.ePeopleDto$.next(value); - this.pageInfoState$.next(value.pageInfo); + this.ePeopleDto$.next(value); + this.pageInfoState$.next(value.pageInfo); })); } - /** - * Event triggered when the user changes page - * @param event - */ - onPageChange(event) { - if (this.config.currentPage !== event) { - this.config.currentPage = event; - this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery }); - } - } - /** * Search in the EPeople by metadata (default) or email * @param data Contains scope and query param */ search(data: any) { - const query: string = data.query; - const scope: string = data.scope; - if (query != null && this.currentSearchQuery !== query) { - this.router.navigateByUrl(this.epersonService.getEPeoplePageRouterLink()); - this.currentSearchQuery = query; - this.config.currentPage = 1; + if (hasValue(this.findListOptionsSub)) { + this.findListOptionsSub.unsubscribe(); } - if (scope != null && this.currentSearchScope !== scope) { - this.router.navigateByUrl(this.epersonService.getEPeoplePageRouterLink()); - this.currentSearchScope = scope; - this.config.currentPage = 1; - } - if (hasValue(this.searchSub)) { - this.searchSub.unsubscribe(); - this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub); - } - this.searchSub = this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { - currentPage: this.config.currentPage, - elementsPerPage: this.config.pageSize - }).pipe( - getAllSucceededRemoteData(), - ).subscribe((peopleRD) => { - this.ePeople$.next(peopleRD.payload); - this.pageInfoState$.next(peopleRD.payload.pageInfo); + this.findListOptionsSub = this.paginationService.getCurrentPagination(this.config.id, this.config).subscribe((findListOptions) => { + const query: string = data.query; + const scope: string = data.scope; + if (query != null && this.currentSearchQuery !== query) { + this.router.navigate([], { + queryParamsHandling: 'merge' + }); + this.currentSearchQuery = query; + this.paginationService.resetPage(this.config.id); + } + if (scope != null && this.currentSearchScope !== scope) { + this.router.navigate([], { + queryParamsHandling: 'merge' + }); + this.currentSearchScope = scope; + this.paginationService.resetPage(this.config.id); + + } + if (hasValue(this.searchSub)) { + this.searchSub.unsubscribe(); + this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub); + } + this.searchSub = this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { + currentPage: findListOptions.currentPage, + elementsPerPage: findListOptions.pageSize + }).pipe( + getAllSucceededRemoteData(), + ).subscribe((peopleRD) => { + this.ePeople$.next(peopleRD.payload); + this.pageInfoState$.next(peopleRD.payload.pageInfo); + } + ); + this.subs.push(this.searchSub); } ); - this.subs.push(this.searchSub); } /** @@ -233,7 +237,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { if (hasValue(ePerson.id)) { this.epersonService.deleteEPerson(ePerson).pipe(getFirstCompletedRemoteData()).subscribe((restResponse: RemoteData) => { if (restResponse.hasSucceeded) { - this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.deleted.success', { name: ePerson.name })); + this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.deleted.success', {name: ePerson.name})); this.reset(); } else { this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + ePerson.id + ' with code: ' + restResponse.statusCode + ' and message: ' + restResponse.errorMessage); @@ -273,7 +277,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { this.searchForm.patchValue({ query: '', }); - this.search({ query: '' }); + this.search({query: ''}); } /** diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts index 3c284735a9..6c66035f14 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -7,8 +7,8 @@ import { DynamicInputModel } from '@ng-dynamic-forms/core'; import { TranslateService } from '@ngx-translate/core'; -import { combineLatest, Observable, of, Subscription } from 'rxjs'; -import { switchMap, take } from 'rxjs/operators'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; +import { switchMap, take, tap } from 'rxjs/operators'; import { PaginatedList } from '../../../../core/data/paginated-list.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; @@ -16,9 +16,9 @@ import { GroupDataService } from '../../../../core/eperson/group-data.service'; import { EPerson } from '../../../../core/eperson/models/eperson.model'; import { Group } from '../../../../core/eperson/models/group.model'; import { - getRemoteDataPayload, + getFirstCompletedRemoteData, getFirstSucceededRemoteData, - getFirstCompletedRemoteData + getRemoteDataPayload } from '../../../../core/shared/operators'; import { hasValue } from '../../../../shared/empty.util'; import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; @@ -31,6 +31,7 @@ import { ConfirmationModalComponent } from '../../../../shared/confirmation-moda import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { RequestService } from '../../../../core/data/request.service'; import { NoContent } from '../../../../core/shared/NoContent.model'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; @Component({ selector: 'ds-eperson-form', @@ -118,7 +119,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy { * Observable whether or not the admin is allowed to reset the EPerson's password * TODO: Initialize the observable once the REST API supports this (currently hardcoded to return false) */ - canReset$: Observable = of(false); + canReset$: Observable = observableOf(false); /** * Observable whether or not the admin is allowed to delete the EPerson @@ -144,7 +145,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy { * Pagination config used to display the list of groups */ config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'groups-ePersonMemberOf-list-pagination', + id: 'gem', pageSize: 5, currentPage: 1 }); @@ -167,6 +168,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy { private authService: AuthService, private authorizationService: AuthorizationDataService, private modalService: NgbModal, + private paginationService: PaginationService, public requestService: RequestService) { this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => { this.epersonInitial = eperson; @@ -184,13 +186,13 @@ export class EPersonFormComponent implements OnInit, OnDestroy { * This method will initialise the page */ initialisePage() { - combineLatest( - this.translateService.get(`${this.messagePrefix}.firstName`), - this.translateService.get(`${this.messagePrefix}.lastName`), - this.translateService.get(`${this.messagePrefix}.email`), - this.translateService.get(`${this.messagePrefix}.canLogIn`), - this.translateService.get(`${this.messagePrefix}.requireCertificate`), - this.translateService.get(`${this.messagePrefix}.emailHint`), + observableCombineLatest( + this.translateService.get(`${this.messagePrefix}.firstName`), + this.translateService.get(`${this.messagePrefix}.lastName`), + this.translateService.get(`${this.messagePrefix}.email`), + this.translateService.get(`${this.messagePrefix}.canLogIn`), + this.translateService.get(`${this.messagePrefix}.requireCertificate`), + this.translateService.get(`${this.messagePrefix}.emailHint`), ).subscribe(([firstName, lastName, email, canLogIn, requireCertificate, emailHint]) => { this.firstName = new DynamicInputModel({ id: 'firstName', @@ -222,19 +224,19 @@ export class EPersonFormComponent implements OnInit, OnDestroy { hint: emailHint }); this.canLogIn = new DynamicCheckboxModel( - { - id: 'canLogIn', - label: canLogIn, - name: 'canLogIn', - value: (this.epersonInitial != null ? this.epersonInitial.canLogIn : true) - }); + { + id: 'canLogIn', + label: canLogIn, + name: 'canLogIn', + value: (this.epersonInitial != null ? this.epersonInitial.canLogIn : true) + }); this.requireCertificate = new DynamicCheckboxModel( - { - id: 'requireCertificate', - label: requireCertificate, - name: 'requireCertificate', - value: (this.epersonInitial != null ? this.epersonInitial.requireCertificate : false) - }); + { + id: 'requireCertificate', + label: requireCertificate, + name: 'requireCertificate', + value: (this.epersonInitial != null ? this.epersonInitial.requireCertificate : false) + }); this.formModel = [ this.firstName, this.lastName, @@ -258,11 +260,31 @@ export class EPersonFormComponent implements OnInit, OnDestroy { requireCertificate: eperson != null ? eperson.requireCertificate : false }); })); - this.canImpersonate$ = this.epersonService.getActiveEPerson().pipe( - switchMap((eperson) => this.authorizationService.isAuthorized(FeatureID.LoginOnBehalfOf, hasValue(eperson) ? eperson.self : undefined)) + + const activeEPerson$ = this.epersonService.getActiveEPerson(); + + this.groups = activeEPerson$.pipe( + switchMap((eperson) => { + return observableCombineLatest([observableOf(eperson), this.paginationService.getFindListOptions(this.config.id, { + currentPage: 1, + elementsPerPage: this.config.pageSize + })]); + }), + switchMap(([eperson, findListOptions]) => { + return this.groupsDataService.findAllByHref(eperson._links.groups.href, findListOptions); + }) ); - this.canDelete$ = this.epersonService.getActiveEPerson().pipe( - switchMap((eperson) => this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(eperson) ? eperson.self : undefined)) + // this.subs.push(combineLatest([activeEPerson$, paginationOption$]).subscribe(([eperson, options]) => { + // if (eperson != null) { + // this.groups = this.groupsDataService.findAllByHref(eperson._links.groups.href, options); + // } + // })); + + this.canImpersonate$ = activeEPerson$.pipe( + switchMap((eperson) => this.authorizationService.isAuthorized(FeatureID.LoginOnBehalfOf, hasValue(eperson) ? eperson.self : undefined)) + ); + this.canDelete$ = activeEPerson$.pipe( + switchMap((eperson) => this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(eperson) ? eperson.self : undefined)) ); }); } @@ -322,10 +344,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy { getFirstCompletedRemoteData() ).subscribe((rd: RemoteData) => { if (rd.hasSucceeded) { - this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.created.success', { name: ePersonToCreate.name })); + this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.created.success', {name: ePersonToCreate.name})); this.submitForm.emit(ePersonToCreate); } else { - this.notificationsService.error(this.translateService.get(this.labelPrefix + 'notification.created.failure', { name: ePersonToCreate.name })); + this.notificationsService.error(this.translateService.get(this.labelPrefix + 'notification.created.failure', {name: ePersonToCreate.name})); this.cancelForm.emit(); } }); @@ -361,10 +383,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy { const response = this.epersonService.updateEPerson(editedEperson); response.pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData) => { if (rd.hasSucceeded) { - this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.edited.success', { name: editedEperson.name })); + this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.edited.success', {name: editedEperson.name})); this.submitForm.emit(editedEperson); } else { - this.notificationsService.error(this.translateService.get(this.labelPrefix + 'notification.edited.failure', { name: editedEperson.name })); + this.notificationsService.error(this.translateService.get(this.labelPrefix + 'notification.edited.failure', {name: editedEperson.name})); this.cancelForm.emit(); } }); diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html index 8e2d23f8d5..54308a82ed 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html +++ b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html @@ -29,8 +29,7 @@ [pageInfoState]="(ePeopleSearchDtos | async)" [collectionSize]="(ePeopleSearchDtos | async)?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChangeSearch($event)"> + [hidePagerWhenSinglePage]="true">
@@ -83,8 +82,7 @@ [pageInfoState]="(ePeopleMembersOfGroupDtos | async)" [collectionSize]="(ePeopleMembersOfGroupDtos | async)?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChange($event)"> + [hidePagerWhenSinglePage]="true">
diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts index f1d25725d6..9f26474094 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts @@ -17,12 +17,14 @@ import { GroupDataService } from '../../../../../core/eperson/group-data.service import { EPerson } from '../../../../../core/eperson/models/eperson.model'; import { Group } from '../../../../../core/eperson/models/group.model'; import { - getRemoteDataPayload, + getFirstCompletedRemoteData, getFirstSucceededRemoteData, getFirstCompletedRemoteData, getAllCompletedRemoteData } from '../../../../../core/shared/operators'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; +import { PaginationService } from '../../../../../core/pagination/pagination.service'; +import { hasValue } from '../../../../../shared/empty.util'; import {EpersonDtoModel} from '../../../../../core/eperson/models/eperson-dto.model'; /** @@ -59,7 +61,7 @@ export class MembersListComponent implements OnInit, OnDestroy { * Pagination config used to display the list of EPeople that are result of EPeople search */ configSearch: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'search-members-list-pagination', + id: 'sml', pageSize: 5, currentPage: 1 }); @@ -67,7 +69,7 @@ export class MembersListComponent implements OnInit, OnDestroy { * Pagination config used to display the list of EPerson Membes of active group being edited */ config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'members-list-pagination', + id: 'ml', pageSize: 5, currentPage: 1 }); @@ -90,11 +92,15 @@ export class MembersListComponent implements OnInit, OnDestroy { // current active group being edited groupBeingEdited: Group; + paginationSub: Subscription; + + constructor(private groupDataService: GroupDataService, public ePersonDataService: EPersonDataService, private translateService: TranslateService, private notificationsService: NotificationsService, private formBuilder: FormBuilder, + private paginationService: PaginationService, private router: Router) { this.currentSearchQuery = ''; this.currentSearchScope = 'metadata'; @@ -113,23 +119,6 @@ export class MembersListComponent implements OnInit, OnDestroy { })); } - /** - * Event triggered when the user changes page on search result - * @param event - */ - onPageChangeSearch(event) { - this.configSearch.currentPage = event; - this.search({ scope: this.currentSearchScope, query: this.currentSearchQuery }); - } - - /** - * Event triggered when the user changes page on EPerson embers of active group - * @param event - */ - onPageChange(event) { - this.retrieveMembers(event); - } - /** * Retrieve the EPersons that are members of the group * @@ -138,10 +127,15 @@ export class MembersListComponent implements OnInit, OnDestroy { */ private retrieveMembers(page: number) { this.unsubFrom(SubKey.MembersDTO); - this.subs.set(SubKey.MembersDTO, this.ePersonDataService.findAllByHref(this.groupBeingEdited._links.epersons.href, { - currentPage: page, - elementsPerPage: this.config.pageSize - }).pipe( + this.subs.set(SubKey.MembersDTO, + this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( + switchMap((currentPagination) => { + return this.ePersonDataService.findAllByHref(this.groupBeingEdited._links.epersons.href, { + currentPage: currentPagination.currentPage, + elementsPerPage: currentPagination.pageSize + } + ); + }), getAllCompletedRemoteData(), map((rd: RemoteData) => { if (rd.hasFailed) { @@ -260,10 +254,13 @@ export class MembersListComponent implements OnInit, OnDestroy { this.unsubFrom(SubKey.SearchResultsDTO); this.subs.set(SubKey.SearchResultsDTO, - this.ePersonDataService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { - currentPage: this.configSearch.currentPage, - elementsPerPage: this.configSearch.pageSize - }, false).pipe( + this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe( + switchMap((paginationOptions) => { + this.ePersonDataService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { + currentPage: this.configSearch.currentPage, + elementsPerPage: this.configSearch.pageSize + }, false) + }), getAllCompletedRemoteData(), map((rd: RemoteData) => { if (rd.hasFailed) { @@ -292,15 +289,6 @@ export class MembersListComponent implements OnInit, OnDestroy { })); } - /** - * unsub all subscriptions - */ - ngOnDestroy(): void { - for (const key of this.subs.keys()) { - this.unsubFrom(key); - } - } - /** * Shows a notification based on the success/failure of the request * @param messageSuffix Suffix for message diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html index 87cbee0b60..93d968e126 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html +++ b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.html @@ -23,8 +23,7 @@ [pageInfoState]="(searchResults$ | async)?.payload" [collectionSize]="(searchResults$ | async)?.payload?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChangeSearch($event)"> + [hidePagerWhenSinglePage]="true">
@@ -77,8 +76,7 @@ [pageInfoState]="(subGroups$ | async)?.payload" [collectionSize]="(subGroups$ | async)?.payload?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChange($event)"> + [hidePagerWhenSinglePage]="true">
diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts index d754e71e4f..3072c4538c 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts @@ -2,20 +2,21 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; -import { Observable, of as observableOf, Subscription, BehaviorSubject } from 'rxjs'; -import { map, mergeMap, take } from 'rxjs/operators'; +import { BehaviorSubject, Observable, of as observableOf, Subscription } from 'rxjs'; +import { map, mergeMap, switchMap, take } from 'rxjs/operators'; import { PaginatedList } from '../../../../../core/data/paginated-list.model'; import { RemoteData } from '../../../../../core/data/remote-data'; import { GroupDataService } from '../../../../../core/eperson/group-data.service'; import { Group } from '../../../../../core/eperson/models/group.model'; import { - getRemoteDataPayload, + getFirstCompletedRemoteData, getFirstSucceededRemoteData, - getFirstCompletedRemoteData + getRemoteDataPayload } from '../../../../../core/shared/operators'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; import { NoContent } from '../../../../../core/shared/NoContent.model'; +import { PaginationService } from '../../../../../core/pagination/pagination.service'; /** * Keys to keep track of specific subscriptions @@ -56,7 +57,7 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { * Pagination config used to display the list of groups that are result of groups search */ configSearch: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'search-subgroups-list-pagination', + id: 'ssgl', pageSize: 5, currentPage: 1 }); @@ -64,7 +65,7 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { * Pagination config used to display the list of subgroups of currently active group being edited */ config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'subgroups-list-pagination', + id: 'sgl', pageSize: 5, currentPage: 1 }); @@ -85,6 +86,7 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { private translateService: TranslateService, private notificationsService: NotificationsService, private formBuilder: FormBuilder, + private paginationService: PaginationService, private router: Router) { this.currentSearchQuery = ''; } @@ -96,42 +98,27 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { this.subs.set(SubKey.ActiveGroup, this.groupDataService.getActiveGroup().subscribe((activeGroup: Group) => { if (activeGroup != null) { this.groupBeingEdited = activeGroup; - this.retrieveSubGroups(this.config.currentPage); + this.retrieveSubGroups(); } })); } - /** - * Event triggered when the user changes page on search result - * @param event - */ - onPageChangeSearch(event) { - this.configSearch.currentPage = event; - this.search({ query: this.currentSearchQuery }); - } - - /** - * Event triggered when the user changes page on subgroups of active group - * @param event - */ - onPageChange(event) { - this.retrieveSubGroups(event); - } - /** * Retrieve the Subgroups that are members of the group * * @param page the number of the page to retrieve * @private */ - private retrieveSubGroups(page: number) { + private retrieveSubGroups() { this.unsubFrom(SubKey.Members); this.subs.set( SubKey.Members, - this.groupDataService.findAllByHref(this.groupBeingEdited._links.subgroups.href, { - currentPage: page, - elementsPerPage: this.config.pageSize - } + this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( + switchMap((config) => this.groupDataService.findAllByHref(this.groupBeingEdited._links.subgroups.href, { + currentPage: config.currentPage, + elementsPerPage: config.pageSize + } + )) ).subscribe((rd: RemoteData>) => { this.subGroups$.next(rd); })); @@ -226,10 +213,12 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { this.searchDone = true; this.unsubFrom(SubKey.SearchResults); - this.subs.set(SubKey.SearchResults, this.groupDataService.searchGroups(this.currentSearchQuery, { - currentPage: this.configSearch.currentPage, - elementsPerPage: this.configSearch.pageSize - }).subscribe((rd: RemoteData>) => { + this.subs.set(SubKey.SearchResults, this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe( + switchMap((config) => this.groupDataService.searchGroups(this.currentSearchQuery, { + currentPage: config.currentPage, + elementsPerPage: config.pageSize + })) + ).subscribe((rd: RemoteData>) => { this.searchResults$.next(rd); })); } diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html index 7a557d79ac..a760423fc5 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html +++ b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.html @@ -35,8 +35,7 @@ [pageInfoState]="pageInfoState$" [collectionSize]="(pageInfoState$ | async)?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChange($event)"> + [hidePagerWhenSinglePage]="true">
diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts index 305da75eeb..1a7ed6a599 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts @@ -5,15 +5,15 @@ import { TranslateService } from '@ngx-translate/core'; import { BehaviorSubject, combineLatest as observableCombineLatest, - Subscription, Observable, - of as observableOf + of as observableOf, + Subscription } from 'rxjs'; -import { catchError, map, switchMap, take } from 'rxjs/operators'; +import { catchError, map, switchMap, take, tap } from 'rxjs/operators'; import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service'; import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; -import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model'; +import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model'; import { RemoteData } from '../../../core/data/remote-data'; import { RequestService } from '../../../core/data/request.service'; import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; @@ -24,6 +24,7 @@ import { Group } from '../../../core/eperson/models/group.model'; import { RouteService } from '../../../core/services/route.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { + getAllSucceededRemoteData, getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, getFirstSucceededRemoteData @@ -33,6 +34,7 @@ import { hasValue } from '../../../shared/empty.util'; import { NotificationsService } from '../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { NoContent } from '../../../core/shared/NoContent.model'; +import { PaginationService } from '../../../core/pagination/pagination.service'; @Component({ selector: 'ds-groups-registry', @@ -50,7 +52,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { * Pagination config used to display the list of groups */ config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'groups-list-pagination', + id: 'gl', pageSize: 5, currentPage: 1 }); @@ -78,6 +80,8 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { */ searchSub: Subscription; + paginationSub: Subscription; + /** * List of subscriptions */ @@ -92,6 +96,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { protected routeService: RouteService, private router: Router, private authorizationService: AuthorizationDataService, + private paginationService: PaginationService, public requestService: RequestService) { this.currentSearchQuery = ''; this.searchForm = this.formBuilder.group(({ @@ -103,20 +108,12 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { this.search({ query: this.currentSearchQuery }); } - /** - * Event triggered when the user changes page - * @param event - */ - onPageChange(event) { - this.config.currentPage = event; - this.search({ query: this.currentSearchQuery }); - } - /** * Search in the groups (searches by group name and by uuid exact match) * @param data Contains query param */ search(data: any) { + const query: string = data.query; if (query != null && this.currentSearchQuery !== query) { this.router.navigateByUrl(this.groupService.getGroupRegistryRouterLink()); @@ -128,44 +125,61 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub); } - this.searchSub = this.groupService.searchGroups(this.currentSearchQuery.trim(), { - currentPage: this.config.currentPage, - elementsPerPage: this.config.pageSize - }).pipe( - getAllSucceededRemoteDataPayload(), - switchMap((groups: PaginatedList) => { - if (groups.page.length === 0) { - return observableOf(buildPaginatedList(groups.pageInfo, [])); + this.searchSub = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( + switchMap((paginationOptions) => { + const query: string = data.query; + if (query != null && this.currentSearchQuery !== query) { + this.router.navigate([], { + queryParamsHandling: 'merge' + }); + this.currentSearchQuery = query; + this.paginationService.resetPage(this.config.id); } - return observableCombineLatest(groups.page.map((group: Group) => { - if (!this.deletedGroupsIds.includes(group.id)) { - return observableCombineLatest([ - this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(group) ? group.self : undefined), - this.hasLinkedDSO(group), - this.getSubgroups(group), - this.getMembers(group) - ]).pipe( - map(([isAuthorized, hasLinkedDSO, subgroups, members]: - [boolean, boolean, RemoteData>, RemoteData>]) => { - const groupDtoModel: GroupDtoModel = new GroupDtoModel(); - groupDtoModel.ableToDelete = isAuthorized && !hasLinkedDSO; - groupDtoModel.group = group; - groupDtoModel.subgroups = subgroups.payload; - groupDtoModel.epersons = members.payload; - return groupDtoModel; - } - ) - ); + if (hasValue(this.searchSub)) { + this.searchSub.unsubscribe(); + this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub); + } + return this.groupService.searchGroups(this.currentSearchQuery.trim(), { + currentPage: paginationOptions.currentPage, + elementsPerPage: paginationOptions.pageSize + }).pipe( + getAllSucceededRemoteData() + switchMap((groups: PaginatedList) => { + if (groups.page.length === 0) { + return observableOf(buildPaginatedList(groups.pageInfo, [])); } - })).pipe(map((dtos: GroupDtoModel[]) => { - return buildPaginatedList(groups.pageInfo, dtos); - })); - })).subscribe((value: PaginatedList) => { - this.groupsDto$.next(value); - this.pageInfoState$.next(value.pageInfo); - }); - this.subs.push(this.searchSub); - } + return observableCombineLatest(groups.page.map((group: Group) => { + if (!this.deletedGroupsIds.includes(group.id)) { + return observableCombineLatest([ + this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(group) ? group.self : undefined), + this.hasLinkedDSO(group), + this.getSubgroups(group), + this.getMembers(group) + ]).pipe( + map(([isAuthorized, hasLinkedDSO, subgroups, members]: + [boolean, boolean, RemoteData>, RemoteData>]) => { + const groupDtoModel: GroupDtoModel = new GroupDtoModel(); + groupDtoModel.ableToDelete = isAuthorized && !hasLinkedDSO; + groupDtoModel.group = group; + groupDtoModel.subgroups = subgroups.payload; + groupDtoModel.epersons = members.payload; + return groupDtoModel; + } + ) + ); + } + })).pipe(map((dtos: GroupDtoModel[]) => { + return buildPaginatedList(groups.pageInfo, dtos); + })); + }) + ). + subscribe((value: PaginatedList) => { + this.groupsDto$.next(value); + this.pageInfoState$.next(value.pageInfo); + }); + this.subs.push(this.searchSub); + + } /** * Delete Group @@ -244,6 +258,9 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { } cleanupSubscribes() { + if (hasValue(this.paginationSub)) { + this.paginationSub.unsubscribe(); + } this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); } } diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.html b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.html index e5cf7cf5ec..6569b2d4c8 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.html +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.html @@ -14,8 +14,7 @@ [pageInfoState]="(bitstreamFormats | async)?.payload" [collectionSize]="(bitstreamFormats | async)?.payload?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChange($event)"> + [hidePagerWhenSinglePage]="true">
diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts index 869e57ef89..7ae117b0a5 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, zip } from 'rxjs'; +import { combineLatest as observableCombineLatest, Observable, zip } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; @@ -12,6 +12,7 @@ import { NotificationsService } from '../../../shared/notifications/notification import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { NoContent } from '../../../core/shared/NoContent.model'; +import { PaginationService } from '../../../core/pagination/pagination.service'; /** * This component renders a list of bitstream formats @@ -30,7 +31,7 @@ export class BitstreamFormatsComponent implements OnInit { /** * A BehaviourSubject that keeps track of the pageState used to update the currently displayed bitstreamFormats */ - pageState: BehaviorSubject; + // pageState: BehaviorSubject; /** * The current pagination configuration for the page used by the FindAll method @@ -45,14 +46,16 @@ export class BitstreamFormatsComponent implements OnInit { * Currently simply renders all bitstream formats */ pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'registry-bitstreamformats-pagination', + id: 'rbp', pageSize: 20 }); constructor(private notificationsService: NotificationsService, private router: Router, private translateService: TranslateService, - private bitstreamFormatService: BitstreamFormatDataService) { + private bitstreamFormatService: BitstreamFormatDataService, + private paginationService: PaginationService, + ) { } /** @@ -80,10 +83,8 @@ export class BitstreamFormatsComponent implements OnInit { this.deselectAll(); - this.router.navigate([], { - queryParams: Object.assign({}, { page: 1 }), - queryParamsHandling: 'merge' - }); }); + this.paginationService.resetPage(this.pageConfig.id); + }); } ); } @@ -141,31 +142,12 @@ export class BitstreamFormatsComponent implements OnInit { }); } - /** - * When the page is changed, make sure to update the list of bitstreams to match the new page - * @param event The page change event - */ - onPageChange(event) { - this.config = Object.assign(new FindListOptions(), this.config, { - currentPage: event, - }); - this.pageConfig.currentPage = event; - this.pageState.next('pageChange'); - } - ngOnInit(): void { - this.pageState = new BehaviorSubject('init'); - this.bitstreamFormats = this.pageState.pipe( - switchMap(() => { - return this.updateFormats() - ; - })); - } - /** - * Finds all formats based on the current config - */ - private updateFormats() { - return this.bitstreamFormatService.findAll(this.config); + this.bitstreamFormats = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((findListOptions: FindListOptions) => { + return this.bitstreamFormatService.findAll(findListOptions); + }) + ); } } diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.html b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.html index 42b7558397..771f18ba4b 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.html +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.html @@ -13,8 +13,7 @@ [paginationOptions]="config" [collectionSize]="(metadataSchemas | async)?.payload?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChange($event)"> + [hidePagerWhenSinglePage]="true">
diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts index 41efb7a578..41b14ace88 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts @@ -13,6 +13,7 @@ import { MetadataSchema } from '../../../core/metadata/metadata-schema.model'; import { toFindListOptions } from '../../../shared/pagination/pagination.utils'; import { NoContent } from '../../../core/shared/NoContent.model'; import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; +import { PaginationService } from '../../../core/pagination/pagination.service'; @Component({ selector: 'ds-metadata-registry', @@ -34,7 +35,7 @@ export class MetadataRegistryComponent { * Pagination config used to display the list of metadata schemas */ config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'registry-metadataschemas-pagination', + id: 'rm', pageSize: 25 }); @@ -46,26 +47,20 @@ export class MetadataRegistryComponent { constructor(private registryService: RegistryService, private notificationsService: NotificationsService, private router: Router, + private paginationService: PaginationService, private translateService: TranslateService) { this.updateSchemas(); } - /** - * Event triggered when the user changes page - * @param event - */ - onPageChange(event) { - this.config.currentPage = event; - this.forceUpdateSchemas(); - } - /** * Update the list of schemas by fetching it from the rest api or cache */ private updateSchemas() { + this.metadataSchemas = this.needsUpdate$.pipe( filter((update) => update === true), - switchMap(() => this.registryService.getMetadataSchemas(toFindListOptions(this.config))) + switchMap(() => this.paginationService.getCurrentPagination(this.config.id, this.config)), + switchMap((currentPagination) => this.registryService.getMetadataSchemas(toFindListOptions(currentPagination))) ); } @@ -169,7 +164,7 @@ export class MetadataRegistryComponent { const suffix = success ? 'success' : 'failure'; const messages = observableCombineLatest( this.translateService.get(success ? `${prefix}.${suffix}` : `${prefix}.${suffix}`), - this.translateService.get(`${prefix}.deleted.${suffix}`, { amount: amount }) + this.translateService.get(`${prefix}.deleted.${suffix}`, {amount: amount}) ); messages.subscribe(([head, content]) => { if (success) { diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.html b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.html index 49ef748349..49fed0c847 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.html +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.html @@ -19,8 +19,7 @@ [pageInfoState]="fields" [collectionSize]="fields?.totalElements" [hideGear]="false" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChange($event)"> + [hidePagerWhenSinglePage]="true">
diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts index 572bcc8a51..513f689f84 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts @@ -6,6 +6,7 @@ import { combineLatest as observableCombineLatest, combineLatest, Observable, + of as observableOf, zip } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; @@ -17,12 +18,10 @@ import { NotificationsService } from '../../../shared/notifications/notification import { TranslateService } from '@ngx-translate/core'; import { MetadataField } from '../../../core/metadata/metadata-field.model'; import { MetadataSchema } from '../../../core/metadata/metadata-schema.model'; -import { - getFirstCompletedRemoteData, - getFirstSucceededRemoteDataPayload -} from '../../../core/shared/operators'; +import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { toFindListOptions } from '../../../shared/pagination/pagination.utils'; import { NoContent } from '../../../core/shared/NoContent.model'; +import { PaginationService } from '../../../core/pagination/pagination.service'; @Component({ selector: 'ds-metadata-schema', @@ -48,7 +47,7 @@ export class MetadataSchemaComponent implements OnInit { * Pagination config used to display the list of metadata fields */ config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'registry-metadatafields-pagination', + id: 'rm', pageSize: 25, pageSizeOptions: [25, 50, 100, 200] }); @@ -62,6 +61,7 @@ export class MetadataSchemaComponent implements OnInit { private route: ActivatedRoute, private notificationsService: NotificationsService, private router: Router, + private paginationService: PaginationService, private translateService: TranslateService) { } @@ -81,25 +81,17 @@ export class MetadataSchemaComponent implements OnInit { this.updateFields(); } - /** - * Event triggered when the user changes page - * @param event - */ - onPageChange(event) { - this.config.currentPage = event; - this.forceUpdateFields(); - } - /** * Update the list of fields by fetching it from the rest api or cache */ private updateFields() { - this.metadataFields$ = combineLatest(this.metadataSchema$, this.needsUpdate$).pipe( - switchMap(([schema, update]: [MetadataSchema, boolean]) => { + this.metadataFields$ = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( + switchMap((currentPagination) => combineLatest(this.metadataSchema$, this.needsUpdate$, observableOf(currentPagination))), + switchMap(([schema, update, currentPagination]: [MetadataSchema, boolean, PaginationComponentOptions]) => { if (update) { this.needsUpdate$.next(false); } - return this.registryService.getMetadataFieldsBySchema(schema, toFindListOptions(this.config), !update, true); + return this.registryService.getMetadataFieldsBySchema(schema, toFindListOptions(currentPagination), !update, true); }) ); } diff --git a/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.ts b/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.ts index 03c50dd051..7e3979e439 100644 --- a/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.ts +++ b/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.ts @@ -8,12 +8,16 @@ import { combineLatest as observableCombineLatest } from 'rxjs'; import { RemoteData } from '../../core/data/remote-data'; import { Item } from '../../core/shared/item.model'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { BrowseService } from '../../core/browse/browse.service'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { StartsWithType } from '../../shared/starts-with/starts-with-decorator'; import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator'; import { environment } from '../../../environments/environment'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { map } from 'rxjs/operators'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortOptions } from '../../core/cache/models/sort-options.model'; @Component({ selector: 'ds-browse-by-date-page', @@ -37,30 +41,31 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent { protected browseService: BrowseService, protected dsoService: DSpaceObjectDataService, protected router: Router, + protected paginationService: PaginationService, protected cdRef: ChangeDetectorRef) { - super(route, browseService, dsoService, router); + super(route, browseService, dsoService, paginationService, router); } ngOnInit(): void { this.startsWithType = StartsWithType.date; this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig)); + const currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); + const currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig); this.subs.push( - observableCombineLatest( - this.route.params, - this.route.queryParams, - this.route.data, - (params, queryParams, data ) => { - return Object.assign({}, params, queryParams, data); + observableCombineLatest([this.route.params, this.route.queryParams, this.route.data, + currentPagination$, currentSort$]).pipe( + map(([routeParams, queryParams, data, currentPage, currentSort]) => { + return [Object.assign({}, routeParams, queryParams, data), currentPage, currentSort]; }) - .subscribe((params) => { - const metadataField = params.metadataField || this.defaultMetadataField; - this.browseId = params.id || this.defaultBrowseId; - this.startsWith = +params.startsWith || params.startsWith; - const searchOptions = browseParamsToOptions(params, Object.assign({}), this.sortConfig, this.browseId); - this.updatePageWithItems(searchOptions, this.value); - this.updateParent(params.scope); - this.updateStartsWithOptions(this.browseId, metadataField, params.scope); - })); + ).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => { + const metadataField = params.metadataField || this.defaultMetadataField; + this.browseId = params.id || this.defaultBrowseId; + this.startsWith = +params.startsWith || params.startsWith; + const searchOptions = browseParamsToOptions(params, currentPage, currentSort, this.browseId); + this.updatePageWithItems(searchOptions, this.value); + this.updateParent(params.scope); + this.updateStartsWithOptions(this.browseId, metadataField, params.scope); + })); } /** 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 45f2ef3b2a..d770d8cb01 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 @@ -33,9 +33,7 @@ [startsWithOptions]="startsWithOptions" [enableArrows]="true" (prev)="goPrev()" - (next)="goNext()" - (pageSizeChange)="pageSizeChange($event)" - (sortDirectionChange)="sortDirectionChange($event)"> + (next)="goNext()"> diff --git a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts index 3b67d2e3d0..54359ff0c3 100644 --- a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts +++ b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts @@ -4,7 +4,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { BrowseService } from '../../core/browse/browse.service'; import { BrowseEntry } from '../../core/shared/browse-entry.model'; @@ -15,6 +15,8 @@ import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.serv import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { StartsWithType } from '../../shared/starts-with/starts-with-decorator'; import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { map } from 'rxjs/operators'; @Component({ selector: 'ds-browse-by-metadata-page', @@ -48,7 +50,7 @@ export class BrowseByMetadataPageComponent implements OnInit { * The pagination config used to display the values */ paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'browse-by-metadata-pagination', + id: 'bbm', currentPage: 1, pageSize: 20 }); @@ -100,23 +102,24 @@ export class BrowseByMetadataPageComponent implements OnInit { public constructor(protected route: ActivatedRoute, protected browseService: BrowseService, protected dsoService: DSpaceObjectDataService, + protected paginationService: PaginationService, protected router: Router) { } ngOnInit(): void { this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig)); + const currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); + const currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig); this.subs.push( - observableCombineLatest( - this.route.params, - this.route.queryParams, - (params, queryParams, ) => { - return Object.assign({}, params, queryParams); + observableCombineLatest([this.route.params, this.route.queryParams, currentPagination$, currentSort$]).pipe( + map(([routeParams, queryParams, currentPage, currentSort]) => { + return [Object.assign({}, routeParams, queryParams),currentPage,currentSort]; }) - .subscribe((params) => { + ).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => { this.browseId = params.id || this.defaultBrowseId; this.value = +params.value || params.value || ''; this.startsWith = +params.startsWith || params.startsWith; - const searchOptions = browseParamsToOptions(params, this.paginationConfig, this.sortConfig, this.browseId); + const searchOptions = browseParamsToOptions(params, currentPage, currentSort, this.browseId); if (isNotEmpty(this.value)) { this.updatePageWithItems(searchOptions, this.value); } else { @@ -203,28 +206,6 @@ export class BrowseByMetadataPageComponent implements OnInit { } } - /** - * Change the page size - * @param size - */ - pageSizeChange(size) { - this.router.navigate([], { - queryParams: Object.assign({ pageSize: size }), - queryParamsHandling: 'merge' - }); - } - - /** - * Change the sorting direction - * @param direction - */ - sortDirectionChange(direction) { - this.router.navigate([], { - queryParams: Object.assign({ sortDirection: direction }), - queryParamsHandling: 'merge' - }); - } - ngOnDestroy(): void { this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); } @@ -244,20 +225,8 @@ export function browseParamsToOptions(params: any, metadata?: string): BrowseEntrySearchOptions { return new BrowseEntrySearchOptions( metadata, - Object.assign({}, - paginationConfig, - { - currentPage: +params.page || paginationConfig.currentPage, - pageSize: +params.pageSize || paginationConfig.pageSize - } - ), - Object.assign({}, - sortConfig, - { - direction: params.sortDirection || sortConfig.direction, - field: params.sortField || sortConfig.field - } - ), + paginationConfig, + sortConfig, +params.startsWith || params.startsWith, params.scope ); diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts index 3b3c29c3fd..d62c58d644 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts @@ -1,7 +1,7 @@ import { combineLatest as observableCombineLatest } from 'rxjs'; import { Component } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { hasValue } from '../../shared/empty.util'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { BrowseByMetadataPageComponent, browseParamsToOptions @@ -11,6 +11,9 @@ import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.serv import { BrowseService } from '../../core/browse/browse.service'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { map } from 'rxjs/operators'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; @Component({ selector: 'ds-browse-by-title-page', @@ -26,26 +29,26 @@ export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent { public constructor(protected route: ActivatedRoute, protected browseService: BrowseService, protected dsoService: DSpaceObjectDataService, + protected paginationService: PaginationService, protected router: Router) { - super(route, browseService, dsoService, router); + super(route, browseService, dsoService, paginationService, router); } ngOnInit(): void { this.sortConfig = new SortOptions('dc.title', SortDirection.ASC); this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig)); + const currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); + const currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig); this.subs.push( - observableCombineLatest( - this.route.params, - this.route.queryParams, - this.route.data, - (params, queryParams, data ) => { - return Object.assign({}, params, queryParams, data); + observableCombineLatest([this.route.params, this.route.queryParams, currentPagination$, currentSort$]).pipe( + map(([routeParams, queryParams, currentPage, currentSort]) => { + return [Object.assign({}, routeParams, queryParams),currentPage,currentSort]; }) - .subscribe((params) => { - this.browseId = params.id || this.defaultBrowseId; - this.updatePageWithItems(browseParamsToOptions(params, this.paginationConfig, this.sortConfig, this.browseId), undefined); - this.updateParent(params.scope); - })); + ).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => { + this.browseId = params.id || this.defaultBrowseId; + this.updatePageWithItems(browseParamsToOptions(params, currentPage, currentSort, this.browseId), undefined); + this.updateParent(params.scope); + })); this.updateStartsWithTextOptions(); } diff --git a/src/app/+collection-page/collection-page.component.html b/src/app/+collection-page/collection-page.component.html index beb7413415..c2ad063d4a 100644 --- a/src/app/+collection-page/collection-page.component.html +++ b/src/app/+collection-page/collection-page.component.html @@ -52,8 +52,7 @@ [config]="paginationConfig" [sortConfig]="sortConfig" [objects]="itemRD" - [hideGear]="true" - (paginationChange)="onPaginationChange($event)"> + [hideGear]="true"> this.collectionRD$.pipe( + const currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); + const currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig); + + this.itemRD$ = observableCombineLatest([currentPagination$, currentSort$]).pipe( + switchMap(([currentPagination, currentSort ]) => this.collectionRD$.pipe( getFirstSucceededRemoteData(), map((rd) => rd.payload.id), switchMap((id: string) => { return this.searchService.search( new PaginatedSearchOptions({ scope: id, - pagination: dto.paginationConfig, - sort: dto.sortConfig, + pagination: currentPagination, + sort: currentSort, dsoTypes: [DSpaceObjectType.ITEM] })).pipe(toDSpaceObjectListRD()) as Observable>>; }), @@ -103,19 +108,4 @@ export class CollectionPageComponent implements OnInit { return isNotEmpty(object); } - onPaginationChange(event: PaginationChangeEvent) { - this.paginationConfig = Object.assign(new PaginationComponentOptions(), { - currentPage: event.pagination.currentPage || this.paginationConfig.currentPage, - pageSize: event.pagination.pageSize || this.paginationConfig.pageSize, - id: 'collection-page-pagination' - }); - this.sortConfig = Object.assign(new SortOptions('dc.date.accessioned', SortDirection.DESC), { - direction: event.sort.direction || this.sortConfig.direction, - field: event.sort.field || this.sortConfig.field - }); - this.paginationChanges$.next({ - paginationConfig: this.paginationConfig, - sortConfig: this.sortConfig - }); - } } diff --git a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.html b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.html index bf6ce7fd57..9928ebd18a 100644 --- a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.html +++ b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.html @@ -5,8 +5,7 @@ [config]="config" [sortConfig]="sortConfig" [objects]="subCollectionsRD" - [hideGear]="false" - (paginationChange)="onPaginationChange($event)"> + [hideGear]="false"> diff --git a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts index 261ae41aa2..4f37934575 100644 --- a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts +++ b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, combineLatest as observableCombineLatest } from 'rxjs'; import { RemoteData } from '../../core/data/remote-data'; import { Collection } from '../../core/shared/collection.model'; @@ -10,7 +10,8 @@ import { PaginatedList } from '../../core/data/paginated-list.model'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { CollectionDataService } from '../../core/data/collection-data.service'; -import { takeUntilCompletedRemoteData } from '../../core/shared/operators'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { switchMap } from 'rxjs/operators'; @Component({ selector: 'ds-community-page-sub-collection-list', @@ -29,7 +30,7 @@ export class CommunityPageSubCollectionListComponent implements OnInit { /** * The pagination id */ - pageId = 'community-collections-pagination'; + pageId = 'cmcl'; /** * The sorting configuration @@ -41,7 +42,10 @@ export class CommunityPageSubCollectionListComponent implements OnInit { */ subCollectionsRDObs: BehaviorSubject>> = new BehaviorSubject>>({} as any); - constructor(private cds: CollectionDataService) {} + constructor(private cds: CollectionDataService, + private paginationService: PaginationService, + + ) {} ngOnInit(): void { this.config = new PaginationComponentOptions(); @@ -49,30 +53,25 @@ export class CommunityPageSubCollectionListComponent implements OnInit { this.config.pageSize = 5; this.config.currentPage = 1; this.sortConfig = new SortOptions('dc.title', SortDirection.ASC); - this.updatePage(); + this.initPage(); } /** - * Called when one of the pagination settings is changed - * @param event The new pagination data + * Initialise the list of collections */ - onPaginationChange(event) { - this.config.currentPage = event.pagination.currentPage; - this.config.pageSize = event.pagination.pageSize; - this.sortConfig.field = event.sort.field; - this.sortConfig.direction = event.sort.direction; - this.updatePage(); - } + initPage() { + const pagination$ = this.paginationService.getCurrentPagination(this.config.id, this.config); + const sort$ = this.paginationService.getCurrentSort(this.config.id, this.sortConfig); - /** - * Update the list of collections - */ - updatePage() { - this.cds.findByParent(this.community.id,{ - currentPage: this.config.currentPage, - elementsPerPage: this.config.pageSize, - sort: { field: this.sortConfig.field, direction: this.sortConfig.direction } - }).pipe(takeUntilCompletedRemoteData()).subscribe((results) => { + observableCombineLatest([pagination$, sort$]).pipe( + switchMap(([currentPagination, currentSort]) => { + return this.cds.findByParent(this.community.id, { + currentPage: currentPagination.currentPage, + elementsPerPage: currentPagination.pageSize, + sort: {field: currentSort.field, direction: currentSort.direction} + }); + }) + ).subscribe((results) => { this.subCollectionsRDObs.next(results); }); } diff --git a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.html b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.html index 880ea9cc8e..2d14dce60a 100644 --- a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.html +++ b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.html @@ -5,8 +5,7 @@ [config]="config" [sortConfig]="sortConfig" [objects]="subCommunitiesRD" - [hideGear]="false" - (paginationChange)="onPaginationChange($event)"> + [hideGear]="false"> diff --git a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.ts b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.ts index c9f72fbc04..ffa2870a90 100644 --- a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.ts +++ b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, combineLatest as observableCombineLatest } from 'rxjs'; import { RemoteData } from '../../core/data/remote-data'; import { Community } from '../../core/shared/community.model'; @@ -10,6 +10,8 @@ import { PaginationComponentOptions } from '../../shared/pagination/pagination-c import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { CommunityDataService } from '../../core/data/community-data.service'; import { takeUntilCompletedRemoteData } from '../../core/shared/operators'; +import { switchMap } from 'rxjs/operators'; +import { PaginationService } from '../../core/pagination/pagination.service'; @Component({ selector: 'ds-community-page-sub-community-list', @@ -31,7 +33,7 @@ export class CommunityPageSubCommunityListComponent implements OnInit { /** * The pagination id */ - pageId = 'community-subCommunities-pagination'; + pageId = 'cmscm'; /** * The sorting configuration @@ -43,7 +45,9 @@ export class CommunityPageSubCommunityListComponent implements OnInit { */ subCommunitiesRDObs: BehaviorSubject>> = new BehaviorSubject>>({} as any); - constructor(private cds: CommunityDataService) { + constructor(private cds: CommunityDataService, + private paginationService: PaginationService + ) { } ngOnInit(): void { @@ -52,25 +56,29 @@ export class CommunityPageSubCommunityListComponent implements OnInit { this.config.pageSize = 5; this.config.currentPage = 1; this.sortConfig = new SortOptions('dc.title', SortDirection.ASC); - this.updatePage(); - } - - /** - * Called when one of the pagination settings is changed - * @param event The new pagination data - */ - onPaginationChange(event) { - this.config.currentPage = event.pagination.currentPage; - this.config.pageSize = event.pagination.pageSize; - this.sortConfig.field = event.sort.field; - this.sortConfig.direction = event.sort.direction; - this.updatePage(); + this.initPage(); } /** * Update the list of sub-communities */ - updatePage() { + initPage() { + const pagination$ = this.paginationService.getCurrentPagination(this.config.id, this.config); + const sort$ = this.paginationService.getCurrentSort(this.config.id, this.sortConfig); + + observableCombineLatest([pagination$, sort$]).pipe( + switchMap(([currentPagination, currentSort]) => { + return this.cds.findByParent(this.community.id, { + currentPage: currentPagination.currentPage, + elementsPerPage: currentPagination.pageSize, + sort: { field: currentSort.field, direction: currentSort.direction } + }); + }) + ).subscribe((results) => { + this.subCommunitiesRDObs.next(results); + }); + + this.cds.findByParent(this.community.id, { currentPage: this.config.currentPage, elementsPerPage: this.config.pageSize, diff --git a/src/app/+home-page/top-level-community-list/top-level-community-list.component.html b/src/app/+home-page/top-level-community-list/top-level-community-list.component.html index f318a04f38..dbea87a175 100644 --- a/src/app/+home-page/top-level-community-list/top-level-community-list.component.html +++ b/src/app/+home-page/top-level-community-list/top-level-community-list.component.html @@ -6,8 +6,7 @@ [config]="config" [sortConfig]="sortConfig" [objects]="communitiesRD$ | async" - [hideGear]="true" - (paginationChange)="onPaginationChange($event)"> + [hideGear]="true"> diff --git a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts index b089244008..137675e4fc 100644 --- a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts +++ b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, OnInit, OnDestroy } from '@angular/core'; -import { BehaviorSubject, Subscription } from 'rxjs'; +import { BehaviorSubject, combineLatest as observableCombineLatest, Subscription } from 'rxjs'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { CommunityDataService } from '../../core/data/community-data.service'; @@ -10,6 +10,8 @@ import { Community } from '../../core/shared/community.model'; import { fadeInOut } from '../../shared/animations/fade'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { hasValue } from '../../shared/empty.util'; +import { switchMap } from 'rxjs/operators'; +import { PaginationService } from '../../core/pagination/pagination.service'; /** * this component renders the Top-Level Community list @@ -36,7 +38,7 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy { /** * The pagination id */ - pageId = 'top-level-pagination'; + pageId = 'tl'; /** * The sorting configuration @@ -48,7 +50,8 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy { */ currentPageSubscription: Subscription; - constructor(private cds: CommunityDataService) { + constructor(private cds: CommunityDataService, + private paginationService: PaginationService) { this.config = new PaginationComponentOptions(); this.config.id = this.pageId; this.config.pageSize = 5; @@ -57,31 +60,26 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy { } ngOnInit() { - this.updatePage(); + this.initPage(); } - /** - * Called when one of the pagination settings is changed - * @param event The new pagination data - */ - onPaginationChange(event) { - this.config.currentPage = event.pagination.currentPage; - this.config.pageSize = event.pagination.pageSize; - this.sortConfig.field = event.sort.field; - this.sortConfig.direction = event.sort.direction; - this.updatePage(); - } /** * Update the list of top communities */ - updatePage() { - this.unsubscribe(); - this.currentPageSubscription = this.cds.findTop({ - currentPage: this.config.currentPage, - elementsPerPage: this.config.pageSize, - sort: { field: this.sortConfig.field, direction: this.sortConfig.direction } - }).subscribe((results) => { + initPage() { + const pagination$ = this.paginationService.getCurrentPagination(this.config.id, this.config); + const sort$ = this.paginationService.getCurrentSort(this.config.id, this.sortConfig); + + this.currentPageSubscription = observableCombineLatest([pagination$, sort$]).pipe( + switchMap(([currentPagination, currentSort]) => { + return this.cds.findTop({ + currentPage: currentPagination.currentPage, + elementsPerPage: currentPagination.pageSize, + sort: {field: currentSort.field, direction: currentSort.direction} + }); + }) + ).subscribe((results) => { this.communitiesRD$.next(results); }); } diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.html b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.html index 9197b89796..8f0d83bd1f 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.html +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.html @@ -4,9 +4,7 @@ [hidePaginationDetail]="true" [paginationOptions]="options" [pageInfoState]="(objectsRD$ | async)?.payload" - [collectionSize]="(objectsRD$ | async)?.payload?.totalElements" - [disableRouteParameterUpdate]="true" - (pageChange)="switchPage($event)"> + [collectionSize]="(objectsRD$ | async)?.payload?.totalElements">
} Emits the current pagination settings + */ + getCurrentPagination(paginationId: string, defaultPagination: PaginationComponentOptions): Observable { + const page$ = this.routeService.getQueryParameterValue(`p.${paginationId}`); + const size$ = this.routeService.getQueryParameterValue(`rpp.${paginationId}`); + return observableCombineLatest([page$, size$]).pipe(map(([page, size]) => { + return Object.assign(new PaginationComponentOptions(), defaultPagination, { + currentPage: this.convertToNumeric(page, defaultPagination.currentPage), + pageSize: this.getBestMatchPageSize(size, defaultPagination) + }); + }) + ); + } + + /** + * @returns {Observable} Emits the current sorting settings + */ + getCurrentSort(paginationId: string, defaultSort: SortOptions, ignoreDefault?: boolean): Observable { + if (!ignoreDefault && (isEmpty(defaultSort) || !hasValue(defaultSort))) { + defaultSort = this.defaultSortOptions; + } + const sortDirection$ = this.routeService.getQueryParameterValue(`sd.${paginationId}`); + const sortField$ = this.routeService.getQueryParameterValue(`sf.${paginationId}`); + return observableCombineLatest([sortDirection$, sortField$]).pipe(map(([sortDirection, sortField]) => { + const field = sortField || defaultSort?.field; + const direction = SortDirection[sortDirection] || defaultSort?.direction; + return new SortOptions(field, direction); + }) + ); + } + + getFindListOptions(paginationId: string, defaultFindList: FindListOptions, ignoreDefault?: boolean): Observable { + const paginationComponentOptions = new PaginationComponentOptions(); + paginationComponentOptions.currentPage = defaultFindList.currentPage; + paginationComponentOptions.pageSize = defaultFindList.elementsPerPage; + const currentPagination$ = this.getCurrentPagination(paginationId, paginationComponentOptions); + const currentSortOptions$ = this.getCurrentSort(paginationId, defaultFindList.sort, ignoreDefault); + + return observableCombineLatest([currentPagination$, currentSortOptions$]).pipe( + filter(([currentPagination, currentSortOptions]) => hasValue(currentPagination) && hasValue(currentSortOptions)), + map(([currentPagination, currentSortOptions]) => { + return Object.assign(new FindListOptions(), defaultFindList, { + sort: currentSortOptions, + currentPage: currentPagination.currentPage, + elementsPerPage: currentPagination.pageSize + }); + })); + } + + resetPage(paginationId: string) { + this.updateRoute(paginationId, {page: 1}); + } + + getCurrentRouting(paginationId: string) { + return this.getFindListOptions(paginationId, {}, true).pipe( + take(1), + map((findListoptions: FindListOptions) => { + return { + page: findListoptions.currentPage, + pageSize: findListoptions.elementsPerPage, + sortField: findListoptions.sort.field, + sortDir: findListoptions.sort.direction, + }; + }) + ); + } + + updateRoute(paginationId: string, params: { + page?: number + pageSize?: number + sortField?: string + sortDirection?: SortDirection + }, extraParams?, changeLocationNot?: boolean) { + this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { + const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); + const parametersWithIdName = this.getParametersWithIdName(paginationId, params); + if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { + const queryParams = Object.assign({}, currentParametersWithIdName, + parametersWithIdName, extraParams); + if (changeLocationNot) { + this.location.go(this.router.createUrlTree([], { + relativeTo: this.route, queryParams: queryParams, queryParamsHandling: 'merge' + }).toString()); + } else { + this.router.navigate([], { + queryParams: queryParams, + queryParamsHandling: 'merge' + }); + } + } + }); + } + + updateRouteWithUrl(paginationId: string, url: string[], params: { + page?: number + pageSize?: number + sortField?: string + sortDirection?: SortDirection + }, extraParams?, changeLocationNot?: boolean) { + this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { + const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); + const parametersWithIdName = this.getParametersWithIdName(paginationId, params); + if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { + const queryParams = Object.assign({}, currentParametersWithIdName, + parametersWithIdName, extraParams); + if (changeLocationNot) { + this.location.go(this.router.createUrlTree([], { + relativeTo: this.route, queryParams: queryParams, queryParamsHandling: 'merge' + }).toString()); + } else { + this.router.navigate(url, { + queryParams: queryParams, + queryParamsHandling: 'merge' + }); + } + } + }); + } + + + getParametersWithIdName(paginationId: string, params: { + page?: number + pageSize?: number + sortField?: string + sortDirection?: SortDirection + }) { + const paramsWithIdName = {}; + if (hasValue(params.page)) { + paramsWithIdName[`p.${paginationId}`] = `${params.page}`; + } + if (hasValue(params.pageSize)) { + paramsWithIdName[`rpp.${paginationId}`] = `${params.pageSize}`; + } + if (hasValue(params.sortField)) { + paramsWithIdName[`sf.${paginationId}`] = `${params.sortField}`; + } + if (hasValue(params.sortDirection)) { + paramsWithIdName[`sd.${paginationId}`] = `${params.sortDirection}`; + } + return paramsWithIdName; + } + + private convertToNumeric(param, defaultValue) { + let result = defaultValue; + if (isNumeric(param)) { + result = +param; + } + return result; + } + + + private getBestMatchPageSize(pageSize: any, defaultPagination: PaginationComponentOptions): number { + const numberPageSize = this.convertToNumeric(pageSize, defaultPagination.pageSize); + const differenceList = defaultPagination.pageSizeOptions.map((pageSizeOption) => { + return Math.abs(pageSizeOption - numberPageSize); + }); + const minDifference = Math.min.apply(Math, differenceList); + return defaultPagination.pageSizeOptions[differenceList.indexOf(minDifference)]; + } + +} diff --git a/src/app/core/shared/search/search-configuration.service.ts b/src/app/core/shared/search/search-configuration.service.ts index edd3982319..6639b53cb9 100644 --- a/src/app/core/shared/search/search-configuration.service.ts +++ b/src/app/core/shared/search/search-configuration.service.ts @@ -14,17 +14,21 @@ import { RouteService } from '../../services/route.service'; import { getFirstSucceededRemoteData } from '../operators'; import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { PaginationService } from '../../pagination/pagination.service'; +import { tap } from 'rxjs/internal/operators/tap'; /** * Service that performs all actions that have to do with the current search configuration */ @Injectable() export class SearchConfigurationService implements OnDestroy { + + public paginationID = 'spc'; /** * Default pagination settings */ protected defaultPagination = Object.assign(new PaginationComponentOptions(), { - id: 'search-page-configuration', + id: this.paginationID, pageSize: 10, currentPage: 1 }); @@ -75,6 +79,7 @@ export class SearchConfigurationService implements OnDestroy { * @param {ActivatedRoute} route */ constructor(protected routeService: RouteService, + protected paginationService: PaginationService, protected route: ActivatedRoute) { this.initDefaults(); @@ -91,7 +96,7 @@ export class SearchConfigurationService implements OnDestroy { this.paginatedSearchOptions = new BehaviorSubject(defs); this.searchOptions = new BehaviorSubject(defs); this.subs.push(this.subscribeToSearchOptions(defs)); - this.subs.push(this.subscribeToPaginatedSearchOptions(defs)); + this.subs.push(this.subscribeToPaginatedSearchOptions(defs.pagination.id, defs)); } ); } @@ -140,34 +145,15 @@ export class SearchConfigurationService implements OnDestroy { /** * @returns {Observable} Emits the current pagination settings */ - getCurrentPagination(defaultPagination: PaginationComponentOptions): Observable { - const page$ = this.routeService.getQueryParameterValue('page'); - const size$ = this.routeService.getQueryParameterValue('pageSize'); - return observableCombineLatest(page$, size$).pipe(map(([page, size]) => { - return Object.assign(new PaginationComponentOptions(), defaultPagination, { - currentPage: page || defaultPagination.currentPage, - pageSize: size || defaultPagination.pageSize - }); - }) - ); + getCurrentPagination(paginationId: string, defaultPagination: PaginationComponentOptions): Observable { + return this.paginationService.getCurrentPagination(paginationId, defaultPagination); } /** * @returns {Observable} Emits the current sorting settings */ - getCurrentSort(defaultSort: SortOptions): Observable { - const sortDirection$ = this.routeService.getQueryParameterValue('sortDirection'); - const sortField$ = this.routeService.getQueryParameterValue('sortField'); - return observableCombineLatest(sortDirection$, sortField$).pipe(map(([sortDirection, sortField]) => { - // Dirty fix because sometimes the observable value is null somehow - sortField = this.route.snapshot.queryParamMap.get('sortField'); - - const field = sortField || defaultSort.field; - const direction = SortDirection[sortDirection] || defaultSort.direction; - return new SortOptions(field, direction); - } - ) - ); + getCurrentSort(paginationId: string, defaultSort: SortOptions): Observable { + return this.paginationService.getCurrentSort(paginationId, defaultSort); } /** @@ -234,10 +220,10 @@ export class SearchConfigurationService implements OnDestroy { * @param {PaginatedSearchOptions} defaults Default values for when no parameters are available * @returns {Subscription} The subscription to unsubscribe from */ - private subscribeToPaginatedSearchOptions(defaults: PaginatedSearchOptions): Subscription { + private subscribeToPaginatedSearchOptions(paginationId: string, defaults: PaginatedSearchOptions): Subscription { return observableMerge( - this.getPaginationPart(defaults.pagination), - this.getSortPart(defaults.sort), + this.getPaginationPart(paginationId, defaults.pagination), + this.getSortPart(paginationId, defaults.sort), this.getConfigurationPart(defaults.configuration), this.getScopePart(defaults.scope), this.getQueryPart(defaults.query), @@ -317,8 +303,8 @@ export class SearchConfigurationService implements OnDestroy { /** * @returns {Observable} Emits the current pagination settings as a partial SearchOptions object */ - private getPaginationPart(defaultPagination: PaginationComponentOptions): Observable { - return this.getCurrentPagination(defaultPagination).pipe(map((pagination) => { + private getPaginationPart(paginationId: string, defaultPagination: PaginationComponentOptions): Observable { + return this.getCurrentPagination(paginationId, defaultPagination).pipe(map((pagination) => { return { pagination }; })); } @@ -326,8 +312,8 @@ export class SearchConfigurationService implements OnDestroy { /** * @returns {Observable} Emits the current sorting settings as a partial SearchOptions object */ - private getSortPart(defaultSort: SortOptions): Observable { - return this.getCurrentSort(defaultSort).pipe(map((sort) => { + private getSortPart(paginationId: string, defaultSort: SortOptions): Observable { + return this.getCurrentSort(paginationId, defaultSort).pipe(map((sort) => { return { sort }; })); } diff --git a/src/app/core/shared/search/search.service.ts b/src/app/core/shared/search/search.service.ts index b380a70d44..4dfd1964c3 100644 --- a/src/app/core/shared/search/search.service.ts +++ b/src/app/core/shared/search/search.service.ts @@ -1,7 +1,7 @@ import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; import { Injectable, OnDestroy } from '@angular/core'; -import { NavigationExtras, Router } from '@angular/router'; -import { first, map, switchMap, take } from 'rxjs/operators'; +import { Router } from '@angular/router'; +import { map, switchMap, take } from 'rxjs/operators'; import { followLink, FollowLinkConfig } from '../../../shared/utils/follow-link-config.model'; import { LinkService } from '../../cache/builders/link.service'; import { PaginatedList } from '../../data/paginated-list.model'; @@ -37,6 +37,10 @@ import { ListableObject } from '../../../shared/object-collection/shared/listabl import { getSearchResultFor } from '../../../shared/search/search-result-element-decorator'; import { FacetConfigResponse } from '../../../shared/search/facet-config-response.model'; import { FacetValues } from '../../../shared/search/facet-values.model'; +import { PaginationService } from '../../pagination/pagination.service'; +import { SearchConfigurationService } from './search-configuration.service'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { tap } from 'rxjs/internal/operators/tap'; /** * Service that performs all general actions that have to do with the search page @@ -75,7 +79,9 @@ export class SearchService implements OnDestroy { private linkService: LinkService, private halService: HALEndpointService, private communityService: CommunityDataService, - private dspaceObjectService: DSpaceObjectDataService + private dspaceObjectService: DSpaceObjectDataService, + private paginationService: PaginationService, + private searchConfigurationService: SearchConfigurationService ) { } @@ -380,20 +386,16 @@ export class SearchService implements OnDestroy { * @param {ViewMode} viewMode Mode to switch to */ setViewMode(viewMode: ViewMode, searchLinkParts?: string[]) { - this.routeService.getQueryParameterValue('pageSize').pipe(first()) - .subscribe((pageSize) => { - let queryParams = { view: viewMode, page: 1 }; + this.paginationService.getCurrentPagination(this.searchConfigurationService.paginationID, new PaginationComponentOptions()).pipe(take(1)) + .subscribe((config) => { + let pageParams = { page: 1 }; + const queryParams = { view: viewMode }; if (viewMode === ViewMode.DetailedListElement) { - queryParams = Object.assign(queryParams, {pageSize: '1'}); - } else if (pageSize === '1') { - queryParams = Object.assign(queryParams, {pageSize: '10'}); + pageParams = Object.assign(pageParams, {pageSize: 1}); + } else if (config.pageSize === 1) { + pageParams = Object.assign(pageParams, {pageSize: 10}); } - const navigationExtras: NavigationExtras = { - queryParams: queryParams, - queryParamsHandling: 'merge' - }; - - this.router.navigate(hasValue(searchLinkParts) ? searchLinkParts : [this.getSearchLink()], navigationExtras); + this.paginationService.updateRouteWithUrl(this.searchConfigurationService.paginationID, hasValue(searchLinkParts) ? searchLinkParts : [this.getSearchLink()], pageParams, queryParams); }); } diff --git a/src/app/process-page/overview/process-overview.component.html b/src/app/process-page/overview/process-overview.component.html index 30eb44430e..62b1433b2c 100644 --- a/src/app/process-page/overview/process-overview.component.html +++ b/src/app/process-page/overview/process-overview.component.html @@ -8,8 +8,7 @@ [pageInfoState]="(processesRD$ | async)?.payload" [collectionSize]="(processesRD$ | async)?.payload?.totalElements" [hideGear]="true" - [hidePagerWhenSinglePage]="true" - (pageChange)="onPageChange($event)"> + [hidePagerWhenSinglePage]="true">
diff --git a/src/app/process-page/overview/process-overview.component.ts b/src/app/process-page/overview/process-overview.component.ts index 541d6c212e..1ea8c5b9c6 100644 --- a/src/app/process-page/overview/process-overview.component.ts +++ b/src/app/process-page/overview/process-overview.component.ts @@ -8,8 +8,9 @@ import { FindListOptions } from '../../core/data/request.models'; import { EPersonDataService } from '../../core/eperson/eperson-data.service'; import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; import { EPerson } from '../../core/eperson/models/eperson.model'; -import { map } from 'rxjs/operators'; +import { map, switchMap } from 'rxjs/operators'; import { ProcessDataService } from '../../core/data/processes/process-data.service'; +import { PaginationService } from '../../core/pagination/pagination.service'; @Component({ selector: 'ds-process-overview', @@ -36,7 +37,7 @@ export class ProcessOverviewComponent implements OnInit { * The current pagination configuration for the page */ pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), { - id: 'process-overview-pagination', + id: 'po', pageSize: 20 }); @@ -46,6 +47,7 @@ export class ProcessOverviewComponent implements OnInit { dateFormat = 'yyyy-MM-dd HH:mm:ss'; constructor(protected processService: ProcessDataService, + protected paginationService: PaginationService, protected ePersonService: EPersonDataService) { } @@ -53,23 +55,13 @@ export class ProcessOverviewComponent implements OnInit { this.setProcesses(); } - /** - * When the page is changed, make sure to update the list of processes to match the new page - * @param event The page change event - */ - onPageChange(event) { - this.config = Object.assign(new FindListOptions(), this.config, { - currentPage: event, - }); - this.pageConfig.currentPage = event; - this.setProcesses(); - } - /** * Send a request to fetch all processes for the current page */ setProcesses() { - this.processesRD$ = this.processService.findAll(this.config); + this.processesRD$ = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe( + switchMap((config) => this.processService.findAll(config)) + ); } /** diff --git a/src/app/search-navbar/search-navbar.component.ts b/src/app/search-navbar/search-navbar.component.ts index 1bedfb73ef..1e509a180b 100644 --- a/src/app/search-navbar/search-navbar.component.ts +++ b/src/app/search-navbar/search-navbar.component.ts @@ -3,6 +3,8 @@ import { FormBuilder } from '@angular/forms'; import { Router } from '@angular/router'; import { SearchService } from '../core/shared/search/search.service'; import { expandSearchInput } from '../shared/animations/slide'; +import { PaginationService } from '../core/pagination/pagination.service'; +import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; /** * The search box in the header that expands on focus and collapses on focus out @@ -24,7 +26,9 @@ export class SearchNavbarComponent { // Search input field @ViewChild('searchInput') searchField: ElementRef; - constructor(private formBuilder: FormBuilder, private router: Router, private searchService: SearchService) { + constructor(private formBuilder: FormBuilder, private router: Router, private searchService: SearchService, + private paginationService: PaginationService, + private searchConfig: SearchConfigurationService) { this.searchForm = this.formBuilder.group(({ query: '', })); @@ -63,9 +67,6 @@ export class SearchNavbarComponent { this.collapse(); const linkToNavigateTo = this.searchService.getSearchLink().split('/'); this.searchForm.reset(); - this.router.navigate(linkToNavigateTo, { - queryParams: Object.assign({}, { page: 1 }, data), - queryParamsHandling: 'merge' - }); + this.paginationService.updateRouteWithUrl(this.searchConfig.paginationID, linkToNavigateTo, {page: 1}, data); } } diff --git a/src/app/shared/browse-by/browse-by.component.ts b/src/app/shared/browse-by/browse-by.component.ts index 8706c39e54..8920726c8b 100644 --- a/src/app/shared/browse-by/browse-by.component.ts +++ b/src/app/shared/browse-by/browse-by.component.ts @@ -7,6 +7,7 @@ import { fadeIn, fadeInOut } from '../animations/fade'; import { Observable } from 'rxjs'; import { ListableObject } from '../object-collection/shared/listable-object.model'; import { getStartsWithComponent, StartsWithType } from '../starts-with/starts-with-decorator'; +import { PaginationService } from '../../core/pagination/pagination.service'; @Component({ selector: 'ds-browse-by', @@ -96,7 +97,9 @@ export class BrowseByComponent implements OnInit { */ public sortDirections = SortDirection; - public constructor(private injector: Injector) { + public constructor(private injector: Injector, + protected paginationService: PaginationService, + ) { } @@ -119,8 +122,7 @@ export class BrowseByComponent implements OnInit { * @param size */ doPageSizeChange(size) { - this.paginationConfig.pageSize = size; - this.pageSizeChange.emit(size); + this.paginationService.updateRoute(this.paginationConfig.id,{pageSize: size}); } /** @@ -128,8 +130,7 @@ export class BrowseByComponent implements OnInit { * @param direction */ doSortDirectionChange(direction) { - this.sortConfig.direction = direction; - this.sortDirectionChange.emit(direction); + this.paginationService.updateRoute(this.paginationConfig.id,{sortDirection: direction}); } /** @@ -141,7 +142,10 @@ export class BrowseByComponent implements OnInit { ngOnInit(): void { this.objectInjector = Injector.create({ - providers: [{ provide: 'startsWithOptions', useFactory: () => (this.startsWithOptions), deps:[] }], + providers: [ + { provide: 'startsWithOptions', useFactory: () => (this.startsWithOptions), deps:[] }, + { provide: 'paginationId', useFactory: () => (this.paginationConfig.id), deps:[] } + ], parent: this.injector }); } diff --git a/src/app/shared/page-size-selector/page-size-selector.component.ts b/src/app/shared/page-size-selector/page-size-selector.component.ts index dfea7d423f..764a8063db 100644 --- a/src/app/shared/page-size-selector/page-size-selector.component.ts +++ b/src/app/shared/page-size-selector/page-size-selector.component.ts @@ -1,11 +1,12 @@ import { Component, Inject, OnInit } from '@angular/core'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; import { Observable } from 'rxjs'; -import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; import { PaginatedSearchOptions } from '../search/paginated-search-options.model'; -import { map } from 'rxjs/operators'; +import { map, take } from 'rxjs/operators'; +import { PaginationService } from '../../core/pagination/pagination.service'; @Component({ selector: 'ds-page-size-selector', @@ -22,8 +23,10 @@ export class PageSizeSelectorComponent implements OnInit { */ paginationOptions$: Observable; + constructor(private route: ActivatedRoute, private router: Router, + private paginationService: PaginationService, @Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService) { } @@ -40,13 +43,10 @@ export class PageSizeSelectorComponent implements OnInit { */ reloadRPP(event: Event) { const value = (event.target as HTMLInputElement).value; - const navigationExtras: NavigationExtras = { - queryParams: { - pageSize: value, - page: 1 - }, - queryParamsHandling: 'merge' - }; - this.router.navigate([], navigationExtras); + this.paginationOptions$.pipe( + take(1) + ).subscribe((pagination: PaginationComponentOptions) => { + this.paginationService.updateRoute(pagination.id, {page: 1, pageSize: +value}); + }) ; } } diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts index 4cc647d091..3b5d8bc3de 100644 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts +++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts @@ -17,6 +17,7 @@ import { Component, ElementRef, EventEmitter, OnDestroy, Output, ViewChild } fro import { PaginationComponent } from '../pagination/pagination.component'; import { ObjectValuesPipe } from '../utils/object-values-pipe'; import { compareArraysUsing } from '../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { PaginationService } from '../../core/pagination/pagination.service'; /** * Operator used for comparing {@link FieldUpdate}s by their field's UUID @@ -81,14 +82,14 @@ export abstract class AbstractPaginatedDragAndDropListComponent { + this.currentPage$.next(currentPagination.currentPage); + }); + } + /** * Initialize the field-updates in the store */ @@ -164,14 +177,6 @@ export abstract class AbstractPaginatedDragAndDropListComponent +
{{ 'pagination.showing.label' | translate }} - {{ 'pagination.showing.detail' | translate:getShowingDetails(collectionSize)}} + {{ 'pagination.showing.detail' | translate:(getShowingDetails(collectionSize)|async)}}
- + - +
@@ -20,15 +20,15 @@
-
diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts index dfd9ea65ab..26a7f47f52 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts +++ b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts @@ -20,6 +20,7 @@ import { EPersonDataService } from '../../../../core/eperson/eperson-data.servic import { GroupDataService } from '../../../../core/eperson/group-data.service'; import { fadeInOut } from '../../../animations/fade'; import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; export interface SearchEvent { scope: string; @@ -93,13 +94,16 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { */ private subs: Subscription[] = []; + private pageConfigSub: Subscription; + /** * Initialize instance variables and inject the properly DataService * * @param {DSONameService} dsoNameService * @param {Injector} parentInjector */ - constructor(public dsoNameService: DSONameService, private parentInjector: Injector) { + constructor(public dsoNameService: DSONameService, private parentInjector: Injector, + private paginationService: PaginationService) { } /** @@ -112,14 +116,14 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { providers: [], parent: this.parentInjector }).get(provider); - this.paginationOptions.id = uniqueId('eperson-group-list-pagination'); + this.paginationOptions.id = uniqueId('egl'); this.paginationOptions.pageSize = 5; if (this.initSelected) { this.entrySelectedId.next(this.initSelected); } - this.updateList(this.paginationOptions, this.currentSearchScope, this.currentSearchQuery); + this.updateList(this.currentSearchScope, this.currentSearchQuery); } /** @@ -151,13 +155,6 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { ); } - /** - * Method called on page change - */ - onPageChange(page: number): void { - this.paginationOptions.currentPage = page; - this.updateList(this.paginationOptions, this.currentSearchScope, this.currentSearchQuery); - } /** * Method called on search @@ -165,17 +162,22 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { onSearch(searchEvent: SearchEvent) { this.currentSearchQuery = searchEvent.query; this.currentSearchScope = searchEvent.scope; - this.paginationOptions.currentPage = 1; - this.updateList(this.paginationOptions, this.currentSearchScope, this.currentSearchQuery); + this.paginationService.resetPage(this.paginationOptions.id); + this.updateList(this.currentSearchScope, this.currentSearchQuery); } /** * Retrieve a paginate list of eperson or group */ - updateList(config: PaginationComponentOptions, scope: string, query: string): void { + updateList(scope: string, query: string): void { + if (hasValue(this.pageConfigSub)) { + this.pageConfigSub.unsubscribe(); + } + this.pageConfigSub = this.paginationService.getCurrentPagination(this.paginationOptions.id, this.paginationOptions) + .subscribe((paginationOptions) => { const options: FindListOptions = Object.assign({}, new FindListOptions(), { - elementsPerPage: config.pageSize, - currentPage: config.currentPage + elementsPerPage: paginationOptions.pageSize, + currentPage: paginationOptions.currentPage }); const search$: Observable>> = this.isListOfEPerson ? @@ -187,6 +189,7 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { this.list$.next(list); }) ); + }); } /** diff --git a/src/app/shared/search-form/search-form.component.ts b/src/app/shared/search-form/search-form.component.ts index 97541c4786..594f0c84e2 100644 --- a/src/app/shared/search-form/search-form.component.ts +++ b/src/app/shared/search-form/search-form.component.ts @@ -4,6 +4,8 @@ import { Router } from '@angular/router'; import { isNotEmpty } from '../empty.util'; import { SearchService } from '../../core/shared/search/search.service'; import { currentPath } from '../utils/route.utils'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; /** * This component renders a simple item page. @@ -60,7 +62,10 @@ export class SearchFormComponent { */ @Output() submitSearch = new EventEmitter(); - constructor(private router: Router, private searchService: SearchService) { + constructor(private router: Router, private searchService: SearchService, + private paginationService: PaginationService, + private searchConfig: SearchConfigurationService + ) { } /** @@ -85,10 +90,14 @@ export class SearchFormComponent { * @param data Updated parameters */ updateSearch(data: any) { - this.router.navigate(this.getSearchLinkParts(), { - queryParams: Object.assign({}, { page: 1 }, data), + const queryParams = Object.assign({}, data); + queryParams[`p.${this.searchConfig.paginationID}`] = 1; + + this.router.navigate(this.getSearchLinkParts(), { + queryParams: queryParams, queryParamsHandling: 'merge' }); + this.paginationService.updateRouteWithUrl(this.searchConfig.paginationID, this.getSearchLinkParts(), { page: 1 }, data); } /** diff --git a/src/app/shared/search/search-settings/search-settings.component.ts b/src/app/shared/search/search-settings/search-settings.component.ts index 45d7c7b432..6f12c161ea 100644 --- a/src/app/shared/search/search-settings/search-settings.component.ts +++ b/src/app/shared/search/search-settings/search-settings.component.ts @@ -6,6 +6,7 @@ import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { Observable } from 'rxjs'; import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.component'; +import { PaginationService } from '../../../core/pagination/pagination.service'; @Component({ selector: 'ds-search-settings', @@ -30,6 +31,7 @@ export class SearchSettingsComponent implements OnInit { constructor(private service: SearchService, private route: ActivatedRoute, private router: Router, + private paginationService: PaginationService, @Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService) { } @@ -46,14 +48,10 @@ export class SearchSettingsComponent implements OnInit { */ reloadOrder(event: Event) { const values = (event.target as HTMLInputElement).value.split(','); - const navigationExtras: NavigationExtras = { - queryParams: { - sortDirection: values[1], - sortField: values[0], - page: 1 - }, - queryParamsHandling: 'merge' - }; - this.router.navigate([], navigationExtras); + this.paginationService.updateRoute(this.searchConfigurationService.paginationID, { + sortField: values[0], + sortDirection: values[1] as SortDirection, + page: 1 + }); } } diff --git a/src/app/shared/starts-with/date/starts-with-date.component.ts b/src/app/shared/starts-with/date/starts-with-date.component.ts index 75173212f9..e947fb76a2 100644 --- a/src/app/shared/starts-with/date/starts-with-date.component.ts +++ b/src/app/shared/starts-with/date/starts-with-date.component.ts @@ -4,6 +4,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { renderStartsWithFor, StartsWithType } from '../starts-with-decorator'; import { StartsWithAbstractComponent } from '../starts-with-abstract.component'; import { hasValue } from '../../empty.util'; +import { PaginationService } from '../../../core/pagination/pagination.service'; /** * A switchable component rendering StartsWith options for the type "Date". @@ -33,9 +34,11 @@ export class StartsWithDateComponent extends StartsWithAbstractComponent { startsWithYear: number; public constructor(@Inject('startsWithOptions') public startsWithOptions: any[], + @Inject('paginationId') public paginationId: string, + protected paginationService: PaginationService, protected route: ActivatedRoute, protected router: Router) { - super(startsWithOptions, route, router); + super(startsWithOptions, paginationId, paginationService, route, router); } ngOnInit() { diff --git a/src/app/shared/starts-with/starts-with-abstract.component.ts b/src/app/shared/starts-with/starts-with-abstract.component.ts index 229777e96d..b0c7015a12 100644 --- a/src/app/shared/starts-with/starts-with-abstract.component.ts +++ b/src/app/shared/starts-with/starts-with-abstract.component.ts @@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Subscription } from 'rxjs'; import { FormControl, FormGroup } from '@angular/forms'; import { hasValue } from '../empty.util'; +import { PaginationService } from '../../core/pagination/pagination.service'; /** * An abstract component to render StartsWith options @@ -28,6 +29,8 @@ export abstract class StartsWithAbstractComponent implements OnInit, OnDestroy { subs: Subscription[] = []; public constructor(@Inject('startsWithOptions') public startsWithOptions: any[], + @Inject('paginationId') public paginationId: string, + protected paginationService: PaginationService, protected route: ActivatedRoute, protected router: Router) { } diff --git a/src/app/submission/import-external/submission-import-external.component.html b/src/app/submission/import-external/submission-import-external.component.html index bee5f5d872..3c7ed3cd64 100644 --- a/src/app/submission/import-external/submission-import-external.component.html +++ b/src/app/submission/import-external/submission-import-external.component.html @@ -20,8 +20,7 @@ [context]="context" [importable]="true" [importConfig]="importConfig" - (importObject)="import($event)" - (pageChange)="paginationChange();"> + (importObject)="import($event)"> diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index 7a7ec2a4a3..d8801880dc 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { BehaviorSubject, combineLatest, Subscription } from 'rxjs'; -import { filter, mergeMap, take } from 'rxjs/operators'; +import { filter, mergeMap, take, tap } from 'rxjs/operators'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { ExternalSourceService } from '../../core/data/external-source.service'; @@ -20,6 +20,7 @@ import { fadeIn } from '../../shared/animations/fade'; import { PageInfo } from '../../core/shared/page-info.model'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { getFinishedRemoteData } from '../../core/shared/operators'; +import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; /** * This component allows to submit a new workspaceitem importing the data from an external source. @@ -44,6 +45,8 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { * TRUE if the REST service is called to retrieve the external source items */ public isLoading$: BehaviorSubject = new BehaviorSubject(false); + + public reload$: BehaviorSubject<{query: string, source: string}>; /** * Configuration to use for the import buttons */ @@ -64,7 +67,7 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { * The initial pagination options */ public initialPagination = Object.assign(new PaginationComponentOptions(), { - id: 'submission-external-source-relation-list', + id: 'spc', pageSize: 10 }); /** @@ -119,6 +122,7 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { ]).pipe( take(1) ).subscribe(([source, query]: [string, string]) => { + this.reload$ = new BehaviorSubject<{query: string; source: string}>({query: query, source: source}); this.retrieveExternalSources(source, query); })); } @@ -133,7 +137,7 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { queryParams: { source: event.sourceId, query: event.query }, replaceUrl: true } - ).then(() => this.retrieveExternalSources(event.sourceId, event.query)); + ).then(() => this.reload$.next({source: event.sourceId, query: event.query})); } /** @@ -148,13 +152,6 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { modalComp.externalSourceEntry = entry; } - /** - * Retrieve external sources on pagination change - */ - paginationChange() { - this.retrieveExternalSources(this.routeData.sourceId, this.routeData.query); - } - /** * Unsubscribe from all subscriptions */ @@ -170,26 +167,27 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { * @param source The source tupe * @param query The query string to search */ - private retrieveExternalSources(source: string, query: string): void { - if (isNotEmpty(source) && isNotEmpty(query)) { - this.routeData.sourceId = source; - this.routeData.query = query; - this.isLoading$.next(true); - this.subs.push( - this.searchConfigService.paginatedSearchOptions.pipe( - filter((searchOptions) => searchOptions.query === query), - take(1), - mergeMap((searchOptions) => this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions).pipe( - getFinishedRemoteData(), - take(1) - )), - take(1) - ).subscribe((rdData) => { - this.entriesRD$.next(rdData); - this.isLoading$.next(false); - }) - ); - } + private retrieveExternalSources(sourcesss: string, querysss: string): void { + this.reload$.subscribe((sourceQueryObject: {source: string, query: string}) => { + const source = sourceQueryObject.source; + const query = sourceQueryObject.query; + if (isNotEmpty(source) && isNotEmpty(query)) { + this.routeData.sourceId = source; + this.routeData.query = query; + this.isLoading$.next(true); + this.subs.push( + this.searchConfigService.paginatedSearchOptions.pipe( + filter((searchOptions) => searchOptions.query === query), + mergeMap((searchOptions) => this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions).pipe( + getFinishedRemoteData(), + )), + ).subscribe((rdData) => { + this.entriesRD$.next(rdData); + this.isLoading$.next(false); + }) + ); + } + }); } } From d07f44ac41a247d5ebef74e57e6756517cd7817d Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Tue, 23 Feb 2021 11:01:40 +0100 Subject: [PATCH 02/14] 76654: Feedback to pagination --- .../epeople-registry.component.ts | 2 + .../eperson-form/eperson-form.component.ts | 2 + .../members-list/members-list.component.ts | 55 ++++++++++++------- .../subgroup-list/subgroups-list.component.ts | 2 + .../groups-registry.component.ts | 4 ++ .../bitstream-formats.component.ts | 10 +++- .../metadata-registry.component.ts | 4 ++ .../metadata-schema.component.ts | 4 ++ .../browse-by-metadata-page.component.ts | 2 + .../collection-page.component.ts | 5 ++ ...nity-page-sub-collection-list.component.ts | 5 ++ ...unity-page-sub-community-list.component.ts | 5 ++ .../top-level-community-list.component.ts | 2 + .../full-file-section.component.html | 6 +- .../full-file-section.component.ts | 46 ++++++---------- .../my-dspace-configuration.service.spec.ts | 4 +- src/app/core/pagination/pagination.service.ts | 42 ++++++++++---- .../overview/process-overview.component.ts | 3 + .../item-versions.component.html | 3 +- .../item-versions/item-versions.component.ts | 29 ++++------ ...-paginated-drag-and-drop-list.component.ts | 1 + .../pagination/pagination.component.html | 2 +- .../shared/pagination/pagination.component.ts | 20 +------ .../eperson-group-list.component.html | 2 +- .../eperson-group-list.component.spec.ts | 2 - .../eperson-group-list.component.ts | 2 + .../search-facet-option.component.ts | 11 +++- .../search-facet-range-option.component.ts | 7 ++- .../search-facet-selected-option.component.ts | 8 ++- .../search-label/search-label.component.ts | 9 ++- src/modules/app/browser-app.module.ts | 1 + 31 files changed, 184 insertions(+), 116 deletions(-) diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts index cb8a76d627..c82afc0621 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts @@ -254,8 +254,10 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { */ ngOnDestroy(): void { this.cleanupSubscribes(); + this.paginationService.clearPagination(this.config.id); } + cleanupSubscribes() { this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); } diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts index 6c66035f14..8fc0d74aca 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -489,8 +489,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.onCancel(); this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); + this.paginationService.clearPagination(this.config.id); } + /** * This method will ensure that the page gets reset and that the cache is cleared */ diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts index 9f26474094..944b2e5dfb 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts @@ -17,9 +17,8 @@ import { GroupDataService } from '../../../../../core/eperson/group-data.service import { EPerson } from '../../../../../core/eperson/models/eperson.model'; import { Group } from '../../../../../core/eperson/models/group.model'; import { - getFirstCompletedRemoteData, getFirstSucceededRemoteData, - getFirstCompletedRemoteData, getAllCompletedRemoteData + getFirstCompletedRemoteData, getAllCompletedRemoteData, getRemoteDataPayload } from '../../../../../core/shared/operators'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; @@ -238,28 +237,33 @@ export class MembersListComponent implements OnInit, OnDestroy { * @param data Contains scope and query param */ search(data: any) { - const query: string = data.query; - const scope: string = data.scope; - if (query != null && this.currentSearchQuery !== query && this.groupBeingEdited) { - this.router.navigateByUrl(this.groupDataService.getGroupEditPageRouterLink(this.groupBeingEdited)); - this.currentSearchQuery = query; - this.configSearch.currentPage = 1; - } - if (scope != null && this.currentSearchScope !== scope && this.groupBeingEdited) { - this.router.navigateByUrl(this.groupDataService.getGroupEditPageRouterLink(this.groupBeingEdited)); - this.currentSearchScope = scope; - this.configSearch.currentPage = 1; - } - this.searchDone = true; - this.unsubFrom(SubKey.SearchResultsDTO); this.subs.set(SubKey.SearchResultsDTO, this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe( switchMap((paginationOptions) => { - this.ePersonDataService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { - currentPage: this.configSearch.currentPage, - elementsPerPage: this.configSearch.pageSize - }, false) + + const query: string = data.query; + const scope: string = data.scope; + if (query != null && this.currentSearchQuery !== query && this.groupBeingEdited) { + this.router.navigate([], { + queryParamsHandling: 'merge' + }); + this.currentSearchQuery = query; + this.paginationService.resetPage(this.configSearch.id); + } + if (scope != null && this.currentSearchScope !== scope && this.groupBeingEdited) { + this.router.navigate([], { + queryParamsHandling: 'merge' + }); + this.currentSearchScope = scope; + this.paginationService.resetPage(this.configSearch.id); + } + this.searchDone = true; + + return this.ePersonDataService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { + currentPage: paginationOptions.currentPage, + elementsPerPage: paginationOptions.pageSize + }); }), getAllCompletedRemoteData(), map((rd: RemoteData) => { @@ -289,6 +293,17 @@ export class MembersListComponent implements OnInit, OnDestroy { })); } + /** + * unsub all subscriptions + */ + ngOnDestroy(): void { + for (const key of this.subs.keys()) { + this.unsubFrom(key); + } + this.paginationService.clearPagination(this.config.id); + this.paginationService.clearPagination(this.configSearch.id); + } + /** * Shows a notification based on the success/failure of the request * @param messageSuffix Suffix for message diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts index 3072c4538c..13d89d2ce1 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts @@ -244,6 +244,8 @@ export class SubgroupsListComponent implements OnInit, OnDestroy { for (const key of this.subs.keys()) { this.unsubFrom(key); } + this.paginationService.clearPagination(this.config.id); + this.paginationService.clearPagination(this.configSearch.id); } /** diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts index 1a7ed6a599..6083efd6f7 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts @@ -255,12 +255,16 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { */ ngOnDestroy(): void { this.cleanupSubscribes(); + this.paginationService.clearPagination(this.config.id); } + cleanupSubscribes() { if (hasValue(this.paginationSub)) { this.paginationSub.unsubscribe(); } this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); + this.paginationService.clearPagination(this.config.id); } + } diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts index 7ae117b0a5..d2ae805be7 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { combineLatest as observableCombineLatest, Observable, zip } from 'rxjs'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list.model'; @@ -21,7 +21,7 @@ import { PaginationService } from '../../../core/pagination/pagination.service'; selector: 'ds-bitstream-formats', templateUrl: './bitstream-formats.component.html' }) -export class BitstreamFormatsComponent implements OnInit { +export class BitstreamFormatsComponent implements OnInit, OnDestroy { /** * A paginated list of bitstream formats to be shown on the page @@ -58,6 +58,7 @@ export class BitstreamFormatsComponent implements OnInit { ) { } + /** * Deletes the currently selected formats from the registry and updates the presented list */ @@ -150,4 +151,9 @@ export class BitstreamFormatsComponent implements OnInit { }) ); } + + + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + } } diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts index 41b14ace88..8574c4678b 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.ts @@ -174,4 +174,8 @@ export class MetadataRegistryComponent { } }); } + ngOnDestroy(): void { + this.paginationService.clearPagination(this.config.id); + } + } diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts index 513f689f84..8a2086d5e2 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.ts @@ -208,4 +208,8 @@ export class MetadataSchemaComponent implements OnInit { } }); } + ngOnDestroy(): void { + this.paginationService.clearPagination(this.config.id); + } + } diff --git a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts index 54359ff0c3..833c3d7d19 100644 --- a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts +++ b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts @@ -208,8 +208,10 @@ export class BrowseByMetadataPageComponent implements OnInit { ngOnDestroy(): void { this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); + this.paginationService.clearPagination(this.paginationConfig.id); } + } /** diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index e826aee702..74d8c76c5c 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -108,4 +108,9 @@ export class CollectionPageComponent implements OnInit { return isNotEmpty(object); } + ngOnDestroy(): void { + this.paginationService.clearPagination(this.paginationConfig.id); + } + + } diff --git a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts index 4f37934575..adb4c32a32 100644 --- a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts +++ b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.ts @@ -75,4 +75,9 @@ export class CommunityPageSubCollectionListComponent implements OnInit { this.subCollectionsRDObs.next(results); }); } + + ngOnDestroy(): void { + this.paginationService.clearPagination(this.config.id); + } + } diff --git a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.ts b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.ts index ffa2870a90..2c30ede554 100644 --- a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.ts +++ b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.ts @@ -87,4 +87,9 @@ export class CommunityPageSubCommunityListComponent implements OnInit { this.subCommunitiesRDObs.next(results); }); } + + ngOnDestroy(): void { + this.paginationService.clearPagination(this.config.id); + } + } diff --git a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts index 137675e4fc..5f6306649f 100644 --- a/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts +++ b/src/app/+home-page/top-level-community-list/top-level-community-list.component.ts @@ -98,5 +98,7 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy { */ ngOnDestroy() { this.unsubscribe(); + this.paginationService.clearPagination(this.config.id); } + } diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.html b/src/app/+item-page/full/field-components/file-section/full-file-section.component.html index 00218b66d1..d593d60ce6 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.html +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.html @@ -8,8 +8,7 @@ [paginationOptions]="originalOptions" [pageInfoState]="originals" [collectionSize]="originals?.totalElements" - [disableRouteParameterUpdate]="true" - (pageChange)="switchOriginalPage($event)"> + [retainScrollPosition]="true">
@@ -51,8 +50,7 @@ [paginationOptions]="licenseOptions" [pageInfoState]="licenses" [collectionSize]="licenses?.totalElements" - [disableRouteParameterUpdate]="true" - (pageChange)="switchLicensePage($event)"> + [retainScrollPosition]="true">
diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts index ca3d5e65c7..439bb6502f 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts @@ -13,6 +13,7 @@ import { switchMap, tap } from 'rxjs/operators'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { hasValue, isEmpty } from '../../../../shared/empty.util'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; /** * This component renders the file section of the item @@ -35,23 +36,22 @@ export class FullFileSectionComponent extends FileSectionComponent implements On pageSize = 5; originalOptions = Object.assign(new PaginationComponentOptions(), { - id: 'original-bitstreams-options', + id: 'obo', currentPage: 1, pageSize: this.pageSize }); - originalCurrentPage$ = new BehaviorSubject(1); licenseOptions = Object.assign(new PaginationComponentOptions(), { - id: 'license-bitstreams-options', + id: 'lbo', currentPage: 1, pageSize: this.pageSize }); - licenseCurrentPage$ = new BehaviorSubject(1); constructor( bitstreamDataService: BitstreamDataService, protected notificationsService: NotificationsService, - protected translateService: TranslateService + protected translateService: TranslateService, + protected paginationService: PaginationService ) { super(bitstreamDataService, notificationsService, translateService); } @@ -61,11 +61,11 @@ export class FullFileSectionComponent extends FileSectionComponent implements On } initialize(): void { - this.originals$ = this.originalCurrentPage$.pipe( - switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName( + this.originals$ = this.paginationService.getCurrentPagination(this.originalOptions.id, this.originalOptions).pipe( + switchMap((options: PaginationComponentOptions) => this.bitstreamDataService.findAllByItemAndBundleName( this.item, 'ORIGINAL', - {elementsPerPage: this.pageSize, currentPage: pageNumber}, + {elementsPerPage: options.pageSize, currentPage: options.currentPage}, true, true, followLink('format') @@ -78,11 +78,11 @@ export class FullFileSectionComponent extends FileSectionComponent implements On ) ); - this.licenses$ = this.licenseCurrentPage$.pipe( - switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName( + this.licenses$ = this.paginationService.getCurrentPagination(this.licenseOptions.id, this.licenseOptions).pipe( + switchMap((options: PaginationComponentOptions) => this.bitstreamDataService.findAllByItemAndBundleName( this.item, 'LICENSE', - {elementsPerPage: this.pageSize, currentPage: pageNumber}, + {elementsPerPage: options.pageSize, currentPage: options.currentPage}, true, true, followLink('format') @@ -97,25 +97,13 @@ export class FullFileSectionComponent extends FileSectionComponent implements On } - /** - * 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); - } - hasValuesInBundle(bundle: PaginatedList) { return hasValue(bundle) && !isEmpty(bundle.page); } + + ngOnDestroy(): void { + this.paginationService.clearPagination(this.originalOptions.id); + this.paginationService.clearPagination(this.licenseOptions.id); + } + } diff --git a/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts b/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts index 4154a09f15..6cbab8125b 100644 --- a/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts +++ b/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts @@ -102,7 +102,7 @@ describe('MyDSpaceConfigurationService', () => { describe('when getCurrentSort is called', () => { beforeEach(() => { - service.getCurrentSort({} as any); + // service.getCurrentSort({} as any); }); it('should call getQueryParameterValue on the routeService with parameter name \'sortDirection\'', () => { expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortDirection'); @@ -114,7 +114,7 @@ describe('MyDSpaceConfigurationService', () => { describe('when getCurrentPagination is called', () => { beforeEach(() => { - service.getCurrentPagination({ currentPage: 1, pageSize: 10 } as any); + // service.getCurrentPagination({ currentPage: 1, pageSize: 10 } as any); }); it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => { expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page'); diff --git a/src/app/core/pagination/pagination.service.ts b/src/app/core/pagination/pagination.service.ts index 35b38b23f7..0143d20923 100644 --- a/src/app/core/pagination/pagination.service.ts +++ b/src/app/core/pagination/pagination.service.ts @@ -99,17 +99,20 @@ export class PaginationService { pageSize?: number sortField?: string sortDirection?: SortDirection - }, extraParams?, changeLocationNot?: boolean) { + }, extraParams?, retainScrollPosition?: boolean) { this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); const parametersWithIdName = this.getParametersWithIdName(paginationId, params); if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { const queryParams = Object.assign({}, currentParametersWithIdName, parametersWithIdName, extraParams); - if (changeLocationNot) { - this.location.go(this.router.createUrlTree([], { - relativeTo: this.route, queryParams: queryParams, queryParamsHandling: 'merge' - }).toString()); + console.log(retainScrollPosition); + if (retainScrollPosition) { + this.router.navigate([], { + queryParams: queryParams, + queryParamsHandling: 'merge', + fragment: `p-${paginationId}` + }); } else { this.router.navigate([], { queryParams: queryParams, @@ -125,17 +128,20 @@ export class PaginationService { pageSize?: number sortField?: string sortDirection?: SortDirection - }, extraParams?, changeLocationNot?: boolean) { + }, extraParams?, retainScrollPosition?: boolean) { + console.log(retainScrollPosition); this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); const parametersWithIdName = this.getParametersWithIdName(paginationId, params); if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { const queryParams = Object.assign({}, currentParametersWithIdName, parametersWithIdName, extraParams); - if (changeLocationNot) { - this.location.go(this.router.createUrlTree([], { - relativeTo: this.route, queryParams: queryParams, queryParamsHandling: 'merge' - }).toString()); + if (retainScrollPosition) { + this.router.navigate(url, { + queryParams: queryParams, + queryParamsHandling: 'merge', + fragment: `p-${paginationId}` + }); } else { this.router.navigate(url, { queryParams: queryParams, @@ -146,6 +152,22 @@ export class PaginationService { }); } + clearPagination(paginationId: string) { + const params = {}; + params[`p.${paginationId}`] = null; + params[`rpp.${paginationId}`] = null; + params[`sf.${paginationId}`] = null; + params[`sd.${paginationId}`] = null; + + this.router.navigate([], { + queryParams: params, + queryParamsHandling: 'merge' + }); + } + + getPageParam(paginationId: string) { + return `p.${paginationId}`; + } getParametersWithIdName(paginationId: string, params: { page?: number diff --git a/src/app/process-page/overview/process-overview.component.ts b/src/app/process-page/overview/process-overview.component.ts index 1ea8c5b9c6..03fcf27222 100644 --- a/src/app/process-page/overview/process-overview.component.ts +++ b/src/app/process-page/overview/process-overview.component.ts @@ -74,5 +74,8 @@ export class ProcessOverviewComponent implements OnInit { map((eperson: EPerson) => eperson.name) ); } + ngOnDestroy(): void { + this.paginationService.clearPagination(this.pageConfig.id); + } } diff --git a/src/app/shared/item/item-versions/item-versions.component.html b/src/app/shared/item/item-versions/item-versions.component.html index 6e93f4c7ca..0061de4b2e 100644 --- a/src/app/shared/item/item-versions/item-versions.component.html +++ b/src/app/shared/item/item-versions/item-versions.component.html @@ -8,8 +8,7 @@ [paginationOptions]="options" [pageInfoState]="versions" [collectionSize]="versions?.totalElements" - [disableRouteParameterUpdate]="true" - (pageChange)="switchPage($event)"> + [retainScrollPosition]="true">
diff --git a/src/app/shared/item/item-versions/item-versions.component.ts b/src/app/shared/item/item-versions/item-versions.component.ts index 9c4682642a..3e515b9452 100644 --- a/src/app/shared/item/item-versions/item-versions.component.ts +++ b/src/app/shared/item/item-versions/item-versions.component.ts @@ -13,6 +13,7 @@ import { PaginatedSearchOptions } from '../../search/paginated-search-options.mo import { AlertType } from '../../alert/aletr-type'; import { followLink } from '../../utils/follow-link-config.model'; import { hasValueOperator } from '../../empty.util'; +import { PaginationService } from '../../../core/pagination/pagination.service'; @Component({ selector: 'ds-item-versions', @@ -76,17 +77,14 @@ export class ItemVersionsComponent implements OnInit { * Start at page 1 and always use the set page size */ options = Object.assign(new PaginationComponentOptions(),{ - id: 'item-versions-options', + id: 'ivo', currentPage: 1, pageSize: this.pageSize }); - /** - * The current page being displayed - */ - currentPage$ = new BehaviorSubject(1); - - constructor(private versionHistoryService: VersionHistoryDataService) { + constructor(private versionHistoryService: VersionHistoryDataService, + private paginationService: PaginationService + ) { } /** @@ -105,10 +103,11 @@ export class ItemVersionsComponent implements OnInit { getRemoteDataPayload(), hasValueOperator(), ); - this.versionsRD$ = observableCombineLatest(versionHistory$, this.currentPage$).pipe( - switchMap(([versionHistory, page]: [VersionHistory, number]) => + const currentPagination = this.paginationService.getCurrentPagination(this.options.id, this.options); + this.versionsRD$ = observableCombineLatest(versionHistory$, currentPagination).pipe( + switchMap(([versionHistory, options]: [VersionHistory, PaginationComponentOptions]) => this.versionHistoryService.getVersions(versionHistory.id, - new PaginatedSearchOptions({pagination: Object.assign({}, this.options, { currentPage: page })}), + new PaginatedSearchOptions({pagination: Object.assign({}, options, { currentPage: options.currentPage })}), true, true, followLink('item'), followLink('eperson'))) ); this.hasEpersons$ = this.versionsRD$.pipe( @@ -120,13 +119,9 @@ export class ItemVersionsComponent implements OnInit { ); } - /** - * Update the current page - * @param page - */ - switchPage(page: number) { - this.options.currentPage = page; - this.currentPage$.next(page); + ngOnDestroy(): void { + this.paginationService.clearPagination(this.options.id); } + } diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts index 3b5d8bc3de..b861104197 100644 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts +++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts @@ -233,5 +233,6 @@ export abstract class AbstractPaginatedDragAndDropListComponent hasValue(sub)).forEach((sub) => sub.unsubscribe()); + this.paginationService.clearPagination(this.options.id); } } diff --git a/src/app/shared/pagination/pagination.component.html b/src/app/shared/pagination/pagination.component.html index 7f7e7acc60..e8382c2eb4 100644 --- a/src/app/shared/pagination/pagination.component.html +++ b/src/app/shared/pagination/pagination.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index cfb6fd147f..d126565e8f 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -20,7 +20,6 @@ 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 { isNumeric } from 'rxjs/internal-compatibility'; /** * The default pagination controls component. @@ -104,7 +103,7 @@ export class PaginationComponent implements OnDestroy, OnInit { * In other words, changing pagination won't add or update the url parameters on the current page, and the url * parameters won't affect the pagination of this component */ - @Input() public disableRouteParameterUpdate = false; + @Input() public retainScrollPosition = false; /** * Current page. @@ -125,7 +124,7 @@ export class PaginationComponent implements OnDestroy, OnInit { * ID for the pagination instance. Only useful if you wish to * have more than once instance at a time in a given component. */ - private id: string; + public id: string; /** * A boolean that indicate if is an extra small devices viewport. @@ -176,16 +175,7 @@ export class PaginationComponent implements OnDestroy, OnInit { })); this.checkConfig(this.paginationOptions); this.initializeConfig(); - // Listen to changes - if (!this.disableRouteParameterUpdate) { - this.subs.push( - this.paginationService.getCurrentPagination(this.id, this.paginationOptions).subscribe((queryParams) => { - })); - this.subs.push( - this.paginationService.getCurrentSort(this.id, this.sortOptions).subscribe((queryParams) => { - })); } - } /** * Method provided by Angular. Invoked when the instance is destroyed. @@ -336,11 +326,7 @@ export class PaginationComponent implements OnDestroy, OnInit { * @param params */ private updateParams(params: {}) { - if (!this.disableRouteParameterUpdate) { - this.paginationService.updateRoute(this.id, params); - } else { - this.paginationService.updateRoute(this.id, params, {}, this.disableRouteParameterUpdate); - } + this.paginationService.updateRoute(this.id, params, {}, this.retainScrollPosition); } /** diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.html b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.html index 1acdb85222..6ee5aad943 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.html +++ b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.html @@ -5,7 +5,7 @@
diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts index 037edbc905..db01146bfe 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts +++ b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts @@ -180,7 +180,6 @@ describe('EpersonGroupListComponent test suite', () => { it('should update list on page change', () => { spyOn(comp, 'updateList'); - comp.onPageChange(2); expect(compAsAny.updateList).toHaveBeenCalled(); }); @@ -257,7 +256,6 @@ describe('EpersonGroupListComponent test suite', () => { it('should update list on page change', () => { spyOn(comp, 'updateList'); - comp.onPageChange(2); expect(compAsAny.updateList).toHaveBeenCalled(); }); diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts index 26a7f47f52..8605033b2e 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts +++ b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts @@ -200,6 +200,8 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { this.subs .filter((subscription) => hasValue(subscription)) .forEach((subscription) => subscription.unsubscribe()); + this.paginationService.clearPagination(this.paginationOptions.id); } + } diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts index c6d7f4ac7c..45c90d8a60 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts @@ -10,6 +10,8 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search import { hasValue } from '../../../../../empty.util'; import { currentPath } from '../../../../../utils/route.utils'; import { getFacetValueForType } from '../../../../search.utils'; +import { PaginationService } from '../../../../../../core/pagination/pagination.service'; +import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; @Component({ selector: 'ds-search-facet-option', @@ -60,10 +62,13 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy { */ sub: Subscription; + paginationId: string; + constructor(protected searchService: SearchService, protected filterService: SearchFilterService, protected searchConfigService: SearchConfigurationService, - protected router: Router + protected router: Router, + protected paginationService: PaginationService ) { } @@ -71,6 +76,7 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy { * Initializes all observable instance variables and starts listening to them */ ngOnInit(): void { + this.paginationId = this.searchConfigService.paginationID; this.searchLink = this.getSearchLink(); this.isVisible = this.isChecked().pipe(map((checked: boolean) => !checked)); this.sub = observableCombineLatest(this.selectedValues$, this.searchConfigService.searchOptions) @@ -101,9 +107,10 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy { * @param {string[]} selectedValues The values that are currently selected for this filter */ private updateAddParams(selectedValues: FacetValue[]): void { + const page = this.paginationService.getPageParam(this.searchConfigService.paginationID); this.addQueryParams = { [this.filterConfig.paramName]: [...selectedValues.map((facetValue: FacetValue) => getFacetValueForType(facetValue, this.filterConfig)), this.getFacetValue()], - page: 1 + [page]: 1 }; } diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts index 56a075d333..3d8215b210 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.ts @@ -13,6 +13,7 @@ import { import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { hasValue } from '../../../../../empty.util'; import { currentPath } from '../../../../../utils/route.utils'; +import { PaginationService } from '../../../../../../core/pagination/pagination.service'; const rangeDelimiter = '-'; @@ -65,7 +66,8 @@ export class SearchFacetRangeOptionComponent implements OnInit, OnDestroy { constructor(protected searchService: SearchService, protected filterService: SearchFilterService, protected searchConfigService: SearchConfigurationService, - protected router: Router + protected router: Router, + protected paginationService: PaginationService ) { } @@ -104,10 +106,11 @@ export class SearchFacetRangeOptionComponent implements OnInit, OnDestroy { const parts = this.filterValue.value.split(rangeDelimiter); const min = parts.length > 1 ? parts[0].trim() : this.filterValue.value; const max = parts.length > 1 ? parts[1].trim() : this.filterValue.value; + const page = this.paginationService.getPageParam(this.searchConfigService.paginationID); this.changeQueryParams = { [this.filterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: [min], [this.filterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: [max], - page: 1 + [page]: 1 }; } diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts index 159effe751..d92455fdd9 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.ts @@ -9,6 +9,7 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search import { FacetValue } from '../../../../facet-value.model'; import { currentPath } from '../../../../../utils/route.utils'; import { getFacetValueForType } from '../../../../search.utils'; +import { PaginationService } from '../../../../../../core/pagination/pagination.service'; @Component({ selector: 'ds-search-facet-selected-option', @@ -58,7 +59,8 @@ export class SearchFacetSelectedOptionComponent implements OnInit, OnDestroy { constructor(protected searchService: SearchService, protected filterService: SearchFilterService, protected searchConfigService: SearchConfigurationService, - protected router: Router + protected router: Router, + protected paginationService: PaginationService ) { } @@ -88,14 +90,14 @@ export class SearchFacetSelectedOptionComponent implements OnInit, OnDestroy { * @param {string[]} selectedValues The values that are currently selected for this filter */ private updateRemoveParams(selectedValues: FacetValue[]): void { + const page = this.paginationService.getPageParam(this.searchConfigService.paginationID); this.removeQueryParams = { [this.filterConfig.paramName]: selectedValues .filter((facetValue: FacetValue) => facetValue.label !== this.selectedValue.label) .map((facetValue: FacetValue) => this.getFacetValue(facetValue)), - page: 1 + [page]: 1 }; } - /** * TODO to review after https://github.com/DSpace/dspace-angular/issues/368 is resolved * Retrieve facet value related to facet type diff --git a/src/app/shared/search/search-labels/search-label/search-label.component.ts b/src/app/shared/search/search-labels/search-label/search-label.component.ts index 8ae1a8dd1b..b66308a5bd 100644 --- a/src/app/shared/search/search-labels/search-label/search-label.component.ts +++ b/src/app/shared/search/search-labels/search-label/search-label.component.ts @@ -1,10 +1,12 @@ import { Component, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { Params, Router } from '@angular/router'; -import { map } from 'rxjs/operators'; +import { map, take } from 'rxjs/operators'; import { hasValue, isNotEmpty } from '../../../empty.util'; import { SearchService } from '../../../../core/shared/search/search.service'; import { currentPath } from '../../../utils/route.utils'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service'; @Component({ selector: 'ds-search-label', @@ -32,6 +34,8 @@ export class SearchLabelComponent implements OnInit { */ constructor( private searchService: SearchService, + private paginationService: PaginationService, + private searchConfigurationService: SearchConfigurationService, private router: Router) { } @@ -50,9 +54,10 @@ export class SearchLabelComponent implements OnInit { map((filters) => { const field: string = Object.keys(filters).find((f) => f === this.key); const newValues = hasValue(filters[field]) ? filters[field].filter((v) => v !== this.value) : null; + const page = this.paginationService.getPageParam(this.searchConfigurationService.paginationID); return { [field]: isNotEmpty(newValues) ? newValues : null, - page: 1 + [page]: 1 }; }) ); diff --git a/src/modules/app/browser-app.module.ts b/src/modules/app/browser-app.module.ts index 4b6c5c813e..0fb4416376 100644 --- a/src/modules/app/browser-app.module.ts +++ b/src/modules/app/browser-app.module.ts @@ -55,6 +55,7 @@ export function getRequest(transferState: TransferState): any { // enableTracing: true, useHash: false, scrollPositionRestoration: 'enabled', + anchorScrolling: 'enabled', preloadingStrategy: NoPreloading }), StatisticsModule.forRoot(), From b18f9c7c9f16e3d6f1b0ca26636d58235efbf4d3 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 4 Mar 2021 17:10:01 +0100 Subject: [PATCH 03/14] Add tests and fix tests --- .../epeople-registry.component.spec.ts | 18 ++- .../eperson-form.component.spec.ts | 19 +++ .../eperson-form/eperson-form.component.ts | 10 +- .../members-list.component.spec.ts | 17 ++ .../subgroups-list.component.spec.ts | 18 +++ .../groups-registry.component.spec.ts | 16 ++ .../groups-registry.component.ts | 94 +++++------ .../bitstream-formats.component.spec.ts | 48 +++++- .../metadata-registry.component.spec.ts | 15 ++ .../metadata-schema.component.spec.ts | 15 ++ .../browse-by-date-page.component.spec.ts | 16 ++ .../browse-by-metadata-page.component.spec.ts | 32 +++- .../browse-by-title-page.component.spec.ts | 15 ++ ...page-sub-collection-list.component.spec.ts | 40 ++--- ...-page-sub-community-list.component.spec.ts | 39 ++--- ...top-level-community-list.component.spec.ts | 36 ++--- ...-and-drop-bitstream-list.component.spec.ts | 18 ++- .../full-file-section.component.spec.ts | 51 ++---- .../my-dspace-configuration.service.spec.ts | 28 ++-- .../my-dspace-configuration.service.ts | 1 + .../pagination/pagination.service.spec.ts | 149 ++++++++++++++++++ src/app/core/pagination/pagination.service.ts | 16 +- .../search-configuration.service.spec.ts | 31 ++-- .../core/shared/search/search.service.spec.ts | 34 +++- .../process-overview.component.spec.ts | 31 ++-- .../search-navbar.component.spec.ts | 26 ++- .../browse-by/browse-by.component.spec.ts | 38 +++-- .../shared/browse-by/browse-by.component.ts | 2 +- .../item-versions.component.spec.ts | 28 ++-- .../collection-select.component.spec.ts | 17 +- .../item-select/item-select.component.spec.ts | 20 ++- .../page-size-selector.component.spec.ts | 8 + ...nated-drag-and-drop-list.component.spec.ts | 31 ++-- .../pagination/pagination.component.spec.ts | 133 ++++++---------- .../shared/pagination/pagination.component.ts | 66 +------- .../eperson-group-list.component.spec.ts | 29 ++-- .../search-form/search-form.component.spec.ts | 23 ++- .../search-facet-option.component.spec.ts | 21 ++- ...earch-facet-range-option.component.spec.ts | 22 ++- ...ch-facet-selected-option.component.spec.ts | 21 ++- .../search-label.component.spec.ts | 19 +++ .../search-settings.component.spec.ts | 13 ++ .../date/starts-with-date.component.spec.ts | 17 ++ .../text/starts-with-text.component.spec.ts | 19 ++- .../search-configuration-service.stub.ts | 2 + ...bmission-import-external.component.spec.ts | 17 +- .../submission-import-external.component.ts | 12 +- 47 files changed, 937 insertions(+), 454 deletions(-) create mode 100644 src/app/core/pagination/pagination.service.spec.ts diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts index c104de0b17..4b9dcef00d 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts @@ -25,6 +25,9 @@ import { NotificationsServiceStub } from '../../../shared/testing/notifications- import { RouterStub } from '../../../shared/testing/router.stub'; import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; import { RequestService } from '../../../core/data/request.service'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('EPeopleRegistryComponent', () => { let component: EPeopleRegistryComponent; @@ -37,6 +40,8 @@ describe('EPeopleRegistryComponent', () => { let authorizationService: AuthorizationDataService; let modalService; + let paginationService; + beforeEach(waitForAsync(() => { mockEPeople = [EPersonMock, EPersonMock2]; ePersonDataServiceStub = { @@ -115,6 +120,16 @@ describe('EPeopleRegistryComponent', () => { }); builderService = getMockFormBuilderService(); translateService = getMockTranslateService(); + + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ @@ -131,7 +146,8 @@ describe('EPeopleRegistryComponent', () => { { provide: AuthorizationDataService, useValue: authorizationService }, { provide: FormBuilderService, useValue: builderService }, { provide: Router, useValue: new RouterStub() }, - { provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) } + { provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }, + { provide: PaginationService, useValue: paginationService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts index 1163490e12..e10c1af94c 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts @@ -26,6 +26,9 @@ import { AuthorizationDataService } from '../../../../core/data/feature-authoriz import { GroupDataService } from '../../../../core/eperson/group-data.service'; import { createPaginatedList } from '../../../../shared/testing/utils.test'; import { RequestService } from '../../../../core/data/request.service'; +import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; describe('EPersonFormComponent', () => { let component: EPersonFormComponent; @@ -38,6 +41,10 @@ describe('EPersonFormComponent', () => { let authorizationService: AuthorizationDataService; let groupsDataService: GroupDataService; + let paginationService: PaginationService; + + + beforeEach(waitForAsync(() => { mockEPeople = [EPersonMock, EPersonMock2]; ePersonDataServiceStub = { @@ -104,6 +111,17 @@ describe('EPersonFormComponent', () => { findAllByHref: createSuccessfulRemoteDataObject$(createPaginatedList([])), getGroupRegistryRouterLink: '' }); + + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {} + }); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ @@ -121,6 +139,7 @@ describe('EPersonFormComponent', () => { { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: AuthService, useValue: authService }, { provide: AuthorizationDataService, useValue: authorizationService }, + { provide: PaginationService, useValue: paginationService }, { provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts index 8fc0d74aca..48f171f966 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -271,14 +271,12 @@ export class EPersonFormComponent implements OnInit, OnDestroy { })]); }), switchMap(([eperson, findListOptions]) => { - return this.groupsDataService.findAllByHref(eperson._links.groups.href, findListOptions); + if (eperson != null) { + return this.groupsDataService.findAllByHref(eperson._links.groups.href, findListOptions); + } + return observableOf(undefined); }) ); - // this.subs.push(combineLatest([activeEPerson$, paginationOption$]).subscribe(([eperson, options]) => { - // if (eperson != null) { - // this.groups = this.groupsDataService.findAllByHref(eperson._links.groups.href, options); - // } - // })); this.canImpersonate$ = activeEPerson$.pipe( switchMap((eperson) => this.authorizationService.isAuthorized(FeatureID.LoginOnBehalfOf, hasValue(eperson) ? eperson.self : undefined)) diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts index 10735cbde5..ad1455ae0f 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts @@ -26,6 +26,10 @@ import { getMockFormBuilderService } from '../../../../../shared/mocks/form-buil import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock'; import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub'; import { RouterMock } from '../../../../../shared/mocks/router.mock'; +import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../../core/data/request.models'; +import { PaginationService } from '../../../../../core/pagination/pagination.service'; describe('MembersListComponent', () => { let component: MembersListComponent; @@ -39,6 +43,7 @@ describe('MembersListComponent', () => { let allGroups; let epersonMembers; let subgroupMembers; + let paginationService; beforeEach(waitForAsync(() => { activeGroup = GroupMock; @@ -113,6 +118,17 @@ describe('MembersListComponent', () => { }; builderService = getMockFormBuilderService(); translateService = getMockTranslateService(); + + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + clearPagination : {}, + }); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ @@ -129,6 +145,7 @@ describe('MembersListComponent', () => { { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: FormBuilderService, useValue: builderService }, { provide: Router, useValue: new RouterMock() }, + { provide: PaginationService, useValue: paginationService }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts index 9841d2b02e..ea65e1b290 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts @@ -35,6 +35,10 @@ import { getMockTranslateService } from '../../../../../shared/mocks/translate.s import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock'; import { NotificationsServiceStub } from '../../../../../shared/testing/notifications-service.stub'; import { map } from 'rxjs/operators'; +import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../../core/data/request.models'; +import { PaginationService } from '../../../../../core/pagination/pagination.service'; describe('SubgroupsListComponent', () => { let component: SubgroupsListComponent; @@ -47,6 +51,7 @@ describe('SubgroupsListComponent', () => { let subgroups; let allGroups; let routerStub; + let paginationService; beforeEach(waitForAsync(() => { activeGroup = GroupMock; @@ -100,6 +105,18 @@ describe('SubgroupsListComponent', () => { routerStub = new RouterMock(); builderService = getMockFormBuilderService(); translateService = getMockTranslateService(); + + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {}, + clearPagination: {} + }); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ @@ -115,6 +132,7 @@ describe('SubgroupsListComponent', () => { { provide: NotificationsService, useValue: new NotificationsServiceStub() }, { provide: FormBuilderService, useValue: builderService }, { provide: Router, useValue: routerStub }, + { provide: PaginationService, useValue: paginationService }, ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts index dd08ea6772..ff75988607 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts +++ b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts @@ -28,6 +28,10 @@ import { TranslateLoaderMock } from '../../../shared/testing/translate-loader.mo import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; import { routeServiceStub } from '../../../shared/testing/route-service.stub'; import { RouterMock } from '../../../shared/mocks/router.mock'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('GroupRegistryComponent', () => { let component: GroupsRegistryComponent; @@ -39,6 +43,7 @@ describe('GroupRegistryComponent', () => { let mockGroups; let mockEPeople; + let paginationService; beforeEach(waitForAsync(() => { mockGroups = [GroupMock, GroupMock2]; @@ -131,6 +136,16 @@ describe('GroupRegistryComponent', () => { authorizationService = jasmine.createSpyObj('authorizationService', { isAuthorized: observableOf(true) }); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {} + }); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ @@ -149,6 +164,7 @@ describe('GroupRegistryComponent', () => { { provide: RouteService, useValue: routeServiceStub }, { provide: Router, useValue: new RouterMock() }, { provide: AuthorizationDataService, useValue: authorizationService }, + { provide: PaginationService, useValue: paginationService }, { provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts index 6083efd6f7..cb55f0f2cd 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.ts @@ -9,7 +9,7 @@ import { of as observableOf, Subscription } from 'rxjs'; -import { catchError, map, switchMap, take, tap } from 'rxjs/operators'; +import { catchError, map, switchMap, take } from 'rxjs/operators'; import { DSpaceObjectDataService } from '../../../core/data/dspace-object-data.service'; import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; @@ -25,9 +25,9 @@ import { RouteService } from '../../../core/services/route.service'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { getAllSucceededRemoteData, - getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, - getFirstSucceededRemoteData + getFirstSucceededRemoteData, + getRemoteDataPayload } from '../../../core/shared/operators'; import { PageInfo } from '../../../core/shared/page-info.model'; import { hasValue } from '../../../shared/empty.util'; @@ -113,72 +113,58 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy { * @param data Contains query param */ search(data: any) { - - const query: string = data.query; - if (query != null && this.currentSearchQuery !== query) { - this.router.navigateByUrl(this.groupService.getGroupRegistryRouterLink()); - this.currentSearchQuery = query; - this.config.currentPage = 1; - } if (hasValue(this.searchSub)) { this.searchSub.unsubscribe(); this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub); } - this.searchSub = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( switchMap((paginationOptions) => { const query: string = data.query; if (query != null && this.currentSearchQuery !== query) { - this.router.navigate([], { - queryParamsHandling: 'merge' - }); this.currentSearchQuery = query; - this.paginationService.resetPage(this.config.id); - } - if (hasValue(this.searchSub)) { - this.searchSub.unsubscribe(); - this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub); + this.paginationService.updateRouteWithUrl(this.config.id, [], {page: 1}); } return this.groupService.searchGroups(this.currentSearchQuery.trim(), { currentPage: paginationOptions.currentPage, elementsPerPage: paginationOptions.pageSize - }).pipe( - getAllSucceededRemoteData() - switchMap((groups: PaginatedList) => { - if (groups.page.length === 0) { - return observableOf(buildPaginatedList(groups.pageInfo, [])); - } - return observableCombineLatest(groups.page.map((group: Group) => { - if (!this.deletedGroupsIds.includes(group.id)) { - return observableCombineLatest([ - this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(group) ? group.self : undefined), - this.hasLinkedDSO(group), - this.getSubgroups(group), - this.getMembers(group) - ]).pipe( - map(([isAuthorized, hasLinkedDSO, subgroups, members]: - [boolean, boolean, RemoteData>, RemoteData>]) => { - const groupDtoModel: GroupDtoModel = new GroupDtoModel(); - groupDtoModel.ableToDelete = isAuthorized && !hasLinkedDSO; - groupDtoModel.group = group; - groupDtoModel.subgroups = subgroups.payload; - groupDtoModel.epersons = members.payload; - return groupDtoModel; - } - ) - ); - } - })).pipe(map((dtos: GroupDtoModel[]) => { - return buildPaginatedList(groups.pageInfo, dtos); - })); - }) - ). - subscribe((value: PaginatedList) => { - this.groupsDto$.next(value); - this.pageInfoState$.next(value.pageInfo); }); - this.subs.push(this.searchSub); + }), + getAllSucceededRemoteData(), + getRemoteDataPayload(), + switchMap((groups: PaginatedList) => { + if (groups.page.length === 0) { + return observableOf(buildPaginatedList(groups.pageInfo, [])); + } + return observableCombineLatest(groups.page.map((group: Group) => { + if (!this.deletedGroupsIds.includes(group.id)) { + return observableCombineLatest([ + this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(group) ? group.self : undefined), + this.hasLinkedDSO(group), + this.getSubgroups(group), + this.getMembers(group) + ]).pipe( + map(([isAuthorized, hasLinkedDSO, subgroups, members]: + [boolean, boolean, RemoteData>, RemoteData>]) => { + const groupDtoModel: GroupDtoModel = new GroupDtoModel(); + groupDtoModel.ableToDelete = isAuthorized && !hasLinkedDSO; + groupDtoModel.group = group; + groupDtoModel.subgroups = subgroups.payload; + groupDtoModel.epersons = members.payload; + return groupDtoModel; + } + ) + ); + } + })).pipe(map((dtos: GroupDtoModel[]) => { + return buildPaginatedList(groups.pageInfo, dtos); + })); + }) + ).subscribe((value: PaginatedList) => { + this.groupsDto$.next(value); + this.pageInfoState$.next(value.pageInfo); + }); + this.subs.push(this.searchSub); } /** diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts index 74ca566029..5bed34d46b 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts @@ -23,6 +23,10 @@ import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; import { createPaginatedList } from '../../../shared/testing/utils.test'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('BitstreamFormatsComponent', () => { let comp: BitstreamFormatsComponent; @@ -30,6 +34,7 @@ describe('BitstreamFormatsComponent', () => { let bitstreamFormatService; let scheduler: TestScheduler; let notificationsServiceStub; + let paginationService; const bitstreamFormat1 = new BitstreamFormat(); bitstreamFormat1.uuid = 'test-uuid-1'; @@ -79,6 +84,10 @@ describe('BitstreamFormatsComponent', () => { ]; const mockFormatsRD = createSuccessfulRemoteDataObject(createPaginatedList(mockFormatsList)); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const initAsync = () => { notificationsServiceStub = new NotificationsServiceStub(); @@ -95,13 +104,23 @@ describe('BitstreamFormatsComponent', () => { clearBitStreamFormatRequests: observableOf('cleared') }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + + + TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe], providers: [ { provide: BitstreamFormatDataService, useValue: bitstreamFormatService }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, - { provide: NotificationsService, useValue: notificationsServiceStub } + { provide: NotificationsService, useValue: notificationsServiceStub }, + { provide: PaginationService, useValue: paginationService } ] }).compileComponents(); }; @@ -217,13 +236,23 @@ describe('BitstreamFormatsComponent', () => { clearBitStreamFormatRequests: observableOf('cleared') }); - TestBed.configureTestingModule({ + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + + + + TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe], providers: [ { provide: BitstreamFormatDataService, useValue: bitstreamFormatService }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, - { provide: NotificationsService, useValue: notificationsServiceStub } + { provide: NotificationsService, useValue: notificationsServiceStub }, + { provide: PaginationService, useValue: paginationService } ] }).compileComponents(); } @@ -263,13 +292,22 @@ describe('BitstreamFormatsComponent', () => { clearBitStreamFormatRequests: observableOf('cleared') }); - TestBed.configureTestingModule({ + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + + + TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe], providers: [ { provide: BitstreamFormatDataService, useValue: bitstreamFormatService }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, - { provide: NotificationsService, useValue: notificationsServiceStub } + { provide: NotificationsService, useValue: notificationsServiceStub }, + { provide: PaginationService, useValue: paginationService } ] }).compileComponents(); } diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts index a5a65198af..beb900c17f 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts @@ -18,11 +18,16 @@ import { NotificationsServiceStub } from '../../../shared/testing/notifications- import { RestResponse } from '../../../core/cache/response.models'; import { MetadataSchema } from '../../../core/metadata/metadata-schema.model'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; describe('MetadataRegistryComponent', () => { let comp: MetadataRegistryComponent; let fixture: ComponentFixture; let registryService: RegistryService; + let paginationService: PaginationService; const mockSchemasList = [ { id: 1, @@ -62,6 +67,15 @@ describe('MetadataRegistryComponent', () => { }; /* tslint:enable:no-empty */ + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], @@ -69,6 +83,7 @@ describe('MetadataRegistryComponent', () => { providers: [ { provide: RegistryService, useValue: registryServiceStub }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, + { provide: PaginationService, useValue: paginationService }, { provide: NotificationsService, useValue: new NotificationsServiceStub() } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts index 8c685c7012..35522462aa 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts @@ -23,6 +23,10 @@ import { MetadataSchema } from '../../../core/metadata/metadata-schema.model'; import { MetadataField } from '../../../core/metadata/metadata-field.model'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; import { VarDirective } from '../../../shared/utils/var.directive'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('MetadataSchemaComponent', () => { let comp: MetadataSchemaComponent; @@ -125,6 +129,16 @@ describe('MetadataSchemaComponent', () => { }) }); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], @@ -134,6 +148,7 @@ describe('MetadataSchemaComponent', () => { { provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, { provide: Router, useValue: new RouterStub() }, + { provide: PaginationService, useValue: paginationService }, { provide: NotificationsService, useValue: new NotificationsServiceStub() } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.spec.ts b/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.spec.ts index 87473a876b..50761b9521 100644 --- a/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.spec.ts +++ b/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.spec.ts @@ -18,11 +18,16 @@ import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search- import { toRemoteData } from '../+browse-by-metadata-page/browse-by-metadata-page.component.spec'; import { VarDirective } from '../../shared/utils/var.directive'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../core/data/request.models'; +import { PaginationService } from '../../core/pagination/pagination.service'; describe('BrowseByDatePageComponent', () => { let comp: BrowseByDatePageComponent; let fixture: ComponentFixture; let route: ActivatedRoute; + let paginationService; const mockCommunity = Object.assign(new Community(), { id: 'test-uuid', @@ -65,6 +70,16 @@ describe('BrowseByDatePageComponent', () => { detectChanges: () => fixture.detectChanges() }); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], @@ -74,6 +89,7 @@ describe('BrowseByDatePageComponent', () => { { provide: BrowseService, useValue: mockBrowseService }, { provide: DSpaceObjectDataService, useValue: mockDsoService }, { provide: Router, useValue: new RouterMock() }, + { provide: PaginationService, useValue: paginationService }, { provide: ChangeDetectorRef, useValue: mockCdRef } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts index faa75af2f2..1c6336c2c8 100644 --- a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts +++ b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts @@ -14,7 +14,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model'; import { PageInfo } from '../../core/shared/page-info.model'; import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-options.model'; -import { SortDirection } from '../../core/cache/models/sort-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { Item } from '../../core/shared/item.model'; import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service'; import { Community } from '../../core/shared/community.model'; @@ -22,12 +22,18 @@ import { RouterMock } from '../../shared/mocks/router.mock'; import { BrowseEntry } from '../../core/shared/browse-entry.model'; import { VarDirective } from '../../shared/utils/var.directive'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; describe('BrowseByMetadataPageComponent', () => { let comp: BrowseByMetadataPageComponent; let fixture: ComponentFixture; let browseService: BrowseService; let route: ActivatedRoute; + let paginationService: PaginationService; + + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); const mockCommunity = Object.assign(new Community(), { id: 'test-uuid', @@ -82,6 +88,12 @@ describe('BrowseByMetadataPageComponent', () => { params: observableOf({}) }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getRouteParameterValue: observableOf('') + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], @@ -90,6 +102,7 @@ describe('BrowseByMetadataPageComponent', () => { { provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: BrowseService, useValue: mockBrowseService }, { provide: DSpaceObjectDataService, useValue: mockDsoService }, + { provide: PaginationService, useValue: paginationService }, { provide: Router, useValue: new RouterMock() } ], schemas: [NO_ERRORS_SCHEMA] @@ -133,18 +146,23 @@ describe('BrowseByMetadataPageComponent', () => { let result: BrowseEntrySearchOptions; beforeEach(() => { - const paramsWithPaginationAndScope = { - page: 5, - pageSize: 10, - sortDirection: SortDirection.ASC, - sortField: 'fake-field', + const paramsScope = { scope: 'fake-scope' }; + const paginationOptions = Object.assign(new PaginationComponentOptions(), { + currentPage: 5, + pageSize: 10, + }); + const sortOptions = { + direction: SortDirection.ASC, + field: 'fake-field', + }; - result = browseParamsToOptions(paramsWithPaginationAndScope, Object.assign({}), Object.assign({}), 'author'); + result = browseParamsToOptions(paramsScope, paginationOptions, sortOptions, 'author'); }); it('should return BrowseEntrySearchOptions with the correct properties', () => { + expect(result.metadataDefinition).toEqual('author'); expect(result.pagination.currentPage).toEqual(5); expect(result.pagination.pageSize).toEqual(10); diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts index 4f7b2d5255..6ae10c6696 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts @@ -18,6 +18,10 @@ import { BrowseService } from '../../core/browse/browse.service'; import { RouterMock } from '../../shared/mocks/router.mock'; import { VarDirective } from '../../shared/utils/var.directive'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../core/data/request.models'; +import { PaginationService } from '../../core/pagination/pagination.service'; describe('BrowseByTitlePageComponent', () => { let comp: BrowseByTitlePageComponent; @@ -61,6 +65,16 @@ describe('BrowseByTitlePageComponent', () => { data: observableOf({ metadata: 'title' }) }); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], @@ -69,6 +83,7 @@ describe('BrowseByTitlePageComponent', () => { { provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: BrowseService, useValue: mockBrowseService }, { provide: DSpaceObjectDataService, useValue: mockDsoService }, + { provide: PaginationService, useValue: paginationService }, { provide: Router, useValue: new RouterMock() } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.spec.ts b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.spec.ts index 13a91563c8..abb3d957bc 100644 --- a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.spec.ts +++ b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.spec.ts @@ -18,6 +18,10 @@ import { PageInfo } from '../../core/shared/page-info.model'; import { HostWindowService } from '../../shared/host-window.service'; import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub'; import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { of as observableOf } from 'rxjs'; +import { PaginationService } from '../../core/pagination/pagination.service'; import { getMockThemeService } from '../../shared/mocks/theme-service.mock'; import { ThemeService } from '../../shared/theme-support/theme.service'; @@ -113,6 +117,17 @@ describe('CommunityPageSubCollectionList Component', () => { } }; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {} + }); + themeService = getMockThemeService(); beforeEach(waitForAsync(() => { @@ -128,6 +143,7 @@ describe('CommunityPageSubCollectionList Component', () => { providers: [ { provide: CollectionDataService, useValue: collectionDataServiceStub }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, + { provide: PaginationService, useValue: paginationService }, { provide: SelectableListService, useValue: {} }, { provide: ThemeService, useValue: themeService }, ], @@ -161,28 +177,4 @@ describe('CommunityPageSubCollectionList Component', () => { const subComHead = fixture.debugElement.queryAll(By.css('h2')); expect(subComHead.length).toEqual(0); }); - - it('should update list of collections on pagination change', () => { - subCollList = collections; - fixture.detectChanges(); - - const pagination = Object.create({ - pagination:{ - id: comp.pageId, - currentPage: 2, - pageSize: 5 - }, - sort: { - field: 'dc.title', - direction: 'ASC' - } - }); - comp.onPaginationChange(pagination); - fixture.detectChanges(); - - const collList = fixture.debugElement.queryAll(By.css('li')); - expect(collList.length).toEqual(2); - expect(collList[0].nativeElement.textContent).toContain('Collection 6'); - expect(collList[1].nativeElement.textContent).toContain('Collection 7'); - }); }); diff --git a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts index 21ba1b28b0..1054879f0e 100644 --- a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts +++ b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts @@ -18,6 +18,10 @@ import { HostWindowService } from '../../shared/host-window.service'; import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub'; import { CommunityDataService } from '../../core/data/community-data.service'; import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { of as observableOf } from 'rxjs'; +import { PaginationService } from '../../core/pagination/pagination.service'; import { getMockThemeService } from '../../shared/mocks/theme-service.mock'; import { ThemeService } from '../../shared/theme-support/theme.service'; @@ -114,6 +118,16 @@ describe('CommunityPageSubCommunityListComponent Component', () => { } }; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + themeService = getMockThemeService(); beforeEach(waitForAsync(() => { @@ -129,6 +143,7 @@ describe('CommunityPageSubCommunityListComponent Component', () => { providers: [ { provide: CommunityDataService, useValue: communityDataServiceStub }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, + { provide: PaginationService, useValue: paginationService }, { provide: SelectableListService, useValue: {} }, { provide: ThemeService, useValue: themeService }, ], @@ -163,28 +178,4 @@ describe('CommunityPageSubCommunityListComponent Component', () => { const subComHead = fixture.debugElement.queryAll(By.css('h2')); expect(subComHead.length).toEqual(0); }); - - it('should update list of sub-communities on pagination change', () => { - subCommList = subcommunities; - fixture.detectChanges(); - - const pagination = Object.create({ - pagination:{ - id: comp.pageId, - currentPage: 2, - pageSize: 5 - }, - sort: { - field: 'dc.title', - direction: 'ASC' - } - }); - comp.onPaginationChange(pagination); - fixture.detectChanges(); - - const collList = fixture.debugElement.queryAll(By.css('li')); - expect(collList.length).toEqual(2); - expect(collList[0].nativeElement.textContent).toContain('SubCommunity 6'); - expect(collList[1].nativeElement.textContent).toContain('SubCommunity 7'); - }); }); diff --git a/src/app/+home-page/top-level-community-list/top-level-community-list.component.spec.ts b/src/app/+home-page/top-level-community-list/top-level-community-list.component.spec.ts index 0daa0a0ae0..4a5549cf4a 100644 --- a/src/app/+home-page/top-level-community-list/top-level-community-list.component.spec.ts +++ b/src/app/+home-page/top-level-community-list/top-level-community-list.component.spec.ts @@ -18,6 +18,10 @@ import { HostWindowService } from '../../shared/host-window.service'; import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub'; import { CommunityDataService } from '../../core/data/community-data.service'; import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service'; +import { of as observableOf } from 'rxjs'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { PaginationService } from '../../core/pagination/pagination.service'; import { getMockThemeService } from '../../shared/mocks/theme-service.mock'; import { ThemeService } from '../../shared/theme-support/theme.service'; @@ -25,6 +29,7 @@ describe('TopLevelCommunityList Component', () => { let comp: TopLevelCommunityListComponent; let fixture: ComponentFixture; let communityDataServiceStub: any; + let paginationService; let themeService; const topCommList = [Object.assign(new Community(), { @@ -104,6 +109,15 @@ describe('TopLevelCommunityList Component', () => { } }; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getRouteParameterValue: observableOf('') + }); + themeService = getMockThemeService(); beforeEach(waitForAsync(() => { @@ -119,6 +133,7 @@ describe('TopLevelCommunityList Component', () => { providers: [ { provide: CommunityDataService, useValue: communityDataServiceStub }, { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, + { provide: PaginationService, useValue: paginationService }, { provide: SelectableListService, useValue: {} }, { provide: ThemeService, useValue: themeService }, ], @@ -143,25 +158,4 @@ describe('TopLevelCommunityList Component', () => { expect(subComList[3].nativeElement.textContent).toContain('TopCommunity 4'); expect(subComList[4].nativeElement.textContent).toContain('TopCommunity 5'); }); - - it('should update list of top-communities on pagination change', () => { - const pagination = Object.create({ - pagination: { - id: comp.pageId, - currentPage: 2, - pageSize: 5 - }, - sort: { - field: 'dc.title', - direction: 'ASC' - } - }); - comp.onPaginationChange(pagination); - fixture.detectChanges(); - - const collList = fixture.debugElement.queryAll(By.css('li')); - expect(collList.length).toEqual(2); - expect(collList[0].nativeElement.textContent).toContain('TopCommunity 6'); - expect(collList[1].nativeElement.textContent).toContain('TopCommunity 7'); - }); }); diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts index 717c5873d2..f3c50f4d13 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts @@ -16,6 +16,10 @@ import { ResponsiveColumnSizes } from '../../../../../shared/responsive-table-si import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils'; import { createPaginatedList } from '../../../../../shared/testing/utils.test'; import { RequestService } from '../../../../../core/data/request.service'; +import { PaginationService } from '../../../../../core/pagination/pagination.service'; +import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../../core/data/request.models'; describe('PaginatedDragAndDropBitstreamListComponent', () => { let comp: PaginatedDragAndDropBitstreamListComponent; @@ -24,6 +28,7 @@ describe('PaginatedDragAndDropBitstreamListComponent', () => { let bundleService: BundleDataService; let objectValuesPipe: ObjectValuesPipe; let requestService: RequestService; + let paginationService: PaginationService; const columnSizes = new ResponsiveTableSizes([ new ResponsiveColumnSizes(2, 2, 3, 4, 4), @@ -109,6 +114,16 @@ describe('PaginatedDragAndDropBitstreamListComponent', () => { hasByHref$: observableOf(true) }); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], declarations: [PaginatedDragAndDropBitstreamListComponent, VarDirective], @@ -116,7 +131,8 @@ describe('PaginatedDragAndDropBitstreamListComponent', () => { { provide: ObjectUpdatesService, useValue: objectUpdatesService }, { provide: BundleDataService, useValue: bundleService }, { provide: ObjectValuesPipe, useValue: objectValuesPipe }, - { provide: RequestService, useValue: requestService } + { provide: RequestService, useValue: requestService }, + { provide: PaginationService, useValue: paginationService } ], schemas: [ NO_ERRORS_SCHEMA ] diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.spec.ts b/src/app/+item-page/full/field-components/file-section/full-file-section.component.spec.ts index 1773a0fe74..0723354ef5 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.spec.ts +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.spec.ts @@ -16,6 +16,10 @@ 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'; +import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../core/data/request.models'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; describe('FullFileSectionComponent', () => { let comp: FullFileSectionComponent; @@ -52,6 +56,16 @@ describe('FullFileSectionComponent', () => { findAllByItemAndBundleName: createSuccessfulRemoteDataObject$(createPaginatedList([mockBitstream, mockBitstream, mockBitstream])) }); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -64,7 +78,8 @@ describe('FullFileSectionComponent', () => { declarations: [FullFileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent], providers: [ { provide: BitstreamDataService, useValue: bitstreamDataService }, - { provide: NotificationsService, useValue: new NotificationsServiceStub() } + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: PaginationService, useValue: paginationService } ], schemas: [NO_ERRORS_SCHEMA] @@ -82,39 +97,5 @@ describe('FullFileSectionComponent', () => { 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(); - }); - }); - }); }); }); diff --git a/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts b/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts index 6cbab8125b..86489019d9 100644 --- a/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts +++ b/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts @@ -34,12 +34,18 @@ describe('MyDSpaceConfigurationService', () => { getRouteDataValue: observableOf({}) }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(defaults.pagination), + getCurrentSort: observableOf(defaults.sort), + getRouteParameterValue: observableOf('') + }); + const activatedRoute: any = new ActivatedRouteStub(); const roleService: any = new RoleServiceMock(); beforeEach(() => { - service = new MyDSpaceConfigurationService(roleService, spy, activatedRoute); + service = new MyDSpaceConfigurationService(roleService, spy, paginationService, activatedRoute); }); describe('when the scope is called', () => { @@ -102,25 +108,19 @@ describe('MyDSpaceConfigurationService', () => { describe('when getCurrentSort is called', () => { beforeEach(() => { - // service.getCurrentSort({} as any); + service.getCurrentSort('page-id', defaults.sort); }); - it('should call getQueryParameterValue on the routeService with parameter name \'sortDirection\'', () => { - expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortDirection'); - }); - it('should call getQueryParameterValue on the routeService with parameter name \'sortField\'', () => { - expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortField'); + it('should call getCurrentSort on the paginationService with the provided id and sort options', () => { + expect((service as any).paginationService.getCurrentSort).toHaveBeenCalledWith('page-id', defaults.sort); }); }); describe('when getCurrentPagination is called', () => { beforeEach(() => { - // service.getCurrentPagination({ currentPage: 1, pageSize: 10 } as any); + service.getCurrentPagination('page-id', defaults.pagination); }); - it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => { - expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page'); - }); - it('should call getQueryParameterValue on the routeService with parameter name \'pageSize\'', () => { - expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('pageSize'); + it('should call getCurrentPagination on the paginationService with the provided id and sort options', () => { + expect((service as any).paginationService.getCurrentPagination).toHaveBeenCalledWith('page-id', defaults.pagination); }); }); @@ -152,7 +152,7 @@ describe('MyDSpaceConfigurationService', () => { describe('when subscribeToPaginatedSearchOptions is called', () => { beforeEach(() => { - (service as any).subscribeToPaginatedSearchOptions(defaults); + (service as any).subscribeToPaginatedSearchOptions('id', defaults); }); it('should call all getters it needs', () => { expect(service.getCurrentPagination).toHaveBeenCalled(); diff --git a/src/app/+my-dspace-page/my-dspace-configuration.service.ts b/src/app/+my-dspace-page/my-dspace-configuration.service.ts index 19eba0fa06..82f76eb776 100644 --- a/src/app/+my-dspace-page/my-dspace-configuration.service.ts +++ b/src/app/+my-dspace-page/my-dspace-configuration.service.ts @@ -56,6 +56,7 @@ export class MyDSpaceConfigurationService extends SearchConfigurationService { * * @param {roleService} roleService * @param {RouteService} routeService + * @param {PaginationService} paginationService * @param {ActivatedRoute} route */ constructor(protected roleService: RoleService, diff --git a/src/app/core/pagination/pagination.service.spec.ts b/src/app/core/pagination/pagination.service.spec.ts new file mode 100644 index 0000000000..990dcd9b90 --- /dev/null +++ b/src/app/core/pagination/pagination.service.spec.ts @@ -0,0 +1,149 @@ +import { PaginationService } from './pagination.service'; +import { RouterStub } from '../../shared/testing/router.stub'; +import { of as observableOf } from 'rxjs'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../cache/models/sort-options.model'; +import { FindListOptions } from '../data/request.models'; + + +describe('PaginationService', () => { + let service: PaginationService; + let router; + let routeService; + + const defaultPagination = new PaginationComponentOptions(); + const defaultSort = new SortOptions('id', SortDirection.DESC); + const defaultFindListOptions = new FindListOptions(); + + beforeEach(() => { + router = new RouterStub(); + routeService = { + getQueryParameterValue: (param) => { + let value; + if (param.startsWith('p.')) { + value = 5; + } + if (param.startsWith('rpp.')) { + value = 10; + } + if (param.startsWith('sd.')) { + value = 'ASC'; + } + if (param.startsWith('sf.')) { + value = 'score'; + } + return observableOf(value); + } + }; + + service = new PaginationService(routeService, router); + }); + + + describe('getCurrentPagination', () => { + it('should retrieve the current pagination info from the routerService', () => { + service.getCurrentPagination('test-id', defaultPagination).subscribe((currentPagination) => { + expect(currentPagination).toEqual(Object.assign(new PaginationComponentOptions(), { + currentPage: 5, + pageSize: 10 + })); + }); + }); + }); + describe('getCurrentSort', () => { + it('should retrieve the current sort info from the routerService', () => { + service.getCurrentSort('test-id', defaultSort).subscribe((currentSort) => { + expect(currentSort).toEqual(Object.assign(new SortOptions('score', SortDirection.ASC ))); + }); + }); + }); + describe('getFindListOptions', () => { + it('should retrieve the current findListOptions info from the routerService', () => { + service.getFindListOptions('test-id', defaultFindListOptions).subscribe((findListOptions) => { + expect(findListOptions).toEqual(Object.assign(new FindListOptions(), + { + sort: new SortOptions('score', SortDirection.ASC ), + currentPage: 5, + elementsPerPage: 10 + })); + }); + }); + }); + describe('resetPage', () => { + it('should call the updateRoute method with the id and page 1', () => { + spyOn(service, 'updateRoute'); + service.resetPage('test'); + + expect(service.updateRoute).toHaveBeenCalledWith('test', {page: 1}); + }); + }); + + describe('updateRoute', () => { + it('should update the route with the provided page params', () => { + service.updateRoute('test', {page: 2, pageSize: 5, sortField: 'title', sortDirection: SortDirection.DESC}); + + const navigateParams = {}; + navigateParams[`p.test`] = `2`; + navigateParams[`rpp.test`] = `5`; + navigateParams[`sf.test`] = `title`; + navigateParams[`sd.test`] = `DESC`; + + expect(router.navigate).toHaveBeenCalledWith([], {queryParams: navigateParams, queryParamsHandling: 'merge'}); + }); + it('should update the route with the provided page params while keeping the existing non provided ones', () => { + service.updateRoute('test', {page: 2}); + + const navigateParams = {}; + navigateParams[`p.test`] = `2`; + navigateParams[`rpp.test`] = `10`; + navigateParams[`sf.test`] = `score`; + navigateParams[`sd.test`] = `ASC`; + + expect(router.navigate).toHaveBeenCalledWith([], {queryParams: navigateParams, queryParamsHandling: 'merge'}); + }); + }); + describe('updateRouteWithUrl', () => { + it('should update the route with the provided page params and url', () => { + service.updateRouteWithUrl('test', ['someUrl'], {page: 2, pageSize: 5, sortField: 'title', sortDirection: SortDirection.DESC}); + + const navigateParams = {}; + navigateParams[`p.test`] = `2`; + navigateParams[`rpp.test`] = `5`; + navigateParams[`sf.test`] = `title`; + navigateParams[`sd.test`] = `DESC`; + + expect(router.navigate).toHaveBeenCalledWith(['someUrl'], {queryParams: navigateParams, queryParamsHandling: 'merge'}); + }); + it('should update the route with the provided page params and url while keeping the existing non provided ones', () => { + service.updateRouteWithUrl('test',['someUrl'], {page: 2}); + + const navigateParams = {}; + navigateParams[`p.test`] = `2`; + navigateParams[`rpp.test`] = `10`; + navigateParams[`sf.test`] = `score`; + navigateParams[`sd.test`] = `ASC`; + + expect(router.navigate).toHaveBeenCalledWith(['someUrl'], {queryParams: navigateParams, queryParamsHandling: 'merge'}); + }); + + }); + describe('clearPagination', () => { + it('should clear the pagination info from the route for the current id', () => { + service.clearPagination('test'); + + const params = {}; + params[`p.test`] = null; + params[`rpp.test`] = null; + params[`sf.test`] = null; + params[`sd.test`] = null; + + expect(router.navigate).toHaveBeenCalledWith([], {queryParams: params, queryParamsHandling: 'merge'}); + }); + }); + describe('getPageParam', () => { + it('should return the name of the page param', () => { + const pageParam = service.getPageParam('test'); + expect(pageParam).toEqual('p.test'); + }); + }); +}); diff --git a/src/app/core/pagination/pagination.service.ts b/src/app/core/pagination/pagination.service.ts index 0143d20923..29e57214c1 100644 --- a/src/app/core/pagination/pagination.service.ts +++ b/src/app/core/pagination/pagination.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Router } from '@angular/router'; import { RouteService } from '../services/route.service'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; @@ -9,7 +9,6 @@ import { FindListOptions } from '../data/request.models'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { difference } from '../../shared/object.util'; import { isNumeric } from 'rxjs/internal-compatibility'; -import { Location } from '@angular/common'; @Injectable({ @@ -20,9 +19,7 @@ export class PaginationService { private defaultSortOptions = new SortOptions('id', SortDirection.ASC); constructor(protected routeService: RouteService, - protected route: ActivatedRoute, - protected router: Router, - protected location: Location + protected router: Router ) { } @@ -33,6 +30,7 @@ export class PaginationService { const page$ = this.routeService.getQueryParameterValue(`p.${paginationId}`); const size$ = this.routeService.getQueryParameterValue(`rpp.${paginationId}`); return observableCombineLatest([page$, size$]).pipe(map(([page, size]) => { + console.log(page, size); return Object.assign(new PaginationComponentOptions(), defaultPagination, { currentPage: this.convertToNumeric(page, defaultPagination.currentPage), pageSize: this.getBestMatchPageSize(size, defaultPagination) @@ -80,7 +78,7 @@ export class PaginationService { this.updateRoute(paginationId, {page: 1}); } - getCurrentRouting(paginationId: string) { + private getCurrentRouting(paginationId: string) { return this.getFindListOptions(paginationId, {}, true).pipe( take(1), map((findListoptions: FindListOptions) => { @@ -88,7 +86,7 @@ export class PaginationService { page: findListoptions.currentPage, pageSize: findListoptions.elementsPerPage, sortField: findListoptions.sort.field, - sortDir: findListoptions.sort.direction, + sortDirection: findListoptions.sort.direction, }; }) ); @@ -101,12 +99,12 @@ export class PaginationService { sortDirection?: SortDirection }, extraParams?, retainScrollPosition?: boolean) { this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { + console.log('currentFindListOptions',currentFindListOptions ); const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); const parametersWithIdName = this.getParametersWithIdName(paginationId, params); if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { const queryParams = Object.assign({}, currentParametersWithIdName, parametersWithIdName, extraParams); - console.log(retainScrollPosition); if (retainScrollPosition) { this.router.navigate([], { queryParams: queryParams, @@ -169,7 +167,7 @@ export class PaginationService { return `p.${paginationId}`; } - getParametersWithIdName(paginationId: string, params: { + private getParametersWithIdName(paginationId: string, params: { page?: number pageSize?: number sortField?: string diff --git a/src/app/core/shared/search/search-configuration.service.spec.ts b/src/app/core/shared/search/search-configuration.service.spec.ts index 43c2c54427..f1f9dc7b9b 100644 --- a/src/app/core/shared/search/search-configuration.service.spec.ts +++ b/src/app/core/shared/search/search-configuration.service.spec.ts @@ -15,7 +15,7 @@ describe('SearchConfigurationService', () => { 'f.date.max': ['2018'] }; const defaults = new PaginatedSearchOptions({ - pagination: Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }), + pagination: Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 }), sort: new SortOptions('score', SortDirection.DESC), configuration: 'default', query: '', @@ -30,10 +30,17 @@ describe('SearchConfigurationService', () => { getRouteParameterValue: observableOf('') }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(defaults.pagination), + getCurrentSort: observableOf(defaults.sort), + getRouteParameterValue: observableOf('') + }); + + const activatedRoute: any = new ActivatedRouteStub(); beforeEach(() => { - service = new SearchConfigurationService(routeService, activatedRoute); + service = new SearchConfigurationService(routeService, paginationService, activatedRoute); }); describe('when the scope is called', () => { beforeEach(() => { @@ -95,25 +102,19 @@ describe('SearchConfigurationService', () => { describe('when getCurrentSort is called', () => { beforeEach(() => { - service.getCurrentSort({} as any); + service.getCurrentSort(defaults.pagination.id, {} as any); }); - it('should call getQueryParameterValue on the routeService with parameter name \'sortDirection\'', () => { - expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortDirection'); - }); - it('should call getQueryParameterValue on the routeService with parameter name \'sortField\'', () => { - expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortField'); + it('should call getCurrentSort on the paginationService with the provided id and sort options', () => { + expect((service as any).paginationService.getCurrentSort).toHaveBeenCalledWith(defaults.pagination.id, {}); }); }); describe('when getCurrentPagination is called', () => { beforeEach(() => { - service.getCurrentPagination({ currentPage: 1, pageSize: 10 } as any); + service.getCurrentPagination(defaults.pagination.id, defaults.pagination); }); - it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => { - expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page'); - }); - it('should call getQueryParameterValue on the routeService with parameter name \'pageSize\'', () => { - expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('pageSize'); + it('should call getCurrentPagination on the paginationService with the provided id and sort options', () => { + expect((service as any).paginationService.getCurrentPagination).toHaveBeenCalledWith(defaults.pagination.id, defaults.pagination); }); }); @@ -145,7 +146,7 @@ describe('SearchConfigurationService', () => { describe('when subscribeToPaginatedSearchOptions is called', () => { beforeEach(() => { - (service as any).subscribeToPaginatedSearchOptions(defaults); + (service as any).subscribeToPaginatedSearchOptions(defaults.pagination.id, defaults); }); it('should call all getters it needs', () => { expect(service.getCurrentPagination).toHaveBeenCalled(); diff --git a/src/app/core/shared/search/search.service.spec.ts b/src/app/core/shared/search/search.service.spec.ts index 06208094bd..9eb650219b 100644 --- a/src/app/core/shared/search/search.service.spec.ts +++ b/src/app/core/shared/search/search.service.spec.ts @@ -22,6 +22,11 @@ import { routeServiceStub } from '../../../shared/testing/route-service.stub'; import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; import { SearchObjects } from '../../../shared/search/search-objects.model'; +import { PaginationService } from '../../pagination/pagination.service'; +import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; +import { FindListOptions } from '../../data/request.models'; +import { SearchConfigurationService } from './search-configuration.service'; @Component({ template: '' }) class DummyComponent { @@ -32,6 +37,7 @@ describe('SearchService', () => { let searchService: SearchService; const router = new RouterStub(); const route = new ActivatedRouteStub(); + const searchConfigService = {paginationID: 'page-id'}; beforeEach(() => { TestBed.configureTestingModule({ imports: [ @@ -51,6 +57,8 @@ describe('SearchService', () => { { provide: HALEndpointService, useValue: {} }, { provide: CommunityDataService, useValue: {} }, { provide: DSpaceObjectDataService, useValue: {} }, + { provide: PaginationService, useValue: {} }, + { provide: SearchConfigurationService, useValue: searchConfigService }, SearchService ], }); @@ -94,6 +102,18 @@ describe('SearchService', () => { } }; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {} + }); + const searchConfigService = {paginationID: 'page-id'}; + beforeEach(() => { TestBed.configureTestingModule({ imports: [ @@ -113,6 +133,8 @@ describe('SearchService', () => { { provide: HALEndpointService, useValue: halService }, { provide: CommunityDataService, useValue: {} }, { provide: DSpaceObjectDataService, useValue: {} }, + { provide: PaginationService, useValue: paginationService }, + { provide: SearchConfigurationService, useValue: searchConfigService }, SearchService ], }); @@ -124,18 +146,14 @@ describe('SearchService', () => { it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => { searchService.setViewMode(ViewMode.ListElement); - expect(router.navigate).toHaveBeenCalledWith(['/search'], { - queryParams: { view: ViewMode.ListElement, page: 1 }, - queryParamsHandling: 'merge' - }); + expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith('page-id', ['/search'], {page: 1}, { view: ViewMode.ListElement } + ); }); it('should call the navigate method on the Router with view mode grid parameter as a parameter when setViewMode is called', () => { searchService.setViewMode(ViewMode.GridElement); - expect(router.navigate).toHaveBeenCalledWith(['/search'], { - queryParams: { view: ViewMode.GridElement, page: 1 }, - queryParamsHandling: 'merge' - }); + expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith('page-id', ['/search'], {page: 1}, { view: ViewMode.GridElement } + ); }); it('should return ViewMode.List when the viewMode is set to ViewMode.List in the ActivatedRoute', () => { diff --git a/src/app/process-page/overview/process-overview.component.spec.ts b/src/app/process-page/overview/process-overview.component.spec.ts index ffbcbb10cf..1da2ac2b5b 100644 --- a/src/app/process-page/overview/process-overview.component.spec.ts +++ b/src/app/process-page/overview/process-overview.component.spec.ts @@ -12,6 +12,11 @@ import { By } from '@angular/platform-browser'; import { ProcessStatus } from '../processes/process-status.model'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; import { createPaginatedList } from '../../shared/testing/utils.test'; +import { of as observableOf } from 'rxjs'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../core/data/request.models'; describe('ProcessOverviewComponent', () => { let component: ProcessOverviewComponent; @@ -19,10 +24,15 @@ describe('ProcessOverviewComponent', () => { let processService: ProcessDataService; let ePersonService: EPersonDataService; + let paginationService: PaginationService; let processes: Process[]; let ePerson: EPerson; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + function init() { processes = [ Object.assign(new Process(), { @@ -69,6 +79,12 @@ describe('ProcessOverviewComponent', () => { ePersonService = jasmine.createSpyObj('ePersonService', { findById: createSuccessfulRemoteDataObject$(ePerson) }); + + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + }); } beforeEach(waitForAsync(() => { @@ -78,7 +94,8 @@ describe('ProcessOverviewComponent', () => { imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], providers: [ { provide: ProcessDataService, useValue: processService }, - { provide: EPersonDataService, useValue: ePersonService } + { provide: EPersonDataService, useValue: ePersonService }, + { provide: PaginationService, useValue: paginationService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -143,16 +160,4 @@ describe('ProcessOverviewComponent', () => { }); }); }); - - describe('onPageChange', () => { - const toPage = 2; - - beforeEach(() => { - component.onPageChange(toPage); - }); - - it('should call a new findAll with the corresponding page', () => { - expect(processService.findAll).toHaveBeenCalledWith(jasmine.objectContaining({ currentPage: toPage })); - }); - }); }); diff --git a/src/app/search-navbar/search-navbar.component.spec.ts b/src/app/search-navbar/search-navbar.component.spec.ts index 9eef81a42e..87b75328bb 100644 --- a/src/app/search-navbar/search-navbar.component.spec.ts +++ b/src/app/search-navbar/search-navbar.component.spec.ts @@ -8,6 +8,11 @@ import { SearchService } from '../core/shared/search/search.service'; import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock'; import { SearchNavbarComponent } from './search-navbar.component'; +import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; +import { of as observableOf } from 'rxjs'; +import { PaginationService } from '../core/pagination/pagination.service'; +import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; describe('SearchNavbarComponent', () => { let component: SearchNavbarComponent; @@ -15,6 +20,7 @@ describe('SearchNavbarComponent', () => { let mockSearchService: any; let router: Router; let routerStub; + let paginationService; beforeEach(waitForAsync(() => { mockSearchService = { @@ -26,6 +32,18 @@ describe('SearchNavbarComponent', () => { routerStub = { navigate: (commands) => commands }; + + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getRouteParameterValue: observableOf(''), + updateRouteWithUrl: {}, + clearPagination : {} + }); + TestBed.configureTestingModule({ imports: [ FormsModule, @@ -40,7 +58,9 @@ describe('SearchNavbarComponent', () => { declarations: [SearchNavbarComponent], providers: [ { provide: SearchService, useValue: mockSearchService }, - { provide: Router, useValue: routerStub } + { provide: PaginationService, useValue: paginationService }, + { provide: Router, useValue: routerStub }, + { provide: SearchConfigurationService, useValue: {paginationID: 'page-id'} } ] }) .compileComponents(); @@ -88,7 +108,7 @@ describe('SearchNavbarComponent', () => { })); it('to search page with empty query', () => { expect(component.onSubmit).toHaveBeenCalledWith({ query: '' }); - expect(router.navigate).toHaveBeenCalled(); + expect(paginationService.updateRouteWithUrl).toHaveBeenCalled(); }); }); }); @@ -112,7 +132,7 @@ describe('SearchNavbarComponent', () => { })); it('to search page with query', async () => { expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' }); - expect(router.navigate).toHaveBeenCalled(); + expect(paginationService.updateRouteWithUrl).toHaveBeenCalled(); }); }); }); 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 9f3ceade1a..4c9ac9204d 100644 --- a/src/app/shared/browse-by/browse-by.component.spec.ts +++ b/src/app/shared/browse-by/browse-by.component.spec.ts @@ -18,6 +18,8 @@ import { PaginationComponentOptions } from '../pagination/pagination-component-o import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; import { storeModuleConfig } from '../../app.reducer'; +import { FindListOptions } from '../../core/data/request.models'; +import { PaginationService } from '../../core/pagination/pagination.service'; describe('BrowseByComponent', () => { let comp: BrowseByComponent; @@ -45,6 +47,22 @@ describe('BrowseByComponent', () => { ]; const mockItemsRD$ = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), mockItems)); + const paginationConfig = Object.assign(new PaginationComponentOptions(), { + id: 'test-pagination', + currentPage: 1, + pageSizeOptions: [5, 10, 15, 20], + pageSize: 15 + }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(paginationConfig), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + updateRoute: {}, + resetPage: {}, + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ @@ -63,7 +81,9 @@ describe('BrowseByComponent', () => { BrowserAnimationsModule ], declarations: [], - providers: [], + providers: [ + {provide: PaginationService, useValue: paginationService} + ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); })); @@ -95,12 +115,8 @@ describe('BrowseByComponent', () => { beforeEach(() => { comp.enableArrows = true; comp.objects$ = mockItemsRD$; - comp.paginationConfig = Object.assign(new PaginationComponentOptions(), { - id: 'test-pagination', - currentPage: 1, - pageSizeOptions: [5, 10, 15, 20], - pageSize: 15 - }); + + comp.paginationConfig = paginationConfig; comp.sortConfig = Object.assign(new SortOptions('dc.title', SortDirection.ASC)); fixture.detectChanges(); }); @@ -136,8 +152,8 @@ describe('BrowseByComponent', () => { fixture.detectChanges(); }); - it('should emit a signal to the EventEmitter', () => { - expect(comp.pageSizeChange.emit).toHaveBeenCalled(); + it('should call the updateRoute method from the paginationService', () => { + expect(paginationService.updateRoute).toHaveBeenCalledWith('test-pagination', {pageSize: paginationConfig.pageSizeOptions[0]}); }); }); @@ -148,8 +164,8 @@ describe('BrowseByComponent', () => { fixture.detectChanges(); }); - it('should emit a signal to the EventEmitter', () => { - expect(comp.sortDirectionChange.emit).toHaveBeenCalled(); + it('should call the updateRoute method from the paginationService', () => { + expect(paginationService.updateRoute).toHaveBeenCalledWith('test-pagination', {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 8920726c8b..1f05ad2258 100644 --- a/src/app/shared/browse-by/browse-by.component.ts +++ b/src/app/shared/browse-by/browse-by.component.ts @@ -144,7 +144,7 @@ export class BrowseByComponent implements OnInit { this.objectInjector = Injector.create({ providers: [ { provide: 'startsWithOptions', useFactory: () => (this.startsWithOptions), deps:[] }, - { provide: 'paginationId', useFactory: () => (this.paginationConfig.id), deps:[] } + { provide: 'paginationId', useFactory: () => (this.paginationConfig?.id), deps:[] } ], parent: this.injector }); diff --git a/src/app/shared/item/item-versions/item-versions.component.spec.ts b/src/app/shared/item/item-versions/item-versions.component.spec.ts index f35ec1993d..33e99eb88f 100644 --- a/src/app/shared/item/item-versions/item-versions.component.spec.ts +++ b/src/app/shared/item/item-versions/item-versions.component.spec.ts @@ -11,11 +11,18 @@ import { VersionHistoryDataService } from '../../../core/data/version-history-da import { By } from '@angular/platform-browser'; import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; import { createPaginatedList } from '../../testing/utils.test'; +import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { of as observableOf } from 'rxjs'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('ItemVersionsComponent', () => { let component: ItemVersionsComponent; let fixture: ComponentFixture; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const versionHistory = Object.assign(new VersionHistory(), { id: '1' }); @@ -52,12 +59,19 @@ describe('ItemVersionsComponent', () => { getVersions: createSuccessfulRemoteDataObject$(createPaginatedList(versions)) }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getRouteParameterValue: observableOf('') + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ItemVersionsComponent, VarDirective], imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], providers: [ - { provide: VersionHistoryDataService, useValue: versionHistoryService } + { provide: VersionHistoryDataService, useValue: versionHistoryService }, + { provide: PaginationService, useValue: paginationService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); @@ -107,16 +121,4 @@ describe('ItemVersionsComponent', () => { expect(summary.nativeElement.textContent).toEqual(version.summary); }); }); - - describe('switchPage', () => { - const page = 5; - - beforeEach(() => { - component.switchPage(page); - }); - - it('should set the option\'s currentPage to the new page', () => { - expect(component.options.currentPage).toEqual(page); - }); - }); }); diff --git a/src/app/shared/object-select/collection-select/collection-select.component.spec.ts b/src/app/shared/object-select/collection-select/collection-select.component.spec.ts index fd4a239cc4..60cce1ae09 100644 --- a/src/app/shared/object-select/collection-select/collection-select.component.spec.ts +++ b/src/app/shared/object-select/collection-select/collection-select.component.spec.ts @@ -13,6 +13,10 @@ import { CollectionSelectComponent } from './collection-select.component'; import { Collection } from '../../../core/shared/collection.model'; import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; import { createPaginatedList } from '../../testing/utils.test'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { of as observableOf } from 'rxjs'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('CollectionSelectComponent', () => { let comp: CollectionSelectComponent; @@ -36,13 +40,24 @@ describe('CollectionSelectComponent', () => { currentPage: 1 }); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, RouterTestingModule.withRoutes([])], declarations: [], providers: [ { provide: ObjectSelectService, useValue: new ObjectSelectServiceStub([mockCollectionList[1].id]) }, - { provide: HostWindowService, useValue: new HostWindowServiceStub(0) } + { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, + { provide: PaginationService, useValue: paginationService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/shared/object-select/item-select/item-select.component.spec.ts b/src/app/shared/object-select/item-select/item-select.component.spec.ts index f99991f391..2ca3cd4fa8 100644 --- a/src/app/shared/object-select/item-select/item-select.component.spec.ts +++ b/src/app/shared/object-select/item-select/item-select.component.spec.ts @@ -11,14 +11,18 @@ import { HostWindowService } from '../../host-window.service'; import { HostWindowServiceStub } from '../../testing/host-window-service.stub'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { of } from 'rxjs'; +import { of as observableOf, of } from 'rxjs'; import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; import { createPaginatedList } from '../../testing/utils.test'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; describe('ItemSelectComponent', () => { let comp: ItemSelectComponent; let fixture: ComponentFixture; let objectSelectService: ObjectSelectService; + let paginationService: PaginationService; const mockItemList = [ Object.assign(new Item(), { @@ -59,13 +63,25 @@ describe('ItemSelectComponent', () => { currentPage: 1 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(mockPaginationOptions), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + + + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, RouterTestingModule.withRoutes([])], declarations: [], providers: [ { provide: ObjectSelectService, useValue: new ObjectSelectServiceStub([mockItemList[1].id]) }, - { provide: HostWindowService, useValue: new HostWindowServiceStub(0) } + { provide: HostWindowService, useValue: new HostWindowServiceStub(0) }, + { provide: PaginationService, useValue: paginationService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/shared/page-size-selector/page-size-selector.component.spec.ts b/src/app/shared/page-size-selector/page-size-selector.component.spec.ts index f75b5841af..cf7f1d5e11 100644 --- a/src/app/shared/page-size-selector/page-size-selector.component.spec.ts +++ b/src/app/shared/page-size-selector/page-size-selector.component.spec.ts @@ -12,6 +12,7 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options import { EnumKeysPipe } from '../utils/enum-keys-pipe'; import { VarDirective } from '../utils/var.directive'; import { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.component'; +import { PaginationService } from '../../core/pagination/pagination.service'; describe('PageSizeSelectorComponent', () => { @@ -33,6 +34,12 @@ describe('PageSizeSelectorComponent', () => { sort }; + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getRouteParameterValue: observableOf('') + }); + const activatedRouteStub = { queryParams: observableOf({ query: queryParam, @@ -46,6 +53,7 @@ describe('PageSizeSelectorComponent', () => { declarations: [PageSizeSelectorComponent, EnumKeysPipe, VarDirective], providers: [ { provide: ActivatedRoute, useValue: activatedRouteStub }, + { provide: PaginationService, useValue: paginationService }, { provide: SEARCH_CONFIG_SERVICE, useValue: { diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts index 905b739270..4c29e2af9d 100644 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts +++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts @@ -11,6 +11,9 @@ import { PaginationComponent } from '../pagination/pagination.component'; import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; import { createPaginatedList } from '../testing/utils.test'; import { ObjectValuesPipe } from '../utils/object-values-pipe'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; @Component({ selector: 'ds-mock-paginated-drag-drop-abstract', @@ -22,8 +25,9 @@ class MockAbstractPaginatedDragAndDropListComponent extends AbstractPaginatedDra protected elRef: ElementRef, protected objectValuesPipe: ObjectValuesPipe, protected mockUrl: string, - protected mockObjectsRD$: Observable>>) { - super(objectUpdatesService, elRef, objectValuesPipe); + protected paginationService: PaginationService, + protected mockObjectsRD$: Observable>>) { + super(objectUpdatesService, elRef, objectValuesPipe, paginationService); } initializeObjectsRD(): void { @@ -43,10 +47,14 @@ describe('AbstractPaginatedDragAndDropListComponent', () => { const url = 'mock-abstract-paginated-drag-and-drop-list-component'; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const object1 = Object.assign(new DSpaceObject(), { uuid: 'object-1' }); const object2 = Object.assign(new DSpaceObject(), { uuid: 'object-2' }); const objectsRD = createSuccessfulRemoteDataObject(createPaginatedList([object1, object2])); let objectsRD$: BehaviorSubject>>; + let paginationService; const updates = { [object1.uuid]: { field: object1, changeType: undefined }, @@ -69,8 +77,13 @@ describe('AbstractPaginatedDragAndDropListComponent', () => { paginationComponent = jasmine.createSpyObj('paginationComponent', { doPageChange: {} }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getRouteParameterValue: observableOf('') + }); objectsRD$ = new BehaviorSubject(objectsRD); - component = new MockAbstractPaginatedDragAndDropListComponent(objectUpdatesService, elRef, objectValuesPipe, url, objectsRD$); + component = new MockAbstractPaginatedDragAndDropListComponent(objectUpdatesService, elRef, objectValuesPipe, url, paginationService, objectsRD$); component.paginationComponent = paginationComponent; component.ngOnInit(); }); @@ -86,18 +99,6 @@ describe('AbstractPaginatedDragAndDropListComponent', () => { }); }); - describe('switchPage', () => { - const page = 3; - - beforeEach(() => { - component.switchPage(page); - }); - - it('should set currentPage$ to the new page', () => { - expect(component.currentPage$.value).toEqual(page); - }); - }); - describe('drop', () => { const event = { previousIndex: 0, diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts index 684ffb55e8..bad54d6e83 100644 --- a/src/app/shared/pagination/pagination.component.spec.ts +++ b/src/app/shared/pagination/pagination.component.spec.ts @@ -31,10 +31,15 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options import { createTestComponent } from '../testing/utils.test'; import { storeModuleConfig } from '../../app.reducer'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { FindListOptions } from '../../core/data/request.models'; +import { BehaviorSubject, of as observableOf } from 'rxjs'; function expectPages(fixture: ComponentFixture, pagesDef: string[]): void { const de = fixture.debugElement.query(By.css('.pagination')); const pages = de.nativeElement.querySelectorAll('li'); + console.log('pages', pages.length, pagesDef.length); + console.log(pages); expect(pages.length).toEqual(pagesDef.length); @@ -105,14 +110,39 @@ describe('Pagination component', () => { let activatedRouteStub: MockActivatedRoute; let routerStub: RouterMock; + let paginationService: PaginationService; + // Define initial state and test state const _initialState = { width: 1600, height: 770 }; + const pagination = new PaginationComponentOptions(); + pagination.currentPage = 1; + pagination.pageSize = 10; + + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 10 }); + let currentPagination; + let currentSort; + let currentFindListOptions; + // waitForAsync beforeEach beforeEach(waitForAsync(() => { activatedRouteStub = new MockActivatedRoute(); - routerStub = new RouterMock(); - hostWindowServiceStub = new HostWindowServiceMock(_initialState.width); + routerStub = new RouterMock(); hostWindowServiceStub = new HostWindowServiceMock(_initialState.width); + + currentPagination = new BehaviorSubject(pagination); + currentSort = new BehaviorSubject(sort); + currentFindListOptions = new BehaviorSubject(findlistOptions); + + + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: currentPagination, + getCurrentSort: currentSort, + getFindListOptions: currentFindListOptions, + resetPage: {}, + updateRoute: {}, + updateRouteWithUrl: {} + }); TestBed.configureTestingModule({ imports: [ @@ -138,6 +168,7 @@ describe('Pagination component', () => { { provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: Router, useValue: routerStub }, { provide: HostWindowService, useValue: hostWindowServiceStub }, + { provide: PaginationService, useValue: paginationService }, ChangeDetectorRef, PaginationComponent ], @@ -179,11 +210,17 @@ describe('Pagination component', () => { it('should render and respond to page change', () => { testComp.collectionSize = 30; + testFixture.detectChanges(); + + + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {currentPage: 3})); + testFixture.detectChanges(); - changePage(testFixture, 3); expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']); - changePage(testFixture, 0); + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {currentPage: 2})); + testFixture.detectChanges(); + expectPages(testFixture, ['« Previous', '1', '+2', '3', '» Next']); }); @@ -205,58 +242,41 @@ describe('Pagination component', () => { testFixture.detectChanges(); expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); - paginationComponent.setPageSize(5); + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 5})); testFixture.detectChanges(); + expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '6', '» Next']); - paginationComponent.setPageSize(10); + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 10})); testFixture.detectChanges(); expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']); - paginationComponent.setPageSize(20); + currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 20})); testFixture.detectChanges(); expectPages(testFixture, ['-« Previous', '+1', '2', '» Next']); }); - it('should emit pageChange event with correct value', fakeAsync(() => { - const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; - - spyOn(testComp, 'pageChanged'); - - paginationComponent.setPage(3); - tick(); - - expect(testComp.pageChanged).toHaveBeenCalledWith(3); - })); - it('should emit pageSizeChange event with correct value', fakeAsync(() => { const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; spyOn(testComp, 'pageSizeChanged'); - paginationComponent.setPageSize(5); + testComp.pageSizeChanged(5); tick(); expect(testComp.pageSizeChanged).toHaveBeenCalledWith(5); })); - it('should set correct page route parameters', fakeAsync(() => { - routerStub = testFixture.debugElement.injector.get(Router) as any; - + it('should call the updateRoute method on the paginationService with the correct params', fakeAsync(() => { testComp.collectionSize = 60; changePage(testFixture, 3); tick(); - expect(routerStub.navigate).toHaveBeenCalledWith([], { - queryParams: { - pageId: 'test', - page: '3', - pageSize: 10, - sortDirection: 'ASC', - sortField: 'dc.title' - }, queryParamsHandling: 'merge' - }); + 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(() => { @@ -266,58 +286,9 @@ describe('Pagination component', () => { changePageSize(testFixture, '20'); tick(); - expect(routerStub.navigate).toHaveBeenCalledWith([], { - queryParams: { - pageId: 'test', - page: 1, - pageSize: 20, - sortDirection: 'ASC', - sortField: 'dc.title' - }, queryParamsHandling: 'merge' - }); + expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ pageId: 'test', page: 1, pageSize: 20}), {}, false); })); - it('should set correct values', fakeAsync(() => { - const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p; - routerStub = testFixture.debugElement.injector.get(Router) as any; - - testComp.collectionSize = 60; - - paginationComponent.setPage(3); - expect(paginationComponent.currentPage).toEqual(3); - - paginationComponent.setPageSize(20); - expect(paginationComponent.pageSize).toEqual(20); - })); - - it('should get parameters from route', () => { - - activatedRouteStub = testFixture.debugElement.injector.get(ActivatedRoute) as any; - activatedRouteStub.testParams = { - pageId: 'test', - page: 2, - pageSize: 20 - }; - - testFixture.detectChanges(); - - expectPages(testFixture, ['« Previous', '1', '+2', '3', '4', '5', '» Next']); - expect(testComp.paginationOptions.currentPage).toEqual(2); - expect(testComp.paginationOptions.pageSize).toEqual(20); - - activatedRouteStub.testParams = { - pageId: 'test', - page: 3, - pageSize: 40 - }; - - testFixture.detectChanges(); - - expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']); - expect(testComp.paginationOptions.currentPage).toEqual(3); - expect(testComp.paginationOptions.pageSize).toEqual(40); - }); - 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; diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index d126565e8f..4a181d7090 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -20,6 +20,7 @@ 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 { tap } from 'rxjs/internal/operators/tap'; /** * The default pagination controls component. @@ -194,11 +195,14 @@ export class PaginationComponent implements OnDestroy, OnInit { this.id = this.paginationOptions.id || null; this.pageSizeOptions = this.paginationOptions.pageSizeOptions; this.currentPage$ = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe( + tap((v) => console.log('currentPage', v)), map((currentPagination) => currentPagination.currentPage) ); this.pageSize$ = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe( map((currentPagination) => currentPagination.pageSize) ); + this.pageSize$.subscribe((v) => console.log('this.pageSize$', v)); + this.currentPage$.subscribe((v) => console.log('this.currentPage$', v)); let sortOptions; if (this.sortOptions) { @@ -237,6 +241,7 @@ export class PaginationComponent implements OnDestroy, OnInit { */ public doPageChange(page: number) { this.updateParams({page: page.toString()}); + this.emitPaginationChange(); } /** @@ -247,6 +252,7 @@ export class PaginationComponent implements OnDestroy, OnInit { */ public doPageSizeChange(pageSize: number) { this.updateParams({ pageId: this.id, page: 1, pageSize: pageSize }); + this.emitPaginationChange(); } /** @@ -257,6 +263,7 @@ export class PaginationComponent implements OnDestroy, OnInit { */ public doSortDirectionChange(sortDirection: SortDirection) { this.updateParams({ pageId: this.id, page: 1, sortDirection: sortDirection }); + this.emitPaginationChange(); } /** @@ -267,50 +274,6 @@ export class PaginationComponent implements OnDestroy, OnInit { */ public doSortFieldChange(field: string) { this.updateParams({ pageId: this.id, page: 1, sortField: field }); - } - - /** - * Method to set the current page and trigger page change events - * - * @param page - * The new page value - */ - public setPage(page: number) { - this.pageChange.emit(page); - this.emitPaginationChange(); - } - - /** - * Method to set the current page size and trigger page size change events - * - * @param pageSize - * The new page size value. - */ - public setPageSize(pageSize: number) { - this.pageSizeChange.emit(pageSize); - this.emitPaginationChange(); - } - - /** - * Method to set the current sort direction and trigger sort direction change events - * - * @param sortDirection - * The new sort directionvalue. - */ - public setSortDirection(sortDirection: SortDirection) { - this.sortDirectionChange.emit(sortDirection); - this.emitPaginationChange(); - } - - /** - * Method to set the current sort field and trigger sort field change events - * - * @param sortField - * The new sort field. - */ - public setSortField(field: string) { - // this.sortField = field; - this.sortFieldChange.emit(field); this.emitPaginationChange(); } @@ -370,21 +333,6 @@ export class PaginationComponent implements OnDestroy, OnInit { } } - /** - * Method to check if none of the query params necessary for pagination are filled out. - * - * @param paginateOptions - * The paginate options object. - */ - private isEmptyPaginationParams(paginateOptions): boolean { - const properties = ['id', 'currentPage', 'pageSize', 'pageSizeOptions']; - const missing = properties.filter((prop) => { - return !(prop in paginateOptions); - }); - - return properties.length === missing.length; - } - /** * Property to check whether the current pagination object has multiple pages * @returns true if there are multiple pages, else returns false diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts index db01146bfe..a683a536b4 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts +++ b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts @@ -19,6 +19,9 @@ import { PaginationComponentOptions } from '../../../pagination/pagination-compo import { buildPaginatedList } from '../../../../core/data/paginated-list.model'; import { PageInfo } from '../../../../core/shared/page-info.model'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../core/data/request.models'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; describe('EpersonGroupListComponent test suite', () => { let comp: EpersonGroupListComponent; @@ -27,6 +30,7 @@ describe('EpersonGroupListComponent test suite', () => { let de; let groupService: any; let epersonService: any; + let paginationService; const paginationOptions: PaginationComponentOptions = new PaginationComponentOptions(); paginationOptions.id = uniqueId('eperson-group-list-pagination-test'); @@ -60,6 +64,16 @@ describe('EpersonGroupListComponent test suite', () => { const groupPaginatedList = buildPaginatedList(new PageInfo(), [GroupMock, GroupMock]); const groupPaginatedListRD = createSuccessfulRemoteDataObject(groupPaginatedList); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(paginationOptions), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + clearPagination: {} + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ @@ -74,6 +88,7 @@ describe('EpersonGroupListComponent test suite', () => { { provide: EPersonDataService, useValue: mockEpersonService }, { provide: GroupDataService, useValue: mockGroupService }, { provide: RequestService, useValue: getMockRequestService() }, + { provide: PaginationService, useValue: paginationService }, EpersonGroupListComponent, ChangeDetectorRef, Injector @@ -177,12 +192,6 @@ describe('EpersonGroupListComponent test suite', () => { a: false })); }); - - it('should update list on page change', () => { - spyOn(comp, 'updateList'); - - expect(compAsAny.updateList).toHaveBeenCalled(); - }); }); describe('when is list of group', () => { @@ -254,12 +263,6 @@ describe('EpersonGroupListComponent test suite', () => { })); }); - it('should update list on page change', () => { - spyOn(comp, 'updateList'); - - expect(compAsAny.updateList).toHaveBeenCalled(); - }); - it('should update list on search triggered', () => { const options: PaginationComponentOptions = comp.paginationOptions; const event: SearchEvent = { @@ -269,7 +272,7 @@ describe('EpersonGroupListComponent test suite', () => { spyOn(comp, 'updateList'); comp.onSearch(event); - expect(compAsAny.updateList).toHaveBeenCalledWith(options, 'metadata', 'test'); + expect(compAsAny.updateList).toHaveBeenCalledWith('metadata', 'test'); }); }); }); diff --git a/src/app/shared/search-form/search-form.component.spec.ts b/src/app/shared/search-form/search-form.component.spec.ts index f2293afeca..635d11f0d0 100644 --- a/src/app/shared/search-form/search-form.component.spec.ts +++ b/src/app/shared/search-form/search-form.component.spec.ts @@ -8,6 +8,12 @@ import { Community } from '../../core/shared/community.model'; import { TranslateModule } from '@ngx-translate/core'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { SearchService } from '../../core/shared/search/search.service'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../core/data/request.models'; +import { of as observableOf } from 'rxjs'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; describe('SearchFormComponent', () => { let comp: SearchFormComponent; @@ -15,6 +21,19 @@ describe('SearchFormComponent', () => { let de: DebugElement; let el: HTMLElement; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {} + }); + + const searchConfigService = {paginationID: 'test-id'}; + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [FormsModule, RouterTestingModule, TranslateModule.forRoot()], @@ -22,7 +41,9 @@ describe('SearchFormComponent', () => { { provide: SearchService, useValue: {} - } + }, + { provide: PaginationService, useValue: paginationService }, + { provide: SearchConfigurationService, useValue: searchConfigService } ], declarations: [SearchFormComponent] }).compileComponents(); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts index 4b2e5d2344..a01843248e 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts @@ -15,6 +15,10 @@ import { FacetValue } from '../../../../facet-value.model'; import { FilterType } from '../../../../filter-type.model'; import { SearchFilterConfig } from '../../../../search-filter-config.model'; import { SearchFacetOptionComponent } from './search-facet-option.component'; +import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../../../core/data/request.models'; +import { PaginationService } from '../../../../../../core/pagination/pagination.service'; describe('SearchFacetOptionComponent', () => { let comp: SearchFacetOptionComponent; @@ -81,6 +85,17 @@ describe('SearchFacetOptionComponent', () => { let router; const page = observableOf(0); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + getPageParam: 'p.page-id', + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], @@ -88,8 +103,10 @@ describe('SearchFacetOptionComponent', () => { providers: [ { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, { provide: Router, useValue: new RouterStub() }, + { provide: PaginationService, useValue: paginationService }, { provide: SearchConfigurationService, useValue: { + paginationID: 'page-id', searchOptions: observableOf({}) } }, @@ -131,7 +148,7 @@ describe('SearchFacetOptionComponent', () => { (comp as any).updateAddParams(selectedValues); expect(comp.addQueryParams).toEqual({ [mockFilterConfig.paramName]: [`${value1},${operator}`, value.value + ',equals'], - page: 1 + ['p.page-id']: 1 }); }); }); @@ -146,7 +163,7 @@ describe('SearchFacetOptionComponent', () => { (comp as any).updateAddParams(selectedValues); expect(comp.addQueryParams).toEqual({ [mockAuthorityFilterConfig.paramName]: [value1 + ',equals', `${value2},${operator}`], - page: 1 + ['p.page-id']: 1 }); }); }); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts index f5df1f038a..6329655eca 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts @@ -19,6 +19,10 @@ import { RANGE_FILTER_MAX_SUFFIX, RANGE_FILTER_MIN_SUFFIX } from '../../search-range-filter/search-range-filter.component'; +import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../../../core/data/request.models'; +import { PaginationService } from '../../../../../../core/pagination/pagination.service'; describe('SearchFacetRangeOptionComponent', () => { let comp: SearchFacetRangeOptionComponent; @@ -54,6 +58,18 @@ describe('SearchFacetRangeOptionComponent', () => { let router; const page = observableOf(0); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {}, + getPageParam: 'p.page-id', + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], @@ -61,9 +77,11 @@ describe('SearchFacetRangeOptionComponent', () => { providers: [ { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, { provide: Router, useValue: new RouterStub() }, + { provide: PaginationService, useValue: paginationService }, { provide: SearchConfigurationService, useValue: { - searchOptions: observableOf({}) + searchOptions: observableOf({}), + paginationId: 'page-id' } }, { @@ -116,7 +134,7 @@ describe('SearchFacetRangeOptionComponent', () => { expect(comp.changeQueryParams).toEqual({ [mockFilterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: ['50'], [mockFilterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: ['60'], - page: 1 + ['p.page-id']: 1 }); }); }); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts index 69945d86f2..60c4fd5721 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts @@ -14,6 +14,10 @@ import { FacetValue } from '../../../../facet-value.model'; import { FilterType } from '../../../../filter-type.model'; import { SearchFilterConfig } from '../../../../search-filter-config.model'; import { SearchFacetSelectedOptionComponent } from './search-facet-selected-option.component'; +import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../../../core/data/request.models'; +import { PaginationService } from '../../../../../../core/pagination/pagination.service'; describe('SearchFacetSelectedOptionComponent', () => { let comp: SearchFacetSelectedOptionComponent; @@ -106,6 +110,18 @@ describe('SearchFacetSelectedOptionComponent', () => { let router; const page = observableOf(0); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {}, + getPageParam: 'p.page-id' + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], @@ -113,6 +129,7 @@ describe('SearchFacetSelectedOptionComponent', () => { providers: [ { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, { provide: Router, useValue: new RouterStub() }, + { provide: PaginationService, useValue: paginationService }, { provide: SearchConfigurationService, useValue: { searchOptions: observableOf({}) @@ -156,7 +173,7 @@ describe('SearchFacetSelectedOptionComponent', () => { (comp as any).updateRemoveParams(selectedValues); expect(comp.removeQueryParams).toEqual({ [mockFilterConfig.paramName]: [value1], - page: 1 + ['p.page-id']: 1 }); }); }); @@ -172,7 +189,7 @@ describe('SearchFacetSelectedOptionComponent', () => { (comp as any).updateRemoveParams(selectedAuthorityValues); expect(comp.removeQueryParams).toEqual({ [mockAuthorityFilterConfig.paramName]: [`${value1},${operator}`], - page: 1 + ['p.page-id']: 1 }); }); }); diff --git a/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts b/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts index 00868a86a2..fe9959aa3a 100644 --- a/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts +++ b/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts @@ -11,6 +11,11 @@ import { SEARCH_CONFIG_SERVICE } from '../../../../+my-dspace-page/my-dspace-pag import { SearchServiceStub } from '../../../testing/search-service.stub'; import { SearchConfigurationServiceStub } from '../../../testing/search-configuration-service.stub'; import { SearchService } from '../../../../core/shared/search/search.service'; +import { PaginationComponentOptions } from '../../../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../../core/data/request.models'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service'; describe('SearchLabelComponent', () => { let comp: SearchLabelComponent; @@ -33,6 +38,18 @@ describe('SearchLabelComponent', () => { filter2 ]; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + updateRouteWithUrl: {}, + getPageParam: 'p.test-id' + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], @@ -40,6 +57,8 @@ describe('SearchLabelComponent', () => { providers: [ { provide: SearchService, useValue: new SearchServiceStub(searchLink) }, { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, + { provide: SearchConfigurationService, useValue: new SearchConfigurationServiceStub() }, + { provide: PaginationService, useValue: paginationService }, { provide: Router, useValue: {} } // { provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => observableOf({})} } ], diff --git a/src/app/shared/search/search-settings/search-settings.component.spec.ts b/src/app/shared/search/search-settings/search-settings.component.spec.ts index cd4a872815..5ae1f7eaf2 100644 --- a/src/app/shared/search/search-settings/search-settings.component.spec.ts +++ b/src/app/shared/search/search-settings/search-settings.component.spec.ts @@ -16,6 +16,7 @@ import { take } from 'rxjs/operators'; import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.component'; import { SidebarService } from '../../sidebar/sidebar.service'; import { SidebarServiceStub } from '../../testing/sidebar-service.stub'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('SearchSettingsComponent', () => { @@ -32,6 +33,8 @@ describe('SearchSettingsComponent', () => { let scopeParam; let paginatedSearchOptions; + let paginationService; + let activatedRouteStub; beforeEach(waitForAsync(() => { @@ -62,6 +65,12 @@ describe('SearchSettingsComponent', () => { }), }; + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + resetPage: {}, + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], declarations: [SearchSettingsComponent, EnumKeysPipe, VarDirective], @@ -77,6 +86,10 @@ describe('SearchSettingsComponent', () => { provide: SearchFilterService, useValue: {}, }, + { + provide: PaginationService, + useValue: paginationService, + }, { provide: SEARCH_CONFIG_SERVICE, useValue: { diff --git a/src/app/shared/starts-with/date/starts-with-date.component.spec.ts b/src/app/shared/starts-with/date/starts-with-date.component.spec.ts index 33edcfa5fd..4b4556f511 100644 --- a/src/app/shared/starts-with/date/starts-with-date.component.spec.ts +++ b/src/app/shared/starts-with/date/starts-with-date.component.spec.ts @@ -11,12 +11,17 @@ import { StartsWithDateComponent } from './starts-with-date.component'; import { ActivatedRouteStub } from '../../testing/active-router.stub'; import { EnumKeysPipe } from '../../utils/enum-keys-pipe'; import { RouterStub } from '../../testing/router.stub'; +import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('StartsWithDateComponent', () => { let comp: StartsWithDateComponent; let fixture: ComponentFixture; let route: ActivatedRoute; let router: Router; + let paginationService; const options = [2019, 2018, 2017, 2016, 2015]; @@ -25,13 +30,25 @@ describe('StartsWithDateComponent', () => { queryParams: observableOf({}) }); + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + + paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], declarations: [StartsWithDateComponent, EnumKeysPipe], providers: [ { provide: 'startsWithOptions', useValue: options }, + { provide: 'paginationId', useValue: 'page-id' }, { provide: ActivatedRoute, useValue: activatedRouteStub }, + { provide: PaginationService, useValue: paginationService }, { provide: Router, useValue: new RouterStub() } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/shared/starts-with/text/starts-with-text.component.spec.ts b/src/app/shared/starts-with/text/starts-with-text.component.spec.ts index 780c221294..1295f0a33a 100644 --- a/src/app/shared/starts-with/text/starts-with-text.component.spec.ts +++ b/src/app/shared/starts-with/text/starts-with-text.component.spec.ts @@ -8,6 +8,11 @@ import { EnumKeysPipe } from '../../utils/enum-keys-pipe'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { StartsWithTextComponent } from './starts-with-text.component'; +import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../../core/data/request.models'; +import { of as observableOf } from 'rxjs'; +import { PaginationService } from '../../../core/pagination/pagination.service'; describe('StartsWithTextComponent', () => { let comp: StartsWithTextComponent; @@ -17,12 +22,24 @@ describe('StartsWithTextComponent', () => { const options = ['0-9', 'A', 'B', 'C']; + const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); + const sort = new SortOptions('score', SortDirection.DESC); + const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); + const paginationService = jasmine.createSpyObj('PaginationService', { + getCurrentPagination: observableOf(pagination), + getCurrentSort: observableOf(sort), + getFindListOptions: observableOf(findlistOptions), + resetPage: {}, + }); + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], declarations: [StartsWithTextComponent, EnumKeysPipe], providers: [ - { provide: 'startsWithOptions', useValue: options } + { provide: 'startsWithOptions', useValue: options }, + { provide: 'paginationId', useValue: 'page-id' }, + { provide: PaginationService, useValue: paginationService } ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); diff --git a/src/app/shared/testing/search-configuration-service.stub.ts b/src/app/shared/testing/search-configuration-service.stub.ts index 4c9402afb1..4b8f1d6f12 100644 --- a/src/app/shared/testing/search-configuration-service.stub.ts +++ b/src/app/shared/testing/search-configuration-service.stub.ts @@ -2,6 +2,8 @@ import { BehaviorSubject, of as observableOf } from 'rxjs'; export class SearchConfigurationServiceStub { + public paginationID = 'test-id'; + private searchOptions: BehaviorSubject = new BehaviorSubject({}); private paginatedSearchOptions: BehaviorSubject = new BehaviorSubject({}); diff --git a/src/app/submission/import-external/submission-import-external.component.spec.ts b/src/app/submission/import-external/submission-import-external.component.spec.ts index 3a69a3727e..c0b85b696b 100644 --- a/src/app/submission/import-external/submission-import-external.component.spec.ts +++ b/src/app/submission/import-external/submission-import-external.component.spec.ts @@ -115,15 +115,22 @@ describe('SubmissionImportExternalComponent test suite', () => { spyOn(compAsAny.routeService, 'getQueryParameterValue').and.returnValues(observableOf('source'), observableOf('dummy')); fixture.detectChanges(); - expect(compAsAny.retrieveExternalSources).toHaveBeenCalledWith('source', 'dummy'); + expect(compAsAny.retrieveExternalSources).toHaveBeenCalled(); }); it('Should call \'getExternalSourceEntries\' properly', () => { - comp.routeData = { sourceId: '', query: '' }; - scheduler.schedule(() => compAsAny.retrieveExternalSources('orcidV2', 'test')); - scheduler.flush(); + spyOn(routeServiceStub, 'getQueryParameterValue').and.callFake((param) => { + if (param === 'source') { + return observableOf('orcidV2'); + } else if (param === 'query') { + return observableOf('test'); + } + return observableOf({}); + }); + + fixture.detectChanges(); + - expect(comp.routeData).toEqual({ sourceId: 'orcidV2', query: 'test' }); expect(comp.isLoading$.value).toBe(false); expect(compAsAny.externalService.getExternalSourceEntries).toHaveBeenCalled(); }); diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index d8801880dc..2c407a1edb 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -20,7 +20,6 @@ import { fadeIn } from '../../shared/animations/fade'; import { PageInfo } from '../../core/shared/page-info.model'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { getFinishedRemoteData } from '../../core/shared/operators'; -import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model'; /** * This component allows to submit a new workspaceitem importing the data from an external source. @@ -46,7 +45,7 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { */ public isLoading$: BehaviorSubject = new BehaviorSubject(false); - public reload$: BehaviorSubject<{query: string, source: string}>; + public reload$: BehaviorSubject<{query: string, source: string}> = new BehaviorSubject<{query: string; source: string}>({query: '', source: ''}); /** * Configuration to use for the import buttons */ @@ -122,9 +121,10 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { ]).pipe( take(1) ).subscribe(([source, query]: [string, string]) => { - this.reload$ = new BehaviorSubject<{query: string; source: string}>({query: query, source: source}); - this.retrieveExternalSources(source, query); + this.reload$.next({query: query, source: source}); + this.retrieveExternalSources(); })); + this.reload$.subscribe((v) => console.log('this.reload$', v)); } /** @@ -167,8 +167,9 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { * @param source The source tupe * @param query The query string to search */ - private retrieveExternalSources(sourcesss: string, querysss: string): void { + private retrieveExternalSources(): void { this.reload$.subscribe((sourceQueryObject: {source: string, query: string}) => { + console.log('ping?', sourceQueryObject); const source = sourceQueryObject.source; const query = sourceQueryObject.query; if (isNotEmpty(source) && isNotEmpty(query)) { @@ -177,6 +178,7 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { this.isLoading$.next(true); this.subs.push( this.searchConfigService.paginatedSearchOptions.pipe( + tap((v) => console.log('searchpag?', v)), filter((searchOptions) => searchOptions.query === query), mergeMap((searchOptions) => this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions).pipe( getFinishedRemoteData(), From da43a56a0b8388943a8580247a35fc10709c0ea6 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Fri, 5 Mar 2021 15:23:23 +0100 Subject: [PATCH 04/14] fix error when state is undefined --- src/app/core/services/route.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core/services/route.service.ts b/src/app/core/services/route.service.ts index 0b00420797..8aee755e3b 100644 --- a/src/app/core/services/route.service.ts +++ b/src/app/core/services/route.service.ts @@ -18,7 +18,7 @@ import { AddUrlToHistoryAction } from '../history/history.actions'; */ export const routeParametersSelector = createSelector( coreSelector, - (state: CoreState) => state.route.params + (state: CoreState) => hasValue(state) && hasValue(state.route) ? state.route.params : undefined ); /** @@ -26,7 +26,7 @@ export const routeParametersSelector = createSelector( */ export const queryParametersSelector = createSelector( coreSelector, - (state: CoreState) => state.route.queryParams + (state: CoreState) => hasValue(state) && hasValue(state.route) ? state.route.queryParams : undefined ); /** From e73f4ca57a69c1b5e356b7cacba09790dee4b446 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Mon, 8 Mar 2021 16:47:16 +0100 Subject: [PATCH 05/14] 76654: Remove console.logs, fix some issues --- ...-drag-and-drop-bitstream-list.component.ts | 5 +- src/app/core/pagination/pagination.service.ts | 186 ++++++++++-------- ...nated-drag-and-drop-list.component.spec.ts | 2 +- ...-paginated-drag-and-drop-list.component.ts | 10 +- .../pagination/pagination.component.spec.ts | 2 - .../shared/pagination/pagination.component.ts | 5 +- .../submission-import-external.component.ts | 3 - 7 files changed, 117 insertions(+), 96 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts index 0941a4dfd6..f3f00abf92 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.ts @@ -11,6 +11,7 @@ import { followLink } from '../../../../../shared/utils/follow-link-config.model import { ObjectValuesPipe } from '../../../../../shared/utils/object-values-pipe'; import { RequestService } from '../../../../../core/data/request.service'; import { PaginationService } from '../../../../../core/pagination/pagination.service'; +import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; @Component({ selector: 'ds-paginated-drag-and-drop-bitstream-list', @@ -52,8 +53,8 @@ export class PaginatedDragAndDropBitstreamListComponent extends AbstractPaginate */ initializeObjectsRD(): void { this.objectsRD$ = this.currentPage$.pipe( - switchMap((page: number) => { - const paginatedOptions = new PaginatedSearchOptions({pagination: Object.assign({}, this.options, { currentPage: page })}); + switchMap((page: PaginationComponentOptions) => { + const paginatedOptions = new PaginatedSearchOptions({pagination: Object.assign({}, page)}); return this.bundleService.getBitstreamsEndpoint(this.bundle.id, paginatedOptions).pipe( switchMap((href) => this.requestService.hasByHref$(href)), switchMap(() => this.bundleService.getBitstreams( diff --git a/src/app/core/pagination/pagination.service.ts b/src/app/core/pagination/pagination.service.ts index 29e57214c1..45a1ffee96 100644 --- a/src/app/core/pagination/pagination.service.ts +++ b/src/app/core/pagination/pagination.service.ts @@ -14,23 +14,31 @@ import { isNumeric } from 'rxjs/internal-compatibility'; @Injectable({ providedIn: 'root', }) +/** + * Service to manage the pagination of different components + */ export class PaginationService { private defaultSortOptions = new SortOptions('id', SortDirection.ASC); + private clearParams = {}; + constructor(protected routeService: RouteService, protected router: Router ) { } /** - * @returns {Observable} Emits the current pagination settings + * Method to retrieve the current pagination settings for an ID based on the router params and default options + * @param paginationId - The id to check the pagination for + * @param defaultPagination - The default pagination values to be used when no route info is present + * @returns {Observable} Retrieves the current pagination settings based on the router params */ getCurrentPagination(paginationId: string, defaultPagination: PaginationComponentOptions): Observable { const page$ = this.routeService.getQueryParameterValue(`p.${paginationId}`); const size$ = this.routeService.getQueryParameterValue(`rpp.${paginationId}`); - return observableCombineLatest([page$, size$]).pipe(map(([page, size]) => { - console.log(page, size); + return observableCombineLatest([page$, size$]).pipe( + map(([page, size]) => { return Object.assign(new PaginationComponentOptions(), defaultPagination, { currentPage: this.convertToNumeric(page, defaultPagination.currentPage), pageSize: this.getBestMatchPageSize(size, defaultPagination) @@ -40,7 +48,11 @@ export class PaginationService { } /** - * @returns {Observable} Emits the current sorting settings + * Method to retrieve the current sort options for an ID based on the router params and default options + * @param paginationId - The id to check the sort options for + * @param defaultSort - The default sort options to be used when no route info is present + * @param ignoreDefault - Indicate whether the default should be ignored + * @returns {Observable} Retrieves the current sort options based on the router params */ getCurrentSort(paginationId: string, defaultSort: SortOptions, ignoreDefault?: boolean): Observable { if (!ignoreDefault && (isEmpty(defaultSort) || !hasValue(defaultSort))) { @@ -56,6 +68,13 @@ export class PaginationService { ); } + /** + * Method to retrieve the current find list options for an ID based on the router params and default options + * @param paginationId - The id to check the find list options for + * @param defaultFindList - The default find list options to be used when no route info is present + * @param ignoreDefault - Indicate whether the default should be ignored + * @returns {Observable} Retrieves the current find list options based on the router params + */ getFindListOptions(paginationId: string, defaultFindList: FindListOptions, ignoreDefault?: boolean): Observable { const paginationComponentOptions = new PaginationComponentOptions(); paginationComponentOptions.currentPage = defaultFindList.currentPage; @@ -74,10 +93,94 @@ export class PaginationService { })); } + /** + * Reset the current page for the provided pagination ID to 1. + * @param paginationId - The pagination id for which to reset the page + */ resetPage(paginationId: string) { this.updateRoute(paginationId, {page: 1}); } + + /** + * Update the route with the provided information + * @param paginationId - The pagination ID for which to update the route with info + * @param params - The page related params to update in the route + * @param extraParams - Addition params unrelated to the pagination that need to be added to the route + * @param retainScrollPosition - Scroll to the pagination component after updating the route instead of the top of the page + */ + updateRoute(paginationId: string, params: { + page?: number + pageSize?: number + sortField?: string + sortDirection?: SortDirection + }, extraParams?, retainScrollPosition?: boolean) { + + this.updateRouteWithUrl(paginationId, [], params, extraParams, retainScrollPosition); + } + + /** + * Update the route with the provided information + * @param paginationId - The pagination ID for which to update the route with info + * @param url - The url to navigate to + * @param params - The page related params to update in the route + * @param extraParams - Addition params unrelated to the pagination that need to be added to the route + * @param retainScrollPosition - Scroll to the pagination component after updating the route instead of the top of the page + */ + updateRouteWithUrl(paginationId: string, url: string[], params: { + page?: number + pageSize?: number + sortField?: string + sortDirection?: SortDirection + }, extraParams?, retainScrollPosition?: boolean) { + this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { + const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); + const parametersWithIdName = this.getParametersWithIdName(paginationId, params); + if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams) || isNotEmpty(this.clearParams)) { + const queryParams = Object.assign({}, this.clearParams, currentParametersWithIdName, + parametersWithIdName, extraParams); + console.log(queryParams, this.clearParams); + if (retainScrollPosition) { + this.router.navigate(url, { + queryParams: queryParams, + queryParamsHandling: 'merge', + fragment: `p-${paginationId}` + }); + } else { + this.router.navigate(url, { + queryParams: queryParams, + queryParamsHandling: 'merge' + }); + } + this.clearParams = {}; + console.log('postcear', this.clearParams); + } + }); + } + + /** + * Add the params to be cleared to the clearParams variable. + * When the updateRoute or updateRouteWithUrl these params will be removed from the route pagination + * @param paginationId - The ID for which to clear the params + */ + clearPagination(paginationId: string) { + const params = {}; + params[`p.${paginationId}`] = null; + params[`rpp.${paginationId}`] = null; + params[`sf.${paginationId}`] = null; + params[`sd.${paginationId}`] = null; + + Object.assign(this.clearParams, params); + } + + /** + * Retrieve the page parameter for the provided id + * @param paginationId - The ID for which to retrieve the page param + */ + getPageParam(paginationId: string) { + return `p.${paginationId}`; + } + private getCurrentRouting(paginationId: string) { return this.getFindListOptions(paginationId, {}, true).pipe( take(1), @@ -92,81 +195,6 @@ export class PaginationService { ); } - updateRoute(paginationId: string, params: { - page?: number - pageSize?: number - sortField?: string - sortDirection?: SortDirection - }, extraParams?, retainScrollPosition?: boolean) { - this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { - console.log('currentFindListOptions',currentFindListOptions ); - const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); - const parametersWithIdName = this.getParametersWithIdName(paginationId, params); - if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { - const queryParams = Object.assign({}, currentParametersWithIdName, - parametersWithIdName, extraParams); - if (retainScrollPosition) { - this.router.navigate([], { - queryParams: queryParams, - queryParamsHandling: 'merge', - fragment: `p-${paginationId}` - }); - } else { - this.router.navigate([], { - queryParams: queryParams, - queryParamsHandling: 'merge' - }); - } - } - }); - } - - updateRouteWithUrl(paginationId: string, url: string[], params: { - page?: number - pageSize?: number - sortField?: string - sortDirection?: SortDirection - }, extraParams?, retainScrollPosition?: boolean) { - console.log(retainScrollPosition); - this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { - const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); - const parametersWithIdName = this.getParametersWithIdName(paginationId, params); - if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { - const queryParams = Object.assign({}, currentParametersWithIdName, - parametersWithIdName, extraParams); - if (retainScrollPosition) { - this.router.navigate(url, { - queryParams: queryParams, - queryParamsHandling: 'merge', - fragment: `p-${paginationId}` - }); - } else { - this.router.navigate(url, { - queryParams: queryParams, - queryParamsHandling: 'merge' - }); - } - } - }); - } - - clearPagination(paginationId: string) { - const params = {}; - params[`p.${paginationId}`] = null; - params[`rpp.${paginationId}`] = null; - params[`sf.${paginationId}`] = null; - params[`sd.${paginationId}`] = null; - - this.router.navigate([], { - queryParams: params, - queryParamsHandling: 'merge' - }); - } - - getPageParam(paginationId: string) { - return `p.${paginationId}`; - } - private getParametersWithIdName(paginationId: string, params: { page?: number pageSize?: number diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts index 4c29e2af9d..53a4619071 100644 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts +++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts @@ -118,7 +118,7 @@ describe('AbstractPaginatedDragAndDropListComponent', () => { it('should send out a dropObject event with the expected processed paginated indexes', () => { expect(component.dropObject.emit).toHaveBeenCalledWith(Object.assign({ - fromIndex: ((component.currentPage$.value - 1) * component.pageSize) + event.previousIndex, + fromIndex: ((component.currentPage$.value.currentPage - 1) * component.pageSize) + event.previousIndex, toIndex: ((hoverPage - 1) * component.pageSize), finish: jasmine.anything() })); diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts index b861104197..f9b9ff8e90 100644 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts +++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts @@ -82,7 +82,7 @@ export abstract class AbstractPaginatedDragAndDropListComponent(1); + currentPage$ = new BehaviorSubject(this.options); /** * Whether or not we should display a loading animation @@ -144,7 +144,7 @@ export abstract class AbstractPaginatedDragAndDropListComponent { - this.currentPage$.next(currentPagination.currentPage); + this.currentPage$.next(currentPagination); }); } @@ -187,8 +187,8 @@ export abstract class AbstractPaginatedDragAndDropListComponent) { const dragIndex = event.previousIndex; let dropIndex = event.currentIndex; - const dragPage = this.currentPage$.value - 1; - let dropPage = this.currentPage$.value - 1; + const dragPage = this.currentPage$.value.currentPage - 1; + let dropPage = this.currentPage$.value.currentPage - 1; // Check if the user is hovering over any of the pagination's pages at the time of dropping the object const droppedOnElement = this.elRef.nativeElement.querySelector('.page-item:hover'); diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts index bad54d6e83..66308df67f 100644 --- a/src/app/shared/pagination/pagination.component.spec.ts +++ b/src/app/shared/pagination/pagination.component.spec.ts @@ -38,8 +38,6 @@ import { BehaviorSubject, of as observableOf } from 'rxjs'; function expectPages(fixture: ComponentFixture, pagesDef: string[]): void { const de = fixture.debugElement.query(By.css('.pagination')); const pages = de.nativeElement.querySelectorAll('li'); - console.log('pages', pages.length, pagesDef.length); - console.log(pages); expect(pages.length).toEqual(pagesDef.length); diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index 4a181d7090..520dcda651 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -176,7 +176,7 @@ export class PaginationComponent implements OnDestroy, OnInit { })); this.checkConfig(this.paginationOptions); this.initializeConfig(); - } + } /** * Method provided by Angular. Invoked when the instance is destroyed. @@ -195,14 +195,11 @@ export class PaginationComponent implements OnDestroy, OnInit { this.id = this.paginationOptions.id || null; this.pageSizeOptions = this.paginationOptions.pageSizeOptions; this.currentPage$ = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe( - tap((v) => console.log('currentPage', v)), map((currentPagination) => currentPagination.currentPage) ); this.pageSize$ = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe( map((currentPagination) => currentPagination.pageSize) ); - this.pageSize$.subscribe((v) => console.log('this.pageSize$', v)); - this.currentPage$.subscribe((v) => console.log('this.currentPage$', v)); let sortOptions; if (this.sortOptions) { diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index 2c407a1edb..9dabf4ceb7 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -124,7 +124,6 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { this.reload$.next({query: query, source: source}); this.retrieveExternalSources(); })); - this.reload$.subscribe((v) => console.log('this.reload$', v)); } /** @@ -169,7 +168,6 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { */ private retrieveExternalSources(): void { this.reload$.subscribe((sourceQueryObject: {source: string, query: string}) => { - console.log('ping?', sourceQueryObject); const source = sourceQueryObject.source; const query = sourceQueryObject.query; if (isNotEmpty(source) && isNotEmpty(query)) { @@ -178,7 +176,6 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { this.isLoading$.next(true); this.subs.push( this.searchConfigService.paginatedSearchOptions.pipe( - tap((v) => console.log('searchpag?', v)), filter((searchOptions) => searchOptions.query === query), mergeMap((searchOptions) => this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions).pipe( getFinishedRemoteData(), From b4e40c820f0de94691888bb73d41efc8e4751700 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 11 Mar 2021 12:47:44 +0100 Subject: [PATCH 06/14] Fix issue with clear pagination test --- .../pagination/pagination.service.spec.ts | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/app/core/pagination/pagination.service.spec.ts b/src/app/core/pagination/pagination.service.spec.ts index 990dcd9b90..f689f4f0f0 100644 --- a/src/app/core/pagination/pagination.service.spec.ts +++ b/src/app/core/pagination/pagination.service.spec.ts @@ -128,16 +128,25 @@ describe('PaginationService', () => { }); describe('clearPagination', () => { - it('should clear the pagination info from the route for the current id', () => { + it('should clear the pagination next time the updateRoute/updateRouteWithUrl method is called', () => { service.clearPagination('test'); - const params = {}; - params[`p.test`] = null; - params[`rpp.test`] = null; - params[`sf.test`] = null; - params[`sd.test`] = null; + const resetParams = {}; + resetParams[`p.test`] = null; + resetParams[`rpp.test`] = null; + resetParams[`sf.test`] = null; + resetParams[`sd.test`] = null; - expect(router.navigate).toHaveBeenCalledWith([], {queryParams: params, queryParamsHandling: 'merge'}); + + const navigateParams = {}; + navigateParams[`p.another-id`] = `5`; + navigateParams[`rpp.another-id`] = `10`; + navigateParams[`sf.another-id`] = `score`; + navigateParams[`sd.another-id`] = `ASC`; + + service.updateRoute('another-id', {}); + + expect(router.navigate).toHaveBeenCalledWith([], {queryParams: Object.assign({}, resetParams, navigateParams), queryParamsHandling: 'merge'}); }); }); describe('getPageParam', () => { From 11728695498cbe6faf0a59d56379c63d97d2266e Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 11 Mar 2021 15:45:04 +0100 Subject: [PATCH 07/14] Fix LGTM issues --- .../epeople-registry/eperson-form/eperson-form.component.ts | 2 +- .../group-form/members-list/members-list.component.ts | 1 - .../+browse-by-title-page/browse-by-title-page.component.ts | 2 +- src/app/+collection-page/collection-page.component.ts | 2 +- .../file-section/full-file-section.component.ts | 2 +- src/app/core/shared/search/search-configuration.service.ts | 1 - src/app/core/shared/search/search.service.ts | 1 - src/app/shared/item/item-versions/item-versions.component.ts | 2 +- src/app/shared/pagination/pagination.component.ts | 1 - .../search-facet-option/search-facet-option.component.ts | 1 - .../search/search-labels/search-label/search-label.component.ts | 2 +- .../shared/search/search-settings/search-settings.component.ts | 2 +- .../import-external/submission-import-external.component.ts | 2 +- 13 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts index 48f171f966..f2b18ab638 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -8,7 +8,7 @@ import { } from '@ng-dynamic-forms/core'; import { TranslateService } from '@ngx-translate/core'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; -import { switchMap, take, tap } from 'rxjs/operators'; +import { switchMap, take } from 'rxjs/operators'; import { PaginatedList } from '../../../../core/data/paginated-list.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { EPersonDataService } from '../../../../core/eperson/eperson-data.service'; diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts index 944b2e5dfb..837649857a 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.ts @@ -23,7 +23,6 @@ import { import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; import { PaginationService } from '../../../../../core/pagination/pagination.service'; -import { hasValue } from '../../../../../shared/empty.util'; import {EpersonDtoModel} from '../../../../../core/eperson/models/eperson-dto.model'; /** diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts index d62c58d644..de9fb2daf0 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts @@ -1,7 +1,7 @@ import { combineLatest as observableCombineLatest } from 'rxjs'; import { Component } from '@angular/core'; import { ActivatedRoute, Params, Router } from '@angular/router'; -import { hasValue, isNotEmpty } from '../../shared/empty.util'; +import { hasValue } from '../../shared/empty.util'; import { BrowseByMetadataPageComponent, browseParamsToOptions diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index 74d8c76c5c..855a7c3301 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subject } from 'rxjs'; -import { filter, map, mergeMap, startWith, switchMap, take, tap } from 'rxjs/operators'; +import { filter, map, mergeMap, startWith, switchMap, take } from 'rxjs/operators'; import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model'; import { SearchService } from '../core/shared/search/search.service'; import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model'; diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts index 439bb6502f..214484120e 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit } from '@angular/core'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; import { Bitstream } from '../../../../core/shared/bitstream.model'; diff --git a/src/app/core/shared/search/search-configuration.service.ts b/src/app/core/shared/search/search-configuration.service.ts index 6639b53cb9..798a0de287 100644 --- a/src/app/core/shared/search/search-configuration.service.ts +++ b/src/app/core/shared/search/search-configuration.service.ts @@ -15,7 +15,6 @@ import { getFirstSucceededRemoteData } from '../operators'; import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../../shared/empty.util'; import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; import { PaginationService } from '../../pagination/pagination.service'; -import { tap } from 'rxjs/internal/operators/tap'; /** * Service that performs all actions that have to do with the current search configuration diff --git a/src/app/core/shared/search/search.service.ts b/src/app/core/shared/search/search.service.ts index 4dfd1964c3..054bde4c08 100644 --- a/src/app/core/shared/search/search.service.ts +++ b/src/app/core/shared/search/search.service.ts @@ -40,7 +40,6 @@ import { FacetValues } from '../../../shared/search/facet-values.model'; import { PaginationService } from '../../pagination/pagination.service'; import { SearchConfigurationService } from './search-configuration.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { tap } from 'rxjs/internal/operators/tap'; /** * Service that performs all general actions that have to do with the search page diff --git a/src/app/shared/item/item-versions/item-versions.component.ts b/src/app/shared/item/item-versions/item-versions.component.ts index 3e515b9452..645eed5b90 100644 --- a/src/app/shared/item/item-versions/item-versions.component.ts +++ b/src/app/shared/item/item-versions/item-versions.component.ts @@ -2,7 +2,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { Item } from '../../../core/shared/item.model'; import { Version } from '../../../core/shared/version.model'; import { RemoteData } from '../../../core/data/remote-data'; -import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { VersionHistory } from '../../../core/shared/version-history.model'; import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../../core/shared/operators'; import { map, startWith, switchMap } from 'rxjs/operators'; diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index 520dcda651..1b9adf8922 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -20,7 +20,6 @@ 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 { tap } from 'rxjs/internal/operators/tap'; /** * The default pagination controls component. diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts index 45c90d8a60..11056a232c 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.ts @@ -11,7 +11,6 @@ import { hasValue } from '../../../../../empty.util'; import { currentPath } from '../../../../../utils/route.utils'; import { getFacetValueForType } from '../../../../search.utils'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; -import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model'; @Component({ selector: 'ds-search-facet-option', diff --git a/src/app/shared/search/search-labels/search-label/search-label.component.ts b/src/app/shared/search/search-labels/search-label/search-label.component.ts index b66308a5bd..74526ad2ad 100644 --- a/src/app/shared/search/search-labels/search-label/search-label.component.ts +++ b/src/app/shared/search/search-labels/search-label/search-label.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { Params, Router } from '@angular/router'; -import { map, take } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { hasValue, isNotEmpty } from '../../../empty.util'; import { SearchService } from '../../../../core/shared/search/search.service'; import { currentPath } from '../../../utils/route.utils'; diff --git a/src/app/shared/search/search-settings/search-settings.component.ts b/src/app/shared/search/search-settings/search-settings.component.ts index 6f12c161ea..2241fc6c6a 100644 --- a/src/app/shared/search/search-settings/search-settings.component.ts +++ b/src/app/shared/search/search-settings/search-settings.component.ts @@ -1,7 +1,7 @@ import { Component, Inject, OnInit } from '@angular/core'; import { SearchService } from '../../../core/shared/search/search.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { PaginatedSearchOptions } from '../paginated-search-options.model'; import { Observable } from 'rxjs'; import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service'; diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index 9dabf4ceb7..faaf83389b 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { BehaviorSubject, combineLatest, Subscription } from 'rxjs'; -import { filter, mergeMap, take, tap } from 'rxjs/operators'; +import { filter, mergeMap, take } from 'rxjs/operators'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { ExternalSourceService } from '../../core/data/external-source.service'; From 659117dfbd3818f8c2093731ec94f1242ba93d58 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 18 Mar 2021 14:55:39 +0100 Subject: [PATCH 08/14] Fix import itssue --- src/app/shared/item/item-versions/item-versions.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/item/item-versions/item-versions.component.ts b/src/app/shared/item/item-versions/item-versions.component.ts index 0d90f9ffee..752cd55b5b 100644 --- a/src/app/shared/item/item-versions/item-versions.component.ts +++ b/src/app/shared/item/item-versions/item-versions.component.ts @@ -2,7 +2,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { Item } from '../../../core/shared/item.model'; import { Version } from '../../../core/shared/version.model'; import { RemoteData } from '../../../core/data/remote-data'; -import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; +import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { VersionHistory } from '../../../core/shared/version-history.model'; import { getAllSucceededRemoteData, From afe345ebacabebc8f1f64955c821970175ac24bd Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Mon, 29 Mar 2021 15:31:27 +0200 Subject: [PATCH 09/14] 76654: Implement feedback --- .../epeople-registry.component.spec.ts | 11 +--- .../epeople-registry.component.ts | 65 ++++++++----------- .../eperson-form.component.spec.ts | 14 +--- .../members-list.component.spec.ts | 12 +--- .../subgroups-list.component.spec.ts | 13 +--- .../groups-registry.component.spec.ts | 12 +--- .../bitstream-formats.component.spec.ts | 27 ++------ .../bitstream-formats.component.ts | 5 -- .../metadata-registry.component.spec.ts | 12 +--- .../metadata-schema.component.spec.ts | 11 +--- .../browse-by-date-page.component.spec.ts | 11 +--- .../browse-by-date-page.component.ts | 11 ++-- .../browse-by-metadata-page.component.html | 4 +- .../browse-by-metadata-page.component.spec.ts | 12 +--- .../browse-by-metadata-page.component.ts | 21 ++++-- .../browse-by-title-page.component.spec.ts | 11 +--- .../browse-by-title-page.component.ts | 10 +-- ...page-sub-collection-list.component.spec.ts | 12 +--- ...-page-sub-community-list.component.spec.ts | 11 +--- ...top-level-community-list.component.spec.ts | 10 +-- ...-and-drop-bitstream-list.component.spec.ts | 13 +--- .../full-file-section.component.spec.ts | 11 +--- .../my-dspace-configuration.service.spec.ts | 11 ++-- src/app/core/pagination/pagination.service.ts | 6 ++ .../search-configuration.service.spec.ts | 9 +-- .../core/shared/search/search.service.spec.ts | 12 +--- .../process-overview.component.spec.ts | 13 +--- .../search-navbar.component.spec.ts | 12 +--- .../browse-by/browse-by.component.spec.ts | 11 +--- .../item-versions.component.spec.ts | 10 +-- .../collection-select.component.spec.ts | 12 +--- .../item-select/item-select.component.spec.ts | 12 +--- .../page-size-selector.component.spec.ts | 7 +- ...nated-drag-and-drop-list.component.spec.ts | 9 +-- .../pagination/pagination.component.spec.ts | 3 +- .../shared/pagination/pagination.component.ts | 11 ++-- .../eperson-group-list.component.spec.ts | 11 +--- .../search-form/search-form.component.spec.ts | 12 +--- .../search-facet-option.component.spec.ts | 14 +--- ...earch-facet-range-option.component.spec.ts | 14 +--- ...ch-facet-selected-option.component.spec.ts | 14 +--- .../search-label.component.spec.ts | 14 +--- .../search-settings.component.spec.ts | 7 +- .../date/starts-with-date.component.spec.ts | 11 +--- .../text/starts-with-text.component.spec.ts | 11 +--- .../shared/testing/pagination-service.stub.ts | 25 +++++++ .../submission-import-external.component.ts | 44 +++++++------ 47 files changed, 203 insertions(+), 431 deletions(-) create mode 100644 src/app/shared/testing/pagination-service.stub.ts diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts index 4b9dcef00d..57070a9e88 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.spec.ts @@ -28,6 +28,7 @@ import { RequestService } from '../../../core/data/request.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; describe('EPeopleRegistryComponent', () => { let component: EPeopleRegistryComponent; @@ -121,15 +122,7 @@ describe('EPeopleRegistryComponent', () => { builderService = getMockFormBuilderService(); translateService = getMockTranslateService(); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts index c82afc0621..365a62bd4e 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts @@ -70,11 +70,6 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { currentSearchQuery: string; currentSearchScope: string; - /** - * The subscription for the search method - */ - searchSub: Subscription; - /** * FindListOptions */ @@ -150,39 +145,35 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { if (hasValue(this.findListOptionsSub)) { this.findListOptionsSub.unsubscribe(); } - this.findListOptionsSub = this.paginationService.getCurrentPagination(this.config.id, this.config).subscribe((findListOptions) => { - const query: string = data.query; - const scope: string = data.scope; - if (query != null && this.currentSearchQuery !== query) { - this.router.navigate([], { - queryParamsHandling: 'merge' - }); - this.currentSearchQuery = query; - this.paginationService.resetPage(this.config.id); - } - if (scope != null && this.currentSearchScope !== scope) { - this.router.navigate([], { - queryParamsHandling: 'merge' - }); - this.currentSearchScope = scope; - this.paginationService.resetPage(this.config.id); - - } - if (hasValue(this.searchSub)) { - this.searchSub.unsubscribe(); - this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub); - } - this.searchSub = this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { - currentPage: findListOptions.currentPage, - elementsPerPage: findListOptions.pageSize - }).pipe( - getAllSucceededRemoteData(), - ).subscribe((peopleRD) => { - this.ePeople$.next(peopleRD.payload); - this.pageInfoState$.next(peopleRD.payload.pageInfo); + this.findListOptionsSub = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe( + switchMap((findListOptions) => { + const query: string = data.query; + const scope: string = data.scope; + if (query != null && this.currentSearchQuery !== query) { + this.router.navigate([], { + queryParamsHandling: 'merge' + }); + this.currentSearchQuery = query; + this.paginationService.resetPage(this.config.id); } - ); - this.subs.push(this.searchSub); + if (scope != null && this.currentSearchScope !== scope) { + this.router.navigate([], { + queryParamsHandling: 'merge' + }); + this.currentSearchScope = scope; + this.paginationService.resetPage(this.config.id); + + } + return this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { + currentPage: findListOptions.currentPage, + elementsPerPage: findListOptions.pageSize + }); + } + ), + getAllSucceededRemoteData(), + ).subscribe((peopleRD) => { + this.ePeople$.next(peopleRD.payload); + this.pageInfoState$.next(peopleRD.payload.pageInfo); } ); } diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts index e10c1af94c..94aab9809a 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts @@ -29,6 +29,7 @@ import { RequestService } from '../../../../core/data/request.service'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model'; import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; describe('EPersonFormComponent', () => { let component: EPersonFormComponent; @@ -41,7 +42,7 @@ describe('EPersonFormComponent', () => { let authorizationService: AuthorizationDataService; let groupsDataService: GroupDataService; - let paginationService: PaginationService; + let paginationService; @@ -112,16 +113,7 @@ describe('EPersonFormComponent', () => { getGroupRegistryRouterLink: '' }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {} - }); + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts index ad1455ae0f..8a9cc94e13 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.spec.ts @@ -30,6 +30,7 @@ import { PaginationComponentOptions } from '../../../../../shared/pagination/pag import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../../../core/data/request.models'; import { PaginationService } from '../../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub'; describe('MembersListComponent', () => { let component: MembersListComponent; @@ -119,16 +120,7 @@ describe('MembersListComponent', () => { builderService = getMockFormBuilderService(); translateService = getMockTranslateService(); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - clearPagination : {}, - }); + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts index ea65e1b290..087b9ebc39 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts @@ -39,6 +39,7 @@ import { PaginationComponentOptions } from '../../../../../shared/pagination/pag import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../../../core/data/request.models'; import { PaginationService } from '../../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub'; describe('SubgroupsListComponent', () => { let component: SubgroupsListComponent; @@ -106,17 +107,7 @@ describe('SubgroupsListComponent', () => { builderService = getMockFormBuilderService(); translateService = getMockTranslateService(); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {}, - clearPagination: {} - }); + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ diff --git a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts index ff75988607..88f2a53b3c 100644 --- a/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts +++ b/src/app/+admin/admin-access-control/group-registry/groups-registry.component.spec.ts @@ -32,6 +32,7 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../core/data/request.models'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; describe('GroupRegistryComponent', () => { let component: GroupsRegistryComponent; @@ -136,16 +137,7 @@ describe('GroupRegistryComponent', () => { authorizationService = jasmine.createSpyObj('authorizationService', { isAuthorized: observableOf(true) }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {} - }); + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule, TranslateModule.forRoot({ diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts index 5bed34d46b..8cfba1d37b 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts @@ -27,6 +27,7 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../core/data/request.models'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; describe('BitstreamFormatsComponent', () => { let comp: BitstreamFormatsComponent; @@ -104,14 +105,7 @@ describe('BitstreamFormatsComponent', () => { clearBitStreamFormatRequests: observableOf('cleared') }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); - - + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], @@ -236,14 +230,7 @@ describe('BitstreamFormatsComponent', () => { clearBitStreamFormatRequests: observableOf('cleared') }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); - - + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], @@ -292,13 +279,7 @@ describe('BitstreamFormatsComponent', () => { clearBitStreamFormatRequests: observableOf('cleared') }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); - + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule], diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts index d2ae805be7..cbbcbe07a4 100644 --- a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts @@ -28,11 +28,6 @@ export class BitstreamFormatsComponent implements OnInit, OnDestroy { */ bitstreamFormats: Observable>>; - /** - * A BehaviourSubject that keeps track of the pageState used to update the currently displayed bitstreamFormats - */ - // pageState: BehaviorSubject; - /** * The current pagination configuration for the page used by the FindAll method * Currently simply renders all bitstream formats diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts index beb900c17f..0253725cb9 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts @@ -22,12 +22,13 @@ import { PaginationService } from '../../../core/pagination/pagination.service'; import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../core/data/request.models'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; describe('MetadataRegistryComponent', () => { let comp: MetadataRegistryComponent; let fixture: ComponentFixture; let registryService: RegistryService; - let paginationService: PaginationService; + let paginationService; const mockSchemasList = [ { id: 1, @@ -67,14 +68,7 @@ describe('MetadataRegistryComponent', () => { }; /* tslint:enable:no-empty */ - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - }); + paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts index 35522462aa..6eb3c5b1a4 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts @@ -27,6 +27,7 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../core/data/request.models'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; describe('MetadataSchemaComponent', () => { let comp: MetadataSchemaComponent; @@ -129,15 +130,7 @@ describe('MetadataSchemaComponent', () => { }) }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + const paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.spec.ts b/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.spec.ts index 50761b9521..a5cc69e430 100644 --- a/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.spec.ts +++ b/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.spec.ts @@ -22,6 +22,7 @@ import { PaginationComponentOptions } from '../../shared/pagination/pagination-c import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../core/data/request.models'; import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('BrowseByDatePageComponent', () => { let comp: BrowseByDatePageComponent; @@ -70,15 +71,7 @@ describe('BrowseByDatePageComponent', () => { detectChanges: () => fixture.detectChanges() }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.ts b/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.ts index 7e3979e439..a9eaa09e2f 100644 --- a/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.ts +++ b/src/app/+browse-by/+browse-by-date-page/browse-by-date-page.component.ts @@ -17,7 +17,7 @@ import { environment } from '../../../environments/environment'; import { PaginationService } from '../../core/pagination/pagination.service'; import { map } from 'rxjs/operators'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; -import { SortOptions } from '../../core/cache/models/sort-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; @Component({ selector: 'ds-browse-by-date-page', @@ -47,13 +47,14 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent { } ngOnInit(): void { + const sortConfig = new SortOptions('default', SortDirection.ASC); this.startsWithType = StartsWithType.date; - this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig)); - const currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); - const currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig); + this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig)); + this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); + this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig); this.subs.push( observableCombineLatest([this.route.params, this.route.queryParams, this.route.data, - currentPagination$, currentSort$]).pipe( + this.currentPagination$, this.currentSort$]).pipe( map(([routeParams, queryParams, data, currentPage, currentSort]) => { return [Object.assign({}, routeParams, queryParams, data), currentPage, currentSort]; }) 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 d770d8cb01..2321da0204 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 @@ -27,8 +27,8 @@ title="{{'browse.title' | translate:{collection: (parent$ | async)?.payload?.name || '', field: 'browse.metadata.' + browseId | translate, value: (value)? '"' + value + '"': ''} }}" parentname="{{(parent$ | async)?.payload?.name || ''}}" [objects$]="(items$ !== undefined)? items$ : browseEntries$" - [paginationConfig]="paginationConfig" - [sortConfig]="sortConfig" + [paginationConfig]="(currentPagination$ |async)" + [sortConfig]="(currentSort$ |async)" [type]="startsWithType" [startsWithOptions]="startsWithOptions" [enableArrows]="true" diff --git a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts index 1c6336c2c8..60d2fa549b 100644 --- a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts +++ b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.spec.ts @@ -24,16 +24,14 @@ import { VarDirective } from '../../shared/utils/var.directive'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; import { PaginationService } from '../../core/pagination/pagination.service'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('BrowseByMetadataPageComponent', () => { let comp: BrowseByMetadataPageComponent; let fixture: ComponentFixture; let browseService: BrowseService; let route: ActivatedRoute; - let paginationService: PaginationService; - - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); + let paginationService; const mockCommunity = Object.assign(new Community(), { id: 'test-uuid', @@ -88,11 +86,7 @@ describe('BrowseByMetadataPageComponent', () => { params: observableOf({}) }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getRouteParameterValue: observableOf('') - }); + paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts index 833c3d7d19..9ebc341856 100644 --- a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts +++ b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts @@ -16,7 +16,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { StartsWithType } from '../../shared/starts-with/starts-with-decorator'; import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator'; import { PaginationService } from '../../core/pagination/pagination.service'; -import { map } from 'rxjs/operators'; +import { map, switchMap } from 'rxjs/operators'; @Component({ selector: 'ds-browse-by-metadata-page', @@ -56,9 +56,14 @@ export class BrowseByMetadataPageComponent implements OnInit { }); /** - * The sorting config used to sort the values (defaults to Ascending) + * The pagination observable */ - sortConfig: SortOptions = new SortOptions('default', SortDirection.ASC); + currentPagination$: Observable; + + /** + * The sorting config observable + */ + currentSort$: Observable; /** * List of subscriptions @@ -107,11 +112,12 @@ export class BrowseByMetadataPageComponent implements OnInit { } ngOnInit(): void { - this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig)); - const currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); - const currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig); + const sortConfig = new SortOptions('default', SortDirection.ASC); + this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig)); + this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); + this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig); this.subs.push( - observableCombineLatest([this.route.params, this.route.queryParams, currentPagination$, currentSort$]).pipe( + observableCombineLatest([this.route.params, this.route.queryParams, this.currentPagination$, this.currentSort$]).pipe( map(([routeParams, queryParams, currentPage, currentSort]) => { return [Object.assign({}, routeParams, queryParams),currentPage,currentSort]; }) @@ -161,6 +167,7 @@ export class BrowseByMetadataPageComponent implements OnInit { * @param value The value of the browse-entry to display items for */ updatePageWithItems(searchOptions: BrowseEntrySearchOptions, value: string) { + console.log('updatePAge', searchOptions); this.items$ = this.browseService.getBrowseItemsFor(value, searchOptions); } diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts index 6ae10c6696..d44c667044 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.spec.ts @@ -22,6 +22,7 @@ import { PaginationComponentOptions } from '../../shared/pagination/pagination-c import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../core/data/request.models'; import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('BrowseByTitlePageComponent', () => { let comp: BrowseByTitlePageComponent; @@ -65,15 +66,7 @@ describe('BrowseByTitlePageComponent', () => { data: observableOf({ metadata: 'title' }) }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + const paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts index de9fb2daf0..381684f9f0 100644 --- a/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts +++ b/src/app/+browse-by/+browse-by-title-page/browse-by-title-page.component.ts @@ -35,12 +35,12 @@ export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent { } ngOnInit(): void { - this.sortConfig = new SortOptions('dc.title', SortDirection.ASC); - this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig)); - const currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); - const currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig); + const sortConfig = new SortOptions('dc.title', SortDirection.ASC); + this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig)); + this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig); + this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig); this.subs.push( - observableCombineLatest([this.route.params, this.route.queryParams, currentPagination$, currentSort$]).pipe( + observableCombineLatest([this.route.params, this.route.queryParams, this.currentPagination$, this.currentSort$]).pipe( map(([routeParams, queryParams, currentPage, currentSort]) => { return [Object.assign({}, routeParams, queryParams),currentPage,currentSort]; }) diff --git a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.spec.ts b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.spec.ts index abb3d957bc..93a6c6fbb1 100644 --- a/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.spec.ts +++ b/src/app/+community-page/sub-collection-list/community-page-sub-collection-list.component.spec.ts @@ -24,6 +24,7 @@ import { of as observableOf } from 'rxjs'; import { PaginationService } from '../../core/pagination/pagination.service'; import { getMockThemeService } from '../../shared/mocks/theme-service.mock'; import { ThemeService } from '../../shared/theme-support/theme.service'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('CommunityPageSubCollectionList Component', () => { let comp: CommunityPageSubCollectionListComponent; @@ -117,16 +118,7 @@ describe('CommunityPageSubCollectionList Component', () => { } }; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {} - }); + const paginationService = new PaginationServiceStub(); themeService = getMockThemeService(); diff --git a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts index 1054879f0e..e573259b63 100644 --- a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts +++ b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts @@ -24,6 +24,7 @@ import { of as observableOf } from 'rxjs'; import { PaginationService } from '../../core/pagination/pagination.service'; import { getMockThemeService } from '../../shared/mocks/theme-service.mock'; import { ThemeService } from '../../shared/theme-support/theme.service'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('CommunityPageSubCommunityListComponent Component', () => { let comp: CommunityPageSubCommunityListComponent; @@ -118,15 +119,7 @@ describe('CommunityPageSubCommunityListComponent Component', () => { } }; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + const paginationService = new PaginationServiceStub(); themeService = getMockThemeService(); diff --git a/src/app/+home-page/top-level-community-list/top-level-community-list.component.spec.ts b/src/app/+home-page/top-level-community-list/top-level-community-list.component.spec.ts index 4a5549cf4a..00408e4696 100644 --- a/src/app/+home-page/top-level-community-list/top-level-community-list.component.spec.ts +++ b/src/app/+home-page/top-level-community-list/top-level-community-list.component.spec.ts @@ -24,6 +24,7 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options import { PaginationService } from '../../core/pagination/pagination.service'; import { getMockThemeService } from '../../shared/mocks/theme-service.mock'; import { ThemeService } from '../../shared/theme-support/theme.service'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('TopLevelCommunityList Component', () => { let comp: TopLevelCommunityListComponent; @@ -109,14 +110,7 @@ describe('TopLevelCommunityList Component', () => { } }; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getRouteParameterValue: observableOf('') - }); + paginationService = new PaginationServiceStub(); themeService = getMockThemeService(); diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts index f3c50f4d13..807d9f8357 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts @@ -20,6 +20,7 @@ import { PaginationService } from '../../../../../core/pagination/pagination.ser import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../../../core/data/request.models'; +import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub'; describe('PaginatedDragAndDropBitstreamListComponent', () => { let comp: PaginatedDragAndDropBitstreamListComponent; @@ -28,7 +29,7 @@ describe('PaginatedDragAndDropBitstreamListComponent', () => { let bundleService: BundleDataService; let objectValuesPipe: ObjectValuesPipe; let requestService: RequestService; - let paginationService: PaginationService; + let paginationService; const columnSizes = new ResponsiveTableSizes([ new ResponsiveColumnSizes(2, 2, 3, 4, 4), @@ -114,15 +115,7 @@ describe('PaginatedDragAndDropBitstreamListComponent', () => { hasByHref$: observableOf(true) }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.spec.ts b/src/app/+item-page/full/field-components/file-section/full-file-section.component.spec.ts index 0723354ef5..9b225632df 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.spec.ts +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.spec.ts @@ -20,6 +20,7 @@ import { PaginationComponentOptions } from '../../../../shared/pagination/pagina import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../../core/data/request.models'; import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; describe('FullFileSectionComponent', () => { let comp: FullFileSectionComponent; @@ -56,15 +57,7 @@ describe('FullFileSectionComponent', () => { findAllByItemAndBundleName: createSuccessfulRemoteDataObject$(createPaginatedList([mockBitstream, mockBitstream, mockBitstream])) }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + const paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { diff --git a/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts b/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts index 86489019d9..87a2f8a9dd 100644 --- a/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts +++ b/src/app/+my-dspace-page/my-dspace-configuration.service.spec.ts @@ -9,6 +9,8 @@ import { ActivatedRouteStub } from '../shared/testing/active-router.stub'; import { RoleServiceMock } from '../shared/mocks/role-service.mock'; import { cold, hot } from 'jasmine-marbles'; import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type'; +import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; +import { PaginationService } from '../core/pagination/pagination.service'; describe('MyDSpaceConfigurationService', () => { let service: MyDSpaceConfigurationService; @@ -34,18 +36,13 @@ describe('MyDSpaceConfigurationService', () => { getRouteDataValue: observableOf({}) }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(defaults.pagination), - getCurrentSort: observableOf(defaults.sort), - getRouteParameterValue: observableOf('') - }); - + const paginationService = new PaginationServiceStub(); const activatedRoute: any = new ActivatedRouteStub(); const roleService: any = new RoleServiceMock(); beforeEach(() => { - service = new MyDSpaceConfigurationService(roleService, spy, paginationService, activatedRoute); + service = new MyDSpaceConfigurationService(roleService, spy, paginationService as any, activatedRoute); }); describe('when the scope is called', () => { diff --git a/src/app/core/pagination/pagination.service.ts b/src/app/core/pagination/pagination.service.ts index 45a1ffee96..8ed81ba8d4 100644 --- a/src/app/core/pagination/pagination.service.ts +++ b/src/app/core/pagination/pagination.service.ts @@ -16,6 +16,12 @@ import { isNumeric } from 'rxjs/internal-compatibility'; }) /** * Service to manage the pagination of different components + * The pagination information will be stored in the route based on a paginationID. + * The following params are used for the different kind of pagination information: + * - For the page: p.{paginationID} + * - For the page size: rpp.{paginationID} + * - For the sort direction: sd.{paginationID} + * - For the sort field: sf.{paginationID} */ export class PaginationService { diff --git a/src/app/core/shared/search/search-configuration.service.spec.ts b/src/app/core/shared/search/search-configuration.service.spec.ts index f1f9dc7b9b..061182c2fc 100644 --- a/src/app/core/shared/search/search-configuration.service.spec.ts +++ b/src/app/core/shared/search/search-configuration.service.spec.ts @@ -5,6 +5,7 @@ import { SortDirection, SortOptions } from '../../cache/models/sort-options.mode import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model'; import { SearchFilter } from '../../../shared/search/search-filter.model'; import { of as observableOf } from 'rxjs'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; describe('SearchConfigurationService', () => { let service: SearchConfigurationService; @@ -30,17 +31,13 @@ describe('SearchConfigurationService', () => { getRouteParameterValue: observableOf('') }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(defaults.pagination), - getCurrentSort: observableOf(defaults.sort), - getRouteParameterValue: observableOf('') - }); + const paginationService = new PaginationServiceStub(); const activatedRoute: any = new ActivatedRouteStub(); beforeEach(() => { - service = new SearchConfigurationService(routeService, paginationService, activatedRoute); + service = new SearchConfigurationService(routeService, paginationService as any, activatedRoute); }); describe('when the scope is called', () => { beforeEach(() => { diff --git a/src/app/core/shared/search/search.service.spec.ts b/src/app/core/shared/search/search.service.spec.ts index 9eb650219b..60cb0a87b9 100644 --- a/src/app/core/shared/search/search.service.spec.ts +++ b/src/app/core/shared/search/search.service.spec.ts @@ -27,6 +27,7 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio import { SortDirection, SortOptions } from '../../cache/models/sort-options.model'; import { FindListOptions } from '../../data/request.models'; import { SearchConfigurationService } from './search-configuration.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; @Component({ template: '' }) class DummyComponent { @@ -102,16 +103,7 @@ describe('SearchService', () => { } }; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {} - }); + const paginationService = new PaginationServiceStub(); const searchConfigService = {paginationID: 'page-id'}; beforeEach(() => { diff --git a/src/app/process-page/overview/process-overview.component.spec.ts b/src/app/process-page/overview/process-overview.component.spec.ts index 1da2ac2b5b..98e78f6b36 100644 --- a/src/app/process-page/overview/process-overview.component.spec.ts +++ b/src/app/process-page/overview/process-overview.component.spec.ts @@ -17,6 +17,7 @@ import { PaginationService } from '../../core/pagination/pagination.service'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../core/data/request.models'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('ProcessOverviewComponent', () => { let component: ProcessOverviewComponent; @@ -24,15 +25,11 @@ describe('ProcessOverviewComponent', () => { let processService: ProcessDataService; let ePersonService: EPersonDataService; - let paginationService: PaginationService; + let paginationService; let processes: Process[]; let ePerson: EPerson; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - function init() { processes = [ Object.assign(new Process(), { @@ -80,11 +77,7 @@ describe('ProcessOverviewComponent', () => { findById: createSuccessfulRemoteDataObject$(ePerson) }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - }); + paginationService = new PaginationServiceStub(); } beforeEach(waitForAsync(() => { diff --git a/src/app/search-navbar/search-navbar.component.spec.ts b/src/app/search-navbar/search-navbar.component.spec.ts index 87b75328bb..ba08c7ca75 100644 --- a/src/app/search-navbar/search-navbar.component.spec.ts +++ b/src/app/search-navbar/search-navbar.component.spec.ts @@ -13,6 +13,7 @@ import { SortDirection, SortOptions } from '../core/cache/models/sort-options.mo import { of as observableOf } from 'rxjs'; import { PaginationService } from '../core/pagination/pagination.service'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; +import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; describe('SearchNavbarComponent', () => { let component: SearchNavbarComponent; @@ -33,16 +34,7 @@ describe('SearchNavbarComponent', () => { navigate: (commands) => commands }; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getRouteParameterValue: observableOf(''), - updateRouteWithUrl: {}, - clearPagination : {} - }); + paginationService = new PaginationServiceStub(); TestBed.configureTestingModule({ imports: [ 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 4c9ac9204d..806f4bdb6f 100644 --- a/src/app/shared/browse-by/browse-by.component.spec.ts +++ b/src/app/shared/browse-by/browse-by.component.spec.ts @@ -20,6 +20,7 @@ import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; import { storeModuleConfig } from '../../app.reducer'; import { FindListOptions } from '../../core/data/request.models'; import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../testing/pagination-service.stub'; describe('BrowseByComponent', () => { let comp: BrowseByComponent; @@ -53,15 +54,7 @@ describe('BrowseByComponent', () => { pageSizeOptions: [5, 10, 15, 20], pageSize: 15 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(paginationConfig), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - updateRoute: {}, - resetPage: {}, - }); + const paginationService = new PaginationServiceStub(paginationConfig); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/shared/item/item-versions/item-versions.component.spec.ts b/src/app/shared/item/item-versions/item-versions.component.spec.ts index 33e99eb88f..cc28779537 100644 --- a/src/app/shared/item/item-versions/item-versions.component.spec.ts +++ b/src/app/shared/item/item-versions/item-versions.component.spec.ts @@ -15,14 +15,12 @@ import { PaginationComponentOptions } from '../../pagination/pagination-componen import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { of as observableOf } from 'rxjs'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../testing/pagination-service.stub'; describe('ItemVersionsComponent', () => { let component: ItemVersionsComponent; let fixture: ComponentFixture; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const versionHistory = Object.assign(new VersionHistory(), { id: '1' }); @@ -59,11 +57,7 @@ describe('ItemVersionsComponent', () => { getVersions: createSuccessfulRemoteDataObject$(createPaginatedList(versions)) }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getRouteParameterValue: observableOf('') - }); + const paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/shared/object-select/collection-select/collection-select.component.spec.ts b/src/app/shared/object-select/collection-select/collection-select.component.spec.ts index 60cce1ae09..199bc56647 100644 --- a/src/app/shared/object-select/collection-select/collection-select.component.spec.ts +++ b/src/app/shared/object-select/collection-select/collection-select.component.spec.ts @@ -17,6 +17,7 @@ import { SortDirection, SortOptions } from '../../../core/cache/models/sort-opti import { FindListOptions } from '../../../core/data/request.models'; import { of as observableOf } from 'rxjs'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../testing/pagination-service.stub'; describe('CollectionSelectComponent', () => { let comp: CollectionSelectComponent; @@ -40,16 +41,7 @@ describe('CollectionSelectComponent', () => { currentPage: 1 }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); - + const paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), SharedModule, RouterTestingModule.withRoutes([])], diff --git a/src/app/shared/object-select/item-select/item-select.component.spec.ts b/src/app/shared/object-select/item-select/item-select.component.spec.ts index 2ca3cd4fa8..224fb764b6 100644 --- a/src/app/shared/object-select/item-select/item-select.component.spec.ts +++ b/src/app/shared/object-select/item-select/item-select.component.spec.ts @@ -17,12 +17,13 @@ import { createPaginatedList } from '../../testing/utils.test'; import { PaginationService } from '../../../core/pagination/pagination.service'; import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../core/data/request.models'; +import { PaginationServiceStub } from '../../testing/pagination-service.stub'; describe('ItemSelectComponent', () => { let comp: ItemSelectComponent; let fixture: ComponentFixture; let objectSelectService: ObjectSelectService; - let paginationService: PaginationService; + let paginationService; const mockItemList = [ Object.assign(new Item(), { @@ -63,14 +64,7 @@ describe('ItemSelectComponent', () => { currentPage: 1 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(mockPaginationOptions), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + paginationService = new PaginationServiceStub(mockPaginationOptions); diff --git a/src/app/shared/page-size-selector/page-size-selector.component.spec.ts b/src/app/shared/page-size-selector/page-size-selector.component.spec.ts index cf7f1d5e11..77931400a2 100644 --- a/src/app/shared/page-size-selector/page-size-selector.component.spec.ts +++ b/src/app/shared/page-size-selector/page-size-selector.component.spec.ts @@ -13,6 +13,7 @@ import { EnumKeysPipe } from '../utils/enum-keys-pipe'; import { VarDirective } from '../utils/var.directive'; import { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.component'; import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../testing/pagination-service.stub'; describe('PageSizeSelectorComponent', () => { @@ -34,11 +35,7 @@ describe('PageSizeSelectorComponent', () => { sort }; - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getRouteParameterValue: observableOf('') - }); + const paginationService = new PaginationServiceStub(pagination, sort); const activatedRouteStub = { queryParams: observableOf({ diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts index 53a4619071..0c6cd80a62 100644 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts +++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts @@ -14,6 +14,7 @@ import { ObjectValuesPipe } from '../utils/object-values-pipe'; import { PaginationService } from '../../core/pagination/pagination.service'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { PaginationServiceStub } from '../testing/pagination-service.stub'; @Component({ selector: 'ds-mock-paginated-drag-drop-abstract', @@ -47,8 +48,6 @@ describe('AbstractPaginatedDragAndDropListComponent', () => { const url = 'mock-abstract-paginated-drag-and-drop-list-component'; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); const object1 = Object.assign(new DSpaceObject(), { uuid: 'object-1' }); const object2 = Object.assign(new DSpaceObject(), { uuid: 'object-2' }); @@ -77,11 +76,7 @@ describe('AbstractPaginatedDragAndDropListComponent', () => { paginationComponent = jasmine.createSpyObj('paginationComponent', { doPageChange: {} }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getRouteParameterValue: observableOf('') - }); + paginationService = new PaginationServiceStub(); objectsRD$ = new BehaviorSubject(objectsRD); component = new MockAbstractPaginatedDragAndDropListComponent(objectUpdatesService, elRef, objectValuesPipe, url, paginationService, objectsRD$); component.paginationComponent = paginationComponent; diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts index 66308df67f..3c50f66158 100644 --- a/src/app/shared/pagination/pagination.component.spec.ts +++ b/src/app/shared/pagination/pagination.component.spec.ts @@ -34,6 +34,7 @@ import { storeModuleConfig } from '../../app.reducer'; import { PaginationService } from '../../core/pagination/pagination.service'; import { FindListOptions } from '../../core/data/request.models'; import { BehaviorSubject, of as observableOf } from 'rxjs'; +import { PaginationServiceStub } from '../testing/pagination-service.stub'; function expectPages(fixture: ComponentFixture, pagesDef: string[]): void { const de = fixture.debugElement.query(By.css('.pagination')); @@ -108,7 +109,7 @@ describe('Pagination component', () => { let activatedRouteStub: MockActivatedRoute; let routerStub: RouterMock; - let paginationService: PaginationService; + let paginationService; // Define initial state and test state const _initialState = { width: 1600, height: 770 }; diff --git a/src/app/shared/pagination/pagination.component.ts b/src/app/shared/pagination/pagination.component.ts index 1b9adf8922..8f1c6bf26f 100644 --- a/src/app/shared/pagination/pagination.component.ts +++ b/src/app/shared/pagination/pagination.component.ts @@ -99,9 +99,8 @@ export class PaginationComponent implements OnDestroy, OnInit { @Input() public hidePagerWhenSinglePage = true; /** - * Option for disabling updating and reading route parameters on pagination changes - * In other words, changing pagination won't add or update the url parameters on the current page, and the url - * parameters won't affect the pagination of this component + * Option for retaining the scroll position upon navigating to an url with updated params. + * After the page update the page will scroll back to the current pagination component. */ @Input() public retainScrollPosition = false; @@ -121,8 +120,8 @@ export class PaginationComponent implements OnDestroy, OnInit { public hostWindow: Observable; /** - * ID for the pagination instance. Only useful if you wish to - * have more than once instance at a time in a given component. + * ID for the pagination instance. This ID is used in the routing to retrieve the pagination options. + * This ID needs to be unique between different pagination components when more than one will be displayed on the same page. */ public id: string; @@ -156,7 +155,7 @@ export class PaginationComponent implements OnDestroy, OnInit { * Name of the field that's used to sort by */ public sortField$; - public defaultSortField = 'id'; + public defaultSortField = 'name'; /** * Array to track all subscriptions and unsubscribe them onDestroy diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts index a683a536b4..73aaab5170 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts +++ b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.spec.ts @@ -22,6 +22,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../../core/data/request.models'; import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../testing/pagination-service.stub'; describe('EpersonGroupListComponent test suite', () => { let comp: EpersonGroupListComponent; @@ -64,15 +65,7 @@ describe('EpersonGroupListComponent test suite', () => { const groupPaginatedList = buildPaginatedList(new PageInfo(), [GroupMock, GroupMock]); const groupPaginatedListRD = createSuccessfulRemoteDataObject(groupPaginatedList); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(paginationOptions), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - clearPagination: {} - }); + paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/shared/search-form/search-form.component.spec.ts b/src/app/shared/search-form/search-form.component.spec.ts index 635d11f0d0..1469eac566 100644 --- a/src/app/shared/search-form/search-form.component.spec.ts +++ b/src/app/shared/search-form/search-form.component.spec.ts @@ -14,6 +14,7 @@ import { FindListOptions } from '../../core/data/request.models'; import { of as observableOf } from 'rxjs'; import { PaginationService } from '../../core/pagination/pagination.service'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; +import { PaginationServiceStub } from '../testing/pagination-service.stub'; describe('SearchFormComponent', () => { let comp: SearchFormComponent; @@ -21,16 +22,7 @@ describe('SearchFormComponent', () => { let de: DebugElement; let el: HTMLElement; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {} - }); + const paginationService = new PaginationServiceStub(); const searchConfigService = {paginationID: 'test-id'}; diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts index a01843248e..4c7798ed0b 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts @@ -19,6 +19,7 @@ import { PaginationComponentOptions } from '../../../../../pagination/pagination import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../../../../core/data/request.models'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; describe('SearchFacetOptionComponent', () => { let comp: SearchFacetOptionComponent; @@ -85,17 +86,8 @@ describe('SearchFacetOptionComponent', () => { let router; const page = observableOf(0); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - getPageParam: 'p.page-id', - }); - + const pagination = Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 }); + const paginationService = new PaginationServiceStub(pagination); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts index 6329655eca..98cb671dba 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts @@ -23,6 +23,7 @@ import { PaginationComponentOptions } from '../../../../../pagination/pagination import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../../../../core/data/request.models'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; describe('SearchFacetRangeOptionComponent', () => { let comp: SearchFacetRangeOptionComponent; @@ -58,17 +59,8 @@ describe('SearchFacetRangeOptionComponent', () => { let router; const page = observableOf(0); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {}, - getPageParam: 'p.page-id', - }); + const pagination = Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 }); + const paginationService = new PaginationServiceStub(pagination); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts index 60c4fd5721..6a37a4d0ba 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts @@ -18,6 +18,7 @@ import { PaginationComponentOptions } from '../../../../../pagination/pagination import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../../../../core/data/request.models'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; describe('SearchFacetSelectedOptionComponent', () => { let comp: SearchFacetSelectedOptionComponent; @@ -110,17 +111,8 @@ describe('SearchFacetSelectedOptionComponent', () => { let router; const page = observableOf(0); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {}, - getPageParam: 'p.page-id' - }); + const pagination = Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 }); + const paginationService = new PaginationServiceStub(pagination); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts b/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts index fe9959aa3a..35de768977 100644 --- a/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts +++ b/src/app/shared/search/search-labels/search-label/search-label.component.spec.ts @@ -16,6 +16,7 @@ import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-o import { FindListOptions } from '../../../../core/data/request.models'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service'; +import { PaginationServiceStub } from '../../../testing/pagination-service.stub'; describe('SearchLabelComponent', () => { let comp: SearchLabelComponent; @@ -38,17 +39,8 @@ describe('SearchLabelComponent', () => { filter2 ]; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - updateRouteWithUrl: {}, - getPageParam: 'p.test-id' - }); + const pagination = Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 }); + const paginationService = new PaginationServiceStub(pagination); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/shared/search/search-settings/search-settings.component.spec.ts b/src/app/shared/search/search-settings/search-settings.component.spec.ts index 5ae1f7eaf2..dff8935ef5 100644 --- a/src/app/shared/search/search-settings/search-settings.component.spec.ts +++ b/src/app/shared/search/search-settings/search-settings.component.spec.ts @@ -17,6 +17,7 @@ import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.c import { SidebarService } from '../../sidebar/sidebar.service'; import { SidebarServiceStub } from '../../testing/sidebar-service.stub'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../testing/pagination-service.stub'; describe('SearchSettingsComponent', () => { @@ -65,11 +66,7 @@ describe('SearchSettingsComponent', () => { }), }; - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - resetPage: {}, - }); + paginationService = new PaginationServiceStub(pagination, sort); TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], diff --git a/src/app/shared/starts-with/date/starts-with-date.component.spec.ts b/src/app/shared/starts-with/date/starts-with-date.component.spec.ts index 4b4556f511..dfee88c955 100644 --- a/src/app/shared/starts-with/date/starts-with-date.component.spec.ts +++ b/src/app/shared/starts-with/date/starts-with-date.component.spec.ts @@ -15,6 +15,7 @@ import { PaginationComponentOptions } from '../../pagination/pagination-componen import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; import { FindListOptions } from '../../../core/data/request.models'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../testing/pagination-service.stub'; describe('StartsWithDateComponent', () => { let comp: StartsWithDateComponent; @@ -30,15 +31,7 @@ describe('StartsWithDateComponent', () => { queryParams: observableOf({}) }); - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - - paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - }); + paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/shared/starts-with/text/starts-with-text.component.spec.ts b/src/app/shared/starts-with/text/starts-with-text.component.spec.ts index 1295f0a33a..9f9d9d6d42 100644 --- a/src/app/shared/starts-with/text/starts-with-text.component.spec.ts +++ b/src/app/shared/starts-with/text/starts-with-text.component.spec.ts @@ -13,6 +13,7 @@ import { SortDirection, SortOptions } from '../../../core/cache/models/sort-opti import { FindListOptions } from '../../../core/data/request.models'; import { of as observableOf } from 'rxjs'; import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../testing/pagination-service.stub'; describe('StartsWithTextComponent', () => { let comp: StartsWithTextComponent; @@ -22,15 +23,7 @@ describe('StartsWithTextComponent', () => { const options = ['0-9', 'A', 'B', 'C']; - const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }); - const sort = new SortOptions('score', SortDirection.DESC); - const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 }); - const paginationService = jasmine.createSpyObj('PaginationService', { - getCurrentPagination: observableOf(pagination), - getCurrentSort: observableOf(sort), - getFindListOptions: observableOf(findlistOptions), - resetPage: {}, - }); + const paginationService = new PaginationServiceStub(); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ diff --git a/src/app/shared/testing/pagination-service.stub.ts b/src/app/shared/testing/pagination-service.stub.ts new file mode 100644 index 0000000000..f26c368b14 --- /dev/null +++ b/src/app/shared/testing/pagination-service.stub.ts @@ -0,0 +1,25 @@ +import { of as observableOf } from 'rxjs'; +import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; +import { FindListOptions } from '../../core/data/request.models'; + +export class PaginationServiceStub { + + constructor( + public pagination = Object.assign(new PaginationComponentOptions(), {currentPage: 1, pageSize: 20}), + public sort = new SortOptions('score', SortDirection.DESC), + public findlistOptions = Object.assign(new FindListOptions(), {currentPage: 1, elementsPerPage: 20}), + ) { + } + + getCurrentPagination = jasmine.createSpy('getCurrentPagination').and.returnValue(observableOf(this.pagination)); + getCurrentSort = jasmine.createSpy('getCurrentSort').and.returnValue(observableOf(this.sort)); + getFindListOptions = jasmine.createSpy('getFindListOptions').and.returnValue(observableOf(this.findlistOptions)); + resetPage = jasmine.createSpy('resetPage'); + updateRoute = jasmine.createSpy('updateRoute'); + updateRouteWithUrl = jasmine.createSpy('updateRouteWithUrl'); + clearPagination = jasmine.createSpy('clearPagination'); + getRouteParameterValue = jasmine.createSpy('getRouteParameterValue').and.returnValue(observableOf('')); + getPageParam = jasmine.createSpy('getPageParam').and.returnValue(`p.${this.pagination.id}`); + +} diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index faaf83389b..fe568533e4 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -2,13 +2,13 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { BehaviorSubject, combineLatest, Subscription } from 'rxjs'; -import { filter, mergeMap, take } from 'rxjs/operators'; +import { filter, mergeMap, switchMap, take } from 'rxjs/operators'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { ExternalSourceService } from '../../core/data/external-source.service'; import { ExternalSourceData } from './import-external-searchbar/submission-import-external-searchbar.component'; import { RemoteData } from '../../core/data/remote-data'; -import { PaginatedList, buildPaginatedList } from '../../core/data/paginated-list.model'; +import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model'; import { ExternalSourceEntry } from '../../core/shared/external-source-entry.model'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; import { Context } from '../../core/shared/context.model'; @@ -167,25 +167,27 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { * @param query The query string to search */ private retrieveExternalSources(): void { - this.reload$.subscribe((sourceQueryObject: {source: string, query: string}) => { - const source = sourceQueryObject.source; - const query = sourceQueryObject.query; - if (isNotEmpty(source) && isNotEmpty(query)) { - this.routeData.sourceId = source; - this.routeData.query = query; - this.isLoading$.next(true); - this.subs.push( - this.searchConfigService.paginatedSearchOptions.pipe( - filter((searchOptions) => searchOptions.query === query), - mergeMap((searchOptions) => this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions).pipe( - getFinishedRemoteData(), - )), - ).subscribe((rdData) => { - this.entriesRD$.next(rdData); - this.isLoading$.next(false); - }) - ); - } + this.reload$.pipe( + switchMap( + (sourceQueryObject: { source: string, query: string }) => { + const source = sourceQueryObject.source; + const query = sourceQueryObject.query; + if (isNotEmpty(source) && isNotEmpty(query)) { + this.routeData.sourceId = source; + this.routeData.query = query; + this.isLoading$.next(true); + return this.searchConfigService.paginatedSearchOptions.pipe( + filter((searchOptions) => searchOptions.query === query), + mergeMap((searchOptions) => this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions).pipe( + getFinishedRemoteData(), + )), + ); + } + } + ), + ).subscribe((rdData) => { + this.entriesRD$.next(rdData); + this.isLoading$.next(false); }); } From a4076ed1fd66c8a76cbca1ca9edfa73c86da1c41 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Mon, 29 Mar 2021 16:13:20 +0200 Subject: [PATCH 10/14] Fix lgtm issue --- .../browse-by-metadata-page.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts index 9ebc341856..f5adefc779 100644 --- a/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts +++ b/src/app/+browse-by/+browse-by-metadata-page/browse-by-metadata-page.component.ts @@ -16,7 +16,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { StartsWithType } from '../../shared/starts-with/starts-with-decorator'; import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator'; import { PaginationService } from '../../core/pagination/pagination.service'; -import { map, switchMap } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; @Component({ selector: 'ds-browse-by-metadata-page', From 824ee029b3f0382eebb51090d27cff2bd4d441ac Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 1 Apr 2021 16:28:20 +0200 Subject: [PATCH 11/14] Change p. to page and reverse id and pagination info --- .../pagination/pagination.service.spec.ts | 58 +++++++++---------- src/app/core/pagination/pagination.service.ts | 26 ++++----- .../search-form/search-form.component.ts | 2 +- .../search-facet-option.component.spec.ts | 4 +- ...earch-facet-range-option.component.spec.ts | 2 +- ...ch-facet-selected-option.component.spec.ts | 4 +- .../shared/testing/pagination-service.stub.ts | 2 +- 7 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/app/core/pagination/pagination.service.spec.ts b/src/app/core/pagination/pagination.service.spec.ts index f689f4f0f0..18f94cc84c 100644 --- a/src/app/core/pagination/pagination.service.spec.ts +++ b/src/app/core/pagination/pagination.service.spec.ts @@ -20,16 +20,16 @@ describe('PaginationService', () => { routeService = { getQueryParameterValue: (param) => { let value; - if (param.startsWith('p.')) { + if (param.endsWith('.page')) { value = 5; } - if (param.startsWith('rpp.')) { + if (param.endsWith('.rpp')) { value = 10; } - if (param.startsWith('sd.')) { + if (param.endsWith('.sd')) { value = 'ASC'; } - if (param.startsWith('sf.')) { + if (param.endsWith('.sf')) { value = 'score'; } return observableOf(value); @@ -83,10 +83,10 @@ describe('PaginationService', () => { service.updateRoute('test', {page: 2, pageSize: 5, sortField: 'title', sortDirection: SortDirection.DESC}); const navigateParams = {}; - navigateParams[`p.test`] = `2`; - navigateParams[`rpp.test`] = `5`; - navigateParams[`sf.test`] = `title`; - navigateParams[`sd.test`] = `DESC`; + navigateParams[`test.page`] = `2`; + navigateParams[`test.rpp`] = `5`; + navigateParams[`test.sf`] = `title`; + navigateParams[`test.sd`] = `DESC`; expect(router.navigate).toHaveBeenCalledWith([], {queryParams: navigateParams, queryParamsHandling: 'merge'}); }); @@ -94,10 +94,10 @@ describe('PaginationService', () => { service.updateRoute('test', {page: 2}); const navigateParams = {}; - navigateParams[`p.test`] = `2`; - navigateParams[`rpp.test`] = `10`; - navigateParams[`sf.test`] = `score`; - navigateParams[`sd.test`] = `ASC`; + navigateParams[`test.page`] = `2`; + navigateParams[`test.rpp`] = `10`; + navigateParams[`test.sf`] = `score`; + navigateParams[`test.sd`] = `ASC`; expect(router.navigate).toHaveBeenCalledWith([], {queryParams: navigateParams, queryParamsHandling: 'merge'}); }); @@ -107,10 +107,10 @@ describe('PaginationService', () => { service.updateRouteWithUrl('test', ['someUrl'], {page: 2, pageSize: 5, sortField: 'title', sortDirection: SortDirection.DESC}); const navigateParams = {}; - navigateParams[`p.test`] = `2`; - navigateParams[`rpp.test`] = `5`; - navigateParams[`sf.test`] = `title`; - navigateParams[`sd.test`] = `DESC`; + navigateParams[`test.page`] = `2`; + navigateParams[`test.rpp`] = `5`; + navigateParams[`test.sf`] = `title`; + navigateParams[`test.sd`] = `DESC`; expect(router.navigate).toHaveBeenCalledWith(['someUrl'], {queryParams: navigateParams, queryParamsHandling: 'merge'}); }); @@ -118,10 +118,10 @@ describe('PaginationService', () => { service.updateRouteWithUrl('test',['someUrl'], {page: 2}); const navigateParams = {}; - navigateParams[`p.test`] = `2`; - navigateParams[`rpp.test`] = `10`; - navigateParams[`sf.test`] = `score`; - navigateParams[`sd.test`] = `ASC`; + navigateParams[`test.page`] = `2`; + navigateParams[`test.rpp`] = `10`; + navigateParams[`test.sf`] = `score`; + navigateParams[`test.sd`] = `ASC`; expect(router.navigate).toHaveBeenCalledWith(['someUrl'], {queryParams: navigateParams, queryParamsHandling: 'merge'}); }); @@ -132,17 +132,17 @@ describe('PaginationService', () => { service.clearPagination('test'); const resetParams = {}; - resetParams[`p.test`] = null; - resetParams[`rpp.test`] = null; - resetParams[`sf.test`] = null; - resetParams[`sd.test`] = null; + resetParams[`test.page`] = null; + resetParams[`test.rpp`] = null; + resetParams[`test.sf`] = null; + resetParams[`test.sd`] = null; const navigateParams = {}; - navigateParams[`p.another-id`] = `5`; - navigateParams[`rpp.another-id`] = `10`; - navigateParams[`sf.another-id`] = `score`; - navigateParams[`sd.another-id`] = `ASC`; + navigateParams[`another-id.page`] = `5`; + navigateParams[`another-id.rpp`] = `10`; + navigateParams[`another-id.sf`] = `score`; + navigateParams[`another-id.sd`] = `ASC`; service.updateRoute('another-id', {}); @@ -152,7 +152,7 @@ describe('PaginationService', () => { describe('getPageParam', () => { it('should return the name of the page param', () => { const pageParam = service.getPageParam('test'); - expect(pageParam).toEqual('p.test'); + expect(pageParam).toEqual('test.page'); }); }); }); diff --git a/src/app/core/pagination/pagination.service.ts b/src/app/core/pagination/pagination.service.ts index 8ed81ba8d4..b6ae304491 100644 --- a/src/app/core/pagination/pagination.service.ts +++ b/src/app/core/pagination/pagination.service.ts @@ -41,8 +41,8 @@ export class PaginationService { * @returns {Observable} Retrieves the current pagination settings based on the router params */ getCurrentPagination(paginationId: string, defaultPagination: PaginationComponentOptions): Observable { - const page$ = this.routeService.getQueryParameterValue(`p.${paginationId}`); - const size$ = this.routeService.getQueryParameterValue(`rpp.${paginationId}`); + const page$ = this.routeService.getQueryParameterValue(`${paginationId}.page`); + const size$ = this.routeService.getQueryParameterValue(`${paginationId}.rpp`); return observableCombineLatest([page$, size$]).pipe( map(([page, size]) => { return Object.assign(new PaginationComponentOptions(), defaultPagination, { @@ -64,8 +64,8 @@ export class PaginationService { if (!ignoreDefault && (isEmpty(defaultSort) || !hasValue(defaultSort))) { defaultSort = this.defaultSortOptions; } - const sortDirection$ = this.routeService.getQueryParameterValue(`sd.${paginationId}`); - const sortField$ = this.routeService.getQueryParameterValue(`sf.${paginationId}`); + const sortDirection$ = this.routeService.getQueryParameterValue(`${paginationId}.sd`); + const sortField$ = this.routeService.getQueryParameterValue(`${paginationId}.sf`); return observableCombineLatest([sortDirection$, sortField$]).pipe(map(([sortDirection, sortField]) => { const field = sortField || defaultSort?.field; const direction = SortDirection[sortDirection] || defaultSort?.direction; @@ -171,10 +171,10 @@ export class PaginationService { */ clearPagination(paginationId: string) { const params = {}; - params[`p.${paginationId}`] = null; - params[`rpp.${paginationId}`] = null; - params[`sf.${paginationId}`] = null; - params[`sd.${paginationId}`] = null; + params[`${paginationId}.page`] = null; + params[`${paginationId}.rpp`] = null; + params[`${paginationId}.sf`] = null; + params[`${paginationId}.sd`] = null; Object.assign(this.clearParams, params); } @@ -184,7 +184,7 @@ export class PaginationService { * @param paginationId - The ID for which to retrieve the page param */ getPageParam(paginationId: string) { - return `p.${paginationId}`; + return `${paginationId}.page`; } private getCurrentRouting(paginationId: string) { @@ -209,16 +209,16 @@ export class PaginationService { }) { const paramsWithIdName = {}; if (hasValue(params.page)) { - paramsWithIdName[`p.${paginationId}`] = `${params.page}`; + paramsWithIdName[`${paginationId}.page`] = `${params.page}`; } if (hasValue(params.pageSize)) { - paramsWithIdName[`rpp.${paginationId}`] = `${params.pageSize}`; + paramsWithIdName[`${paginationId}.rpp`] = `${params.pageSize}`; } if (hasValue(params.sortField)) { - paramsWithIdName[`sf.${paginationId}`] = `${params.sortField}`; + paramsWithIdName[`${paginationId}.sf`] = `${params.sortField}`; } if (hasValue(params.sortDirection)) { - paramsWithIdName[`sd.${paginationId}`] = `${params.sortDirection}`; + paramsWithIdName[`${paginationId}.sd`] = `${params.sortDirection}`; } return paramsWithIdName; } diff --git a/src/app/shared/search-form/search-form.component.ts b/src/app/shared/search-form/search-form.component.ts index 594f0c84e2..1c9aadf03d 100644 --- a/src/app/shared/search-form/search-form.component.ts +++ b/src/app/shared/search-form/search-form.component.ts @@ -91,7 +91,7 @@ export class SearchFormComponent { */ updateSearch(data: any) { const queryParams = Object.assign({}, data); - queryParams[`p.${this.searchConfig.paginationID}`] = 1; + queryParams[`page.${this.searchConfig.paginationID}`] = 1; this.router.navigate(this.getSearchLinkParts(), { queryParams: queryParams, diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts index 4c7798ed0b..a266e4e425 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts @@ -140,7 +140,7 @@ describe('SearchFacetOptionComponent', () => { (comp as any).updateAddParams(selectedValues); expect(comp.addQueryParams).toEqual({ [mockFilterConfig.paramName]: [`${value1},${operator}`, value.value + ',equals'], - ['p.page-id']: 1 + ['page.page-id']: 1 }); }); }); @@ -155,7 +155,7 @@ describe('SearchFacetOptionComponent', () => { (comp as any).updateAddParams(selectedValues); expect(comp.addQueryParams).toEqual({ [mockAuthorityFilterConfig.paramName]: [value1 + ',equals', `${value2},${operator}`], - ['p.page-id']: 1 + ['page.page-id']: 1 }); }); }); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts index 98cb671dba..2c93b0186b 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts @@ -126,7 +126,7 @@ describe('SearchFacetRangeOptionComponent', () => { expect(comp.changeQueryParams).toEqual({ [mockFilterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: ['50'], [mockFilterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: ['60'], - ['p.page-id']: 1 + ['page.page-id']: 1 }); }); }); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts index 6a37a4d0ba..cbb6672916 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts @@ -165,7 +165,7 @@ describe('SearchFacetSelectedOptionComponent', () => { (comp as any).updateRemoveParams(selectedValues); expect(comp.removeQueryParams).toEqual({ [mockFilterConfig.paramName]: [value1], - ['p.page-id']: 1 + ['page.page-id']: 1 }); }); }); @@ -181,7 +181,7 @@ describe('SearchFacetSelectedOptionComponent', () => { (comp as any).updateRemoveParams(selectedAuthorityValues); expect(comp.removeQueryParams).toEqual({ [mockAuthorityFilterConfig.paramName]: [`${value1},${operator}`], - ['p.page-id']: 1 + ['page.page-id']: 1 }); }); }); diff --git a/src/app/shared/testing/pagination-service.stub.ts b/src/app/shared/testing/pagination-service.stub.ts index f26c368b14..cd24808161 100644 --- a/src/app/shared/testing/pagination-service.stub.ts +++ b/src/app/shared/testing/pagination-service.stub.ts @@ -20,6 +20,6 @@ export class PaginationServiceStub { updateRouteWithUrl = jasmine.createSpy('updateRouteWithUrl'); clearPagination = jasmine.createSpy('clearPagination'); getRouteParameterValue = jasmine.createSpy('getRouteParameterValue').and.returnValue(observableOf('')); - getPageParam = jasmine.createSpy('getPageParam').and.returnValue(`p.${this.pagination.id}`); + getPageParam = jasmine.createSpy('getPageParam').and.returnValue(`page.${this.pagination.id}`); } From b16a565f7cade7ed0973554a9ecd1ddd7af97bdb Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 6 Apr 2021 12:59:38 +0200 Subject: [PATCH 12/14] fixed dropzone layover issue --- src/app/shared/uploader/uploader.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/uploader/uploader.component.html b/src/app/shared/uploader/uploader.component.html index 36078fbeb4..4f7d507404 100644 --- a/src/app/shared/uploader/uploader.component.html +++ b/src/app/shared/uploader/uploader.component.html @@ -1,5 +1,5 @@
Date: Tue, 6 Apr 2021 13:27:20 +0200 Subject: [PATCH 13/14] Unreverted changes from #1053 --- src/app/shared/mocks/submission.mock.ts | 85 +++++++++++++++++++ src/app/shared/uploader/uploader.component.ts | 25 +----- .../form/submission-form.component.html | 65 +++++++------- .../form/submission-form.component.spec.ts | 9 +- .../form/submission-form.component.ts | 12 ++- .../sections/sections.service.spec.ts | 34 ++++++-- .../submission/sections/sections.service.ts | 25 +++++- 7 files changed, 186 insertions(+), 69 deletions(-) diff --git a/src/app/shared/mocks/submission.mock.ts b/src/app/shared/mocks/submission.mock.ts index 16cc9b6262..1ee097af71 100644 --- a/src/app/shared/mocks/submission.mock.ts +++ b/src/app/shared/mocks/submission.mock.ts @@ -1101,6 +1101,91 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, { } }); +export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.assign({}, { + 826: { + collection: mockSubmissionCollectionId, + definition: 'traditional', + selfUrl: mockSubmissionSelfUrl, + activeSection: null, + sections: { + extraction: { + config: '', + mandatory: true, + sectionType: 'utils', + visibility: { + main: 'HIDDEN', + other: 'HIDDEN' + }, + collapsed: false, + enabled: true, + data: {}, + errors: [], + isLoading: false, + isValid: false + } as any, + collection: { + config: '', + mandatory: true, + sectionType: 'collection', + visibility: { + main: 'HIDDEN', + other: 'HIDDEN' + }, + collapsed: false, + enabled: true, + data: {}, + errors: [], + isLoading: false, + isValid: false + } as any, + traditionalpageone: { + header: 'submit.progressbar.describe.stepone', + config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone', + mandatory: true, + sectionType: 'submission-form', + collapsed: false, + enabled: true, + data: {}, + errors: [], + formId: '2_traditionalpageone', + isLoading: false, + isValid: false + } as any, + traditionalpagetwo: { + header: 'submit.progressbar.describe.steptwo', + config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo', + mandatory: false, + sectionType: 'submission-form', + collapsed: false, + enabled: false, + data: {}, + errors: [], + isLoading: false, + isValid: false + } as any, + license: { + header: 'submit.progressbar.license', + config: '', + mandatory: true, + sectionType: 'license', + visibility: { + main: null, + other: 'READONLY' + }, + collapsed: false, + enabled: true, + data: {}, + errors: [], + isLoading: false, + isValid: false + } as any + }, + isLoading: false, + savePending: false, + depositPending: false + } +}); + export const mockSectionsState = Object.assign({}, { extraction: { config: '', diff --git a/src/app/shared/uploader/uploader.component.ts b/src/app/shared/uploader/uploader.component.ts index 0e19c38b55..a0dd0e5bba 100644 --- a/src/app/shared/uploader/uploader.component.ts +++ b/src/app/shared/uploader/uploader.component.ts @@ -1,29 +1,16 @@ -import { - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - EventEmitter, - HostListener, - Input, - Output, - ViewEncapsulation, -} from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostListener, Input, Output, ViewEncapsulation, } from '@angular/core'; import { of as observableOf } from 'rxjs'; import { FileUploader } from 'ng2-file-upload'; import { uniqueId } from 'lodash'; -import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; +import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; import { UploaderOptions } from './uploader-options.model'; import { hasValue, isNotEmpty, isUndefined } from '../empty.util'; import { UploaderService } from './uploader.service'; import { UploaderProperties } from './uploader-properties.model'; import { HttpXsrfTokenExtractor } from '@angular/common/http'; -import { - XSRF_REQUEST_HEADER, - XSRF_RESPONSE_HEADER, - XSRF_COOKIE -} from '../../core/xsrf/xsrf.interceptor'; +import { XSRF_COOKIE, XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER } from '../../core/xsrf/xsrf.interceptor'; import { CookieService } from '../../core/services/cookie.service'; @Component({ @@ -146,12 +133,6 @@ export class UploaderComponent { this.uploader.options.headers = [{ name: XSRF_REQUEST_HEADER, value: this.tokenExtractor.getToken() }]; this.onBeforeUpload(); this.isOverDocumentDropZone = observableOf(false); - - // Move page target to the uploader - const config: ScrollToConfigOptions = { - target: this.uploaderId - }; - this.scrollToService.scrollTo(config); }; if (hasValue(this.uploadProperties)) { this.uploader.onBuildItemForm = (item, form) => { diff --git a/src/app/submission/form/submission-form.component.html b/src/app/submission/form/submission-form.component.html index 7376b1e10b..33b5d4be12 100644 --- a/src/app/submission/form/submission-form.component.html +++ b/src/app/submission/form/submission-form.component.html @@ -1,35 +1,36 @@
-
- -
-
-
-
- - -
-
- - -
-
+
+
+ +
+
-
- - - - -
- +
+ + +
+
+ + +
+
+ +
+ + + + +
+
diff --git a/src/app/submission/form/submission-form.component.spec.ts b/src/app/submission/form/submission-form.component.spec.ts index d719472adf..dd8e6d0ea3 100644 --- a/src/app/submission/form/submission-form.component.spec.ts +++ b/src/app/submission/form/submission-form.component.spec.ts @@ -24,7 +24,7 @@ import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-servic import { createTestComponent } from '../../shared/testing/utils.test'; import { Item } from '../../core/shared/item.model'; import { TestScheduler } from 'rxjs/testing'; - +import { SectionsService } from '../sections/sections.service'; describe('SubmissionFormComponent Component', () => { @@ -55,6 +55,7 @@ describe('SubmissionFormComponent Component', () => { { provide: AuthService, useClass: AuthServiceStub }, { provide: HALEndpointService, useValue: new HALEndpointServiceStub('workspaceitems') }, { provide: SubmissionService, useValue: submissionServiceStub }, + { provide: SectionsService, useValue: { isSectionTypeAvailable: () => observableOf(true) } }, ChangeDetectorRef, SubmissionFormComponent ], @@ -115,7 +116,7 @@ describe('SubmissionFormComponent Component', () => { expect(compAsAny.submissionSections).toBeUndefined(); expect(compAsAny.subs).toEqual([]); expect(submissionServiceStub.startAutoSave).not.toHaveBeenCalled(); - expect(comp.loading).toBeObservable(cold('(a|)', {a: true})); + expect(comp.loading).toBeObservable(cold('(a|)', { a: true })); done(); }); @@ -140,7 +141,7 @@ describe('SubmissionFormComponent Component', () => { }); scheduler.flush(); - expect(comp.submissionSections).toBeObservable(cold('(a|)', {a: sectionsList})); + expect(comp.submissionSections).toBeObservable(cold('(a|)', { a: sectionsList })); expect(submissionServiceStub.dispatchInit).toHaveBeenCalledWith( collectionId, @@ -201,7 +202,7 @@ describe('SubmissionFormComponent Component', () => { submissionDefinition: { name: 'traditional' } - } as any); + } as any); fixture.detectChanges(); }); scheduler.flush(); diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index dc6f264d9b..8df0ab1658 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -15,6 +15,8 @@ import { SubmissionObjectEntry } from '../objects/submission-objects.reducer'; import { SectionDataObject } from '../sections/models/section-data.model'; import { SubmissionService } from '../submission.service'; import { Item } from '../../core/shared/item.model'; +import { SectionsType } from '../sections/sections-type'; +import { SectionsService } from '../sections/sections.service'; /** * This component represents the submission form. @@ -69,6 +71,11 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { */ public loading: Observable = observableOf(true); + /** + * Emits true when the submission config has bitstream uploading enabled in submission + */ + public uploadEnabled$: Observable; + /** * Observable of the list of submission's sections * @type {Observable} @@ -100,12 +107,14 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { * @param {ChangeDetectorRef} changeDetectorRef * @param {HALEndpointService} halService * @param {SubmissionService} submissionService + * @param {SectionsService} sectionsService */ constructor( private authService: AuthService, private changeDetectorRef: ChangeDetectorRef, private halService: HALEndpointService, - private submissionService: SubmissionService) { + private submissionService: SubmissionService, + private sectionsService: SectionsService) { this.isActive = true; } @@ -129,6 +138,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { return observableOf([]); } })); + this.uploadEnabled$ = this.sectionsService.isSectionTypeAvailable(this.submissionId, SectionsType.Upload); // check if is submission loading this.loading = this.submissionService.getSubmissionObject(this.submissionId).pipe( diff --git a/src/app/submission/sections/sections.service.spec.ts b/src/app/submission/sections/sections.service.spec.ts index 6bdf26a082..0d63beeaea 100644 --- a/src/app/submission/sections/sections.service.spec.ts +++ b/src/app/submission/sections/sections.service.spec.ts @@ -1,4 +1,4 @@ -import { waitForAsync, TestBed } from '@angular/core/testing'; +import { TestBed, waitForAsync } from '@angular/core/testing'; import { cold, getTestScheduler } from 'jasmine-marbles'; import { of as observableOf } from 'rxjs'; @@ -17,7 +17,8 @@ import { SectionsService } from './sections.service'; import { mockSectionsData, mockSectionsErrors, - mockSubmissionState + mockSubmissionState, + mockSubmissionStateWithoutUpload } from '../../shared/mocks/submission.mock'; import { DisableSectionAction, @@ -27,11 +28,7 @@ import { SectionStatusChangeAction, UpdateSectionDataAction } from '../objects/submission-objects.actions'; -import { - FormAddError, - FormClearErrorsAction, - FormRemoveErrorAction -} from '../../shared/form/form.actions'; +import { FormAddError, FormClearErrorsAction, FormRemoveErrorAction } from '../../shared/form/form.actions'; import parseSectionErrors from '../utils/parseSectionErrors'; import { SubmissionScopeType } from '../../core/submission/submission-scope-type'; import { SubmissionSectionError } from '../objects/submission-objects.reducer'; @@ -52,6 +49,7 @@ describe('SectionsService test suite', () => { const sectionErrors: any = parseSectionErrors(mockSectionsErrors); const sectionData: any = mockSectionsData; const submissionState: any = Object.assign({}, mockSubmissionState[submissionId]); + const submissionStateWithoutUpload: any = Object.assign({}, mockSubmissionStateWithoutUpload[submissionId]); const sectionState: any = Object.assign({}, mockSubmissionState['826'].sections[sectionId]); const store: any = jasmine.createSpyObj('store', { @@ -314,6 +312,28 @@ describe('SectionsService test suite', () => { }); }); + describe('isSectionTypeAvailable', () => { + it('should return an observable of true when section is available', () => { + store.select.and.returnValue(observableOf(submissionState)); + + const expected = cold('(b|)', { + b: true + }); + + expect(service.isSectionTypeAvailable(submissionId, SectionsType.Upload)).toBeObservable(expected); + }); + + it('should return an observable of false when section is not available', () => { + store.select.and.returnValue(observableOf(submissionStateWithoutUpload)); + + const expected = cold('(b|)', { + b: false + }); + + expect(service.isSectionAvailable(submissionId, SectionsType.Upload)).toBeObservable(expected); + }); + }); + describe('addSection', () => { it('should dispatch a new EnableSectionAction a move target to new section', () => { diff --git a/src/app/submission/sections/sections.service.ts b/src/app/submission/sections/sections.service.ts index b2bc0e4f98..d8d1491cb7 100644 --- a/src/app/submission/sections/sections.service.ts +++ b/src/app/submission/sections/sections.service.ts @@ -5,7 +5,7 @@ import { distinctUntilChanged, filter, map, take } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to'; -import { isEqual } from 'lodash'; +import { findKey, isEqual } from 'lodash'; import { SubmissionState } from '../submission.reducers'; import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empty.util'; @@ -291,14 +291,14 @@ export class SectionsService { } /** - * Check if a given section is a read only available + * Check if a given section id is present in the list of sections * * @param submissionId * The submission id * @param sectionId * The section id * @return Observable - * Emits true whenever a given section should be available + * Emits true whenever a given section id should be available */ public isSectionAvailable(submissionId: string, sectionId: string): Observable { return this.store.select(submissionObjectFromIdSelector(submissionId)).pipe( @@ -309,6 +309,25 @@ export class SectionsService { distinctUntilChanged()); } + /** + * Check if a given section type is present in the list of sections + * + * @param submissionId + * The submission id + * @param sectionType + * The section type + * @return Observable + * Emits true whenever a given section type should be available + */ + public isSectionTypeAvailable(submissionId: string, sectionType: SectionsType): Observable { + return this.store.select(submissionObjectFromIdSelector(submissionId)).pipe( + filter((submissionState: SubmissionObjectEntry) => isNotUndefined(submissionState)), + map((submissionState: SubmissionObjectEntry) => { + return isNotUndefined(submissionState.sections) && isNotUndefined(findKey(submissionState.sections, {sectionType: sectionType})); + }), + distinctUntilChanged()); + } + /** * Dispatch a new [EnableSectionAction] to add a new section and move page target to it * From 73319533d1b8ced458e754b74714669abe4d44ba Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Tue, 6 Apr 2021 16:36:01 +0200 Subject: [PATCH 14/14] Implement feedback --- .../epeople-registry.component.spec.ts | 6 +-- .../epeople-registry.component.ts | 6 +-- .../eperson-form.component.spec.ts | 6 +-- .../eperson-form/eperson-form.component.ts | 2 +- .../members-list.component.spec.ts | 7 +-- .../members-list/members-list.component.ts | 2 +- .../subgroups-list.component.spec.ts | 7 +-- .../subgroup-list/subgroups-list.component.ts | 2 +- .../groups-registry.component.spec.ts | 7 +-- .../groups-registry.component.ts | 2 +- src/app/core/pagination/pagination.service.ts | 10 ++-- .../pagination/pagination.component.spec.ts | 3 +- .../eperson-group-list.component.ts | 4 +- .../search-form/search-form.component.ts | 3 +- .../search-facet-option.component.spec.ts | 4 +- ...earch-facet-range-option.component.spec.ts | 2 +- ...ch-facet-selected-option.component.spec.ts | 4 +- .../shared/testing/pagination-service.stub.ts | 2 +- ...ion-import-external-searchbar.component.ts | 5 +- .../submission-import-external.component.ts | 51 ++++++++++++------- 20 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts b/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts index 29baba4409..bcf7e8f1d9 100644 --- a/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts +++ b/src/app/access-control/epeople-registry/epeople-registry.component.spec.ts @@ -25,10 +25,8 @@ import { NotificationsServiceStub } from '../../shared/testing/notifications-ser import { RouterStub } from '../../shared/testing/router.stub'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { RequestService } from '../../core/data/request.service'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { PaginationService } from '../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('EPeopleRegistryComponent', () => { let component: EPeopleRegistryComponent; diff --git a/src/app/access-control/epeople-registry/epeople-registry.component.ts b/src/app/access-control/epeople-registry/epeople-registry.component.ts index 3ec8efa940..b99304d037 100644 --- a/src/app/access-control/epeople-registry/epeople-registry.component.ts +++ b/src/app/access-control/epeople-registry/epeople-registry.component.ts @@ -20,7 +20,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { RequestService } from '../../core/data/request.service'; import { PageInfo } from '../../core/shared/page-info.model'; import { NoContent } from '../../core/shared/NoContent.model'; -import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationService } from '../../core/pagination/pagination.service'; @Component({ selector: 'ds-epeople-registry', @@ -157,14 +157,14 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { const query: string = data.query; const scope: string = data.scope; if (query != null && this.currentSearchQuery !== query) { - this.router.navigate(this.epersonService.getEPeoplePageRouterLink(), { + this.router.navigate([this.epersonService.getEPeoplePageRouterLink()], { queryParamsHandling: 'merge' }); this.currentSearchQuery = query; this.paginationService.resetPage(this.config.id); } if (scope != null && this.currentSearchScope !== scope) { - this.router.navigate(this.epersonService.getEPeoplePageRouterLink(), { + this.router.navigate([this.epersonService.getEPeoplePageRouterLink()], { queryParamsHandling: 'merge' }); this.currentSearchScope = scope; diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts index 66f633ceef..832f4f6ce5 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.spec.ts @@ -26,10 +26,8 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati import { GroupDataService } from '../../../core/eperson/group-data.service'; import { createPaginatedList } from '../../../shared/testing/utils.test'; import { RequestService } from '../../../core/data/request.service'; -import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model'; -import { PaginationService } from '../../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; +import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; describe('EPersonFormComponent', () => { let component: EPersonFormComponent; diff --git a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts index faf3b34454..11c117ef55 100644 --- a/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -31,7 +31,7 @@ import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/c import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { RequestService } from '../../../core/data/request.service'; import { NoContent } from '../../../core/shared/NoContent.model'; -import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { PaginationService } from '../../../core/pagination/pagination.service'; @Component({ selector: 'ds-eperson-form', diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts index 186cfb713b..0b19b17100 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.spec.ts @@ -26,11 +26,8 @@ import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock'; import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; import { RouterMock } from '../../../../shared/mocks/router.mock'; -import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model'; -import { FindListOptions } from '../../../../../core/data/request.models'; -import { PaginationService } from '../../../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; describe('MembersListComponent', () => { let component: MembersListComponent; diff --git a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts index b4032520e0..54d144da51 100644 --- a/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts +++ b/src/app/access-control/group-registry/group-form/members-list/members-list.component.ts @@ -23,8 +23,8 @@ import { } from '../../../../core/shared/operators'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; -import { PaginationService } from '../../../../../core/pagination/pagination.service'; import {EpersonDtoModel} from '../../../../core/eperson/models/eperson-dto.model'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; /** * Keys to keep track of specific subscriptions diff --git a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts index af54a60da6..bee5126e09 100644 --- a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts +++ b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.spec.ts @@ -35,11 +35,8 @@ import { getMockTranslateService } from '../../../../shared/mocks/translate.serv import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock'; import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; import { map } from 'rxjs/operators'; -import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model'; -import { FindListOptions } from '../../../../../core/data/request.models'; -import { PaginationService } from '../../../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; describe('SubgroupsListComponent', () => { let component: SubgroupsListComponent; diff --git a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts index 1aee7048f7..6d8285f10b 100644 --- a/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts +++ b/src/app/access-control/group-registry/group-form/subgroup-list/subgroups-list.component.ts @@ -16,7 +16,7 @@ import { import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model'; import { NoContent } from '../../../../core/shared/NoContent.model'; -import { PaginationService } from '../../../../../core/pagination/pagination.service'; +import { PaginationService } from '../../../../core/pagination/pagination.service'; /** * Keys to keep track of specific subscriptions diff --git a/src/app/access-control/group-registry/groups-registry.component.spec.ts b/src/app/access-control/group-registry/groups-registry.component.spec.ts index b0b954c4e4..10064800e1 100644 --- a/src/app/access-control/group-registry/groups-registry.component.spec.ts +++ b/src/app/access-control/group-registry/groups-registry.component.spec.ts @@ -28,11 +28,8 @@ import { TranslateLoaderMock } from '../../shared/testing/translate-loader.mock' import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; import { routeServiceStub } from '../../shared/testing/route-service.stub'; import { RouterMock } from '../../shared/mocks/router.mock'; -import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model'; -import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model'; -import { FindListOptions } from '../../../core/data/request.models'; -import { PaginationService } from '../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; describe('GroupRegistryComponent', () => { let component: GroupsRegistryComponent; diff --git a/src/app/access-control/group-registry/groups-registry.component.ts b/src/app/access-control/group-registry/groups-registry.component.ts index f7834949e0..b28ac043d9 100644 --- a/src/app/access-control/group-registry/groups-registry.component.ts +++ b/src/app/access-control/group-registry/groups-registry.component.ts @@ -34,7 +34,7 @@ import { hasValue } from '../../shared/empty.util'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; import { NoContent } from '../../core/shared/NoContent.model'; -import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginationService } from '../../core/pagination/pagination.service'; @Component({ selector: 'ds-groups-registry', diff --git a/src/app/core/pagination/pagination.service.ts b/src/app/core/pagination/pagination.service.ts index b6ae304491..dae6991834 100644 --- a/src/app/core/pagination/pagination.service.ts +++ b/src/app/core/pagination/pagination.service.ts @@ -18,10 +18,10 @@ import { isNumeric } from 'rxjs/internal-compatibility'; * Service to manage the pagination of different components * The pagination information will be stored in the route based on a paginationID. * The following params are used for the different kind of pagination information: - * - For the page: p.{paginationID} - * - For the page size: rpp.{paginationID} - * - For the sort direction: sd.{paginationID} - * - For the sort field: sf.{paginationID} + * - For the page: {paginationID}.p + * - For the page size: {paginationID}.rpp + * - For the sort direction: {paginationID}.sd + * - For the sort field: {paginationID}.sf */ export class PaginationService { @@ -145,7 +145,6 @@ export class PaginationService { if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams) || isNotEmpty(this.clearParams)) { const queryParams = Object.assign({}, this.clearParams, currentParametersWithIdName, parametersWithIdName, extraParams); - console.log(queryParams, this.clearParams); if (retainScrollPosition) { this.router.navigate(url, { queryParams: queryParams, @@ -159,7 +158,6 @@ export class PaginationService { }); } this.clearParams = {}; - console.log('postcear', this.clearParams); } }); } diff --git a/src/app/shared/pagination/pagination.component.spec.ts b/src/app/shared/pagination/pagination.component.spec.ts index 3c50f66158..cf2d1c13fd 100644 --- a/src/app/shared/pagination/pagination.component.spec.ts +++ b/src/app/shared/pagination/pagination.component.spec.ts @@ -127,7 +127,8 @@ describe('Pagination component', () => { // waitForAsync beforeEach beforeEach(waitForAsync(() => { activatedRouteStub = new MockActivatedRoute(); - routerStub = new RouterMock(); hostWindowServiceStub = new HostWindowServiceMock(_initialState.width); + routerStub = new RouterMock(); + hostWindowServiceStub = new HostWindowServiceMock(_initialState.width); currentPagination = new BehaviorSubject(pagination); currentSort = new BehaviorSubject(sort); diff --git a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts index 8605033b2e..11b5b5e7b3 100644 --- a/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts +++ b/src/app/shared/resource-policies/form/eperson-group-list/eperson-group-list.component.ts @@ -186,7 +186,9 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { this.subs.push(search$.pipe(getFirstCompletedRemoteData()) .subscribe((list: RemoteData>) => { - this.list$.next(list); + if (hasValue(this.list$)) { + this.list$.next(list); + } }) ); }); diff --git a/src/app/shared/search-form/search-form.component.ts b/src/app/shared/search-form/search-form.component.ts index fd1abde057..2791aee378 100644 --- a/src/app/shared/search-form/search-form.component.ts +++ b/src/app/shared/search-form/search-form.component.ts @@ -95,7 +95,8 @@ export class SearchFormComponent { */ updateSearch(data: any) { const queryParams = Object.assign({}, data); - queryParams[`page.${this.searchConfig.paginationID}`] = 1; + const pageParam = this.paginationService.getPageParam(this.searchConfig.paginationID); + queryParams[pageParam] = 1; this.router.navigate(this.getSearchLinkParts(), { queryParams: queryParams, diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts index a266e4e425..7299a39c32 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-option/search-facet-option.component.spec.ts @@ -140,7 +140,7 @@ describe('SearchFacetOptionComponent', () => { (comp as any).updateAddParams(selectedValues); expect(comp.addQueryParams).toEqual({ [mockFilterConfig.paramName]: [`${value1},${operator}`, value.value + ',equals'], - ['page.page-id']: 1 + ['page-id.page']: 1 }); }); }); @@ -155,7 +155,7 @@ describe('SearchFacetOptionComponent', () => { (comp as any).updateAddParams(selectedValues); expect(comp.addQueryParams).toEqual({ [mockAuthorityFilterConfig.paramName]: [value1 + ',equals', `${value2},${operator}`], - ['page.page-id']: 1 + ['page-id.page']: 1 }); }); }); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts index 2c93b0186b..9ed8dee0ea 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-range-option/search-facet-range-option.component.spec.ts @@ -126,7 +126,7 @@ describe('SearchFacetRangeOptionComponent', () => { expect(comp.changeQueryParams).toEqual({ [mockFilterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: ['50'], [mockFilterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: ['60'], - ['page.page-id']: 1 + ['page-id.page']: 1 }); }); }); diff --git a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts index cbb6672916..8f422b41bf 100644 --- a/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-facet-filter-options/search-facet-selected-option/search-facet-selected-option.component.spec.ts @@ -165,7 +165,7 @@ describe('SearchFacetSelectedOptionComponent', () => { (comp as any).updateRemoveParams(selectedValues); expect(comp.removeQueryParams).toEqual({ [mockFilterConfig.paramName]: [value1], - ['page.page-id']: 1 + ['page-id.page']: 1 }); }); }); @@ -181,7 +181,7 @@ describe('SearchFacetSelectedOptionComponent', () => { (comp as any).updateRemoveParams(selectedAuthorityValues); expect(comp.removeQueryParams).toEqual({ [mockAuthorityFilterConfig.paramName]: [`${value1},${operator}`], - ['page.page-id']: 1 + ['page-id.page']: 1 }); }); }); diff --git a/src/app/shared/testing/pagination-service.stub.ts b/src/app/shared/testing/pagination-service.stub.ts index cd24808161..985a5bfc4a 100644 --- a/src/app/shared/testing/pagination-service.stub.ts +++ b/src/app/shared/testing/pagination-service.stub.ts @@ -20,6 +20,6 @@ export class PaginationServiceStub { updateRouteWithUrl = jasmine.createSpy('updateRouteWithUrl'); clearPagination = jasmine.createSpy('clearPagination'); getRouteParameterValue = jasmine.createSpy('getRouteParameterValue').and.returnValue(observableOf('')); - getPageParam = jasmine.createSpy('getPageParam').and.returnValue(`page.${this.pagination.id}`); + getPageParam = jasmine.createSpy('getPageParam').and.returnValue(`${this.pagination.id}.page`); } diff --git a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts index 5e26df829c..30f5184d57 100644 --- a/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts +++ b/src/app/submission/import-external/import-external-searchbar/submission-import-external-searchbar.component.ts @@ -18,7 +18,7 @@ import { RemoteData } from '../../../core/data/remote-data'; import { PageInfo } from '../../../core/shared/page-info.model'; import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils'; import { FindListOptions } from '../../../core/data/request.models'; -import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; +import { getFirstSucceededRemoteData, getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; import { HostWindowService } from '../../../shared/host-window.service'; import { hasValue } from '../../../shared/empty.util'; @@ -124,7 +124,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit, OnDes const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); return observableOf(paginatedListRD); }), - getFirstSucceededRemoteDataPayload() + getFirstSucceededRemoteDataPayload(), ).subscribe((externalSource: PaginatedList) => { externalSource.page.forEach((element) => { this.sourceList.push({ id: element.id, name: element.name }); @@ -166,6 +166,7 @@ export class SubmissionImportExternalSearchbarComponent implements OnInit, OnDes const paginatedListRD = createSuccessfulRemoteDataObject(paginatedList); return observableOf(paginatedListRD); }), + getFirstSucceededRemoteData(), tap(() => this.sourceListLoading = false) ).subscribe((externalSource: RemoteData>) => { externalSource.payload.page.forEach((element) => { diff --git a/src/app/submission/import-external/submission-import-external.component.ts b/src/app/submission/import-external/submission-import-external.component.ts index fe568533e4..e8370a9be0 100644 --- a/src/app/submission/import-external/submission-import-external.component.ts +++ b/src/app/submission/import-external/submission-import-external.component.ts @@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { BehaviorSubject, combineLatest, Subscription } from 'rxjs'; -import { filter, mergeMap, switchMap, take } from 'rxjs/operators'; +import { filter, mergeMap, switchMap, take, tap } from 'rxjs/operators'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { ExternalSourceService } from '../../core/data/external-source.service'; @@ -45,7 +45,10 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { */ public isLoading$: BehaviorSubject = new BehaviorSubject(false); - public reload$: BehaviorSubject<{query: string, source: string}> = new BehaviorSubject<{query: string; source: string}>({query: '', source: ''}); + public reload$: BehaviorSubject<{ query: string, source: string }> = new BehaviorSubject<{ query: string; source: string }>({ + query: '', + source: '' + }); /** * Configuration to use for the import buttons */ @@ -83,6 +86,8 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { */ protected subs: Subscription[] = []; + private retrieveExternalSourcesSub: Subscription; + /** * Initialize the component variables. * @param {SearchConfigurationService} searchConfigService @@ -108,7 +113,7 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { this.listId = 'list-submission-external-sources'; this.context = Context.EntitySearchModalWithNameVariants; this.repeatable = false; - this.routeData = { sourceId: '', query: '' }; + this.routeData = {sourceId: '', query: ''}; this.importConfig = { buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label }; @@ -133,10 +138,13 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { this.router.navigate( [], { - queryParams: { source: event.sourceId, query: event.query }, + queryParams: {source: event.sourceId, query: event.query}, replaceUrl: true } - ).then(() => this.reload$.next({source: event.sourceId, query: event.query})); + ).then(() => { + this.reload$.next({source: event.sourceId, query: event.query}); + this.retrieveExternalSources(); + }); } /** @@ -158,6 +166,10 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { this.subs .filter((sub) => hasValue(sub)) .forEach((sub) => sub.unsubscribe()); + if (hasValue(this.retrieveExternalSourcesSub)) { + this.retrieveExternalSourcesSub.unsubscribe(); + } + } /** @@ -167,22 +179,23 @@ export class SubmissionImportExternalComponent implements OnInit, OnDestroy { * @param query The query string to search */ private retrieveExternalSources(): void { - this.reload$.pipe( - switchMap( - (sourceQueryObject: { source: string, query: string }) => { + if (hasValue(this.retrieveExternalSourcesSub)) { + this.retrieveExternalSourcesSub.unsubscribe(); + } + this.retrieveExternalSourcesSub = this.reload$.pipe( + filter((sourceQueryObject: { source: string, query: string }) => isNotEmpty(sourceQueryObject.source) && isNotEmpty(sourceQueryObject.query)), + switchMap((sourceQueryObject: { source: string, query: string }) => { const source = sourceQueryObject.source; const query = sourceQueryObject.query; - if (isNotEmpty(source) && isNotEmpty(query)) { - this.routeData.sourceId = source; - this.routeData.query = query; - this.isLoading$.next(true); - return this.searchConfigService.paginatedSearchOptions.pipe( - filter((searchOptions) => searchOptions.query === query), - mergeMap((searchOptions) => this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions).pipe( - getFinishedRemoteData(), - )), - ); - } + this.routeData.sourceId = source; + this.routeData.query = query; + return this.searchConfigService.paginatedSearchOptions.pipe( + tap((v) => this.isLoading$.next(true)), + filter((searchOptions) => searchOptions.query === query), + mergeMap((searchOptions) => this.externalService.getExternalSourceEntries(this.routeData.sourceId, searchOptions).pipe( + getFinishedRemoteData(), + )), + ); } ), ).subscribe((rdData) => {