Skip to content

Commit

Permalink
#9586 - Persist timeline animation settings when saving a map (#9865)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsuren1 authored Jan 11, 2024
1 parent c72e60f commit 254dcc2
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 8 deletions.
9 changes: 8 additions & 1 deletion web/client/actions/__tests__/playback-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
PLAY, PAUSE, STOP, SET_FRAMES, SET_CURRENT_FRAME, APPEND_FRAMES, FRAMES_LOADING, SELECT_PLAYBACK_RANGE,
CHANGE_SETTING, TOGGLE_ANIMATION_MODE, ANIMATION_STEP_MOVE, UPDATE_METADATA, SET_INTERVAL_DATA,
pause, play, stop, setFrames, setCurrentFrame, appendFrames, framesLoading, selectPlaybackRange,
changeSetting, toggleAnimationMode, animationStepMove, updateMetadata, setIntervalData
changeSetting, toggleAnimationMode, animationStepMove, updateMetadata, setIntervalData, onInitPlayback, INIT
} from "../playback";

describe('Test playback actions', () => {
Expand Down Expand Up @@ -99,4 +99,11 @@ describe('Test playback actions', () => {
expect(retval.type).toBe(SET_INTERVAL_DATA);
expect(retval.timeIntervalData).toBe(true);
});
it('Test init action creator', () => {
const payload = {metadata: "1", settings: "2"};
const retval = onInitPlayback(payload);
expect(retval).toBeTruthy();
expect(retval.type).toBe(INIT);
expect(retval.payload).toEqual(payload);
});
});
10 changes: 10 additions & 0 deletions web/client/actions/playback.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const PLAY = "PLAYBACK:START";
export const PAUSE = "PLAYBACK:PAUSE";
export const STOP = "PLAYBACK:STOP";

export const INIT = "PLAYBACK:INIT";
export const SET_FRAMES = "PLAYBACK:SET_FRAMES";
export const APPEND_FRAMES = "PLAYBACK:APPEND_FRAMES";
export const FRAMES_LOADING = "PLAYBACK:FRAMES_LOADING";
Expand Down Expand Up @@ -88,3 +89,12 @@ export const setIntervalData = (timeIntervalData) => ({
type: SET_INTERVAL_DATA,
timeIntervalData
});

/**
* Initialize the playback data on config load
* @param {object} playback data
*/
export const onInitPlayback = (payload) => ({
type: INIT,
payload
});
32 changes: 30 additions & 2 deletions web/client/epics/__tests__/playback-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
SET_FRAMES,
SET_INTERVAL_DATA,
TOGGLE_ANIMATION_MODE,
toggleAnimationMode
toggleAnimationMode,
INIT
} from '../../actions/playback';

import {
Expand All @@ -26,14 +27,16 @@ import {
playbackCacheNextPreviousTimes,
setIsIntervalData,
switchOffSnapToLayer,
playbackToggleGuideLayerToFixedStep
playbackToggleGuideLayerToFixedStep,
updatePlaybackDataOnMapLoad
} from '../playback';

import DOMAIN_VALUES_RESPONSE from 'raw-loader!../../test-resources/wmts/DomainValues.xml';
import DOMAIN_INTERVAL_VALUES_RESPONSE from 'raw-loader!../../test-resources/wmts/DomainIntervalValues.xml';
import { removeNode, CHANGE_LAYER_PROPERTIES, changeLayerProperties } from '../../actions/layers';
import { setCurrentTime, moveTime } from '../../actions/dimension';
import { selectLayer, LOADING, setMapSync, SELECT_LAYER, initializeSelectLayer } from '../../actions/timeline';
import { configureMap } from '../../actions/config';
import axios from '../../libs/ajax';
import MockAdapter from 'axios-mock-adapter';
const ANIMATION_MOCK_STATE = {
Expand Down Expand Up @@ -585,4 +588,29 @@ describe('playback Epics', () => {
}
}, state);
});
it('updatePlaybackDataOnMapLoad on config load', done => {
const _payload = {playback: {metadata: {timeIntervalData: false}, settings: "2"}};
testEpic(updatePlaybackDataOnMapLoad, 1, configureMap(_payload), ([action]) => {
try {
const { type, payload } = action;
expect(type).toBe(INIT);
expect(payload.metadata.timeIntervalData).toBe(false);
expect(payload.settings).toBe("2");
done();
} catch (e) {
done(e);
}
}, ANIMATION_MOCK_STATE);
});
it('updatePlaybackDataOnMapLoad on no playback config data', done => {
const _payload = {map: {}};
testEpic(addTimeoutEpic(updatePlaybackDataOnMapLoad, 500), 1, configureMap(_payload), ([action]) => {
try {
expect(action.type).toBe(TEST_TIMEOUT);
done();
} catch (e) {
done(e);
}
}, ANIMATION_MOCK_STATE);
});
});
21 changes: 18 additions & 3 deletions web/client/epics/playback.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
*/
import moment from 'moment';

