import { ThunkDispatch } from 'redux-thunk' ; import { getCounts } from '../../ctrl/export' ; import { State } from '../../store' ; import { GuideType } from '../../store/factory/Guide' ; import { Scale } from '../../store/factory/Scale' ; import { updateGuideProperty } from '../guideActions' ; import { updateMarkProperty } from '../markActions' ; import { addScale , amendDataRef , updateScaleProperty } from '../scaleActions' ; import { addScaleToGroup } from './helperActions' ; import { assignId } from '../../util/counter' ; const imutils = require ( '../../util/immutable-utils' ) , getInVis = imutils . getInVis , getIn = imutils . getIn ; param { Function } dispatch param { State } state param { Object } parsed returns { void } export default function ( dispatch , state , parsed ) { const map = parsed . map , aggId = map . data . summary , markId = parsed . markId , mark = getInVis ( state , 'marks.' + markId ) , counts = getCounts ( true ) , clones = { } ; function dataRefHasAgg ( ref ) { return ref . get ( 'data' ) === aggId ; } Object . values ( map . scales ) . forEach ( function ( scaleId ) { const type = getInVis ( state , 'scales.' + scaleId + '.type' ) , domain = getInVis ( state , 'scales.' + scaleId + '._domain' ) , range = getInVis ( state , 'scales.' + scaleId + '._range' ) , count = counts . scales [ scaleId ] . markTotal ; function updateDataRef ( property , ref , idx ) { if ( ref . get ( 'data' ) === aggId ) { return ; } if ( count === 1 ) { dispatch ( updateScaleProperty ( { property : property + '.' + idx + '.data' , value : aggId } , scaleId ) ) ; } else if ( type === 'ordinal' ) { clones [ scaleId ] = true ; } else { dispatch ( amendDataRef ( { property : property , ref : ref . set ( 'data' , aggId ) } , scaleId ) ) ; } } if ( domain . size && ! domain . filter ( dataRefHasAgg ) . size ) { domain . forEach ( updateDataRef . bind ( null , '_domain' ) ) ; } if ( range . size && ! range . filter ( dataRefHasAgg ) . size ) { range . forEach ( updateDataRef . bind ( null , '_range' ) ) ; } } ) ; if ( Object . keys ( clones ) . length > 0 ) { Object . keys ( clones ) . forEach ( function ( scaleId ) { const scale = getInVis ( state , 'scales.' + scaleId ) , groupId = mark . get ( '_parent' ) ; let guide , guideId ; const newScaleId = ( clones [ scaleId ] = assignId ( dispatch , state ) ) ; const newScale = cloneScale ( scale , aggId ) . merge ( { _id : newScaleId } ) ; dispatch ( addScale ( newScale ) ) ; dispatch ( addScaleToGroup ( newScaleId , groupId ) ) ; for ( guideId in counts . scales [ scaleId ] . guides ) { guide = getInVis ( state , 'guides.' + guideId ) ; if ( guide . get ( '_gtype' ) === GuideType . Axis ) { dispatch ( updateGuideProperty ( { property : 'scale' , value : newScaleId } , guideId ) ) ; } else { dispatch ( updateGuideProperty ( { property : guide . get ( '_type' ) , value : newScaleId } , guideId ) ) ; } } } ) ; getIn ( mark , 'encode.update' ) . forEach ( function ( def , name ) { const newScaleId = clones [ def . get ( 'scale' ) ] ; if ( newScaleId ) { dispatch ( updateMarkProperty ( { property : 'encode.update.' + name + '.scale' , value : newScaleId } , markId ) ) ; } } ) ; } } ; function cloneScale ( def , aggId ) { function updateDataRef ( ref ) { return { data : aggId , field : ref . field } ; } const scale = Scale ( { _origName : def . get ( '_origName' ) , type : def . get ( 'type' ) , nice : def . get ( 'nice' ) , round : def . get ( 'round' ) , zero : def . get ( 'zero' ) , padding : def . get ( 'padding' ) , domain : def . get ( 'domain' ) , _domain : def . get ( '_domain' ) . toJS ( ) . map ( updateDataRef ) , range : def . get ( 'range' ) , _range : def . get ( '_range' ) . toJS ( ) . map ( updateDataRef ) } ) ; return scale ; }