import { Map } from 'immutable' ; import { ActionType , getType } from 'typesafe-actions' ; import * as helperActions from '../actions/bindChannel/helperActions' ; import * as guideActions from '../actions/guideActions' ; import * as markActions from '../actions/markActions' ; import * as sceneActions from '../actions/sceneActions' ; import * as interactionActions from '../actions/interactionActions' ; import * as widgetActions from '../actions/widgetActions' ; import { MarkRecord , MarkState } from '../store/factory/Mark' ; import { SceneRecord } from '../store/factory/marks/Scene' ; import { convertValuesToSignals , propSg } from '../util/prop-signal' ; const ensureValuePresent = function ( state , path , valToAdd ) : MarkState { return state . updateIn ( path , marks => { if ( marks . indexOf ( valToAdd ) === - 1 ) { marks . push ( valToAdd ) ; } return marks ; } ) ; } ; const ensureValuePresentImmutable = function ( state , path , valToAdd ) : MarkState { return state . updateIn ( path , marks => { if ( marks . indexOf ( valToAdd ) === - 1 ) { return [ ... marks , valToAdd ] ; } return marks ; } ) ; } ; const ensureValueAbsent = function ( state , path , valToRemove ) : MarkState { return state . updateIn ( path , children => children . filter ( c => c !== valToRemove ) ) ; } ; function makeMark ( action ) { const def = action . payload . props ; const props = def . encode && def . encode . update ; return def . encode ? ( def as any ) . merge ( { encode : { update : convertValuesToSignals ( props , ( def as MarkRecord ) . type , action . meta ) } } ) : def ; } function setParentMark ( state , params ) { const { parentId , childId } = params ; if ( typeof childId === 'undefined' ) { return state ; } const child = state . get ( String ( childId ) ) ; if ( ! child ) { return state ; } const existingParentId = child . _parent ; if ( existingParentId == null && ! parentId ) { return state ; } const existingParent = state . get ( String ( existingParentId ) ) ; const newParent = parentId ? state . get ( String ( parentId ) ) : parentId ; if ( newParent === null ) { return ensureValueAbsent ( state . setIn ( [ String ( childId ) , '_parent' ] , null ) , [ String ( existingParentId ) , 'marks' ] , childId ) ; } if ( existingParent && newParent ) { return ensureValuePresent ( ensureValueAbsent ( state . setIn ( [ String ( childId ) , '_parent' ] , parentId ) , [ String ( existingParentId ) , 'marks' ] , childId ) , [ String ( parentId ) , 'marks' ] , childId ) ; } return ensureValuePresent ( state . setIn ( [ String ( childId ) , '_parent' ] , parentId ) , [ String ( parentId ) , 'marks' ] , childId ) ; } param { Object } state param action param { number } action . id param { number } action . oldGroupId param { number } action . groupId param { string } collection returns { Object } param { Object } state param { Object } action returns { Object } export function marksReducer ( state , action ) { if ( typeof state === 'undefined' ) { return Map ( ) ; } const markId = action . meta ; if ( action . type === getType ( sceneActions . baseCreateScene ) ) { return state . set ( String ( markId ) , makeMark ( action ) ) ; } if ( action . type === getType ( markActions . baseAddMark ) ) { return setParentMark ( state . set ( String ( markId ) , makeMark ( action ) ) , { parentId : action . payload . props ? action . payload . props . _parent : null , childId : markId } ) ; } if ( action . type === getType ( markActions . baseDeleteMark ) ) { return setParentMark ( state , { childId : markId , parentId : null } ) . remove ( String ( markId ) ) ; } if ( action . type === getType ( markActions . setParent ) ) { return setParentMark ( state , { parentId : action . payload , childId : markId } ) ; } if ( action . type === getType ( markActions . updateMarkProperty ) ) { return state . setIn ( [ String ( markId ) , action . payload . property ] , action . payload . value ) ; } if ( action . type === getType ( markActions . setMarkVisual ) ) { return state . setIn ( [ String ( markId ) , 'encode' , 'update' , action . payload . property ] , action . payload . def ) ; } if ( action . type === getType ( markActions . disableMarkVisual ) ) { return state . setIn ( [ String ( markId ) , 'encode' , 'update' , action . payload , '_disabled' ] , true ) ; } if ( action . type === getType ( markActions . resetMarkVisual ) ) { const markType = state . getIn ( [ String ( markId ) , 'type' ] ) ; const property = action . payload ; return state . setIn ( [ String ( markId ) , 'encode' , 'update' , property ] , { signal : propSg ( markId , markType , property ) } ) ; } if ( action . type === getType ( markActions . setMarkExtent ) ) { return state . setIn ( [ String ( markId ) , 'encode' , 'update' , action . payload . oldExtent , '_disabled' ] , true ) . setIn ( [ String ( markId ) , 'encode' , 'update' , action . payload . newExtent , '_disabled' ] , false ) ; } if ( action . type === getType ( markActions . setVlUnit ) ) { return state . setIn ( [ String ( markId ) , '_vlUnit' ] , action . payload ) ; } if ( action . type === getType ( markActions . bindScale ) ) { return state . setIn ( [ String ( markId ) , 'encode' , 'update' , action . payload . property , 'scale' ] , action . payload . scaleId ) ; } const groupId = action . meta ; if ( action . type === getType ( helperActions . addScaleToGroup ) ) { return ensureValuePresent ( state , [ String ( groupId ) , 'scales' ] , action . payload ) ; } if ( action . type === getType ( helperActions . addAxisToGroup ) ) { return ensureValuePresentImmutable ( state , [ String ( groupId ) , 'axes' ] , action . payload ) ; } if ( action . type === getType ( helperActions . addLegendToGroup ) ) { return ensureValuePresentImmutable ( state , [ String ( groupId ) , 'legends' ] , action . payload ) ; } if ( action . type === getType ( helperActions . addInteractionToGroup ) ) { return ensureValuePresentImmutable ( state , [ String ( groupId ) , '_interactions' ] , action . payload ) ; } if ( action . type === getType ( helperActions . addWidgetToGroup ) ) { return ensureValuePresentImmutable ( state , [ String ( groupId ) , '_widgets' ] , action . payload ) ; } const id = action . meta ; if ( action . type === getType ( guideActions . deleteGuide ) ) { state = ensureValueAbsent ( state , [ String ( action . payload . groupId ) , 'axes' ] , id ) ; return ensureValueAbsent ( state , [ String ( action . payload . groupId ) , 'legends' ] , id ) ; } if ( action . type === getType ( interactionActions . deleteInteraction ) ) { return ensureValueAbsent ( state , [ String ( action . payload . groupId ) , '_interactions' ] , id ) ; } if ( action . type === getType ( widgetActions . deleteWidget ) ) { return ensureValueAbsent ( state , [ String ( action . payload . groupId ) , '_widgets' ] , id ) ; } return state ; }