@@ -3,13 +3,13 @@ const Rx = require('rxjs');
33const { isString, get, head, castArray} = require ( 'lodash' ) ;
44const moment = require ( 'moment' ) ;
55
6- const { SELECT_TIME , RANGE_CHANGED , ENABLE_OFFSET , timeDataLoading, rangeDataLoaded } = require ( '../actions/timeline' ) ;
6+ const { SELECT_TIME , RANGE_CHANGED , ENABLE_OFFSET , timeDataLoading, rangeDataLoaded, onRangeChanged } = require ( '../actions/timeline' ) ;
77const { setCurrentTime, UPDATE_LAYER_DIMENSION_DATA , setCurrentOffset } = require ( '../actions/dimension' ) ;
88
99
1010const { getLayerFromId} = require ( '../selectors/layers' ) ;
11- const { rangeSelector, offsetEnabledSelector , selectedLayerName, selectedLayerUrl } = require ( '../selectors/timeline' ) ;
12- const { layerTimeSequenceSelectorCreator, timeDataSelector, layersWithTimeDataSelector, offsetTimeSelector, currentTimeSelector } = require ( '../selectors/dimension' ) ;
11+ const { rangeSelector, selectedLayerName, selectedLayerUrl } = require ( '../selectors/timeline' ) ;
12+ const { layerTimeSequenceSelectorCreator, offsetEnabledSelector , timeDataSelector, layersWithTimeDataSelector, offsetTimeSelector, currentTimeSelector } = require ( '../selectors/dimension' ) ;
1313
1414const { getNearestDate, roundRangeResolution, isTimeDomainInterval } = require ( '../utils/TimeUtils' ) ;
1515const { getHistogram, describeDomains, getDomainValues } = require ( '../api/MultiDim' ) ;
@@ -164,24 +164,46 @@ module.exports = {
164164 } ) ,
165165 /**
166166 * When offset is initiated this epic sets both initial current time and offset if any does not exist
167+ * The policy is:
168+ * - if current time is not defined, it will be placed to the center of the current timeline's viewport. If the viewport is undefined it is set to "now"
169+ * - if offsetTime is not defined, it will be placed at 1/ RATIO * (current viewport size) distance from current time (to make it visible). If viewport is not defined, 1 day from the current time
170+ * - At the end, if the viewport is not defined, it will be placed to center the current time. This way the range will be visible when the timeline is available.
171+ *
167172 */
168173 settingInitialOffsetValue : ( action$ , { getState = ( ) => { } } = { } ) =>
169174 action$ . ofType ( ENABLE_OFFSET )
170175 . switchMap ( ( action ) => {
176+ const RATIO = 5 ; // ratio of the size of the offset to set relative to the current viewport, if set
171177 const state = getState ( ) ;
172178 const time = currentTimeSelector ( state ) ;
173- const { start, end} = rangeSelector ( state ) ;
174- const currentOffset = offsetTimeSelector ( state ) ;
175- const rangeDistance = moment ( end ) . diff ( start ) ;
176- let currentMoment = moment ( start ) . add ( rangeDistance / 2 ) . toISOString ( ) ;
177-
178- const initialOffsetTime = moment ( time ? time : currentMoment ) . add ( rangeDistance / 5 ) ;
179- let setTime = action . enabled && ! time ? Rx . Observable . of ( setCurrentTime ( currentMoment ) ) : Rx . Observable . empty ( ) ;
180- let setOff = action . enabled && ! currentOffset || action . enabled && moment ( currentOffset ) . diff ( time ) < 0 ? Rx . Observable . of ( setCurrentOffset ( initialOffsetTime . toISOString ( ) ) )
181- : Rx . Observable . empty ( ) ;
182- return setTime . concat ( setOff ) ;
179+ const currentViewRange = rangeSelector ( state ) ;
180+ // find out current viewport range, if exist, to define a good offset to use as default
181+ if ( action . enabled ) {
182+ const {
183+ start = 0 ,
184+ end = 1000 * 60 * 60 * 24 * RATIO // this makes the offset 1 day by default, if timeline is not initialized
185+ } = currentViewRange || { } ;
186+ const currentOffset = offsetTimeSelector ( state ) ;
187+ const rangeDistance = moment ( end ) . diff ( start ) ;
188+ // Set current moment, if not set yet, to current viewport center. otherwise, it is set to now.
189+ let currentMoment = currentViewRange ? moment ( start ) . add ( rangeDistance / 2 ) . toISOString ( ) : moment ( new Date ( ) ) ;
190+
191+ const initialOffsetTime = moment ( time ? time : currentMoment ) . add ( rangeDistance / RATIO ) ;
192+ let setTime = action . enabled && ! time ? Rx . Observable . of ( setCurrentTime ( currentMoment . toISOString ( ) ) ) : Rx . Observable . empty ( ) ;
193+ let setOff = action . enabled && ! currentOffset || action . enabled && moment ( currentOffset . toISOString ( ) ) . diff ( time ) < 0 ? Rx . Observable . of ( setCurrentOffset ( initialOffsetTime . toISOString ( ) ) )
194+ : Rx . Observable . empty ( ) ;
195+ const centerToCurrentViewRange = currentViewRange ? Rx . Observable . empty ( ) : Rx . Observable . of (
196+ onRangeChanged ( {
197+ start : moment ( currentMoment ) . add ( - 1 * rangeDistance / 2 ) ,
198+ end : moment ( currentMoment ) . add ( rangeDistance / 2 )
199+ } )
200+ ) ;
201+ return setTime . concat ( setOff ) . concat ( centerToCurrentViewRange ) ;
202+ }
203+ return Rx . Observable . of ( setCurrentOffset ( ) ) ;
204+ // disable by setting off the offset
183205 } ) ,
184- /**
206+ /**
185207 * Update the time data when the timeline range changes, or when the layer dimension data is
186208 * updated (for instance when a layer is added to the map)
187209 */
0 commit comments