diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts index 3c9b575027..cfffc5ddb7 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.spec.ts @@ -1,4 +1,6 @@ -import { DsDynamicLookupRelationExternalSourceTabComponent } from './dynamic-lookup-relation-external-source-tab.component'; +import { + DsDynamicLookupRelationExternalSourceTabComponent +} from './dynamic-lookup-relation-external-source-tab.component'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { VarDirective } from '../../../../../utils/var.directive'; import { TranslateModule } from '@ngx-translate/core'; @@ -6,7 +8,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core'; import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; -import { of as observableOf } from 'rxjs'; +import { of as observableOf, EMPTY } from 'rxjs'; import { createFailedRemoteDataObject$, createPendingRemoteDataObject$, @@ -22,11 +24,13 @@ import { SelectableListService } from '../../../../../object-list/selectable-lis import { Item } from '../../../../../../core/shared/item.model'; import { Collection } from '../../../../../../core/shared/collection.model'; import { RelationshipOptions } from '../../../models/relationship-options.model'; -import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component'; import { createPaginatedList } from '../../../../../testing/utils.test'; import { PaginationService } from '../../../../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; import { ItemType } from '../../../../../../core/shared/item-relationships/item-type.model'; +import { + ThemedExternalSourceEntryImportModalComponent +} from './external-source-entry-import-modal/themed-external-source-entry-import-modal.component'; describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { let component: DsDynamicLookupRelationExternalSourceTabComponent; @@ -187,12 +191,13 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => { describe('import', () => { beforeEach(() => { - spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ importedObject: new EventEmitter() }) })); + spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ importedObject: new EventEmitter(), compRef$: EMPTY }) })); + component.modalRef = modalService.open(ThemedExternalSourceEntryImportModalComponent, { size: 'lg', container: 'ds-dynamic-lookup-relation-modal' }); component.import(externalEntries[0]); }); it('should open a new ExternalSourceEntryImportModalComponent', () => { - expect(modalService.open).toHaveBeenCalledWith(ExternalSourceEntryImportModalComponent, jasmine.any(Object)); + expect(modalService.open).toHaveBeenCalledWith(ThemedExternalSourceEntryImportModalComponent, jasmine.any(Object)); }); }); }); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts index e5ea98e537..22fcc4e8bb 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/dynamic-lookup-relation-external-source-tab.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ComponentRef } from '@angular/core'; import { SEARCH_CONFIG_SERVICE } from '../../../../../../my-dspace-page/my-dspace-page.component'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { Router } from '@angular/router'; @@ -16,7 +16,8 @@ import { PaginationComponentOptions } from '../../../../../pagination/pagination import { RelationshipOptions } from '../../../models/relationship-options.model'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component'; -import { hasValue } from '../../../../../empty.util'; +import { ThemedExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/themed-external-source-entry-import-modal.component'; +import { hasValue, hasValueOperator } from '../../../../../empty.util'; import { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service'; import { Item } from '../../../../../../core/shared/item.model'; import { Collection } from '../../../../../../core/shared/collection.model'; @@ -114,9 +115,9 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit modalRef: NgbModalRef; /** - * Subscription to the modal's importedObject event-emitter + * Array to track all subscriptions and unsubscribe them onDestroy */ - importObjectSub: Subscription; + protected subs: Subscription[] = []; /** * The entity types compatible with the given external source @@ -161,30 +162,40 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit * @param entry The entry to import */ import(entry) { - this.modalRef = this.modalService.open(ExternalSourceEntryImportModalComponent, { + this.modalRef = this.modalService.open(ThemedExternalSourceEntryImportModalComponent, { size: 'lg', container: 'ds-dynamic-lookup-relation-modal' }); - const modalComp = this.modalRef.componentInstance; - modalComp.externalSourceEntry = entry; - modalComp.item = this.item; - modalComp.collection = this.collection; - modalComp.relationship = this.relationship; - modalComp.label = this.label; - modalComp.relatedEntityType = this.relatedEntityType; - this.importObjectSub = modalComp.importedObject.subscribe((object) => { + + const modalComp$ = this.modalRef.componentInstance.compRef$.pipe( + hasValueOperator(), + map((compRef: ComponentRef) => compRef.instance) + ); + + this.subs.push(modalComp$.subscribe((modalComp: ExternalSourceEntryImportModalComponent) => { + modalComp.externalSourceEntry = entry; + modalComp.item = this.item; + // modalComp.collection = this.collection; + modalComp.relationship = this.relationship; + modalComp.label = this.label; + modalComp.relatedEntityType = this.relatedEntityType; + })); + + this.subs.push(modalComp$.pipe( + switchMap((modalComp: ExternalSourceEntryImportModalComponent) => modalComp.importedObject) + ).subscribe((object) => { this.selectableListService.selectSingle(this.listId, object); this.importedObject.emit(object); - }); + })); } /** * Unsubscribe from open subscriptions */ ngOnDestroy(): void { - if (hasValue(this.importObjectSub)) { - this.importObjectSub.unsubscribe(); - } + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); } /** diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/themed-external-source-entry-import-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/themed-external-source-entry-import-modal.component.ts new file mode 100644 index 0000000000..26e6097c2d --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/themed-external-source-entry-import-modal.component.ts @@ -0,0 +1,22 @@ +import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal.component'; +import { ThemedComponent } from '../../../../../../theme-support/themed.component'; +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-themed-external-source-entry-import-modal', + styleUrls: [], + templateUrl: '../../../../../../../shared/theme-support/themed.component.html', +}) +export class ThemedExternalSourceEntryImportModalComponent extends ThemedComponent { + protected getComponentName(): string { + return 'ExternalSourceEntryImportModalComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../../../../../../themes/${themeName}/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component`); + } + + protected importUnthemedComponent(): Promise { + return import(`./external-source-entry-import-modal.component`); + } +} diff --git a/src/app/shared/form/form.module.ts b/src/app/shared/form/form.module.ts index 598cc2d32c..c3062b4231 100644 --- a/src/app/shared/form/form.module.ts +++ b/src/app/shared/form/form.module.ts @@ -37,6 +37,7 @@ import { FormBuilderService } from './builder/form-builder.service'; import { DsDynamicTypeBindRelationService } from './builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service'; import { FormService } from './form.service'; import { NgxMaskModule } from 'ngx-mask'; +import { ThemedExternalSourceEntryImportModalComponent } from './builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/themed-external-source-entry-import-modal.component'; const COMPONENTS = [ CustomSwitchComponent, @@ -64,6 +65,7 @@ const COMPONENTS = [ ChipsComponent, NumberPickerComponent, VocabularyTreeviewComponent, + ThemedExternalSourceEntryImportModalComponent ]; const DIRECTIVES = [ diff --git a/src/app/shared/theme-support/themed.component.ts b/src/app/shared/theme-support/themed.component.ts index 87f182a5ff..2a85dae402 100644 --- a/src/app/shared/theme-support/themed.component.ts +++ b/src/app/shared/theme-support/themed.component.ts @@ -11,7 +11,7 @@ import { OnChanges } from '@angular/core'; import { hasValue, isNotEmpty } from '../empty.util'; -import { from as fromPromise, Observable, of as observableOf, Subscription } from 'rxjs'; +import { from as fromPromise, Observable, of as observableOf, Subscription, BehaviorSubject } from 'rxjs'; import { ThemeService } from './theme.service'; import { catchError, switchMap, map } from 'rxjs/operators'; import { GenericConstructor } from '../../core/shared/generic-constructor'; @@ -25,6 +25,12 @@ export abstract class ThemedComponent implements OnInit, OnDestroy, OnChanges @ViewChild('vcr', { read: ViewContainerRef }) vcr: ViewContainerRef; protected compRef: ComponentRef; + /** + * A reference to the themed component. Will start as undefined and emit every time the themed + * component is rendered + */ + public compRef$: BehaviorSubject> = new BehaviorSubject(undefined); + protected lazyLoadSub: Subscription; protected themeSub: Subscription; @@ -90,6 +96,7 @@ export abstract class ThemedComponent implements OnInit, OnDestroy, OnChanges const factory = this.resolver.resolveComponentFactory(constructor); this.compRef = this.vcr.createComponent(factory); this.connectInputsAndOutputs(); + this.compRef$.next(this.compRef); this.cdr.markForCheck(); }); } diff --git a/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html b/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.scss b/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts b/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts new file mode 100644 index 0000000000..cd1de5d159 --- /dev/null +++ b/src/themes/custom/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.ts @@ -0,0 +1,15 @@ +import { + ExternalSourceEntryImportModalComponent as BaseComponent +} from '../../../../../../../../../../app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component'; +import { Component } from '@angular/core'; + +@Component({ + selector: 'ds-external-source-entry-import-modal', + styleUrls: ['../../../../../../../../../../app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.scss'], + // styleUrls: ['./external-source-entry-import-modal.component.scss'], + templateUrl: '../../../../../../../../../../app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component.html', + // templateUrl: './external-source-entry-import-modal.component.html' +}) +export class ExternalSourceEntryImportModalComponent extends BaseComponent { + +} diff --git a/src/themes/custom/lazy-theme.module.ts b/src/themes/custom/lazy-theme.module.ts index d2ac0ae787..2ff4af7946 100644 --- a/src/themes/custom/lazy-theme.module.ts +++ b/src/themes/custom/lazy-theme.module.ts @@ -114,6 +114,9 @@ import { ObjectListComponent } from './app/shared/object-list/object-list.compon import { BrowseByMetadataPageComponent } from './app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component'; import { BrowseByDatePageComponent } from './app/browse-by/browse-by-date-page/browse-by-date-page.component'; import { BrowseByTitlePageComponent } from './app/browse-by/browse-by-title-page/browse-by-title-page.component'; +import { + ExternalSourceEntryImportModalComponent +} from './app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/external-source-tab/external-source-entry-import-modal/external-source-entry-import-modal.component'; const DECLARATIONS = [ FileSectionComponent, @@ -168,6 +171,7 @@ const DECLARATIONS = [ BrowseByMetadataPageComponent, BrowseByDatePageComponent, BrowseByTitlePageComponent, + ExternalSourceEntryImportModalComponent, ];