76654: Feedback to pagination

This commit is contained in:
Yana De Pauw
2021-02-23 11:01:40 +01:00
parent fab226912f
commit d07f44ac41
31 changed files with 184 additions and 116 deletions

View File

@@ -254,8 +254,10 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
*/ */
ngOnDestroy(): void { ngOnDestroy(): void {
this.cleanupSubscribes(); this.cleanupSubscribes();
this.paginationService.clearPagination(this.config.id);
} }
cleanupSubscribes() { cleanupSubscribes() {
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
} }

View File

@@ -489,8 +489,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
ngOnDestroy(): void { ngOnDestroy(): void {
this.onCancel(); this.onCancel();
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); 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 * This method will ensure that the page gets reset and that the cache is cleared
*/ */

View File

@@ -17,9 +17,8 @@ import { GroupDataService } from '../../../../../core/eperson/group-data.service
import { EPerson } from '../../../../../core/eperson/models/eperson.model'; import { EPerson } from '../../../../../core/eperson/models/eperson.model';
import { Group } from '../../../../../core/eperson/models/group.model'; import { Group } from '../../../../../core/eperson/models/group.model';
import { import {
getFirstCompletedRemoteData,
getFirstSucceededRemoteData, getFirstSucceededRemoteData,
getFirstCompletedRemoteData, getAllCompletedRemoteData getFirstCompletedRemoteData, getAllCompletedRemoteData, getRemoteDataPayload
} from '../../../../../core/shared/operators'; } from '../../../../../core/shared/operators';
import { NotificationsService } from '../../../../../shared/notifications/notifications.service'; import { NotificationsService } from '../../../../../shared/notifications/notifications.service';
import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model'; 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 * @param data Contains scope and query param
*/ */
search(data: any) { 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.unsubFrom(SubKey.SearchResultsDTO);
this.subs.set(SubKey.SearchResultsDTO, this.subs.set(SubKey.SearchResultsDTO,
this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe( this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe(
switchMap((paginationOptions) => { switchMap((paginationOptions) => {
this.ePersonDataService.searchByScope(this.currentSearchScope, this.currentSearchQuery, {
currentPage: this.configSearch.currentPage, const query: string = data.query;
elementsPerPage: this.configSearch.pageSize const scope: string = data.scope;
}, false) 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(), getAllCompletedRemoteData(),
map((rd: RemoteData<any>) => { map((rd: RemoteData<any>) => {
@@ -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 * Shows a notification based on the success/failure of the request
* @param messageSuffix Suffix for message * @param messageSuffix Suffix for message

View File

@@ -244,6 +244,8 @@ export class SubgroupsListComponent implements OnInit, OnDestroy {
for (const key of this.subs.keys()) { for (const key of this.subs.keys()) {
this.unsubFrom(key); this.unsubFrom(key);
} }
this.paginationService.clearPagination(this.config.id);
this.paginationService.clearPagination(this.configSearch.id);
} }
/** /**

View File

@@ -255,12 +255,16 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
*/ */
ngOnDestroy(): void { ngOnDestroy(): void {
this.cleanupSubscribes(); this.cleanupSubscribes();
this.paginationService.clearPagination(this.config.id);
} }
cleanupSubscribes() { cleanupSubscribes() {
if (hasValue(this.paginationSub)) { if (hasValue(this.paginationSub)) {
this.paginationSub.unsubscribe(); this.paginationSub.unsubscribe();
} }
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
this.paginationService.clearPagination(this.config.id);
} }
} }

View File

@@ -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 { combineLatest as observableCombineLatest, Observable, zip } from 'rxjs';
import { RemoteData } from '../../../core/data/remote-data'; import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list.model'; import { PaginatedList } from '../../../core/data/paginated-list.model';
@@ -21,7 +21,7 @@ import { PaginationService } from '../../../core/pagination/pagination.service';
selector: 'ds-bitstream-formats', selector: 'ds-bitstream-formats',
templateUrl: './bitstream-formats.component.html' 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 * 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 * 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);
}
} }

View File

@@ -174,4 +174,8 @@ export class MetadataRegistryComponent {
} }
}); });
} }
ngOnDestroy(): void {
this.paginationService.clearPagination(this.config.id);
}
} }

