import { Component , Input , ViewChild } from '@angular/core' ; import { Router , ActivatedRoute , Params } from '@angular/router' ; import { Subscription } from 'rxjs/Subscription' ; import { ModalDirective } from 'ngx-bootstrap/modal' ; import { DataService } from 'app/services/data.service' ; import { CodelistService } from 'app/services/codelist.service' ; import { ToastService } from 'app/services/toast.service' ; import { ParagraphNamesCodelist } from 'app/shared/schema/codelist' ; import { ChartGroups } from "app/shared/data/chartGroups" ; import { TreeBudget } from 'app/shared/schema' ; @ Component ( { selector : 'expenditure-viz' , host : { '(window:keydown)' : 'hotkeys($event)' } , templateUrl : 'expenditure-viz.component.html' , styleUrls : [ '../../../shared/styles/inc-exp-viz.scss' ] } ) export class ExpenditureVizComponent { profile = { _id : "abc" } ; @ ViewChild ( 'eventReceiptsModal' ) public eventReceiptsModal : ModalDirective ; modalLoaded : boolean = false ; state : { year : number ; group : string ; event : string ; } = { year : null , group : null , event : null } ; events = [ ] ; eventIndex = { } ; groups : any [ ] = [ ] ; groupIndex : any = { } ; paragraphNames : ParagraphNamesCodelist = new ParagraphNamesCodelist ( ) ; hoveredGroup : string = null ; openedGroupList : boolean = true ; maxAmount : number = 0 ; maxBudgetsAmount : number = 0 ; vizScale : number = 1 ; paramsSubscription : Subscription ; constructor ( private router , private route , private dataService , private codelistService , private _toastService ) { this . groups = ChartGroups ; this . groups . forEach ( group => { group . amount = 0 ; group . budgetAmount = 0 ; group . paragraphs = [ ] ; this . groupIndex [ group . id ] = group ; } ) ; } ngOnInit ( ) { this . paramsSubscription = this . route . params . subscribe ( ( params ) => { let newState = { group : this . groupIndex [ params [ "skupina" ] ] ? params [ "skupina" ] : null , year : Number ( params [ "rok" ] ) , event : params [ "akce" ] } ; let oldState = this . state ; this . openedGroupList = ! ! newState . group ; if ( newState . year !== oldState . year && newState . year ) { this . loadData ( this . profile . _id , newState . year ) ; } if ( newState . event !== oldState . event && this . modalLoaded ) { if ( newState . event ) this . eventReceiptsModal . show ( ) ; else this . eventReceiptsModal . hide ( ) ; } this . state = newState ; } ) ; } ngAfterViewInit ( ) { this . modalLoaded = true ; if ( this . state . event ) this . eventReceiptsModal . show ( ) ; else this . eventReceiptsModal . hide ( ) ; } ngOnDestroy ( ) { this . paramsSubscription . unsubscribe ( ) ; } selectBudget ( budget ) { this . updateState ( { year : budget . year } ) ; } selectGroup ( groupId ) { this . updateState ( { group : groupId } ) ; } selectEvent ( eventId ) { this . updateState ( { event : eventId } ) ; } updateState ( setParams ) { var replaceUrl = ! this . state . year ; let params = { rok : "year" in setParams ? setParams . year : this . state . year , skupina : "group" in setParams ? setParams . group : this . state . group , akce : "event" in setParams ? setParams . event : this . state . event } ; Object . keys ( params ) . forEach ( key => { if ( ! params [ key ] ) delete params [ key ] ; } ) ; this . router . navigate ( [ "./" , params ] , { relativeTo : this . route , replaceUrl : replaceUrl } ) ; } /**
        * method to handle left/right arrows to switch the selected group
        */ hotkeys ( event ) { var groupIds = Object . keys ( this . groupIndex ) ; var i = groupIds . indexOf ( this . state . group ) ; if ( event . keyCode == 37 ) this . selectGroup ( groupIds [ i - 1 >= 0 ? i - 1 : groupIds . length - 1 ] ) ; if ( event . keyCode == 39 ) this . selectGroup ( groupIds [ i + 1 <= groupIds . length - 1 ? i + 1 : 0 ] ) ; } string2number ( string ) { if ( string . charAt ( string . length - 1 ) === "-" ) string = "-" + string . substring ( 0 , string . length - 1 ) ; string . replace ( "," , "." ) ; return Number ( string ) ; } getDonutChartData ( paragraph ) { return { amount : paragraph . expenditureAmount , budgetAmount : paragraph . budgetExpenditureAmount } ; } loadData ( profileId , year ) { let queue = [ ] ; queue . push ( this . codelistService . getCodelist ( "paragraph-names" , new Date ( year , 0 , 1 ) ) ) ; queue . push ( this . dataService . getProfileBudget ( profileId , year ) ) ; queue . push ( this . dataService . getProfileEvents ( profileId , { year : year } ) ) ; Promise . all ( queue ) . then ( values => this . setData ( values [ 0 ] , values [ 1 ] , values [ 2 ] ) ) . catch ( ( err ) => { switch ( err . status ) { case 404 : this . _toastService . toast ( "Data nejsou k dispozici" , "warning" ) ; return ; case 503 : this . _toastService . toast ( "Služba je momentálně nedostupná" , "warning" ) ; return ; default : console . error ( err ) ; this . _toastService . toast ( "Nastala neočekávaná chyba " + err , "error" ) ; } } ) ; } setData ( paragraphNames , budget , events ) { this . paragraphNames = paragraphNames ? paragraphNames : { } ; let eventIndex = { } ; events . forEach ( event => eventIndex [ event . _id ] = event ) ; this . groups . forEach ( group => { group . amount = 0 ; group . budgetAmount = 0 ; group . paragraphs = [ ] ; } ) ; budget . paragraphs . forEach ( paragraph => { let groupId = String ( paragraph . id ) . substring ( 0 , 2 ) ; let group = this . groupIndex [ groupId ] ; if ( ! group ) return ; let eventAmount = 0 ; let eventBudgetAmount = 0 ; paragraph . events . forEach ( event => { event . name = eventIndex [ event . event ] && eventIndex [ event . event ] . name ? eventIndex [ event . event ] . name : ( "Nepojmenovaná akce (č. " + event . event + ")" ) ; eventAmount += event . expenditureAmount ; eventBudgetAmount += event . budgetExpenditureAmount ; } ) ; paragraph . events . sort ( ( a , b ) => a . name && b . name ? a . name . localeCompare ( b . name ) : - 1 ) ; if ( paragraph . expenditureAmount !== eventAmount || paragraph . budgetExpenditureAmount !== eventBudgetAmount ) { paragraph . events . push ( { event : undefined , name : "Ostatní" , incomeAmount : 0 , budgetIncomeAmount : 0 , expenditureAmount : paragraph . expenditureAmount - eventAmount , budgetExpenditureAmount : paragraph . budgetExpenditureAmount - eventBudgetAmount } ) ; } group . budgetAmount += paragraph . budgetExpenditureAmount ; group . amount += paragraph . expenditureAmount ; group . paragraphs . push ( paragraph ) ; } ) ; this . maxAmount = 0 ; this . groups . forEach ( group => { this . maxAmount = Math . max ( this . maxAmount , group . budgetAmount , group . amount ) ; } ) ; } sortEvents ( ) { } }