mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge branch 'main' into CST-4009
# Conflicts: # src/app/core/shared/search/search-configuration.service.ts # src/app/core/shared/search/search.service.ts # src/app/shared/search/search-settings/search-settings.component.ts
This commit is contained in:
@@ -14,8 +14,7 @@
|
|||||||
[pageInfoState]="(bitstreamFormats | async)?.payload"
|
[pageInfoState]="(bitstreamFormats | async)?.payload"
|
||||||
[collectionSize]="(bitstreamFormats | async)?.payload?.totalElements"
|
[collectionSize]="(bitstreamFormats | async)?.payload?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="formats" class="table table-striped table-hover">
|
<table id="formats" class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
@@ -23,6 +23,11 @@ import {
|
|||||||
createSuccessfulRemoteDataObject$
|
createSuccessfulRemoteDataObject$
|
||||||
} from '../../../shared/remote-data.utils';
|
} from '../../../shared/remote-data.utils';
|
||||||
import { createPaginatedList } from '../../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../../shared/testing/utils.test';
|
||||||
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('BitstreamFormatsComponent', () => {
|
describe('BitstreamFormatsComponent', () => {
|
||||||
let comp: BitstreamFormatsComponent;
|
let comp: BitstreamFormatsComponent;
|
||||||
@@ -30,6 +35,7 @@ describe('BitstreamFormatsComponent', () => {
|
|||||||
let bitstreamFormatService;
|
let bitstreamFormatService;
|
||||||
let scheduler: TestScheduler;
|
let scheduler: TestScheduler;
|
||||||
let notificationsServiceStub;
|
let notificationsServiceStub;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
const bitstreamFormat1 = new BitstreamFormat();
|
const bitstreamFormat1 = new BitstreamFormat();
|
||||||
bitstreamFormat1.uuid = 'test-uuid-1';
|
bitstreamFormat1.uuid = 'test-uuid-1';
|
||||||
@@ -79,6 +85,10 @@ describe('BitstreamFormatsComponent', () => {
|
|||||||
];
|
];
|
||||||
const mockFormatsRD = createSuccessfulRemoteDataObject(createPaginatedList(mockFormatsList));
|
const mockFormatsRD = createSuccessfulRemoteDataObject(createPaginatedList(mockFormatsList));
|
||||||
|
|
||||||
|
const pagination = Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 });
|
||||||
|
const sort = new SortOptions('score', SortDirection.DESC);
|
||||||
|
const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 20 });
|
||||||
|
|
||||||
const initAsync = () => {
|
const initAsync = () => {
|
||||||
notificationsServiceStub = new NotificationsServiceStub();
|
notificationsServiceStub = new NotificationsServiceStub();
|
||||||
|
|
||||||
@@ -95,13 +105,16 @@ describe('BitstreamFormatsComponent', () => {
|
|||||||
clearBitStreamFormatRequests: observableOf('cleared')
|
clearBitStreamFormatRequests: observableOf('cleared')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
|
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
{ provide: NotificationsService, useValue: notificationsServiceStub }
|
{ provide: NotificationsService, useValue: notificationsServiceStub },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
]
|
]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
};
|
};
|
||||||
@@ -217,13 +230,16 @@ describe('BitstreamFormatsComponent', () => {
|
|||||||
clearBitStreamFormatRequests: observableOf('cleared')
|
clearBitStreamFormatRequests: observableOf('cleared')
|
||||||
});
|
});
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
|
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
{ provide: NotificationsService, useValue: notificationsServiceStub }
|
{ provide: NotificationsService, useValue: notificationsServiceStub },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
]
|
]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}
|
}
|
||||||
@@ -263,13 +279,16 @@ describe('BitstreamFormatsComponent', () => {
|
|||||||
clearBitStreamFormatRequests: observableOf('cleared')
|
clearBitStreamFormatRequests: observableOf('cleared')
|
||||||
});
|
});
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
|
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
{ provide: NotificationsService, useValue: notificationsServiceStub }
|
{ provide: NotificationsService, useValue: notificationsServiceStub },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
]
|
]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnDestroy, 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 { RemoteData } from '../../../core/data/remote-data';
|
||||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.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 { Router } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { NoContent } from '../../../core/shared/NoContent.model';
|
import { NoContent } from '../../../core/shared/NoContent.model';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders a list of bitstream formats
|
* This component renders a list of bitstream formats
|
||||||
@@ -20,18 +21,13 @@ import { NoContent } from '../../../core/shared/NoContent.model';
|
|||||||
selector: 'ds-bitstream-formats',
|
selector: 'ds-bitstream-formats',
|
||||||
templateUrl: './bitstream-formats.component.html'
|
templateUrl: './bitstream-formats.component.html'
|
||||||
})
|
})
|
||||||
export class BitstreamFormatsComponent implements OnInit {
|
export class BitstreamFormatsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A paginated list of bitstream formats to be shown on the page
|
* A paginated list of bitstream formats to be shown on the page
|
||||||
*/
|
*/
|
||||||
bitstreamFormats: Observable<RemoteData<PaginatedList<BitstreamFormat>>>;
|
bitstreamFormats: Observable<RemoteData<PaginatedList<BitstreamFormat>>>;
|
||||||
|
|
||||||
/**
|
|
||||||
* A BehaviourSubject that keeps track of the pageState used to update the currently displayed bitstreamFormats
|
|
||||||
*/
|
|
||||||
pageState: BehaviorSubject<string>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current pagination configuration for the page used by the FindAll method
|
* The current pagination configuration for the page used by the FindAll method
|
||||||
* Currently simply renders all bitstream formats
|
* Currently simply renders all bitstream formats
|
||||||
@@ -45,16 +41,19 @@ export class BitstreamFormatsComponent implements OnInit {
|
|||||||
* Currently simply renders all bitstream formats
|
* Currently simply renders all bitstream formats
|
||||||
*/
|
*/
|
||||||
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'registry-bitstreamformats-pagination',
|
id: 'rbp',
|
||||||
pageSize: 20
|
pageSize: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(private notificationsService: NotificationsService,
|
constructor(private notificationsService: NotificationsService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private bitstreamFormatService: BitstreamFormatDataService) {
|
private bitstreamFormatService: BitstreamFormatDataService,
|
||||||
|
private paginationService: PaginationService,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the currently selected formats from the registry and updates the presented list
|
* Deletes the currently selected formats from the registry and updates the presented list
|
||||||
*/
|
*/
|
||||||
@@ -80,10 +79,8 @@ export class BitstreamFormatsComponent implements OnInit {
|
|||||||
|
|
||||||
this.deselectAll();
|
this.deselectAll();
|
||||||
|
|
||||||
this.router.navigate([], {
|
this.paginationService.resetPage(this.pageConfig.id);
|
||||||
queryParams: Object.assign({}, { page: 1 }),
|
});
|
||||||
queryParamsHandling: 'merge'
|
|
||||||
}); });
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -141,31 +138,17 @@ 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 {
|
ngOnInit(): void {
|
||||||
this.pageState = new BehaviorSubject('init');
|
|
||||||
this.bitstreamFormats = this.pageState.pipe(
|
this.bitstreamFormats = this.paginationService.getFindListOptions(this.pageConfig.id, this.config).pipe(
|
||||||
switchMap(() => {
|
switchMap((findListOptions: FindListOptions) => {
|
||||||
return this.updateFormats()
|
return this.bitstreamFormatService.findAll(findListOptions);
|
||||||
;
|
})
|
||||||
}));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds all formats based on the current config
|
ngOnDestroy(): void {
|
||||||
*/
|
this.paginationService.clearPagination(this.pageConfig.id);
|
||||||
private updateFormats() {
|
|
||||||
return this.bitstreamFormatService.findAll(this.config);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,8 +13,7 @@
|
|||||||
[paginationOptions]="config"
|
[paginationOptions]="config"
|
||||||
[collectionSize]="(metadataSchemas | async)?.payload?.totalElements"
|
[collectionSize]="(metadataSchemas | async)?.payload?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="metadata-schemas" class="table table-striped table-hover">
|
<table id="metadata-schemas" class="table table-striped table-hover">
|
||||||
|
@@ -18,11 +18,17 @@ import { NotificationsServiceStub } from '../../../shared/testing/notifications-
|
|||||||
import { RestResponse } from '../../../core/cache/response.models';
|
import { RestResponse } from '../../../core/cache/response.models';
|
||||||
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('MetadataRegistryComponent', () => {
|
describe('MetadataRegistryComponent', () => {
|
||||||
let comp: MetadataRegistryComponent;
|
let comp: MetadataRegistryComponent;
|
||||||
let fixture: ComponentFixture<MetadataRegistryComponent>;
|
let fixture: ComponentFixture<MetadataRegistryComponent>;
|
||||||
let registryService: RegistryService;
|
let registryService: RegistryService;
|
||||||
|
let paginationService;
|
||||||
const mockSchemasList = [
|
const mockSchemasList = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -62,6 +68,8 @@ describe('MetadataRegistryComponent', () => {
|
|||||||
};
|
};
|
||||||
/* tslint:enable:no-empty */
|
/* tslint:enable:no-empty */
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
@@ -69,6 +77,7 @@ describe('MetadataRegistryComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: RegistryService, useValue: registryServiceStub },
|
{ provide: RegistryService, useValue: registryServiceStub },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() }
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -13,6 +13,7 @@ import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
|||||||
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
|
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
|
||||||
import { NoContent } from '../../../core/shared/NoContent.model';
|
import { NoContent } from '../../../core/shared/NoContent.model';
|
||||||
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
import { getFirstCompletedRemoteData } from '../../../core/shared/operators';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-metadata-registry',
|
selector: 'ds-metadata-registry',
|
||||||
@@ -34,7 +35,7 @@ export class MetadataRegistryComponent {
|
|||||||
* Pagination config used to display the list of metadata schemas
|
* Pagination config used to display the list of metadata schemas
|
||||||
*/
|
*/
|
||||||
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'registry-metadataschemas-pagination',
|
id: 'rm',
|
||||||
pageSize: 25
|
pageSize: 25
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -46,26 +47,20 @@ export class MetadataRegistryComponent {
|
|||||||
constructor(private registryService: RegistryService,
|
constructor(private registryService: RegistryService,
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private paginationService: PaginationService,
|
||||||
private translateService: TranslateService) {
|
private translateService: TranslateService) {
|
||||||
this.updateSchemas();
|
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
|
* Update the list of schemas by fetching it from the rest api or cache
|
||||||
*/
|
*/
|
||||||
private updateSchemas() {
|
private updateSchemas() {
|
||||||
|
|
||||||
this.metadataSchemas = this.needsUpdate$.pipe(
|
this.metadataSchemas = this.needsUpdate$.pipe(
|
||||||
filter((update) => update === true),
|
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 suffix = success ? 'success' : 'failure';
|
||||||
const messages = observableCombineLatest(
|
const messages = observableCombineLatest(
|
||||||
this.translateService.get(success ? `${prefix}.${suffix}` : `${prefix}.${suffix}`),
|
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]) => {
|
messages.subscribe(([head, content]) => {
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -179,4 +174,8 @@ export class MetadataRegistryComponent {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,8 +19,7 @@
|
|||||||
[pageInfoState]="fields"
|
[pageInfoState]="fields"
|
||||||
[collectionSize]="fields?.totalElements"
|
[collectionSize]="fields?.totalElements"
|
||||||
[hideGear]="false"
|
[hideGear]="false"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="metadata-fields" class="table table-striped table-hover">
|
<table id="metadata-fields" class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
@@ -23,6 +23,11 @@ import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
|||||||
import { MetadataField } from '../../../core/metadata/metadata-field.model';
|
import { MetadataField } from '../../../core/metadata/metadata-field.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
import { VarDirective } from '../../../shared/utils/var.directive';
|
import { VarDirective } from '../../../shared/utils/var.directive';
|
||||||
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('MetadataSchemaComponent', () => {
|
describe('MetadataSchemaComponent', () => {
|
||||||
let comp: MetadataSchemaComponent;
|
let comp: MetadataSchemaComponent;
|
||||||
@@ -125,6 +130,8 @@ describe('MetadataSchemaComponent', () => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
@@ -134,6 +141,7 @@ describe('MetadataSchemaComponent', () => {
|
|||||||
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() }
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -6,6 +6,7 @@ import {
|
|||||||
combineLatest as observableCombineLatest,
|
combineLatest as observableCombineLatest,
|
||||||
combineLatest,
|
combineLatest,
|
||||||
Observable,
|
Observable,
|
||||||
|
of as observableOf,
|
||||||
zip
|
zip
|
||||||
} from 'rxjs';
|
} from 'rxjs';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
@@ -17,12 +18,10 @@ import { NotificationsService } from '../../../shared/notifications/notification
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { MetadataField } from '../../../core/metadata/metadata-field.model';
|
import { MetadataField } from '../../../core/metadata/metadata-field.model';
|
||||||
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
|
||||||
import {
|
import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators';
|
||||||
getFirstCompletedRemoteData,
|
|
||||||
getFirstSucceededRemoteDataPayload
|
|
||||||
} from '../../../core/shared/operators';
|
|
||||||
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
|
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
|
||||||
import { NoContent } from '../../../core/shared/NoContent.model';
|
import { NoContent } from '../../../core/shared/NoContent.model';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-metadata-schema',
|
selector: 'ds-metadata-schema',
|
||||||
@@ -48,7 +47,7 @@ export class MetadataSchemaComponent implements OnInit {
|
|||||||
* Pagination config used to display the list of metadata fields
|
* Pagination config used to display the list of metadata fields
|
||||||
*/
|
*/
|
||||||
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'registry-metadatafields-pagination',
|
id: 'rm',
|
||||||
pageSize: 25,
|
pageSize: 25,
|
||||||
pageSizeOptions: [25, 50, 100, 200]
|
pageSizeOptions: [25, 50, 100, 200]
|
||||||
});
|
});
|
||||||
@@ -62,6 +61,7 @@ export class MetadataSchemaComponent implements OnInit {
|
|||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private paginationService: PaginationService,
|
||||||
private translateService: TranslateService) {
|
private translateService: TranslateService) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -81,25 +81,17 @@ export class MetadataSchemaComponent implements OnInit {
|
|||||||
this.updateFields();
|
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
|
* Update the list of fields by fetching it from the rest api or cache
|
||||||
*/
|
*/
|
||||||
private updateFields() {
|
private updateFields() {
|
||||||
this.metadataFields$ = combineLatest(this.metadataSchema$, this.needsUpdate$).pipe(
|
this.metadataFields$ = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe(
|
||||||
switchMap(([schema, update]: [MetadataSchema, boolean]) => {
|
switchMap((currentPagination) => combineLatest(this.metadataSchema$, this.needsUpdate$, observableOf(currentPagination))),
|
||||||
|
switchMap(([schema, update, currentPagination]: [MetadataSchema, boolean, PaginationComponentOptions]) => {
|
||||||
if (update) {
|
if (update) {
|
||||||
this.needsUpdate$.next(false);
|
this.needsUpdate$.next(false);
|
||||||
}
|
}
|
||||||
return this.registryService.getMetadataFieldsBySchema(schema, toFindListOptions(this.config), !update, true);
|
return this.registryService.getMetadataFieldsBySchema(schema, toFindListOptions(currentPagination), !update, true);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -216,4 +208,8 @@ export class MetadataSchemaComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -18,11 +18,17 @@ import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-
|
|||||||
import { toRemoteData } from '../+browse-by-metadata-page/browse-by-metadata-page.component.spec';
|
import { toRemoteData } from '../+browse-by-metadata-page/browse-by-metadata-page.component.spec';
|
||||||
import { VarDirective } from '../../shared/utils/var.directive';
|
import { VarDirective } from '../../shared/utils/var.directive';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('BrowseByDatePageComponent', () => {
|
describe('BrowseByDatePageComponent', () => {
|
||||||
let comp: BrowseByDatePageComponent;
|
let comp: BrowseByDatePageComponent;
|
||||||
let fixture: ComponentFixture<BrowseByDatePageComponent>;
|
let fixture: ComponentFixture<BrowseByDatePageComponent>;
|
||||||
let route: ActivatedRoute;
|
let route: ActivatedRoute;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
const mockCommunity = Object.assign(new Community(), {
|
const mockCommunity = Object.assign(new Community(), {
|
||||||
id: 'test-uuid',
|
id: 'test-uuid',
|
||||||
@@ -65,6 +71,8 @@ describe('BrowseByDatePageComponent', () => {
|
|||||||
detectChanges: () => fixture.detectChanges()
|
detectChanges: () => fixture.detectChanges()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
@@ -74,6 +82,7 @@ describe('BrowseByDatePageComponent', () => {
|
|||||||
{ provide: BrowseService, useValue: mockBrowseService },
|
{ provide: BrowseService, useValue: mockBrowseService },
|
||||||
{ provide: DSpaceObjectDataService, useValue: mockDsoService },
|
{ provide: DSpaceObjectDataService, useValue: mockDsoService },
|
||||||
{ provide: Router, useValue: new RouterMock() },
|
{ provide: Router, useValue: new RouterMock() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: ChangeDetectorRef, useValue: mockCdRef }
|
{ provide: ChangeDetectorRef, useValue: mockCdRef }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -8,12 +8,16 @@ import { combineLatest as observableCombineLatest } from 'rxjs';
|
|||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { Item } from '../../core/shared/item.model';
|
import { Item } from '../../core/shared/item.model';
|
||||||
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
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 { BrowseService } from '../../core/browse/browse.service';
|
||||||
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
||||||
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
||||||
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
|
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
|
||||||
import { environment } from '../../../environments/environment';
|
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 { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-browse-by-date-page',
|
selector: 'ds-browse-by-date-page',
|
||||||
@@ -37,30 +41,32 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
|
|||||||
protected browseService: BrowseService,
|
protected browseService: BrowseService,
|
||||||
protected dsoService: DSpaceObjectDataService,
|
protected dsoService: DSpaceObjectDataService,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected cdRef: ChangeDetectorRef) {
|
protected cdRef: ChangeDetectorRef) {
|
||||||
super(route, browseService, dsoService, router);
|
super(route, browseService, dsoService, paginationService, router);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
const sortConfig = new SortOptions('default', SortDirection.ASC);
|
||||||
this.startsWithType = StartsWithType.date;
|
this.startsWithType = StartsWithType.date;
|
||||||
this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig));
|
this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig));
|
||||||
|
this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig);
|
||||||
|
this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig);
|
||||||
this.subs.push(
|
this.subs.push(
|
||||||
observableCombineLatest(
|
observableCombineLatest([this.route.params, this.route.queryParams, this.route.data,
|
||||||
this.route.params,
|
this.currentPagination$, this.currentSort$]).pipe(
|
||||||
this.route.queryParams,
|
map(([routeParams, queryParams, data, currentPage, currentSort]) => {
|
||||||
this.route.data,
|
return [Object.assign({}, routeParams, queryParams, data), currentPage, currentSort];
|
||||||
(params, queryParams, data ) => {
|
|
||||||
return Object.assign({}, params, queryParams, data);
|
|
||||||
})
|
})
|
||||||
.subscribe((params) => {
|
).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => {
|
||||||
const metadataField = params.metadataField || this.defaultMetadataField;
|
const metadataField = params.metadataField || this.defaultMetadataField;
|
||||||
this.browseId = params.id || this.defaultBrowseId;
|
this.browseId = params.id || this.defaultBrowseId;
|
||||||
this.startsWith = +params.startsWith || params.startsWith;
|
this.startsWith = +params.startsWith || params.startsWith;
|
||||||
const searchOptions = browseParamsToOptions(params, Object.assign({}), this.sortConfig, this.browseId);
|
const searchOptions = browseParamsToOptions(params, currentPage, currentSort, this.browseId);
|
||||||
this.updatePageWithItems(searchOptions, this.value);
|
this.updatePageWithItems(searchOptions, this.value);
|
||||||
this.updateParent(params.scope);
|
this.updateParent(params.scope);
|
||||||
this.updateStartsWithOptions(this.browseId, metadataField, params.scope);
|
this.updateStartsWithOptions(this.browseId, metadataField, params.scope);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -27,15 +27,13 @@
|
|||||||
title="{{'browse.title' | translate:{collection: (parent$ | async)?.payload?.name || '', field: 'browse.metadata.' + browseId | translate, value: (value)? '"' + value + '"': ''} }}"
|
title="{{'browse.title' | translate:{collection: (parent$ | async)?.payload?.name || '', field: 'browse.metadata.' + browseId | translate, value: (value)? '"' + value + '"': ''} }}"
|
||||||
parentname="{{(parent$ | async)?.payload?.name || ''}}"
|
parentname="{{(parent$ | async)?.payload?.name || ''}}"
|
||||||
[objects$]="(items$ !== undefined)? items$ : browseEntries$"
|
[objects$]="(items$ !== undefined)? items$ : browseEntries$"
|
||||||
[paginationConfig]="paginationConfig"
|
[paginationConfig]="(currentPagination$ |async)"
|
||||||
[sortConfig]="sortConfig"
|
[sortConfig]="(currentSort$ |async)"
|
||||||
[type]="startsWithType"
|
[type]="startsWithType"
|
||||||
[startsWithOptions]="startsWithOptions"
|
[startsWithOptions]="startsWithOptions"
|
||||||
[enableArrows]="true"
|
[enableArrows]="true"
|
||||||
(prev)="goPrev()"
|
(prev)="goPrev()"
|
||||||
(next)="goNext()"
|
(next)="goNext()">
|
||||||
(pageSizeChange)="pageSizeChange($event)"
|
|
||||||
(sortDirectionChange)="sortDirectionChange($event)">
|
|
||||||
</ds-browse-by>
|
</ds-browse-by>
|
||||||
<ds-loading *ngIf="!startsWithOptions" message="{{'loading.browse-by-page' | translate}}"></ds-loading>
|
<ds-loading *ngIf="!startsWithOptions" message="{{'loading.browse-by-page' | translate}}"></ds-loading>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -14,7 +14,7 @@ import { RemoteData } from '../../core/data/remote-data';
|
|||||||
import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model';
|
import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../core/shared/page-info.model';
|
||||||
import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-options.model';
|
import { BrowseEntrySearchOptions } from '../../core/browse/browse-entry-search-options.model';
|
||||||
import { SortDirection } from '../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { Item } from '../../core/shared/item.model';
|
import { Item } from '../../core/shared/item.model';
|
||||||
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
||||||
import { Community } from '../../core/shared/community.model';
|
import { Community } from '../../core/shared/community.model';
|
||||||
@@ -22,12 +22,16 @@ import { RouterMock } from '../../shared/mocks/router.mock';
|
|||||||
import { BrowseEntry } from '../../core/shared/browse-entry.model';
|
import { BrowseEntry } from '../../core/shared/browse-entry.model';
|
||||||
import { VarDirective } from '../../shared/utils/var.directive';
|
import { VarDirective } from '../../shared/utils/var.directive';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('BrowseByMetadataPageComponent', () => {
|
describe('BrowseByMetadataPageComponent', () => {
|
||||||
let comp: BrowseByMetadataPageComponent;
|
let comp: BrowseByMetadataPageComponent;
|
||||||
let fixture: ComponentFixture<BrowseByMetadataPageComponent>;
|
let fixture: ComponentFixture<BrowseByMetadataPageComponent>;
|
||||||
let browseService: BrowseService;
|
let browseService: BrowseService;
|
||||||
let route: ActivatedRoute;
|
let route: ActivatedRoute;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
const mockCommunity = Object.assign(new Community(), {
|
const mockCommunity = Object.assign(new Community(), {
|
||||||
id: 'test-uuid',
|
id: 'test-uuid',
|
||||||
@@ -82,6 +86,8 @@ describe('BrowseByMetadataPageComponent', () => {
|
|||||||
params: observableOf({})
|
params: observableOf({})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
@@ -90,6 +96,7 @@ describe('BrowseByMetadataPageComponent', () => {
|
|||||||
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
||||||
{ provide: BrowseService, useValue: mockBrowseService },
|
{ provide: BrowseService, useValue: mockBrowseService },
|
||||||
{ provide: DSpaceObjectDataService, useValue: mockDsoService },
|
{ provide: DSpaceObjectDataService, useValue: mockDsoService },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: Router, useValue: new RouterMock() }
|
{ provide: Router, useValue: new RouterMock() }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -133,18 +140,23 @@ describe('BrowseByMetadataPageComponent', () => {
|
|||||||
let result: BrowseEntrySearchOptions;
|
let result: BrowseEntrySearchOptions;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const paramsWithPaginationAndScope = {
|
const paramsScope = {
|
||||||
page: 5,
|
|
||||||
pageSize: 10,
|
|
||||||
sortDirection: SortDirection.ASC,
|
|
||||||
sortField: 'fake-field',
|
|
||||||
scope: 'fake-scope'
|
scope: 'fake-scope'
|
||||||
};
|
};
|
||||||
|
const paginationOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
|
currentPage: 5,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
const sortOptions = {
|
||||||
|
direction: SortDirection.ASC,
|
||||||
|
field: 'fake-field',
|
||||||
|
};
|
||||||
|
|
||||||
result = browseParamsToOptions(paramsWithPaginationAndScope, Object.assign({}), Object.assign({}), 'author');
|
result = browseParamsToOptions(paramsScope, paginationOptions, sortOptions, 'author');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return BrowseEntrySearchOptions with the correct properties', () => {
|
it('should return BrowseEntrySearchOptions with the correct properties', () => {
|
||||||
|
|
||||||
expect(result.metadataDefinition).toEqual('author');
|
expect(result.metadataDefinition).toEqual('author');
|
||||||
expect(result.pagination.currentPage).toEqual(5);
|
expect(result.pagination.currentPage).toEqual(5);
|
||||||
expect(result.pagination.pageSize).toEqual(10);
|
expect(result.pagination.pageSize).toEqual(10);
|
||||||
|
@@ -4,7 +4,7 @@ import { RemoteData } from '../../core/data/remote-data';
|
|||||||
import { PaginatedList } from '../../core/data/paginated-list.model';
|
import { PaginatedList } from '../../core/data/paginated-list.model';
|
||||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-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 { hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||||
import { BrowseService } from '../../core/browse/browse.service';
|
import { BrowseService } from '../../core/browse/browse.service';
|
||||||
import { BrowseEntry } from '../../core/shared/browse-entry.model';
|
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 { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||||
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
import { StartsWithType } from '../../shared/starts-with/starts-with-decorator';
|
||||||
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
|
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-browse-by-metadata-page',
|
selector: 'ds-browse-by-metadata-page',
|
||||||
@@ -48,15 +50,20 @@ export class BrowseByMetadataPageComponent implements OnInit {
|
|||||||
* The pagination config used to display the values
|
* The pagination config used to display the values
|
||||||
*/
|
*/
|
||||||
paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
paginationConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'browse-by-metadata-pagination',
|
id: 'bbm',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: 20
|
pageSize: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sorting config used to sort the values (defaults to Ascending)
|
* The pagination observable
|
||||||
*/
|
*/
|
||||||
sortConfig: SortOptions = new SortOptions('default', SortDirection.ASC);
|
currentPagination$: Observable<PaginationComponentOptions>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sorting config observable
|
||||||
|
*/
|
||||||
|
currentSort$: Observable<SortOptions>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of subscriptions
|
* List of subscriptions
|
||||||
@@ -100,23 +107,25 @@ export class BrowseByMetadataPageComponent implements OnInit {
|
|||||||
public constructor(protected route: ActivatedRoute,
|
public constructor(protected route: ActivatedRoute,
|
||||||
protected browseService: BrowseService,
|
protected browseService: BrowseService,
|
||||||
protected dsoService: DSpaceObjectDataService,
|
protected dsoService: DSpaceObjectDataService,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected router: Router) {
|
protected router: Router) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig));
|
const sortConfig = new SortOptions('default', SortDirection.ASC);
|
||||||
|
this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig));
|
||||||
|
this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig);
|
||||||
|
this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig);
|
||||||
this.subs.push(
|
this.subs.push(
|
||||||
observableCombineLatest(
|
observableCombineLatest([this.route.params, this.route.queryParams, this.currentPagination$, this.currentSort$]).pipe(
|
||||||
this.route.params,
|
map(([routeParams, queryParams, currentPage, currentSort]) => {
|
||||||
this.route.queryParams,
|
return [Object.assign({}, routeParams, queryParams),currentPage,currentSort];
|
||||||
(params, queryParams, ) => {
|
|
||||||
return Object.assign({}, params, queryParams);
|
|
||||||
})
|
})
|
||||||
.subscribe((params) => {
|
).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => {
|
||||||
this.browseId = params.id || this.defaultBrowseId;
|
this.browseId = params.id || this.defaultBrowseId;
|
||||||
this.value = +params.value || params.value || '';
|
this.value = +params.value || params.value || '';
|
||||||
this.startsWith = +params.startsWith || params.startsWith;
|
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)) {
|
if (isNotEmpty(this.value)) {
|
||||||
this.updatePageWithItems(searchOptions, this.value);
|
this.updatePageWithItems(searchOptions, this.value);
|
||||||
} else {
|
} else {
|
||||||
@@ -158,6 +167,7 @@ export class BrowseByMetadataPageComponent implements OnInit {
|
|||||||
* @param value The value of the browse-entry to display items for
|
* @param value The value of the browse-entry to display items for
|
||||||
*/
|
*/
|
||||||
updatePageWithItems(searchOptions: BrowseEntrySearchOptions, value: string) {
|
updatePageWithItems(searchOptions: BrowseEntrySearchOptions, value: string) {
|
||||||
|
console.log('updatePAge', searchOptions);
|
||||||
this.items$ = this.browseService.getBrowseItemsFor(value, searchOptions);
|
this.items$ = this.browseService.getBrowseItemsFor(value, searchOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,32 +213,12 @@ 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 {
|
ngOnDestroy(): void {
|
||||||
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
||||||
|
this.paginationService.clearPagination(this.paginationConfig.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -244,20 +234,8 @@ export function browseParamsToOptions(params: any,
|
|||||||
metadata?: string): BrowseEntrySearchOptions {
|
metadata?: string): BrowseEntrySearchOptions {
|
||||||
return new BrowseEntrySearchOptions(
|
return new BrowseEntrySearchOptions(
|
||||||
metadata,
|
metadata,
|
||||||
Object.assign({},
|
paginationConfig,
|
||||||
paginationConfig,
|
sortConfig,
|
||||||
{
|
|
||||||
currentPage: +params.page || paginationConfig.currentPage,
|
|
||||||
pageSize: +params.pageSize || paginationConfig.pageSize
|
|
||||||
}
|
|
||||||
),
|
|
||||||
Object.assign({},
|
|
||||||
sortConfig,
|
|
||||||
{
|
|
||||||
direction: params.sortDirection || sortConfig.direction,
|
|
||||||
field: params.sortField || sortConfig.field
|
|
||||||
}
|
|
||||||
),
|
|
||||||
+params.startsWith || params.startsWith,
|
+params.startsWith || params.startsWith,
|
||||||
params.scope
|
params.scope
|
||||||
);
|
);
|
||||||
|
@@ -18,6 +18,11 @@ import { BrowseService } from '../../core/browse/browse.service';
|
|||||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||||
import { VarDirective } from '../../shared/utils/var.directive';
|
import { VarDirective } from '../../shared/utils/var.directive';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('BrowseByTitlePageComponent', () => {
|
describe('BrowseByTitlePageComponent', () => {
|
||||||
let comp: BrowseByTitlePageComponent;
|
let comp: BrowseByTitlePageComponent;
|
||||||
@@ -61,6 +66,8 @@ describe('BrowseByTitlePageComponent', () => {
|
|||||||
data: observableOf({ metadata: 'title' })
|
data: observableOf({ metadata: 'title' })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
@@ -69,6 +76,7 @@ describe('BrowseByTitlePageComponent', () => {
|
|||||||
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
||||||
{ provide: BrowseService, useValue: mockBrowseService },
|
{ provide: BrowseService, useValue: mockBrowseService },
|
||||||
{ provide: DSpaceObjectDataService, useValue: mockDsoService },
|
{ provide: DSpaceObjectDataService, useValue: mockDsoService },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: Router, useValue: new RouterMock() }
|
{ provide: Router, useValue: new RouterMock() }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { combineLatest as observableCombineLatest } from 'rxjs';
|
import { combineLatest as observableCombineLatest } from 'rxjs';
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import {
|
import {
|
||||||
BrowseByMetadataPageComponent,
|
BrowseByMetadataPageComponent,
|
||||||
@@ -11,6 +11,9 @@ import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.serv
|
|||||||
import { BrowseService } from '../../core/browse/browse.service';
|
import { BrowseService } from '../../core/browse/browse.service';
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { BrowseByType, rendersBrowseBy } from '../+browse-by-switcher/browse-by-decorator';
|
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({
|
@Component({
|
||||||
selector: 'ds-browse-by-title-page',
|
selector: 'ds-browse-by-title-page',
|
||||||
@@ -26,26 +29,26 @@ export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent {
|
|||||||
public constructor(protected route: ActivatedRoute,
|
public constructor(protected route: ActivatedRoute,
|
||||||
protected browseService: BrowseService,
|
protected browseService: BrowseService,
|
||||||
protected dsoService: DSpaceObjectDataService,
|
protected dsoService: DSpaceObjectDataService,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected router: Router) {
|
protected router: Router) {
|
||||||
super(route, browseService, dsoService, router);
|
super(route, browseService, dsoService, paginationService, router);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.sortConfig = new SortOptions('dc.title', SortDirection.ASC);
|
const sortConfig = new SortOptions('dc.title', SortDirection.ASC);
|
||||||
this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, this.sortConfig));
|
this.updatePage(new BrowseEntrySearchOptions(this.defaultBrowseId, this.paginationConfig, sortConfig));
|
||||||
|
this.currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig);
|
||||||
|
this.currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, sortConfig);
|
||||||
this.subs.push(
|
this.subs.push(
|
||||||
observableCombineLatest(
|
observableCombineLatest([this.route.params, this.route.queryParams, this.currentPagination$, this.currentSort$]).pipe(
|
||||||
this.route.params,
|
map(([routeParams, queryParams, currentPage, currentSort]) => {
|
||||||
this.route.queryParams,
|
return [Object.assign({}, routeParams, queryParams),currentPage,currentSort];
|
||||||
this.route.data,
|
|
||||||
(params, queryParams, data ) => {
|
|
||||||
return Object.assign({}, params, queryParams, data);
|
|
||||||
})
|
})
|
||||||
.subscribe((params) => {
|
).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => {
|
||||||
this.browseId = params.id || this.defaultBrowseId;
|
this.browseId = params.id || this.defaultBrowseId;
|
||||||
this.updatePageWithItems(browseParamsToOptions(params, this.paginationConfig, this.sortConfig, this.browseId), undefined);
|
this.updatePageWithItems(browseParamsToOptions(params, currentPage, currentSort, this.browseId), undefined);
|
||||||
this.updateParent(params.scope);
|
this.updateParent(params.scope);
|
||||||
}));
|
}));
|
||||||
this.updateStartsWithTextOptions();
|
this.updateStartsWithTextOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,8 +52,7 @@
|
|||||||
[config]="paginationConfig"
|
[config]="paginationConfig"
|
||||||
[sortConfig]="sortConfig"
|
[sortConfig]="sortConfig"
|
||||||
[objects]="itemRD"
|
[objects]="itemRD"
|
||||||
[hideGear]="true"
|
[hideGear]="true">
|
||||||
(paginationChange)="onPaginationChange($event)">
|
|
||||||
</ds-viewable-collection>
|
</ds-viewable-collection>
|
||||||
</div>
|
</div>
|
||||||
<ds-error *ngIf="itemRD?.hasFailed"
|
<ds-error *ngIf="itemRD?.hasFailed"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subject } from 'rxjs';
|
||||||
import { filter, map, mergeMap, startWith, switchMap, take } from 'rxjs/operators';
|
import { filter, map, mergeMap, startWith, switchMap, take } from 'rxjs/operators';
|
||||||
import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../shared/search/paginated-search-options.model';
|
||||||
import { SearchService } from '../core/shared/search/search.service';
|
import { SearchService } from '../core/shared/search/search.service';
|
||||||
@@ -26,7 +26,7 @@ import { fadeIn, fadeInOut } from '../shared/animations/fade';
|
|||||||
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
import { AuthService } from '../core/auth/auth.service';
|
import { AuthService } from '../core/auth/auth.service';
|
||||||
import {PaginationChangeEvent} from '../shared/pagination/paginationChangeEvent.interface';
|
import { PaginationService } from '../core/pagination/pagination.service';
|
||||||
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
||||||
import { FeatureID } from '../core/data/feature-authorization/feature-id';
|
import { FeatureID } from '../core/data/feature-authorization/feature-id';
|
||||||
import { getCollectionPageRoute } from './collection-page-routing-paths';
|
import { getCollectionPageRoute } from './collection-page-routing-paths';
|
||||||
@@ -69,10 +69,11 @@ export class CollectionPageComponent implements OnInit {
|
|||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
private paginationService: PaginationService,
|
||||||
private authorizationDataService: AuthorizationDataService,
|
private authorizationDataService: AuthorizationDataService,
|
||||||
) {
|
) {
|
||||||
this.paginationConfig = new PaginationComponentOptions();
|
this.paginationConfig = new PaginationComponentOptions();
|
||||||
this.paginationConfig.id = 'collection-page-pagination';
|
this.paginationConfig.id = 'cp';
|
||||||
this.paginationConfig.pageSize = 5;
|
this.paginationConfig.pageSize = 5;
|
||||||
this.paginationConfig.currentPage = 1;
|
this.paginationConfig.currentPage = 1;
|
||||||
this.sortConfig = new SortOptions('dc.date.accessioned', SortDirection.DESC);
|
this.sortConfig = new SortOptions('dc.date.accessioned', SortDirection.DESC);
|
||||||
@@ -96,16 +97,19 @@ export class CollectionPageComponent implements OnInit {
|
|||||||
sortConfig: this.sortConfig
|
sortConfig: this.sortConfig
|
||||||
});
|
});
|
||||||
|
|
||||||
this.itemRD$ = this.paginationChanges$.pipe(
|
const currentPagination$ = this.paginationService.getCurrentPagination(this.paginationConfig.id, this.paginationConfig);
|
||||||
switchMap((dto) => this.collectionRD$.pipe(
|
const currentSort$ = this.paginationService.getCurrentSort(this.paginationConfig.id, this.sortConfig);
|
||||||
|
|
||||||
|
this.itemRD$ = observableCombineLatest([currentPagination$, currentSort$]).pipe(
|
||||||
|
switchMap(([currentPagination, currentSort ]) => this.collectionRD$.pipe(
|
||||||
getFirstSucceededRemoteData(),
|
getFirstSucceededRemoteData(),
|
||||||
map((rd) => rd.payload.id),
|
map((rd) => rd.payload.id),
|
||||||
switchMap((id: string) => {
|
switchMap((id: string) => {
|
||||||
return this.searchService.search(
|
return this.searchService.search(
|
||||||
new PaginatedSearchOptions({
|
new PaginatedSearchOptions({
|
||||||
scope: id,
|
scope: id,
|
||||||
pagination: dto.paginationConfig,
|
pagination: currentPagination,
|
||||||
sort: dto.sortConfig,
|
sort: currentSort,
|
||||||
dsoTypes: [DSpaceObjectType.ITEM]
|
dsoTypes: [DSpaceObjectType.ITEM]
|
||||||
})).pipe(toDSpaceObjectListRD()) as Observable<RemoteData<PaginatedList<Item>>>;
|
})).pipe(toDSpaceObjectListRD()) as Observable<RemoteData<PaginatedList<Item>>>;
|
||||||
}),
|
}),
|
||||||
@@ -128,19 +132,9 @@ export class CollectionPageComponent implements OnInit {
|
|||||||
return isNotEmpty(object);
|
return isNotEmpty(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPaginationChange(event: PaginationChangeEvent) {
|
ngOnDestroy(): void {
|
||||||
this.paginationConfig = Object.assign(new PaginationComponentOptions(), {
|
this.paginationService.clearPagination(this.paginationConfig.id);
|
||||||
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"
|
[config]="config"
|
||||||
[sortConfig]="sortConfig"
|
[sortConfig]="sortConfig"
|
||||||
[objects]="subCollectionsRD"
|
[objects]="subCollectionsRD"
|
||||||
[hideGear]="false"
|
[hideGear]="false">
|
||||||
(paginationChange)="onPaginationChange($event)">
|
|
||||||
</ds-viewable-collection>
|
</ds-viewable-collection>
|
||||||
</div>
|
</div>
|
||||||
<ds-error *ngIf="subCollectionsRD?.hasFailed" message="{{'error.sub-collections' | translate}}"></ds-error>
|
<ds-error *ngIf="subCollectionsRD?.hasFailed" message="{{'error.sub-collections' | translate}}"></ds-error>
|
||||||
|
@@ -18,8 +18,13 @@ import { PageInfo } from '../../core/shared/page-info.model';
|
|||||||
import { HostWindowService } from '../../shared/host-window.service';
|
import { HostWindowService } from '../../shared/host-window.service';
|
||||||
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
||||||
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
||||||
import { ThemeService } from '../../shared/theme-support/theme.service';
|
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('CommunityPageSubCollectionList Component', () => {
|
describe('CommunityPageSubCollectionList Component', () => {
|
||||||
let comp: CommunityPageSubCollectionListComponent;
|
let comp: CommunityPageSubCollectionListComponent;
|
||||||
@@ -113,6 +118,8 @@ describe('CommunityPageSubCollectionList Component', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
themeService = getMockThemeService();
|
themeService = getMockThemeService();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
@@ -128,6 +135,7 @@ describe('CommunityPageSubCollectionList Component', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: CollectionDataService, useValue: collectionDataServiceStub },
|
{ provide: CollectionDataService, useValue: collectionDataServiceStub },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: SelectableListService, useValue: {} },
|
{ provide: SelectableListService, useValue: {} },
|
||||||
{ provide: ThemeService, useValue: themeService },
|
{ provide: ThemeService, useValue: themeService },
|
||||||
],
|
],
|
||||||
@@ -161,28 +169,4 @@ describe('CommunityPageSubCollectionList Component', () => {
|
|||||||
const subComHead = fixture.debugElement.queryAll(By.css('h2'));
|
const subComHead = fixture.debugElement.queryAll(By.css('h2'));
|
||||||
expect(subComHead.length).toEqual(0);
|
expect(subComHead.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update list of collections on pagination change', () => {
|
|
||||||
subCollList = collections;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const pagination = Object.create({
|
|
||||||
pagination:{
|
|
||||||
id: comp.pageId,
|
|
||||||
currentPage: 2,
|
|
||||||
pageSize: 5
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
field: 'dc.title',
|
|
||||||
direction: 'ASC'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
comp.onPaginationChange(pagination);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const collList = fixture.debugElement.queryAll(By.css('li'));
|
|
||||||
expect(collList.length).toEqual(2);
|
|
||||||
expect(collList[0].nativeElement.textContent).toContain('Collection 6');
|
|
||||||
expect(collList[1].nativeElement.textContent).toContain('Collection 7');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
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 { RemoteData } from '../../core/data/remote-data';
|
||||||
import { Collection } from '../../core/shared/collection.model';
|
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 { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { CollectionDataService } from '../../core/data/collection-data.service';
|
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({
|
@Component({
|
||||||
selector: 'ds-community-page-sub-collection-list',
|
selector: 'ds-community-page-sub-collection-list',
|
||||||
@@ -29,7 +30,7 @@ export class CommunityPageSubCollectionListComponent implements OnInit {
|
|||||||
/**
|
/**
|
||||||
* The pagination id
|
* The pagination id
|
||||||
*/
|
*/
|
||||||
pageId = 'community-collections-pagination';
|
pageId = 'cmcl';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sorting configuration
|
* The sorting configuration
|
||||||
@@ -41,7 +42,10 @@ export class CommunityPageSubCollectionListComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
subCollectionsRDObs: BehaviorSubject<RemoteData<PaginatedList<Collection>>> = new BehaviorSubject<RemoteData<PaginatedList<Collection>>>({} as any);
|
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 {
|
ngOnInit(): void {
|
||||||
this.config = new PaginationComponentOptions();
|
this.config = new PaginationComponentOptions();
|
||||||
@@ -49,31 +53,31 @@ export class CommunityPageSubCollectionListComponent implements OnInit {
|
|||||||
this.config.pageSize = 5;
|
this.config.pageSize = 5;
|
||||||
this.config.currentPage = 1;
|
this.config.currentPage = 1;
|
||||||
this.sortConfig = new SortOptions('dc.title', SortDirection.ASC);
|
this.sortConfig = new SortOptions('dc.title', SortDirection.ASC);
|
||||||
this.updatePage();
|
this.initPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when one of the pagination settings is changed
|
* Initialise the list of collections
|
||||||
* @param event The new pagination data
|
|
||||||
*/
|
*/
|
||||||
onPaginationChange(event) {
|
initPage() {
|
||||||
this.config.currentPage = event.pagination.currentPage;
|
const pagination$ = this.paginationService.getCurrentPagination(this.config.id, this.config);
|
||||||
this.config.pageSize = event.pagination.pageSize;
|
const sort$ = this.paginationService.getCurrentSort(this.config.id, this.sortConfig);
|
||||||
this.sortConfig.field = event.sort.field;
|
|
||||||
this.sortConfig.direction = event.sort.direction;
|
|
||||||
this.updatePage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
observableCombineLatest([pagination$, sort$]).pipe(
|
||||||
* Update the list of collections
|
switchMap(([currentPagination, currentSort]) => {
|
||||||
*/
|
return this.cds.findByParent(this.community.id, {
|
||||||
updatePage() {
|
currentPage: currentPagination.currentPage,
|
||||||
this.cds.findByParent(this.community.id,{
|
elementsPerPage: currentPagination.pageSize,
|
||||||
currentPage: this.config.currentPage,
|
sort: {field: currentSort.field, direction: currentSort.direction}
|
||||||
elementsPerPage: this.config.pageSize,
|
});
|
||||||
sort: { field: this.sortConfig.field, direction: this.sortConfig.direction }
|
})
|
||||||
}).pipe(takeUntilCompletedRemoteData()).subscribe((results) => {
|
).subscribe((results) => {
|
||||||
this.subCollectionsRDObs.next(results);
|
this.subCollectionsRDObs.next(results);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -5,8 +5,7 @@
|
|||||||
[config]="config"
|
[config]="config"
|
||||||
[sortConfig]="sortConfig"
|
[sortConfig]="sortConfig"
|
||||||
[objects]="subCommunitiesRD"
|
[objects]="subCommunitiesRD"
|
||||||
[hideGear]="false"
|
[hideGear]="false">
|
||||||
(paginationChange)="onPaginationChange($event)">
|
|
||||||
</ds-viewable-collection>
|
</ds-viewable-collection>
|
||||||
</div>
|
</div>
|
||||||
<ds-error *ngIf="subCommunitiesRD?.hasFailed" message="{{'error.sub-communities' | translate}}"></ds-error>
|
<ds-error *ngIf="subCommunitiesRD?.hasFailed" message="{{'error.sub-communities' | translate}}"></ds-error>
|
||||||
|
@@ -18,8 +18,13 @@ import { HostWindowService } from '../../shared/host-window.service';
|
|||||||
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
||||||
import { CommunityDataService } from '../../core/data/community-data.service';
|
import { CommunityDataService } from '../../core/data/community-data.service';
|
||||||
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
||||||
import { ThemeService } from '../../shared/theme-support/theme.service';
|
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('CommunityPageSubCommunityListComponent Component', () => {
|
describe('CommunityPageSubCommunityListComponent Component', () => {
|
||||||
let comp: CommunityPageSubCommunityListComponent;
|
let comp: CommunityPageSubCommunityListComponent;
|
||||||
@@ -114,6 +119,8 @@ describe('CommunityPageSubCommunityListComponent Component', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
themeService = getMockThemeService();
|
themeService = getMockThemeService();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
@@ -129,6 +136,7 @@ describe('CommunityPageSubCommunityListComponent Component', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: CommunityDataService, useValue: communityDataServiceStub },
|
{ provide: CommunityDataService, useValue: communityDataServiceStub },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: SelectableListService, useValue: {} },
|
{ provide: SelectableListService, useValue: {} },
|
||||||
{ provide: ThemeService, useValue: themeService },
|
{ provide: ThemeService, useValue: themeService },
|
||||||
],
|
],
|
||||||
@@ -163,28 +171,4 @@ describe('CommunityPageSubCommunityListComponent Component', () => {
|
|||||||
const subComHead = fixture.debugElement.queryAll(By.css('h2'));
|
const subComHead = fixture.debugElement.queryAll(By.css('h2'));
|
||||||
expect(subComHead.length).toEqual(0);
|
expect(subComHead.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update list of sub-communities on pagination change', () => {
|
|
||||||
subCommList = subcommunities;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const pagination = Object.create({
|
|
||||||
pagination:{
|
|
||||||
id: comp.pageId,
|
|
||||||
currentPage: 2,
|
|
||||||
pageSize: 5
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
field: 'dc.title',
|
|
||||||
direction: 'ASC'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
comp.onPaginationChange(pagination);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const collList = fixture.debugElement.queryAll(By.css('li'));
|
|
||||||
expect(collList.length).toEqual(2);
|
|
||||||
expect(collList[0].nativeElement.textContent).toContain('SubCommunity 6');
|
|
||||||
expect(collList[1].nativeElement.textContent).toContain('SubCommunity 7');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
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 { RemoteData } from '../../core/data/remote-data';
|
||||||
import { Community } from '../../core/shared/community.model';
|
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 { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { CommunityDataService } from '../../core/data/community-data.service';
|
import { CommunityDataService } from '../../core/data/community-data.service';
|
||||||
import { takeUntilCompletedRemoteData } from '../../core/shared/operators';
|
import { takeUntilCompletedRemoteData } from '../../core/shared/operators';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-community-page-sub-community-list',
|
selector: 'ds-community-page-sub-community-list',
|
||||||
@@ -31,7 +33,7 @@ export class CommunityPageSubCommunityListComponent implements OnInit {
|
|||||||
/**
|
/**
|
||||||
* The pagination id
|
* The pagination id
|
||||||
*/
|
*/
|
||||||
pageId = 'community-subCommunities-pagination';
|
pageId = 'cmscm';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sorting configuration
|
* The sorting configuration
|
||||||
@@ -43,7 +45,9 @@ export class CommunityPageSubCommunityListComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
subCommunitiesRDObs: BehaviorSubject<RemoteData<PaginatedList<Community>>> = new BehaviorSubject<RemoteData<PaginatedList<Community>>>({} as any);
|
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 {
|
ngOnInit(): void {
|
||||||
@@ -52,25 +56,29 @@ export class CommunityPageSubCommunityListComponent implements OnInit {
|
|||||||
this.config.pageSize = 5;
|
this.config.pageSize = 5;
|
||||||
this.config.currentPage = 1;
|
this.config.currentPage = 1;
|
||||||
this.sortConfig = new SortOptions('dc.title', SortDirection.ASC);
|
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
|
|
||||||
*/
|
|
||||||
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 sub-communities
|
* 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, {
|
this.cds.findByParent(this.community.id, {
|
||||||
currentPage: this.config.currentPage,
|
currentPage: this.config.currentPage,
|
||||||
elementsPerPage: this.config.pageSize,
|
elementsPerPage: this.config.pageSize,
|
||||||
@@ -79,4 +87,9 @@ export class CommunityPageSubCommunityListComponent implements OnInit {
|
|||||||
this.subCommunitiesRDObs.next(results);
|
this.subCommunitiesRDObs.next(results);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -6,8 +6,7 @@
|
|||||||
[config]="config"
|
[config]="config"
|
||||||
[sortConfig]="sortConfig"
|
[sortConfig]="sortConfig"
|
||||||
[objects]="communitiesRD$ | async"
|
[objects]="communitiesRD$ | async"
|
||||||
[hideGear]="true"
|
[hideGear]="true">
|
||||||
(paginationChange)="onPaginationChange($event)">
|
|
||||||
</ds-viewable-collection>
|
</ds-viewable-collection>
|
||||||
</div>
|
</div>
|
||||||
<ds-error *ngIf="communitiesRD?.hasFailed " message="{{'error.top-level-communites' | translate}}"></ds-error>
|
<ds-error *ngIf="communitiesRD?.hasFailed " message="{{'error.top-level-communites' | translate}}"></ds-error>
|
||||||
|
@@ -18,13 +18,19 @@ import { HostWindowService } from '../../shared/host-window.service';
|
|||||||
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../shared/testing/host-window-service.stub';
|
||||||
import { CommunityDataService } from '../../core/data/community-data.service';
|
import { CommunityDataService } from '../../core/data/community-data.service';
|
||||||
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
import { SelectableListService } from '../../shared/object-list/selectable-list/selectable-list.service';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
|
||||||
import { ThemeService } from '../../shared/theme-support/theme.service';
|
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('TopLevelCommunityList Component', () => {
|
describe('TopLevelCommunityList Component', () => {
|
||||||
let comp: TopLevelCommunityListComponent;
|
let comp: TopLevelCommunityListComponent;
|
||||||
let fixture: ComponentFixture<TopLevelCommunityListComponent>;
|
let fixture: ComponentFixture<TopLevelCommunityListComponent>;
|
||||||
let communityDataServiceStub: any;
|
let communityDataServiceStub: any;
|
||||||
|
let paginationService;
|
||||||
let themeService;
|
let themeService;
|
||||||
|
|
||||||
const topCommList = [Object.assign(new Community(), {
|
const topCommList = [Object.assign(new Community(), {
|
||||||
@@ -104,6 +110,8 @@ describe('TopLevelCommunityList Component', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
themeService = getMockThemeService();
|
themeService = getMockThemeService();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
@@ -119,6 +127,7 @@ describe('TopLevelCommunityList Component', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: CommunityDataService, useValue: communityDataServiceStub },
|
{ provide: CommunityDataService, useValue: communityDataServiceStub },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: SelectableListService, useValue: {} },
|
{ provide: SelectableListService, useValue: {} },
|
||||||
{ provide: ThemeService, useValue: themeService },
|
{ provide: ThemeService, useValue: themeService },
|
||||||
],
|
],
|
||||||
@@ -143,25 +152,4 @@ describe('TopLevelCommunityList Component', () => {
|
|||||||
expect(subComList[3].nativeElement.textContent).toContain('TopCommunity 4');
|
expect(subComList[3].nativeElement.textContent).toContain('TopCommunity 4');
|
||||||
expect(subComList[4].nativeElement.textContent).toContain('TopCommunity 5');
|
expect(subComList[4].nativeElement.textContent).toContain('TopCommunity 5');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update list of top-communities on pagination change', () => {
|
|
||||||
const pagination = Object.create({
|
|
||||||
pagination: {
|
|
||||||
id: comp.pageId,
|
|
||||||
currentPage: 2,
|
|
||||||
pageSize: 5
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
field: 'dc.title',
|
|
||||||
direction: 'ASC'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
comp.onPaginationChange(pagination);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const collList = fixture.debugElement.queryAll(By.css('li'));
|
|
||||||
expect(collList.length).toEqual(2);
|
|
||||||
expect(collList[0].nativeElement.textContent).toContain('TopCommunity 6');
|
|
||||||
expect(collList[1].nativeElement.textContent).toContain('TopCommunity 7');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { ChangeDetectionStrategy, Component, OnInit, OnDestroy } from '@angular/core';
|
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 { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { CommunityDataService } from '../../core/data/community-data.service';
|
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 { fadeInOut } from '../../shared/animations/fade';
|
||||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
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
|
* this component renders the Top-Level Community list
|
||||||
@@ -36,7 +38,7 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* The pagination id
|
* The pagination id
|
||||||
*/
|
*/
|
||||||
pageId = 'top-level-pagination';
|
pageId = 'tl';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sorting configuration
|
* The sorting configuration
|
||||||
@@ -48,7 +50,8 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
currentPageSubscription: Subscription;
|
currentPageSubscription: Subscription;
|
||||||
|
|
||||||
constructor(private cds: CommunityDataService) {
|
constructor(private cds: CommunityDataService,
|
||||||
|
private paginationService: PaginationService) {
|
||||||
this.config = new PaginationComponentOptions();
|
this.config = new PaginationComponentOptions();
|
||||||
this.config.id = this.pageId;
|
this.config.id = this.pageId;
|
||||||
this.config.pageSize = 5;
|
this.config.pageSize = 5;
|
||||||
@@ -57,31 +60,26 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
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
|
* Update the list of top communities
|
||||||
*/
|
*/
|
||||||
updatePage() {
|
initPage() {
|
||||||
this.unsubscribe();
|
const pagination$ = this.paginationService.getCurrentPagination(this.config.id, this.config);
|
||||||
this.currentPageSubscription = this.cds.findTop({
|
const sort$ = this.paginationService.getCurrentSort(this.config.id, this.sortConfig);
|
||||||
currentPage: this.config.currentPage,
|
|
||||||
elementsPerPage: this.config.pageSize,
|
this.currentPageSubscription = observableCombineLatest([pagination$, sort$]).pipe(
|
||||||
sort: { field: this.sortConfig.field, direction: this.sortConfig.direction }
|
switchMap(([currentPagination, currentSort]) => {
|
||||||
}).subscribe((results) => {
|
return this.cds.findTop({
|
||||||
|
currentPage: currentPagination.currentPage,
|
||||||
|
elementsPerPage: currentPagination.pageSize,
|
||||||
|
sort: {field: currentSort.field, direction: currentSort.direction}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
).subscribe((results) => {
|
||||||
this.communitiesRD$.next(results);
|
this.communitiesRD$.next(results);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -100,5 +98,7 @@ export class TopLevelCommunityListComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.unsubscribe();
|
this.unsubscribe();
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,7 @@
|
|||||||
[hidePaginationDetail]="true"
|
[hidePaginationDetail]="true"
|
||||||
[paginationOptions]="options"
|
[paginationOptions]="options"
|
||||||
[pageInfoState]="(objectsRD$ | async)?.payload"
|
[pageInfoState]="(objectsRD$ | async)?.payload"
|
||||||
[collectionSize]="(objectsRD$ | async)?.payload?.totalElements"
|
[collectionSize]="(objectsRD$ | async)?.payload?.totalElements">
|
||||||
[disableRouteParameterUpdate]="true"
|
|
||||||
(pageChange)="switchPage($event)">
|
|
||||||
<ng-container *ngIf="!(loading$ | async)">
|
<ng-container *ngIf="!(loading$ | async)">
|
||||||
<div [id]="bundle.id" class="bundle-bitstreams-list"
|
<div [id]="bundle.id" class="bundle-bitstreams-list"
|
||||||
[ngClass]="{'mb-3': (objectsRD$ | async)?.payload?.totalElements > pageSize}"
|
[ngClass]="{'mb-3': (objectsRD$ | async)?.payload?.totalElements > pageSize}"
|
||||||
|
@@ -16,6 +16,11 @@ import { ResponsiveColumnSizes } from '../../../../../shared/responsive-table-si
|
|||||||
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/remote-data.utils';
|
||||||
import { createPaginatedList } from '../../../../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../../../../shared/testing/utils.test';
|
||||||
import { RequestService } from '../../../../../core/data/request.service';
|
import { RequestService } from '../../../../../core/data/request.service';
|
||||||
|
import { PaginationService } from '../../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../../../core/data/request.models';
|
||||||
|
import { PaginationServiceStub } from '../../../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('PaginatedDragAndDropBitstreamListComponent', () => {
|
describe('PaginatedDragAndDropBitstreamListComponent', () => {
|
||||||
let comp: PaginatedDragAndDropBitstreamListComponent;
|
let comp: PaginatedDragAndDropBitstreamListComponent;
|
||||||
@@ -24,6 +29,7 @@ describe('PaginatedDragAndDropBitstreamListComponent', () => {
|
|||||||
let bundleService: BundleDataService;
|
let bundleService: BundleDataService;
|
||||||
let objectValuesPipe: ObjectValuesPipe;
|
let objectValuesPipe: ObjectValuesPipe;
|
||||||
let requestService: RequestService;
|
let requestService: RequestService;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
const columnSizes = new ResponsiveTableSizes([
|
const columnSizes = new ResponsiveTableSizes([
|
||||||
new ResponsiveColumnSizes(2, 2, 3, 4, 4),
|
new ResponsiveColumnSizes(2, 2, 3, 4, 4),
|
||||||
@@ -109,6 +115,8 @@ describe('PaginatedDragAndDropBitstreamListComponent', () => {
|
|||||||
hasByHref$: observableOf(true)
|
hasByHref$: observableOf(true)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot()],
|
imports: [TranslateModule.forRoot()],
|
||||||
declarations: [PaginatedDragAndDropBitstreamListComponent, VarDirective],
|
declarations: [PaginatedDragAndDropBitstreamListComponent, VarDirective],
|
||||||
@@ -116,7 +124,8 @@ describe('PaginatedDragAndDropBitstreamListComponent', () => {
|
|||||||
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
|
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
|
||||||
{ provide: BundleDataService, useValue: bundleService },
|
{ provide: BundleDataService, useValue: bundleService },
|
||||||
{ provide: ObjectValuesPipe, useValue: objectValuesPipe },
|
{ provide: ObjectValuesPipe, useValue: objectValuesPipe },
|
||||||
{ provide: RequestService, useValue: requestService }
|
{ provide: RequestService, useValue: requestService },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
], schemas: [
|
], schemas: [
|
||||||
NO_ERRORS_SCHEMA
|
NO_ERRORS_SCHEMA
|
||||||
]
|
]
|
||||||
|
@@ -10,6 +10,8 @@ import { ResponsiveTableSizes } from '../../../../../shared/responsive-table-siz
|
|||||||
import { followLink } from '../../../../../shared/utils/follow-link-config.model';
|
import { followLink } from '../../../../../shared/utils/follow-link-config.model';
|
||||||
import { ObjectValuesPipe } from '../../../../../shared/utils/object-values-pipe';
|
import { ObjectValuesPipe } from '../../../../../shared/utils/object-values-pipe';
|
||||||
import { RequestService } from '../../../../../core/data/request.service';
|
import { RequestService } from '../../../../../core/data/request.service';
|
||||||
|
import { PaginationService } from '../../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-paginated-drag-and-drop-bitstream-list',
|
selector: 'ds-paginated-drag-and-drop-bitstream-list',
|
||||||
@@ -37,8 +39,9 @@ export class PaginatedDragAndDropBitstreamListComponent extends AbstractPaginate
|
|||||||
protected elRef: ElementRef,
|
protected elRef: ElementRef,
|
||||||
protected objectValuesPipe: ObjectValuesPipe,
|
protected objectValuesPipe: ObjectValuesPipe,
|
||||||
protected bundleService: BundleDataService,
|
protected bundleService: BundleDataService,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected requestService: RequestService) {
|
protected requestService: RequestService) {
|
||||||
super(objectUpdatesService, elRef, objectValuesPipe);
|
super(objectUpdatesService, elRef, objectValuesPipe, paginationService);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -50,8 +53,8 @@ export class PaginatedDragAndDropBitstreamListComponent extends AbstractPaginate
|
|||||||
*/
|
*/
|
||||||
initializeObjectsRD(): void {
|
initializeObjectsRD(): void {
|
||||||
this.objectsRD$ = this.currentPage$.pipe(
|
this.objectsRD$ = this.currentPage$.pipe(
|
||||||
switchMap((page: number) => {
|
switchMap((page: PaginationComponentOptions) => {
|
||||||
const paginatedOptions = new PaginatedSearchOptions({pagination: Object.assign({}, this.options, { currentPage: page })});
|
const paginatedOptions = new PaginatedSearchOptions({pagination: Object.assign({}, page)});
|
||||||
return this.bundleService.getBitstreamsEndpoint(this.bundle.id, paginatedOptions).pipe(
|
return this.bundleService.getBitstreamsEndpoint(this.bundle.id, paginatedOptions).pipe(
|
||||||
switchMap((href) => this.requestService.hasByHref$(href)),
|
switchMap((href) => this.requestService.hasByHref$(href)),
|
||||||
switchMap(() => this.bundleService.getBitstreams(
|
switchMap(() => this.bundleService.getBitstreams(
|
||||||
|
@@ -8,8 +8,7 @@
|
|||||||
[paginationOptions]="originalOptions"
|
[paginationOptions]="originalOptions"
|
||||||
[pageInfoState]="originals"
|
[pageInfoState]="originals"
|
||||||
[collectionSize]="originals?.totalElements"
|
[collectionSize]="originals?.totalElements"
|
||||||
[disableRouteParameterUpdate]="true"
|
[retainScrollPosition]="true">
|
||||||
(pageChange)="switchOriginalPage($event)">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="file-section row" *ngFor="let file of originals?.page;">
|
<div class="file-section row" *ngFor="let file of originals?.page;">
|
||||||
@@ -51,8 +50,7 @@
|
|||||||
[paginationOptions]="licenseOptions"
|
[paginationOptions]="licenseOptions"
|
||||||
[pageInfoState]="licenses"
|
[pageInfoState]="licenses"
|
||||||
[collectionSize]="licenses?.totalElements"
|
[collectionSize]="licenses?.totalElements"
|
||||||
[disableRouteParameterUpdate]="true"
|
[retainScrollPosition]="true">
|
||||||
(pageChange)="switchLicensePage($event)">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="file-section row" *ngFor="let file of licenses?.page;">
|
<div class="file-section row" *ngFor="let file of licenses?.page;">
|
||||||
|
@@ -16,6 +16,11 @@ import { MockBitstreamFormat1 } from '../../../../shared/mocks/item.mock';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||||
|
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('FullFileSectionComponent', () => {
|
describe('FullFileSectionComponent', () => {
|
||||||
let comp: FullFileSectionComponent;
|
let comp: FullFileSectionComponent;
|
||||||
@@ -52,6 +57,8 @@ describe('FullFileSectionComponent', () => {
|
|||||||
findAllByItemAndBundleName: createSuccessfulRemoteDataObject$(createPaginatedList([mockBitstream, mockBitstream, mockBitstream]))
|
findAllByItemAndBundleName: createSuccessfulRemoteDataObject$(createPaginatedList([mockBitstream, mockBitstream, mockBitstream]))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -64,7 +71,8 @@ describe('FullFileSectionComponent', () => {
|
|||||||
declarations: [FullFileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
declarations: [FullFileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
{ provide: BitstreamDataService, useValue: bitstreamDataService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() }
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
],
|
],
|
||||||
|
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -82,39 +90,5 @@ describe('FullFileSectionComponent', () => {
|
|||||||
const fileSection = fixture.debugElement.queryAll(By.css('.file-section'));
|
const fileSection = fixture.debugElement.queryAll(By.css('.file-section'));
|
||||||
expect(fileSection.length).toEqual(6);
|
expect(fileSection.length).toEqual(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when we press the pageChange button for original bundle', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
comp.switchOriginalPage(2);
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should give the value to the currentpage', () => {
|
|
||||||
expect(comp.originalOptions.currentPage).toBe(2);
|
|
||||||
});
|
|
||||||
it('should call the next function on the originalCurrentPage', (done) => {
|
|
||||||
comp.originalCurrentPage$.subscribe((event) => {
|
|
||||||
expect(event).toEqual(2);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when we press the pageChange button for license bundle', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
comp.switchLicensePage(2);
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should give the value to the currentpage', () => {
|
|
||||||
expect(comp.licenseOptions.currentPage).toBe(2);
|
|
||||||
});
|
|
||||||
it('should call the next function on the licenseCurrentPage', (done) => {
|
|
||||||
comp.licenseCurrentPage$.subscribe((event) => {
|
|
||||||
expect(event).toEqual(2);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||||
|
|
||||||
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||||
@@ -13,6 +13,7 @@ import { switchMap, tap } from 'rxjs/operators';
|
|||||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders the file section of the item
|
* This component renders the file section of the item
|
||||||
@@ -35,23 +36,22 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
|||||||
|
|
||||||
pageSize = 5;
|
pageSize = 5;
|
||||||
originalOptions = Object.assign(new PaginationComponentOptions(), {
|
originalOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'original-bitstreams-options',
|
id: 'obo',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: this.pageSize
|
pageSize: this.pageSize
|
||||||
});
|
});
|
||||||
originalCurrentPage$ = new BehaviorSubject<number>(1);
|
|
||||||
|
|
||||||
licenseOptions = Object.assign(new PaginationComponentOptions(), {
|
licenseOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'license-bitstreams-options',
|
id: 'lbo',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: this.pageSize
|
pageSize: this.pageSize
|
||||||
});
|
});
|
||||||
licenseCurrentPage$ = new BehaviorSubject<number>(1);
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
bitstreamDataService: BitstreamDataService,
|
bitstreamDataService: BitstreamDataService,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translateService: TranslateService
|
protected translateService: TranslateService,
|
||||||
|
protected paginationService: PaginationService
|
||||||
) {
|
) {
|
||||||
super(bitstreamDataService, notificationsService, translateService);
|
super(bitstreamDataService, notificationsService, translateService);
|
||||||
}
|
}
|
||||||
@@ -61,11 +61,11 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
|||||||
}
|
}
|
||||||
|
|
||||||
initialize(): void {
|
initialize(): void {
|
||||||
this.originals$ = this.originalCurrentPage$.pipe(
|
this.originals$ = this.paginationService.getCurrentPagination(this.originalOptions.id, this.originalOptions).pipe(
|
||||||
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName(
|
switchMap((options: PaginationComponentOptions) => this.bitstreamDataService.findAllByItemAndBundleName(
|
||||||
this.item,
|
this.item,
|
||||||
'ORIGINAL',
|
'ORIGINAL',
|
||||||
{elementsPerPage: this.pageSize, currentPage: pageNumber},
|
{elementsPerPage: options.pageSize, currentPage: options.currentPage},
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
followLink('format')
|
followLink('format')
|
||||||
@@ -78,11 +78,11 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.licenses$ = this.licenseCurrentPage$.pipe(
|
this.licenses$ = this.paginationService.getCurrentPagination(this.licenseOptions.id, this.licenseOptions).pipe(
|
||||||
switchMap((pageNumber: number) => this.bitstreamDataService.findAllByItemAndBundleName(
|
switchMap((options: PaginationComponentOptions) => this.bitstreamDataService.findAllByItemAndBundleName(
|
||||||
this.item,
|
this.item,
|
||||||
'LICENSE',
|
'LICENSE',
|
||||||
{elementsPerPage: this.pageSize, currentPage: pageNumber},
|
{elementsPerPage: options.pageSize, currentPage: options.currentPage},
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
followLink('format')
|
followLink('format')
|
||||||
@@ -97,25 +97,13 @@ export class FullFileSectionComponent extends FileSectionComponent implements On
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the current page for the original bundle bitstreams
|
|
||||||
* @param page
|
|
||||||
*/
|
|
||||||
switchOriginalPage(page: number) {
|
|
||||||
this.originalOptions.currentPage = page;
|
|
||||||
this.originalCurrentPage$.next(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the current page for the license bundle bitstreams
|
|
||||||
* @param page
|
|
||||||
*/
|
|
||||||
switchLicensePage(page: number) {
|
|
||||||
this.licenseOptions.currentPage = page;
|
|
||||||
this.licenseCurrentPage$.next(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasValuesInBundle(bundle: PaginatedList<Bitstream>) {
|
hasValuesInBundle(bundle: PaginatedList<Bitstream>) {
|
||||||
return hasValue(bundle) && !isEmpty(bundle.page);
|
return hasValue(bundle) && !isEmpty(bundle.page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.paginationService.clearPagination(this.originalOptions.id);
|
||||||
|
this.paginationService.clearPagination(this.licenseOptions.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,8 @@ import { ActivatedRouteStub } from '../shared/testing/active-router.stub';
|
|||||||
import { RoleServiceMock } from '../shared/mocks/role-service.mock';
|
import { RoleServiceMock } from '../shared/mocks/role-service.mock';
|
||||||
import { cold, hot } from 'jasmine-marbles';
|
import { cold, hot } from 'jasmine-marbles';
|
||||||
import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type';
|
import { MyDSpaceConfigurationValueType } from './my-dspace-configuration-value-type';
|
||||||
|
import { PaginationServiceStub } from '../shared/testing/pagination-service.stub';
|
||||||
|
import { PaginationService } from '../core/pagination/pagination.service';
|
||||||
|
|
||||||
describe('MyDSpaceConfigurationService', () => {
|
describe('MyDSpaceConfigurationService', () => {
|
||||||
let service: MyDSpaceConfigurationService;
|
let service: MyDSpaceConfigurationService;
|
||||||
@@ -34,12 +36,13 @@ describe('MyDSpaceConfigurationService', () => {
|
|||||||
getRouteDataValue: observableOf({})
|
getRouteDataValue: observableOf({})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
const activatedRoute: any = new ActivatedRouteStub();
|
const activatedRoute: any = new ActivatedRouteStub();
|
||||||
|
|
||||||
const roleService: any = new RoleServiceMock();
|
const roleService: any = new RoleServiceMock();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service = new MyDSpaceConfigurationService(roleService, spy, activatedRoute);
|
service = new MyDSpaceConfigurationService(roleService, spy, paginationService as any, activatedRoute);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the scope is called', () => {
|
describe('when the scope is called', () => {
|
||||||
@@ -102,25 +105,19 @@ describe('MyDSpaceConfigurationService', () => {
|
|||||||
|
|
||||||
describe('when getCurrentSort is called', () => {
|
describe('when getCurrentSort is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service.getCurrentSort({} as any);
|
service.getCurrentSort('page-id', defaults.sort);
|
||||||
});
|
});
|
||||||
it('should call getQueryParameterValue on the routeService with parameter name \'sortDirection\'', () => {
|
it('should call getCurrentSort on the paginationService with the provided id and sort options', () => {
|
||||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortDirection');
|
expect((service as any).paginationService.getCurrentSort).toHaveBeenCalledWith('page-id', defaults.sort);
|
||||||
});
|
|
||||||
it('should call getQueryParameterValue on the routeService with parameter name \'sortField\'', () => {
|
|
||||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortField');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when getCurrentPagination is called', () => {
|
describe('when getCurrentPagination is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service.getCurrentPagination({ currentPage: 1, pageSize: 10 } as any);
|
service.getCurrentPagination('page-id', defaults.pagination);
|
||||||
});
|
});
|
||||||
it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => {
|
it('should call getCurrentPagination on the paginationService with the provided id and sort options', () => {
|
||||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page');
|
expect((service as any).paginationService.getCurrentPagination).toHaveBeenCalledWith('page-id', defaults.pagination);
|
||||||
});
|
|
||||||
it('should call getQueryParameterValue on the routeService with parameter name \'pageSize\'', () => {
|
|
||||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('pageSize');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -152,7 +149,7 @@ describe('MyDSpaceConfigurationService', () => {
|
|||||||
|
|
||||||
describe('when subscribeToPaginatedSearchOptions is called', () => {
|
describe('when subscribeToPaginatedSearchOptions is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
(service as any).subscribeToPaginatedSearchOptions(defaults);
|
(service as any).subscribeToPaginatedSearchOptions('id', defaults);
|
||||||
});
|
});
|
||||||
it('should call all getters it needs', () => {
|
it('should call all getters it needs', () => {
|
||||||
expect(service.getCurrentPagination).toHaveBeenCalled();
|
expect(service.getCurrentPagination).toHaveBeenCalled();
|
||||||
|
@@ -11,6 +11,7 @@ import { SearchConfigurationService } from '../core/shared/search/search-configu
|
|||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
||||||
import { RouteService } from '../core/services/route.service';
|
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
|
* Service that performs all actions that have to do with the current mydspace configuration
|
||||||
@@ -55,13 +56,15 @@ export class MyDSpaceConfigurationService extends SearchConfigurationService {
|
|||||||
*
|
*
|
||||||
* @param {roleService} roleService
|
* @param {roleService} roleService
|
||||||
* @param {RouteService} routeService
|
* @param {RouteService} routeService
|
||||||
|
* @param {PaginationService} paginationService
|
||||||
* @param {ActivatedRoute} route
|
* @param {ActivatedRoute} route
|
||||||
*/
|
*/
|
||||||
constructor(protected roleService: RoleService,
|
constructor(protected roleService: RoleService,
|
||||||
protected routeService: RouteService,
|
protected routeService: RouteService,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected route: ActivatedRoute) {
|
protected route: ActivatedRoute) {
|
||||||
|
|
||||||
super(routeService, route);
|
super(routeService, paginationService, route);
|
||||||
|
|
||||||
// override parent class initialization
|
// override parent class initialization
|
||||||
this._defaults = null;
|
this._defaults = null;
|
||||||
|
@@ -52,8 +52,7 @@
|
|||||||
[pageInfoState]="pageInfoState$"
|
[pageInfoState]="pageInfoState$"
|
||||||
[collectionSize]="(pageInfoState$ | async)?.totalElements"
|
[collectionSize]="(pageInfoState$ | async)?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="epeople" class="table table-striped table-hover table-bordered">
|
<table id="epeople" class="table table-striped table-hover table-bordered">
|
||||||
|
@@ -25,6 +25,8 @@ import { NotificationsServiceStub } from '../../shared/testing/notifications-ser
|
|||||||
import { RouterStub } from '../../shared/testing/router.stub';
|
import { RouterStub } from '../../shared/testing/router.stub';
|
||||||
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
import { RequestService } from '../../core/data/request.service';
|
import { RequestService } from '../../core/data/request.service';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('EPeopleRegistryComponent', () => {
|
describe('EPeopleRegistryComponent', () => {
|
||||||
let component: EPeopleRegistryComponent;
|
let component: EPeopleRegistryComponent;
|
||||||
@@ -37,6 +39,8 @@ describe('EPeopleRegistryComponent', () => {
|
|||||||
let authorizationService: AuthorizationDataService;
|
let authorizationService: AuthorizationDataService;
|
||||||
let modalService;
|
let modalService;
|
||||||
|
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
mockEPeople = [EPersonMock, EPersonMock2];
|
mockEPeople = [EPersonMock, EPersonMock2];
|
||||||
ePersonDataServiceStub = {
|
ePersonDataServiceStub = {
|
||||||
@@ -115,6 +119,8 @@ describe('EPeopleRegistryComponent', () => {
|
|||||||
});
|
});
|
||||||
builderService = getMockFormBuilderService();
|
builderService = getMockFormBuilderService();
|
||||||
translateService = getMockTranslateService();
|
translateService = getMockTranslateService();
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
@@ -131,7 +137,8 @@ describe('EPeopleRegistryComponent', () => {
|
|||||||
{ provide: AuthorizationDataService, useValue: authorizationService },
|
{ provide: AuthorizationDataService, useValue: authorizationService },
|
||||||
{ provide: FormBuilderService, useValue: builderService },
|
{ provide: FormBuilderService, useValue: builderService },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }
|
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
@@ -4,7 +4,7 @@ import { Router } from '@angular/router';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
|
import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
|
||||||
import { map, switchMap, take } from 'rxjs/operators';
|
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 { RemoteData } from '../../core/data/remote-data';
|
||||||
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
||||||
import { EPerson } from '../../core/eperson/models/eperson.model';
|
import { EPerson } from '../../core/eperson/models/eperson.model';
|
||||||
@@ -14,15 +14,13 @@ import { PaginationComponentOptions } from '../../shared/pagination/pagination-c
|
|||||||
import { EpersonDtoModel } from '../../core/eperson/models/eperson-dto.model';
|
import { EpersonDtoModel } from '../../core/eperson/models/eperson-dto.model';
|
||||||
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
|
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
|
||||||
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
import {
|
import { getAllSucceededRemoteData, getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||||
getFirstCompletedRemoteData,
|
|
||||||
getAllSucceededRemoteData
|
|
||||||
} from '../../core/shared/operators';
|
|
||||||
import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component';
|
import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component';
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { RequestService } from '../../core/data/request.service';
|
import { RequestService } from '../../core/data/request.service';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../core/shared/page-info.model';
|
||||||
import { NoContent } from '../../core/shared/NoContent.model';
|
import { NoContent } from '../../core/shared/NoContent.model';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-epeople-registry',
|
selector: 'ds-epeople-registry',
|
||||||
@@ -60,7 +58,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
|
|||||||
* Pagination config used to display the list of epeople
|
* Pagination config used to display the list of epeople
|
||||||
*/
|
*/
|
||||||
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'epeople-list-pagination',
|
id: 'elp',
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
@@ -78,9 +76,9 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
|
|||||||
currentSearchScope: string;
|
currentSearchScope: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The subscription for the search method
|
* FindListOptions
|
||||||
*/
|
*/
|
||||||
searchSub: Subscription;
|
findListOptionsSub: Subscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of subscriptions
|
* List of subscriptions
|
||||||
@@ -94,6 +92,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
|
|||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private modalService: NgbModal,
|
private modalService: NgbModal,
|
||||||
|
private paginationService: PaginationService,
|
||||||
public requestService: RequestService) {
|
public requestService: RequestService) {
|
||||||
this.currentSearchQuery = '';
|
this.currentSearchQuery = '';
|
||||||
this.currentSearchScope = 'metadata';
|
this.currentSearchScope = 'metadata';
|
||||||
@@ -113,7 +112,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
|
|||||||
initialisePage() {
|
initialisePage() {
|
||||||
this.searching$.next(true);
|
this.searching$.next(true);
|
||||||
this.isEPersonFormShown = false;
|
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) => {
|
this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => {
|
||||||
if (eperson != null && eperson.id) {
|
if (eperson != null && eperson.id) {
|
||||||
this.isEPersonFormShown = true;
|
this.isEPersonFormShown = true;
|
||||||
@@ -139,56 +138,51 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
|
|||||||
return [epeople];
|
return [epeople];
|
||||||
}
|
}
|
||||||
})).subscribe((value: PaginatedList<EpersonDtoModel>) => {
|
})).subscribe((value: PaginatedList<EpersonDtoModel>) => {
|
||||||
this.searching$.next(false);
|
this.searching$.next(false);this.ePeopleDto$.next(value);
|
||||||
this.ePeopleDto$.next(value);
|
this.pageInfoState$.next(value.pageInfo);
|
||||||
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
|
* Search in the EPeople by metadata (default) or email
|
||||||
* @param data Contains scope and query param
|
* @param data Contains scope and query param
|
||||||
*/
|
*/
|
||||||
search(data: any) {
|
search(data: any) {
|
||||||
this.searching$.next(true);
|
this.searching$.next(true);
|
||||||
const query: string = data.query;
|
if (hasValue(this.findListOptionsSub)) {
|
||||||
const scope: string = data.scope;
|
this.findListOptionsSub.unsubscribe();
|
||||||
if (query != null && this.currentSearchQuery !== query) {
|
|
||||||
this.router.navigateByUrl(this.epersonService.getEPeoplePageRouterLink());
|
|
||||||
this.currentSearchQuery = query;
|
|
||||||
this.config.currentPage = 1;
|
|
||||||
}
|
}
|
||||||
if (scope != null && this.currentSearchScope !== scope) {
|
this.findListOptionsSub = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe(
|
||||||
this.router.navigateByUrl(this.epersonService.getEPeoplePageRouterLink());
|
switchMap((findListOptions) => {
|
||||||
this.currentSearchScope = scope;
|
const query: string = data.query;
|
||||||
this.config.currentPage = 1;
|
const scope: string = data.scope;
|
||||||
}
|
if (query != null && this.currentSearchQuery !== query) {
|
||||||
if (hasValue(this.searchSub)) {
|
this.router.navigate([this.epersonService.getEPeoplePageRouterLink()], {
|
||||||
this.searchSub.unsubscribe();
|
queryParamsHandling: 'merge'
|
||||||
this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub);
|
});
|
||||||
}
|
this.currentSearchQuery = query;
|
||||||
this.searchSub = this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, {
|
this.paginationService.resetPage(this.config.id);
|
||||||
currentPage: this.config.currentPage,
|
}
|
||||||
elementsPerPage: this.config.pageSize
|
if (scope != null && this.currentSearchScope !== scope) {
|
||||||
}).pipe(
|
this.router.navigate([this.epersonService.getEPeoplePageRouterLink()], {
|
||||||
|
queryParamsHandling: 'merge'
|
||||||
|
});
|
||||||
|
this.currentSearchScope = scope;
|
||||||
|
this.paginationService.resetPage(this.config.id);
|
||||||
|
|
||||||
|
}
|
||||||
|
return this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, {
|
||||||
|
currentPage: findListOptions.currentPage,
|
||||||
|
elementsPerPage: findListOptions.pageSize
|
||||||
|
});
|
||||||
|
}
|
||||||
|
),
|
||||||
getAllSucceededRemoteData(),
|
getAllSucceededRemoteData(),
|
||||||
).subscribe((peopleRD) => {
|
).subscribe((peopleRD) => {
|
||||||
this.ePeople$.next(peopleRD.payload);
|
this.ePeople$.next(peopleRD.payload);
|
||||||
this.pageInfoState$.next(peopleRD.payload.pageInfo);
|
this.pageInfoState$.next(peopleRD.payload.pageInfo);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.subs.push(this.searchSub);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,7 +237,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
|
|||||||
if (hasValue(ePerson.id)) {
|
if (hasValue(ePerson.id)) {
|
||||||
this.epersonService.deleteEPerson(ePerson).pipe(getFirstCompletedRemoteData()).subscribe((restResponse: RemoteData<NoContent>) => {
|
this.epersonService.deleteEPerson(ePerson).pipe(getFirstCompletedRemoteData()).subscribe((restResponse: RemoteData<NoContent>) => {
|
||||||
if (restResponse.hasSucceeded) {
|
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();
|
this.reset();
|
||||||
} else {
|
} else {
|
||||||
this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + ePerson.id + ' with code: ' + restResponse.statusCode + ' and message: ' + restResponse.errorMessage);
|
this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + ePerson.id + ' with code: ' + restResponse.statusCode + ' and message: ' + restResponse.errorMessage);
|
||||||
@@ -260,8 +254,10 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.cleanupSubscribes();
|
this.cleanupSubscribes();
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cleanupSubscribes() {
|
cleanupSubscribes() {
|
||||||
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
||||||
}
|
}
|
||||||
@@ -283,7 +279,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy {
|
|||||||
this.searchForm.patchValue({
|
this.searchForm.patchValue({
|
||||||
query: '',
|
query: '',
|
||||||
});
|
});
|
||||||
this.search({ query: '' });
|
this.search({query: ''});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -26,6 +26,8 @@ import { AuthorizationDataService } from '../../../core/data/feature-authorizati
|
|||||||
import { GroupDataService } from '../../../core/eperson/group-data.service';
|
import { GroupDataService } from '../../../core/eperson/group-data.service';
|
||||||
import { createPaginatedList } from '../../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../../shared/testing/utils.test';
|
||||||
import { RequestService } from '../../../core/data/request.service';
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('EPersonFormComponent', () => {
|
describe('EPersonFormComponent', () => {
|
||||||
let component: EPersonFormComponent;
|
let component: EPersonFormComponent;
|
||||||
@@ -38,6 +40,10 @@ describe('EPersonFormComponent', () => {
|
|||||||
let authorizationService: AuthorizationDataService;
|
let authorizationService: AuthorizationDataService;
|
||||||
let groupsDataService: GroupDataService;
|
let groupsDataService: GroupDataService;
|
||||||
|
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
mockEPeople = [EPersonMock, EPersonMock2];
|
mockEPeople = [EPersonMock, EPersonMock2];
|
||||||
ePersonDataServiceStub = {
|
ePersonDataServiceStub = {
|
||||||
@@ -104,6 +110,8 @@ describe('EPersonFormComponent', () => {
|
|||||||
findAllByHref: createSuccessfulRemoteDataObject$(createPaginatedList([])),
|
findAllByHref: createSuccessfulRemoteDataObject$(createPaginatedList([])),
|
||||||
getGroupRegistryRouterLink: ''
|
getGroupRegistryRouterLink: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
@@ -121,6 +129,7 @@ describe('EPersonFormComponent', () => {
|
|||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
{ provide: AuthService, useValue: authService },
|
{ provide: AuthService, useValue: authService },
|
||||||
{ provide: AuthorizationDataService, useValue: authorizationService },
|
{ provide: AuthorizationDataService, useValue: authorizationService },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }
|
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -7,7 +7,7 @@ import {
|
|||||||
DynamicInputModel
|
DynamicInputModel
|
||||||
} from '@ng-dynamic-forms/core';
|
} from '@ng-dynamic-forms/core';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { combineLatest, Observable, of, Subscription } from 'rxjs';
|
import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs';
|
||||||
import { switchMap, take } from 'rxjs/operators';
|
import { switchMap, take } from 'rxjs/operators';
|
||||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
@@ -16,9 +16,9 @@ import { GroupDataService } from '../../../core/eperson/group-data.service';
|
|||||||
import { EPerson } from '../../../core/eperson/models/eperson.model';
|
import { EPerson } from '../../../core/eperson/models/eperson.model';
|
||||||
import { Group } from '../../../core/eperson/models/group.model';
|
import { Group } from '../../../core/eperson/models/group.model';
|
||||||
import {
|
import {
|
||||||
getRemoteDataPayload,
|
getFirstCompletedRemoteData,
|
||||||
getFirstSucceededRemoteData,
|
getFirstSucceededRemoteData,
|
||||||
getFirstCompletedRemoteData
|
getRemoteDataPayload
|
||||||
} from '../../../core/shared/operators';
|
} from '../../../core/shared/operators';
|
||||||
import { hasValue } from '../../../shared/empty.util';
|
import { hasValue } from '../../../shared/empty.util';
|
||||||
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
|
import { FormBuilderService } from '../../../shared/form/builder/form-builder.service';
|
||||||
@@ -31,6 +31,7 @@ import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/c
|
|||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { RequestService } from '../../../core/data/request.service';
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
import { NoContent } from '../../../core/shared/NoContent.model';
|
import { NoContent } from '../../../core/shared/NoContent.model';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-eperson-form',
|
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
|
* 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)
|
* 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
|
* 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
|
* Pagination config used to display the list of groups
|
||||||
*/
|
*/
|
||||||
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'groups-ePersonMemberOf-list-pagination',
|
id: 'gem',
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
@@ -167,6 +168,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
|
|||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private authorizationService: AuthorizationDataService,
|
private authorizationService: AuthorizationDataService,
|
||||||
private modalService: NgbModal,
|
private modalService: NgbModal,
|
||||||
|
private paginationService: PaginationService,
|
||||||
public requestService: RequestService) {
|
public requestService: RequestService) {
|
||||||
this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => {
|
this.subs.push(this.epersonService.getActiveEPerson().subscribe((eperson: EPerson) => {
|
||||||
this.epersonInitial = eperson;
|
this.epersonInitial = eperson;
|
||||||
@@ -184,13 +186,13 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
|
|||||||
* This method will initialise the page
|
* This method will initialise the page
|
||||||
*/
|
*/
|
||||||
initialisePage() {
|
initialisePage() {
|
||||||
combineLatest(
|
observableCombineLatest(
|
||||||
this.translateService.get(`${this.messagePrefix}.firstName`),
|
this.translateService.get(`${this.messagePrefix}.firstName`),
|
||||||
this.translateService.get(`${this.messagePrefix}.lastName`),
|
this.translateService.get(`${this.messagePrefix}.lastName`),
|
||||||
this.translateService.get(`${this.messagePrefix}.email`),
|
this.translateService.get(`${this.messagePrefix}.email`),
|
||||||
this.translateService.get(`${this.messagePrefix}.canLogIn`),
|
this.translateService.get(`${this.messagePrefix}.canLogIn`),
|
||||||
this.translateService.get(`${this.messagePrefix}.requireCertificate`),
|
this.translateService.get(`${this.messagePrefix}.requireCertificate`),
|
||||||
this.translateService.get(`${this.messagePrefix}.emailHint`),
|
this.translateService.get(`${this.messagePrefix}.emailHint`),
|
||||||
).subscribe(([firstName, lastName, email, canLogIn, requireCertificate, emailHint]) => {
|
).subscribe(([firstName, lastName, email, canLogIn, requireCertificate, emailHint]) => {
|
||||||
this.firstName = new DynamicInputModel({
|
this.firstName = new DynamicInputModel({
|
||||||
id: 'firstName',
|
id: 'firstName',
|
||||||
@@ -222,19 +224,19 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
|
|||||||
hint: emailHint
|
hint: emailHint
|
||||||
});
|
});
|
||||||
this.canLogIn = new DynamicCheckboxModel(
|
this.canLogIn = new DynamicCheckboxModel(
|
||||||
{
|
{
|
||||||
id: 'canLogIn',
|
id: 'canLogIn',
|
||||||
label: canLogIn,
|
label: canLogIn,
|
||||||
name: 'canLogIn',
|
name: 'canLogIn',
|
||||||
value: (this.epersonInitial != null ? this.epersonInitial.canLogIn : true)
|
value: (this.epersonInitial != null ? this.epersonInitial.canLogIn : true)
|
||||||
});
|
});
|
||||||
this.requireCertificate = new DynamicCheckboxModel(
|
this.requireCertificate = new DynamicCheckboxModel(
|
||||||
{
|
{
|
||||||
id: 'requireCertificate',
|
id: 'requireCertificate',
|
||||||
label: requireCertificate,
|
label: requireCertificate,
|
||||||
name: 'requireCertificate',
|
name: 'requireCertificate',
|
||||||
value: (this.epersonInitial != null ? this.epersonInitial.requireCertificate : false)
|
value: (this.epersonInitial != null ? this.epersonInitial.requireCertificate : false)
|
||||||
});
|
});
|
||||||
this.formModel = [
|
this.formModel = [
|
||||||
this.firstName,
|
this.firstName,
|
||||||
this.lastName,
|
this.lastName,
|
||||||
@@ -258,11 +260,29 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
|
|||||||
requireCertificate: eperson != null ? eperson.requireCertificate : false
|
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]) => {
|
||||||
|
if (eperson != null) {
|
||||||
|
return this.groupsDataService.findAllByHref(eperson._links.groups.href, findListOptions);
|
||||||
|
}
|
||||||
|
return observableOf(undefined);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
this.canDelete$ = this.epersonService.getActiveEPerson().pipe(
|
|
||||||
switchMap((eperson) => this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(eperson) ? eperson.self : undefined))
|
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 +342,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
|
|||||||
getFirstCompletedRemoteData()
|
getFirstCompletedRemoteData()
|
||||||
).subscribe((rd: RemoteData<EPerson>) => {
|
).subscribe((rd: RemoteData<EPerson>) => {
|
||||||
if (rd.hasSucceeded) {
|
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);
|
this.submitForm.emit(ePersonToCreate);
|
||||||
} else {
|
} 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();
|
this.cancelForm.emit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -361,10 +381,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
|
|||||||
const response = this.epersonService.updateEPerson(editedEperson);
|
const response = this.epersonService.updateEPerson(editedEperson);
|
||||||
response.pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData<EPerson>) => {
|
response.pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData<EPerson>) => {
|
||||||
if (rd.hasSucceeded) {
|
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);
|
this.submitForm.emit(editedEperson);
|
||||||
} else {
|
} 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();
|
this.cancelForm.emit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -469,8 +489,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
|
|||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.onCancel();
|
this.onCancel();
|
||||||
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will ensure that the page gets reset and that the cache is cleared
|
* This method will ensure that the page gets reset and that the cache is cleared
|
||||||
*/
|
*/
|
||||||
|
@@ -32,8 +32,7 @@
|
|||||||
[pageInfoState]="(ePeopleSearchDtos | async)"
|
[pageInfoState]="(ePeopleSearchDtos | async)"
|
||||||
[collectionSize]="(ePeopleSearchDtos | async)?.totalElements"
|
[collectionSize]="(ePeopleSearchDtos | async)?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChangeSearch($event)">
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="epersonsSearch" class="table table-striped table-hover table-bordered">
|
<table id="epersonsSearch" class="table table-striped table-hover table-bordered">
|
||||||
@@ -86,8 +85,7 @@
|
|||||||
[pageInfoState]="(ePeopleMembersOfGroupDtos | async)"
|
[pageInfoState]="(ePeopleMembersOfGroupDtos | async)"
|
||||||
[collectionSize]="(ePeopleMembersOfGroupDtos | async)?.totalElements"
|
[collectionSize]="(ePeopleMembersOfGroupDtos | async)?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="ePeopleMembersOfGroup" class="table table-striped table-hover table-bordered">
|
<table id="ePeopleMembersOfGroup" class="table table-striped table-hover table-bordered">
|
||||||
|
@@ -26,6 +26,8 @@ import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder
|
|||||||
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
|
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
|
||||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||||
import { RouterMock } from '../../../../shared/mocks/router.mock';
|
import { RouterMock } from '../../../../shared/mocks/router.mock';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('MembersListComponent', () => {
|
describe('MembersListComponent', () => {
|
||||||
let component: MembersListComponent;
|
let component: MembersListComponent;
|
||||||
@@ -39,6 +41,7 @@ describe('MembersListComponent', () => {
|
|||||||
let allGroups;
|
let allGroups;
|
||||||
let epersonMembers;
|
let epersonMembers;
|
||||||
let subgroupMembers;
|
let subgroupMembers;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
activeGroup = GroupMock;
|
activeGroup = GroupMock;
|
||||||
@@ -113,6 +116,8 @@ describe('MembersListComponent', () => {
|
|||||||
};
|
};
|
||||||
builderService = getMockFormBuilderService();
|
builderService = getMockFormBuilderService();
|
||||||
translateService = getMockTranslateService();
|
translateService = getMockTranslateService();
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
@@ -129,6 +134,7 @@ describe('MembersListComponent', () => {
|
|||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
{ provide: FormBuilderService, useValue: builderService },
|
{ provide: FormBuilderService, useValue: builderService },
|
||||||
{ provide: Router, useValue: new RouterMock() },
|
{ provide: Router, useValue: new RouterMock() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
@@ -18,13 +18,13 @@ import { GroupDataService } from '../../../../core/eperson/group-data.service';
|
|||||||
import { EPerson } from '../../../../core/eperson/models/eperson.model';
|
import { EPerson } from '../../../../core/eperson/models/eperson.model';
|
||||||
import { Group } from '../../../../core/eperson/models/group.model';
|
import { Group } from '../../../../core/eperson/models/group.model';
|
||||||
import {
|
import {
|
||||||
getRemoteDataPayload,
|
|
||||||
getFirstSucceededRemoteData,
|
getFirstSucceededRemoteData,
|
||||||
getFirstCompletedRemoteData, getAllCompletedRemoteData
|
getFirstCompletedRemoteData, getAllCompletedRemoteData, getRemoteDataPayload
|
||||||
} from '../../../../core/shared/operators';
|
} from '../../../../core/shared/operators';
|
||||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
|
||||||
import {EpersonDtoModel} from '../../../../core/eperson/models/eperson-dto.model';
|
import {EpersonDtoModel} from '../../../../core/eperson/models/eperson-dto.model';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keys to keep track of specific subscriptions
|
* Keys to keep track of specific subscriptions
|
||||||
@@ -60,7 +60,7 @@ export class MembersListComponent implements OnInit, OnDestroy {
|
|||||||
* Pagination config used to display the list of EPeople that are result of EPeople search
|
* Pagination config used to display the list of EPeople that are result of EPeople search
|
||||||
*/
|
*/
|
||||||
configSearch: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
configSearch: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'search-members-list-pagination',
|
id: 'sml',
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
@@ -68,7 +68,7 @@ export class MembersListComponent implements OnInit, OnDestroy {
|
|||||||
* Pagination config used to display the list of EPerson Membes of active group being edited
|
* Pagination config used to display the list of EPerson Membes of active group being edited
|
||||||
*/
|
*/
|
||||||
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'members-list-pagination',
|
id: 'ml',
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
@@ -91,11 +91,15 @@ export class MembersListComponent implements OnInit, OnDestroy {
|
|||||||
// current active group being edited
|
// current active group being edited
|
||||||
groupBeingEdited: Group;
|
groupBeingEdited: Group;
|
||||||
|
|
||||||
|
paginationSub: Subscription;
|
||||||
|
|
||||||
|
|
||||||
constructor(private groupDataService: GroupDataService,
|
constructor(private groupDataService: GroupDataService,
|
||||||
public ePersonDataService: EPersonDataService,
|
public ePersonDataService: EPersonDataService,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
|
private paginationService: PaginationService,
|
||||||
private router: Router) {
|
private router: Router) {
|
||||||
this.currentSearchQuery = '';
|
this.currentSearchQuery = '';
|
||||||
this.currentSearchScope = 'metadata';
|
this.currentSearchScope = 'metadata';
|
||||||
@@ -114,23 +118,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
|
* Retrieve the EPersons that are members of the group
|
||||||
*
|
*
|
||||||
@@ -139,10 +126,15 @@ export class MembersListComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
private retrieveMembers(page: number) {
|
private retrieveMembers(page: number) {
|
||||||
this.unsubFrom(SubKey.MembersDTO);
|
this.unsubFrom(SubKey.MembersDTO);
|
||||||
this.subs.set(SubKey.MembersDTO, this.ePersonDataService.findAllByHref(this.groupBeingEdited._links.epersons.href, {
|
this.subs.set(SubKey.MembersDTO,
|
||||||
currentPage: page,
|
this.paginationService.getCurrentPagination(this.config.id, this.config).pipe(
|
||||||
elementsPerPage: this.config.pageSize
|
switchMap((currentPagination) => {
|
||||||
}).pipe(
|
return this.ePersonDataService.findAllByHref(this.groupBeingEdited._links.epersons.href, {
|
||||||
|
currentPage: currentPagination.currentPage,
|
||||||
|
elementsPerPage: currentPagination.pageSize
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}),
|
||||||
getAllCompletedRemoteData(),
|
getAllCompletedRemoteData(),
|
||||||
map((rd: RemoteData<any>) => {
|
map((rd: RemoteData<any>) => {
|
||||||
if (rd.hasFailed) {
|
if (rd.hasFailed) {
|
||||||
@@ -245,26 +237,34 @@ export class MembersListComponent implements OnInit, OnDestroy {
|
|||||||
* @param data Contains scope and query param
|
* @param data Contains scope and query param
|
||||||
*/
|
*/
|
||||||
search(data: any) {
|
search(data: any) {
|
||||||
const query: string = data.query;
|
|
||||||
const scope: string = data.scope;
|
|
||||||
if (query != null && this.currentSearchQuery !== query && this.groupBeingEdited) {
|
|
||||||
this.router.navigateByUrl(this.groupDataService.getGroupEditPageRouterLink(this.groupBeingEdited));
|
|
||||||
this.currentSearchQuery = query;
|
|
||||||
this.configSearch.currentPage = 1;
|
|
||||||
}
|
|
||||||
if (scope != null && this.currentSearchScope !== scope && this.groupBeingEdited) {
|
|
||||||
this.router.navigateByUrl(this.groupDataService.getGroupEditPageRouterLink(this.groupBeingEdited));
|
|
||||||
this.currentSearchScope = scope;
|
|
||||||
this.configSearch.currentPage = 1;
|
|
||||||
}
|
|
||||||
this.searchDone = true;
|
|
||||||
|
|
||||||
this.unsubFrom(SubKey.SearchResultsDTO);
|
this.unsubFrom(SubKey.SearchResultsDTO);
|
||||||
this.subs.set(SubKey.SearchResultsDTO,
|
this.subs.set(SubKey.SearchResultsDTO,
|
||||||
this.ePersonDataService.searchByScope(this.currentSearchScope, this.currentSearchQuery, {
|
this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe(
|
||||||
currentPage: this.configSearch.currentPage,
|
switchMap((paginationOptions) => {
|
||||||
elementsPerPage: this.configSearch.pageSize
|
|
||||||
}, false).pipe(
|
const query: string = data.query;
|
||||||
|
const scope: string = data.scope;
|
||||||
|
if (query != null && this.currentSearchQuery !== query && this.groupBeingEdited) {
|
||||||
|
this.router.navigate([], {
|
||||||
|
queryParamsHandling: 'merge'
|
||||||
|
});
|
||||||
|
this.currentSearchQuery = query;
|
||||||
|
this.paginationService.resetPage(this.configSearch.id);
|
||||||
|
}
|
||||||
|
if (scope != null && this.currentSearchScope !== scope && this.groupBeingEdited) {
|
||||||
|
this.router.navigate([], {
|
||||||
|
queryParamsHandling: 'merge'
|
||||||
|
});
|
||||||
|
this.currentSearchScope = scope;
|
||||||
|
this.paginationService.resetPage(this.configSearch.id);
|
||||||
|
}
|
||||||
|
this.searchDone = true;
|
||||||
|
|
||||||
|
return this.ePersonDataService.searchByScope(this.currentSearchScope, this.currentSearchQuery, {
|
||||||
|
currentPage: paginationOptions.currentPage,
|
||||||
|
elementsPerPage: paginationOptions.pageSize
|
||||||
|
});
|
||||||
|
}),
|
||||||
getAllCompletedRemoteData(),
|
getAllCompletedRemoteData(),
|
||||||
map((rd: RemoteData<any>) => {
|
map((rd: RemoteData<any>) => {
|
||||||
if (rd.hasFailed) {
|
if (rd.hasFailed) {
|
||||||
@@ -300,6 +300,8 @@ export class MembersListComponent implements OnInit, OnDestroy {
|
|||||||
for (const key of this.subs.keys()) {
|
for (const key of this.subs.keys()) {
|
||||||
this.unsubFrom(key);
|
this.unsubFrom(key);
|
||||||
}
|
}
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
|
this.paginationService.clearPagination(this.configSearch.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -29,8 +29,7 @@
|
|||||||
[pageInfoState]="(searchResults$ | async)?.payload"
|
[pageInfoState]="(searchResults$ | async)?.payload"
|
||||||
[collectionSize]="(searchResults$ | async)?.payload?.totalElements"
|
[collectionSize]="(searchResults$ | async)?.payload?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChangeSearch($event)">
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="groupsSearch" class="table table-striped table-hover table-bordered">
|
<table id="groupsSearch" class="table table-striped table-hover table-bordered">
|
||||||
@@ -83,8 +82,7 @@
|
|||||||
[pageInfoState]="(subGroups$ | async)?.payload"
|
[pageInfoState]="(subGroups$ | async)?.payload"
|
||||||
[collectionSize]="(subGroups$ | async)?.payload?.totalElements"
|
[collectionSize]="(subGroups$ | async)?.payload?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="subgroupsOfGroup" class="table table-striped table-hover table-bordered">
|
<table id="subgroupsOfGroup" class="table table-striped table-hover table-bordered">
|
||||||
|
@@ -35,6 +35,8 @@ import { getMockTranslateService } from '../../../../shared/mocks/translate.serv
|
|||||||
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
|
import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock';
|
||||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SubgroupsListComponent', () => {
|
describe('SubgroupsListComponent', () => {
|
||||||
let component: SubgroupsListComponent;
|
let component: SubgroupsListComponent;
|
||||||
@@ -47,6 +49,7 @@ describe('SubgroupsListComponent', () => {
|
|||||||
let subgroups;
|
let subgroups;
|
||||||
let allGroups;
|
let allGroups;
|
||||||
let routerStub;
|
let routerStub;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
activeGroup = GroupMock;
|
activeGroup = GroupMock;
|
||||||
@@ -100,6 +103,8 @@ describe('SubgroupsListComponent', () => {
|
|||||||
routerStub = new RouterMock();
|
routerStub = new RouterMock();
|
||||||
builderService = getMockFormBuilderService();
|
builderService = getMockFormBuilderService();
|
||||||
translateService = getMockTranslateService();
|
translateService = getMockTranslateService();
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
@@ -115,6 +120,7 @@ describe('SubgroupsListComponent', () => {
|
|||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
{ provide: FormBuilderService, useValue: builderService },
|
{ provide: FormBuilderService, useValue: builderService },
|
||||||
{ provide: Router, useValue: routerStub },
|
{ provide: Router, useValue: routerStub },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
@@ -2,20 +2,21 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
|||||||
import { FormBuilder } from '@angular/forms';
|
import { FormBuilder } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Observable, of as observableOf, Subscription, BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject, Observable, of as observableOf, Subscription } from 'rxjs';
|
||||||
import { map, mergeMap, take } from 'rxjs/operators';
|
import { map, mergeMap, switchMap, take } from 'rxjs/operators';
|
||||||
import { PaginatedList } from '../../../../core/data/paginated-list.model';
|
import { PaginatedList } from '../../../../core/data/paginated-list.model';
|
||||||
import { RemoteData } from '../../../../core/data/remote-data';
|
import { RemoteData } from '../../../../core/data/remote-data';
|
||||||
import { GroupDataService } from '../../../../core/eperson/group-data.service';
|
import { GroupDataService } from '../../../../core/eperson/group-data.service';
|
||||||
import { Group } from '../../../../core/eperson/models/group.model';
|
import { Group } from '../../../../core/eperson/models/group.model';
|
||||||
import {
|
import {
|
||||||
getRemoteDataPayload,
|
getFirstCompletedRemoteData,
|
||||||
getFirstSucceededRemoteData,
|
getFirstSucceededRemoteData,
|
||||||
getFirstCompletedRemoteData
|
getRemoteDataPayload
|
||||||
} from '../../../../core/shared/operators';
|
} from '../../../../core/shared/operators';
|
||||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||||
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
|
||||||
import { NoContent } from '../../../../core/shared/NoContent.model';
|
import { NoContent } from '../../../../core/shared/NoContent.model';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keys to keep track of specific subscriptions
|
* 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
|
* Pagination config used to display the list of groups that are result of groups search
|
||||||
*/
|
*/
|
||||||
configSearch: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
configSearch: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'search-subgroups-list-pagination',
|
id: 'ssgl',
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
currentPage: 1
|
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
|
* Pagination config used to display the list of subgroups of currently active group being edited
|
||||||
*/
|
*/
|
||||||
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'subgroups-list-pagination',
|
id: 'sgl',
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
@@ -85,6 +86,7 @@ export class SubgroupsListComponent implements OnInit, OnDestroy {
|
|||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
|
private paginationService: PaginationService,
|
||||||
private router: Router) {
|
private router: Router) {
|
||||||
this.currentSearchQuery = '';
|
this.currentSearchQuery = '';
|
||||||
}
|
}
|
||||||
@@ -96,42 +98,27 @@ export class SubgroupsListComponent implements OnInit, OnDestroy {
|
|||||||
this.subs.set(SubKey.ActiveGroup, this.groupDataService.getActiveGroup().subscribe((activeGroup: Group) => {
|
this.subs.set(SubKey.ActiveGroup, this.groupDataService.getActiveGroup().subscribe((activeGroup: Group) => {
|
||||||
if (activeGroup != null) {
|
if (activeGroup != null) {
|
||||||
this.groupBeingEdited = activeGroup;
|
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
|
* Retrieve the Subgroups that are members of the group
|
||||||
*
|
*
|
||||||
* @param page the number of the page to retrieve
|
* @param page the number of the page to retrieve
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private retrieveSubGroups(page: number) {
|
private retrieveSubGroups() {
|
||||||
this.unsubFrom(SubKey.Members);
|
this.unsubFrom(SubKey.Members);
|
||||||
this.subs.set(
|
this.subs.set(
|
||||||
SubKey.Members,
|
SubKey.Members,
|
||||||
this.groupDataService.findAllByHref(this.groupBeingEdited._links.subgroups.href, {
|
this.paginationService.getCurrentPagination(this.config.id, this.config).pipe(
|
||||||
currentPage: page,
|
switchMap((config) => this.groupDataService.findAllByHref(this.groupBeingEdited._links.subgroups.href, {
|
||||||
elementsPerPage: this.config.pageSize
|
currentPage: config.currentPage,
|
||||||
}
|
elementsPerPage: config.pageSize
|
||||||
|
}
|
||||||
|
))
|
||||||
).subscribe((rd: RemoteData<PaginatedList<Group>>) => {
|
).subscribe((rd: RemoteData<PaginatedList<Group>>) => {
|
||||||
this.subGroups$.next(rd);
|
this.subGroups$.next(rd);
|
||||||
}));
|
}));
|
||||||
@@ -226,10 +213,12 @@ export class SubgroupsListComponent implements OnInit, OnDestroy {
|
|||||||
this.searchDone = true;
|
this.searchDone = true;
|
||||||
|
|
||||||
this.unsubFrom(SubKey.SearchResults);
|
this.unsubFrom(SubKey.SearchResults);
|
||||||
this.subs.set(SubKey.SearchResults, this.groupDataService.searchGroups(this.currentSearchQuery, {
|
this.subs.set(SubKey.SearchResults, this.paginationService.getCurrentPagination(this.configSearch.id, this.configSearch).pipe(
|
||||||
currentPage: this.configSearch.currentPage,
|
switchMap((config) => this.groupDataService.searchGroups(this.currentSearchQuery, {
|
||||||
elementsPerPage: this.configSearch.pageSize
|
currentPage: config.currentPage,
|
||||||
}).subscribe((rd: RemoteData<PaginatedList<Group>>) => {
|
elementsPerPage: config.pageSize
|
||||||
|
}))
|
||||||
|
).subscribe((rd: RemoteData<PaginatedList<Group>>) => {
|
||||||
this.searchResults$.next(rd);
|
this.searchResults$.next(rd);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -255,6 +244,8 @@ export class SubgroupsListComponent implements OnInit, OnDestroy {
|
|||||||
for (const key of this.subs.keys()) {
|
for (const key of this.subs.keys()) {
|
||||||
this.unsubFrom(key);
|
this.unsubFrom(key);
|
||||||
}
|
}
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
|
this.paginationService.clearPagination(this.configSearch.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -40,8 +40,7 @@
|
|||||||
[pageInfoState]="pageInfoState$"
|
[pageInfoState]="pageInfoState$"
|
||||||
[collectionSize]="(pageInfoState$ | async)?.totalElements"
|
[collectionSize]="(pageInfoState$ | async)?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="groups" class="table table-striped table-hover table-bordered">
|
<table id="groups" class="table table-striped table-hover table-bordered">
|
||||||
|
@@ -28,6 +28,8 @@ import { TranslateLoaderMock } from '../../shared/testing/translate-loader.mock'
|
|||||||
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
||||||
import { routeServiceStub } from '../../shared/testing/route-service.stub';
|
import { routeServiceStub } from '../../shared/testing/route-service.stub';
|
||||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('GroupRegistryComponent', () => {
|
describe('GroupRegistryComponent', () => {
|
||||||
let component: GroupsRegistryComponent;
|
let component: GroupsRegistryComponent;
|
||||||
@@ -39,6 +41,7 @@ describe('GroupRegistryComponent', () => {
|
|||||||
|
|
||||||
let mockGroups;
|
let mockGroups;
|
||||||
let mockEPeople;
|
let mockEPeople;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
mockGroups = [GroupMock, GroupMock2];
|
mockGroups = [GroupMock, GroupMock2];
|
||||||
@@ -131,6 +134,7 @@ describe('GroupRegistryComponent', () => {
|
|||||||
authorizationService = jasmine.createSpyObj('authorizationService', {
|
authorizationService = jasmine.createSpyObj('authorizationService', {
|
||||||
isAuthorized: observableOf(true)
|
isAuthorized: observableOf(true)
|
||||||
});
|
});
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
@@ -149,6 +153,7 @@ describe('GroupRegistryComponent', () => {
|
|||||||
{ provide: RouteService, useValue: routeServiceStub },
|
{ provide: RouteService, useValue: routeServiceStub },
|
||||||
{ provide: Router, useValue: new RouterMock() },
|
{ provide: Router, useValue: new RouterMock() },
|
||||||
{ provide: AuthorizationDataService, useValue: authorizationService },
|
{ provide: AuthorizationDataService, useValue: authorizationService },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }
|
{ provide: RequestService, useValue: jasmine.createSpyObj('requestService', ['removeByHrefSubstring']) }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -5,15 +5,15 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import {
|
import {
|
||||||
BehaviorSubject,
|
BehaviorSubject,
|
||||||
combineLatest as observableCombineLatest,
|
combineLatest as observableCombineLatest,
|
||||||
Subscription,
|
|
||||||
Observable,
|
Observable,
|
||||||
of as observableOf
|
of as observableOf,
|
||||||
|
Subscription
|
||||||
} from 'rxjs';
|
} from 'rxjs';
|
||||||
import { catchError, map, switchMap, take } from 'rxjs/operators';
|
import { catchError, map, switchMap, take } from 'rxjs/operators';
|
||||||
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
||||||
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
|
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 { RemoteData } from '../../core/data/remote-data';
|
||||||
import { RequestService } from '../../core/data/request.service';
|
import { RequestService } from '../../core/data/request.service';
|
||||||
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
||||||
@@ -24,15 +24,17 @@ import { Group } from '../../core/eperson/models/group.model';
|
|||||||
import { RouteService } from '../../core/services/route.service';
|
import { RouteService } from '../../core/services/route.service';
|
||||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||||
import {
|
import {
|
||||||
getAllSucceededRemoteDataPayload,
|
getAllSucceededRemoteData,
|
||||||
getFirstCompletedRemoteData,
|
getFirstCompletedRemoteData,
|
||||||
getFirstSucceededRemoteData
|
getFirstSucceededRemoteData,
|
||||||
|
getRemoteDataPayload
|
||||||
} from '../../core/shared/operators';
|
} from '../../core/shared/operators';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../core/shared/page-info.model';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
import { NoContent } from '../../core/shared/NoContent.model';
|
import { NoContent } from '../../core/shared/NoContent.model';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-groups-registry',
|
selector: 'ds-groups-registry',
|
||||||
@@ -50,7 +52,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
|
|||||||
* Pagination config used to display the list of groups
|
* Pagination config used to display the list of groups
|
||||||
*/
|
*/
|
||||||
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'groups-list-pagination',
|
id: 'gl',
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
@@ -83,6 +85,8 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
searchSub: Subscription;
|
searchSub: Subscription;
|
||||||
|
|
||||||
|
paginationSub: Subscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of subscriptions
|
* List of subscriptions
|
||||||
*/
|
*/
|
||||||
@@ -97,6 +101,7 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
|
|||||||
protected routeService: RouteService,
|
protected routeService: RouteService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private authorizationService: AuthorizationDataService,
|
private authorizationService: AuthorizationDataService,
|
||||||
|
private paginationService: PaginationService,
|
||||||
public requestService: RequestService) {
|
public requestService: RequestService) {
|
||||||
this.currentSearchQuery = '';
|
this.currentSearchQuery = '';
|
||||||
this.searchForm = this.formBuilder.group(({
|
this.searchForm = this.formBuilder.group(({
|
||||||
@@ -108,37 +113,30 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
|
|||||||
this.search({ query: this.currentSearchQuery });
|
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)
|
* Search in the groups (searches by group name and by uuid exact match)
|
||||||
* @param data Contains query param
|
* @param data Contains query param
|
||||||
*/
|
*/
|
||||||
search(data: any) {
|
search(data: any) {
|
||||||
this.searching$.next(true);
|
this.searching$.next(true);
|
||||||
const query: string = data.query;
|
|
||||||
if (query != null && this.currentSearchQuery !== query) {
|
|
||||||
this.router.navigateByUrl(this.groupService.getGroupRegistryRouterLink());
|
|
||||||
this.currentSearchQuery = query;
|
|
||||||
this.config.currentPage = 1;
|
|
||||||
}
|
|
||||||
if (hasValue(this.searchSub)) {
|
if (hasValue(this.searchSub)) {
|
||||||
this.searchSub.unsubscribe();
|
this.searchSub.unsubscribe();
|
||||||
this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub);
|
this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub);
|
||||||
}
|
}
|
||||||
|
this.searchSub = this.paginationService.getCurrentPagination(this.config.id, this.config).pipe(
|
||||||
this.searchSub = this.groupService.searchGroups(this.currentSearchQuery.trim(), {
|
switchMap((paginationOptions) => {
|
||||||
currentPage: this.config.currentPage,
|
const query: string = data.query;
|
||||||
elementsPerPage: this.config.pageSize
|
if (query != null && this.currentSearchQuery !== query) {
|
||||||
}).pipe(
|
this.currentSearchQuery = query;
|
||||||
getAllSucceededRemoteDataPayload(),
|
this.paginationService.updateRouteWithUrl(this.config.id, [], {page: 1});
|
||||||
|
}
|
||||||
|
return this.groupService.searchGroups(this.currentSearchQuery.trim(), {
|
||||||
|
currentPage: paginationOptions.currentPage,
|
||||||
|
elementsPerPage: paginationOptions.pageSize
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
getAllSucceededRemoteData(),
|
||||||
|
getRemoteDataPayload(),
|
||||||
switchMap((groups: PaginatedList<Group>) => {
|
switchMap((groups: PaginatedList<Group>) => {
|
||||||
if (groups.page.length === 0) {
|
if (groups.page.length === 0) {
|
||||||
return observableOf(buildPaginatedList(groups.pageInfo, []));
|
return observableOf(buildPaginatedList(groups.pageInfo, []));
|
||||||
@@ -166,13 +164,15 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
|
|||||||
})).pipe(map((dtos: GroupDtoModel[]) => {
|
})).pipe(map((dtos: GroupDtoModel[]) => {
|
||||||
return buildPaginatedList(groups.pageInfo, dtos);
|
return buildPaginatedList(groups.pageInfo, dtos);
|
||||||
}));
|
}));
|
||||||
})).subscribe((value: PaginatedList<GroupDtoModel>) => {
|
})
|
||||||
|
).subscribe((value: PaginatedList<GroupDtoModel>) => {
|
||||||
this.groupsDto$.next(value);
|
this.groupsDto$.next(value);
|
||||||
this.pageInfoState$.next(value.pageInfo);
|
this.pageInfoState$.next(value.pageInfo);
|
||||||
this.searching$.next(false);
|
this.searching$.next(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.subs.push(this.searchSub);
|
this.subs.push(this.searchSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete Group
|
* Delete Group
|
||||||
@@ -248,9 +248,16 @@ export class GroupsRegistryComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.cleanupSubscribes();
|
this.cleanupSubscribes();
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cleanupSubscribes() {
|
cleanupSubscribes() {
|
||||||
|
if (hasValue(this.paginationSub)) {
|
||||||
|
this.paginationSub.unsubscribe();
|
||||||
|
}
|
||||||
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
||||||
|
this.paginationService.clearPagination(this.config.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
158
src/app/core/pagination/pagination.service.spec.ts
Normal file
158
src/app/core/pagination/pagination.service.spec.ts
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import { PaginationService } from './pagination.service';
|
||||||
|
import { RouterStub } from '../../shared/testing/router.stub';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../data/request.models';
|
||||||
|
|
||||||
|
|
||||||
|
describe('PaginationService', () => {
|
||||||
|
let service: PaginationService;
|
||||||
|
let router;
|
||||||
|
let routeService;
|
||||||
|
|
||||||
|
const defaultPagination = new PaginationComponentOptions();
|
||||||
|
const defaultSort = new SortOptions('id', SortDirection.DESC);
|
||||||
|
const defaultFindListOptions = new FindListOptions();
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
router = new RouterStub();
|
||||||
|
routeService = {
|
||||||
|
getQueryParameterValue: (param) => {
|
||||||
|
let value;
|
||||||
|
if (param.endsWith('.page')) {
|
||||||
|
value = 5;
|
||||||
|
}
|
||||||
|
if (param.endsWith('.rpp')) {
|
||||||
|
value = 10;
|
||||||
|
}
|
||||||
|
if (param.endsWith('.sd')) {
|
||||||
|
value = 'ASC';
|
||||||
|
}
|
||||||
|
if (param.endsWith('.sf')) {
|
||||||
|
value = 'score';
|
||||||
|
}
|
||||||
|
return observableOf(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
service = new PaginationService(routeService, router);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('getCurrentPagination', () => {
|
||||||
|
it('should retrieve the current pagination info from the routerService', () => {
|
||||||
|
service.getCurrentPagination('test-id', defaultPagination).subscribe((currentPagination) => {
|
||||||
|
expect(currentPagination).toEqual(Object.assign(new PaginationComponentOptions(), {
|
||||||
|
currentPage: 5,
|
||||||
|
pageSize: 10
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getCurrentSort', () => {
|
||||||
|
it('should retrieve the current sort info from the routerService', () => {
|
||||||
|
service.getCurrentSort('test-id', defaultSort).subscribe((currentSort) => {
|
||||||
|
expect(currentSort).toEqual(Object.assign(new SortOptions('score', SortDirection.ASC )));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getFindListOptions', () => {
|
||||||
|
it('should retrieve the current findListOptions info from the routerService', () => {
|
||||||
|
service.getFindListOptions('test-id', defaultFindListOptions).subscribe((findListOptions) => {
|
||||||
|
expect(findListOptions).toEqual(Object.assign(new FindListOptions(),
|
||||||
|
{
|
||||||
|
sort: new SortOptions('score', SortDirection.ASC ),
|
||||||
|
currentPage: 5,
|
||||||
|
elementsPerPage: 10
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('resetPage', () => {
|
||||||
|
it('should call the updateRoute method with the id and page 1', () => {
|
||||||
|
spyOn(service, 'updateRoute');
|
||||||
|
service.resetPage('test');
|
||||||
|
|
||||||
|
expect(service.updateRoute).toHaveBeenCalledWith('test', {page: 1});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('updateRoute', () => {
|
||||||
|
it('should update the route with the provided page params', () => {
|
||||||
|
service.updateRoute('test', {page: 2, pageSize: 5, sortField: 'title', sortDirection: SortDirection.DESC});
|
||||||
|
|
||||||
|
const navigateParams = {};
|
||||||
|
navigateParams[`test.page`] = `2`;
|
||||||
|
navigateParams[`test.rpp`] = `5`;
|
||||||
|
navigateParams[`test.sf`] = `title`;
|
||||||
|
navigateParams[`test.sd`] = `DESC`;
|
||||||
|
|
||||||
|
expect(router.navigate).toHaveBeenCalledWith([], {queryParams: navigateParams, queryParamsHandling: 'merge'});
|
||||||
|
});
|
||||||
|
it('should update the route with the provided page params while keeping the existing non provided ones', () => {
|
||||||
|
service.updateRoute('test', {page: 2});
|
||||||
|
|
||||||
|
const navigateParams = {};
|
||||||
|
navigateParams[`test.page`] = `2`;
|
||||||
|
navigateParams[`test.rpp`] = `10`;
|
||||||
|
navigateParams[`test.sf`] = `score`;
|
||||||
|
navigateParams[`test.sd`] = `ASC`;
|
||||||
|
|
||||||
|
expect(router.navigate).toHaveBeenCalledWith([], {queryParams: navigateParams, queryParamsHandling: 'merge'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('updateRouteWithUrl', () => {
|
||||||
|
it('should update the route with the provided page params and url', () => {
|
||||||
|
service.updateRouteWithUrl('test', ['someUrl'], {page: 2, pageSize: 5, sortField: 'title', sortDirection: SortDirection.DESC});
|
||||||
|
|
||||||
|
const navigateParams = {};
|
||||||
|
navigateParams[`test.page`] = `2`;
|
||||||
|
navigateParams[`test.rpp`] = `5`;
|
||||||
|
navigateParams[`test.sf`] = `title`;
|
||||||
|
navigateParams[`test.sd`] = `DESC`;
|
||||||
|
|
||||||
|
expect(router.navigate).toHaveBeenCalledWith(['someUrl'], {queryParams: navigateParams, queryParamsHandling: 'merge'});
|
||||||
|
});
|
||||||
|
it('should update the route with the provided page params and url while keeping the existing non provided ones', () => {
|
||||||
|
service.updateRouteWithUrl('test',['someUrl'], {page: 2});
|
||||||
|
|
||||||
|
const navigateParams = {};
|
||||||
|
navigateParams[`test.page`] = `2`;
|
||||||
|
navigateParams[`test.rpp`] = `10`;
|
||||||
|
navigateParams[`test.sf`] = `score`;
|
||||||
|
navigateParams[`test.sd`] = `ASC`;
|
||||||
|
|
||||||
|
expect(router.navigate).toHaveBeenCalledWith(['someUrl'], {queryParams: navigateParams, queryParamsHandling: 'merge'});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
describe('clearPagination', () => {
|
||||||
|
it('should clear the pagination next time the updateRoute/updateRouteWithUrl method is called', () => {
|
||||||
|
service.clearPagination('test');
|
||||||
|
|
||||||
|
const resetParams = {};
|
||||||
|
resetParams[`test.page`] = null;
|
||||||
|
resetParams[`test.rpp`] = null;
|
||||||
|
resetParams[`test.sf`] = null;
|
||||||
|
resetParams[`test.sd`] = null;
|
||||||
|
|
||||||
|
|
||||||
|
const navigateParams = {};
|
||||||
|
navigateParams[`another-id.page`] = `5`;
|
||||||
|
navigateParams[`another-id.rpp`] = `10`;
|
||||||
|
navigateParams[`another-id.sf`] = `score`;
|
||||||
|
navigateParams[`another-id.sd`] = `ASC`;
|
||||||
|
|
||||||
|
service.updateRoute('another-id', {});
|
||||||
|
|
||||||
|
expect(router.navigate).toHaveBeenCalledWith([], {queryParams: Object.assign({}, resetParams, navigateParams), queryParamsHandling: 'merge'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getPageParam', () => {
|
||||||
|
it('should return the name of the page param', () => {
|
||||||
|
const pageParam = service.getPageParam('test');
|
||||||
|
expect(pageParam).toEqual('test.page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
242
src/app/core/pagination/pagination.service.ts
Normal file
242
src/app/core/pagination/pagination.service.ts
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { RouteService } from '../services/route.service';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
||||||
|
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';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Service to manage the pagination of different components
|
||||||
|
* The pagination information will be stored in the route based on a paginationID.
|
||||||
|
* The following params are used for the different kind of pagination information:
|
||||||
|
* - For the page: {paginationID}.p
|
||||||
|
* - For the page size: {paginationID}.rpp
|
||||||
|
* - For the sort direction: {paginationID}.sd
|
||||||
|
* - For the sort field: {paginationID}.sf
|
||||||
|
*/
|
||||||
|
export class PaginationService {
|
||||||
|
|
||||||
|
private defaultSortOptions = new SortOptions('id', SortDirection.ASC);
|
||||||
|
|
||||||
|
private clearParams = {};
|
||||||
|
|
||||||
|
constructor(protected routeService: RouteService,
|
||||||
|
protected router: Router
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to retrieve the current pagination settings for an ID based on the router params and default options
|
||||||
|
* @param paginationId - The id to check the pagination for
|
||||||
|
* @param defaultPagination - The default pagination values to be used when no route info is present
|
||||||
|
* @returns {Observable<PaginationComponentOptions>} Retrieves the current pagination settings based on the router params
|
||||||
|
*/
|
||||||
|
getCurrentPagination(paginationId: string, defaultPagination: PaginationComponentOptions): Observable<PaginationComponentOptions> {
|
||||||
|
const page$ = this.routeService.getQueryParameterValue(`${paginationId}.page`);
|
||||||
|
const size$ = this.routeService.getQueryParameterValue(`${paginationId}.rpp`);
|
||||||
|
return observableCombineLatest([page$, size$]).pipe(
|
||||||
|
map(([page, size]) => {
|
||||||
|
return Object.assign(new PaginationComponentOptions(), defaultPagination, {
|
||||||
|
currentPage: this.convertToNumeric(page, defaultPagination.currentPage),
|
||||||
|
pageSize: this.getBestMatchPageSize(size, defaultPagination)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to retrieve the current sort options for an ID based on the router params and default options
|
||||||
|
* @param paginationId - The id to check the sort options for
|
||||||
|
* @param defaultSort - The default sort options to be used when no route info is present
|
||||||
|
* @param ignoreDefault - Indicate whether the default should be ignored
|
||||||
|
* @returns {Observable<SortOptions>} Retrieves the current sort options based on the router params
|
||||||
|
*/
|
||||||
|
getCurrentSort(paginationId: string, defaultSort: SortOptions, ignoreDefault?: boolean): Observable<SortOptions> {
|
||||||
|
if (!ignoreDefault && (isEmpty(defaultSort) || !hasValue(defaultSort))) {
|
||||||
|
defaultSort = this.defaultSortOptions;
|
||||||
|
}
|
||||||
|
const sortDirection$ = this.routeService.getQueryParameterValue(`${paginationId}.sd`);
|
||||||
|
const sortField$ = this.routeService.getQueryParameterValue(`${paginationId}.sf`);
|
||||||
|
return observableCombineLatest([sortDirection$, sortField$]).pipe(map(([sortDirection, sortField]) => {
|
||||||
|
const field = sortField || defaultSort?.field;
|
||||||
|
const direction = SortDirection[sortDirection] || defaultSort?.direction;
|
||||||
|
return new SortOptions(field, direction);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to retrieve the current find list options for an ID based on the router params and default options
|
||||||
|
* @param paginationId - The id to check the find list options for
|
||||||
|
* @param defaultFindList - The default find list options to be used when no route info is present
|
||||||
|
* @param ignoreDefault - Indicate whether the default should be ignored
|
||||||
|
* @returns {Observable<FindListOptions>} Retrieves the current find list options based on the router params
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the current page for the provided pagination ID to 1.
|
||||||
|
* @param paginationId - The pagination id for which to reset the page
|
||||||
|
*/
|
||||||
|
resetPage(paginationId: string) {
|
||||||
|
this.updateRoute(paginationId, {page: 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the route with the provided information
|
||||||
|
* @param paginationId - The pagination ID for which to update the route with info
|
||||||
|
* @param params - The page related params to update in the route
|
||||||
|
* @param extraParams - Addition params unrelated to the pagination that need to be added to the route
|
||||||
|
* @param retainScrollPosition - Scroll to the pagination component after updating the route instead of the top of the page
|
||||||
|
*/
|
||||||
|
updateRoute(paginationId: string, params: {
|
||||||
|
page?: number
|
||||||
|
pageSize?: number
|
||||||
|
sortField?: string
|
||||||
|
sortDirection?: SortDirection
|
||||||
|
}, extraParams?, retainScrollPosition?: boolean) {
|
||||||
|
|
||||||
|
this.updateRouteWithUrl(paginationId, [], params, extraParams, retainScrollPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the route with the provided information
|
||||||
|
* @param paginationId - The pagination ID for which to update the route with info
|
||||||
|
* @param url - The url to navigate to
|
||||||
|
* @param params - The page related params to update in the route
|
||||||
|
* @param extraParams - Addition params unrelated to the pagination that need to be added to the route
|
||||||
|
* @param retainScrollPosition - Scroll to the pagination component after updating the route instead of the top of the page
|
||||||
|
*/
|
||||||
|
updateRouteWithUrl(paginationId: string, url: string[], params: {
|
||||||
|
page?: number
|
||||||
|
pageSize?: number
|
||||||
|
sortField?: string
|
||||||
|
sortDirection?: SortDirection
|
||||||
|
}, extraParams?, retainScrollPosition?: boolean) {
|
||||||
|
this.getCurrentRouting(paginationId).subscribe((currentFindListOptions) => {
|
||||||
|
const currentParametersWithIdName = this.getParametersWithIdName(paginationId, currentFindListOptions);
|
||||||
|
const parametersWithIdName = this.getParametersWithIdName(paginationId, params);
|
||||||
|
if (isNotEmpty(difference(parametersWithIdName, currentParametersWithIdName)) || isNotEmpty(extraParams) || isNotEmpty(this.clearParams)) {
|
||||||
|
const queryParams = Object.assign({}, this.clearParams, currentParametersWithIdName,
|
||||||
|
parametersWithIdName, extraParams);
|
||||||
|
if (retainScrollPosition) {
|
||||||
|
this.router.navigate(url, {
|
||||||
|
queryParams: queryParams,
|
||||||
|
queryParamsHandling: 'merge',
|
||||||
|
fragment: `p-${paginationId}`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.router.navigate(url, {
|
||||||
|
queryParams: queryParams,
|
||||||
|
queryParamsHandling: 'merge'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.clearParams = {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the params to be cleared to the clearParams variable.
|
||||||
|
* When the updateRoute or updateRouteWithUrl these params will be removed from the route pagination
|
||||||
|
* @param paginationId - The ID for which to clear the params
|
||||||
|
*/
|
||||||
|
clearPagination(paginationId: string) {
|
||||||
|
const params = {};
|
||||||
|
params[`${paginationId}.page`] = null;
|
||||||
|
params[`${paginationId}.rpp`] = null;
|
||||||
|
params[`${paginationId}.sf`] = null;
|
||||||
|
params[`${paginationId}.sd`] = null;
|
||||||
|
|
||||||
|
Object.assign(this.clearParams, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the page parameter for the provided id
|
||||||
|
* @param paginationId - The ID for which to retrieve the page param
|
||||||
|
*/
|
||||||
|
getPageParam(paginationId: string) {
|
||||||
|
return `${paginationId}.page`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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,
|
||||||
|
sortDirection: findListoptions.sort.direction,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getParametersWithIdName(paginationId: string, params: {
|
||||||
|
page?: number
|
||||||
|
pageSize?: number
|
||||||
|
sortField?: string
|
||||||
|
sortDirection?: SortDirection
|
||||||
|
}) {
|
||||||
|
const paramsWithIdName = {};
|
||||||
|
if (hasValue(params.page)) {
|
||||||
|
paramsWithIdName[`${paginationId}.page`] = `${params.page}`;
|
||||||
|
}
|
||||||
|
if (hasValue(params.pageSize)) {
|
||||||
|
paramsWithIdName[`${paginationId}.rpp`] = `${params.pageSize}`;
|
||||||
|
}
|
||||||
|
if (hasValue(params.sortField)) {
|
||||||
|
paramsWithIdName[`${paginationId}.sf`] = `${params.sortField}`;
|
||||||
|
}
|
||||||
|
if (hasValue(params.sortDirection)) {
|
||||||
|
paramsWithIdName[`${paginationId}.sd`] = `${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)];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -18,7 +18,7 @@ import { AddUrlToHistoryAction } from '../history/history.actions';
|
|||||||
*/
|
*/
|
||||||
export const routeParametersSelector = createSelector(
|
export const routeParametersSelector = createSelector(
|
||||||
coreSelector,
|
coreSelector,
|
||||||
(state: CoreState) => state.route.params
|
(state: CoreState) => hasValue(state) && hasValue(state.route) ? state.route.params : undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,7 +26,7 @@ export const routeParametersSelector = createSelector(
|
|||||||
*/
|
*/
|
||||||
export const queryParametersSelector = createSelector(
|
export const queryParametersSelector = createSelector(
|
||||||
coreSelector,
|
coreSelector,
|
||||||
(state: CoreState) => state.route.queryParams
|
(state: CoreState) => hasValue(state) && hasValue(state.route) ? state.route.queryParams : undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -5,6 +5,7 @@ import { SortDirection, SortOptions } from '../../cache/models/sort-options.mode
|
|||||||
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
||||||
import { SearchFilter } from '../../../shared/search/search-filter.model';
|
import { SearchFilter } from '../../../shared/search/search-filter.model';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SearchConfigurationService', () => {
|
describe('SearchConfigurationService', () => {
|
||||||
let service: SearchConfigurationService;
|
let service: SearchConfigurationService;
|
||||||
@@ -15,7 +16,7 @@ describe('SearchConfigurationService', () => {
|
|||||||
'f.date.max': ['2018']
|
'f.date.max': ['2018']
|
||||||
};
|
};
|
||||||
const defaults = new PaginatedSearchOptions({
|
const defaults = new PaginatedSearchOptions({
|
||||||
pagination: Object.assign(new PaginationComponentOptions(), { currentPage: 1, pageSize: 20 }),
|
pagination: Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 }),
|
||||||
sort: new SortOptions('score', SortDirection.DESC),
|
sort: new SortOptions('score', SortDirection.DESC),
|
||||||
configuration: 'default',
|
configuration: 'default',
|
||||||
query: '',
|
query: '',
|
||||||
@@ -30,10 +31,13 @@ describe('SearchConfigurationService', () => {
|
|||||||
getRouteParameterValue: observableOf('')
|
getRouteParameterValue: observableOf('')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
|
|
||||||
const activatedRoute: any = new ActivatedRouteStub();
|
const activatedRoute: any = new ActivatedRouteStub();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service = new SearchConfigurationService(routeService, activatedRoute);
|
service = new SearchConfigurationService(routeService, paginationService as any, activatedRoute);
|
||||||
});
|
});
|
||||||
describe('when the scope is called', () => {
|
describe('when the scope is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -95,25 +99,19 @@ describe('SearchConfigurationService', () => {
|
|||||||
|
|
||||||
describe('when getCurrentSort is called', () => {
|
describe('when getCurrentSort is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service.getCurrentSort({} as any);
|
service.getCurrentSort(defaults.pagination.id, {} as any);
|
||||||
});
|
});
|
||||||
it('should call getQueryParameterValue on the routeService with parameter name \'sortDirection\'', () => {
|
it('should call getCurrentSort on the paginationService with the provided id and sort options', () => {
|
||||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortDirection');
|
expect((service as any).paginationService.getCurrentSort).toHaveBeenCalledWith(defaults.pagination.id, {});
|
||||||
});
|
|
||||||
it('should call getQueryParameterValue on the routeService with parameter name \'sortField\'', () => {
|
|
||||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('sortField');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when getCurrentPagination is called', () => {
|
describe('when getCurrentPagination is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service.getCurrentPagination({ currentPage: 1, pageSize: 10 } as any);
|
service.getCurrentPagination(defaults.pagination.id, defaults.pagination);
|
||||||
});
|
});
|
||||||
it('should call getQueryParameterValue on the routeService with parameter name \'page\'', () => {
|
it('should call getCurrentPagination on the paginationService with the provided id and sort options', () => {
|
||||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('page');
|
expect((service as any).paginationService.getCurrentPagination).toHaveBeenCalledWith(defaults.pagination.id, defaults.pagination);
|
||||||
});
|
|
||||||
it('should call getQueryParameterValue on the routeService with parameter name \'pageSize\'', () => {
|
|
||||||
expect((service as any).routeService.getQueryParameterValue).toHaveBeenCalledWith('pageSize');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -145,7 +143,7 @@ describe('SearchConfigurationService', () => {
|
|||||||
|
|
||||||
describe('when subscribeToPaginatedSearchOptions is called', () => {
|
describe('when subscribeToPaginatedSearchOptions is called', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
(service as any).subscribeToPaginatedSearchOptions(defaults);
|
(service as any).subscribeToPaginatedSearchOptions(defaults.pagination.id, defaults);
|
||||||
});
|
});
|
||||||
it('should call all getters it needs', () => {
|
it('should call all getters it needs', () => {
|
||||||
expect(service.getCurrentPagination).toHaveBeenCalled();
|
expect(service.getCurrentPagination).toHaveBeenCalled();
|
||||||
|
@@ -24,17 +24,20 @@ import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.u
|
|||||||
import { SearchConfig } from './search-filters/search-config.model';
|
import { SearchConfig } from './search-filters/search-config.model';
|
||||||
import { SearchService } from './search.service';
|
import { SearchService } from './search.service';
|
||||||
import { of } from 'rxjs/internal/observable/of';
|
import { of } from 'rxjs/internal/observable/of';
|
||||||
|
import { PaginationService } from '../../pagination/pagination.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that performs all actions that have to do with the current search configuration
|
* Service that performs all actions that have to do with the current search configuration
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SearchConfigurationService implements OnDestroy {
|
export class SearchConfigurationService implements OnDestroy {
|
||||||
|
|
||||||
|
public paginationID = 'spc';
|
||||||
/**
|
/**
|
||||||
* Default pagination settings
|
* Default pagination settings
|
||||||
*/
|
*/
|
||||||
protected defaultPagination = Object.assign(new PaginationComponentOptions(), {
|
protected defaultPagination = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'search-page-configuration',
|
id: this.paginationID,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
@@ -85,6 +88,7 @@ export class SearchConfigurationService implements OnDestroy {
|
|||||||
* @param {ActivatedRoute} route
|
* @param {ActivatedRoute} route
|
||||||
*/
|
*/
|
||||||
constructor(protected routeService: RouteService,
|
constructor(protected routeService: RouteService,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected route: ActivatedRoute) {
|
protected route: ActivatedRoute) {
|
||||||
|
|
||||||
this.initDefaults();
|
this.initDefaults();
|
||||||
@@ -101,7 +105,7 @@ export class SearchConfigurationService implements OnDestroy {
|
|||||||
this.paginatedSearchOptions = new BehaviorSubject<PaginatedSearchOptions>(defs);
|
this.paginatedSearchOptions = new BehaviorSubject<PaginatedSearchOptions>(defs);
|
||||||
this.searchOptions = new BehaviorSubject<SearchOptions>(defs);
|
this.searchOptions = new BehaviorSubject<SearchOptions>(defs);
|
||||||
this.subs.push(this.subscribeToSearchOptions(defs));
|
this.subs.push(this.subscribeToSearchOptions(defs));
|
||||||
this.subs.push(this.subscribeToPaginatedSearchOptions(defs));
|
this.subs.push(this.subscribeToPaginatedSearchOptions(defs.pagination.id, defs));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -150,34 +154,15 @@ export class SearchConfigurationService implements OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* @returns {Observable<string>} Emits the current pagination settings
|
* @returns {Observable<string>} Emits the current pagination settings
|
||||||
*/
|
*/
|
||||||
getCurrentPagination(defaultPagination: PaginationComponentOptions): Observable<PaginationComponentOptions> {
|
getCurrentPagination(paginationId: string, defaultPagination: PaginationComponentOptions): Observable<PaginationComponentOptions> {
|
||||||
const page$ = this.routeService.getQueryParameterValue('page');
|
return this.paginationService.getCurrentPagination(paginationId, defaultPagination);
|
||||||
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
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {Observable<string>} Emits the current sorting settings
|
* @returns {Observable<string>} Emits the current sorting settings
|
||||||
*/
|
*/
|
||||||
getCurrentSort(defaultSort: SortOptions): Observable<SortOptions> {
|
getCurrentSort(paginationId: string, defaultSort: SortOptions): Observable<SortOptions> {
|
||||||
const sortDirection$ = this.routeService.getQueryParameterValue('sortDirection');
|
return this.paginationService.getCurrentSort(paginationId, defaultSort);
|
||||||
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);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,10 +274,10 @@ export class SearchConfigurationService implements OnDestroy {
|
|||||||
* @param {PaginatedSearchOptions} defaults Default values for when no parameters are available
|
* @param {PaginatedSearchOptions} defaults Default values for when no parameters are available
|
||||||
* @returns {Subscription} The subscription to unsubscribe from
|
* @returns {Subscription} The subscription to unsubscribe from
|
||||||
*/
|
*/
|
||||||
private subscribeToPaginatedSearchOptions(defaults: PaginatedSearchOptions): Subscription {
|
private subscribeToPaginatedSearchOptions(paginationId: string, defaults: PaginatedSearchOptions): Subscription {
|
||||||
return observableMerge(
|
return observableMerge(
|
||||||
this.getPaginationPart(defaults.pagination),
|
this.getPaginationPart(paginationId, defaults.pagination),
|
||||||
this.getSortPart(defaults.sort),
|
this.getSortPart(paginationId, defaults.sort),
|
||||||
this.getConfigurationPart(defaults.configuration),
|
this.getConfigurationPart(defaults.configuration),
|
||||||
this.getScopePart(defaults.scope),
|
this.getScopePart(defaults.scope),
|
||||||
this.getQueryPart(defaults.query),
|
this.getQueryPart(defaults.query),
|
||||||
@@ -372,8 +357,8 @@ export class SearchConfigurationService implements OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* @returns {Observable<string>} Emits the current pagination settings as a partial SearchOptions object
|
* @returns {Observable<string>} Emits the current pagination settings as a partial SearchOptions object
|
||||||
*/
|
*/
|
||||||
private getPaginationPart(defaultPagination: PaginationComponentOptions): Observable<any> {
|
private getPaginationPart(paginationId: string, defaultPagination: PaginationComponentOptions): Observable<any> {
|
||||||
return this.getCurrentPagination(defaultPagination).pipe(map((pagination) => {
|
return this.getCurrentPagination(paginationId, defaultPagination).pipe(map((pagination) => {
|
||||||
return { pagination };
|
return { pagination };
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -381,8 +366,8 @@ export class SearchConfigurationService implements OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* @returns {Observable<string>} Emits the current sorting settings as a partial SearchOptions object
|
* @returns {Observable<string>} Emits the current sorting settings as a partial SearchOptions object
|
||||||
*/
|
*/
|
||||||
private getSortPart(defaultSort: SortOptions): Observable<any> {
|
private getSortPart(paginationId: string, defaultSort: SortOptions): Observable<any> {
|
||||||
return this.getCurrentSort(defaultSort).pipe(map((sort) => {
|
return this.getCurrentSort(paginationId, defaultSort).pipe(map((sort) => {
|
||||||
return { sort };
|
return { sort };
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,12 @@ import { routeServiceStub } from '../../../shared/testing/route-service.stub';
|
|||||||
import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../../cache/builders/remote-data-build.service';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
import { SearchObjects } from '../../../shared/search/search-objects.model';
|
import { SearchObjects } from '../../../shared/search/search-objects.model';
|
||||||
|
import { PaginationService } from '../../pagination/pagination.service';
|
||||||
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../data/request.models';
|
||||||
|
import { SearchConfigurationService } from './search-configuration.service';
|
||||||
|
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
@Component({ template: '' })
|
@Component({ template: '' })
|
||||||
class DummyComponent {
|
class DummyComponent {
|
||||||
@@ -32,6 +38,7 @@ describe('SearchService', () => {
|
|||||||
let searchService: SearchService;
|
let searchService: SearchService;
|
||||||
const router = new RouterStub();
|
const router = new RouterStub();
|
||||||
const route = new ActivatedRouteStub();
|
const route = new ActivatedRouteStub();
|
||||||
|
const searchConfigService = {paginationID: 'page-id'};
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -51,6 +58,8 @@ describe('SearchService', () => {
|
|||||||
{ provide: HALEndpointService, useValue: {} },
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
{ provide: CommunityDataService, useValue: {} },
|
{ provide: CommunityDataService, useValue: {} },
|
||||||
{ provide: DSpaceObjectDataService, useValue: {} },
|
{ provide: DSpaceObjectDataService, useValue: {} },
|
||||||
|
{ provide: PaginationService, useValue: {} },
|
||||||
|
{ provide: SearchConfigurationService, useValue: searchConfigService },
|
||||||
SearchService
|
SearchService
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -94,6 +103,9 @@ describe('SearchService', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
const searchConfigService = {paginationID: 'page-id'};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -113,6 +125,8 @@ describe('SearchService', () => {
|
|||||||
{ provide: HALEndpointService, useValue: halService },
|
{ provide: HALEndpointService, useValue: halService },
|
||||||
{ provide: CommunityDataService, useValue: {} },
|
{ provide: CommunityDataService, useValue: {} },
|
||||||
{ provide: DSpaceObjectDataService, useValue: {} },
|
{ provide: DSpaceObjectDataService, useValue: {} },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
|
{ provide: SearchConfigurationService, useValue: searchConfigService },
|
||||||
SearchService
|
SearchService
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -124,18 +138,14 @@ describe('SearchService', () => {
|
|||||||
|
|
||||||
it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => {
|
it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => {
|
||||||
searchService.setViewMode(ViewMode.ListElement);
|
searchService.setViewMode(ViewMode.ListElement);
|
||||||
expect(router.navigate).toHaveBeenCalledWith(['/search'], {
|
expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith('page-id', ['/search'], {page: 1}, { view: ViewMode.ListElement }
|
||||||
queryParams: { view: ViewMode.ListElement, page: 1 },
|
);
|
||||||
queryParamsHandling: 'merge'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call the navigate method on the Router with view mode grid parameter as a parameter when setViewMode is called', () => {
|
it('should call the navigate method on the Router with view mode grid parameter as a parameter when setViewMode is called', () => {
|
||||||
searchService.setViewMode(ViewMode.GridElement);
|
searchService.setViewMode(ViewMode.GridElement);
|
||||||
expect(router.navigate).toHaveBeenCalledWith(['/search'], {
|
expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith('page-id', ['/search'], {page: 1}, { view: ViewMode.GridElement }
|
||||||
queryParams: { view: ViewMode.GridElement, page: 1 },
|
);
|
||||||
queryParamsHandling: 'merge'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return ViewMode.List when the viewMode is set to ViewMode.List in the ActivatedRoute', () => {
|
it('should return ViewMode.List when the viewMode is set to ViewMode.List in the ActivatedRoute', () => {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
|
import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
|
||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { Injectable, OnDestroy } from '@angular/core';
|
||||||
import { NavigationExtras, Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { first, map, switchMap, take } from 'rxjs/operators';
|
import { map, switchMap, take } from 'rxjs/operators';
|
||||||
import { followLink, FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
|
import { followLink, FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
|
||||||
import { LinkService } from '../../cache/builders/link.service';
|
import { LinkService } from '../../cache/builders/link.service';
|
||||||
import { PaginatedList } from '../../data/paginated-list.model';
|
import { PaginatedList } from '../../data/paginated-list.model';
|
||||||
@@ -38,6 +38,9 @@ import { getSearchResultFor } from '../../../shared/search/search-result-element
|
|||||||
import { FacetConfigResponse } from '../../../shared/search/facet-config-response.model';
|
import { FacetConfigResponse } from '../../../shared/search/facet-config-response.model';
|
||||||
import { FacetValues } from '../../../shared/search/facet-values.model';
|
import { FacetValues } from '../../../shared/search/facet-values.model';
|
||||||
import { SearchConfig } from './search-filters/search-config.model';
|
import { SearchConfig } from './search-filters/search-config.model';
|
||||||
|
import { PaginationService } from '../../pagination/pagination.service';
|
||||||
|
import { SearchConfigurationService } from './search-configuration.service';
|
||||||
|
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that performs all general actions that have to do with the search page
|
* Service that performs all general actions that have to do with the search page
|
||||||
@@ -82,7 +85,9 @@ export class SearchService implements OnDestroy {
|
|||||||
private linkService: LinkService,
|
private linkService: LinkService,
|
||||||
private halService: HALEndpointService,
|
private halService: HALEndpointService,
|
||||||
private communityService: CommunityDataService,
|
private communityService: CommunityDataService,
|
||||||
private dspaceObjectService: DSpaceObjectDataService
|
private dspaceObjectService: DSpaceObjectDataService,
|
||||||
|
private paginationService: PaginationService,
|
||||||
|
private searchConfigurationService: SearchConfigurationService
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,20 +394,16 @@ export class SearchService implements OnDestroy {
|
|||||||
* @param {ViewMode} viewMode Mode to switch to
|
* @param {ViewMode} viewMode Mode to switch to
|
||||||
*/
|
*/
|
||||||
setViewMode(viewMode: ViewMode, searchLinkParts?: string[]) {
|
setViewMode(viewMode: ViewMode, searchLinkParts?: string[]) {
|
||||||
this.routeService.getQueryParameterValue('pageSize').pipe(first())
|
this.paginationService.getCurrentPagination(this.searchConfigurationService.paginationID, new PaginationComponentOptions()).pipe(take(1))
|
||||||
.subscribe((pageSize) => {
|
.subscribe((config) => {
|
||||||
let queryParams = { view: viewMode, page: 1 };
|
let pageParams = { page: 1 };
|
||||||
|
const queryParams = { view: viewMode };
|
||||||
if (viewMode === ViewMode.DetailedListElement) {
|
if (viewMode === ViewMode.DetailedListElement) {
|
||||||
queryParams = Object.assign(queryParams, {pageSize: '1'});
|
pageParams = Object.assign(pageParams, {pageSize: 1});
|
||||||
} else if (pageSize === '1') {
|
} else if (config.pageSize === 1) {
|
||||||
queryParams = Object.assign(queryParams, {pageSize: '10'});
|
pageParams = Object.assign(pageParams, {pageSize: 10});
|
||||||
}
|
}
|
||||||
const navigationExtras: NavigationExtras = {
|
this.paginationService.updateRouteWithUrl(this.searchConfigurationService.paginationID, hasValue(searchLinkParts) ? searchLinkParts : [this.getSearchLink()], pageParams, queryParams);
|
||||||
queryParams: queryParams,
|
|
||||||
queryParamsHandling: 'merge'
|
|
||||||
};
|
|
||||||
|
|
||||||
this.router.navigate(hasValue(searchLinkParts) ? searchLinkParts : [this.getSearchLink()], navigationExtras);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,8 +8,7 @@
|
|||||||
[pageInfoState]="(processesRD$ | async)?.payload"
|
[pageInfoState]="(processesRD$ | async)?.payload"
|
||||||
[collectionSize]="(processesRD$ | async)?.payload?.totalElements"
|
[collectionSize]="(processesRD$ | async)?.payload?.totalElements"
|
||||||
[hideGear]="true"
|
[hideGear]="true"
|
||||||
[hidePagerWhenSinglePage]="true"
|
[hidePagerWhenSinglePage]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-striped table-hover">
|
<table class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
@@ -12,6 +12,12 @@ import { By } from '@angular/platform-browser';
|
|||||||
import { ProcessStatus } from '../processes/process-status.model';
|
import { ProcessStatus } from '../processes/process-status.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||||
import { createPaginatedList } from '../../shared/testing/utils.test';
|
import { createPaginatedList } from '../../shared/testing/utils.test';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../core/data/request.models';
|
||||||
|
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('ProcessOverviewComponent', () => {
|
describe('ProcessOverviewComponent', () => {
|
||||||
let component: ProcessOverviewComponent;
|
let component: ProcessOverviewComponent;
|
||||||
@@ -19,6 +25,7 @@ describe('ProcessOverviewComponent', () => {
|
|||||||
|
|
||||||
let processService: ProcessDataService;
|
let processService: ProcessDataService;
|
||||||
let ePersonService: EPersonDataService;
|
let ePersonService: EPersonDataService;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
let processes: Process[];
|
let processes: Process[];
|
||||||
let ePerson: EPerson;
|
let ePerson: EPerson;
|
||||||
@@ -69,6 +76,8 @@ describe('ProcessOverviewComponent', () => {
|
|||||||
ePersonService = jasmine.createSpyObj('ePersonService', {
|
ePersonService = jasmine.createSpyObj('ePersonService', {
|
||||||
findById: createSuccessfulRemoteDataObject$(ePerson)
|
findById: createSuccessfulRemoteDataObject$(ePerson)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
@@ -78,7 +87,8 @@ describe('ProcessOverviewComponent', () => {
|
|||||||
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
|
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: ProcessDataService, useValue: processService },
|
{ provide: ProcessDataService, useValue: processService },
|
||||||
{ provide: EPersonDataService, useValue: ePersonService }
|
{ provide: EPersonDataService, useValue: ePersonService },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
@@ -143,16 +153,4 @@ describe('ProcessOverviewComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onPageChange', () => {
|
|
||||||
const toPage = 2;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
component.onPageChange(toPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call a new findAll with the corresponding page', () => {
|
|
||||||
expect(processService.findAll).toHaveBeenCalledWith(jasmine.objectContaining({ currentPage: toPage }));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@@ -8,8 +8,9 @@ import { FindListOptions } from '../../core/data/request.models';
|
|||||||
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
||||||
import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
|
import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
|
||||||
import { EPerson } from '../../core/eperson/models/eperson.model';
|
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 { ProcessDataService } from '../../core/data/processes/process-data.service';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-process-overview',
|
selector: 'ds-process-overview',
|
||||||
@@ -36,7 +37,7 @@ export class ProcessOverviewComponent implements OnInit {
|
|||||||
* The current pagination configuration for the page
|
* The current pagination configuration for the page
|
||||||
*/
|
*/
|
||||||
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||||
id: 'process-overview-pagination',
|
id: 'po',
|
||||||
pageSize: 20
|
pageSize: 20
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ export class ProcessOverviewComponent implements OnInit {
|
|||||||
dateFormat = 'yyyy-MM-dd HH:mm:ss';
|
dateFormat = 'yyyy-MM-dd HH:mm:ss';
|
||||||
|
|
||||||
constructor(protected processService: ProcessDataService,
|
constructor(protected processService: ProcessDataService,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected ePersonService: EPersonDataService) {
|
protected ePersonService: EPersonDataService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,23 +55,13 @@ export class ProcessOverviewComponent implements OnInit {
|
|||||||
this.setProcesses();
|
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
|
* Send a request to fetch all processes for the current page
|
||||||
*/
|
*/
|
||||||
setProcesses() {
|
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))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,5 +74,8 @@ export class ProcessOverviewComponent implements OnInit {
|
|||||||
map((eperson: EPerson) => eperson.name)
|
map((eperson: EPerson) => eperson.name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.paginationService.clearPagination(this.pageConfig.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,12 @@ import { SearchService } from '../core/shared/search/search.service';
|
|||||||
import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
|
import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
|
||||||
|
|
||||||
import { SearchNavbarComponent } from './search-navbar.component';
|
import { SearchNavbarComponent } from './search-navbar.component';
|
||||||
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationService } from '../core/pagination/pagination.service';
|
||||||
|
import { SearchConfigurationService } from '../core/shared/search/search-configuration.service';
|
||||||
|
import { PaginationServiceStub } from '../shared/testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SearchNavbarComponent', () => {
|
describe('SearchNavbarComponent', () => {
|
||||||
let component: SearchNavbarComponent;
|
let component: SearchNavbarComponent;
|
||||||
@@ -15,6 +21,7 @@ describe('SearchNavbarComponent', () => {
|
|||||||
let mockSearchService: any;
|
let mockSearchService: any;
|
||||||
let router: Router;
|
let router: Router;
|
||||||
let routerStub;
|
let routerStub;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
mockSearchService = {
|
mockSearchService = {
|
||||||
@@ -26,6 +33,9 @@ describe('SearchNavbarComponent', () => {
|
|||||||
routerStub = {
|
routerStub = {
|
||||||
navigate: (commands) => commands
|
navigate: (commands) => commands
|
||||||
};
|
};
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
FormsModule,
|
FormsModule,
|
||||||
@@ -40,7 +50,9 @@ describe('SearchNavbarComponent', () => {
|
|||||||
declarations: [SearchNavbarComponent],
|
declarations: [SearchNavbarComponent],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: SearchService, useValue: mockSearchService },
|
{ provide: SearchService, useValue: mockSearchService },
|
||||||
{ provide: Router, useValue: routerStub }
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
|
{ provide: Router, useValue: routerStub },
|
||||||
|
{ provide: SearchConfigurationService, useValue: {paginationID: 'page-id'} }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
@@ -88,7 +100,7 @@ describe('SearchNavbarComponent', () => {
|
|||||||
}));
|
}));
|
||||||
it('to search page with empty query', () => {
|
it('to search page with empty query', () => {
|
||||||
expect(component.onSubmit).toHaveBeenCalledWith({ query: '' });
|
expect(component.onSubmit).toHaveBeenCalledWith({ query: '' });
|
||||||
expect(router.navigate).toHaveBeenCalled();
|
expect(paginationService.updateRouteWithUrl).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -112,7 +124,7 @@ describe('SearchNavbarComponent', () => {
|
|||||||
}));
|
}));
|
||||||
it('to search page with query', async () => {
|
it('to search page with query', async () => {
|
||||||
expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' });
|
expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' });
|
||||||
expect(router.navigate).toHaveBeenCalled();
|
expect(paginationService.updateRouteWithUrl).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -3,6 +3,8 @@ import { FormBuilder } from '@angular/forms';
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { SearchService } from '../core/shared/search/search.service';
|
import { SearchService } from '../core/shared/search/search.service';
|
||||||
import { expandSearchInput } from '../shared/animations/slide';
|
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
|
* 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
|
// Search input field
|
||||||
@ViewChild('searchInput') searchField: ElementRef;
|
@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(({
|
this.searchForm = this.formBuilder.group(({
|
||||||
query: '',
|
query: '',
|
||||||
}));
|
}));
|
||||||
@@ -63,9 +67,6 @@ export class SearchNavbarComponent {
|
|||||||
this.collapse();
|
this.collapse();
|
||||||
const linkToNavigateTo = this.searchService.getSearchLink().split('/');
|
const linkToNavigateTo = this.searchService.getSearchLink().split('/');
|
||||||
this.searchForm.reset();
|
this.searchForm.reset();
|
||||||
this.router.navigate(linkToNavigateTo, {
|
this.paginationService.updateRouteWithUrl(this.searchConfig.paginationID, linkToNavigateTo, {page: 1}, data);
|
||||||
queryParams: Object.assign({}, { page: 1 }, data),
|
|
||||||
queryParamsHandling: 'merge'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,9 @@ import { PaginationComponentOptions } from '../pagination/pagination-component-o
|
|||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
|
||||||
import { storeModuleConfig } from '../../app.reducer';
|
import { storeModuleConfig } from '../../app.reducer';
|
||||||
|
import { FindListOptions } from '../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('BrowseByComponent', () => {
|
describe('BrowseByComponent', () => {
|
||||||
let comp: BrowseByComponent;
|
let comp: BrowseByComponent;
|
||||||
@@ -45,6 +48,14 @@ describe('BrowseByComponent', () => {
|
|||||||
];
|
];
|
||||||
const mockItemsRD$ = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), mockItems));
|
const mockItemsRD$ = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), mockItems));
|
||||||
|
|
||||||
|
const paginationConfig = Object.assign(new PaginationComponentOptions(), {
|
||||||
|
id: 'test-pagination',
|
||||||
|
currentPage: 1,
|
||||||
|
pageSizeOptions: [5, 10, 15, 20],
|
||||||
|
pageSize: 15
|
||||||
|
});
|
||||||
|
const paginationService = new PaginationServiceStub(paginationConfig);
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -63,7 +74,9 @@ describe('BrowseByComponent', () => {
|
|||||||
BrowserAnimationsModule
|
BrowserAnimationsModule
|
||||||
],
|
],
|
||||||
declarations: [],
|
declarations: [],
|
||||||
providers: [],
|
providers: [
|
||||||
|
{provide: PaginationService, useValue: paginationService}
|
||||||
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
@@ -95,12 +108,8 @@ describe('BrowseByComponent', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
comp.enableArrows = true;
|
comp.enableArrows = true;
|
||||||
comp.objects$ = mockItemsRD$;
|
comp.objects$ = mockItemsRD$;
|
||||||
comp.paginationConfig = Object.assign(new PaginationComponentOptions(), {
|
|
||||||
id: 'test-pagination',
|
comp.paginationConfig = paginationConfig;
|
||||||
currentPage: 1,
|
|
||||||
pageSizeOptions: [5, 10, 15, 20],
|
|
||||||
pageSize: 15
|
|
||||||
});
|
|
||||||
comp.sortConfig = Object.assign(new SortOptions('dc.title', SortDirection.ASC));
|
comp.sortConfig = Object.assign(new SortOptions('dc.title', SortDirection.ASC));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
@@ -136,8 +145,8 @@ describe('BrowseByComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit a signal to the EventEmitter', () => {
|
it('should call the updateRoute method from the paginationService', () => {
|
||||||
expect(comp.pageSizeChange.emit).toHaveBeenCalled();
|
expect(paginationService.updateRoute).toHaveBeenCalledWith('test-pagination', {pageSize: paginationConfig.pageSizeOptions[0]});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -148,8 +157,8 @@ describe('BrowseByComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit a signal to the EventEmitter', () => {
|
it('should call the updateRoute method from the paginationService', () => {
|
||||||
expect(comp.sortDirectionChange.emit).toHaveBeenCalled();
|
expect(paginationService.updateRoute).toHaveBeenCalledWith('test-pagination', {sortDirection: 'ASC'});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -7,6 +7,7 @@ import { fadeIn, fadeInOut } from '../animations/fade';
|
|||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ListableObject } from '../object-collection/shared/listable-object.model';
|
import { ListableObject } from '../object-collection/shared/listable-object.model';
|
||||||
import { getStartsWithComponent, StartsWithType } from '../starts-with/starts-with-decorator';
|
import { getStartsWithComponent, StartsWithType } from '../starts-with/starts-with-decorator';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-browse-by',
|
selector: 'ds-browse-by',
|
||||||
@@ -96,7 +97,9 @@ export class BrowseByComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public sortDirections = SortDirection;
|
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
|
* @param size
|
||||||
*/
|
*/
|
||||||
doPageSizeChange(size) {
|
doPageSizeChange(size) {
|
||||||
this.paginationConfig.pageSize = size;
|
this.paginationService.updateRoute(this.paginationConfig.id,{pageSize: size});
|
||||||
this.pageSizeChange.emit(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,8 +130,7 @@ export class BrowseByComponent implements OnInit {
|
|||||||
* @param direction
|
* @param direction
|
||||||
*/
|
*/
|
||||||
doSortDirectionChange(direction) {
|
doSortDirectionChange(direction) {
|
||||||
this.sortConfig.direction = direction;
|
this.paginationService.updateRoute(this.paginationConfig.id,{sortDirection: direction});
|
||||||
this.sortDirectionChange.emit(direction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,7 +142,10 @@ export class BrowseByComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.objectInjector = Injector.create({
|
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
|
parent: this.injector
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -8,8 +8,7 @@
|
|||||||
[paginationOptions]="options"
|
[paginationOptions]="options"
|
||||||
[pageInfoState]="versions"
|
[pageInfoState]="versions"
|
||||||
[collectionSize]="versions?.totalElements"
|
[collectionSize]="versions?.totalElements"
|
||||||
[disableRouteParameterUpdate]="true"
|
[retainScrollPosition]="true">
|
||||||
(pageChange)="switchPage($event)">
|
|
||||||
<table class="table table-striped my-2">
|
<table class="table table-striped my-2">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@@ -11,6 +11,11 @@ import { VersionHistoryDataService } from '../../../core/data/version-history-da
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
|
||||||
import { createPaginatedList } from '../../testing/utils.test';
|
import { createPaginatedList } from '../../testing/utils.test';
|
||||||
|
import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('ItemVersionsComponent', () => {
|
describe('ItemVersionsComponent', () => {
|
||||||
let component: ItemVersionsComponent;
|
let component: ItemVersionsComponent;
|
||||||
@@ -52,12 +57,15 @@ describe('ItemVersionsComponent', () => {
|
|||||||
getVersions: createSuccessfulRemoteDataObject$(createPaginatedList(versions))
|
getVersions: createSuccessfulRemoteDataObject$(createPaginatedList(versions))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ItemVersionsComponent, VarDirective],
|
declarations: [ItemVersionsComponent, VarDirective],
|
||||||
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
|
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: VersionHistoryDataService, useValue: versionHistoryService }
|
{ provide: VersionHistoryDataService, useValue: versionHistoryService },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
@@ -107,16 +115,4 @@ describe('ItemVersionsComponent', () => {
|
|||||||
expect(summary.nativeElement.textContent).toEqual(version.summary);
|
expect(summary.nativeElement.textContent).toEqual(version.summary);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('switchPage', () => {
|
|
||||||
const page = 5;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
component.switchPage(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set the option\'s currentPage to the new page', () => {
|
|
||||||
expect(component.options.currentPage).toEqual(page);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@@ -17,6 +17,7 @@ import { PaginatedSearchOptions } from '../../search/paginated-search-options.mo
|
|||||||
import { AlertType } from '../../alert/aletr-type';
|
import { AlertType } from '../../alert/aletr-type';
|
||||||
import { followLink } from '../../utils/follow-link-config.model';
|
import { followLink } from '../../utils/follow-link-config.model';
|
||||||
import { hasValueOperator } from '../../empty.util';
|
import { hasValueOperator } from '../../empty.util';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
import { getItemPageRoute } from '../../../+item-page/item-page-routing-paths';
|
import { getItemPageRoute } from '../../../+item-page/item-page-routing-paths';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -81,7 +82,7 @@ export class ItemVersionsComponent implements OnInit {
|
|||||||
* Start at page 1 and always use the set page size
|
* Start at page 1 and always use the set page size
|
||||||
*/
|
*/
|
||||||
options = Object.assign(new PaginationComponentOptions(),{
|
options = Object.assign(new PaginationComponentOptions(),{
|
||||||
id: 'item-versions-options',
|
id: 'ivo',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: this.pageSize
|
pageSize: this.pageSize
|
||||||
});
|
});
|
||||||
@@ -100,7 +101,9 @@ export class ItemVersionsComponent implements OnInit {
|
|||||||
[itemId: string]: string
|
[itemId: string]: string
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
constructor(private versionHistoryService: VersionHistoryDataService) {
|
constructor(private versionHistoryService: VersionHistoryDataService,
|
||||||
|
private paginationService: PaginationService
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,10 +122,11 @@ export class ItemVersionsComponent implements OnInit {
|
|||||||
getRemoteDataPayload(),
|
getRemoteDataPayload(),
|
||||||
hasValueOperator(),
|
hasValueOperator(),
|
||||||
);
|
);
|
||||||
this.versionsRD$ = observableCombineLatest(versionHistory$, this.currentPage$).pipe(
|
const currentPagination = this.paginationService.getCurrentPagination(this.options.id, this.options);
|
||||||
switchMap(([versionHistory, page]: [VersionHistory, number]) =>
|
this.versionsRD$ = observableCombineLatest(versionHistory$, currentPagination).pipe(
|
||||||
|
switchMap(([versionHistory, options]: [VersionHistory, PaginationComponentOptions]) =>
|
||||||
this.versionHistoryService.getVersions(versionHistory.id,
|
this.versionHistoryService.getVersions(versionHistory.id,
|
||||||
new PaginatedSearchOptions({pagination: Object.assign({}, this.options, { currentPage: page })}),
|
new PaginatedSearchOptions({pagination: Object.assign({}, options, { currentPage: options.currentPage })}),
|
||||||
true, true, followLink('item'), followLink('eperson')))
|
true, true, followLink('item'), followLink('eperson')))
|
||||||
);
|
);
|
||||||
this.hasEpersons$ = this.versionsRD$.pipe(
|
this.hasEpersons$ = this.versionsRD$.pipe(
|
||||||
@@ -143,13 +147,9 @@ export class ItemVersionsComponent implements OnInit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
ngOnDestroy(): void {
|
||||||
* Update the current page
|
this.paginationService.clearPagination(this.options.id);
|
||||||
* @param page
|
|
||||||
*/
|
|
||||||
switchPage(page: number) {
|
|
||||||
this.options.currentPage = page;
|
|
||||||
this.currentPage$.next(page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1101,6 +1101,91 @@ export const mockSubmissionState: SubmissionObjectState = Object.assign({}, {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const mockSubmissionStateWithoutUpload: SubmissionObjectState = Object.assign({}, {
|
||||||
|
826: {
|
||||||
|
collection: mockSubmissionCollectionId,
|
||||||
|
definition: 'traditional',
|
||||||
|
selfUrl: mockSubmissionSelfUrl,
|
||||||
|
activeSection: null,
|
||||||
|
sections: {
|
||||||
|
extraction: {
|
||||||
|
config: '',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'utils',
|
||||||
|
visibility: {
|
||||||
|
main: 'HIDDEN',
|
||||||
|
other: 'HIDDEN'
|
||||||
|
},
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {},
|
||||||
|
errors: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false
|
||||||
|
} as any,
|
||||||
|
collection: {
|
||||||
|
config: '',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'collection',
|
||||||
|
visibility: {
|
||||||
|
main: 'HIDDEN',
|
||||||
|
other: 'HIDDEN'
|
||||||
|
},
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {},
|
||||||
|
errors: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false
|
||||||
|
} as any,
|
||||||
|
traditionalpageone: {
|
||||||
|
header: 'submit.progressbar.describe.stepone',
|
||||||
|
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'submission-form',
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {},
|
||||||
|
errors: [],
|
||||||
|
formId: '2_traditionalpageone',
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false
|
||||||
|
} as any,
|
||||||
|
traditionalpagetwo: {
|
||||||
|
header: 'submit.progressbar.describe.steptwo',
|
||||||
|
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo',
|
||||||
|
mandatory: false,
|
||||||
|
sectionType: 'submission-form',
|
||||||
|
collapsed: false,
|
||||||
|
enabled: false,
|
||||||
|
data: {},
|
||||||
|
errors: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false
|
||||||
|
} as any,
|
||||||
|
license: {
|
||||||
|
header: 'submit.progressbar.license',
|
||||||
|
config: '',
|
||||||
|
mandatory: true,
|
||||||
|
sectionType: 'license',
|
||||||
|
visibility: {
|
||||||
|
main: null,
|
||||||
|
other: 'READONLY'
|
||||||
|
},
|
||||||
|
collapsed: false,
|
||||||
|
enabled: true,
|
||||||
|
data: {},
|
||||||
|
errors: [],
|
||||||
|
isLoading: false,
|
||||||
|
isValid: false
|
||||||
|
} as any
|
||||||
|
},
|
||||||
|
isLoading: false,
|
||||||
|
savePending: false,
|
||||||
|
depositPending: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const mockSectionsState = Object.assign({}, {
|
export const mockSectionsState = Object.assign({}, {
|
||||||
extraction: {
|
extraction: {
|
||||||
config: '',
|
config: '',
|
||||||
|
@@ -13,6 +13,11 @@ import { CollectionSelectComponent } from './collection-select.component';
|
|||||||
import { Collection } from '../../../core/shared/collection.model';
|
import { Collection } from '../../../core/shared/collection.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
|
||||||
import { createPaginatedList } from '../../testing/utils.test';
|
import { createPaginatedList } from '../../testing/utils.test';
|
||||||
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('CollectionSelectComponent', () => {
|
describe('CollectionSelectComponent', () => {
|
||||||
let comp: CollectionSelectComponent;
|
let comp: CollectionSelectComponent;
|
||||||
@@ -36,13 +41,15 @@ describe('CollectionSelectComponent', () => {
|
|||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), SharedModule, RouterTestingModule.withRoutes([])],
|
imports: [TranslateModule.forRoot(), SharedModule, RouterTestingModule.withRoutes([])],
|
||||||
declarations: [],
|
declarations: [],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: ObjectSelectService, useValue: new ObjectSelectServiceStub([mockCollectionList[1].id]) },
|
{ provide: ObjectSelectService, useValue: new ObjectSelectServiceStub([mockCollectionList[1].id]) },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) }
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
@@ -11,14 +11,19 @@ import { HostWindowService } from '../../host-window.service';
|
|||||||
import { HostWindowServiceStub } from '../../testing/host-window-service.stub';
|
import { HostWindowServiceStub } from '../../testing/host-window-service.stub';
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { of } from 'rxjs';
|
import { of as observableOf, of } from 'rxjs';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils';
|
||||||
import { createPaginatedList } from '../../testing/utils.test';
|
import { createPaginatedList } from '../../testing/utils.test';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { PaginationServiceStub } from '../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('ItemSelectComponent', () => {
|
describe('ItemSelectComponent', () => {
|
||||||
let comp: ItemSelectComponent;
|
let comp: ItemSelectComponent;
|
||||||
let fixture: ComponentFixture<ItemSelectComponent>;
|
let fixture: ComponentFixture<ItemSelectComponent>;
|
||||||
let objectSelectService: ObjectSelectService;
|
let objectSelectService: ObjectSelectService;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
const mockItemList = [
|
const mockItemList = [
|
||||||
Object.assign(new Item(), {
|
Object.assign(new Item(), {
|
||||||
@@ -59,13 +64,18 @@ describe('ItemSelectComponent', () => {
|
|||||||
currentPage: 1
|
currentPage: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub(mockPaginationOptions);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), SharedModule, RouterTestingModule.withRoutes([])],
|
imports: [TranslateModule.forRoot(), SharedModule, RouterTestingModule.withRoutes([])],
|
||||||
declarations: [],
|
declarations: [],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: ObjectSelectService, useValue: new ObjectSelectServiceStub([mockItemList[1].id]) },
|
{ provide: ObjectSelectService, useValue: new ObjectSelectServiceStub([mockItemList[1].id]) },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) }
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
@@ -12,6 +12,8 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options
|
|||||||
import { EnumKeysPipe } from '../utils/enum-keys-pipe';
|
import { EnumKeysPipe } from '../utils/enum-keys-pipe';
|
||||||
import { VarDirective } from '../utils/var.directive';
|
import { VarDirective } from '../utils/var.directive';
|
||||||
import { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.component';
|
import { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.component';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('PageSizeSelectorComponent', () => {
|
describe('PageSizeSelectorComponent', () => {
|
||||||
|
|
||||||
@@ -33,6 +35,8 @@ describe('PageSizeSelectorComponent', () => {
|
|||||||
sort
|
sort
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub(pagination, sort);
|
||||||
|
|
||||||
const activatedRouteStub = {
|
const activatedRouteStub = {
|
||||||
queryParams: observableOf({
|
queryParams: observableOf({
|
||||||
query: queryParam,
|
query: queryParam,
|
||||||
@@ -46,6 +50,7 @@ describe('PageSizeSelectorComponent', () => {
|
|||||||
declarations: [PageSizeSelectorComponent, EnumKeysPipe, VarDirective],
|
declarations: [PageSizeSelectorComponent, EnumKeysPipe, VarDirective],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{
|
{
|
||||||
provide: SEARCH_CONFIG_SERVICE,
|
provide: SEARCH_CONFIG_SERVICE,
|
||||||
useValue: {
|
useValue: {
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
import { Component, Inject, OnInit } from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
||||||
import { Observable } from 'rxjs';
|
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 { SEARCH_CONFIG_SERVICE } from '../../+my-dspace-page/my-dspace-page.component';
|
||||||
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
||||||
import { PaginatedSearchOptions } from '../search/paginated-search-options.model';
|
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({
|
@Component({
|
||||||
selector: 'ds-page-size-selector',
|
selector: 'ds-page-size-selector',
|
||||||
@@ -22,8 +23,10 @@ export class PageSizeSelectorComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
paginationOptions$: Observable<PaginationComponentOptions>;
|
paginationOptions$: Observable<PaginationComponentOptions>;
|
||||||
|
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute,
|
constructor(private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private paginationService: PaginationService,
|
||||||
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService) {
|
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,13 +43,10 @@ export class PageSizeSelectorComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
reloadRPP(event: Event) {
|
reloadRPP(event: Event) {
|
||||||
const value = (event.target as HTMLInputElement).value;
|
const value = (event.target as HTMLInputElement).value;
|
||||||
const navigationExtras: NavigationExtras = {
|
this.paginationOptions$.pipe(
|
||||||
queryParams: {
|
take(1)
|
||||||
pageSize: value,
|
).subscribe((pagination: PaginationComponentOptions) => {
|
||||||
page: 1
|
this.paginationService.updateRoute(pagination.id, {page: 1, pageSize: +value});
|
||||||
},
|
}) ;
|
||||||
queryParamsHandling: 'merge'
|
|
||||||
};
|
|
||||||
this.router.navigate([], navigationExtras);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,10 @@ import { PaginationComponent } from '../pagination/pagination.component';
|
|||||||
import { createSuccessfulRemoteDataObject } from '../remote-data.utils';
|
import { createSuccessfulRemoteDataObject } from '../remote-data.utils';
|
||||||
import { createPaginatedList } from '../testing/utils.test';
|
import { createPaginatedList } from '../testing/utils.test';
|
||||||
import { ObjectValuesPipe } from '../utils/object-values-pipe';
|
import { ObjectValuesPipe } from '../utils/object-values-pipe';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { PaginationServiceStub } from '../testing/pagination-service.stub';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-mock-paginated-drag-drop-abstract',
|
selector: 'ds-mock-paginated-drag-drop-abstract',
|
||||||
@@ -22,8 +26,9 @@ class MockAbstractPaginatedDragAndDropListComponent extends AbstractPaginatedDra
|
|||||||
protected elRef: ElementRef,
|
protected elRef: ElementRef,
|
||||||
protected objectValuesPipe: ObjectValuesPipe,
|
protected objectValuesPipe: ObjectValuesPipe,
|
||||||
protected mockUrl: string,
|
protected mockUrl: string,
|
||||||
protected mockObjectsRD$: Observable<RemoteData<PaginatedList<DSpaceObject>>>) {
|
protected paginationService: PaginationService,
|
||||||
super(objectUpdatesService, elRef, objectValuesPipe);
|
protected mockObjectsRD$: Observable<RemoteData<PaginatedList<DSpaceObject>>>) {
|
||||||
|
super(objectUpdatesService, elRef, objectValuesPipe, paginationService);
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeObjectsRD(): void {
|
initializeObjectsRD(): void {
|
||||||
@@ -43,10 +48,12 @@ describe('AbstractPaginatedDragAndDropListComponent', () => {
|
|||||||
|
|
||||||
const url = 'mock-abstract-paginated-drag-and-drop-list-component';
|
const url = 'mock-abstract-paginated-drag-and-drop-list-component';
|
||||||
|
|
||||||
|
|
||||||
const object1 = Object.assign(new DSpaceObject(), { uuid: 'object-1' });
|
const object1 = Object.assign(new DSpaceObject(), { uuid: 'object-1' });
|
||||||
const object2 = Object.assign(new DSpaceObject(), { uuid: 'object-2' });
|
const object2 = Object.assign(new DSpaceObject(), { uuid: 'object-2' });
|
||||||
const objectsRD = createSuccessfulRemoteDataObject(createPaginatedList([object1, object2]));
|
const objectsRD = createSuccessfulRemoteDataObject(createPaginatedList([object1, object2]));
|
||||||
let objectsRD$: BehaviorSubject<RemoteData<PaginatedList<DSpaceObject>>>;
|
let objectsRD$: BehaviorSubject<RemoteData<PaginatedList<DSpaceObject>>>;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
const updates = {
|
const updates = {
|
||||||
[object1.uuid]: { field: object1, changeType: undefined },
|
[object1.uuid]: { field: object1, changeType: undefined },
|
||||||
@@ -69,8 +76,9 @@ describe('AbstractPaginatedDragAndDropListComponent', () => {
|
|||||||
paginationComponent = jasmine.createSpyObj('paginationComponent', {
|
paginationComponent = jasmine.createSpyObj('paginationComponent', {
|
||||||
doPageChange: {}
|
doPageChange: {}
|
||||||
});
|
});
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
objectsRD$ = new BehaviorSubject(objectsRD);
|
objectsRD$ = new BehaviorSubject(objectsRD);
|
||||||
component = new MockAbstractPaginatedDragAndDropListComponent(objectUpdatesService, elRef, objectValuesPipe, url, objectsRD$);
|
component = new MockAbstractPaginatedDragAndDropListComponent(objectUpdatesService, elRef, objectValuesPipe, url, paginationService, objectsRD$);
|
||||||
component.paginationComponent = paginationComponent;
|
component.paginationComponent = paginationComponent;
|
||||||
component.ngOnInit();
|
component.ngOnInit();
|
||||||
});
|
});
|
||||||
@@ -86,18 +94,6 @@ describe('AbstractPaginatedDragAndDropListComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('switchPage', () => {
|
|
||||||
const page = 3;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
component.switchPage(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set currentPage$ to the new page', () => {
|
|
||||||
expect(component.currentPage$.value).toEqual(page);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('drop', () => {
|
describe('drop', () => {
|
||||||
const event = {
|
const event = {
|
||||||
previousIndex: 0,
|
previousIndex: 0,
|
||||||
@@ -117,7 +113,7 @@ describe('AbstractPaginatedDragAndDropListComponent', () => {
|
|||||||
|
|
||||||
it('should send out a dropObject event with the expected processed paginated indexes', () => {
|
it('should send out a dropObject event with the expected processed paginated indexes', () => {
|
||||||
expect(component.dropObject.emit).toHaveBeenCalledWith(Object.assign({
|
expect(component.dropObject.emit).toHaveBeenCalledWith(Object.assign({
|
||||||
fromIndex: ((component.currentPage$.value - 1) * component.pageSize) + event.previousIndex,
|
fromIndex: ((component.currentPage$.value.currentPage - 1) * component.pageSize) + event.previousIndex,
|
||||||
toIndex: ((hoverPage - 1) * component.pageSize),
|
toIndex: ((hoverPage - 1) * component.pageSize),
|
||||||
finish: jasmine.anything()
|
finish: jasmine.anything()
|
||||||
}));
|
}));
|
||||||
|
@@ -17,6 +17,7 @@ import { Component, ElementRef, EventEmitter, OnDestroy, Output, ViewChild } fro
|
|||||||
import { PaginationComponent } from '../pagination/pagination.component';
|
import { PaginationComponent } from '../pagination/pagination.component';
|
||||||
import { ObjectValuesPipe } from '../utils/object-values-pipe';
|
import { ObjectValuesPipe } from '../utils/object-values-pipe';
|
||||||
import { compareArraysUsing } from '../../+item-page/simple/item-types/shared/item-relationships-utils';
|
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
|
* Operator used for comparing {@link FieldUpdate}s by their field's UUID
|
||||||
@@ -88,7 +89,7 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
|||||||
* Start at page 1 and always use the set page size
|
* Start at page 1 and always use the set page size
|
||||||
*/
|
*/
|
||||||
options = Object.assign(new PaginationComponentOptions(),{
|
options = Object.assign(new PaginationComponentOptions(),{
|
||||||
id: 'paginated-drag-and-drop-options',
|
id: 'dad',
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
pageSize: this.pageSize
|
pageSize: this.pageSize
|
||||||
});
|
});
|
||||||
@@ -96,7 +97,7 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
|||||||
/**
|
/**
|
||||||
* The current page being displayed
|
* The current page being displayed
|
||||||
*/
|
*/
|
||||||
currentPage$ = new BehaviorSubject<number>(1);
|
currentPage$ = new BehaviorSubject<PaginationComponentOptions>(this.options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not we should display a loading animation
|
* Whether or not we should display a loading animation
|
||||||
@@ -113,7 +114,9 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
|||||||
|
|
||||||
protected constructor(protected objectUpdatesService: ObjectUpdatesService,
|
protected constructor(protected objectUpdatesService: ObjectUpdatesService,
|
||||||
protected elRef: ElementRef,
|
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.initializeObjectsRD();
|
||||||
this.initializeURL();
|
this.initializeURL();
|
||||||
this.initializeUpdates();
|
this.initializeUpdates();
|
||||||
|
this.initializePagination();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,6 +139,15 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
|||||||
*/
|
*/
|
||||||
abstract initializeURL(): void;
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the field-updates in the store
|
* 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
|
* 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
|
* When the object is dropped on a page within the pagination of this component, the object moves to the top of that
|
||||||
@@ -182,8 +187,8 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
|||||||
drop(event: CdkDragDrop<any>) {
|
drop(event: CdkDragDrop<any>) {
|
||||||
const dragIndex = event.previousIndex;
|
const dragIndex = event.previousIndex;
|
||||||
let dropIndex = event.currentIndex;
|
let dropIndex = event.currentIndex;
|
||||||
const dragPage = this.currentPage$.value - 1;
|
const dragPage = this.currentPage$.value.currentPage - 1;
|
||||||
let dropPage = this.currentPage$.value - 1;
|
let dropPage = this.currentPage$.value.currentPage - 1;
|
||||||
|
|
||||||
// Check if the user is hovering over any of the pagination's pages at the time of dropping the object
|
// Check if the user is hovering over any of the pagination's pages at the time of dropping the object
|
||||||
const droppedOnElement = this.elRef.nativeElement.querySelector('.page-item:hover');
|
const droppedOnElement = this.elRef.nativeElement.querySelector('.page-item:hover');
|
||||||
@@ -228,5 +233,6 @@ export abstract class AbstractPaginatedDragAndDropListComponent<T extends DSpace
|
|||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
this.subs.filter((sub) => hasValue(sub)).forEach((sub) => sub.unsubscribe());
|
||||||
|
this.paginationService.clearPagination(this.options.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
<div *ngIf="currentPageState == undefined || currentPageState == currentPage">
|
<div *ngIf="currentPageState == undefined || currentPageState == (currentPage$|async)" [id]="'p-' + id">
|
||||||
<div *ngIf="(!hidePaginationDetail && collectionSize > 0) || !hideGear" class="pagination-masked clearfix top">
|
<div *ngIf="(!hidePaginationDetail && collectionSize > 0) || !hideGear" class="pagination-masked clearfix top">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div *ngIf="!hidePaginationDetail && collectionSize > 0" class="col-auto pagination-info">
|
<div *ngIf="!hidePaginationDetail && collectionSize > 0" class="col-auto pagination-info">
|
||||||
<span class="align-middle hidden-xs-down">{{ 'pagination.showing.label' | translate }}</span>
|
<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>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div *ngIf="!hideGear" ngbDropdown #paginationControls="ngbDropdown" placement="bottom-right" class="d-inline-block float-right">
|
<div *ngIf="!hideGear" ngbDropdown #paginationControls="ngbDropdown" placement="bottom-right" class="d-inline-block float-right">
|
||||||
<button class="btn btn-secondary" id="paginationControls" ngbDropdownToggle [title]="'pagination.options.description' | translate" [attr.aria-label]="'pagination.options.description' | translate"><i class="fas fa-cog" aria-hidden="true"></i></button>
|
<button class="btn btn-secondary" id="paginationControls" ngbDropdownToggle [title]="'pagination.options.description' | translate" [attr.aria-label]="'pagination.options.description' | translate"><i class="fas fa-cog" aria-hidden="true"></i></button>
|
||||||
<div id="paginationControlsDropdownMenu" aria-labelledby="paginationControls" ngbDropdownMenu>
|
<div id="paginationControlsDropdownMenu" aria-labelledby="paginationControls" ngbDropdownMenu>
|
||||||
<h6 class="dropdown-header">{{ 'pagination.results-per-page' | translate}}</h6>
|
<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>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -20,15 +20,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<ng-content></ng-content>
|
<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"
|
<ngb-pagination [boundaryLinks]="paginationOptions.boundaryLinks"
|
||||||
[collectionSize]="collectionSize"
|
[collectionSize]="collectionSize"
|
||||||
[disabled]="paginationOptions.disabled"
|
[disabled]="paginationOptions.disabled"
|
||||||
[ellipses]="paginationOptions.ellipses"
|
[ellipses]="paginationOptions.ellipses"
|
||||||
[maxSize]="(isXs)?5:paginationOptions.maxSize"
|
[maxSize]="(isXs)?5:paginationOptions.maxSize"
|
||||||
[page]="currentPage"
|
[page]="(currentPage$|async)"
|
||||||
(pageChange)="doPageChange($event)"
|
(pageChange)="doPageChange($event)"
|
||||||
[pageSize]="pageSize"
|
[pageSize]="(pageSize$ |async)"
|
||||||
[rotate]="paginationOptions.rotate"
|
[rotate]="paginationOptions.rotate"
|
||||||
[size]="(isXs)?'sm':paginationOptions.size"></ngb-pagination>
|
[size]="(isXs)?'sm':paginationOptions.size"></ngb-pagination>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -31,6 +31,10 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options
|
|||||||
|
|
||||||
import { createTestComponent } from '../testing/utils.test';
|
import { createTestComponent } from '../testing/utils.test';
|
||||||
import { storeModuleConfig } from '../../app.reducer';
|
import { storeModuleConfig } from '../../app.reducer';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { FindListOptions } from '../../core/data/request.models';
|
||||||
|
import { BehaviorSubject, of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationServiceStub } from '../testing/pagination-service.stub';
|
||||||
|
|
||||||
function expectPages(fixture: ComponentFixture<any>, pagesDef: string[]): void {
|
function expectPages(fixture: ComponentFixture<any>, pagesDef: string[]): void {
|
||||||
const de = fixture.debugElement.query(By.css('.pagination'));
|
const de = fixture.debugElement.query(By.css('.pagination'));
|
||||||
@@ -105,15 +109,41 @@ describe('Pagination component', () => {
|
|||||||
let activatedRouteStub: MockActivatedRoute;
|
let activatedRouteStub: MockActivatedRoute;
|
||||||
let routerStub: RouterMock;
|
let routerStub: RouterMock;
|
||||||
|
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
// Define initial state and test state
|
// Define initial state and test state
|
||||||
const _initialState = { width: 1600, height: 770 };
|
const _initialState = { width: 1600, height: 770 };
|
||||||
|
|
||||||
|
const pagination = new PaginationComponentOptions();
|
||||||
|
pagination.currentPage = 1;
|
||||||
|
pagination.pageSize = 10;
|
||||||
|
|
||||||
|
const sort = new SortOptions('score', SortDirection.DESC);
|
||||||
|
const findlistOptions = Object.assign(new FindListOptions(), { currentPage: 1, elementsPerPage: 10 });
|
||||||
|
let currentPagination;
|
||||||
|
let currentSort;
|
||||||
|
let currentFindListOptions;
|
||||||
|
|
||||||
// waitForAsync beforeEach
|
// waitForAsync beforeEach
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
activatedRouteStub = new MockActivatedRoute();
|
activatedRouteStub = new MockActivatedRoute();
|
||||||
routerStub = new RouterMock();
|
routerStub = new RouterMock();
|
||||||
hostWindowServiceStub = new HostWindowServiceMock(_initialState.width);
|
hostWindowServiceStub = new HostWindowServiceMock(_initialState.width);
|
||||||
|
|
||||||
|
currentPagination = new BehaviorSubject<PaginationComponentOptions>(pagination);
|
||||||
|
currentSort = new BehaviorSubject<SortOptions>(sort);
|
||||||
|
currentFindListOptions = new BehaviorSubject<FindListOptions>(findlistOptions);
|
||||||
|
|
||||||
|
|
||||||
|
paginationService = jasmine.createSpyObj('PaginationService', {
|
||||||
|
getCurrentPagination: currentPagination,
|
||||||
|
getCurrentSort: currentSort,
|
||||||
|
getFindListOptions: currentFindListOptions,
|
||||||
|
resetPage: {},
|
||||||
|
updateRoute: {},
|
||||||
|
updateRouteWithUrl: {}
|
||||||
|
});
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -138,6 +168,7 @@ describe('Pagination component', () => {
|
|||||||
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
||||||
{ provide: Router, useValue: routerStub },
|
{ provide: Router, useValue: routerStub },
|
||||||
{ provide: HostWindowService, useValue: hostWindowServiceStub },
|
{ provide: HostWindowService, useValue: hostWindowServiceStub },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
PaginationComponent
|
PaginationComponent
|
||||||
],
|
],
|
||||||
@@ -179,11 +210,17 @@ describe('Pagination component', () => {
|
|||||||
|
|
||||||
it('should render and respond to page change', () => {
|
it('should render and respond to page change', () => {
|
||||||
testComp.collectionSize = 30;
|
testComp.collectionSize = 30;
|
||||||
|
testFixture.detectChanges();
|
||||||
|
|
||||||
|
|
||||||
|
currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {currentPage: 3}));
|
||||||
|
testFixture.detectChanges();
|
||||||
|
|
||||||
changePage(testFixture, 3);
|
|
||||||
expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']);
|
expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']);
|
||||||
|
|
||||||
changePage(testFixture, 0);
|
currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {currentPage: 2}));
|
||||||
|
testFixture.detectChanges();
|
||||||
|
|
||||||
expectPages(testFixture, ['« Previous', '1', '+2', '3', '» Next']);
|
expectPages(testFixture, ['« Previous', '1', '+2', '3', '» Next']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -205,58 +242,41 @@ describe('Pagination component', () => {
|
|||||||
testFixture.detectChanges();
|
testFixture.detectChanges();
|
||||||
expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']);
|
expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']);
|
||||||
|
|
||||||
paginationComponent.setPageSize(5);
|
currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 5}));
|
||||||
testFixture.detectChanges();
|
testFixture.detectChanges();
|
||||||
|
|
||||||
expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '6', '» Next']);
|
expectPages(testFixture, ['-« Previous', '+1', '2', '3', '4', '5', '6', '» Next']);
|
||||||
|
|
||||||
paginationComponent.setPageSize(10);
|
currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 10}));
|
||||||
testFixture.detectChanges();
|
testFixture.detectChanges();
|
||||||
expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']);
|
expectPages(testFixture, ['-« Previous', '+1', '2', '3', '» Next']);
|
||||||
|
|
||||||
paginationComponent.setPageSize(20);
|
currentPagination.next(Object.assign(new PaginationComponentOptions(), pagination, {pageSize: 20}));
|
||||||
testFixture.detectChanges();
|
testFixture.detectChanges();
|
||||||
expectPages(testFixture, ['-« Previous', '+1', '2', '» Next']);
|
expectPages(testFixture, ['-« Previous', '+1', '2', '» Next']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit pageChange event with correct value', fakeAsync(() => {
|
|
||||||
const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p;
|
|
||||||
|
|
||||||
spyOn(testComp, 'pageChanged');
|
|
||||||
|
|
||||||
paginationComponent.setPage(3);
|
|
||||||
tick();
|
|
||||||
|
|
||||||
expect(testComp.pageChanged).toHaveBeenCalledWith(3);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should emit pageSizeChange event with correct value', fakeAsync(() => {
|
it('should emit pageSizeChange event with correct value', fakeAsync(() => {
|
||||||
const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p;
|
const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p;
|
||||||
|
|
||||||
spyOn(testComp, 'pageSizeChanged');
|
spyOn(testComp, 'pageSizeChanged');
|
||||||
|
|
||||||
paginationComponent.setPageSize(5);
|
testComp.pageSizeChanged(5);
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(testComp.pageSizeChanged).toHaveBeenCalledWith(5);
|
expect(testComp.pageSizeChanged).toHaveBeenCalledWith(5);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set correct page route parameters', fakeAsync(() => {
|
it('should call the updateRoute method on the paginationService with the correct params', fakeAsync(() => {
|
||||||
routerStub = testFixture.debugElement.injector.get(Router) as any;
|
|
||||||
|
|
||||||
testComp.collectionSize = 60;
|
testComp.collectionSize = 60;
|
||||||
|
|
||||||
changePage(testFixture, 3);
|
changePage(testFixture, 3);
|
||||||
tick();
|
tick();
|
||||||
expect(routerStub.navigate).toHaveBeenCalledWith([], {
|
expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ page: '3'}), {}, false);
|
||||||
queryParams: {
|
|
||||||
pageId: 'test',
|
|
||||||
page: '3',
|
|
||||||
pageSize: 10,
|
|
||||||
sortDirection: 'ASC',
|
|
||||||
sortField: 'dc.title'
|
|
||||||
}, queryParamsHandling: 'merge'
|
|
||||||
});
|
|
||||||
|
|
||||||
|
changePage(testFixture, 0);
|
||||||
|
tick();
|
||||||
|
expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ page: '2'}), {}, false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set correct pageSize route parameters', fakeAsync(() => {
|
it('should set correct pageSize route parameters', fakeAsync(() => {
|
||||||
@@ -266,58 +286,9 @@ describe('Pagination component', () => {
|
|||||||
|
|
||||||
changePageSize(testFixture, '20');
|
changePageSize(testFixture, '20');
|
||||||
tick();
|
tick();
|
||||||
expect(routerStub.navigate).toHaveBeenCalledWith([], {
|
expect(paginationService.updateRoute).toHaveBeenCalledWith('test', Object.assign({ pageId: 'test', page: 1, pageSize: 20}), {}, false);
|
||||||
queryParams: {
|
|
||||||
pageId: 'test',
|
|
||||||
page: 1,
|
|
||||||
pageSize: 20,
|
|
||||||
sortDirection: 'ASC',
|
|
||||||
sortField: 'dc.title'
|
|
||||||
}, queryParamsHandling: 'merge'
|
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set correct values', fakeAsync(() => {
|
|
||||||
const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p;
|
|
||||||
routerStub = testFixture.debugElement.injector.get(Router) as any;
|
|
||||||
|
|
||||||
testComp.collectionSize = 60;
|
|
||||||
|
|
||||||
paginationComponent.setPage(3);
|
|
||||||
expect(paginationComponent.currentPage).toEqual(3);
|
|
||||||
|
|
||||||
paginationComponent.setPageSize(20);
|
|
||||||
expect(paginationComponent.pageSize).toEqual(20);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should get parameters from route', () => {
|
|
||||||
|
|
||||||
activatedRouteStub = testFixture.debugElement.injector.get(ActivatedRoute) as any;
|
|
||||||
activatedRouteStub.testParams = {
|
|
||||||
pageId: 'test',
|
|
||||||
page: 2,
|
|
||||||
pageSize: 20
|
|
||||||
};
|
|
||||||
|
|
||||||
testFixture.detectChanges();
|
|
||||||
|
|
||||||
expectPages(testFixture, ['« Previous', '1', '+2', '3', '4', '5', '» Next']);
|
|
||||||
expect(testComp.paginationOptions.currentPage).toEqual(2);
|
|
||||||
expect(testComp.paginationOptions.pageSize).toEqual(20);
|
|
||||||
|
|
||||||
activatedRouteStub.testParams = {
|
|
||||||
pageId: 'test',
|
|
||||||
page: 3,
|
|
||||||
pageSize: 40
|
|
||||||
};
|
|
||||||
|
|
||||||
testFixture.detectChanges();
|
|
||||||
|
|
||||||
expectPages(testFixture, ['« Previous', '1', '2', '+3', '-» Next']);
|
|
||||||
expect(testComp.paginationOptions.currentPage).toEqual(3);
|
|
||||||
expect(testComp.paginationOptions.pageSize).toEqual(40);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should respond to windows resize', () => {
|
it('should respond to windows resize', () => {
|
||||||
const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p;
|
const paginationComponent: PaginationComponent = testFixture.debugElement.query(By.css('ds-pagination')).references.p;
|
||||||
hostWindowServiceStub = testFixture.debugElement.injector.get(HostWindowService) as any;
|
hostWindowServiceStub = testFixture.debugElement.injector.get(HostWindowService) as any;
|
||||||
|
@@ -9,19 +9,17 @@ import {
|
|||||||
Output,
|
Output,
|
||||||
ViewEncapsulation
|
ViewEncapsulation
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
|
||||||
|
|
||||||
import { Observable, Subscription } from 'rxjs';
|
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
||||||
import { isNumeric } from 'rxjs/internal-compatibility';
|
|
||||||
import { isEqual, isObject, transform } from 'lodash';
|
|
||||||
|
|
||||||
import { HostWindowService } from '../host-window.service';
|
import { HostWindowService } from '../host-window.service';
|
||||||
import { HostWindowState } from '../search/host-window.reducer';
|
import { HostWindowState } from '../search/host-window.reducer';
|
||||||
import { PaginationComponentOptions } from './pagination-component-options.model';
|
import { PaginationComponentOptions } from './pagination-component-options.model';
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-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 { PageInfo } from '../../core/shared/page-info.model';
|
||||||
import { difference } from '../object.util';
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default pagination controls component.
|
* The default pagination controls component.
|
||||||
@@ -101,37 +99,31 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
@Input() public hidePagerWhenSinglePage = true;
|
@Input() public hidePagerWhenSinglePage = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Option for disabling updating and reading route parameters on pagination changes
|
* Option for retaining the scroll position upon navigating to an url with updated params.
|
||||||
* In other words, changing pagination won't add or update the url parameters on the current page, and the url
|
* After the page update the page will scroll back to the current pagination component.
|
||||||
* parameters won't affect the pagination of this component
|
|
||||||
*/
|
*/
|
||||||
@Input() public disableRouteParameterUpdate = false;
|
@Input() public retainScrollPosition = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current page.
|
* Current page.
|
||||||
*/
|
*/
|
||||||
public currentPage;
|
public currentPage$;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current page in the state of a Remote paginated objects.
|
* Current page in the state of a Remote paginated objects.
|
||||||
*/
|
*/
|
||||||
public currentPageState: number = undefined;
|
public currentPageState: number = undefined;
|
||||||
|
|
||||||
/**
|
|
||||||
* Current URL query parameters
|
|
||||||
*/
|
|
||||||
public currentQueryParams: any;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An observable of HostWindowState type
|
* An observable of HostWindowState type
|
||||||
*/
|
*/
|
||||||
public hostWindow: Observable<HostWindowState>;
|
public hostWindow: Observable<HostWindowState>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID for the pagination instance. Only useful if you wish to
|
* ID for the pagination instance. This ID is used in the routing to retrieve the pagination options.
|
||||||
* have more than once instance at a time in a given component.
|
* This ID needs to be unique between different pagination components when more than one will be displayed on the same page.
|
||||||
*/
|
*/
|
||||||
private id: string;
|
public id: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A boolean that indicate if is an extra small devices viewport.
|
* A boolean that indicate if is an extra small devices viewport.
|
||||||
@@ -141,7 +133,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
/**
|
/**
|
||||||
* Number of items per page.
|
* Number of items per page.
|
||||||
*/
|
*/
|
||||||
public pageSize;
|
public pageSize$;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare SortDirection enumeration to use it in the template
|
* Declare SortDirection enumeration to use it in the template
|
||||||
@@ -156,12 +148,14 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
/**
|
/**
|
||||||
* Direction in which to sort: ascending or descending
|
* 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
|
* Name of the field that's used to sort by
|
||||||
*/
|
*/
|
||||||
public sortField = 'id';
|
public sortField$;
|
||||||
|
public defaultSortField = 'name';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array to track all subscriptions and unsubscribe them onDestroy
|
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||||
@@ -180,40 +174,6 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
}));
|
}));
|
||||||
this.checkConfig(this.paginationOptions);
|
this.checkConfig(this.paginationOptions);
|
||||||
this.initializeConfig();
|
this.initializeConfig();
|
||||||
// Listen to changes
|
|
||||||
if (!this.disableRouteParameterUpdate) {
|
|
||||||
this.subs.push(this.route.queryParams
|
|
||||||
.subscribe((queryParams) => {
|
|
||||||
this.initializeParams(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,23 +188,29 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
/**
|
/**
|
||||||
* Initializes all default variables
|
* Initializes all default variables
|
||||||
*/
|
*/
|
||||||
private initializeConfig(queryParams: any = {}) {
|
private initializeConfig() {
|
||||||
// Set initial values
|
// Set initial values
|
||||||
this.id = this.paginationOptions.id || null;
|
this.id = this.paginationOptions.id || null;
|
||||||
this.pageSizeOptions = this.paginationOptions.pageSizeOptions;
|
this.pageSizeOptions = this.paginationOptions.pageSizeOptions;
|
||||||
this.currentPage = this.paginationOptions.currentPage;
|
this.currentPage$ = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe(
|
||||||
this.pageSize = this.paginationOptions.pageSize;
|
map((currentPagination) => currentPagination.currentPage)
|
||||||
|
);
|
||||||
|
this.pageSize$ = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe(
|
||||||
|
map((currentPagination) => currentPagination.pageSize)
|
||||||
|
);
|
||||||
|
|
||||||
|
let sortOptions;
|
||||||
if (this.sortOptions) {
|
if (this.sortOptions) {
|
||||||
this.sortDirection = this.sortOptions.direction;
|
sortOptions = this.sortOptions;
|
||||||
this.sortField = this.sortOptions.field;
|
} else {
|
||||||
|
sortOptions = new SortOptions(this.defaultSortField, this.defaultsortDirection);
|
||||||
}
|
}
|
||||||
this.currentQueryParams = Object.assign({}, queryParams, {
|
this.sortDirection$ = this.paginationService.getCurrentSort(this.id, sortOptions).pipe(
|
||||||
pageId: this.id,
|
map((currentSort) => currentSort.direction)
|
||||||
page: this.currentPage,
|
);
|
||||||
pageSize: this.pageSize,
|
this.sortField$ = this.paginationService.getCurrentSort(this.id, sortOptions).pipe(
|
||||||
sortDirection: this.sortDirection,
|
map((currentSort) => currentSort.field)
|
||||||
sortField: this.sortField
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -258,8 +224,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
* the HostWindowService singleton.
|
* the HostWindowService singleton.
|
||||||
*/
|
*/
|
||||||
constructor(private cdRef: ChangeDetectorRef,
|
constructor(private cdRef: ChangeDetectorRef,
|
||||||
private route: ActivatedRoute,
|
private paginationService: PaginationService,
|
||||||
private router: Router,
|
|
||||||
public hostWindowService: HostWindowService) {
|
public hostWindowService: HostWindowService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +235,8 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
* The page being navigated to.
|
* The page being navigated to.
|
||||||
*/
|
*/
|
||||||
public doPageChange(page: number) {
|
public doPageChange(page: number) {
|
||||||
this.updateParams(Object.assign({}, this.currentQueryParams, { pageId: this.id, page: page.toString() }));
|
this.updateParams({page: page.toString()});
|
||||||
|
this.emitPaginationChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,7 +246,8 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
* The page size being navigated to.
|
* The page size being navigated to.
|
||||||
*/
|
*/
|
||||||
public doPageSizeChange(pageSize: number) {
|
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 });
|
||||||
|
this.emitPaginationChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -290,7 +257,8 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
* The sort direction being navigated to.
|
* The sort direction being navigated to.
|
||||||
*/
|
*/
|
||||||
public doSortDirectionChange(sortDirection: SortDirection) {
|
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 });
|
||||||
|
this.emitPaginationChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -300,54 +268,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
* The sort field being navigated to.
|
* The sort field being navigated to.
|
||||||
*/
|
*/
|
||||||
public doSortFieldChange(field: string) {
|
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 });
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to set the current page and trigger page change events
|
|
||||||
*
|
|
||||||
* @param page
|
|
||||||
* The new page value
|
|
||||||
*/
|
|
||||||
public setPage(page: number) {
|
|
||||||
this.currentPage = page;
|
|
||||||
this.pageChange.emit(page);
|
|
||||||
this.emitPaginationChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to set the current page size and trigger page size change events
|
|
||||||
*
|
|
||||||
* @param pageSize
|
|
||||||
* The new page size value.
|
|
||||||
*/
|
|
||||||
public setPageSize(pageSize: number) {
|
|
||||||
this.pageSize = pageSize;
|
|
||||||
this.pageSizeChange.emit(pageSize);
|
|
||||||
this.emitPaginationChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to set the current sort direction and trigger sort direction change events
|
|
||||||
*
|
|
||||||
* @param sortDirection
|
|
||||||
* The new sort directionvalue.
|
|
||||||
*/
|
|
||||||
public setSortDirection(sortDirection: SortDirection) {
|
|
||||||
this.sortDirection = sortDirection;
|
|
||||||
this.sortDirectionChange.emit(sortDirection);
|
|
||||||
this.emitPaginationChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to set the current sort field and trigger sort field change events
|
|
||||||
*
|
|
||||||
* @param sortField
|
|
||||||
* The new sort field.
|
|
||||||
*/
|
|
||||||
public setSortField(field: string) {
|
|
||||||
this.sortField = field;
|
|
||||||
this.sortFieldChange.emit(field);
|
|
||||||
this.emitPaginationChange();
|
this.emitPaginationChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,19 +276,7 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
* Method to emit a general pagination change event
|
* Method to emit a general pagination change event
|
||||||
*/
|
*/
|
||||||
private emitPaginationChange() {
|
private emitPaginationChange() {
|
||||||
this.paginationChange.emit(
|
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)
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -375,142 +284,34 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
private updateParams(params: {}) {
|
private updateParams(params: {}) {
|
||||||
if (isNotEmpty(difference(params, this.currentQueryParams))) {
|
this.paginationService.updateRoute(this.id, params, {}, this.retainScrollPosition);
|
||||||
if (!this.disableRouteParameterUpdate) {
|
|
||||||
this.updateRoute(params);
|
|
||||||
} else {
|
|
||||||
this.initializeParams(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
* Method to get pagination details of the current viewed page.
|
||||||
*/
|
*/
|
||||||
public getShowingDetails(collectionSize: number): any {
|
public getShowingDetails(collectionSize: number): Observable<any> {
|
||||||
let showingDetails = { range: null + ' - ' + null, total: null };
|
let showingDetails = observableOf({ range: null + ' - ' + null, total: null });
|
||||||
if (collectionSize) {
|
if (collectionSize) {
|
||||||
let firstItem;
|
showingDetails = this.paginationService.getCurrentPagination(this.id, this.paginationOptions).pipe(
|
||||||
let lastItem;
|
map((currentPaginationOptions) => {
|
||||||
const pageMax = this.pageSize * this.currentPage;
|
let firstItem;
|
||||||
|
let lastItem;
|
||||||
|
const pageMax = currentPaginationOptions.pageSize * currentPaginationOptions.currentPage;
|
||||||
|
|
||||||
firstItem = this.pageSize * (this.currentPage - 1) + 1;
|
firstItem = currentPaginationOptions.pageSize * (currentPaginationOptions.currentPage - 1) + 1;
|
||||||
if (collectionSize > pageMax) {
|
if (collectionSize > pageMax) {
|
||||||
lastItem = pageMax;
|
lastItem = pageMax;
|
||||||
} else {
|
} else {
|
||||||
lastItem = collectionSize;
|
lastItem = collectionSize;
|
||||||
}
|
}
|
||||||
showingDetails = { range: firstItem + ' - ' + lastItem, total: collectionSize };
|
return {range: firstItem + ' - ' + lastItem, total: collectionSize};
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return showingDetails;
|
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.
|
* Method to ensure options passed contains the required properties.
|
||||||
*
|
*
|
||||||
@@ -527,34 +328,23 @@ export class PaginationComponent implements OnDestroy, OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to check if none of the query params necessary for pagination are filled out.
|
|
||||||
*
|
|
||||||
* @param paginateOptions
|
|
||||||
* The paginate options object.
|
|
||||||
*/
|
|
||||||
private isEmptyPaginationParams(paginateOptions): boolean {
|
|
||||||
const properties = ['id', 'currentPage', 'pageSize', 'pageSizeOptions'];
|
|
||||||
const missing = properties.filter((prop) => {
|
|
||||||
return !(prop in paginateOptions);
|
|
||||||
});
|
|
||||||
|
|
||||||
return properties.length === missing.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property to check whether the current pagination object has multiple pages
|
* Property to check whether the current pagination object has multiple pages
|
||||||
* @returns true if there are multiple pages, else returns false
|
* @returns true if there are multiple pages, else returns false
|
||||||
*/
|
*/
|
||||||
get hasMultiplePages(): boolean {
|
get hasMultiplePages(): Observable<boolean> {
|
||||||
return this.collectionSize > this.pageSize;
|
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
|
* Property to check whether the current pagination should show a bottom pages
|
||||||
* @returns true if a bottom pages should be shown, else returns false
|
* @returns true if a bottom pages should be shown, else returns false
|
||||||
*/
|
*/
|
||||||
get shouldShowBottomPager(): boolean {
|
get shouldShowBottomPager(): Observable<boolean> {
|
||||||
return this.hasMultiplePages || !this.hidePagerWhenSinglePage;
|
return this.hasMultiplePages.pipe(
|
||||||
|
map((hasMultiplePages) => hasMultiplePages || !this.hidePagerWhenSinglePage)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,9 +5,8 @@
|
|||||||
<ds-pagination *ngIf="(getList() | async)?.payload?.totalElements > 0"
|
<ds-pagination *ngIf="(getList() | async)?.payload?.totalElements > 0"
|
||||||
[paginationOptions]="paginationOptions"
|
[paginationOptions]="paginationOptions"
|
||||||
[collectionSize]="(getList() | async)?.payload?.totalElements"
|
[collectionSize]="(getList() | async)?.payload?.totalElements"
|
||||||
[disableRouteParameterUpdate]="true"
|
[retainScrollPosition]="true"
|
||||||
[hideGear]="true"
|
[hideGear]="true">
|
||||||
(pageChange)="onPageChange($event)">
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="groups" class="table table-sm table-striped table-hover table-bordered">
|
<table id="groups" class="table table-sm table-striped table-hover table-bordered">
|
||||||
|
@@ -19,6 +19,10 @@ import { PaginationComponentOptions } from '../../../pagination/pagination-compo
|
|||||||
import { buildPaginatedList } from '../../../../core/data/paginated-list.model';
|
import { buildPaginatedList } from '../../../../core/data/paginated-list.model';
|
||||||
import { PageInfo } from '../../../../core/shared/page-info.model';
|
import { PageInfo } from '../../../../core/shared/page-info.model';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('EpersonGroupListComponent test suite', () => {
|
describe('EpersonGroupListComponent test suite', () => {
|
||||||
let comp: EpersonGroupListComponent;
|
let comp: EpersonGroupListComponent;
|
||||||
@@ -27,6 +31,7 @@ describe('EpersonGroupListComponent test suite', () => {
|
|||||||
let de;
|
let de;
|
||||||
let groupService: any;
|
let groupService: any;
|
||||||
let epersonService: any;
|
let epersonService: any;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
const paginationOptions: PaginationComponentOptions = new PaginationComponentOptions();
|
const paginationOptions: PaginationComponentOptions = new PaginationComponentOptions();
|
||||||
paginationOptions.id = uniqueId('eperson-group-list-pagination-test');
|
paginationOptions.id = uniqueId('eperson-group-list-pagination-test');
|
||||||
@@ -60,6 +65,8 @@ describe('EpersonGroupListComponent test suite', () => {
|
|||||||
const groupPaginatedList = buildPaginatedList(new PageInfo(), [GroupMock, GroupMock]);
|
const groupPaginatedList = buildPaginatedList(new PageInfo(), [GroupMock, GroupMock]);
|
||||||
const groupPaginatedListRD = createSuccessfulRemoteDataObject(groupPaginatedList);
|
const groupPaginatedListRD = createSuccessfulRemoteDataObject(groupPaginatedList);
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -74,6 +81,7 @@ describe('EpersonGroupListComponent test suite', () => {
|
|||||||
{ provide: EPersonDataService, useValue: mockEpersonService },
|
{ provide: EPersonDataService, useValue: mockEpersonService },
|
||||||
{ provide: GroupDataService, useValue: mockGroupService },
|
{ provide: GroupDataService, useValue: mockGroupService },
|
||||||
{ provide: RequestService, useValue: getMockRequestService() },
|
{ provide: RequestService, useValue: getMockRequestService() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
EpersonGroupListComponent,
|
EpersonGroupListComponent,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
Injector
|
Injector
|
||||||
@@ -177,13 +185,6 @@ describe('EpersonGroupListComponent test suite', () => {
|
|||||||
a: false
|
a: false
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update list on page change', () => {
|
|
||||||
spyOn(comp, 'updateList');
|
|
||||||
comp.onPageChange(2);
|
|
||||||
|
|
||||||
expect(compAsAny.updateList).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when is list of group', () => {
|
describe('when is list of group', () => {
|
||||||
@@ -255,13 +256,6 @@ describe('EpersonGroupListComponent test suite', () => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update list on page change', () => {
|
|
||||||
spyOn(comp, 'updateList');
|
|
||||||
comp.onPageChange(2);
|
|
||||||
|
|
||||||
expect(compAsAny.updateList).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update list on search triggered', () => {
|
it('should update list on search triggered', () => {
|
||||||
const options: PaginationComponentOptions = comp.paginationOptions;
|
const options: PaginationComponentOptions = comp.paginationOptions;
|
||||||
const event: SearchEvent = {
|
const event: SearchEvent = {
|
||||||
@@ -271,7 +265,7 @@ describe('EpersonGroupListComponent test suite', () => {
|
|||||||
spyOn(comp, 'updateList');
|
spyOn(comp, 'updateList');
|
||||||
comp.onSearch(event);
|
comp.onSearch(event);
|
||||||
|
|
||||||
expect(compAsAny.updateList).toHaveBeenCalledWith(options, 'metadata', 'test');
|
expect(compAsAny.updateList).toHaveBeenCalledWith('metadata', 'test');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -20,6 +20,7 @@ import { EPersonDataService } from '../../../../core/eperson/eperson-data.servic
|
|||||||
import { GroupDataService } from '../../../../core/eperson/group-data.service';
|
import { GroupDataService } from '../../../../core/eperson/group-data.service';
|
||||||
import { fadeInOut } from '../../../animations/fade';
|
import { fadeInOut } from '../../../animations/fade';
|
||||||
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
|
import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
export interface SearchEvent {
|
export interface SearchEvent {
|
||||||
scope: string;
|
scope: string;
|
||||||
@@ -93,13 +94,16 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
private subs: Subscription[] = [];
|
private subs: Subscription[] = [];
|
||||||
|
|
||||||
|
private pageConfigSub: Subscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize instance variables and inject the properly DataService
|
* Initialize instance variables and inject the properly DataService
|
||||||
*
|
*
|
||||||
* @param {DSONameService} dsoNameService
|
* @param {DSONameService} dsoNameService
|
||||||
* @param {Injector} parentInjector
|
* @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: [],
|
providers: [],
|
||||||
parent: this.parentInjector
|
parent: this.parentInjector
|
||||||
}).get(provider);
|
}).get(provider);
|
||||||
this.paginationOptions.id = uniqueId('eperson-group-list-pagination');
|
this.paginationOptions.id = uniqueId('egl');
|
||||||
this.paginationOptions.pageSize = 5;
|
this.paginationOptions.pageSize = 5;
|
||||||
|
|
||||||
if (this.initSelected) {
|
if (this.initSelected) {
|
||||||
this.entrySelectedId.next(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
|
* Method called on search
|
||||||
@@ -165,17 +162,22 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy {
|
|||||||
onSearch(searchEvent: SearchEvent) {
|
onSearch(searchEvent: SearchEvent) {
|
||||||
this.currentSearchQuery = searchEvent.query;
|
this.currentSearchQuery = searchEvent.query;
|
||||||
this.currentSearchScope = searchEvent.scope;
|
this.currentSearchScope = searchEvent.scope;
|
||||||
this.paginationOptions.currentPage = 1;
|
this.paginationService.resetPage(this.paginationOptions.id);
|
||||||
this.updateList(this.paginationOptions, this.currentSearchScope, this.currentSearchQuery);
|
this.updateList(this.currentSearchScope, this.currentSearchQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a paginate list of eperson or group
|
* 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(), {
|
const options: FindListOptions = Object.assign({}, new FindListOptions(), {
|
||||||
elementsPerPage: config.pageSize,
|
elementsPerPage: paginationOptions.pageSize,
|
||||||
currentPage: config.currentPage
|
currentPage: paginationOptions.currentPage
|
||||||
});
|
});
|
||||||
|
|
||||||
const search$: Observable<RemoteData<PaginatedList<DSpaceObject>>> = this.isListOfEPerson ?
|
const search$: Observable<RemoteData<PaginatedList<DSpaceObject>>> = this.isListOfEPerson ?
|
||||||
@@ -184,9 +186,12 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.subs.push(search$.pipe(getFirstCompletedRemoteData())
|
this.subs.push(search$.pipe(getFirstCompletedRemoteData())
|
||||||
.subscribe((list: RemoteData<PaginatedList<DSpaceObject>>) => {
|
.subscribe((list: RemoteData<PaginatedList<DSpaceObject>>) => {
|
||||||
this.list$.next(list);
|
if (hasValue(this.list$)) {
|
||||||
|
this.list$.next(list);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,6 +202,8 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy {
|
|||||||
this.subs
|
this.subs
|
||||||
.filter((subscription) => hasValue(subscription))
|
.filter((subscription) => hasValue(subscription))
|
||||||
.forEach((subscription) => subscription.unsubscribe());
|
.forEach((subscription) => subscription.unsubscribe());
|
||||||
|
this.paginationService.clearPagination(this.paginationOptions.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,13 @@ import { Community } from '../../core/shared/community.model';
|
|||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||||
import { SearchService } from '../../core/shared/search/search.service';
|
import { SearchService } from '../../core/shared/search/search.service';
|
||||||
|
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../core/data/request.models';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
||||||
|
import { PaginationServiceStub } from '../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SearchFormComponent', () => {
|
describe('SearchFormComponent', () => {
|
||||||
let comp: SearchFormComponent;
|
let comp: SearchFormComponent;
|
||||||
@@ -15,6 +22,10 @@ describe('SearchFormComponent', () => {
|
|||||||
let de: DebugElement;
|
let de: DebugElement;
|
||||||
let el: HTMLElement;
|
let el: HTMLElement;
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
|
const searchConfigService = {paginationID: 'test-id'};
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [FormsModule, RouterTestingModule, TranslateModule.forRoot()],
|
imports: [FormsModule, RouterTestingModule, TranslateModule.forRoot()],
|
||||||
@@ -22,7 +33,9 @@ describe('SearchFormComponent', () => {
|
|||||||
{
|
{
|
||||||
provide: SearchService,
|
provide: SearchService,
|
||||||
useValue: {}
|
useValue: {}
|
||||||
}
|
},
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
|
{ provide: SearchConfigurationService, useValue: searchConfigService }
|
||||||
],
|
],
|
||||||
declarations: [SearchFormComponent]
|
declarations: [SearchFormComponent]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
@@ -4,6 +4,8 @@ import { Router } from '@angular/router';
|
|||||||
import { isNotEmpty } from '../empty.util';
|
import { isNotEmpty } from '../empty.util';
|
||||||
import { SearchService } from '../../core/shared/search/search.service';
|
import { SearchService } from '../../core/shared/search/search.service';
|
||||||
import { currentPath } from '../utils/route.utils';
|
import { currentPath } from '../utils/route.utils';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders a simple item page.
|
* This component renders a simple item page.
|
||||||
@@ -64,7 +66,10 @@ export class SearchFormComponent {
|
|||||||
*/
|
*/
|
||||||
@Output() submitSearch = new EventEmitter<any>();
|
@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
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,10 +94,15 @@ export class SearchFormComponent {
|
|||||||
* @param data Updated parameters
|
* @param data Updated parameters
|
||||||
*/
|
*/
|
||||||
updateSearch(data: any) {
|
updateSearch(data: any) {
|
||||||
this.router.navigate(this.getSearchLinkParts(), {
|
const queryParams = Object.assign({}, data);
|
||||||
queryParams: Object.assign({}, { page: 1 }, data),
|
const pageParam = this.paginationService.getPageParam(this.searchConfig.paginationID);
|
||||||
|
queryParams[pageParam] = 1;
|
||||||
|
|
||||||
|
this.router.navigate(this.getSearchLinkParts(), {
|
||||||
|
queryParams: queryParams,
|
||||||
queryParamsHandling: 'merge'
|
queryParamsHandling: 'merge'
|
||||||
});
|
});
|
||||||
|
this.paginationService.updateRouteWithUrl(this.searchConfig.paginationID, this.getSearchLinkParts(), { page: 1 }, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -15,6 +15,11 @@ import { FacetValue } from '../../../../facet-value.model';
|
|||||||
import { FilterType } from '../../../../filter-type.model';
|
import { FilterType } from '../../../../filter-type.model';
|
||||||
import { SearchFilterConfig } from '../../../../search-filter-config.model';
|
import { SearchFilterConfig } from '../../../../search-filter-config.model';
|
||||||
import { SearchFacetOptionComponent } from './search-facet-option.component';
|
import { SearchFacetOptionComponent } from './search-facet-option.component';
|
||||||
|
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SearchFacetOptionComponent', () => {
|
describe('SearchFacetOptionComponent', () => {
|
||||||
let comp: SearchFacetOptionComponent;
|
let comp: SearchFacetOptionComponent;
|
||||||
@@ -81,6 +86,8 @@ describe('SearchFacetOptionComponent', () => {
|
|||||||
let router;
|
let router;
|
||||||
const page = observableOf(0);
|
const page = observableOf(0);
|
||||||
|
|
||||||
|
const pagination = Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 });
|
||||||
|
const paginationService = new PaginationServiceStub(pagination);
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
||||||
@@ -88,8 +95,10 @@ describe('SearchFacetOptionComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{
|
{
|
||||||
provide: SearchConfigurationService, useValue: {
|
provide: SearchConfigurationService, useValue: {
|
||||||
|
paginationID: 'page-id',
|
||||||
searchOptions: observableOf({})
|
searchOptions: observableOf({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -131,7 +140,7 @@ describe('SearchFacetOptionComponent', () => {
|
|||||||
(comp as any).updateAddParams(selectedValues);
|
(comp as any).updateAddParams(selectedValues);
|
||||||
expect(comp.addQueryParams).toEqual({
|
expect(comp.addQueryParams).toEqual({
|
||||||
[mockFilterConfig.paramName]: [`${value1},${operator}`, value.value + ',equals'],
|
[mockFilterConfig.paramName]: [`${value1},${operator}`, value.value + ',equals'],
|
||||||
page: 1
|
['page-id.page']: 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -146,7 +155,7 @@ describe('SearchFacetOptionComponent', () => {
|
|||||||
(comp as any).updateAddParams(selectedValues);
|
(comp as any).updateAddParams(selectedValues);
|
||||||
expect(comp.addQueryParams).toEqual({
|
expect(comp.addQueryParams).toEqual({
|
||||||
[mockAuthorityFilterConfig.paramName]: [value1 + ',equals', `${value2},${operator}`],
|
[mockAuthorityFilterConfig.paramName]: [value1 + ',equals', `${value2},${operator}`],
|
||||||
page: 1
|
['page-id.page']: 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -10,6 +10,7 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
|
|||||||
import { hasValue } from '../../../../../empty.util';
|
import { hasValue } from '../../../../../empty.util';
|
||||||
import { currentPath } from '../../../../../utils/route.utils';
|
import { currentPath } from '../../../../../utils/route.utils';
|
||||||
import { getFacetValueForType } from '../../../../search.utils';
|
import { getFacetValueForType } from '../../../../search.utils';
|
||||||
|
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-search-facet-option',
|
selector: 'ds-search-facet-option',
|
||||||
@@ -60,10 +61,13 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
sub: Subscription;
|
sub: Subscription;
|
||||||
|
|
||||||
|
paginationId: string;
|
||||||
|
|
||||||
constructor(protected searchService: SearchService,
|
constructor(protected searchService: SearchService,
|
||||||
protected filterService: SearchFilterService,
|
protected filterService: SearchFilterService,
|
||||||
protected searchConfigService: SearchConfigurationService,
|
protected searchConfigService: SearchConfigurationService,
|
||||||
protected router: Router
|
protected router: Router,
|
||||||
|
protected paginationService: PaginationService
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +75,7 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy {
|
|||||||
* Initializes all observable instance variables and starts listening to them
|
* Initializes all observable instance variables and starts listening to them
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.paginationId = this.searchConfigService.paginationID;
|
||||||
this.searchLink = this.getSearchLink();
|
this.searchLink = this.getSearchLink();
|
||||||
this.isVisible = this.isChecked().pipe(map((checked: boolean) => !checked));
|
this.isVisible = this.isChecked().pipe(map((checked: boolean) => !checked));
|
||||||
this.sub = observableCombineLatest(this.selectedValues$, this.searchConfigService.searchOptions)
|
this.sub = observableCombineLatest(this.selectedValues$, this.searchConfigService.searchOptions)
|
||||||
@@ -101,9 +106,10 @@ export class SearchFacetOptionComponent implements OnInit, OnDestroy {
|
|||||||
* @param {string[]} selectedValues The values that are currently selected for this filter
|
* @param {string[]} selectedValues The values that are currently selected for this filter
|
||||||
*/
|
*/
|
||||||
private updateAddParams(selectedValues: FacetValue[]): void {
|
private updateAddParams(selectedValues: FacetValue[]): void {
|
||||||
|
const page = this.paginationService.getPageParam(this.searchConfigService.paginationID);
|
||||||
this.addQueryParams = {
|
this.addQueryParams = {
|
||||||
[this.filterConfig.paramName]: [...selectedValues.map((facetValue: FacetValue) => getFacetValueForType(facetValue, this.filterConfig)), this.getFacetValue()],
|
[this.filterConfig.paramName]: [...selectedValues.map((facetValue: FacetValue) => getFacetValueForType(facetValue, this.filterConfig)), this.getFacetValue()],
|
||||||
page: 1
|
[page]: 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,11 @@ import {
|
|||||||
RANGE_FILTER_MAX_SUFFIX,
|
RANGE_FILTER_MAX_SUFFIX,
|
||||||
RANGE_FILTER_MIN_SUFFIX
|
RANGE_FILTER_MIN_SUFFIX
|
||||||
} from '../../search-range-filter/search-range-filter.component';
|
} from '../../search-range-filter/search-range-filter.component';
|
||||||
|
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SearchFacetRangeOptionComponent', () => {
|
describe('SearchFacetRangeOptionComponent', () => {
|
||||||
let comp: SearchFacetRangeOptionComponent;
|
let comp: SearchFacetRangeOptionComponent;
|
||||||
@@ -54,6 +59,9 @@ describe('SearchFacetRangeOptionComponent', () => {
|
|||||||
let router;
|
let router;
|
||||||
const page = observableOf(0);
|
const page = observableOf(0);
|
||||||
|
|
||||||
|
const pagination = Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 });
|
||||||
|
const paginationService = new PaginationServiceStub(pagination);
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
||||||
@@ -61,9 +69,11 @@ describe('SearchFacetRangeOptionComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{
|
{
|
||||||
provide: SearchConfigurationService, useValue: {
|
provide: SearchConfigurationService, useValue: {
|
||||||
searchOptions: observableOf({})
|
searchOptions: observableOf({}),
|
||||||
|
paginationId: 'page-id'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -116,7 +126,7 @@ describe('SearchFacetRangeOptionComponent', () => {
|
|||||||
expect(comp.changeQueryParams).toEqual({
|
expect(comp.changeQueryParams).toEqual({
|
||||||
[mockFilterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: ['50'],
|
[mockFilterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: ['50'],
|
||||||
[mockFilterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: ['60'],
|
[mockFilterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: ['60'],
|
||||||
page: 1
|
['page-id.page']: 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -13,6 +13,7 @@ import {
|
|||||||
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
||||||
import { hasValue } from '../../../../../empty.util';
|
import { hasValue } from '../../../../../empty.util';
|
||||||
import { currentPath } from '../../../../../utils/route.utils';
|
import { currentPath } from '../../../../../utils/route.utils';
|
||||||
|
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
const rangeDelimiter = '-';
|
const rangeDelimiter = '-';
|
||||||
|
|
||||||
@@ -65,7 +66,8 @@ export class SearchFacetRangeOptionComponent implements OnInit, OnDestroy {
|
|||||||
constructor(protected searchService: SearchService,
|
constructor(protected searchService: SearchService,
|
||||||
protected filterService: SearchFilterService,
|
protected filterService: SearchFilterService,
|
||||||
protected searchConfigService: SearchConfigurationService,
|
protected searchConfigService: SearchConfigurationService,
|
||||||
protected router: Router
|
protected router: Router,
|
||||||
|
protected paginationService: PaginationService
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,10 +106,11 @@ export class SearchFacetRangeOptionComponent implements OnInit, OnDestroy {
|
|||||||
const parts = this.filterValue.value.split(rangeDelimiter);
|
const parts = this.filterValue.value.split(rangeDelimiter);
|
||||||
const min = parts.length > 1 ? parts[0].trim() : this.filterValue.value;
|
const min = parts.length > 1 ? parts[0].trim() : this.filterValue.value;
|
||||||
const max = parts.length > 1 ? parts[1].trim() : this.filterValue.value;
|
const max = parts.length > 1 ? parts[1].trim() : this.filterValue.value;
|
||||||
|
const page = this.paginationService.getPageParam(this.searchConfigService.paginationID);
|
||||||
this.changeQueryParams = {
|
this.changeQueryParams = {
|
||||||
[this.filterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: [min],
|
[this.filterConfig.paramName + RANGE_FILTER_MIN_SUFFIX]: [min],
|
||||||
[this.filterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: [max],
|
[this.filterConfig.paramName + RANGE_FILTER_MAX_SUFFIX]: [max],
|
||||||
page: 1
|
[page]: 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,6 +14,11 @@ import { FacetValue } from '../../../../facet-value.model';
|
|||||||
import { FilterType } from '../../../../filter-type.model';
|
import { FilterType } from '../../../../filter-type.model';
|
||||||
import { SearchFilterConfig } from '../../../../search-filter-config.model';
|
import { SearchFilterConfig } from '../../../../search-filter-config.model';
|
||||||
import { SearchFacetSelectedOptionComponent } from './search-facet-selected-option.component';
|
import { SearchFacetSelectedOptionComponent } from './search-facet-selected-option.component';
|
||||||
|
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SearchFacetSelectedOptionComponent', () => {
|
describe('SearchFacetSelectedOptionComponent', () => {
|
||||||
let comp: SearchFacetSelectedOptionComponent;
|
let comp: SearchFacetSelectedOptionComponent;
|
||||||
@@ -106,6 +111,9 @@ describe('SearchFacetSelectedOptionComponent', () => {
|
|||||||
let router;
|
let router;
|
||||||
const page = observableOf(0);
|
const page = observableOf(0);
|
||||||
|
|
||||||
|
const pagination = Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 });
|
||||||
|
const paginationService = new PaginationServiceStub(pagination);
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
||||||
@@ -113,6 +121,7 @@ describe('SearchFacetSelectedOptionComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{
|
{
|
||||||
provide: SearchConfigurationService, useValue: {
|
provide: SearchConfigurationService, useValue: {
|
||||||
searchOptions: observableOf({})
|
searchOptions: observableOf({})
|
||||||
@@ -156,7 +165,7 @@ describe('SearchFacetSelectedOptionComponent', () => {
|
|||||||
(comp as any).updateRemoveParams(selectedValues);
|
(comp as any).updateRemoveParams(selectedValues);
|
||||||
expect(comp.removeQueryParams).toEqual({
|
expect(comp.removeQueryParams).toEqual({
|
||||||
[mockFilterConfig.paramName]: [value1],
|
[mockFilterConfig.paramName]: [value1],
|
||||||
page: 1
|
['page-id.page']: 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -172,7 +181,7 @@ describe('SearchFacetSelectedOptionComponent', () => {
|
|||||||
(comp as any).updateRemoveParams(selectedAuthorityValues);
|
(comp as any).updateRemoveParams(selectedAuthorityValues);
|
||||||
expect(comp.removeQueryParams).toEqual({
|
expect(comp.removeQueryParams).toEqual({
|
||||||
[mockAuthorityFilterConfig.paramName]: [`${value1},${operator}`],
|
[mockAuthorityFilterConfig.paramName]: [`${value1},${operator}`],
|
||||||
page: 1
|
['page-id.page']: 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -9,6 +9,7 @@ import { SearchConfigurationService } from '../../../../../../core/shared/search
|
|||||||
import { FacetValue } from '../../../../facet-value.model';
|
import { FacetValue } from '../../../../facet-value.model';
|
||||||
import { currentPath } from '../../../../../utils/route.utils';
|
import { currentPath } from '../../../../../utils/route.utils';
|
||||||
import { getFacetValueForType } from '../../../../search.utils';
|
import { getFacetValueForType } from '../../../../search.utils';
|
||||||
|
import { PaginationService } from '../../../../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-search-facet-selected-option',
|
selector: 'ds-search-facet-selected-option',
|
||||||
@@ -58,7 +59,8 @@ export class SearchFacetSelectedOptionComponent implements OnInit, OnDestroy {
|
|||||||
constructor(protected searchService: SearchService,
|
constructor(protected searchService: SearchService,
|
||||||
protected filterService: SearchFilterService,
|
protected filterService: SearchFilterService,
|
||||||
protected searchConfigService: SearchConfigurationService,
|
protected searchConfigService: SearchConfigurationService,
|
||||||
protected router: Router
|
protected router: Router,
|
||||||
|
protected paginationService: PaginationService
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,14 +90,14 @@ export class SearchFacetSelectedOptionComponent implements OnInit, OnDestroy {
|
|||||||
* @param {string[]} selectedValues The values that are currently selected for this filter
|
* @param {string[]} selectedValues The values that are currently selected for this filter
|
||||||
*/
|
*/
|
||||||
private updateRemoveParams(selectedValues: FacetValue[]): void {
|
private updateRemoveParams(selectedValues: FacetValue[]): void {
|
||||||
|
const page = this.paginationService.getPageParam(this.searchConfigService.paginationID);
|
||||||
this.removeQueryParams = {
|
this.removeQueryParams = {
|
||||||
[this.filterConfig.paramName]: selectedValues
|
[this.filterConfig.paramName]: selectedValues
|
||||||
.filter((facetValue: FacetValue) => facetValue.label !== this.selectedValue.label)
|
.filter((facetValue: FacetValue) => facetValue.label !== this.selectedValue.label)
|
||||||
.map((facetValue: FacetValue) => this.getFacetValue(facetValue)),
|
.map((facetValue: FacetValue) => this.getFacetValue(facetValue)),
|
||||||
page: 1
|
[page]: 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO to review after https://github.com/DSpace/dspace-angular/issues/368 is resolved
|
* TODO to review after https://github.com/DSpace/dspace-angular/issues/368 is resolved
|
||||||
* Retrieve facet value related to facet type
|
* Retrieve facet value related to facet type
|
||||||
|
@@ -11,6 +11,12 @@ import { SEARCH_CONFIG_SERVICE } from '../../../../+my-dspace-page/my-dspace-pag
|
|||||||
import { SearchServiceStub } from '../../../testing/search-service.stub';
|
import { SearchServiceStub } from '../../../testing/search-service.stub';
|
||||||
import { SearchConfigurationServiceStub } from '../../../testing/search-configuration-service.stub';
|
import { SearchConfigurationServiceStub } from '../../../testing/search-configuration-service.stub';
|
||||||
import { SearchService } from '../../../../core/shared/search/search.service';
|
import { SearchService } from '../../../../core/shared/search/search.service';
|
||||||
|
import { PaginationComponentOptions } from '../../../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
|
||||||
|
import { PaginationServiceStub } from '../../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SearchLabelComponent', () => {
|
describe('SearchLabelComponent', () => {
|
||||||
let comp: SearchLabelComponent;
|
let comp: SearchLabelComponent;
|
||||||
@@ -33,6 +39,9 @@ describe('SearchLabelComponent', () => {
|
|||||||
filter2
|
filter2
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const pagination = Object.assign(new PaginationComponentOptions(), { id: 'page-id', currentPage: 1, pageSize: 20 });
|
||||||
|
const paginationService = new PaginationServiceStub(pagination);
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule],
|
||||||
@@ -40,6 +49,8 @@ describe('SearchLabelComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||||
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() },
|
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() },
|
||||||
|
{ provide: SearchConfigurationService, useValue: new SearchConfigurationServiceStub() },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: Router, useValue: {} }
|
{ provide: Router, useValue: {} }
|
||||||
// { provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => observableOf({})} }
|
// { provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => observableOf({})} }
|
||||||
],
|
],
|
||||||
|
@@ -5,6 +5,8 @@ import { map } from 'rxjs/operators';
|
|||||||
import { hasValue, isNotEmpty } from '../../../empty.util';
|
import { hasValue, isNotEmpty } from '../../../empty.util';
|
||||||
import { SearchService } from '../../../../core/shared/search/search.service';
|
import { SearchService } from '../../../../core/shared/search/search.service';
|
||||||
import { currentPath } from '../../../utils/route.utils';
|
import { currentPath } from '../../../utils/route.utils';
|
||||||
|
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||||
|
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-search-label',
|
selector: 'ds-search-label',
|
||||||
@@ -32,6 +34,8 @@ export class SearchLabelComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private searchService: SearchService,
|
private searchService: SearchService,
|
||||||
|
private paginationService: PaginationService,
|
||||||
|
private searchConfigurationService: SearchConfigurationService,
|
||||||
private router: Router) {
|
private router: Router) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,9 +54,10 @@ export class SearchLabelComponent implements OnInit {
|
|||||||
map((filters) => {
|
map((filters) => {
|
||||||
const field: string = Object.keys(filters).find((f) => f === this.key);
|
const field: string = Object.keys(filters).find((f) => f === this.key);
|
||||||
const newValues = hasValue(filters[field]) ? filters[field].filter((v) => v !== this.value) : null;
|
const newValues = hasValue(filters[field]) ? filters[field].filter((v) => v !== this.value) : null;
|
||||||
|
const page = this.paginationService.getPageParam(this.searchConfigurationService.paginationID);
|
||||||
return {
|
return {
|
||||||
[field]: isNotEmpty(newValues) ? newValues : null,
|
[field]: isNotEmpty(newValues) ? newValues : null,
|
||||||
page: 1
|
[page]: 1
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@@ -15,6 +15,8 @@ import { VarDirective } from '../../utils/var.directive';
|
|||||||
import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.component';
|
import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.component';
|
||||||
import { SidebarService } from '../../sidebar/sidebar.service';
|
import { SidebarService } from '../../sidebar/sidebar.service';
|
||||||
import { SidebarServiceStub } from '../../testing/sidebar-service.stub';
|
import { SidebarServiceStub } from '../../testing/sidebar-service.stub';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('SearchSettingsComponent', () => {
|
describe('SearchSettingsComponent', () => {
|
||||||
|
|
||||||
@@ -31,6 +33,8 @@ describe('SearchSettingsComponent', () => {
|
|||||||
let scopeParam;
|
let scopeParam;
|
||||||
let paginatedSearchOptions;
|
let paginatedSearchOptions;
|
||||||
|
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
let activatedRouteStub;
|
let activatedRouteStub;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
@@ -61,6 +65,8 @@ describe('SearchSettingsComponent', () => {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub(pagination, sort);
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
|
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
|
||||||
declarations: [SearchSettingsComponent, EnumKeysPipe, VarDirective],
|
declarations: [SearchSettingsComponent, EnumKeysPipe, VarDirective],
|
||||||
@@ -76,6 +82,10 @@ describe('SearchSettingsComponent', () => {
|
|||||||
provide: SearchFilterService,
|
provide: SearchFilterService,
|
||||||
useValue: {},
|
useValue: {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: PaginationService,
|
||||||
|
useValue: paginationService,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: SEARCH_CONFIG_SERVICE,
|
provide: SEARCH_CONFIG_SERVICE,
|
||||||
useValue: {
|
useValue: {
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
import { Component, Inject, Input } from '@angular/core';
|
import { Component, Inject, Input } from '@angular/core';
|
||||||
import { SearchService } from '../../../core/shared/search/search.service';
|
import { SearchService } from '../../../core/shared/search/search.service';
|
||||||
import { SortOptions } from '../../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../paginated-search-options.model';
|
||||||
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
|
||||||
import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.component';
|
import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.component';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-search-settings',
|
selector: 'ds-search-settings',
|
||||||
@@ -30,6 +31,7 @@ export class SearchSettingsComponent {
|
|||||||
constructor(private service: SearchService,
|
constructor(private service: SearchService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private paginationService: PaginationService,
|
||||||
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService) {
|
@Inject(SEARCH_CONFIG_SERVICE) public searchConfigurationService: SearchConfigurationService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,14 +41,10 @@ export class SearchSettingsComponent {
|
|||||||
*/
|
*/
|
||||||
reloadOrder(event: Event) {
|
reloadOrder(event: Event) {
|
||||||
const values = (event.target as HTMLInputElement).value.split(',');
|
const values = (event.target as HTMLInputElement).value.split(',');
|
||||||
const navigationExtras: NavigationExtras = {
|
this.paginationService.updateRoute(this.searchConfigurationService.paginationID, {
|
||||||
queryParams: {
|
sortField: values[0],
|
||||||
sortDirection: values[1],
|
sortDirection: values[1] as SortDirection,
|
||||||
sortField: values[0],
|
page: 1
|
||||||
page: 1
|
});
|
||||||
},
|
|
||||||
queryParamsHandling: 'merge'
|
|
||||||
};
|
|
||||||
this.router.navigate([], navigationExtras);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,12 +11,18 @@ import { StartsWithDateComponent } from './starts-with-date.component';
|
|||||||
import { ActivatedRouteStub } from '../../testing/active-router.stub';
|
import { ActivatedRouteStub } from '../../testing/active-router.stub';
|
||||||
import { EnumKeysPipe } from '../../utils/enum-keys-pipe';
|
import { EnumKeysPipe } from '../../utils/enum-keys-pipe';
|
||||||
import { RouterStub } from '../../testing/router.stub';
|
import { RouterStub } from '../../testing/router.stub';
|
||||||
|
import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('StartsWithDateComponent', () => {
|
describe('StartsWithDateComponent', () => {
|
||||||
let comp: StartsWithDateComponent;
|
let comp: StartsWithDateComponent;
|
||||||
let fixture: ComponentFixture<StartsWithDateComponent>;
|
let fixture: ComponentFixture<StartsWithDateComponent>;
|
||||||
let route: ActivatedRoute;
|
let route: ActivatedRoute;
|
||||||
let router: Router;
|
let router: Router;
|
||||||
|
let paginationService;
|
||||||
|
|
||||||
const options = [2019, 2018, 2017, 2016, 2015];
|
const options = [2019, 2018, 2017, 2016, 2015];
|
||||||
|
|
||||||
@@ -25,13 +31,17 @@ describe('StartsWithDateComponent', () => {
|
|||||||
queryParams: observableOf({})
|
queryParams: observableOf({})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
declarations: [StartsWithDateComponent, EnumKeysPipe],
|
declarations: [StartsWithDateComponent, EnumKeysPipe],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: 'startsWithOptions', useValue: options },
|
{ provide: 'startsWithOptions', useValue: options },
|
||||||
|
{ provide: 'paginationId', useValue: 'page-id' },
|
||||||
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
{ provide: ActivatedRoute, useValue: activatedRouteStub },
|
||||||
|
{ provide: PaginationService, useValue: paginationService },
|
||||||
{ provide: Router, useValue: new RouterStub() }
|
{ provide: Router, useValue: new RouterStub() }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -4,6 +4,7 @@ import { ActivatedRoute, Router } from '@angular/router';
|
|||||||
import { renderStartsWithFor, StartsWithType } from '../starts-with-decorator';
|
import { renderStartsWithFor, StartsWithType } from '../starts-with-decorator';
|
||||||
import { StartsWithAbstractComponent } from '../starts-with-abstract.component';
|
import { StartsWithAbstractComponent } from '../starts-with-abstract.component';
|
||||||
import { hasValue } from '../../empty.util';
|
import { hasValue } from '../../empty.util';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A switchable component rendering StartsWith options for the type "Date".
|
* A switchable component rendering StartsWith options for the type "Date".
|
||||||
@@ -33,9 +34,11 @@ export class StartsWithDateComponent extends StartsWithAbstractComponent {
|
|||||||
startsWithYear: number;
|
startsWithYear: number;
|
||||||
|
|
||||||
public constructor(@Inject('startsWithOptions') public startsWithOptions: any[],
|
public constructor(@Inject('startsWithOptions') public startsWithOptions: any[],
|
||||||
|
@Inject('paginationId') public paginationId: string,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
protected router: Router) {
|
protected router: Router) {
|
||||||
super(startsWithOptions, route, router);
|
super(startsWithOptions, paginationId, paginationService, route, router);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
@@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router';
|
|||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { hasValue } from '../empty.util';
|
import { hasValue } from '../empty.util';
|
||||||
|
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract component to render StartsWith options
|
* An abstract component to render StartsWith options
|
||||||
@@ -28,6 +29,8 @@ export abstract class StartsWithAbstractComponent implements OnInit, OnDestroy {
|
|||||||
subs: Subscription[] = [];
|
subs: Subscription[] = [];
|
||||||
|
|
||||||
public constructor(@Inject('startsWithOptions') public startsWithOptions: any[],
|
public constructor(@Inject('startsWithOptions') public startsWithOptions: any[],
|
||||||
|
@Inject('paginationId') public paginationId: string,
|
||||||
|
protected paginationService: PaginationService,
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
protected router: Router) {
|
protected router: Router) {
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,12 @@ import { EnumKeysPipe } from '../../utils/enum-keys-pipe';
|
|||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { StartsWithTextComponent } from './starts-with-text.component';
|
import { StartsWithTextComponent } from './starts-with-text.component';
|
||||||
|
import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||||
|
import { PaginationServiceStub } from '../../testing/pagination-service.stub';
|
||||||
|
|
||||||
describe('StartsWithTextComponent', () => {
|
describe('StartsWithTextComponent', () => {
|
||||||
let comp: StartsWithTextComponent;
|
let comp: StartsWithTextComponent;
|
||||||
@@ -17,12 +23,16 @@ describe('StartsWithTextComponent', () => {
|
|||||||
|
|
||||||
const options = ['0-9', 'A', 'B', 'C'];
|
const options = ['0-9', 'A', 'B', 'C'];
|
||||||
|
|
||||||
|
const paginationService = new PaginationServiceStub();
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
|
||||||
declarations: [StartsWithTextComponent, EnumKeysPipe],
|
declarations: [StartsWithTextComponent, EnumKeysPipe],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: 'startsWithOptions', useValue: options }
|
{ provide: 'startsWithOptions', useValue: options },
|
||||||
|
{ provide: 'paginationId', useValue: 'page-id' },
|
||||||
|
{ provide: PaginationService, useValue: paginationService }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
25
src/app/shared/testing/pagination-service.stub.ts
Normal file
25
src/app/shared/testing/pagination-service.stub.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../core/data/request.models';
|
||||||
|
|
||||||
|
export class PaginationServiceStub {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public pagination = Object.assign(new PaginationComponentOptions(), {currentPage: 1, pageSize: 20}),
|
||||||
|
public sort = new SortOptions('score', SortDirection.DESC),
|
||||||
|
public findlistOptions = Object.assign(new FindListOptions(), {currentPage: 1, elementsPerPage: 20}),
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentPagination = jasmine.createSpy('getCurrentPagination').and.returnValue(observableOf(this.pagination));
|
||||||
|
getCurrentSort = jasmine.createSpy('getCurrentSort').and.returnValue(observableOf(this.sort));
|
||||||
|
getFindListOptions = jasmine.createSpy('getFindListOptions').and.returnValue(observableOf(this.findlistOptions));
|
||||||
|
resetPage = jasmine.createSpy('resetPage');
|
||||||
|
updateRoute = jasmine.createSpy('updateRoute');
|
||||||
|
updateRouteWithUrl = jasmine.createSpy('updateRouteWithUrl');
|
||||||
|
clearPagination = jasmine.createSpy('clearPagination');
|
||||||
|
getRouteParameterValue = jasmine.createSpy('getRouteParameterValue').and.returnValue(observableOf(''));
|
||||||
|
getPageParam = jasmine.createSpy('getPageParam').and.returnValue(`${this.pagination.id}.page`);
|
||||||
|
|
||||||
|
}
|
@@ -2,6 +2,8 @@ import { BehaviorSubject, of as observableOf } from 'rxjs';
|
|||||||
|
|
||||||
export class SearchConfigurationServiceStub {
|
export class SearchConfigurationServiceStub {
|
||||||
|
|
||||||
|
public paginationID = 'test-id';
|
||||||
|
|
||||||
private searchOptions: BehaviorSubject<any> = new BehaviorSubject<any>({});
|
private searchOptions: BehaviorSubject<any> = new BehaviorSubject<any>({});
|
||||||
private paginatedSearchOptions: BehaviorSubject<any> = new BehaviorSubject<any>({});
|
private paginatedSearchOptions: BehaviorSubject<any> = new BehaviorSubject<any>({});
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<div ng2FileDrop
|
<div ng2FileDrop
|
||||||
*ngIf="enableDragOverDocument"
|
*ngIf="(isOverDocumentDropZone | async)"
|
||||||
class="ds-document-drop-zone position-fixed h-100 w-100"
|
class="ds-document-drop-zone position-fixed h-100 w-100"
|
||||||
[class.ds-document-drop-zone-active]="(isOverDocumentDropZone | async)"
|
[class.ds-document-drop-zone-active]="(isOverDocumentDropZone | async)"
|
||||||
[uploader]="uploader"
|
[uploader]="uploader"
|
||||||
|
@@ -1,29 +1,16 @@
|
|||||||
import {
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostListener, Input, Output, ViewEncapsulation, } from '@angular/core';
|
||||||
ChangeDetectionStrategy,
|
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
|
||||||
EventEmitter,
|
|
||||||
HostListener,
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
ViewEncapsulation,
|
|
||||||
} from '@angular/core';
|
|
||||||
|
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { FileUploader } from 'ng2-file-upload';
|
import { FileUploader } from 'ng2-file-upload';
|
||||||
import { uniqueId } from 'lodash';
|
import { uniqueId } from 'lodash';
|
||||||
import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
||||||
|
|
||||||
import { UploaderOptions } from './uploader-options.model';
|
import { UploaderOptions } from './uploader-options.model';
|
||||||
import { hasValue, isNotEmpty, isUndefined } from '../empty.util';
|
import { hasValue, isNotEmpty, isUndefined } from '../empty.util';
|
||||||
import { UploaderService } from './uploader.service';
|
import { UploaderService } from './uploader.service';
|
||||||
import { UploaderProperties } from './uploader-properties.model';
|
import { UploaderProperties } from './uploader-properties.model';
|
||||||
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
||||||
import {
|
import { XSRF_COOKIE, XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER } from '../../core/xsrf/xsrf.interceptor';
|
||||||
XSRF_REQUEST_HEADER,
|
|
||||||
XSRF_RESPONSE_HEADER,
|
|
||||||
XSRF_COOKIE
|
|
||||||
} from '../../core/xsrf/xsrf.interceptor';
|
|
||||||
import { CookieService } from '../../core/services/cookie.service';
|
import { CookieService } from '../../core/services/cookie.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -146,12 +133,6 @@ export class UploaderComponent {
|
|||||||
this.uploader.options.headers = [{ name: XSRF_REQUEST_HEADER, value: this.tokenExtractor.getToken() }];
|
this.uploader.options.headers = [{ name: XSRF_REQUEST_HEADER, value: this.tokenExtractor.getToken() }];
|
||||||
this.onBeforeUpload();
|
this.onBeforeUpload();
|
||||||
this.isOverDocumentDropZone = observableOf(false);
|
this.isOverDocumentDropZone = observableOf(false);
|
||||||
|
|
||||||
// Move page target to the uploader
|
|
||||||
const config: ScrollToConfigOptions = {
|
|
||||||
target: this.uploaderId
|
|
||||||
};
|
|
||||||
this.scrollToService.scrollTo(config);
|
|
||||||
};
|
};
|
||||||
if (hasValue(this.uploadProperties)) {
|
if (hasValue(this.uploadProperties)) {
|
||||||
this.uploader.onBuildItemForm = (item, form) => {
|
this.uploader.onBuildItemForm = (item, form) => {
|
||||||
|
@@ -1,35 +1,36 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div *ngIf="!(isLoading() | async)">
|
<div *ngIf="!(isLoading() | async)" class="submission-form-header mb-3 d-flex flex-wrap position-sticky">
|
||||||
<ds-submission-upload-files [submissionId]="submissionId"
|
<div *ngIf="(uploadEnabled$ | async)" class="w-100">
|
||||||
[collectionId]="collectionId"
|
<ds-submission-upload-files [submissionId]="submissionId"
|
||||||
[sectionId]="'upload'"
|
[collectionId]="collectionId"
|
||||||
[uploadFilesOptions]="uploadFilesOptions"></ds-submission-upload-files>
|
[sectionId]="'upload'"
|
||||||
<div class="clearfix"></div>
|
[uploadFilesOptions]="uploadFilesOptions"></ds-submission-upload-files>
|
||||||
</div>
|
<div class="clearfix"></div>
|
||||||
<div *ngIf="!(isLoading() | async)" class="submission-form-header mb-3 d-flex flex-wrap position-sticky">
|
</div>
|
||||||
<div class="submission-form-header-item mb-3 mb-sm-0 flex-sm-grow-1 flex-md-grow-0">
|
|
||||||
<ds-submission-form-collection [currentCollectionId]="collectionId"
|
|
||||||
[currentDefinition]="definitionId"
|
|
||||||
[submissionId]="submissionId"
|
|
||||||
(collectionChange)="onCollectionChange($event)">
|
|
||||||
</ds-submission-form-collection>
|
|
||||||
</div>
|
|
||||||
<div class="submission-form-header-item text-right">
|
|
||||||
<ds-submission-form-section-add [collectionId]="collectionId"
|
|
||||||
[submissionId]="submissionId">
|
|
||||||
</ds-submission-form-section-add>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="submission-form-content">
|
<div class="submission-form-header-item mb-3 mb-sm-0 flex-sm-grow-1 flex-md-grow-0">
|
||||||
<ds-loading *ngIf="(isLoading() | async)" message="Loading..."></ds-loading>
|
<ds-submission-form-collection [currentCollectionId]="collectionId"
|
||||||
<ng-container *ngFor="let object of (submissionSections | async)">
|
[currentDefinition]="definitionId"
|
||||||
<ds-submission-section-container [collectionId]="collectionId"
|
[submissionId]="submissionId"
|
||||||
[submissionId]="submissionId"
|
(collectionChange)="onCollectionChange($event)">
|
||||||
[sectionData]="object"></ds-submission-section-container>
|
</ds-submission-form-collection>
|
||||||
</ng-container>
|
</div>
|
||||||
</div>
|
<div class="submission-form-header-item text-right">
|
||||||
<div *ngIf="!(isLoading() | async)" class="submission-form-footer mt-3 mb-3 position-sticky">
|
<ds-submission-form-section-add [collectionId]="collectionId"
|
||||||
<ds-submission-form-footer [submissionId]="submissionId"></ds-submission-form-footer>
|
[submissionId]="submissionId">
|
||||||
</div>
|
</ds-submission-form-section-add>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="submission-form-content">
|
||||||
|
<ds-loading *ngIf="(isLoading() | async)" message="Loading..."></ds-loading>
|
||||||
|
<ng-container *ngFor="let object of (submissionSections | async)">
|
||||||
|
<ds-submission-section-container [collectionId]="collectionId"
|
||||||
|
[submissionId]="submissionId"
|
||||||
|
[sectionData]="object"></ds-submission-section-container>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!(isLoading() | async)" class="submission-form-footer mt-3 mb-3 position-sticky">
|
||||||
|
<ds-submission-form-footer [submissionId]="submissionId"></ds-submission-form-footer>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user