import { Component , Input , OnDestroy , OnInit , TemplateRef , ViewChild } from '@angular/core' ; import { RenderResult } from '../../../../models/cmdb-render' ; import { BehaviorSubject , ReplaySubject , Subject } from 'rxjs' ; import { Column , Sort , SortDirection , TableState , TableStatePayload } from '../../../../../layout/table/table.types' ; import { APIGetMultiResponse } from '../../../../../services/models/api-response' ; import { SupportedExporterExtension } from '../../../../../export/export-objects/model/supported-exporter-extension' ; import { ObjectService } from '../../../../services/object.service' ; import { DatePipe } from '@angular/common' ; import { FileSaverService } from 'ngx-filesaver' ; import { FileService } from '../../../../../export/export.service' ; import { CollectionParameters } from '../../../../../services/models/api-parameter' ; import { takeUntil } from 'rxjs/operators' ; import { ActivatedRoute , Data , Router } from '@angular/router' ; import { UserSetting } from '../../../../../management/user-settings/models/user-setting' ; import { convertResourceURL , UserSettingsService } from '../../../../../management/user-settings/services/user-settings.service' ; import { UserSettingsDBService } from '../../../../../management/user-settings/services/user-settings-db.service' ; @ Component ( { selector : 'cmdb-object-references-by-type' , templateUrl : './object-references-by-type.component.html' , styleUrls : [ './object-references-by-type.component.scss' ] } ) export class ObjectReferencesByTypeComponent implements OnInit , OnDestroy { /**
     * Table Template: active column.
     */ @ ViewChild ( 'activeTemplate' , { static : true } ) activeTemplate : TemplateRef < any > ; /**
     * Table Template: Type name column.
     */ @ ViewChild ( 'typeNameTemplate' , { static : true } ) typeNameTemplate : TemplateRef < any > ; /**
     * Table Template: Link action column.
     */ @ ViewChild ( 'actionTemplate' , { static : true } ) actionTemplate : TemplateRef < any > ; /**
     * Table Template: reference column.
     */ @ ViewChild ( 'referenceType' , { static : true } ) referenceType : TemplateRef < any > ; /**
     * Table Template: export button column.
     */ @ ViewChild ( 'exportButtonTemplate' , { static : true } ) exportButtonTemplate : TemplateRef < any > ; /**
     * Global un-subscriber for http calls to the rest backend.
     */ private subscriber : ReplaySubject < void > = new ReplaySubject < void > ( ) ; /**
     * ID of the referenced object.
     */ @ Input ( ) publicID : number ; /**
     * ID of the type for which the results will be filtered
     */ @ Input ( ) typeID : number ; /**
     * Listener to the initialization of this component
     */ @ Input ( ) initSubject : Subject < number > ; /**
     * The Id used for the table
     */ @ Input ( ) id : string ; /**
     * Table columns definition.
     */ public columns : Array < Column > ; public refererObjects : Array < RenderResult > = [ ] ; public refererAPIResponse : APIGetMultiResponse < RenderResult > ; public totalReferer : number = 0 ; /**
     * Referer selection.
     */ public selectedObjects : Array < RenderResult > = [ ] ; public selectedObjectIDs : Array < number > = [ ] ; private private readonly initLimit : number = 10 ; public limit : number = this . initLimit ; /**
     * Begin with first page.
     */ public readonly initPage : number = 1 ; public page : number = this . initPage ; /**
     * Filter parameter from table search
     */ public filter : string ; /**
     * Default sort filter.
     */ public sort : Sort = { name : 'public_id' , order : SortDirection . DESCENDING } as Sort ; /**
     * Loading indicator.
     */ public loading : boolean = false ; /**
     * Possible export formats.
     */ public formatList : Array < SupportedExporterExtension > = [ ] ; public tableStateSubject : BehaviorSubject < TableState > = new BehaviorSubject < TableState > ( undefined ) ; public tableStates : Array < TableState > = [ ] ; public get tableState ( ) : TableState { return this . tableStateSubject . getValue ( ) as TableState ; } constructor ( private objectService , private datePipe , private fileSaverService , private fileService , private route , private router , private userSettingsService , private indexDB ) { this . fileService . callFileFormatRoute ( ) . subscribe ( data => { this . formatList = data ; } ) ; } public ngOnInit ( ) { this . route . data . pipe ( takeUntil ( this . subscriber ) ) . subscribe ( ( data ) => { if ( data . userSetting ) { const userSettingPayloads = ( data . userSetting as UserSetting < TableStatePayload > ) . payloads . find ( payloads => payloads . id === this . id ) ; if ( ! userSettingPayloads ) { const payloads = ( data . userSetting as UserSetting < TableStatePayload > ) . payloads ; const statePayload = new TableStatePayload ( this . id , [ ] ) ; payloads . push ( statePayload ) ; const resource = convertResourceURL ( this . router . url . toString ( ) ) ; const userSetting = this . userSettingsService . createUserSetting < TableStatePayload > ( resource , payloads ) ; this . indexDB . updateSetting ( userSetting ) ; this . tableStates = statePayload . tableStates ; this . tableStateSubject . next ( statePayload . currentState ) ; } else { this . tableStates = userSettingPayloads . tableStates ; this . tableStateSubject . next ( userSettingPayloads . currentState ) ; } } } ) ; this . columns = [ { display : 'Active' , name : 'active' , data : 'object_information.active' , sortable : true , template : this . activeTemplate , cssClasses : [ 'text-center' ] , style : { width : '6rem' } } , { display : 'Public ID' , name : 'public_id' , data : 'object_information.object_id' , sortable : true } , { display : 'Reference Type' , name : 'reference_type' , sortable : false , searchable : false , template : this . referenceType } , { display : 'Type' , name : 'type_id' , data : 'type_information.type_name' , sortable : true , template : this . typeNameTemplate , } , { display : 'Summary' , name : 'summary' , data : 'summary_line' , sortable : false } , { display : 'Creation Time' , name : 'creation_time' , data : 'object_information.creation_time' , sortable : true , searchable : false , render ( data ) { const date = new Date ( data ) ; return new DatePipe ( 'en-US' ) . transform ( date , 'dd/MM/yyyy - hh:mm:ss' ) . toString ( ) ; } } , { display : 'Actions' , name : 'actions' , data : 'object_information.object_id' , template : this . actionTemplate , sortable : false , fixed : true , cssClasses : [ 'text-center' ] , cellClasses : [ 'actions-buttons' ] , style : { width : '6rem' } } , ] as Array < Column > ; const subscription = this . initSubject . subscribe ( ( event ) => { if ( event === this . typeID ) { this . initTable ( ) ; this . loadObjectsFromAPI ( ) ; subscription . unsubscribe ( ) ; } } ) ; } /**
     * Initialize table state
     */ private initTable ( ) { if ( this . tableState ) { this . sort = this . tableState . sort ; this . limit = this . tableState . pageSize ; this . page = this . tableState . page ; } } private private loadObjectsFromAPI ( ) { this . loading = true ; const filter = this . filterBuilder ( this . columns ) ; const params = { filter , limit : this . limit , sort : this . sort . name , order : this . sort . order , page : this . page } ; this . objectService . getObjectReferences ( this . publicID , params ) . pipe ( takeUntil ( this . subscriber ) ) . subscribe ( ( apiResponse ) => { this . refererAPIResponse = apiResponse ; this . refererObjects = apiResponse . results as Array < RenderResult > ; this . totalReferer = apiResponse . total ; this . loading = false ; } ) ; } param columns Array are taken into account in the query.
     *  return query  {@link: any[]} private filterBuilder ( columns ) { const query = [ ] ; query . push ( { $match : { type_id : this . typeID } } ) ; if ( this . filter ) { const or = [ ] ; for ( const column of columns ) { const regex = { } ; regex [ column . name ] = { $regex : String ( this . filter ) , $options : 'ismx' } ; or . push ( regex ) ; } query . push ( { $lookup : { from : 'framework.objects' , localField : 'fields.value' , foreignField : 'public_id' , as : 'data' } } ) ; query . push ( { $project : { _id : 1 , public_id : 1 , type_id : 1 , active : 1 , author_id : 1 , creation_time : 1 , last_edit_time : 1 , fields : 1 , simple : { $reduce : { input : '$data.fields' , initialValue : [ ] , in : { $setUnion : [ '$$value' , '$$this' ] } } } } } ) ; query . push ( { $group : { _id : '$_id' , public_id : { $first : '$public_id' } , type_id : { $first : '$type_id' } , active : { $first : '$active' } , author_id : { $first : '$author_id' } , creation_time : { $first : '$creation_time' } , last_edit_time : { $first : '$last_edit_time' } , fields : { $first : '$fields' } , simple : { $first : '$simple' } , } } ) ; query . push ( { $project : { _id : '$_id' , public_id : 1 , type_id : 1 , active : 1 , author_id : 1 , creation_time : 1 , last_edit_time : 1 , fields : 1 , references : { $setUnion : [ '$fields' , '$simple' ] } , } } ) ; query . push ( { $addFields : { creationString : { $dateToString : { format : '%Y-%m-%dT%H:%M:%S.%LZ' , date : '$creation_time' } } } } ) ; query . push ( { $addFields : { editString : { $dateToString : { format : '%Y-%m-%dT%H:%M:%S.%LZ' , date : '$last_edit_time' } } } } ) ; query . push ( { $addFields : { references : { $map : { input : '$references' , as : 'new_fields' , in : { $cond : [ { $eq : [ { $type : '$$new_fields.value' } , 'date' ] } , { name : '$$new_fields.name' , value : { $dateToString : { format : '%Y-%m-%dT%H:%M:%S.%LZ' , date : '$$new_fields.value' } } } , { name : '$$new_fields.name' , value : '$$new_fields.value' } ] } } } } } ) ; query . push ( { $addFields : { public_id : { $toString : '$public_id' } } } ) ; or . push ( { public_id : { $elemMatch : { value : { $regex : String ( this . filter ) , $options : 'ism' } } } } ) ; or . push ( { creationString : { $regex : String ( this . filter ) , $options : 'ims' } } ) ; or . push ( { editString : { $regex : String ( this . filter ) , $options : 'ims' } } ) ; or . push ( { references : { $elemMatch : { value : { $regex : String ( this . filter ) , $options : 'ism' } } } } ) ; query . push ( { $match : { $or : or } } ) ; } return query ; } param search public onSearchChange ( search ) { this . page = this . initPage ; if ( search ) { this . filter = search ; } else { this . filter = undefined ; } this . loadObjectsFromAPI ( ) ; } param sort public onSortChange ( sort ) { this . sort = sort ; this . loadObjectsFromAPI ( ) ; } param page public onPageChange ( page ) { this . page = page ; this . loadObjectsFromAPI ( ) ; } param limit public onPageSizeChange ( limit ) { this . limit = limit ; this . loadObjectsFromAPI ( ) ; } param state public onStateSelect ( state ) { this . tableStateSubject . next ( state ) ; this . page = this . tableState . page ; this . limit = this . tableState . pageSize ; this . sort = this . tableState . sort ; this . loadObjectsFromAPI ( ) ; } public onStateReset ( ) { this . sort = { name : 'public_id' , order : SortDirection . DESCENDING } as Sort ; this . limit = this . initLimit ; this . page = this . initPage ; this . loadObjectsFromAPI ( ) ; } param selectedItems public onSelectedChange ( selectedItems ) { this . selectedObjects = selectedItems ; this . selectedObjectIDs = selectedItems . map ( t => t . object_information . object_id ) ; } param see public exportingFiles ( see ) { const filter = { public_id : { $in : this . selectedObjectIDs } } ; const optional = { classname : see . extension } ; const exportAPI = { filter , optional , order : this . sort . order , sort : this . sort . name } ; if ( this . selectedObjects . length !== 0 ) { this . fileService . callExportRoute ( exportAPI ) . subscribe ( res => this . downLoadFile ( res , see . label ) ) ; } } param data public downLoadFile ( data , label ) { const timestamp = this . datePipe . transform ( new Date ( ) , 'MM_dd_yyyy_hh_mm_ss' ) ; this . fileSaverService . save ( data . body , timestamp + '.' + label ) ; } /**
     * Unsubscribe all on component destroy.
     */ public ngOnDestroy ( ) { this . subscriber . next ( ) ; this . subscriber . complete ( ) ; } }