Merge pull request #1942 from atmire/w2p-96062_theme-external-source-entry-import-modal-component

make the ExternalSourceEntryImportModalComponent themeable by default
This commit is contained in:
Tim Donohue
2022-12-16 11:29:57 -06:00
committed by GitHub
9 changed files with 89 additions and 23 deletions

View File

@@ -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 { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { VarDirective } from '../../../../../utils/var.directive'; import { VarDirective } from '../../../../../utils/var.directive';
import { TranslateModule } from '@ngx-translate/core'; 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 { EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core';
import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model'; import { PaginatedSearchOptions } from '../../../../../search/models/paginated-search-options.model';
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
import { of as observableOf } from 'rxjs'; import { of as observableOf, EMPTY } from 'rxjs';
import { import {
createFailedRemoteDataObject$, createFailedRemoteDataObject$,
createPendingRemoteDataObject$, createPendingRemoteDataObject$,
@@ -22,11 +24,13 @@ import { SelectableListService } from '../../../../../object-list/selectable-lis
import { Item } from '../../../../../../core/shared/item.model'; import { Item } from '../../../../../../core/shared/item.model';
import { Collection } from '../../../../../../core/shared/collection.model'; import { Collection } from '../../../../../../core/shared/collection.model';
import { RelationshipOptions } from '../../../models/relationship-options.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 { createPaginatedList } from '../../../../../testing/utils.test';
import { PaginationService } from '../../../../../../core/pagination/pagination.service'; import { PaginationService } from '../../../../../../core/pagination/pagination.service';
import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub'; import { PaginationServiceStub } from '../../../../../testing/pagination-service.stub';
import { ItemType } from '../../../../../../core/shared/item-relationships/item-type.model'; 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', () => { describe('DsDynamicLookupRelationExternalSourceTabComponent', () => {
let component: DsDynamicLookupRelationExternalSourceTabComponent; let component: DsDynamicLookupRelationExternalSourceTabComponent;
@@ -187,12 +191,13 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => {
describe('import', () => { describe('import', () => {
beforeEach(() => { beforeEach(() => {
spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ importedObject: new EventEmitter<any>() }) })); spyOn(modalService, 'open').and.returnValue(Object.assign({ componentInstance: Object.assign({ importedObject: new EventEmitter<any>(), compRef$: EMPTY }) }));
component.modalRef = modalService.open(ThemedExternalSourceEntryImportModalComponent, { size: 'lg', container: 'ds-dynamic-lookup-relation-modal' });
component.import(externalEntries[0]); component.import(externalEntries[0]);
}); });
it('should open a new ExternalSourceEntryImportModalComponent', () => { it('should open a new ExternalSourceEntryImportModalComponent', () => {
expect(modalService.open).toHaveBeenCalledWith(ExternalSourceEntryImportModalComponent, jasmine.any(Object)); expect(modalService.open).toHaveBeenCalledWith(ThemedExternalSourceEntryImportModalComponent, jasmine.any(Object));
}); });
}); });
}); });

View File

