From 66f9f421a90edca7f7024870df81f6aed69c8eb4 Mon Sep 17 00:00:00 2001 From: Mary Bucknell <mbucknell@usgs.gov> Date: Tue, 8 May 2018 08:04:36 -0500 Subject: [PATCH] Start of implementation of a loading indicator --- .../scripts/components/hydrograph/index.js | 15 ++++++++++--- .../src/scripts/components/map/index.spec.js | 2 +- .../scripts/selectors/timeSeriesSelector.js | 12 +++++++++-- assets/src/scripts/store/index.js | 21 +++++++++++++++++-- .../scripts/store/timeSeriesStateReducer.js | 16 ++++++++++++++ 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/assets/src/scripts/components/hydrograph/index.js b/assets/src/scripts/components/hydrograph/index.js index ebaa25b14..190b64906 100644 --- a/assets/src/scripts/components/hydrograph/index.js +++ b/assets/src/scripts/components/hydrograph/index.js @@ -8,7 +8,7 @@ const { select } = require('d3-selection'); const { createStructuredSelector } = require('reselect'); const { addSVGAccessibility } = require('../../accessibility'); -const { USWDS_MEDIUM_SCREEN, USWDS_SMALL_SCREEN, STATIC_URL } = require('../../config'); +const { USWDS_SMALL_SCREEN, STATIC_URL } = require('../../config'); const { dispatch, link, provide } = require('../../lib/redux'); const { Actions } = require('../../store'); const { mediaQuery } = require('../../utils'); @@ -27,7 +27,7 @@ const { allTimeSeriesSelector, isVisibleSelector, titleSelector, const { createTooltipFocus, createTooltipText } = require('./tooltip'); const { coerceStatisticalSeries } = require('./statistics'); -const { getCurrentDateRange } = require('../../selectors/timeSeriesSelector'); +const { getCurrentDateRange, isLoadingTS } = require('../../selectors/timeSeriesSelector'); const drawMessage = function (elem, message) { @@ -407,7 +407,16 @@ const attachToNode = function (store, node, {siteno} = {}) { store.dispatch(Actions.resizeUI(window.innerWidth, node.offsetWidth)); select(node) - .call(provide(store)) + .call(provide(store)); + select(node) + .call(link(function(elem, isLoadingCurrentTS) { + elem.select('.loading-indicator').remove(); + if (isLoadingCurrentTS) { + select(elem).append('i') + .attr('class', 'fas fa-spinner fa-spin'); + } + }, isLoadingTS('current:P7D'))); + select(node) .call(link(createDaterangeControls, createStructuredSelector({ siteno: () => siteno, showControls: hasTimeSeriesWithPoints('current', 'P7D') diff --git a/assets/src/scripts/components/map/index.spec.js b/assets/src/scripts/components/map/index.spec.js index b71f7376c..cc6b46a56 100644 --- a/assets/src/scripts/components/map/index.spec.js +++ b/assets/src/scripts/components/map/index.spec.js @@ -4,7 +4,7 @@ const proxyquire = require('proxyquireify')(require); const { attachToNode } = require('./index'); const { configureStore } = require('../../store'); -fdescribe('map module', () => { +describe('map module', () => { let mapNode; let store; let floodDataMock; diff --git a/assets/src/scripts/selectors/timeSeriesSelector.js b/assets/src/scripts/selectors/timeSeriesSelector.js index 9bc234e44..f5ded6053 100644 --- a/assets/src/scripts/selectors/timeSeriesSelector.js +++ b/assets/src/scripts/selectors/timeSeriesSelector.js @@ -6,13 +6,17 @@ const { createSelector } = require('reselect'); */ export const getVariables = state => state.series.variables ? state.series.variables : null; +export const getMethods = state => state.series.methods ? state.series.methods : null; + +export const getQueryInfo = state => state.series.queryInfo || {}; + + export const getCurrentVariableID = state => state.timeSeriesState.currentVariableID; export const getCurrentDateRange = state => state.timeSeriesState.currentDateRange; -export const getMethods = state => state.series.methods ? state.series.methods : null; +export const getLoadingTsKeys = state => state.timeSeriesState.loadingTSKeys; -export const getQueryInfo = state => state.series.queryInfo || {}; /* * Selectors the return derived data from the state @@ -111,3 +115,7 @@ export const getRequestTimeRange = memoize((tsKey, period, parmCd) => createSele } )); +export const isLoadingTS = memoize(tsKey => createSelector( + getLoadingTsKeys, + (loadingTSKeys) => loadingTSKeys.includes(tsKey) +)); diff --git a/assets/src/scripts/store/index.js b/assets/src/scripts/store/index.js index 66eebd5d4..defa7856f 100644 --- a/assets/src/scripts/store/index.js +++ b/assets/src/scripts/store/index.js @@ -50,9 +50,12 @@ export const Actions = { retrieveTimeSeries(siteno, params=null) { return function (dispatch, getState) { const currentState = getState(); + const requestKey = getTsRequestKey('current', 'P7D')(currentState); + dispatch(Actions.addTimeSeriesLoading([requestKey])); + const timeSeries = getTimeSeries({sites: [siteno], params}).then( series => { - const requestKey = getTsRequestKey('current', 'P7D')(currentState); + dispatch(Actions.removeTimeSeriesLoading([requestKey])); const collection = normalize(series, requestKey); // Get the start/end times of this request's range. @@ -77,6 +80,7 @@ export const Actions = { return {collection, startTime, endTime}; }, () => { + dispatch(Actions.removeTimeSeriesLoading([requestKey])); dispatch(Actions.resetTimeSeries(getTsRequestKey('current', 'P7D')(currentState))); dispatch(Actions.toggleTimeSeries('current', false)); return { @@ -193,6 +197,18 @@ export const Actions = { type: 'TIMESERIES_PLAY_STOP' }; }, + addTimeSeriesLoading(tsKeys) { + return { + type: 'TIMESERIES_LOADING_ADD', + tsKeys + }; + }, + removeTimeSeriesLoading(tsKeys) { + return { + type: 'TIMESERIES_LOADING_REMOVE', + tsKeys + }; + }, setFloodFeatures(stages, extent) { return { type: 'SET_FLOOD_FEATURES', @@ -289,7 +305,8 @@ export const configureStore = function (initialState) { currentDateRange: 'P7D', currentVariableID: null, cursorOffset: null, - audiblePlayId: null + audiblePlayId: null, + loadingTSKeys: [] }, floodState: { gageHeight: null diff --git a/assets/src/scripts/store/timeSeriesStateReducer.js b/assets/src/scripts/store/timeSeriesStateReducer.js index f3222f341..46529150e 100644 --- a/assets/src/scripts/store/timeSeriesStateReducer.js +++ b/assets/src/scripts/store/timeSeriesStateReducer.js @@ -48,6 +48,20 @@ const timeSeriesPlayStop = function(timeSeriesState) { }; }; +const addLoadingTimeSeries = function(timeSeriesState, action) { + return { + ...timeSeriesState, + loadingTSKeys: timeSeriesState.loadingTSKeys.concat([action.tsKeys]) + }; +}; + +const removeLoadingTimeSeries = function(timeSeriesState, action) { + return { + ...timeSeriesState, + loadingTSKeys: timeSeriesState.loadingTSKeys.filter((tsKey) => action.tsKeys.includes(tsKey)) + }; +}; + /* * Slice reducer */ @@ -59,6 +73,8 @@ export const timeSeriesStateReducer = function(timeSeriesState={}, action) { case 'SET_CURSOR_OFFSET': return setCursorOffset(timeSeriesState, action); case 'TIMESERIES_PLAY_ON': return timeSeriesPlayOn(timeSeriesState, action); case 'TIMESERIES_PLAY_STOP': return timeSeriesPlayStop(timeSeriesState, action); + case 'TIMESERIES_LOADING_ADD': return addLoadingTimeSeries(timeSeriesState, action); + case 'TIMESERIES_LOADING_REMOVE': return removeLoadingTimeSeries(timeSeriesState, action); default: return timeSeriesState; } }; -- GitLab