diff --git a/karma.conf.js b/karma.conf.js index a3b6803e6d4..24cd067fd18 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -14,7 +14,8 @@ module.exports = function (config) { require('karma-mocha-reporter'), ], client: { - clearContext: false // leave Jasmine Spec Runner output visible in browser + clearContext: false, // leave Jasmine Spec Runner output visible in browser + captureConsole: false }, coverageIstanbulReporter: { dir: require('path').join(__dirname, './coverage/dspace-angular'), diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts index e648a7f25ec..11b146b294e 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.ts @@ -3,7 +3,7 @@ import { FormBuilder } from '@angular/forms'; import { Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs'; -import { filter, map, switchMap, take } from 'rxjs/operators'; +import { map, switchMap, take } from 'rxjs/operators'; import { PaginatedList, buildPaginatedList } from '../../../core/data/paginated-list.model'; import { RemoteData } from '../../../core/data/remote-data'; import { EPersonDataService } from '../../../core/eperson/eperson-data.service'; @@ -15,8 +15,8 @@ import { EpersonDtoModel } from '../../../core/eperson/models/eperson-dto.model' import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; import { - getAllSucceededRemoteDataPayload, - getFirstCompletedRemoteData + getFirstCompletedRemoteData, + getAllSucceededRemoteData } from '../../../core/shared/operators'; import { ConfirmationModalComponent } from '../../../shared/confirmation-modal/confirmation-modal.component'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; @@ -39,7 +39,7 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { /** * A list of all the current EPeople within the repository or the result of the search */ - ePeople$: BehaviorSubject>> = new BehaviorSubject>>({} as any); + ePeople$: BehaviorSubject> = new BehaviorSubject(buildPaginatedList(new PageInfo(), [])); /** * A BehaviorSubject with the list of EpersonDtoModel objects made from the EPeople in the repository or * as the result of the search @@ -72,6 +72,11 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { currentSearchQuery: string; currentSearchScope: string; + /** + * The subscription for the search method + */ + searchSub: Subscription; + /** * List of subscriptions */ @@ -108,6 +113,29 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { this.isEPersonFormShown = true; } })); + this.subs.push(this.ePeople$.pipe( + switchMap((epeople: PaginatedList) => { + if (epeople.pageInfo.totalElements > 0) { + return combineLatest(...epeople.page.map((eperson) => { + return this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(eperson) ? eperson.self : undefined).pipe( + map((authorized) => { + const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel(); + epersonDtoModel.ableToDelete = authorized; + epersonDtoModel.eperson = eperson; + return epersonDtoModel; + }) + ); + })).pipe(map((dtos: EpersonDtoModel[]) => { + return buildPaginatedList(epeople.pageInfo, dtos); + })); + } else { + // if it's empty, simply forward the empty list + return [epeople]; + } + })).subscribe((value: PaginatedList) => { + this.ePeopleDto$.next(value); + this.pageInfoState$.next(value.pageInfo); + })); } /** @@ -138,34 +166,21 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { this.currentSearchScope = scope; this.config.currentPage = 1; } - this.subs.push(this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { + if (hasValue(this.searchSub)) { + this.searchSub.unsubscribe(); + this.subs = this.subs.filter((sub: Subscription) => sub !== this.searchSub); + } + this.searchSub = this.epersonService.searchByScope(this.currentSearchScope, this.currentSearchQuery, { currentPage: this.config.currentPage, elementsPerPage: this.config.pageSize - }).subscribe((peopleRD) => { - this.ePeople$.next(peopleRD); + }).pipe( + getAllSucceededRemoteData(), + ).subscribe((peopleRD) => { + this.ePeople$.next(peopleRD.payload); this.pageInfoState$.next(peopleRD.payload.pageInfo); } - )); - - this.subs.push(this.ePeople$.pipe( - getAllSucceededRemoteDataPayload(), - switchMap((epeople) => { - return combineLatest(...epeople.page.map((eperson) => { - return this.authorizationService.isAuthorized(FeatureID.CanDelete, hasValue(eperson) ? eperson.self : undefined).pipe( - map((authorized) => { - const epersonDtoModel: EpersonDtoModel = new EpersonDtoModel(); - epersonDtoModel.ableToDelete = authorized; - epersonDtoModel.eperson = eperson; - return epersonDtoModel; - }) - ); - })).pipe(map((dtos: EpersonDtoModel[]) => { - return buildPaginatedList(epeople.pageInfo, dtos); - })); - })).subscribe((value) => { - this.ePeopleDto$.next(value); - this.pageInfoState$.next(value.pageInfo); - })); + ); + this.subs.push(this.searchSub); } /** @@ -224,7 +239,8 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + ePerson.id + ' with code: ' + restResponse.statusCode + ' and message: ' + restResponse.errorMessage); } }); - }} + } + } }); } } @@ -261,16 +277,16 @@ export class EPeopleRegistryComponent implements OnInit, OnDestroy { } /** - * This method will ensure that the page gets reset and that the cache is cleared + * This method will set everything to stale, which will cause the lists on this page to update. */ reset() { this.epersonService.getBrowseEndpoint().pipe( - switchMap((href) => this.requestService.removeByHrefSubstring(href)), - filter((isCached) => isCached), - take(1) - ).subscribe(() => { - this.cleanupSubscribes(); - this.initialisePage(); + take(1) + ).subscribe((href: string) => { + this.requestService.setStaleByHrefSubstring(href).pipe(take(1)).subscribe(() => { + this.epersonService.cancelEditEPerson(); + this.isEPersonFormShown = false; + }); }); } } diff --git a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts index 59c019f6f62..3c284735a9a 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts +++ b/src/app/+admin/admin-access-control/epeople-registry/eperson-form/eperson-form.component.ts @@ -359,7 +359,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy { }); const response = this.epersonService.updateEPerson(editedEperson); - response.pipe(take(1)).subscribe((rd: RemoteData) => { + response.pipe(getFirstCompletedRemoteData()).subscribe((rd: RemoteData) => { if (rd.hasSucceeded) { this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.edited.success', { name: editedEperson.name })); this.submitForm.emit(editedEperson); @@ -439,10 +439,10 @@ export class EPersonFormComponent implements OnInit, OnDestroy { modalRef.componentInstance.response.pipe(take(1)).subscribe((confirm: boolean) => { if (confirm) { if (hasValue(eperson.id)) { - this.epersonService.deleteEPerson(eperson).pipe(take(1)).subscribe((restResponse: RemoteData) => { + this.epersonService.deleteEPerson(eperson).pipe(getFirstCompletedRemoteData()).subscribe((restResponse: RemoteData) => { if (restResponse.hasSucceeded) { this.notificationsService.success(this.translateService.get(this.labelPrefix + 'notification.deleted.success', { name: eperson.name })); - this.reset(); + this.submitForm.emit(); } else { this.notificationsService.error('Error occured when trying to delete EPerson with id: ' + eperson.id + ' with code: ' + restResponse.statusCode + ' and message: ' + restResponse.errorMessage); } diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts b/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts index b17807b9d37..81e95134332 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts +++ b/src/app/+admin/admin-access-control/group-registry/group-form/group-form.component.ts @@ -345,7 +345,7 @@ export class GroupFormComponent implements OnInit, OnDestroy { this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => { if (activeGroup === null) { this.groupDataService.cancelEditGroup(); - this.groupDataService.findByHref(groupSelfLink, false, followLink('subgroups'), followLink('epersons'), followLink('object')) + this.groupDataService.findByHref(groupSelfLink, false, false, followLink('subgroups'), followLink('epersons'), followLink('object')) .pipe( getFirstSucceededRemoteData(), getRemoteDataPayload()) diff --git a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html index d24bf35e2a2..0ac67aff75e 100644 --- a/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html +++ b/src/app/+admin/admin-access-control/group-registry/group-form/members-list/members-list.component.html @@ -24,10 +24,10 @@