diff --git a/src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.html b/src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.html index 44b6bfb697..a9fb368ef4 100644 --- a/src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.html +++ b/src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.html @@ -1,4 +1,4 @@ -
+

{{messagePrefix + '.create' | translate}}

diff --git a/src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.ts b/src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.ts index f04324bdc5..c072d183aa 100644 --- a/src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.ts +++ b/src/app/admin/admin-registries/metadata-schema/metadata-field-form/metadata-field-form.component.ts @@ -11,7 +11,7 @@ import { RegistryService } from '../../../../core/registry/registry.service'; import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service'; import { take } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; -import { combineLatest } from 'rxjs'; +import { Observable } from 'rxjs'; import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model'; import { MetadataField } from '../../../../core/metadata/metadata-field.model'; @@ -90,6 +90,8 @@ export class MetadataFieldFormComponent implements OnInit, OnDestroy { */ @Output() submitForm: EventEmitter = new EventEmitter(); + activeMetadataField$: Observable; + constructor(public registryService: RegistryService, private formBuilderService: FormBuilderService, private translateService: TranslateService) { @@ -99,70 +101,64 @@ export class MetadataFieldFormComponent implements OnInit, OnDestroy { * Initialize the component, setting up the necessary Models for the dynamic form */ ngOnInit() { - combineLatest([ - this.translateService.get(`${this.messagePrefix}.element`), - this.translateService.get(`${this.messagePrefix}.qualifier`), - this.translateService.get(`${this.messagePrefix}.scopenote`) - ]).subscribe(([element, qualifier, scopenote]) => { - this.element = new DynamicInputModel({ - id: 'element', - label: element, - name: 'element', - validators: { - required: null, - pattern: '^[^. ,]*$', - maxLength: 64, - }, - required: true, - errorMessages: { - pattern: 'error.validation.metadata.element.invalid-pattern', - maxLength: 'error.validation.metadata.element.max-length', - }, - }); - this.qualifier = new DynamicInputModel({ - id: 'qualifier', - label: qualifier, - name: 'qualifier', - validators: { - pattern: '^[^. ,]*$', - maxLength: 64, - }, - required: false, - errorMessages: { - pattern: 'error.validation.metadata.qualifier.invalid-pattern', - maxLength: 'error.validation.metadata.qualifier.max-length', - }, - }); - this.scopeNote = new DynamicTextAreaModel({ - id: 'scopeNote', - label: scopenote, - name: 'scopeNote', - required: false, - rows: 5, - }); - this.formModel = [ - new DynamicFormGroupModel( - { - id: 'metadatadatafieldgroup', - group:[this.element, this.qualifier, this.scopeNote] - }) - ]; - this.formGroup = this.formBuilderService.createFormGroup(this.formModel); - this.registryService.getActiveMetadataField().subscribe((field: MetadataField): void => { - if (field == null) { - this.clearFields(); - } else { - this.formGroup.patchValue({ - metadatadatafieldgroup: { - element: field.element, - qualifier: field.qualifier, - scopeNote: field.scopeNote, - }, - }); - this.element.disabled = true; - this.qualifier.disabled = true; - } - }); + this.element = new DynamicInputModel({ + id: 'element', + label: this.translateService.instant(`${this.messagePrefix}.element`), + name: 'element', + validators: { + required: null, + pattern: '^[^. ,]*$', + maxLength: 64, + }, + required: true, + errorMessages: { + pattern: 'error.validation.metadata.element.invalid-pattern', + maxLength: 'error.validation.metadata.element.max-length', + }, + }); + this.qualifier = new DynamicInputModel({ + id: 'qualifier', + label: this.translateService.instant(`${this.messagePrefix}.qualifier`), + name: 'qualifier', + validators: { + pattern: '^[^. ,]*$', + maxLength: 64, + }, + required: false, + errorMessages: { + pattern: 'error.validation.metadata.qualifier.invalid-pattern', + maxLength: 'error.validation.metadata.qualifier.max-length', + }, + }); + this.scopeNote = new DynamicTextAreaModel({ + id: 'scopeNote', + label: this.translateService.instant(`${this.messagePrefix}.scopenote`), + name: 'scopeNote', + required: false, + rows: 5, + }); + this.formModel = [ + new DynamicFormGroupModel( + { + id: 'metadatadatafieldgroup', + group:[this.element, this.qualifier, this.scopeNote] + }) + ]; + this.formGroup = this.formBuilderService.createFormGroup(this.formModel); + this.registryService.getActiveMetadataField().subscribe((field: MetadataField): void => { + if (field == null) { + this.clearFields(); + } else { + this.formGroup.patchValue({ + metadatadatafieldgroup: { + element: field.element, + qualifier: field.qualifier, + scopeNote: field.scopeNote, + }, + }); + this.element.disabled = true; + this.qualifier.disabled = true; + } }); } diff --git a/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.html b/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.html index 7f121081f2..7569ebd6e3 100644 --- a/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.html +++ b/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.html @@ -1,9 +1,9 @@
- - + + - + @@ -16,7 +16,7 @@
+ *ngFor="let bitstream of (bundleBitstreamsMap.get(bundle.id).bitstreams | async)"> diff --git a/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.spec.ts b/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.spec.ts index 5d2afbaf4c..3269a91118 100644 --- a/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.spec.ts +++ b/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.spec.ts @@ -147,17 +147,9 @@ describe('ItemAuthorizationsComponent test suite', () => { })); }); - it('should get the item UUID', () => { - - expect(comp.getItemUUID()).toBeObservable(cold('(a|)', { - a: item.id - })); - - }); - it('should get the item\'s bundle', () => { - expect(comp.getItemBundles()).toBeObservable(cold('a', { + expect(comp.bundles$).toBeObservable(cold('a', { a: bundles })); diff --git a/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.ts b/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.ts index 635cf455b5..cd82f5182f 100644 --- a/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.ts +++ b/src/app/item-page/edit-item-page/item-authorizations/item-authorizations.component.ts @@ -4,7 +4,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { BehaviorSubject, Observable, of as observableOf, Subscription } from 'rxjs'; -import { catchError, filter, first, map, mergeMap, take } from 'rxjs/operators'; +import { catchError, filter, map, mergeMap, take } from 'rxjs/operators'; import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model'; import { @@ -17,6 +17,7 @@ import { LinkService } from '../../../core/cache/builders/link.service'; import { Bundle } from '../../../core/shared/bundle.model'; import { hasValue, isNotEmpty } from '../../../shared/empty.util'; import { Bitstream } from '../../../core/shared/bitstream.model'; +import { AlertType } from '../../../shared/alert/alert-type'; /** * Interface for a bundle's bitstream map entry @@ -52,7 +53,7 @@ export class ItemAuthorizationsComponent implements OnInit, OnDestroy { * The target editing item * @type {Observable} */ - private item$: Observable; + item$: Observable; /** * Array to track all subscriptions and unsubscribe them onDestroy @@ -91,16 +92,13 @@ export class ItemAuthorizationsComponent implements OnInit, OnDestroy { */ private bitstreamPageSize = 4; - /** - * Initialize instance variables - * - * @param {LinkService} linkService - * @param {ActivatedRoute} route - * @param nameService - */ + itemName$: Observable; + + readonly AlertType = AlertType; + constructor( - private linkService: LinkService, - private route: ActivatedRoute, + protected linkService: LinkService, + protected route: ActivatedRoute, public nameService: DSONameService ) { } @@ -109,37 +107,19 @@ export class ItemAuthorizationsComponent implements OnInit, OnDestroy { * Initialize the component, setting up the bundle and bitstream within the item */ ngOnInit(): void { - this.getBundlesPerItem(); + this.getBundlesPerItem(); + this.itemName$ = this.getItemName(); } /** - * Return the item's UUID + * Return the item's name */ - getItemUUID(): Observable { - return this.item$.pipe( - map((item: Item) => item.id), - first((UUID: string) => isNotEmpty(UUID)) - ); - } - - /** - * Return the item's name - */ - getItemName(): Observable { + private getItemName(): Observable { return this.item$.pipe( map((item: Item) => this.nameService.getName(item)) ); } - /** - * Return all item's bundles - * - * @return an observable that emits all item's bundles - */ - getItemBundles(): Observable { - return this.bundles$.asObservable(); - } - /** * Get all bundles per item * and all the bitstreams per bundle diff --git a/src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.html b/src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.html index c37b54aab3..0ba2c87011 100644 --- a/src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.html +++ b/src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.html @@ -1,18 +1,18 @@

{{'person.orcid.registry.auth' | translate}}

- +
-
+
{{ 'person.page.orcid.granted-authorizations'| translate }}
    -
  • +
  • {{getAuthorizationDescription(auth) | translate}}
@@ -25,13 +25,13 @@
{{ 'person.page.orcid.missing-authorizations'| translate }}
- + {{'person.page.orcid.no-missing-authorizations-message' | translate}} - + {{'person.page.orcid.missing-authorizations-message' | translate}}
    -
  • +
  • {{getAuthorizationDescription(auth) | translate }}
@@ -41,11 +41,11 @@
- + {{ 'person.page.orcid.remove-orcid-message' | translate}} -
+
- @@ -68,7 +68,7 @@
orcid-logo
- {{ getOrcidNotLinkedMessage() | async }} + {{ getOrcidNotLinkedMessage() }}
diff --git a/src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.ts b/src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.ts index 73b4a7b4e1..59da0d4fe6 100644 --- a/src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.ts +++ b/src/app/item-page/orcid-page/orcid-auth/orcid-auth.component.ts @@ -12,6 +12,7 @@ import { getFirstCompletedRemoteData } from '../../../core/shared/operators'; import { OrcidAuthService } from '../../../core/orcid/orcid-auth.service'; import { createFailedRemoteDataObject } from '../../../shared/remote-data.utils'; import { HttpErrorResponse } from '@angular/common/http'; +import { AlertType } from '../../../shared/alert/alert-type'; @Component({ selector: 'ds-orcid-auth', @@ -28,43 +29,49 @@ export class OrcidAuthComponent implements OnInit, OnChanges { /** * The list of exposed orcid authorization scopes for the orcid profile */ - profileAuthorizationScopes: BehaviorSubject = new BehaviorSubject([]); + profileAuthorizationScopes$: BehaviorSubject = new BehaviorSubject([]); + + hasOrcidAuthorizations$: Observable; /** * The list of all orcid authorization scopes missing in the orcid profile */ - missingAuthorizationScopes: BehaviorSubject = new BehaviorSubject([]); + missingAuthorizationScopes: BehaviorSubject = new BehaviorSubject([]); + + hasMissingOrcidAuthorizations$: Observable; /** * The list of all orcid authorization scopes available */ - orcidAuthorizationScopes: BehaviorSubject = new BehaviorSubject([]); + orcidAuthorizationScopes: BehaviorSubject = new BehaviorSubject([]); /** * A boolean representing if unlink operation is processing */ - unlinkProcessing: BehaviorSubject = new BehaviorSubject(false); + unlinkProcessing: BehaviorSubject = new BehaviorSubject(false); /** * A boolean representing if orcid profile is linked */ - private isOrcidLinked$: BehaviorSubject = new BehaviorSubject(false); + isOrcidLinked$: BehaviorSubject = new BehaviorSubject(false); /** * A boolean representing if only admin can disconnect orcid profile */ - private onlyAdminCanDisconnectProfileFromOrcid$: BehaviorSubject = new BehaviorSubject(false); + onlyAdminCanDisconnectProfileFromOrcid$: BehaviorSubject = new BehaviorSubject(false); /** * A boolean representing if owner can disconnect orcid profile */ - private ownerCanDisconnectProfileFromOrcid$: BehaviorSubject = new BehaviorSubject(false); + ownerCanDisconnectProfileFromOrcid$: BehaviorSubject = new BehaviorSubject(false); /** * An event emitted when orcid profile is unliked successfully */ @Output() unlink: EventEmitter = new EventEmitter(); + readonly AlertType = AlertType; + constructor( private orcidAuthService: OrcidAuthService, private translateService: TranslateService, @@ -78,6 +85,8 @@ export class OrcidAuthComponent implements OnInit, OnChanges { this.orcidAuthorizationScopes.next(scopes); this.initOrcidAuthSettings(); }); + this.hasOrcidAuthorizations$ = this.hasOrcidAuthorizations(); + this.hasMissingOrcidAuthorizations$ = this.hasMissingOrcidAuthorizations(); } ngOnChanges(changes: SimpleChanges): void { @@ -90,18 +99,11 @@ export class OrcidAuthComponent implements OnInit, OnChanges { * Check if the list of exposed orcid authorization scopes for the orcid profile has values */ hasOrcidAuthorizations(): Observable { - return this.profileAuthorizationScopes.asObservable().pipe( + return this.profileAuthorizationScopes$.pipe( map((scopes: string[]) => scopes.length > 0) ); } - /** - * Return the list of exposed orcid authorization scopes for the orcid profile - */ - getOrcidAuthorizations(): Observable { - return this.profileAuthorizationScopes.asObservable(); - } - /** * Check if the list of exposed orcid authorization scopes for the orcid profile has values */ @@ -111,26 +113,12 @@ export class OrcidAuthComponent implements OnInit, OnChanges { ); } - /** - * Return the list of exposed orcid authorization scopes for the orcid profile - */ - getMissingOrcidAuthorizations(): Observable { - return this.profileAuthorizationScopes.asObservable(); - } - - /** - * Return a boolean representing if orcid profile is linked - */ - isLinkedToOrcid(): Observable { - return this.isOrcidLinked$.asObservable(); - } - - getOrcidNotLinkedMessage(): Observable { + getOrcidNotLinkedMessage(): string { const orcid = this.item.firstMetadataValue('person.identifier.orcid'); if (orcid) { - return this.translateService.get('person.page.orcid.orcid-not-linked-message', { 'orcid': orcid }); + return this.translateService.instant('person.page.orcid.orcid-not-linked-message', { 'orcid': orcid }); } else { - return this.translateService.get('person.page.orcid.no-orcid-message'); + return this.translateService.instant('person.page.orcid.no-orcid-message'); } } @@ -143,13 +131,6 @@ export class OrcidAuthComponent implements OnInit, OnChanges { return 'person.page.orcid.scope.' + scope.substring(1).replace('/', '-'); } - /** - * Return a boolean representing if only admin can disconnect orcid profile - */ - onlyAdminCanDisconnectProfileFromOrcid(): Observable { - return this.onlyAdminCanDisconnectProfileFromOrcid$.asObservable(); - } - /** * Return a boolean representing if owner can disconnect orcid profile */ @@ -215,7 +196,7 @@ export class OrcidAuthComponent implements OnInit, OnChanges { } private setOrcidAuthorizationsFromItem(): void { - this.profileAuthorizationScopes.next(this.orcidAuthService.getOrcidAuthorizationScopesByItem(this.item)); + this.profileAuthorizationScopes$.next(this.orcidAuthService.getOrcidAuthorizationScopesByItem(this.item)); } } diff --git a/src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.html b/src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.html index 6ba318f7fd..9b3e470fc1 100644 --- a/src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.html +++ b/src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.html @@ -3,13 +3,13 @@

{{ 'person.orcid.registry.queue' | translate }}

- {{ 'person.page.orcid.sync-queue.empty-message' | translate}} -
@@ -22,7 +22,7 @@ - + diff --git a/src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.ts b/src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.ts index 3e88826952..7df84864c6 100644 --- a/src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.ts +++ b/src/app/item-page/orcid-page/orcid-queue/orcid-queue.component.ts @@ -47,13 +47,12 @@ export class OrcidQueueComponent implements OnInit, OnDestroy { /** * A list of orcid queue records */ - private list$: BehaviorSubject>> = new BehaviorSubject>>({} as any); + list$: BehaviorSubject>> = new BehaviorSubject>>({} as any); /** * The AlertType enumeration - * @type {AlertType} */ - AlertTypeEnum = AlertType; + readonly AlertTypeEnum = AlertType; /** * Array to track all subscriptions and unsubscribe them onDestroy @@ -99,13 +98,6 @@ export class OrcidQueueComponent implements OnInit, OnDestroy { ); } - /** - * Return the list of orcid queue records - */ - getList(): Observable>> { - return this.list$.asObservable(); - } - /** * Return the icon class for the queue object type * diff --git a/src/app/navbar/navbar.component.html b/src/app/navbar/navbar.component.html index bda9815481..c4f0a612f3 100644 --- a/src/app/navbar/navbar.component.html +++ b/src/app/navbar/navbar.component.html @@ -1,5 +1,5 @@
diff --git a/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts b/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts index 8c5fc88137..f2ee4374a0 100644 --- a/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts +++ b/src/app/shared/eperson-group-list/eperson-group-list.component.spec.ts @@ -3,7 +3,7 @@ import { ChangeDetectorRef, Component, Injector, NO_ERRORS_SCHEMA } from '@angul import { of as observableOf } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; -import { cold } from 'jasmine-marbles'; +import { hot } from 'jasmine-marbles'; import uniqueId from 'lodash/uniqueId'; import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; @@ -22,14 +22,13 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { PaginationService } from '../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../testing/pagination-service.stub'; -describe('EpersonGroupListComponent test suite', () => { +describe('EpersonGroupListComponent', () => { let comp: EpersonGroupListComponent; let compAsAny: any; let fixture: ComponentFixture; - let de; let groupService: any; let epersonService: any; - let paginationService; + let paginationService: PaginationServiceStub; const paginationOptions: PaginationComponentOptions = new PaginationComponentOptions(); paginationOptions.id = uniqueId('eperson-group-list-pagination-test'); @@ -91,7 +90,6 @@ describe('EpersonGroupListComponent test suite', () => { })); describe('', () => { - let testComp: TestComponent; let testFixture: ComponentFixture; // synchronous beforeEach @@ -101,7 +99,6 @@ describe('EpersonGroupListComponent test suite', () => { `; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; - testComp = testFixture.componentInstance; }); afterEach(() => { @@ -129,7 +126,6 @@ describe('EpersonGroupListComponent test suite', () => { afterEach(() => { comp = null; compAsAny = null; - de = null; fixture.destroy(); }); @@ -147,16 +143,15 @@ describe('EpersonGroupListComponent test suite', () => { fixture.detectChanges(); - expect(compAsAny.entrySelectedId.value).toBe(EPersonMock.id); + expect(comp.entrySelectedId$.value).toBe(EPersonMock.id); }); it('should init the list of eperson', () => { epersonService.searchByScope.and.returnValue(observableOf(epersonPaginatedListRD)); fixture.detectChanges(); - expect(compAsAny.list$.value).toEqual(epersonPaginatedListRD); - expect(comp.getList()).toBeObservable(cold('a', { - a: epersonPaginatedListRD + expect(comp.list$).toBeObservable(hot('(a|)', { + a: epersonPaginatedList, })); }); @@ -165,23 +160,13 @@ describe('EpersonGroupListComponent test suite', () => { comp.emitSelect(EPersonMock); expect(comp.select.emit).toHaveBeenCalled(); - expect(compAsAny.entrySelectedId.value).toBe(EPersonMock.id); + expect(comp.entrySelectedId$.value).toBe(EPersonMock.id); }); - it('should return true when entry is selected', () => { - compAsAny.entrySelectedId.next(EPersonMock.id); + it('should return the entrySelectedId$ value', () => { + comp.entrySelectedId$.next(EPersonMock.id); - expect(comp.isSelected(EPersonMock)).toBeObservable(cold('a', { - a: true - })); - }); - - it('should return false when entry is not selected', () => { - compAsAny.entrySelectedId.next(''); - - expect(comp.isSelected(EPersonMock)).toBeObservable(cold('a', { - a: false - })); + expect(comp.entrySelectedId$.value).toBe(EPersonMock.id); }); }); @@ -199,7 +184,6 @@ describe('EpersonGroupListComponent test suite', () => { afterEach(() => { comp = null; compAsAny = null; - de = null; fixture.destroy(); }); @@ -217,16 +201,15 @@ describe('EpersonGroupListComponent test suite', () => { fixture.detectChanges(); - expect(compAsAny.entrySelectedId.value).toBe(GroupMock.id); + expect(comp.entrySelectedId$.value).toBe(GroupMock.id); }); it('should init the list of group', () => { groupService.searchGroups.and.returnValue(observableOf(groupPaginatedListRD)); fixture.detectChanges(); - expect(compAsAny.list$.value).toEqual(groupPaginatedListRD); - expect(comp.getList()).toBeObservable(cold('a', { - a: groupPaginatedListRD + expect(comp.list$).toBeObservable(hot('(a|)', { + a: groupPaginatedList, })); }); @@ -235,27 +218,16 @@ describe('EpersonGroupListComponent test suite', () => { comp.emitSelect(GroupMock); expect(comp.select.emit).toHaveBeenCalled(); - expect(compAsAny.entrySelectedId.value).toBe(GroupMock.id); + expect(comp.entrySelectedId$.value).toBe(GroupMock.id); }); - it('should return true when entry is selected', () => { - compAsAny.entrySelectedId.next(EPersonMock.id); + it('should return the entrySelectedId$ value', () => { + comp.entrySelectedId$.next(GroupMock.id); - expect(comp.isSelected(EPersonMock)).toBeObservable(cold('a', { - a: true - })); - }); - - it('should return false when entry is not selected', () => { - compAsAny.entrySelectedId.next(''); - - expect(comp.isSelected(EPersonMock)).toBeObservable(cold('a', { - a: false - })); + expect(comp.entrySelectedId$.value).toBe(GroupMock.id); }); it('should update list on search triggered', () => { - const options: PaginationComponentOptions = comp.paginationOptions; const event: SearchEvent = { scope: 'metadata', query: 'test' @@ -263,7 +235,7 @@ describe('EpersonGroupListComponent test suite', () => { spyOn(comp, 'updateList'); comp.onSearch(event); - expect(compAsAny.updateList).toHaveBeenCalledWith('metadata', 'test'); + expect(comp.updateList).toHaveBeenCalledWith('metadata', 'test'); }); }); }); diff --git a/src/app/shared/eperson-group-list/eperson-group-list.component.ts b/src/app/shared/eperson-group-list/eperson-group-list.component.ts index 7cad7a9783..154533deda 100644 --- a/src/app/shared/eperson-group-list/eperson-group-list.component.ts +++ b/src/app/shared/eperson-group-list/eperson-group-list.component.ts @@ -1,14 +1,12 @@ import { Component, EventEmitter, Injector, Input, OnDestroy, OnInit, Output } from '@angular/core'; -import { BehaviorSubject, Observable, Subscription } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { switchMap } from 'rxjs/operators'; import uniqueId from 'lodash/uniqueId'; -import { RemoteData } from '../../core/data/remote-data'; import { PaginatedList } from '../../core/data/paginated-list.model'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; -import { hasValue, isNotEmpty } from '../empty.util'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { EPERSON } from '../../core/eperson/models/eperson.resource-type'; import { GROUP } from '../../core/eperson/models/group.resource-type'; @@ -16,10 +14,12 @@ import { ResourceType } from '../../core/shared/resource-type'; import { EPersonDataService } from '../../core/eperson/eperson-data.service'; import { GroupDataService } from '../../core/eperson/group-data.service'; import { fadeInOut } from '../animations/fade'; -import { getFirstCompletedRemoteData } from '../../core/shared/operators'; +import { getAllCompletedRemoteData, getRemoteDataPayload } from '../../core/shared/operators'; import { PaginationService } from '../../core/pagination/pagination.service'; import { FindListOptions } from '../../core/data/find-list-options.model'; import { getDataServiceFor } from '../../core/data/base/data-service.decorator'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { Group } from '../../core/eperson/models/group.model'; export interface SearchEvent { scope: string; @@ -79,21 +79,13 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { /** * A list of eperson or group */ - private list$: BehaviorSubject>> = new BehaviorSubject>>({} as any); + list$: Observable>; /** * The eperson or group's id selected * @type {string} */ - private entrySelectedId: BehaviorSubject = new BehaviorSubject(''); - - /** - * Array to track all subscriptions and unsubscribe them onDestroy - * @type {Array} - */ - private subs: Subscription[] = []; - - private pageConfigSub: Subscription; + entrySelectedId$: BehaviorSubject = new BehaviorSubject(''); /** * Initialize instance variables and inject the properly DataService @@ -119,7 +111,7 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { this.paginationOptions.pageSize = 5; if (this.initSelected) { - this.entrySelectedId.next(this.initSelected); + this.entrySelectedId$.next(this.initSelected); } this.updateList(this.currentSearchScope, this.currentSearchQuery); @@ -133,28 +125,9 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { */ emitSelect(entry: DSpaceObject): void { this.select.emit(entry); - this.entrySelectedId.next(entry.id); + this.entrySelectedId$.next(entry.id); } - /** - * Return the list of eperson or group - */ - getList(): Observable>> { - return this.list$.asObservable(); - } - - /** - * Return a boolean representing if a table row is selected - * - * @return {boolean} - */ - isSelected(entry: DSpaceObject): Observable { - return this.entrySelectedId.asObservable().pipe( - map((selectedId) => isNotEmpty(selectedId) && selectedId === entry.id) - ); - } - - /** * Method called on search */ @@ -169,38 +142,26 @@ export class EpersonGroupListComponent implements OnInit, OnDestroy { * Retrieve a paginate list of eperson or group */ 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(), { + this.list$ = this.paginationService.getCurrentPagination(this.paginationOptions.id, this.paginationOptions).pipe( + switchMap((paginationOptions) => { + const options: FindListOptions = Object.assign(new FindListOptions(), { elementsPerPage: paginationOptions.pageSize, - currentPage: paginationOptions.currentPage - }); + currentPage: paginationOptions.currentPage, + }); - const search$: Observable>> = this.isListOfEPerson ? - (this.dataService as EPersonDataService).searchByScope(scope, query, options) : - (this.dataService as GroupDataService).searchGroups(query, options); - - this.subs.push(search$.pipe(getFirstCompletedRemoteData()) - .subscribe((list: RemoteData>) => { - if (hasValue(this.list$)) { - this.list$.next(list); - } - }) + return this.isListOfEPerson ? + (this.dataService as EPersonDataService).searchByScope(scope, query, options) : + (this.dataService as GroupDataService).searchGroups(query, options); + }), + getAllCompletedRemoteData(), + getRemoteDataPayload(), ); - }); } /** * Unsubscribe from all subscriptions */ ngOnDestroy(): void { - this.list$ = null; - this.subs - .filter((subscription) => hasValue(subscription)) - .forEach((subscription) => subscription.unsubscribe()); this.paginationService.clearPagination(this.paginationOptions.id); } diff --git a/src/app/shared/host-window.service.ts b/src/app/shared/host-window.service.ts index 1c71bf5075..2a07165a1e 100644 --- a/src/app/shared/host-window.service.ts +++ b/src/app/shared/host-window.service.ts @@ -137,10 +137,10 @@ export class HostWindowService { } isXsOrSm(): Observable { - return observableCombineLatest( + return observableCombineLatest([ this.isXs(), this.isSm() - ).pipe( + ]).pipe( map(([isXs, isSm]) => isXs || isSm), distinctUntilChanged() ); diff --git a/src/app/shared/pagination/pagination.component.html b/src/app/shared/pagination/pagination.component.html index 281a009d2e..d7fdb62c5a 100644 --- a/src/app/shared/pagination/pagination.component.html +++ b/src/app/shared/pagination/pagination.component.html @@ -37,7 +37,7 @@
-
+