@@ -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 { SEARCH_CONFIG_SERVICE } from '../../../../../../my-dspace-page/my-dspace-page.component';
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service'; import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@@ -16,7 +16,8 @@ import { PaginationComponentOptions } from '../../../../../pagination/pagination
import { RelationshipOptions } from '../../../models/relationship-options.model'; import { RelationshipOptions } from '../../../models/relationship-options.model';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { ExternalSourceEntryImportModalComponent } from './external-source-entry-import-modal/external-source-entry-import-modal.component'; 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 { SelectableListService } from '../../../../../object-list/selectable-list/selectable-list.service';
import { Item } from '../../../../../../core/shared/item.model'; import { Item } from '../../../../../../core/shared/item.model';
import { Collection } from '../../../../../../core/shared/collection.model'; import { Collection } from '../../../../../../core/shared/collection.model';
@@ -114,9 +115,9 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit
modalRef: NgbModalRef; 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 * The entity types compatible with the given external source
@@ -161,30 +162,40 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit
* @param entry The entry to import * @param entry The entry to import
*/ */
import(entry) { import(entry) {
this.modalRef = this.modalService.open(ExternalSourceEntryImportModalComponent, { this.modalRef = this.modalService.open(ThemedExternalSourceEntryImportModalComponent, {
size: 'lg', size: 'lg',
container: 'ds-dynamic-lookup-relation-modal' container: 'ds-dynamic-lookup-relation-modal'
}); });
const modalComp = this.modalRef.componentInstance;
modalComp.externalSourceEntry = entry; const modalComp$ = this.modalRef.componentInstance.compRef$.pipe(
modalComp.item = this.item; hasValueOperator(),
modalComp.collection = this.collection; map((compRef: ComponentRef<ExternalSourceEntryImportModalComponent>) => compRef.instance)
modalComp.relationship = this.relationship; );
modalComp.label = this.label;
modalComp.relatedEntityType = this.relatedEntityType; this.subs.push(modalComp$.subscribe((modalComp: ExternalSourceEntryImportModalComponent) => {
this.importObjectSub = modalComp.importedObject.subscribe((object) => { 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.selectableListService.selectSingle(this.listId, object);
this.importedObject.emit(object); this.importedObject.emit(object);
}); }));
} }
/** /**
* Unsubscribe from open subscriptions * Unsubscribe from open subscriptions
*/ */
ngOnDestroy(): void { ngOnDestroy(): void {
if (hasValue(this.importObjectSub)) { this.subs
this.importObjectSub.unsubscribe(); .filter((sub) => hasValue(sub))
} .forEach((sub) => sub.unsubscribe());
} }
/** /**

View File

@@ -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<ExternalSourceEntryImportModalComponent> {
protected getComponentName(): string {
return 'ExternalSourceEntryImportModalComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
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<any> {
return import(`./external-source-entry-import-modal.component`);
}
}

View File

@@ -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 { DsDynamicTypeBindRelationService } from './builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service';
import { FormService } from './form.service'; import { FormService } from './form.service';
import { NgxMaskModule } from 'ngx-mask'; 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 = [ const COMPONENTS = [
CustomSwitchComponent, CustomSwitchComponent,
@@ -64,6 +65,7 @@ const COMPONENTS = [
ChipsComponent, ChipsComponent,
NumberPickerComponent, NumberPickerComponent,
VocabularyTreeviewComponent, VocabularyTreeviewComponent,
ThemedExternalSourceEntryImportModalComponent
]; ];
const DIRECTIVES = [ const DIRECTIVES = [

View File

@@ -11,7 +11,7 @@ import {
OnChanges OnChanges
} from '@angular/core'; } from '@angular/core';
import { hasValue, isNotEmpty } from '../empty.util'; 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 { ThemeService } from './theme.service';
import { catchError, switchMap, map } from 'rxjs/operators'; import { catchError, switchMap, map } from 'rxjs/operators';
import { GenericConstructor } from '../../core/shared/generic-constructor'; import { GenericConstructor } from '../../core/shared/generic-constructor';
@@ -25,6 +25,12 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
@ViewChild('vcr', { read: ViewContainerRef }) vcr: ViewContainerRef; @ViewChild('vcr', { read: ViewContainerRef }) vcr: ViewContainerRef;
protected compRef: ComponentRef<T>; protected compRef: ComponentRef<T>;
/**
* A reference to the themed component. Will start as undefined and emit every time the themed
* component is rendered
*/
public compRef$: BehaviorSubject<ComponentRef<T>> = new BehaviorSubject(undefined);
protected lazyLoadSub: Subscription; protected lazyLoadSub: Subscription;
protected themeSub: Subscription; protected themeSub: Subscription;
@@ -90,6 +96,7 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
const factory = this.resolver.resolveComponentFactory(constructor); const factory = this.resolver.resolveComponentFactory(constructor);
this.compRef = this.vcr.createComponent(factory); this.compRef = this.vcr.createComponent(factory);
this.connectInputsAndOutputs(); this.connectInputsAndOutputs();
this.compRef$.next(this.compRef);
this.cdr.markForCheck(); this.cdr.markForCheck();
}); });
} }

View File

@@ -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 {
}

View File

@@ -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 { 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 { 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 { 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 = [ const DECLARATIONS = [
FileSectionComponent, FileSectionComponent,
@@ -168,6 +171,7 @@ const DECLARATIONS = [
BrowseByMetadataPageComponent, BrowseByMetadataPageComponent,
BrowseByDatePageComponent, BrowseByDatePageComponent,
BrowseByTitlePageComponent, BrowseByTitlePageComponent,
ExternalSourceEntryImportModalComponent,
]; ];