import 'core-js/stable' ; import './../style/visual.less' ; import powerbi from 'powerbi-visuals-api' ; import VisualConstructorOptions = powerbi . extensibility . visual . VisualConstructorOptions ; import VisualUpdateOptions = powerbi . extensibility . visual . VisualUpdateOptions ; import IVisual = powerbi . extensibility . visual . IVisual ; import EnumerateVisualObjectInstancesOptions = powerbi . EnumerateVisualObjectInstancesOptions ; import VisualObjectInstance = powerbi . VisualObjectInstance ; import DataView = powerbi . DataView ; import VisualObjectInstanceEnumerationObject = powerbi . VisualObjectInstanceEnumerationObject ; import IVisualHost = powerbi . extensibility . visual . IVisualHost ; import IVisualEventService = powerbi . extensibility . IVisualEventService ; import ILocalizationManager = powerbi . extensibility . ILocalizationManager ; import VisualUpdateType = powerbi . VisualUpdateType ; import VisualEnumerationInstanceKinds = powerbi . VisualEnumerationInstanceKinds ; import * as d3Select from 'd3-selection' ; import { VisualSettings } from './VisualSettings' ; import { VisualConstants } from './VisualConstants' ; import { ViewModelHandler } from './ViewModel' ; import DomainUtils from './DomainUtils' ; import LandingPageHandler from './LandingPageHandler' ; export class Visual implements IVisual { private container : d3 . Selection < HTMLDivElement , any , any , any > ; private landingContainer : d3 . Selection < HTMLDivElement , any , any , any > ; private statusContainer : d3 . Selection < HTMLDivElement , any , any , any > ; private contentContainer : d3 . Selection < HTMLDivElement , any , any , any > ; private host : IVisualHost ; private settings : VisualSettings ; private events : IVisualEventService ; private localisationManager : ILocalizationManager ; private viewModelHandler = new ViewModelHandler ( ) ; private landingPageHandler : LandingPageHandler ; private styleSheetContainer : d3Select . Selection < HTMLStyleElement , any , any , any > ; constructor ( options ) { this . container = d3Select . select ( options . element ) . append ( 'div' ) . attr ( 'id' , VisualConstants . dom . viewerIdSelector ) ; this . host = options . host ; this . localisationManager = this . host . createLocalizationManager ( ) ; this . styleSheetContainer = d3Select . select ( 'head' ) . append ( 'style' ) . attr ( 'id' , VisualConstants . dom . stylesheetIdSelector ) . attr ( 'name' , VisualConstants . dom . stylesheetIdSelector ) . attr ( 'type' , 'text/css' ) ; this . landingContainer = this . container . append ( 'div' ) . attr ( 'id' , VisualConstants . dom . landingIdSelector ) ; this . statusContainer = this . container . append ( 'div' ) . attr ( 'id' , VisualConstants . dom . statusIdSelector ) ; this . contentContainer = this . container . append ( 'div' ) . attr ( 'id' , VisualConstants . dom . contentIdSelector ) ; this . landingPageHandler = new LandingPageHandler ( this . landingContainer , this . localisationManager ) ; this . events = this . host . eventService ; this . viewModelHandler . reset ( ) ; } public update ( options ) { const viewModel = this . viewModelHandler . viewModel ; try { this . events . renderingStarted ( options ) ; this . updateStatus ( ) ; this . contentContainer . selectAll ( '*' ) . remove ( ) ; this . settings = Visual . parseSettings ( options && options . dataViews && options . dataViews [ 0 ] ) ; switch ( options . type ) { case VisualUpdateType . Data : case VisualUpdateType . All : { this . updateStatus ( this . localisationManager . getDisplayName ( 'Status_Mapping_DataView' ) ) ; this . viewModelHandler . validateDataView ( options . dataViews ) ; viewModel . isValid && this . viewModelHandler . mapDataView ( options . dataViews , this . settings ) ; this . updateStatus ( ) ; break ; } } this . landingPageHandler . handleLandingPage ( this . viewModelHandler . viewModel . isValid , this . host ) ; if ( ! viewModel . isValid ) { throw new Error ( 'View model mapping error' ) ; } DomainUtils . resolveStyling ( this . styleSheetContainer , this . container , this . settings ) ; if ( viewModel . isEmpty ) { this . updateStatus ( this . settings . contentFormatting . noDataMessage , viewModel . contentFormatting . showRawHtml ) ; } else { let dataElements = DomainUtils . bindVisualDataToDom ( this . contentContainer , viewModel . htmlEntries ) ; DomainUtils . resolveHtmlGroupElement ( dataElements ) ; DomainUtils . resolveForRawHtml ( this . styleSheetContainer , this . contentContainer , this . settings ) ; } DomainUtils . resolveHyperlinkHandling ( this . host , this . container , viewModel . contentFormatting . hyperlinks ) ; DomainUtils . resolveContextMenu ( this . container , this . host . createSelectionManager ( ) ) ; DomainUtils . resolveScrollableContent ( this . container . node ( ) ) ; this . events . renderingFinished ( options ) ; return ; } catch ( e ) { this . events . renderingFailed ( options , e ) ; this . contentContainer . selectAll ( '*' ) . remove ( ) ; this . updateStatus ( ) ; } } param message param showRawHtml private updateStatus ( message ? , showRawHtml ? ) { this . statusContainer . selectAll ( '*' ) . remove ( ) ; this . statusContainer . append ( 'div' ) . html ( message ) ; if ( showRawHtml ) { DomainUtils . resolveForRawHtml ( this . styleSheetContainer , this . statusContainer , this . settings ) ; } } private static parseSettings ( dataView ) { return VisualSettings . parse ( dataView ) ; } /**
     * This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
     * objects and properties you want to expose to the users in the property pane.
     *
     */ public enumerateObjectInstances ( options ) { const instances = ( < VisualObjectInstanceEnumerationObject > VisualSettings . enumerateObjectInstances ( this . settings || VisualSettings . getDefault ( ) , options ) ) . instances ; let objectName = options . objectName ; switch ( objectName ) { case 'contentFormatting' : { if ( this . settings . contentFormatting . showRawHtml ) { delete instances [ 0 ] . properties [ 'fontFamily' ] ; } if ( DomainUtils . shouldUseStylesheet ( this . settings . stylesheet ) ) { delete instances [ 0 ] . properties [ 'fontFamily' ] ; delete instances [ 0 ] . properties [ 'fontSize' ] ; delete instances [ 0 ] . properties [ 'fontColour' ] ; delete instances [ 0 ] . properties [ 'align' ] ; } instances [ 0 ] . propertyInstanceKind = { noDataMessage : VisualEnumerationInstanceKinds . ConstantOrRule } ; break ; } case 'stylesheet' : { instances [ 0 ] . propertyInstanceKind = { stylesheet : VisualEnumerationInstanceKinds . Rule } ; break ; } } return instances ; } }