View File

@@ -208,4 +208,8 @@ export class MetadataSchemaComponent implements OnInit {
} }
}); });
} }
ngOnDestroy(): void {
this.paginationService.clearPagination(this.config.id);
}
} }

View File

@@ -208,8 +208,10 @@ export class BrowseByMetadataPageComponent implements OnInit {
ngOnDestroy(): void { ngOnDestroy(): void {
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
this.paginationService.clearPagination(this.paginationConfig.id);
} }
} }
/** /**

View File

@@ -108,4 +108,9 @@ export class CollectionPageComponent implements OnInit {
return isNotEmpty(object); return isNotEmpty(object);
} }
ngOnDestroy(): void {
this.paginationService.clearPagination(this.paginationConfig.id);
}
} }

View File

@@ -75,4 +75,9 @@ export class CommunityPageSubCollectionListComponent implements OnInit {
this.subCollectionsRDObs.next(results); this.subCollectionsRDObs.next(results);
}); });
} }
ngOnDestroy(): void {
this.paginationService.clearPagination(this.config.id);
}
} }

View File

@@ -87,4 +87,9 @@ export class CommunityPageSubCommunityListComponent implements OnInit {
this.subCommunitiesRDObs.next(results); this.subCommunitiesRDObs.next(results);
}); });
} }
ngOnDestroy(): void {
this.paginationService.clearPagination(this.config.id);
}
} }

View File

@@ -98,5 +98,7 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy {
*/ */
ngOnDestroy() { ngOnDestroy() {
this.unsubscribe(); this.unsubscribe();
this.paginationService.clearPagination(this.config.id);
} }
} }

View File

@@ -8,8 +8,7 @@
[paginationOptions]="originalOptions" [paginationOptions]="originalOptions"
[pageInfoState]="originals" [pageInfoState]="originals"
[collectionSize]="originals?.totalElements" [collectionSize]="originals?.totalElements"
[disableRouteParameterUpdate]="true" [retainScrollPosition]="true">
(pageChange)="switchOriginalPage($event)">
<div class="file-section row" *ngFor="let file of originals?.page;"> <div class="file-section row" *ngFor="let file of originals?.page;">
@@ -51,8 +50,7 @@
[paginationOptions]="licenseOptions" [paginationOptions]="licenseOptions"
[pageInfoState]="licenses" [pageInfoState]="licenses"
[collectionSize]="licenses?.totalElements" [collectionSize]="licenses?.totalElements"
[disableRouteParameterUpdate]="true" [retainScrollPosition]="true">
(pageChange)="switchLicensePage($event)">
<div class="file-section row" *ngFor="let file of licenses?.page;"> <div class="file-section row" *ngFor="let file of licenses?.page;">

View File

