import { Component , OnDestroy , OnInit } from '@angular/core' ; import { BehaviorSubject , forkJoin , Observable , ReplaySubject } from 'rxjs' ; import { CmdbCategory , CmdbCategoryNode , CmdbCategoryTree } from '../models/cmdb-category' ; import { CategoryService } from '../services/category.service' ; import { CmdbMode } from '../modes.enum' ; import { ActivatedRoute , Data , Router } from '@angular/router' ; import { SidebarService } from '../../layout/services/sidebar.service' ; import { takeUntil } from 'rxjs/operators' ; import { APIGetMultiResponse } from '../../services/models/api-response' ; import { CollectionParameters } from '../../services/models/api-parameter' ; import { Column , Sort , SortDirection , TableState , TableStatePayload } from '../../layout/table/table.types' ; 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-category' , templateUrl : './category.component.html' , styleUrls : [ './category.component.scss' ] } ) export class CategoryComponent implements OnInit , OnDestroy { /**
     * HTML ID of the table.
     * Used for user settings and table-states
     */ public readonly id : string = 'category-list-table' ; /**
     * Global unsubscriber for http calls to the rest backend.
     */ private unSubscribe : ReplaySubject < void > = new ReplaySubject ( ) ; /**
     * Current category collection
     */ public categories : Array < CmdbCategory > ; public categoriesAPIResponse : APIGetMultiResponse < CmdbCategory > ; /**
     * Root element of the category tree
     */ public categoryTree : CmdbCategoryTree ; /**
     * Current display mode
     */ private displayMode : Observable < CmdbMode > ; /**
     * Current display mode subject
     */ private displayModeSubject : BehaviorSubject < CmdbMode > = new BehaviorSubject < CmdbMode > ( CmdbMode . View ) ; /**
     * Table datas
     */ public apiParameters : CollectionParameters = { limit : 10 , sort : 'public_id' , order : - 1 , page : 1 } ; public tableColumns : Array < Column > ; public totalResults : number = 0 ; /**
     * Default sort filter.
     */ public sort : Sort = { name : 'public_id' , order : SortDirection . DESCENDING } as Sort ; public tableStateSubject : BehaviorSubject < TableState > = new BehaviorSubject < TableState > ( undefined ) ; public tableStates : Array < TableState > = [ ] ; public get tableState ( ) : TableState { return this . tableStateSubject . getValue ( ) as TableState ; } constructor ( private categoryService , private route , private sidebarService , private router , private userSettingsService , private indexDB ) { this . categories = [ ] ; this . displayMode = this . displayModeSubject . asObservable ( ) ; this . displayModeSubject . next ( this . route . snapshot . data . mode ) ; this . route . data . pipe ( takeUntil ( this . unSubscribe ) ) . subscribe ( ( data ) => { if ( data . userSetting ) { const userSettingPayloads = ( data . userSetting as UserSetting < TableStatePayload > ) . payloads . find ( payloads => payloads . id === this . id ) ; this . tableStates = userSettingPayloads . tableStates ; this . tableStateSubject . next ( userSettingPayloads . currentState ) ; } else { this . tableStates = [ ] ; this . tableStateSubject . next ( undefined ) ; const statePayload = new TableStatePayload ( this . id , [ ] ) ; const resource = convertResourceURL ( this . router . url . toString ( ) ) ; const userSetting = this . userSettingsService . createUserSetting < TableStatePayload > ( resource , [ statePayload ] ) ; this . indexDB . addSetting ( userSetting ) ; } } ) ; } private tableColumnBuilder ( ) { const publicColumn = { display : 'Public ID' , name : 'public_id' , data : 'public_id' , cssClasses : [ 'text-center' ] , style : { 'white-space' : 'nowrap' } , searchable : false , sortable : true } as unknown as Column ; const nameColumn = { display : 'Name' , name : 'name' , data : 'name' , cssClasses : [ 'text-center' ] , searchable : false , sortable : true } as unknown as Column ; const labelColumn = { display : 'Label' , name : 'label' , data : 'label' , cssClasses : [ 'text-center' ] , searchable : false , sortable : true } as unknown as Column ; const parentColumn = { display : 'Parent ID' , name : 'parent' , data : 'parent' , cssClasses : [ 'text-center' ] , style : { 'white-space' : 'nowrap' } , searchable : false , sortable : true } as unknown as Column ; this . tableColumns = [ publicColumn , labelColumn , nameColumn , parentColumn ] ; this . initTable ( ) ; } private private initTable ( ) { if ( this . tableState ) { this . sort = this . tableState . sort ; this . apiParameters . sort = this . sort . name ; this . apiParameters . order = this . sort . order ; this . apiParameters . page = this . tableState . page ; this . apiParameters . limit = this . tableState . pageSize ; } } /**
     * Load categories from the backend.
     */ private loadCategories ( ) { this . categoryService . getCategories ( this . apiParameters ) . pipe ( takeUntil ( this . unSubscribe ) ) . subscribe ( ( response ) => { this . categoriesAPIResponse = response ; this . categories = this . categoriesAPIResponse . results ; this . totalResults = response . total ; } ) ; } /**
     * Load category tree from the backend.
     */ private loadCategoryTree ( ) { this . displayMode . subscribe ( ( ) => { this . sidebarService . categoryTree . asObservable ( ) . pipe ( takeUntil ( this . unSubscribe ) ) . subscribe ( ( categoryTree ) => { this . categoryTree = categoryTree ; } ) ; } ) ; } /**
     * Will generate all needed data for cmdb-table.
     */ private dataLoader ( ) { this . tableColumnBuilder ( ) ; this . loadCategoryTree ( ) ; this . loadCategories ( ) ; } public ngOnInit ( ) { this . dataLoader ( ) ; } param sort public onSortChange ( sort ) { this . sort = sort ; this . apiParameters . sort = sort . name ; this . apiParameters . order = sort . order ; this . loadCategories ( ) ; } /**
     * On table state reset.
     * Resets the table state
     */ public onStateReset ( ) { this . sort = { name : 'public_id' , order : SortDirection . DESCENDING } as Sort ; this . apiParameters . sort = this . sort . name ; this . apiParameters . order = this . sort . order ; this . apiParameters . limit = 10 ; this . apiParameters . page = 1 ; } param state public onStateSelect ( state ) { this . tableStateSubject . next ( state ) ; this . apiParameters . page = this . tableState . page ; this . apiParameters . limit = this . tableState . pageSize ; this . sort = this . tableState . sort ; for ( const col of this . tableColumns ) { col . hidden = ! this . tableState . visibleColumns . includes ( col . name ) ; } this . loadCategories ( ) ; } param page public onPageChange ( page ) { this . apiParameters . page = page ; this . loadCategories ( ) ; } param limit public onPageSizeChange ( limit ) { this . apiParameters . limit = limit ; this . loadCategories ( ) ; } public ngOnDestroy ( ) { this . unSubscribe . next ( ) ; this . unSubscribe . complete ( ) ; } public get mode ( ) : CmdbMode { return this . displayModeSubject . getValue ( ) ; } /**
     * Rest caller updates every category in tree
     */ public onSave ( ) { const observers = this . saveTree ( this . categoryTree ) ; forkJoin ( observers ) . subscribe ( ( ) => { this . sidebarService . loadCategoryTree ( ) ; this . dataLoader ( ) ; } ) ; } param root param parentNode private saveTree ( root , parentNode ? ) { let observers = [ ] ; for ( let i = 0 ; i < root . length ; i ++ ) { const node = root [ i ] ; node . category . meta . order = i + 1 ; if ( parentNode ) { node . category . parent = parentNode . category . public_id ; } if ( ! parentNode && node . category . parent !== null ) { node . category . parent = null ; } observers . push ( this . categoryService . updateCategory ( node . category ) ) ; if ( node . children . length > 0 ) { observers = observers . concat ( this . saveTree ( node . children , node ) ) ; } } return observers ; } public onTreeChange ( ) { this . sidebarService . loadCategoryTree ( ) ; this . dataLoader ( ) ; } }