import { ElementRef , Inject , Injectable , InjectionToken , Renderer2 , RendererFactory2 } from '@angular/core' ; import * as _ from 'lodash' ; import { NodeUtils , OF_ATTR } from './node.utils' ; export interface UsedConceptsConfig { [ conceptAlias ] : { config : any ; } ; } export const USED_CONCEPTS_CONFIG = new InjectionToken < string > ( 'usedConceptsConfig' ) ; export abstract class ConfigService { abstract getConfig ( ) ; } class AppConfigService extends ConfigService { constructor ( private readonly usedConceptsConfig , protected readonly forNode ) { super ( ) ; } getConfig ( ) { const alias = this . getConceptAlias ( ) ; const usedConcept = _ . get ( this . usedConceptsConfig , alias ) ; if ( usedConcept === undefined ) { throw new Error ( `Concept ${ alias } not found` ) ; } return usedConcept . config ; } protected getConceptAlias ( ) { return NodeUtils . GetConceptAliasOfNode ( this . forNode . nativeElement ) ; } } class DesignerConfigService extends AppConfigService { constructor ( usedConceptsConfig , protected readonly forNode , private readonly renderer ) { super ( usedConceptsConfig , forNode ) ; } /**
     * The designer will always set the dvOf attribute on the element
     * which is an ancestor of the concept component.
     *
     * Note that this assumes a concept component that cares about the config
     *   is never used in another concept component.
     */ protected getConceptAlias ( ) { let dvOf ; NodeUtils . WalkUpFromNode ( this . forNode . nativeElement , this . renderer , ( ) => ! ! dvOf , ( node ) => { dvOf = NodeUtils . GetAttribute ( node , OF_ATTR ) ; } ) ; if ( ! dvOf ) { const fqtag = NodeUtils . GetFqTagOfNode ( this . forNode . nativeElement ) ; throw new Error ( `In designer, dvOf for ${ fqtag } not found` ) ; } return dvOf ; } } @ Injectable ( ) export class ConfigServiceFactory { private readonly renderer : Renderer2 ; constructor ( @ Inject ( USED_CONCEPTS_CONFIG ) private readonly usedConceptsConfig , rendererFactory ) { this . renderer = rendererFactory . createRenderer ( null , null ) ; } createConfigService ( forNode ) { if ( window [ 'dv-designer' ] ) { return new DesignerConfigService ( this . usedConceptsConfig , forNode , this . renderer ) ; } return new AppConfigService ( this . usedConceptsConfig , forNode ) ; } }