@@ -13,6 +13,7 @@ import { switchMap, tap } from 'rxjs/operators';
import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { hasValue, isEmpty } from '../../../../shared/empty.util'; import { hasValue, isEmpty } from '../../../../shared/empty.util';
import { PaginationService } from '../../../../core/pagination/pagination.service';
/** /**
* This component renders the file section of the item * This component renders the file section of the item
@@ -35,23 +36,22 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
pageSize = 5; pageSize = 5;
originalOptions = Object.assign(new PaginationComponentOptions(), { originalOptions = Object.assign(new PaginationComponentOptions(), {
id: 'original-bitstreams-options', id: 'obo',
currentPage: 1, currentPage: 1,
pageSize: this.pageSize pageSize: this.pageSize
}); });
originalCurrentPage$ = new BehaviorSubject<number>(1);
licenseOptions = Object.assign(new PaginationComponentOptions(), { licenseOptions = Object.assign(new PaginationComponentOptions(), {
id: 'license-bitstreams-options', id: 'lbo',
currentPage: 1, currentPage: 1,
pageSize: this.pageSize pageSize: this.pageSize
}); });
licenseCurrentPage$ = new BehaviorSubject<number>(1);
constructor( constructor(
bitstreamDataService: BitstreamDataService, bitstreamDataService: BitstreamDataService,
protected notificationsService: NotificationsService, protected notificationsService: NotificationsService,
protected translateService: TranslateService protected translateService: TranslateService,
protected paginationService: PaginationService
) { ) {
super(bitstreamDataService, notificationsService, translateService); super(bitstreamDataService, notificationsService, translateService);
} }
@@ -61,11 +61,11 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
} }
initialize(): void { initialize(): void {
this.originals$ = this.originalCurrentPage$.pipe( this.originals$ = this.paginationService.getCurrentPagination(this.originalOptions.id, this.originalOptions).pipe(
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName( switchMap((options: PaginationComponentOptions) => this.bitstreamDataService.findAllByItemAndBundleName(
this.item, this.item,
'ORIGINAL', 'ORIGINAL',
{elementsPerPage: this.pageSize, currentPage: pageNumber}, {elementsPerPage: options.pageSize, currentPage: options.currentPage},
true, true,
true, true,
followLink('format') followLink('format')
@@ -78,11 +78,11 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
) )
); );
this.licenses$ = this.licenseCurrentPage$.pipe( this.licenses$ = this.paginationService.getCurrentPagination(this.licenseOptions.id, this.licenseOptions).pipe(
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName( switchMap((options: PaginationComponentOptions) => this.bitstreamDataService.findAllByItemAndBundleName(
this.item, this.item,
'LICENSE', 'LICENSE',
{elementsPerPage: this.pageSize, currentPage: pageNumber}, {elementsPerPage: options.pageSize, currentPage: options.currentPage},
true, true,
true, true,
followLink('format') 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<Bitstream>) { hasValuesInBundle(bundle: PaginatedList<Bitstream>) {
return hasValue(bundle) && !isEmpty(bundle.page); return hasValue(bundle) && !isEmpty(bundle.page);
} }
ngOnDestroy(): void {
this.paginationService.clearPagination(this.originalOptions.id);
this.paginationService.clearPagination(this.licenseOptions.id);
}
} }

View File

@@ -102,7 +102,7 @@ describe('MyDSpaceConfigurationService', () => {
describe('when getCurrentSort is called', () => { describe('when getCurrentSort is called', () => {
beforeEach(() => { beforeEach(() => {
service.getCurrentSort({} as any); // service.getCurrentSort({} as any);
}); });
it('should call getQueryParameterValue on the routeService with parameter name \'sortDirection\'', () => { it('should call getQueryParameterValue on the routeService with parameter name \'sortDirection\'', () => {
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortDirection'); expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortDirection');
@@ -114,7 +114,7 @@ describe('MyDSpaceConfigurationService', () => {
describe('when getCurrentPagination is called', () => { describe('when getCurrentPagination is called', () => {
beforeEach(() => { 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\'', () => { it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => {
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page'); expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page');

View File

@@ -99,17 +99,20 @@ export class PaginationService {
pageSize?: number pageSize?: number
sortField?: string sortField?: string
sortDirection?: SortDirection sortDirection?: SortDirection
}, extraParams?, changeLocationNot?: boolean) { }, extraParams?, retainScrollPosition?: boolean) {
this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => {
const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions);
const parametersWithIdName = this.getParametersWithIdName(paginationId, params); const parametersWithIdName = this.getParametersWithIdName(paginationId, params);
if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) {
const queryParams = Object.assign({}, currentParametersWithIdName, const queryParams = Object.assign({}, currentParametersWithIdName,
parametersWithIdName, extraParams); parametersWithIdName, extraParams);
if (changeLocationNot) { console.log(retainScrollPosition);
this.location.go(this.router.createUrlTree([], { if (retainScrollPosition) {
relativeTo: this.route, queryParams: queryParams, queryParamsHandling: 'merge' this.router.navigate([], {
}).toString()); queryParams: queryParams,
queryParamsHandling: 'merge',
fragment: `p-${paginationId}`
});
} else { } else {
this.router.navigate([], { this.router.navigate([], {
queryParams: queryParams, queryParams: queryParams,
@@ -125,17 +128,20 @@ export class PaginationService {
pageSize?: number pageSize?: number
sortField?: string sortField?: string
sortDirection?: SortDirection sortDirection?: SortDirection
}, extraParams?, changeLocationNot?: boolean) { }, extraParams?, retainScrollPosition?: boolean) {
console.log(retainScrollPosition);
this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => { this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => {
const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions); const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions);
const parametersWithIdName = this.getParametersWithIdName(paginationId, params); const parametersWithIdName = this.getParametersWithIdName(paginationId, params);
if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) { if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams)) {
const queryParams = Object.assign({}, currentParametersWithIdName, const queryParams = Object.assign({}, currentParametersWithIdName,
parametersWithIdName, extraParams); parametersWithIdName, extraParams);
if (changeLocationNot) { if (retainScrollPosition) {
this.location.go(this.router.createUrlTree([], { this.router.navigate(url, {
relativeTo: this.route, queryParams: queryParams, queryParamsHandling: 'merge' queryParams: queryParams,
}).toString()); queryParamsHandling: 'merge',
fragment: `p-${paginationId}`
});
} else { } else {
this.router.navigate(url, { this.router.navigate(url, {
queryParams: queryParams, 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: { getParametersWithIdName(paginationId: string, params: {
page?: number page?: number

View File

@@ -74,5 +74,8 @@ export class ProcessOverviewComponent implements OnInit {
map((eperson: EPerson) => eperson.name) map((eperson: EPerson) => eperson.name)
); );
} }
ngOnDestroy(): void {
this.paginationService.clearPagination(this.pageConfig.id);
}
} }

View File

@@ -8,8 +8,7 @@
[paginationOptions]="options" [paginationOptions]="options"
[pageInfoState]="versions" [pageInfoState]="versions"
[collectionSize]="versions?.totalElements" [collectionSize]="versions?.totalElements"
[disableRouteParameterUpdate]="true" [retainScrollPosition]="true">
(pageChange)="switchPage($event)">
<table class="table table-striped my-2"> <table class="table table-striped my-2">
<thead> <thead>
<tr> <tr>

View File

@@ -13,6 +13,7 @@ import { PaginatedSearchOptions } from '../../search/paginated-search-options.mo
import { AlertType } from '../../alert/aletr-type'; import { AlertType } from '../../alert/aletr-type';
import { followLink } from '../../utils/follow-link-config.model'; import { followLink } from '../../utils/follow-link-config.model';
import { hasValueOperator } from '../../empty.util'; import { hasValueOperator } from '../../empty.util';
import { PaginationService } from '../../../core/pagination/pagination.service';
@Component({ @Component({
selector: 'ds-item-versions', selector: 'ds-item-versions',
@@ -76,17 +77,14 @@ export class ItemVersionsComponent implements OnInit {
* Start at page 1 and always use the set page size * Start at page 1 and always use the set page size
*/ */
options = Object.assign(new PaginationComponentOptions(),{ options = Object.assign(new PaginationComponentOptions(),{
id: 'item-versions-options', id: 'ivo',
currentPage: 1, currentPage: 1,
pageSize: this.pageSize pageSize: this.pageSize
}); });
/** constructor(private versionHistoryService: VersionHistoryDataService,
* The current page being displayed private paginationService: PaginationService
*/ ) {
currentPage$ = new BehaviorSubject<number>(1);
constructor(private versionHistoryService: VersionHistoryDataService) {
} }
/** /**
@@ -105,10 +103,11 @@ export class ItemVersionsComponent implements OnInit {
getRemoteDataPayload(), getRemoteDataPayload(),
hasValueOperator(), hasValueOperator(),
); );
this.versionsRD$ = observableCombineLatest(versionHistory$, this.currentPage$).pipe( const currentPagination = this.paginationService.getCurrentPagination(this.options.id, this.options);
switchMap(([versionHistory, page]: [VersionHistory, number]) => this.versionsRD$ = observableCombineLatest(versionHistory$, currentPagination).pipe(
switchMap(([versionHistory, options]: [VersionHistory, PaginationComponentOptions]) =>
this.versionHistoryService.getVersions(versionHistory.id, 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'))) true, true, followLink('item'), followLink('eperson')))
); );
this.hasEpersons$ = this.versionsRD$.pipe( this.hasEpersons$ = this.versionsRD$.pipe(
@@ -120,13 +119,9 @@ export class ItemVersionsComponent implements OnInit {
); );
} }
/** ngOnDestroy(): void {
* Update the current page this.paginationService.clearPagination(this.options.id);
* @param page
*/
switchPage(page: number) {
this.options.currentPage = page;
this.currentPage$.next(page);
} }
} }

