From 7472e6939b7a7faee3194765bbbe6af0b69f3ae3 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Mon, 18 Mar 2024 13:45:42 +0100 Subject: [PATCH] [DURACOM-191] Fix dso-edit-metadata.component which still used getDataServiceFor decorator --- .../edit-item-template-page.component.spec.ts | 6 ++ .../edit-item-template-page.component.ts | 2 + .../dso-edit-metadata.component.spec.ts | 42 ++++----- .../dso-edit-metadata.component.ts | 85 +++++++++++++------ .../shared/testing/test-data-service.mock.ts | 13 ++- 5 files changed, 97 insertions(+), 51 deletions(-) diff --git a/src/app/collection-page/edit-item-template-page/edit-item-template-page.component.spec.ts b/src/app/collection-page/edit-item-template-page/edit-item-template-page.component.spec.ts index a148881db7..7fa29919f8 100644 --- a/src/app/collection-page/edit-item-template-page/edit-item-template-page.component.spec.ts +++ b/src/app/collection-page/edit-item-template-page/edit-item-template-page.component.spec.ts @@ -12,6 +12,8 @@ import { of as observableOf } from 'rxjs'; import { ItemTemplateDataService } from '../../core/data/item-template-data.service'; import { Collection } from '../../core/shared/collection.model'; +import { DsoEditMetadataComponent } from '../../dso-shared/dso-edit-metadata/dso-edit-metadata.component'; +import { ThemedDsoEditMetadataComponent } from '../../dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component'; import { getMockThemeService } from '../../shared/mocks/theme-service.mock'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { @@ -47,6 +49,10 @@ describe('EditItemTemplatePageComponent', () => { { provide: NotificationsService, useValue: new NotificationsServiceStub() }, ], schemas: [NO_ERRORS_SCHEMA], + }).overrideComponent(EditItemTemplatePageComponent, { + remove: { + imports: [ThemedDsoEditMetadataComponent, DsoEditMetadataComponent], + }, }).compileComponents(); })); diff --git a/src/app/collection-page/edit-item-template-page/edit-item-template-page.component.ts b/src/app/collection-page/edit-item-template-page/edit-item-template-page.component.ts index cc96b46588..eb44ffdc9b 100644 --- a/src/app/collection-page/edit-item-template-page/edit-item-template-page.component.ts +++ b/src/app/collection-page/edit-item-template-page/edit-item-template-page.component.ts @@ -24,6 +24,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { Collection } from '../../core/shared/collection.model'; import { Item } from '../../core/shared/item.model'; import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; +import { DsoEditMetadataComponent } from '../../dso-shared/dso-edit-metadata/dso-edit-metadata.component'; import { ThemedDsoEditMetadataComponent } from '../../dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component'; import { AlertComponent } from '../../shared/alert/alert.component'; import { AlertType } from '../../shared/alert/alert-type'; @@ -36,6 +37,7 @@ import { getCollectionEditRoute } from '../collection-page-routing-paths'; templateUrl: './edit-item-template-page.component.html', imports: [ ThemedDsoEditMetadataComponent, + DsoEditMetadataComponent, RouterLink, AsyncPipe, VarDirective, diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts index 567572c4fa..c3d82d0795 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.spec.ts @@ -1,7 +1,6 @@ +import { CommonModule } from '@angular/common'; import { - ChangeDetectionStrategy, DebugElement, - Injectable, NO_ERRORS_SCHEMA, } from '@angular/core'; import { @@ -9,15 +8,15 @@ import { TestBed, waitForAsync, } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; +import { + BrowserModule, + By, +} from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; -import { Operation } from 'fast-json-patch'; -import { Observable } from 'rxjs'; +import { APP_DATA_SERVICES_MAP } from '../../../config/app-config.interface'; import { ArrayMoveChangeAnalyzer } from '../../core/data/array-move-change-analyzer.service'; -import { DATA_SERVICE_FACTORY } from '../../core/data/base/data-service.decorator'; -import { RemoteData } from '../../core/data/remote-data'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { Item } from '../../core/shared/item.model'; import { ITEM } from '../../core/shared/item.resource-type'; @@ -25,7 +24,7 @@ import { MetadataValue } from '../../core/shared/metadata.models'; import { AlertComponent } from '../../shared/alert/alert.component'; import { LoadingComponent } from '../../shared/loading/loading.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; -import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { TestDataService } from '../../shared/testing/test-data-service.mock'; import { VarDirective } from '../../shared/utils/var.directive'; import { DsoEditMetadataComponent } from './dso-edit-metadata.component'; import { DsoEditMetadataFieldValuesComponent } from './dso-edit-metadata-field-values/dso-edit-metadata-field-values.component'; @@ -39,12 +38,9 @@ const REINSTATE_BTN = 'reinstate'; const SAVE_BTN = 'save'; const DISCARD_BTN = 'discard'; -@Injectable() -class TestDataService { - patch(object: Item, operations: Operation[]): Observable> { - return createSuccessfulRemoteDataObject$(object); - } -} +const mockDataServiceMap: any = { + [ITEM.value]: () => import('../../shared/testing/test-data-service.mock').then(m => m.TestDataService), +}; describe('DsoEditMetadataComponent', () => { let component: DsoEditMetadataComponent; @@ -92,21 +88,18 @@ describe('DsoEditMetadataComponent', () => { TestBed.configureTestingModule({ imports: [ + CommonModule, + BrowserModule, TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), DsoEditMetadataComponent, VarDirective, ], providers: [ - TestDataService, - { - provide: DATA_SERVICE_FACTORY, - useValue: jasmine - .createSpy('getDataServiceFor') - .and.returnValue(TestDataService), - }, + { provide: APP_DATA_SERVICES_MAP, useValue: mockDataServiceMap }, { provide: NotificationsService, useValue: notificationsService }, ArrayMoveChangeAnalyzer, + TestDataService, ], schemas: [NO_ERRORS_SCHEMA], }) @@ -122,19 +115,16 @@ describe('DsoEditMetadataComponent', () => { LoadingComponent, ], }, - add: { - changeDetection: ChangeDetectionStrategy.Default, - }, }) .compileComponents(); })); - beforeEach(() => { + beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(DsoEditMetadataComponent); component = fixture.componentInstance; component.dso = dso; fixture.detectChanges(); - }); + })); describe('when no changes have been made', () => { assertButton(ADD_BTN, true, false); diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts index 517843f3da..6365f1ea99 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata.component.ts @@ -4,8 +4,10 @@ import { NgIf, } from '@angular/common'; import { + ChangeDetectorRef, Component, Inject, + InjectionToken, Injector, Input, OnDestroy, @@ -23,18 +25,25 @@ import { import { BehaviorSubject, combineLatest as observableCombineLatest, + EMPTY, Observable, Subscription, } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { + map, + mergeMap, + tap, +} from 'rxjs/operators'; +import { + APP_DATA_SERVICES_MAP, + LazyDataServicesMap, +} from '../../../config/app-config.interface'; import { ArrayMoveChangeAnalyzer } from '../../core/data/array-move-change-analyzer.service'; -import { DATA_SERVICE_FACTORY } from '../../core/data/base/data-service.decorator'; -import { HALDataService } from '../../core/data/base/hal-data-service.interface'; import { RemoteData } from '../../core/data/remote-data'; import { UpdateDataService } from '../../core/data/update-data.service'; +import { lazyService } from '../../core/lazy-service'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; -import { GenericConstructor } from '../../core/shared/generic-constructor'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; import { ResourceType } from '../../core/shared/resource-type'; import { AlertComponent } from '../../shared/alert/alert.component'; @@ -42,6 +51,7 @@ import { AlertType } from '../../shared/alert/alert-type'; import { hasNoValue, hasValue, + isNotEmpty, } from '../../shared/empty.util'; import { LoadingComponent } from '../../shared/loading/loading.component'; import { NotificationsService } from '../../shared/notifications/notifications.service'; @@ -141,7 +151,8 @@ export class DsoEditMetadataComponent implements OnInit, OnDestroy { protected translateService: TranslateService, protected parentInjector: Injector, protected arrayMoveChangeAnalyser: ArrayMoveChangeAnalyzer, - @Inject(DATA_SERVICE_FACTORY) protected getDataServiceFor: (resourceType: ResourceType) => GenericConstructor>) { + protected cdr: ChangeDetectorRef, + @Inject(APP_DATA_SERVICES_MAP) private dataServiceMap: InjectionToken) { } /** @@ -152,15 +163,18 @@ export class DsoEditMetadataComponent implements OnInit, OnDestroy { if (hasNoValue(this.dso)) { this.dsoUpdateSubscription = observableCombineLatest([this.route.data, this.route.parent.data]).pipe( map(([data, parentData]: [Data, Data]) => Object.assign({}, data, parentData)), - map((data: any) => data.dso), - ).subscribe((rd: RemoteData) => { - this.dso = rd.payload; - this.initDataService(); + tap((data: any) => this.initDSO(data.dso.payload)), + mergeMap(() => this.retrieveDataService()), + ).subscribe((dataService: UpdateDataService) => { + this.initDataService(dataService); this.initForm(); }); } else { - this.initDataService(); - this.initForm(); + this.initDSOType(this.dso); + this.retrieveDataService().subscribe((dataService: UpdateDataService) => { + this.initDataService(dataService); + this.initForm(); + }); } this.savingOrLoadingFieldValidation$ = observableCombineLatest([this.saving$, this.loadingFieldValidation$]).pipe( map(([saving, loading]: [boolean, boolean]) => saving || loading), @@ -168,25 +182,47 @@ export class DsoEditMetadataComponent implements OnInit, OnDestroy { } /** - * Initialise (resolve) the data-service for the current DSpaceObject + * Resolve the data-service for the current DSpaceObject and retrieve its instance */ - initDataService(): void { - let type: ResourceType; - if (typeof this.dso.type === 'string') { - type = new ResourceType(this.dso.type); - } else { - type = this.dso.type; - } + retrieveDataService(): Observable> { if (hasNoValue(this.updateDataService)) { - const provider = this.getDataServiceFor(type); - this.updateDataService = Injector.create({ - providers: [], - parent: this.parentInjector, - }).get(provider); + const lazyProvider$: Observable> = lazyService(this.dataServiceMap[this.dsoType], this.parentInjector); + return lazyProvider$; + } else { + return EMPTY; + } + } + + /** + * Initialise the current DSpaceObject + */ + initDSO(object: DSpaceObject) { + this.dso = object; + this.initDSOType(object); + } + + /** + * Initialise the current DSpaceObject's type + */ + initDSOType(object: DSpaceObject) { + let type: ResourceType; + if (typeof object.type === 'string') { + type = new ResourceType(object.type); + } else { + type = object.type; } this.dsoType = type.value; } + /** + * Initialise the data-service for the current DSpaceObject + */ + initDataService(dataService: UpdateDataService): void { + if (isNotEmpty(dataService)) { + this.updateDataService = dataService; + } + } + /** * Initialise the dynamic form object by passing the DSpaceObject's metadata * Call onValueSaved() to update the form's state properties @@ -194,6 +230,7 @@ export class DsoEditMetadataComponent implements OnInit, OnDestroy { initForm(): void { this.form = new DsoEditMetadataForm(this.dso.metadata); this.onValueSaved(); + this.cdr.detectChanges(); } /** diff --git a/src/app/shared/testing/test-data-service.mock.ts b/src/app/shared/testing/test-data-service.mock.ts index dbb216ea57..b5529f4a07 100644 --- a/src/app/shared/testing/test-data-service.mock.ts +++ b/src/app/shared/testing/test-data-service.mock.ts @@ -1,7 +1,14 @@ import { Injectable } from '@angular/core'; -import { of } from 'rxjs'; +import { Operation } from 'fast-json-patch'; +import { + Observable, + of, +} from 'rxjs'; import { FindListOptions } from '../../core/data/find-list-options.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { Item } from '../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; import { FollowLinkConfig } from '../utils/follow-link-config.model'; @Injectable() @@ -13,4 +20,8 @@ export class TestDataService { findByHref(href: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]) { return of('findByHref'); } + + patch(object: Item, operations: Operation[]): Observable> { + return createSuccessfulRemoteDataObject$(object); + } }