import { get } from 'lodash';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';

import {
PLAY,
Expand All @@ -25,7 +26,8 @@ import {
framesLoading,
updateMetadata,
setIntervalData,
toggleAnimationMode
toggleAnimationMode,
onInitPlayback
} from '../actions/playback';

import { moveTime, SET_CURRENT_TIME, MOVE_TIME } from '../actions/dimension';
Expand Down Expand Up @@ -79,6 +81,7 @@ import { wrapStartStop } from '../observables/epics';
import { getTimeDomainsObservable } from '../observables/multidim';
import { getDomainValues } from '../api/MultiDim';
import Rx from 'rxjs';
import { MAP_CONFIG_LOADED } from '../actions/config';

const BUFFER_SIZE = 20;
const PRELOAD_BEFORE = 10;
Expand Down Expand Up @@ -437,6 +440,17 @@ export const playbackStopWhenDeleteLayer = (action$, { getState = () => {} } = {
)
.switchMap( () => Rx.Observable.of(stop()));

/**
* Updates playback state on map config load
* @param action$
* @return {observable}
*/
export const updatePlaybackDataOnMapLoad = (action$) =>
action$.ofType(MAP_CONFIG_LOADED)
.filter(({config} = {}) => !isEmpty(config?.playback))
.switchMap(({config} = {}) => {
return Rx.Observable.of(onInitPlayback(config?.playback));
});

export default {
retrieveFramesForPlayback,
Expand All @@ -448,5 +462,6 @@ export default {
playbackFollowCursor,
playbackStopWhenDeleteLayer,
setIsIntervalData,
switchOffSnapToLayer
switchOffSnapToLayer,
updatePlaybackDataOnMapLoad
};
9 changes: 8 additions & 1 deletion web/client/plugins/Playback.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,15 @@ import playback from '../epics/playback';
import dimensionReducers from '../reducers/dimension';
import playbackReducers from '../reducers/playback';
import { currentTimeSelector } from '../selectors/dimension';
import { loadingSelector, statusSelector } from '../selectors/playback';
import { loadingSelector, playbackMetadataSelector, playbackRangeSelector, playbackSettingsSelector, statusSelector } from '../selectors/playback';
import PlaybackComp from './playback/Playback';
import { registerCustomSaveHandler } from '../selectors/mapsave';

registerCustomSaveHandler('playback', (state) => ({
settings: playbackSettingsSelector(state),
playbackRange: playbackRangeSelector(state),
metadata: playbackMetadataSelector(state)
}));

const Playback = compose(
defaultProps({
Expand Down
11 changes: 10 additions & 1 deletion web/client/reducers/__tests__/playback-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
selectPlaybackRange,
framesLoading,
STATUS,
setIntervalData
setIntervalData,
onInitPlayback
} from '../../actions/playback';

import playback from '../playback';
Expand Down Expand Up @@ -135,4 +136,12 @@ describe('playback reducer', () => {
expect(state).toExist();
expect(state.metadata.timeIntervalData).toBe(false);
});
it('initialize playback data', () => {
const payload = {metadata: {timeIntervalData: false}, settings: "2"};
const action = onInitPlayback(payload);
const state = playback(undefined, action);
expect(state).toBeTruthy();
expect(state.metadata.timeIntervalData).toBe(false);
expect(state.settings).toBe("2");
});
});
4 changes: 4 additions & 0 deletions web/client/reducers/playback.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
PAUSE,
STOP,
STATUS,
INIT,
SET_FRAMES,
APPEND_FRAMES,
FRAMES_LOADING,
Expand All @@ -25,6 +26,9 @@ const DEFAULT_SETTINGS = {

export default (state = { status: STATUS.STOP, currentFrame: -1, settings: DEFAULT_SETTINGS}, action) => {
switch (action.type) {
case INIT: {
return {...state, ...action.payload};
}
case PLAY: {
return set(`status`, STATUS.PLAY, state);
}
Expand Down

0 comments on commit 254dcc2

Please sign in to comment.