View File

@@ -233,5 +233,6 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
*/ */
ngOnDestroy(): void { ngOnDestroy(): void {
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe()); this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
this.paginationService.clearPagination(this.options.id);
} }
} }

View File

@@ -1,4 +1,4 @@
<div *ngIf="currentPageState == undefined || currentPageState == (currentPage$|async)"> <div *ngIf="currentPageState == undefined || currentPageState == (currentPage$|async)" [id]="'p-' + id">
<div *ngIf="(!hidePaginationDetail && collectionSize > 0) || !hideGear" class="pagination-masked clearfix top"> <div *ngIf="(!hidePaginationDetail && collectionSize > 0) || !hideGear" class="pagination-masked clearfix top">
<div class="row"> <div class="row">
<div *ngIf="!hidePaginationDetail && collectionSize > 0" class="col-auto pagination-info"> <div *ngIf="!hidePaginationDetail && collectionSize > 0" class="col-auto pagination-info">

View File

@@ -20,7 +20,6 @@ import { hasValue } from '../empty.util';
import { PageInfo } from '../../core/shared/page-info.model'; import { PageInfo } from '../../core/shared/page-info.model';
import { PaginationService } from '../../core/pagination/pagination.service'; import { PaginationService } from '../../core/pagination/pagination.service';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { isNumeric } from 'rxjs/internal-compatibility';
/** /**
* The default pagination controls component. * 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 * 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 * parameters won't affect the pagination of this component
*/ */
@Input() public disableRouteParameterUpdate = false; @Input() public retainScrollPosition = false;
/** /**
* Current page. * Current page.
@@ -125,7 +124,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
* ID for the pagination instance. Only useful if you wish to * ID for the pagination instance. Only useful if you wish to
* have more than once instance at a time in a given component. * 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. * 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.checkConfig(this.paginationOptions);
this.initializeConfig(); 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. * Method provided by Angular. Invoked when the instance is destroyed.
@@ -336,11 +326,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
* @param params * @param params
*/ */
private updateParams(params: {}) { private updateParams(params: {}) {
if (!this.disableRouteParameterUpdate) { this.paginationService.updateRoute(this.id, params, {}, this.retainScrollPosition);
this.paginationService.updateRoute(this.id, params);
} else {
this.paginationService.updateRoute(this.id, params, {}, this.disableRouteParameterUpdate);
}
} }
/** /**

View File

@@ -5,7 +5,7 @@
<ds-pagination *ngIf="(getList() | async)?.payload?.totalElements > 0" <ds-pagination *ngIf="(getList() | async)?.payload?.totalElements > 0"
[paginationOptions]="paginationOptions" [paginationOptions]="paginationOptions"
[collectionSize]="(getList() | async)?.payload?.totalElements" [collectionSize]="(getList() | async)?.payload?.totalElements"
[disableRouteParameterUpdate]="true" [retainScrollPosition]="true"
[hideGear]="true"> [hideGear]="true">
<div class="table-responsive"> <div class="table-responsive">

View File

@@ -180,7 +180,6 @@ describe('EpersonGroupListComponent test suite', () => {
it('should update list on page change', () => { it('should update list on page change', () => {
spyOn(comp, 'updateList'); spyOn(comp, 'updateList');
comp.onPageChange(2);
expect(compAsAny.updateList).toHaveBeenCalled(); expect(compAsAny.updateList).toHaveBeenCalled();
}); });
@@ -257,7 +256,6 @@ describe('EpersonGroupListComponent test suite', () => {
it('should update list on page change', () => { it('should update list on page change', () => {
spyOn(comp, 'updateList'); spyOn(comp, 'updateList');
comp.onPageChange(2);
expect(compAsAny.updateList).toHaveBeenCalled(); expect(compAsAny.updateList).toHaveBeenCalled();
}); });

View File

@@ -200,6 +200,8 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy {
this.subs this.subs
.filter((subscription) => hasValue(subscription)) .filter((subscription) => hasValue(subscription))
.forEach((subscription) => subscription.unsubscribe()); .forEach((subscription) => subscription.unsubscribe());
this.paginationService.clearPagination(this.paginationOptions.id);
} }
} }

View File

@@ -10,6 +10,8 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
import { hasValue } from '../../../../../empty.util'; import { hasValue } from '../../../../../empty.util';
import { currentPath } from '../../../../../utils/route.utils'; import { currentPath } from '../../../../../utils/route.utils';
import { getFacetValueForType } from '../../../../search.utils'; import { getFacetValueForType } from '../../../../search.utils';
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
@Component({ @Component({
selector: 'ds-search-facet-option', selector: 'ds-search-facet-option',
@@ -60,10 +62,13 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy {
*/ */
sub: Subscription; sub: Subscription;
paginationId: string;
constructor(protected searchService: SearchService, constructor(protected searchService: SearchService,
protected filterService: SearchFilterService, protected filterService: SearchFilterService,
protected searchConfigService: SearchConfigurationService, 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 * Initializes all observable instance variables and starts listening to them
*/ */
ngOnInit(): void { ngOnInit(): void {
this.paginationId = this.searchConfigService.paginationID;
this.searchLink = this.getSearchLink(); this.searchLink = this.getSearchLink();
this.isVisible = this.isChecked().pipe(map((checked: boolean) => !checked)); this.isVisible = this.isChecked().pipe(map((checked: boolean) => !checked));
this.sub = observableCombineLatest(this.selectedValues$, this.searchConfigService.searchOptions) 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 * @param {string[]} selectedValues The values that are currently selected for this filter
*/ */
private updateAddParams(selectedValues: FacetValue[]): void { private updateAddParams(selectedValues: FacetValue[]): void {
const page = this.paginationService.getPageParam(this.searchConfigService.paginationID);
this.addQueryParams = { this.addQueryParams = {
[this.filterConfig.paramName]: [...selectedValues.map((facetValue: FacetValue) => getFacetValueForType(facetValue, this.filterConfig)), this.getFacetValue()], [this.filterConfig.paramName]: [...selectedValues.map((facetValue: FacetValue) => getFacetValueForType(facetValue, this.filterConfig)), this.getFacetValue()],
page: 1 [page]: 1
}; };
} }

View File

@@ -13,6 +13,7 @@ import {
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
import { hasValue } from '../../../../../empty.util'; import { hasValue } from '../../../../../empty.util';
import { currentPath } from '../../../../../utils/route.utils'; import { currentPath } from '../../../../../utils/route.utils';
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
const rangeDelimiter = '-'; const rangeDelimiter = '-';
@@ -65,7 +66,8 @@ export class SearchFacetRangeOptionComponent implements OnInit, OnDestroy {
constructor(protected searchService: SearchService, constructor(protected searchService: SearchService,
protected filterService: SearchFilterService, protected filterService: SearchFilterService,
protected searchConfigService: SearchConfigurationService, 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 parts = this.filterValue.value.split(rangeDelimiter);
const min = parts.length > 1 ? parts[0].trim() : this.filterValue.value; const min = parts.length > 1 ? parts[0].trim() : this.filterValue.value;
const max = parts.length > 1 ? parts[1].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.changeQueryParams = {
[this.filterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: [min], [this.filterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: [min],
[this.filterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: [max], [this.filterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: [max],
page: 1 [page]: 1
}; };
} }

View File

@@ -9,6 +9,7 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
import { FacetValue } from '../../../../facet-value.model'; import { FacetValue } from '../../../../facet-value.model';
import { currentPath } from '../../../../../utils/route.utils'; import { currentPath } from '../../../../../utils/route.utils';
import { getFacetValueForType } from '../../../../search.utils'; import { getFacetValueForType } from '../../../../search.utils';
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
@Component({ @Component({
selector: 'ds-search-facet-selected-option', selector: 'ds-search-facet-selected-option',
@@ -58,7 +59,8 @@ export class SearchFacetSelectedOptionComponent implements OnInit, OnDestroy {
constructor(protected searchService: SearchService, constructor(protected searchService: SearchService,
protected filterService: SearchFilterService, protected filterService: SearchFilterService,
protected searchConfigService: SearchConfigurationService, 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 * @param {string[]} selectedValues The values that are currently selected for this filter
*/ */
private updateRemoveParams(selectedValues: FacetValue[]): void { private updateRemoveParams(selectedValues: FacetValue[]): void {
const page = this.paginationService.getPageParam(this.searchConfigService.paginationID);
this.removeQueryParams = { this.removeQueryParams = {
[this.filterConfig.paramName]: selectedValues [this.filterConfig.paramName]: selectedValues
.filter((facetValue: FacetValue) => facetValue.label !== this.selectedValue.label) .filter((facetValue: FacetValue) => facetValue.label !== this.selectedValue.label)
.map((facetValue: FacetValue) => this.getFacetValue(facetValue)), .map((facetValue: FacetValue) => this.getFacetValue(facetValue)),
page: 1 [page]: 1
}; };
} }
/** /**
* TODO to review after https://github.com/DSpace/dspace-angular/issues/368 is resolved * TODO to review after https://github.com/DSpace/dspace-angular/issues/368 is resolved
* Retrieve facet value related to facet type * Retrieve facet value related to facet type

View File

@@ -1,10 +1,12 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Params, Router } from '@angular/router'; import { Params, Router } from '@angular/router';
import { map } from 'rxjs/operators'; import { map, take } from 'rxjs/operators';
import { hasValue, isNotEmpty } from '../../../empty.util'; import { hasValue, isNotEmpty } from '../../../empty.util';
import { SearchService } from '../../../../core/shared/search/search.service'; import { SearchService } from '../../../../core/shared/search/search.service';
import { currentPath } from '../../../utils/route.utils'; import { currentPath } from '../../../utils/route.utils';
import { PaginationService } from '../../../../core/pagination/pagination.service';
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
@Component({ @Component({
selector: 'ds-search-label', selector: 'ds-search-label',
@@ -32,6 +34,8 @@ export class SearchLabelComponent implements OnInit {
*/ */
constructor( constructor(
private searchService: SearchService, private searchService: SearchService,
private paginationService: PaginationService,
private searchConfigurationService: SearchConfigurationService,
private router: Router) { private router: Router) {
} }
@@ -50,9 +54,10 @@ export class SearchLabelComponent implements OnInit {
map((filters) => { map((filters) => {
const field: string = Object.keys(filters).find((f) => f === this.key); 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 newValues = hasValue(filters[field]) ? filters[field].filter((v) => v !== this.value) : null;
const page = this.paginationService.getPageParam(this.searchConfigurationService.paginationID);
return { return {
[field]: isNotEmpty(newValues) ? newValues : null, [field]: isNotEmpty(newValues) ? newValues : null,
page: 1 [page]: 1
}; };
}) })
); );

View File

@@ -55,6 +55,7 @@ export function getRequest(transferState: TransferState): any {
// enableTracing: true, // enableTracing: true,
useHash: false, useHash: false,
scrollPositionRestoration: 'enabled', scrollPositionRestoration: 'enabled',
anchorScrolling: 'enabled',
preloadingStrategy: NoPreloading preloadingStrategy: NoPreloading
}), }),
StatisticsModule.forRoot(), StatisticsModule.forRoot(),