import * as Ajv from 'ajv' ; import * as draft4Schemas from 'ajv/lib/refs/json-schema-draft-04.json' ; import 'font-awesome-sass-loader' ; import * as React from 'react' ; import * as ReactDOM from 'react-dom' ; import { Provider } from 'react-redux' ; import { Store } from 'redux' ; import { TopLevelSpec } from 'vega-lite' ; import { Data } from 'vega-lite/build/src/data' ; import { FacetedCompositeUnitSpec , isUnitSpec , TopLevel } from 'vega-lite/build/src/spec' ; import * as vlSchema from 'vega-lite/build/vega-lite-schema.json' ; import { isString } from 'vega-util' ; import { REDO , UNDO } from './actions/index' ; import { App } from './components/app' ; import { State } from './models' ; import { DEFAULT_VOYAGER_CONFIG , VoyagerConfig } from './models/config' ; import { fromSerializable , SerializableState , toSerializable } from './models/index' ; import { selectData } from './selectors/dataset' ; import { selectBookmark } from './selectors/index' ; import { selectMainSpec } from './selectors/result' ; import { configureStore } from './store' ; export type Container = string | HTMLElement ; /**
 * The Voyager class encapsulates the voyager application and allows for easy
 * instantiation and interaction from non-react projects.
 */ export class Voyager { private container : HTMLElement ; private config : VoyagerConfig ; private store : Store < State > ; private data : Data ; private filename : string ; constructor ( container , config , data ) { if ( isString ( container ) ) { this . container = document . querySelector ( container ) as HTMLElement ; } else { this . container = container ; } this . config = { ... DEFAULT_VOYAGER_CONFIG , ... config } ; this . data = data ; this . init ( ) ; } param { VoyagerData } data memberof public updateData ( data ) { this . data = data ; this . render ( ) ; } memberof public undo ( ) { this . store . dispatch ( { type : UNDO } ) ; this . render ( ) ; } memberof public redo ( ) { this . store . dispatch ( { type : REDO } ) ; this . render ( ) ; } param { VoyagerConfig } config memberof public updateConfig ( config ) { this . config = config ; this . render ( ) ; } public setFilename ( filename ) { this . filename = filename ; } param { VoyagerConfig } config memberof public setSpec ( spec ) { const ajv = new Ajv ( { validateSchema : true , allErrors : true , extendRefs : 'fail' } ) ; ajv . addMetaSchema ( draft4Schemas , 'http://json-schema.org/draft-04/schema#' ) ; const validateVl = ajv . compile ( vlSchema ) ; const valid = validateVl ( spec ) ; if ( ! valid ) { throw new Error ( "Invalid spec:" + validateVl . errors . toString ( ) ) ; } if ( ! isUnitSpec ( spec as TopLevelSpec ) ) { throw new Error ( "Voyager does not support layered or multi-view vega-lite specs" ) ; } const validSpec = spec as TopLevel < FacetedCompositeUnitSpec > ; this . data = validSpec . data ; this . render ( validSpec ) ; } param state param state . config param state . dataset param state . shelf param state . result memberof public setApplicationState ( state ) { this . data = undefined ; this . config = undefined ; this . renderFromState ( fromSerializable ( state ) ) ; } returns { Readonly < State > } memberof public getApplicationState ( ) { return toSerializable ( this . store . getState ( ) ) ; } returns { Readonly < Spec > } memberof public getSpec ( includeData ) { const spec = selectMainSpec ( this . store . getState ( ) ) ; if ( includeData ) { return { ... spec , data : selectData ( this . store . getState ( ) ) , } ; } return spec ; } returns { string [ ] } memberof public getBookmarkedSpecs ( ) { return selectBookmark ( this . store . getState ( ) ) . list ; } param { Function } onChange returns { Function } memberof public onStateChange ( onChange ) { let currentState ; const handleChange = ( ) => { const nextState = this . store . getState ( ) ; if ( nextState !== currentState ) { currentState = nextState ; onChange ( toSerializable ( currentState ) ) ; } } ; const unsubscribe = this . store . subscribe ( handleChange ) ; return unsubscribe ; } private memberof private init ( ) { this . store = configureStore ( ) ; this . render ( ) ; } private render ( spec ? ) { const store = this . store ; const root = this . container ; ReactDOM . render ( < Provider store = { store } > < App dispatch = { store . dispatch } data = { this . data } config = { this . config } spec = { spec } filename = { this . filename } / > < /Provider>, root); } private renderFromState ( state ) { const store = this . store ; const root = this . container ; ReactDOM . render ( < Provider store = { store } > < App dispatch = { store . dispatch } applicationState = { state } / > < /Provider>, root); } } param { Container } container param { Object } config param { Array } data export function CreateVoyager ( container , config , data ) { return new Voyager ( container , config , data ) ; }