Newer
Older
* Hydrograph charting module.
*/
Bucknell, Mary S.
committed
import {link} from 'ui/lib/d3-redux';
import {createStructuredSelector} from 'reselect';
Bucknell, Mary S.
committed
import {drawInfoAlert} from 'd3render/alerts';
import {renderTimeSeriesUrlParams} from 'ml/url-params';
import {getInputsForRetrieval} from 'ml/selectors/hydrograph-state-selector';
Bucknell, Mary S.
committed
import {retrieveGroundwaterLevelData} from 'ml/store/groundwater-level-field-visits';
import {retrieveHydrographData} from 'ml/store/hydrograph-data';
Bucknell, Mary S.
committed
import {retrieveHydrographParameters} from 'ml/store/hydrograph-parameters';
Bucknell, Mary S.
committed
import {setSelectedParameterCode, setCompareDataVisibility, setSelectedTimeSpan,
} from 'ml/store/hydrograph-state';
Bucknell, Mary S.
committed
Bucknell, Mary S.
committed
import {Actions as floodDataActions} from 'ml/store/flood-data';
import {getPreferredIVMethodID, getTitle} from './selectors/time-series-data';
import {getStatisticsData, getLatestPrimaryValue} from 'ml/selectors/hydrograph-data-selector';
Bucknell, Mary S.
committed
import {showDataIndicators} from './data-indicator';
import {drawDataTables} from './data-table';
Bucknell, Mary S.
committed
import {initializeGraphBrush, drawGraphBrush} from './graph-brush';
import {drawGraphControls} from './graph-controls';
Bucknell, Mary S.
committed
import {drawTimeSeriesLegend} from './legend';
import {drawSelectionList} from './parameters';
import {drawSelectActions} from './select-actions';
import {drawTimeSpanShortcutButtons} from './time-span-shortcuts';
Bucknell, Mary S.
committed
import {initializeTimeSeriesGraph, drawTimeSeriesGraphData} from './time-series-graph';
import {initializeTooltipCursorSlider, drawTooltipCursorSlider} from './tooltip';
Bucknell, Mary S.
committed
/*
* Renders the hydrograph on the node element using the Redux store for state information. The siteno, latitude, and
* longitude are required parameters. All others are optional and are used to set the initial state of the hydrograph.
Bucknell, Mary S.
committed
* @param {Redux store} store
* @param {DOM node} node
* @param {Object} - string properties to set initial state information. The property siteno is required
* @param {Promise} loadPromise - will resolve when any data needed by this module
* that is fetched by the caller has been fetched
* */
Bucknell, Mary S.
committed
sitename,
parameterCode,
compare,
period,
startDT,
endDT,
showOnlyGraph = false,
showMLName = false
Bucknell, Mary S.
committed
const nodeElem = select(node);
Bucknell, Mary S.
committed
if (!config.ivPeriodOfRecord && !config.gwPeriodOfRecord) {
select(node).select('.select-actions-container').call(drawSelectActions, store, siteno, agencyCd);
Bucknell, Mary S.
committed
select(node).select('.graph-container').call(drawInfoAlert, {title: 'Hydrograph Alert', body: 'No IV or field visit data is available.'});
Bucknell, Mary S.
committed
}
Bucknell, Mary S.
committed
const initialLoadCompare = compare === 'true' || compare === true ? true : false;
const thisShowOnlyGraph = showOnlyGraph === 'true' || showOnlyGraph === true ? true : false;
const thisShowMLName = showMLName === 'true' || showMLName === true ? true : false;
Bucknell, Mary S.
committed
// Initialize all hydrograph state variables
store.dispatch(setSelectedParameterCode(parameterCode));
store.dispatch(setCompareDataVisibility(initialLoadCompare));
if (period) {
Bucknell, Mary S.
committed
store.dispatch(setSelectedTimeSpan(period));
} else if (startDT && endDT) {
Bucknell, Mary S.
committed
store.dispatch(setSelectedTimeSpan({
start: startDT,
end: endDT
}));
} else {
store.dispatch(setSelectedTimeSpan(config.ivPeriodOfRecord && config.ivPeriodOfRecord[parameterCode] ?
'P7D' : 'P1Y'));
Bucknell, Mary S.
committed
}
Bucknell, Mary S.
committed
Bucknell, Mary S.
committed
// Fetch all data needed to render the hydrograph
Bucknell, Mary S.
committed
const fetchHydrographDataPromise = store.dispatch(retrieveHydrographData(siteno, agencyCd,
getInputsForRetrieval(store.getState())));
Bucknell, Mary S.
committed
let fetchDataPromises = [fetchHydrographDataPromise];
Bucknell, Mary S.
committed
Bucknell, Mary S.
committed
// if showing only graph make a call to retrieve all of the groundwater level data. Otherwise
// this is done when retrieving all hydrograph parameter meta data.
if (thisShowOnlyGraph) {
if (config.gwPeriodOfRecord) {
fetchDataPromises.push(store.dispatch(retrieveGroundwaterLevelData(siteno, agencyCd)));
}
} else {
fetchDataPromises.push(store.dispatch(retrieveHydrographParameters(siteno, agencyCd)));
}
Bucknell, Mary S.
committed
Bucknell, Mary S.
committed
// Fetch flood levels
Bucknell, Mary S.
committed
if (config.ivPeriodOfRecord && config.GAGE_HEIGHT_PARAMETER_CODE in config.ivPeriodOfRecord) {
Bucknell, Mary S.
committed
const fetchFloodLevelsPromise = store.dispatch(floodDataActions.retrieveFloodLevels(siteno));
Bucknell, Mary S.
committed
// If flood levels are to be shown then wait to render the hydrograph until those have been fetched.
if (parameterCode === config.GAGE_HEIGHT_PARAMETER_CODE) {
fetchDataPromises.push(fetchFloodLevelsPromise);
}
Bucknell, Mary S.
committed
}
Bucknell, Mary S.
committed
Bucknell, Mary S.
committed
// Render initial UI elements prior to completion of data fetching
if (!showOnlyGraph) {
nodeElem.select('.short-cut-time-span-container').call(drawTimeSpanShortcutButtons, store, siteno, agencyCd);
select(node).select('.select-actions-container').call(drawSelectActions, store, siteno, agencyCd);
Bucknell, Mary S.
committed
}
Bucknell, Mary S.
committed
const graphContainer = nodeElem.select('.graph-container');
graphContainer.call(initializeTimeSeriesGraph, store, siteno, agencyCd, sitename, thisShowMLName, !thisShowOnlyGraph);
showDataIndicators(true, store);
if (!showOnlyGraph) {
initializeTooltipCursorSlider(graphContainer, store);
initializeGraphBrush(graphContainer, store);
Bucknell, Mary S.
committed
}
Bucknell, Mary S.
committed
const legendControlsContainer = graphContainer.append('div')
.classed('ts-legend-controls-container', true);
if (!showOnlyGraph) {
legendControlsContainer.call(drawGraphControls, store, siteno);
nodeElem.select('.select-time-series-container')
.call(drawSelectionList, store, siteno, agencyCd);
Bucknell, Mary S.
committed
}
// Once hydrograph data has been fetched, render the time series data.
Bucknell, Mary S.
committed
Promise.all(fetchDataPromises).then(() => {
Bucknell, Mary S.
committed
// selectedIVMethodID should be set regardless of whether we are showing only the graph but the preferred method ID
// can not be determined until the data is fetched so that is done here.
const initialIVMethodID = timeSeriesId || getPreferredIVMethodID(store.getState());
store.dispatch(setSelectedIVMethodID(initialIVMethodID));
Bucknell, Mary S.
committed
showDataIndicators(false, store);
Bucknell, Mary S.
committed
graphContainer.call(drawTimeSeriesGraphData, store, !thisShowOnlyGraph);
Bucknell, Mary S.
committed
if (!thisShowOnlyGraph) {
Bucknell, Mary S.
committed
graphContainer
.call(drawTooltipCursorSlider, store)
.call(drawGraphBrush, store);
}
Bucknell, Mary S.
committed
legendControlsContainer.call(drawTimeSeriesLegend, store);
Bucknell, Mary S.
committed
if (!thisShowOnlyGraph) {
Bucknell, Mary S.
committed
nodeElem.select('#iv-data-table-container')
.call(drawDataTables, store, siteno, agencyCd);
Bucknell, Mary S.
committed
renderTimeSeriesUrlParams(store);
nodeElem.select('#stats-container')
.call(link(store, drawStatsTable, createStructuredSelector({
stats: getStatisticsData,
latestValue: getLatestPrimaryValue,
parameterName: getTitle
Bucknell, Mary S.
committed
}
Bucknell, Mary S.
committed
})
.catch(reason => {
console.error(reason);
throw reason;
Bucknell, Mary S.
committed
});