mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
76654: PaginationService
This commit is contained in:
@@ -45,8 +45,7 @@
|
||||
[pageInfoState]="pageInfoState$"
|
||||
[collectionSize]="(pageInfoState$ | async)?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="epeople" class="table table-striped table-hover table-bordered">
|
||||
|
@@ -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<EpersonDtoModel>) => {
|
||||
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<NoContent>) => {
|
||||
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: ''});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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<boolean> = of(false);
|
||||
canReset$: Observable<boolean> = 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<EPerson>) => {
|
||||
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<EPerson>) => {
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
@@ -29,8 +29,7 @@
|
||||
[pageInfoState]="(ePeopleSearchDtos | async)"
|
||||
[collectionSize]="(ePeopleSearchDtos | async)?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChangeSearch($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="epersonsSearch" class="table table-striped table-hover table-bordered">
|
||||
@@ -83,8 +82,7 @@
|
||||
[pageInfoState]="(ePeopleMembersOfGroupDtos | async)"
|
||||
[collectionSize]="(ePeopleMembersOfGroupDtos | async)?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="ePeopleMembersOfGroup" class="table table-striped table-hover table-bordered">
|
||||
|
@@ -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<any>) => {
|
||||
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<any>) => {
|
||||
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
|
||||
|
@@ -23,8 +23,7 @@
|
||||
[pageInfoState]="(searchResults$ | async)?.payload"
|
||||
[collectionSize]="(searchResults$ | async)?.payload?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChangeSearch($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="groupsSearch" class="table table-striped table-hover table-bordered">
|
||||
@@ -77,8 +76,7 @@
|
||||
[pageInfoState]="(subGroups$ | async)?.payload"
|
||||
[collectionSize]="(subGroups$ | async)?.payload?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="subgroupsOfGroup" class="table table-striped table-hover table-bordered">
|
||||
|
@@ -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<PaginatedList<Group>>) => {
|
||||
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<PaginatedList<Group>>) => {
|
||||
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<PaginatedList<Group>>) => {
|
||||
this.searchResults$.next(rd);
|
||||
}));
|
||||
}
|
||||
|
@@ -35,8 +35,7 @@
|
||||
[pageInfoState]="pageInfoState$"
|
||||
[collectionSize]="(pageInfoState$ | async)?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="groups" class="table table-striped table-hover table-bordered">
|
||||
|
@@ -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<Group>) => {
|
||||
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<PaginatedList<Group>>, RemoteData<PaginatedList<EPerson>>]) => {
|
||||
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<Group>) => {
|
||||
if (groups.page.length === 0) {
|
||||
return observableOf(buildPaginatedList(groups.pageInfo, []));
|
||||
}
|
||||
})).pipe(map((dtos: GroupDtoModel[]) => {
|
||||
return buildPaginatedList(groups.pageInfo, dtos);
|
||||
}));
|
||||
})).subscribe((value: PaginatedList<GroupDtoModel>) => {
|
||||
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<PaginatedList<Group>>, RemoteData<PaginatedList<EPerson>>]) => {
|
||||
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<GroupDtoModel>) => {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@@ -14,8 +14,7 @@
|
||||
[pageInfoState]="(bitstreamFormats | async)?.payload"
|
||||
[collectionSize]="(bitstreamFormats | async)?.payload?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
<div class="table-responsive">
|
||||
<table id="formats" class="table table-striped table-hover">
|
||||
<thead>
|
||||
|
@@ -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<string>;
|
||||
// pageState: BehaviorSubject<string>;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -13,8 +13,7 @@
|
||||
[paginationOptions]="config"
|
||||
[collectionSize]="(metadataSchemas | async)?.payload?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="metadata-schemas" class="table table-striped table-hover">
|
||||
|
@@ -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) {
|
||||
|
@@ -19,8 +19,7 @@
|
||||
[pageInfoState]="fields"
|
||||
[collectionSize]="fields?.totalElements"
|
||||
[hideGear]="false"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
<div class="table-responsive">
|
||||
<table id="metadata-fields" class="table table-striped table-hover">
|
||||
<thead>
|
||||
|
@@ -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);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@@ -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);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -33,9 +33,7 @@
|
||||
[startsWithOptions]="startsWithOptions"
|
||||
[enableArrows]="true"
|
||||
(prev)="goPrev()"
|
||||
(next)="goNext()"
|
||||
(pageSizeChange)="pageSizeChange($event)"
|
||||
(sortDirectionChange)="sortDirectionChange($event)">
|
||||
(next)="goNext()">
|
||||
</ds-browse-by>
|
||||
<ds-loading *ngIf="!startsWithOptions" message="{{'loading.browse-by-page' | translate}}"></ds-loading>
|
||||
</div>
|
||||
|
@@ -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
|
||||
);
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -52,8 +52,7 @@
|
||||
[config]="paginationConfig"
|
||||
[sortConfig]="sortConfig"
|
||||
[objects]="itemRD"
|
||||
[hideGear]="true"
|
||||
(paginationChange)="onPaginationChange($event)">
|
||||
[hideGear]="true">
|
||||
</ds-viewable-collection>
|
||||
</div>
|
||||
<ds-error *ngIf="itemRD?.hasFailed"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||
import { filter, map, mergeMap, startWith, switchMap, take } from 'rxjs/operators';
|
||||
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subject } from 'rxjs';
|
||||
import { filter, map, mergeMap, startWith, switchMap, take, tap } 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';
|
||||
@@ -21,7 +21,7 @@ import { fadeIn, fadeInOut } from '../shared/animations/fade';
|
||||
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||
import { AuthService } from '../core/auth/auth.service';
|
||||
import {PaginationChangeEvent} from '../shared/pagination/paginationChangeEvent.interface';
|
||||
import { PaginationService } from '../core/pagination/pagination.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-collection-page',
|
||||
@@ -51,9 +51,11 @@ export class CollectionPageComponent implements OnInit {
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private authService: AuthService,
|
||||
private paginationService: PaginationService,
|
||||
|
||||
) {
|
||||
this.paginationConfig = new PaginationComponentOptions();
|
||||
this.paginationConfig.id = 'collection-page-pagination';
|
||||
this.paginationConfig.id = 'cp';
|
||||
this.paginationConfig.pageSize = 5;
|
||||
this.paginationConfig.currentPage = 1;
|
||||
this.sortConfig = new SortOptions('dc.date.accessioned', SortDirection.DESC);
|
||||
@@ -76,16 +78,19 @@ export class CollectionPageComponent implements OnInit {
|
||||
sortConfig: this.sortConfig
|
||||
});
|
||||
|
||||
this.itemRD$ = this.paginationChanges$.pipe(
|
||||
switchMap((dto) => 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<RemoteData<PaginatedList<Item>>>;
|
||||
}),
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -5,8 +5,7 @@
|
||||
[config]="config"
|
||||
[sortConfig]="sortConfig"
|
||||
[objects]="subCollectionsRD"
|
||||
[hideGear]="false"
|
||||
(paginationChange)="onPaginationChange($event)">
|
||||
[hideGear]="false">
|
||||
</ds-viewable-collection>
|
||||
</div>
|
||||
<ds-error *ngIf="subCollectionsRD?.hasFailed" message="{{'error.sub-collections' | translate}}"></ds-error>
|
||||
|
@@ -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<RemoteData<PaginatedList<Collection>>> = new BehaviorSubject<RemoteData<PaginatedList<Collection>>>({} 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);
|
||||
});
|
||||
}
|
||||
|
@@ -5,8 +5,7 @@
|
||||
[config]="config"
|
||||
[sortConfig]="sortConfig"
|
||||
[objects]="subCommunitiesRD"
|
||||
[hideGear]="false"
|
||||
(paginationChange)="onPaginationChange($event)">
|
||||
[hideGear]="false">
|
||||
</ds-viewable-collection>
|
||||
</div>
|
||||
<ds-error *ngIf="subCommunitiesRD?.hasFailed" message="{{'error.sub-communities' | translate}}"></ds-error>
|
||||
|
@@ -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<RemoteData<PaginatedList<Community>>> = new BehaviorSubject<RemoteData<PaginatedList<Community>>>({} 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,
|
||||
|
@@ -6,8 +6,7 @@
|
||||
[config]="config"
|
||||
[sortConfig]="sortConfig"
|
||||
[objects]="communitiesRD$ | async"
|
||||
[hideGear]="true"
|
||||
(paginationChange)="onPaginationChange($event)">
|
||||
[hideGear]="true">
|
||||
</ds-viewable-collection>
|
||||
</div>
|
||||
<ds-error *ngIf="communitiesRD?.hasFailed " message="{{'error.top-level-communites' | translate}}"></ds-error>
|
||||
|
@@ -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);
|
||||
});
|
||||
}
|
||||
|
@@ -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">
|
||||
<ng-container *ngIf="!(loading$ | async)">
|
||||
<div [id]="bundle.id" class="bundle-bitstreams-list"
|
||||
[ngClass]="{'mb-3': (objectsRD$ | async)?.payload?.totalElements > pageSize}"
|
||||
|
@@ -10,6 +10,7 @@ import { ResponsiveTableSizes } from '../../../../../shared/responsive-table-siz
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-paginated-drag-and-drop-bitstream-list',
|
||||
@@ -37,8 +38,9 @@ export class PaginatedDragAndDropBitstreamListComponent extends AbstractPaginate
|
||||
protected elRef: ElementRef,
|
||||
protected objectValuesPipe: ObjectValuesPipe,
|
||||
protected bundleService: BundleDataService,
|
||||
protected paginationService: PaginationService,
|
||||
protected requestService: RequestService) {
|
||||
super(objectUpdatesService, elRef, objectValuesPipe);
|
||||
super(objectUpdatesService, elRef, objectValuesPipe, paginationService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@@ -11,6 +11,7 @@ import { SearchConfigurationService } from '../core/shared/search/search-configu
|
||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
||||
import { RouteService } from '../core/services/route.service';
|
||||
import { PaginationService } from '../core/pagination/pagination.service';
|
||||
|
||||
/**
|
||||
* Service that performs all actions that have to do with the current mydspace configuration
|
||||
@@ -59,9 +60,10 @@ export class MyDSpaceConfigurationService extends SearchConfigurationService {
|
||||
*/
|
||||
constructor(protected roleService: RoleService,
|
||||
protected routeService: RouteService,
|
||||
protected paginationService: PaginationService,
|
||||
protected route: ActivatedRoute) {
|
||||
|
||||
super(routeService, route);
|
||||
super(routeService, paginationService, route);
|
||||
|
||||
// override parent class initialization
|
||||
this._defaults = null;
|
||||
|
190
src/app/core/pagination/pagination.service.ts
Normal file
190
src/app/core/pagination/pagination.service.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRoute, 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';
|
||||
import { filter, map, take } from 'rxjs/operators';
|
||||
import { SortDirection, SortOptions } from '../cache/models/sort-options.model';
|
||||
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({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class PaginationService {
|
||||
|
||||
private defaultSortOptions = new SortOptions('id', SortDirection.ASC);
|
||||
|
||||
constructor(protected routeService: RouteService,
|
||||
protected route: ActivatedRoute,
|
||||
protected router: Router,
|
||||
protected location: Location
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current pagination settings
|
||||
*/
|
||||
getCurrentPagination(paginationId: string, defaultPagination: PaginationComponentOptions): Observable<PaginationComponentOptions> {
|
||||
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<string>} Emits the current sorting settings
|
||||
*/
|
||||
getCurrentSort(paginationId: string, defaultSort: SortOptions, ignoreDefault?: boolean): Observable<SortOptions> {
|
||||
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<FindListOptions> {
|
||||
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)];
|
||||
}
|
||||
|
||||
}
|
@@ -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<PaginatedSearchOptions>(defs);
|
||||
this.searchOptions = new BehaviorSubject<SearchOptions>(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<string>} Emits the current pagination settings
|
||||
*/
|
||||
getCurrentPagination(defaultPagination: PaginationComponentOptions): Observable<PaginationComponentOptions> {
|
||||
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<PaginationComponentOptions> {
|
||||
return this.paginationService.getCurrentPagination(paginationId, defaultPagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current sorting settings
|
||||
*/
|
||||
getCurrentSort(defaultSort: SortOptions): Observable<SortOptions> {
|
||||
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<SortOptions> {
|
||||
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<string>} Emits the current pagination settings as a partial SearchOptions object
|
||||
*/
|
||||
private getPaginationPart(defaultPagination: PaginationComponentOptions): Observable<any> {
|
||||
return this.getCurrentPagination(defaultPagination).pipe(map((pagination) => {
|
||||
private getPaginationPart(paginationId: string, defaultPagination: PaginationComponentOptions): Observable<any> {
|
||||
return this.getCurrentPagination(paginationId, defaultPagination).pipe(map((pagination) => {
|
||||
return { pagination };
|
||||
}));
|
||||
}
|
||||
@@ -326,8 +312,8 @@ export class SearchConfigurationService implements OnDestroy {
|
||||
/**
|
||||
* @returns {Observable<string>} Emits the current sorting settings as a partial SearchOptions object
|
||||
*/
|
||||
private getSortPart(defaultSort: SortOptions): Observable<any> {
|
||||
return this.getCurrentSort(defaultSort).pipe(map((sort) => {
|
||||
private getSortPart(paginationId: string, defaultSort: SortOptions): Observable<any> {
|
||||
return this.getCurrentSort(paginationId, defaultSort).pipe(map((sort) => {
|
||||
return { sort };
|
||||
}));
|
||||
}
|
||||
|
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -8,8 +8,7 @@
|
||||
[pageInfoState]="(processesRD$ | async)?.payload"
|
||||
[collectionSize]="(processesRD$ | async)?.payload?.totalElements"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hidePagerWhenSinglePage]="true">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
|
@@ -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))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
});
|
||||
}
|
||||
|
@@ -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<PaginationComponentOptions>;
|
||||
|
||||
|
||||
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});
|
||||
}) ;
|
||||
}
|
||||
}
|
||||
|
@@ -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<T extends DSpace
|
||||
/**
|
||||
* The amount of objects to display per page
|
||||
*/
|
||||
pageSize = 10;
|
||||
pageSize = 2;
|
||||
|
||||
/**
|
||||
* The page options to use for fetching the objects
|
||||
* Start at page 1 and always use the set page size
|
||||
*/
|
||||
options = Object.assign(new PaginationComponentOptions(),{
|
||||
id: 'paginated-drag-and-drop-options',
|
||||
id: 'dad',
|
||||
currentPage: 1,
|
||||
pageSize: this.pageSize
|
||||
});
|
||||
@@ -113,7 +114,9 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
||||
|
||||
protected constructor(protected objectUpdatesService: ObjectUpdatesService,
|
||||
protected elRef: ElementRef,
|
||||
protected objectValuesPipe: ObjectValuesPipe) {
|
||||
protected objectValuesPipe: ObjectValuesPipe,
|
||||
protected paginationService: PaginationService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,6 +126,7 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
||||
this.initializeObjectsRD();
|
||||
this.initializeURL();
|
||||
this.initializeUpdates();
|
||||
this.initializePagination();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,6 +139,15 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
||||
*/
|
||||
abstract initializeURL(): void;
|
||||
|
||||
/**
|
||||
* Initialize the current pagination retrieval from the paginationService and push to the currentPage$
|
||||
*/
|
||||
initializePagination() {
|
||||
this.paginationService.getCurrentPagination(this.options.id, this.options).subscribe((currentPagination) => {
|
||||
this.currentPage$.next(currentPagination.currentPage);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the field-updates in the store
|
||||
*/
|
||||
@@ -164,14 +177,6 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current page
|
||||
* @param page
|
||||
*/
|
||||
switchPage(page: number) {
|
||||
this.currentPage$.next(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* An object was moved, send updates to the dropObject EventEmitter
|
||||
* When the object is dropped on a page within the pagination of this component, the object moves to the top of that
|
||||
|
@@ -1,18 +1,18 @@
|
||||
<div *ngIf="currentPageState == undefined || currentPageState == currentPage">
|
||||
<div *ngIf="currentPageState == undefined || currentPageState == (currentPage$|async)">
|
||||
<div *ngIf="(!hidePaginationDetail && collectionSize > 0) || !hideGear" class="pagination-masked clearfix top">
|
||||
<div class="row">
|
||||
<div *ngIf="!hidePaginationDetail && collectionSize > 0" class="col-auto pagination-info">
|
||||
<span class="align-middle hidden-xs-down">{{ 'pagination.showing.label' | translate }}</span>
|
||||
<span class="align-middle">{{ 'pagination.showing.detail' | translate:getShowingDetails(collectionSize)}}</span>
|
||||
<span class="align-middle">{{ 'pagination.showing.detail' | translate:(getShowingDetails(collectionSize)|async)}}</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div *ngIf="!hideGear" ngbDropdown #paginationControls="ngbDropdown" placement="bottom-right" class="d-inline-block float-right">
|
||||
<button class="btn btn-outline-primary" id="paginationControls" ngbDropdownToggle><i class="fas fa-cog" aria-hidden="true"></i></button>
|
||||
<div id="paginationControlsDropdownMenu" aria-labelledby="paginationControls" ngbDropdownMenu>
|
||||
<h6 class="dropdown-header">{{ 'pagination.results-per-page' | translate}}</h6>
|
||||
<button class="dropdown-item" *ngFor="let item of pageSizeOptions" (click)="doPageSizeChange(item)"><i [ngClass]="{'invisible': item != pageSize}" class="fas fa-check" aria-hidden="true"></i> {{item}} </button>
|
||||
<button class="dropdown-item" *ngFor="let item of pageSizeOptions" (click)="doPageSizeChange(item)"><i [ngClass]="{'invisible': item != (pageSize$|async)}" class="fas fa-check" aria-hidden="true"></i> {{item}} </button>
|
||||
<h6 class="dropdown-header">{{ 'pagination.sort-direction' | translate}}</h6>
|
||||
<button class="dropdown-item" *ngFor="let direction of (sortDirections | dsKeys)" (click)="doSortDirectionChange(direction.value)"><i [ngClass]="{'invisible': direction.value !== sortDirection}" class="fas fa-check" aria-hidden="true"></i> {{'sorting.' + direction.key | translate}} </button>
|
||||
<button class="dropdown-item" *ngFor="let direction of (sortDirections | dsKeys)" (click)="doSortDirectionChange(direction.value)"><i [ngClass]="{'invisible': direction.value !== (sortDirection$ |async)}" class="fas fa-check" aria-hidden="true"></i> {{'sorting.' + direction.key | translate}} </button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -20,15 +20,15 @@
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
|
||||
<div *ngIf="shouldShowBottomPager" class="pagination justify-content-center clearfix bottom">
|
||||
<div *ngIf="shouldShowBottomPager |async" class="pagination justify-content-center clearfix bottom">
|
||||
<ngb-pagination [boundaryLinks]="paginationOptions.boundaryLinks"
|
||||
[collectionSize]="collectionSize"
|
||||
[disabled]="paginationOptions.disabled"
|
||||
[ellipses]="paginationOptions.ellipses"
|
||||
[maxSize]="(isXs)?5:paginationOptions.maxSize"
|
||||
[page]="currentPage"
|
||||
[page]="(currentPage$|async)"
|
||||
(pageChange)="doPageChange($event)"
|
||||
[pageSize]="pageSize"
|
||||
[pageSize]="(pageSize$ |async)"
|
||||
[rotate]="paginationOptions.rotate"
|
||||
[size]="(isXs)?'sm':paginationOptions.size"></ngb-pagination>
|
||||
</div>
|
||||
|
@@ -9,19 +9,18 @@ import {
|
||||
Output,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { isNumeric } from 'rxjs/internal-compatibility';
|
||||
import { isEqual, isObject, transform } from 'lodash';
|
||||
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
||||
|
||||
import { HostWindowService } from '../host-window.service';
|
||||
import { HostWindowState } from '../search/host-window.reducer';
|
||||
import { PaginationComponentOptions } from './pagination-component-options.model';
|
||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||
import { hasValue, isNotEmpty } from '../empty.util';
|
||||
import { hasValue } from '../empty.util';
|
||||
import { PageInfo } from '../../core/shared/page-info.model';
|
||||
import { difference } from '../object.util';
|
||||
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { isNumeric } from 'rxjs/internal-compatibility';
|
||||
|
||||
/**
|
||||
* The default pagination controls component.
|
||||
@@ -110,18 +109,13 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
/**
|
||||
* Current page.
|
||||
*/
|
||||
public currentPage;
|
||||
public currentPage$;
|
||||
|
||||
/**
|
||||
* Current page in the state of a Remote paginated objects.
|
||||
*/
|
||||
public currentPageState: number = undefined;
|
||||
|
||||
/**
|
||||
* Current URL query parameters
|
||||
*/
|
||||
public currentQueryParams: any;
|
||||
|
||||
/**
|
||||
* An observable of HostWindowState type
|
||||
*/
|
||||
@@ -141,7 +135,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
/**
|
||||
* Number of items per page.
|
||||
*/
|
||||
public pageSize;
|
||||
public pageSize$;
|
||||
|
||||
/**
|
||||
* Declare SortDirection enumeration to use it in the template
|
||||
@@ -156,12 +150,14 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
/**
|
||||
* Direction in which to sort: ascending or descending
|
||||
*/
|
||||
public sortDirection: SortDirection = SortDirection.ASC;
|
||||
public sortDirection$: Observable<SortDirection>;
|
||||
public defaultsortDirection: SortDirection = SortDirection.ASC;
|
||||
|
||||
/**
|
||||
* Name of the field that's used to sort by
|
||||
*/
|
||||
public sortField = 'id';
|
||||
public sortField$;
|
||||
public defaultSortField = 'id';
|
||||
|
||||
/**
|
||||
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||
@@ -182,40 +178,15 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
this.initializeConfig();
|
||||
// Listen to changes
|
||||
if (!this.disableRouteParameterUpdate) {
|
||||
this.subs.push(this.route.queryParams
|
||||
.subscribe((queryParams) => {
|
||||
this.initializeParams(queryParams);
|
||||
this.subs.push(
|
||||
this.paginationService.getCurrentPagination(this.id, this.paginationOptions).subscribe((queryParams) => {
|
||||
}));
|
||||
this.subs.push(
|
||||
this.paginationService.getCurrentSort(this.id, this.sortOptions).subscribe((queryParams) => {
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the route and current parameters
|
||||
* This method will fix any invalid or missing parameters
|
||||
* @param params
|
||||
*/
|
||||
private initializeParams(params) {
|
||||
if (this.isEmptyPaginationParams(params)) {
|
||||
this.initializeConfig(params);
|
||||
} else {
|
||||
this.currentQueryParams = params;
|
||||
const fixedProperties = this.validateParams(params);
|
||||
if (isNotEmpty(fixedProperties)) {
|
||||
if (!this.disableRouteParameterUpdate) {
|
||||
this.fixRoute(fixedProperties);
|
||||
} else {
|
||||
this.initializeParams(fixedProperties);
|
||||
}
|
||||
} else {
|
||||
this.setFields();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fixRoute(fixedProperties) {
|
||||
this.updateRoute(fixedProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method provided by Angular. Invoked when the instance is destroyed.
|
||||
*/
|
||||
@@ -228,23 +199,29 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
/**
|
||||
* Initializes all default variables
|
||||
*/
|
||||
private initializeConfig(queryParams: any = {}) {
|
||||
private initializeConfig() {
|
||||
// Set initial values
|
||||
this.id = this.paginationOptions.id || null;
|
||||
this.pageSizeOptions = this.paginationOptions.pageSizeOptions;
|
||||
this.currentPage = this.paginationOptions.currentPage;
|
||||
this.pageSize = this.paginationOptions.pageSize;
|
||||
this.currentPage$ = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe(
|
||||
map((currentPagination) => currentPagination.currentPage)
|
||||
);
|
||||
this.pageSize$ = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe(
|
||||
map((currentPagination) => currentPagination.pageSize)
|
||||
);
|
||||
|
||||
let sortOptions;
|
||||
if (this.sortOptions) {
|
||||
this.sortDirection = this.sortOptions.direction;
|
||||
this.sortField = this.sortOptions.field;
|
||||
sortOptions = this.sortOptions;
|
||||
} else {
|
||||
sortOptions = new SortOptions(this.defaultSortField, this.defaultsortDirection);
|
||||
}
|
||||
this.currentQueryParams = Object.assign({}, queryParams, {
|
||||
pageId: this.id,
|
||||
page: this.currentPage,
|
||||
pageSize: this.pageSize,
|
||||
sortDirection: this.sortDirection,
|
||||
sortField: this.sortField
|
||||
});
|
||||
this.sortDirection$ = this.paginationService.getCurrentSort(this.id, sortOptions).pipe(
|
||||
map((currentSort) => currentSort.direction)
|
||||
);
|
||||
this.sortField$ = this.paginationService.getCurrentSort(this.id, sortOptions).pipe(
|
||||
map((currentSort) => currentSort.field)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,8 +235,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* the HostWindowService singleton.
|
||||
*/
|
||||
constructor(private cdRef: ChangeDetectorRef,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private paginationService: PaginationService,
|
||||
public hostWindowService: HostWindowService) {
|
||||
}
|
||||
|
||||
@@ -270,7 +246,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* The page being navigated to.
|
||||
*/
|
||||
public doPageChange(page: number) {
|
||||
this.updateParams(Object.assign({}, this.currentQueryParams, { pageId: this.id, page: page.toString() }));
|
||||
this.updateParams({page: page.toString()});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -280,7 +256,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* The page size being navigated to.
|
||||
*/
|
||||
public doPageSizeChange(pageSize: number) {
|
||||
this.updateParams(Object.assign({}, this.currentQueryParams,{ pageId: this.id, page: 1, pageSize: pageSize }));
|
||||
this.updateParams({ pageId: this.id, page: 1, pageSize: pageSize });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,7 +266,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* The sort direction being navigated to.
|
||||
*/
|
||||
public doSortDirectionChange(sortDirection: SortDirection) {
|
||||
this.updateParams(Object.assign({}, this.currentQueryParams,{ pageId: this.id, page: 1, sortDirection: sortDirection }));
|
||||
this.updateParams({ pageId: this.id, page: 1, sortDirection: sortDirection });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,7 +276,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* The sort field being navigated to.
|
||||
*/
|
||||
public doSortFieldChange(field: string) {
|
||||
this.updateParams(Object.assign(this.currentQueryParams,{ pageId: this.id, page: 1, sortField: field }));
|
||||
this.updateParams({ pageId: this.id, page: 1, sortField: field });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,7 +286,6 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* The new page value
|
||||
*/
|
||||
public setPage(page: number) {
|
||||
this.currentPage = page;
|
||||
this.pageChange.emit(page);
|
||||
this.emitPaginationChange();
|
||||
}
|
||||
@@ -322,7 +297,6 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* The new page size value.
|
||||
*/
|
||||
public setPageSize(pageSize: number) {
|
||||
this.pageSize = pageSize;
|
||||
this.pageSizeChange.emit(pageSize);
|
||||
this.emitPaginationChange();
|
||||
}
|
||||
@@ -334,7 +308,6 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* The new sort directionvalue.
|
||||
*/
|
||||
public setSortDirection(sortDirection: SortDirection) {
|
||||
this.sortDirection = sortDirection;
|
||||
this.sortDirectionChange.emit(sortDirection);
|
||||
this.emitPaginationChange();
|
||||
}
|
||||
@@ -346,7 +319,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* The new sort field.
|
||||
*/
|
||||
public setSortField(field: string) {
|
||||
this.sortField = field;
|
||||
// this.sortField = field;
|
||||
this.sortFieldChange.emit(field);
|
||||
this.emitPaginationChange();
|
||||
}
|
||||
@@ -355,19 +328,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* Method to emit a general pagination change event
|
||||
*/
|
||||
private emitPaginationChange() {
|
||||
this.paginationChange.emit(
|
||||
{
|
||||
pagination: Object.assign(
|
||||
new PaginationComponentOptions(),
|
||||
{
|
||||
id: this.id,
|
||||
currentPage: this.currentPage,
|
||||
pageSize: this.pageSize,
|
||||
}),
|
||||
sort: Object.assign(
|
||||
new SortOptions(this.sortField, this.sortDirection)
|
||||
)
|
||||
});
|
||||
this.paginationChange.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,142 +336,38 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* @param params
|
||||
*/
|
||||
private updateParams(params: {}) {
|
||||
if (isNotEmpty(difference(params, this.currentQueryParams))) {
|
||||
if (!this.disableRouteParameterUpdate) {
|
||||
this.updateRoute(params);
|
||||
this.paginationService.updateRoute(this.id, params);
|
||||
} else {
|
||||
this.initializeParams(params);
|
||||
this.paginationService.updateRoute(this.id, params, {}, this.disableRouteParameterUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update the route parameters
|
||||
*/
|
||||
private updateRoute(params: {}) {
|
||||
if (isNotEmpty(difference(params, this.currentQueryParams))) {
|
||||
this.router.navigate([], {
|
||||
queryParams: Object.assign({}, this.currentQueryParams, params),
|
||||
queryParamsHandling: 'merge'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private difference(object, base) {
|
||||
const changes = (o, b) => {
|
||||
return transform(o, (result, value, key) => {
|
||||
if (!isEqual(value, b[key]) && isNotEmpty(value)) {
|
||||
result[key] = (isObject(value) && isObject(b[key])) ? changes(value, b[key]) : value;
|
||||
}
|
||||
});
|
||||
};
|
||||
return changes(object, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get pagination details of the current viewed page.
|
||||
*/
|
||||
public getShowingDetails(collectionSize: number): any {
|
||||
let showingDetails = { range: null + ' - ' + null, total: null };
|
||||
public getShowingDetails(collectionSize: number): Observable<any> {
|
||||
let showingDetails = observableOf({ range: null + ' - ' + null, total: null });
|
||||
if (collectionSize) {
|
||||
let firstItem;
|
||||
let lastItem;
|
||||
const pageMax = this.pageSize * this.currentPage;
|
||||
showingDetails = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe(
|
||||
map((currentPaginationOptions) => {
|
||||
let firstItem;
|
||||
let lastItem;
|
||||
const pageMax = currentPaginationOptions.pageSize * currentPaginationOptions.currentPage;
|
||||
|
||||
firstItem = this.pageSize * (this.currentPage - 1) + 1;
|
||||
if (collectionSize > pageMax) {
|
||||
lastItem = pageMax;
|
||||
} else {
|
||||
lastItem = collectionSize;
|
||||
}
|
||||
showingDetails = { range: firstItem + ' - ' + lastItem, total: collectionSize };
|
||||
firstItem = currentPaginationOptions.pageSize * (currentPaginationOptions.currentPage - 1) + 1;
|
||||
if (collectionSize > pageMax) {
|
||||
lastItem = pageMax;
|
||||
} else {
|
||||
lastItem = collectionSize;
|
||||
}
|
||||
return {range: firstItem + ' - ' + lastItem, total: collectionSize};
|
||||
})
|
||||
);
|
||||
}
|
||||
return showingDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to validate query params
|
||||
*
|
||||
* @param page
|
||||
* The page number to validate
|
||||
* @param pageSize
|
||||
* The page size to validate
|
||||
* @returns valid parameters if initial parameters were invalid
|
||||
*/
|
||||
private validateParams(params: any): any {
|
||||
const validPage = this.validatePage(params.page);
|
||||
const filteredSize = this.validatePageSize(params.pageSize);
|
||||
const fixedFields: any = {};
|
||||
if (+params.page !== validPage) {
|
||||
fixedFields.page = validPage.toString();
|
||||
}
|
||||
if (+params.pageSize !== filteredSize) {
|
||||
fixedFields.pageSize = filteredSize.toString();
|
||||
}
|
||||
return fixedFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update all pagination variables to the current query parameters
|
||||
*/
|
||||
private setFields() {
|
||||
// set fields only when page id is the one configured for this pagination instance
|
||||
if (this.currentQueryParams.pageId === this.id) {
|
||||
// (+) converts string to a number
|
||||
const page = this.currentQueryParams.page;
|
||||
if (this.currentPage !== +page) {
|
||||
this.setPage(+page);
|
||||
}
|
||||
|
||||
const pageSize = this.currentQueryParams.pageSize;
|
||||
if (this.pageSize !== +pageSize) {
|
||||
this.setPageSize(+pageSize);
|
||||
}
|
||||
|
||||
const sortDirection = this.currentQueryParams.sortDirection;
|
||||
if (this.sortDirection !== sortDirection) {
|
||||
this.setSortDirection(sortDirection);
|
||||
}
|
||||
|
||||
const sortField = this.currentQueryParams.sortField;
|
||||
if (this.sortField !== sortField) {
|
||||
this.setSortField(sortField);
|
||||
}
|
||||
this.cdRef.detectChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to validate the current page value
|
||||
*
|
||||
* @param page
|
||||
* The page number to validate
|
||||
* @returns returns valid page value
|
||||
*/
|
||||
private validatePage(page: any): number {
|
||||
let result = this.currentPage;
|
||||
if (isNumeric(page)) {
|
||||
result = +page;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to validate the current page size value
|
||||
*
|
||||
* @param page size
|
||||
* The page size to validate
|
||||
* @returns returns valid page size value
|
||||
*/
|
||||
private validatePageSize(pageSize: any): number {
|
||||
const filteredPageSize = this.pageSizeOptions.find((x) => x === +pageSize);
|
||||
let result = this.pageSize;
|
||||
if (filteredPageSize) {
|
||||
result = +pageSize;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to ensure options passed contains the required properties.
|
||||
*
|
||||
@@ -546,15 +403,19 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
||||
* Property to check whether the current pagination object has multiple pages
|
||||
* @returns true if there are multiple pages, else returns false
|
||||
*/
|
||||
get hasMultiplePages(): boolean {
|
||||
return this.collectionSize > this.pageSize;
|
||||
get hasMultiplePages(): Observable<boolean> {
|
||||
return this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe(
|
||||
map((currentPaginationOptions) => this.collectionSize > currentPaginationOptions.pageSize)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Property to check whether the current pagination should show a bottom pages
|
||||
* @returns true if a bottom pages should be shown, else returns false
|
||||
*/
|
||||
get shouldShowBottomPager(): boolean {
|
||||
return this.hasMultiplePages || !this.hidePagerWhenSinglePage;
|
||||
get shouldShowBottomPager(): Observable<boolean> {
|
||||
return this.hasMultiplePages.pipe(
|
||||
map((hasMultiplePages) => hasMultiplePages || !this.hidePagerWhenSinglePage)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -6,8 +6,7 @@
|
||||
[paginationOptions]="paginationOptions"
|
||||
[collectionSize]="(getList() | async)?.payload?.totalElements"
|
||||
[disableRouteParameterUpdate]="true"
|
||||
[hideGear]="true"
|
||||
(pageChange)="onPageChange($event)">
|
||||
[hideGear]="true">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="groups" class="table table-sm table-striped table-hover table-bordered">
|
||||
|
@@ -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<RemoteData<PaginatedList<DSpaceObject>>> = this.isListOfEPerson ?
|
||||
@@ -187,6 +189,7 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy {
|
||||
this.list$.next(list);
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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<any>();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -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() {
|
||||
|
@@ -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) {
|
||||
}
|
||||
|
@@ -20,8 +20,7 @@
|
||||
[context]="context"
|
||||
[importable]="true"
|
||||
[importConfig]="importConfig"
|
||||
(importObject)="import($event)"
|
||||
(pageChange)="paginationChange();">
|
||||
(importObject)="import($event)">
|
||||
</ds-viewable-collection>
|
||||
<ds-loading *ngIf="(isLoading$ | async)"
|
||||
message="{{'loading.search-results' | translate}}"></ds-loading>
|
||||
|
@@ -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<boolean> = new BehaviorSubject<boolean>(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);
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user