import { ChangeDetectionStrategy , Component , DoCheck , Input , IterableDiffer , IterableDiffers , OnDestroy , OnInit , } from '@angular/core' ; import { AbstractControl , FormControl , FormGroup , Validators } from '@angular/forms' ; import { TypeBuilderStepComponent } from '../type-builder-step.component' ; import { ReplaySubject } from 'rxjs' ; import { CmdbType } from '../../../models/cmdb-type' ; import { takeUntil } from 'rxjs/operators' ; function occurrences ( s , subString ) { s += '' ; subString += '' ; if ( subString . length <= 0 ) { return ( s . length + 1 ) ; } let n = 0 ; let pos = 0 ; while ( true ) { pos = s . indexOf ( subString , pos ) ; if ( pos >= 0 ) { ++ n ; pos += 1 ; } else { break ; } } return n ; } @ Component ( { selector : 'cmdb-type-meta-step' , templateUrl : './type-meta-step.component.html' , styleUrls : [ './type-meta-step.component.scss' ] , changeDetection : ChangeDetectionStrategy . OnPush } ) export class TypeMetaStepComponent extends TypeBuilderStepComponent implements DoCheck , OnInit , OnDestroy { private subscriber : ReplaySubject < void > = new ReplaySubject < void > ( ) ; public summaryForm : FormGroup ; public externalsForm : FormGroup ; public hasInter : boolean = false ; public fields : Array < any > = [ ] ; public summaries : Array < any > = [ ] ; private iterableDiffer : IterableDiffer < any > ; @ Input ( 'typeInstance' ) public set TypeInstance ( instance ) { if ( instance ) { this . typeInstance = instance ; this . summaries = [ ... this . typeInstance . fields ] ; this . fields = [ { label : 'Object ID' , name : 'object_id' } , ... this . typeInstance . fields ] ; this . summaryForm . patchValue ( this . typeInstance . render_meta . summary ) ; this . externalsForm . get ( 'name' ) . setValidators ( this . listNameValidator ( ) ) ; } } constructor ( private iterableDiffers ) { super ( ) ; this . iterableDiffer = iterableDiffers . find ( [ ] ) . create ( null ) ; this . summaryForm = new FormGroup ( { fields : new FormControl ( '' , Validators . required ) } ) ; this . externalsForm = new FormGroup ( { name : new FormControl ( '' , [ Validators . required ] ) , label : new FormControl ( '' , Validators . required ) , icon : new FormControl ( '' ) , href : new FormControl ( '' , [ Validators . required ] ) , fields : new FormControl ( '' ) } ) ; } public ngOnDestroy ( ) { this . subscriber . next ( ) ; this . subscriber . complete ( ) ; } public get external_name ( ) { return this . externalsForm . get ( 'name' ) ; } public get external_label ( ) { return this . externalsForm . get ( 'label' ) ; } public listNameValidator ( ) { return ( control ) : { [ key ] : any ; } | null => { const nameInList = this . typeInstance . render_meta . externals . find ( el => el . name === control . value ) ; return nameInList ? { nameAlreadyTaken : { value : control . value } } : null ; } ; } public ngOnInit ( ) { this . externalsForm . get ( 'name' ) . valueChanges . pipe ( takeUntil ( this . subscriber ) ) . subscribe ( val => { if ( this . externalsForm . get ( 'name' ) . value !== null ) { this . externalsForm . get ( 'label' ) . setValue ( val . charAt ( 0 ) . toUpperCase ( ) + val . toString ( ) . slice ( 1 ) ) ; this . externalsForm . get ( 'label' ) . markAsDirty ( { onlySelf : true } ) ; this . externalsForm . get ( 'label' ) . markAsTouched ( { onlySelf : true } ) ; } } ) ; this . externalsForm . get ( 'href' ) . valueChanges . pipe ( takeUntil ( this . subscriber ) ) . subscribe ( ( href ) => { this . hasInter = occurrences ( href , '{}' ) > 0 ; } ) ; } public get summaryFields ( ) : FormControl { return this . summaryForm . get ( 'fields' ) as FormControl ; } public addExternal ( ) { this . typeInstance . render_meta . externals . push ( this . externalsForm . value ) ; this . externalsForm . reset ( ) ; this . externalsForm . get ( 'icon' ) . setValue ( 'fas fa-external-link-alt' ) ; } public editExternal ( data ) { const rawExternalData = this . typeInstance . render_meta . externals [ this . typeInstance . render_meta . externals . indexOf ( data ) ] ; this . externalsForm . reset ( ) ; this . deleteExternal ( data ) ; this . externalsForm . patchValue ( rawExternalData ) ; } public deleteExternal ( data ) { const index = this . typeInstance . render_meta . externals . indexOf ( data ) ; if ( index !== - 1 ) { this . typeInstance . render_meta . externals . splice ( index , 1 ) ; } } public ngDoCheck ( ) { const changes = this . iterableDiffer . diff ( this . typeInstance . fields ) ; if ( changes ) { let summaries = this . summaryFields . value ; changes . forEachRemovedItem ( record => { summaries = summaries . filter ( f => f !== record . item . name ) ; } ) ; this . summaries = [ ... this . typeInstance . fields ] ; this . fields = [ { label : 'Object ID' , name : 'object_id' } , ... this . typeInstance . fields ] ; this . typeInstance . render_meta . summary . fields = summaries ; this . summaryFields . patchValue ( summaries ) ; } } public onSummaryChange ( fields ) { this . typeInstance . render_meta . summary . fields = fields . map ( f => f . name ) ; } }