import * as React from 'react' ; import { IChartControlState , IChartControlProps } from '.' ; import styles from './ChartControl.module.scss' ; import { css } from 'office-ui-fabric-react/lib/Utilities' ; import { Chart , ChartSize } from 'chart.js' ; import { PaletteGenerator } from './PaletteGenerator' ; import { AccessibleChartTable } from './AccessibleChartTable' ; import * as telemetry from '../../common/telemetry' ; import { ChartPalette } from './ChartControl.types' ; import { ThemeColorHelper } from '../../common/utilities/ThemeColorHelper' ; interface Window { __themeState__ : any ; } declare var window ; export class ChartControl extends React . Component < IChartControlProps , IChartControlState > { /**
     * Sets default properties
     */ public static defaultProps : Partial < IChartControlProps > = { accessibility : { enable : true } , useTheme : true , palette : ChartPalette . OfficeColorful1 , options : { responsive : true , maintainAspectRatio : true } } ; /**
     * The ChartJs instance
     */ private _chart : Chart ; /**
     * The canvas element that will host the chart
     */ private _canvasElem : HTMLCanvasElement = undefined ; constructor ( props ) { super ( props ) ; telemetry . track ( 'ReactChartComponent' , { type : ! ! props . type , className : ! ! props . className , palette : ! ! props . palette , accessibility : ! ! props . accessibility . enable } ) ; this . state = { isLoading : false , rejected : undefined , data : undefined } ; } /**
     * componentDidMount lifecycle hook
     */ public componentDidMount ( ) { if ( this . props . datapromise ) { this . _doPromise ( this . props . datapromise ) ; } else { this . _initChart ( this . props , this . props . data ) ; } } param nextProps public componentWillReceiveProps ( nextProps ) { if ( nextProps . datapromise !== this . props . datapromise ) { this . setState ( { isLoading : false } ) ; this . _doPromise ( nextProps . datapromise ) ; } else { this . _destroyChart ( ) ; this . _initChart ( nextProps , this . props . data ) ; } } /**
     * componentWillUnmount lifecycle hook
     */ public componentWillUnmount ( ) { this . _destroyChart ( ) ; } param nextProps param nextState public shouldComponentUpdate ( nextProps , nextState ) { const { data , options , plugins , className , accessibility , useTheme , palette } = this . props ; return data !== nextProps . data || options !== nextProps . options || plugins !== nextProps . plugins || className !== nextProps . className || useTheme !== nextProps . useTheme || palette !== nextProps . palette || accessibility !== nextProps . accessibility ; } /**
     * Default React render method
     */ public render ( ) { const { type , accessibility , useTheme , options , data } = this . props ; if ( this . state . isLoading ) { if ( this . props . loadingtemplate ) { if ( typeof this . props . loadingtemplate === "function" ) { return this . props . loadingtemplate ( ) ; } else { return this . props . loadingtemplate ; } } } if ( this . state . rejected ) { if ( this . props . rejectedtemplate ) { if ( typeof this . props . rejectedtemplate === "function" ) { return this . props . rejectedtemplate ( this . state . rejected ) ; } else { return this . props . rejectedtemplate ; } } } const alternateText = accessibility ! . alternateText ; return ( < div className = { css ( styles . chartComponent , ( useTheme ? styles . themed : null ) , this . props . className ) } > < canvas ref = { this . _linkCanvas } role = 'img' aria - label = { alternateText } /> { accessibility . enable === undefined || accessibility . enable ? ( < AccessibleChartTable chartType = { type } data = { data || this . state . data } chartOptions = { options } className = { accessibility . className } caption = { accessibility . caption } summary = { accessibility . summary } onRenderTable = { accessibility . onRenderTable } / > ) : null } < /div>); } public update ( config ? ) { this . _chart . update ( config ) ; } public renderChart ( config ) { this . _chart . render ( config ) ; } public stop ( ) { this . _chart . stop ( ) ; } public clear ( ) { this . _chart . clear ( ) ; } public toBase64Image ( ) { return this . _chart . toBase64Image ( ) ; } public getChart ( ) { return this . _chart ; } public getCanvas ( ) { return this . _chart . canvas ; } public getDatasetAtEvent ( e ) { return this . getChart ( ) . getDatasetAtEvent ( e ) ; } public getElementAtEvent ( e ) { return this . getChart ( ) . getElementAtEvent ( e ) ; } public getElementsAtEvent ( e ) { return this . getChart ( ) . getElementsAtEvent ( e ) ; } private _initChart ( props , data ) { const { options , type , plugins , useTheme } = props ; if ( this . props . onClick !== undefined ) { if ( options . onClick === undefined ) { options . onClick = this . props . onClick ; } } if ( this . props . onHover !== undefined ) { if ( options . onHover === undefined ) { options . onHover = ( event , activeElements ) => { this . props . onHover ( this . getChart ( ) , event , activeElements ) ; } ; } } if ( this . props . onResize !== undefined ) { if ( options . onResize === undefined ) { options . onResize = ( newSize ) => { this . props . onResize ( this . getChart ( ) , newSize ) ; } ; } } this . _applyDatasetPalette ( data ) ; if ( useTheme ) { this . _applyChartThemes ( ) ; } this . _chart = new Chart ( this . _canvasElem , { type : type , data : data , options : options , plugins : plugins } ) ; } private _applyDatasetPalette ( data ) { try { let datasets = data . datasets ; if ( datasets !== undefined ) { datasets . forEach ( dataset => { if ( dataset . backgroundColor === undefined ) { const datasetLength = dataset ! . data ! . length ; if ( datasetLength ) { dataset . backgroundColor = PaletteGenerator . GetPalette ( this . props . palette , datasetLength ) ; } } } ) ; } } catch ( error ) { } } private _applyChartThemes ( ) { try { Chart . defaults . global . defaultFontColor = ThemeColorHelper . GetThemeColor ( styles . defaultFontColor ) ; Chart . defaults . global . defaultFontFamily = styles . defaultFontFamily ; Chart . defaults . global . defaultFontSize = this . _getFontSizeNumber ( styles . defaultFontSize ) ; Chart . defaults . global . title . fontColor = ThemeColorHelper . GetThemeColor ( styles . titleColor ) ; Chart . defaults . global . title . fontFamily = styles . titleFont ; Chart . defaults . global . title . fontSize = this . _getFontSizeNumber ( styles . titleFontSize ) ; Chart . defaults . global . legend . labels . fontColor = ThemeColorHelper . GetThemeColor ( styles . legendColor ) ; Chart . defaults . global . legend . labels . fontFamily = styles . legendFont ; Chart . defaults . global . legend . labels . fontSize = this . _getFontSizeNumber ( styles . legendFontSize ) ; Chart . defaults . global . tooltips . backgroundColor = ThemeColorHelper . GetThemeColor ( styles . tooltipBackgroundColor ) ; Chart . defaults . global . tooltips . bodyFontColor = ThemeColorHelper . GetThemeColor ( styles . tooltipBodyColor ) ; Chart . defaults . global . tooltips . bodyFontFamily = styles . tooltipFont ; Chart . defaults . global . tooltips . bodyFontSize = this . _getFontSizeNumber ( styles . tooltipFontSize ) ; Chart . defaults . global . tooltips . titleFontColor = ThemeColorHelper . GetThemeColor ( styles . tooltipTitleColor ) ; Chart . defaults . global . tooltips . titleFontFamily = styles . tooltipTitleFont ; Chart . defaults . global . tooltips . titleFontSize = this . _getFontSizeNumber ( styles . tooltipTitleFontSize ) ; Chart . defaults . global . tooltips . footerFontColor = ThemeColorHelper . GetThemeColor ( styles . tooltipFooterColor ) ; Chart . defaults . global . tooltips . footerFontFamily = styles . tooltipFooterFont ; Chart . defaults . global . tooltips . footerFontSize = this . _getFontSizeNumber ( styles . tooltipFooterFontSize ) ; Chart . defaults . global . tooltips . borderColor = ThemeColorHelper . GetThemeColor ( styles . tooltipBorderColor ) ; if ( Chart . defaults && Chart . defaults . scale && Chart . defaults . scale . gridLines && Chart . defaults . scale . gridLines . color ) { Chart . defaults . scale . gridLines . color = ThemeColorHelper . GetThemeColor ( styles . lineColor ) ; } } catch ( error ) { } } private _destroyChart ( ) { try { if ( this . _chart !== undefined ) { this . _chart . destroy ( ) ; } } catch ( error ) { } } private _linkCanvas = ( e ) => { this . _canvasElem = e ; } ; private _getFontSizeNumber ( value ) { try { return parseInt ( value . replace ( 'px' , '' ) , 10 ) ; } catch ( error ) { return undefined ; } } private _doPromise ( promise ) { this . setState ( { isLoading : true } , ( ) => { promise . then ( results => { this . setState ( { isLoading : false , data : results } , ( ) => { this . _initChart ( this . props , results ) ; } ) ; } , rejected => { this . setState ( { isLoading : false , rejected : rejected } ) ; } ) ; } ) ; } }