diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.html b/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.html index b0c155ac957..1fe121e8988 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.html +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.html @@ -1,18 +1,18 @@
- - -
diff --git a/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.ts b/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.ts index 2d1308cc83a..95295386c0e 100644 --- a/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.ts +++ b/src/app/collection-page/edit-collection-page/collection-source/collection-source.component.ts @@ -204,11 +204,6 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem */ formGroup: UntypedFormGroup; - /** - * Subscription to update the current form - */ - updateSub: Subscription; - /** * The content harvesting type used when harvesting is disabled */ @@ -228,28 +223,29 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem */ displayedNotifications: INotification[] = []; - public constructor(public objectUpdatesService: ObjectUpdatesService, - public notificationsService: NotificationsService, - protected location: Location, - protected formService: DynamicFormService, - protected translate: TranslateService, - protected route: ActivatedRoute, - protected router: Router, - protected collectionService: CollectionDataService, - protected requestService: RequestService) { - super(objectUpdatesService, notificationsService, translate); + subs: Subscription[] = []; + + public constructor( + public objectUpdatesService: ObjectUpdatesService, + public notificationsService: NotificationsService, + public translateService: TranslateService, + public router: Router, + protected location: Location, + protected formService: DynamicFormService, + protected route: ActivatedRoute, + protected collectionService: CollectionDataService, + protected requestService: RequestService, + ) { + super(objectUpdatesService, notificationsService, translateService, router); } /** * Initialize properties to setup the Field Update and Form */ ngOnInit(): void { + super.ngOnInit(); this.notificationsPrefix = 'collection.edit.tabs.source.notifications.'; this.discardTimeOut = environment.collection.edit.undoTimeout; - this.url = this.router.url; - if (this.url.indexOf('?') > 0) { - this.url = this.url.substr(0, this.url.indexOf('?')); - } this.formGroup = this.formService.createFormGroup(this.formModel); this.collectionRD$ = this.route.parent.data.pipe(first(), map((data) => data.dso)); @@ -263,10 +259,9 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem }); this.updateFieldTranslations(); - this.translate.onLangChange - .subscribe(() => { - this.updateFieldTranslations(); - }); + this.subs.push(this.translateService.onLangChange.subscribe(() => { + this.updateFieldTranslations(); + })); } /** @@ -281,7 +276,7 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem this.update$ = this.objectUpdatesService.getFieldUpdates(this.url, [initialContentSource]).pipe( map((updates: FieldUpdates) => updates[initialContentSource.uuid]) ); - this.updateSub = this.update$.subscribe((update: FieldUpdate) => { + this.subs.push(this.update$.subscribe((update: FieldUpdate) => { if (update) { const field = update.field as ContentSource; let configId; @@ -308,7 +303,7 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem } this.contentSource.metadataConfigId = configId; } - }); + })); } /** @@ -342,18 +337,18 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem * @param fieldModel */ private updateFieldTranslation(fieldModel: DynamicFormControlModel) { - fieldModel.label = this.translate.instant(this.LABEL_KEY_PREFIX + fieldModel.id); + fieldModel.label = this.translateService.instant(this.LABEL_KEY_PREFIX + fieldModel.id); if (isNotEmpty(fieldModel.validators)) { fieldModel.errorMessages = {}; Object.keys(fieldModel.validators).forEach((key) => { - fieldModel.errorMessages[key] = this.translate.instant(this.ERROR_KEY_PREFIX + fieldModel.id + '.' + key); + fieldModel.errorMessages[key] = this.translateService.instant(this.ERROR_KEY_PREFIX + fieldModel.id + '.' + key); }); } if (fieldModel instanceof DynamicOptionControlModel) { if (isNotEmpty(fieldModel.options)) { fieldModel.options.forEach((option) => { if (hasNoValue(option.label)) { - option.label = this.translate.instant(this.OPTIONS_KEY_PREFIX + fieldModel.id + '.' + option.value); + option.label = this.translateService.instant(this.OPTIONS_KEY_PREFIX + fieldModel.id + '.' + option.value); } }); } @@ -470,8 +465,6 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem * Make sure open subscriptions are closed */ ngOnDestroy(): void { - if (this.updateSub) { - this.updateSub.unsubscribe(); - } + this.subs.forEach((sub: Subscription) => sub.unsubscribe()); } } diff --git a/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts b/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts index 964405dfdda..4c737978142 100644 --- a/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts +++ b/src/app/item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts @@ -35,10 +35,6 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl */ updates$: Observable; - hasChanges$: Observable; - - isReinstatable$: Observable; - /** * Route to the item's page */ @@ -58,7 +54,7 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl public translateService: TranslateService, public route: ActivatedRoute ) { - super(objectUpdatesService, notificationsService, translateService); + super(objectUpdatesService, notificationsService, translateService, router); } /** @@ -83,11 +79,9 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl this.setItem(rd.payload); }); } + super.ngOnInit(); this.discardTimeOut = environment.item.edit.undoTimeout; - this.url = this.router.url.split('?')[0]; - this.hasChanges$ = this.hasChanges(); - this.isReinstatable$ = this.isReinstatable(); this.hasChanges().pipe(first()).subscribe((hasChanges) => { if (!hasChanges) { this.initializeOriginalFields(); diff --git a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts index ee53bd919c2..a9aad655e96 100644 --- a/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts +++ b/src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectorRef, Component, NgZone, OnDestroy } from '@angular/core'; import { AbstractItemUpdateComponent } from '../abstract-item-update/abstract-item-update.component'; import { filter, map, switchMap, take } from 'rxjs/operators'; -import { Observable, Subscription, zip as observableZip } from 'rxjs'; +import { Observable, Subscription, zip as observableZip, combineLatest } from 'rxjs'; import { ItemDataService } from '../../../core/data/item-data.service'; import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service'; import { ActivatedRoute, Router } from '@angular/router'; @@ -222,7 +222,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme */ isReinstatable(): Observable { return this.bundles$.pipe( - switchMap((bundles: Bundle[]) => observableZip(...bundles.map((bundle: Bundle) => this.objectUpdatesService.isReinstatable(bundle.self)))), + switchMap((bundles: Bundle[]) => combineLatest(bundles.map((bundle: Bundle) => this.objectUpdatesService.isReinstatable(bundle.self)))), map((reinstatable: boolean[]) => reinstatable.includes(true)) ); } @@ -232,7 +232,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme */ hasChanges(): Observable { return this.bundles$.pipe( - switchMap((bundles: Bundle[]) => observableZip(...bundles.map((bundle: Bundle) => this.objectUpdatesService.hasUpdates(bundle.self)))), + switchMap((bundles: Bundle[]) => combineLatest(bundles.map((bundle: Bundle) => this.objectUpdatesService.hasUpdates(bundle.self)))), map((hasChanges: boolean[]) => hasChanges.includes(true)) ); } diff --git a/src/app/shared/trackable/abstract-trackable.component.spec.ts b/src/app/shared/trackable/abstract-trackable.component.spec.ts index c538f074c54..ad2d821ada3 100644 --- a/src/app/shared/trackable/abstract-trackable.component.spec.ts +++ b/src/app/shared/trackable/abstract-trackable.component.spec.ts @@ -9,6 +9,8 @@ import { NotificationsService } from '../notifications/notifications.service'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { TestScheduler } from 'rxjs/testing'; import { getTestScheduler } from 'jasmine-marbles'; +import { RouterStub } from '../testing/router.stub'; +import { Router } from '@angular/router'; describe('AbstractTrackableComponent', () => { let comp: AbstractTrackableComponent; @@ -27,6 +29,7 @@ describe('AbstractTrackableComponent', () => { success: successNotification } ); + let router: RouterStub; const url = 'http://test-url.com/test-url'; @@ -42,6 +45,8 @@ describe('AbstractTrackableComponent', () => { isValidPage: observableOf(true) } ); + router = new RouterStub(); + router.url = url; scheduler = getTestScheduler(); @@ -51,6 +56,7 @@ describe('AbstractTrackableComponent', () => { providers: [ { provide: ObjectUpdatesService, useValue: objectUpdatesService }, { provide: NotificationsService, useValue: notificationsService }, + { provide: Router, useValue: router }, ], schemas: [ NO_ERRORS_SCHEMA ] @@ -60,7 +66,6 @@ describe('AbstractTrackableComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(AbstractTrackableComponent); comp = fixture.componentInstance; - comp.url = url; fixture.detectChanges(); }); diff --git a/src/app/shared/trackable/abstract-trackable.component.ts b/src/app/shared/trackable/abstract-trackable.component.ts index e1a99d90b94..396d7438551 100644 --- a/src/app/shared/trackable/abstract-trackable.component.ts +++ b/src/app/shared/trackable/abstract-trackable.component.ts @@ -2,7 +2,8 @@ import { ObjectUpdatesService } from '../../core/data/object-updates/object-upda import { NotificationsService } from '../notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; /** * Abstract Component that is able to track changes made in the inheriting component using the ObjectUpdateService @@ -11,7 +12,7 @@ import { Component } from '@angular/core'; selector: 'ds-abstract-trackable', template: '' }) -export class AbstractTrackableComponent { +export class AbstractTrackableComponent implements OnInit { /** * The time span for being able to undo discarding changes @@ -21,14 +22,25 @@ export class AbstractTrackableComponent { public url: string; public notificationsPrefix = 'static-pages.form.notification'; + hasChanges$: Observable; + + isReinstatable$: Observable; + constructor( public objectUpdatesService: ObjectUpdatesService, public notificationsService: NotificationsService, public translateService: TranslateService, + public router: Router, ) { } + ngOnInit(): void { + this.url = this.router.url.split('?')[0]; + this.hasChanges$ = this.hasChanges(); + this.isReinstatable$ = this.isReinstatable(); + } + /** * Request the object updates service to discard all current changes to this item * Shows a notification to remind the user that they can undo this