Skip to content
Snippets Groups Projects
index.js 10.7 KiB
Newer Older
  • Learn to ignore specific revisions
  •  * Hydrograph charting module.
     */
    
    import {select} from 'd3-selection';
    
    import {bindActionCreators} from 'redux';
    import ReduxConnectVue from 'redux-connect-vue';
    import {createStructuredSelector} from 'reselect';
    
    import config from 'ui/config.js';
    
    import {drawInfoAlert} from 'd3render/alerts';
    
    import {renderTimeSeriesUrlParams} from 'ml/url-params';
    
    import {getInputsForRetrieval} from 'ml/selectors/hydrograph-state-selector';
    
    
    import {retrieveGroundwaterLevelData} from 'ml/store/groundwater-level-field-visits';
    
    import {retrieveHydrographData} from 'ml/store/hydrograph-data';
    
    import {retrieveHydrographParameters} from 'ml/store/hydrograph-parameters';
    
    import {setSelectedParameterCode, setCompareDataVisibility, setSelectedTimeSpan,
    
    Briggs, Aaron Shane's avatar
    Briggs, Aaron Shane committed
        setSelectedIVMethodID
    
    } from 'ml/store/hydrograph-state';
    
    import {Actions as floodDataActions} from 'ml/store/flood-data';
    
    Williams, Darius Shamar's avatar
    Williams, Darius Shamar committed
    import {getPreferredIVMethodID} from './selectors/time-series-data';
    
    
    import {showDataIndicators} from './data-indicator';
    
    import {drawTimeSeriesLegend} from './legend';
    
    import {initializeTimeSeriesGraph, drawTimeSeriesGraphData} from './time-series-graph';
    import {initializeTooltipCursorSlider, drawTooltipCursorSlider} from './tooltip';
    
    import DataTablesApp from './DataTablesApp.vue';
    
    import GraphControlsApp from './GraphControlsApp.vue';
    
    import HydrographApp from './HydrographApp.vue';
    
    import ParameterSelectionApp from './ParameterSelectionApp.vue';
    
    Williams, Darius Shamar's avatar
    Williams, Darius Shamar committed
    import StatisticsTableApp from './StatisticsTableApp.vue';
    
    import TimeDownloadGraphControlsApp from './TimeDownloadGraphControlsApp.vue';
    
    /* eslint-disable vue/one-component-per-file */
    
    /*
     * 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.
    
     * @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
     * */
    
    export const attachToNode = function(store,
    
                                         node,
                                         {
                                             siteno,
    
                                             agencyCd,
    
                                             parameterCode,
                                             compare,
                                             period,
                                             startDT,
                                             endDT,
    
                                             timeSeriesId,
    
                                             showOnlyGraph = false,
                                             showMLName = false
    
    Briggs, Aaron Shane's avatar
    Briggs, Aaron Shane committed
        const addTimeDownloadGraphControlsApp = function() {
            const timeDownloadGraphControlsApp = createApp(TimeDownloadGraphControlsApp, {});
            timeDownloadGraphControlsApp.use(ReduxConnectVue, {
                store,
                mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
                mapStateToPropsFactory: createStructuredSelector
            });
            timeDownloadGraphControlsApp.provide('store', store);
            timeDownloadGraphControlsApp.provide('siteno', siteno);
            timeDownloadGraphControlsApp.provide('agencyCd', agencyCd);
            timeDownloadGraphControlsApp.mount('#time-download-graph-controls-anchor');
        };
    
    
        if (!config.ivPeriodOfRecord && !config.gwPeriodOfRecord) {
    
    Briggs, Aaron Shane's avatar
    Briggs, Aaron Shane committed
            addTimeDownloadGraphControlsApp();
    
            select(node).select('.graph-container').call(drawInfoAlert, {title: 'Hydrograph Alert', body: 'No IV or field visit data is available.'});
    
        const initialLoadCompare = compare === 'true' || compare === true ? true : false;
    
        const thisShowOnlyGraph = showOnlyGraph === 'true' || showOnlyGraph === true ? true : false;
        const thisShowMLName = showMLName === 'true' || showMLName === true ? true : false;
    
        // Initialize all hydrograph state variables
    
        store.dispatch(setSelectedParameterCode(parameterCode));
        store.dispatch(setCompareDataVisibility(initialLoadCompare));
        if (period) {
    
            store.dispatch(setSelectedTimeSpan(period));
    
            store.dispatch(setSelectedTimeSpan({
                start: startDT,
                end: endDT
            }));
    
            store.dispatch(setSelectedTimeSpan(config.ivPeriodOfRecord && config.ivPeriodOfRecord[parameterCode] ?
                'P7D' : 'P1Y'));
    
        // Fetch all data needed to render the hydrograph
    
        const fetchHydrographDataPromise = store.dispatch(retrieveHydrographData(siteno, agencyCd,
    
            getInputsForRetrieval(store.getState()), true));
    
        let fetchDataPromises = [fetchHydrographDataPromise];
    
        // 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)));
    
        if (config.ivPeriodOfRecord && config.GAGE_HEIGHT_PARAMETER_CODE in config.ivPeriodOfRecord) {
    
            const fetchFloodLevelsPromise =  store.dispatch(floodDataActions.retrieveFloodLevels(siteno));
    
            // 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);
            }
    
        // Render initial UI elements prior to completion of data fetching
        if (!showOnlyGraph) {
    
    Briggs, Aaron Shane's avatar
    Briggs, Aaron Shane committed
            addTimeDownloadGraphControlsApp();
    
        const graphContainer = nodeElem.select('.graph-container');
        graphContainer.call(initializeTimeSeriesGraph, store, siteno, agencyCd, sitename, thisShowMLName, !thisShowOnlyGraph);
        showDataIndicators(true, store);
        if (!showOnlyGraph) {
            initializeTooltipCursorSlider(graphContainer, store);
    
            //TODO: The tooltips, legend and  the main hydrograph can be added to the HydrographApp.
            // The main hydrograph should be converted to a Vue component last. As part of that task we
            // will figure out how to handle the loading indicator and the no data overlay
    
            // The addition of the hydrograph-brush-container is merely to create the brush in the correct location
            // This will change as we add things and eventually we won't need to do this.
            graphContainer.append('div').attr('id', 'hydrograph-brush-container');
    
    
            const hydrographApp = createApp(HydrographApp, {});
            hydrographApp.use(ReduxConnectVue, {
                store,
                mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
                mapStateToPropsFactory: createStructuredSelector
            });
            hydrographApp.provide('store', store);
    
            hydrographApp.provide('initialLoadingComplete', initialLoadingComplete);
    
            hydrographApp.mount('#hydrograph-brush-container');
    
        const legendControlsContainer = graphContainer.append('div')
            .classed('ts-legend-controls-container', true);
        if (!showOnlyGraph) {
    
            const graphControlsApp = createApp(GraphControlsApp, {});
            graphControlsApp.use(ReduxConnectVue, {
                store,
                mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
                mapStateToPropsFactory: createStructuredSelector
            });
            graphControlsApp.provide('store', store);
            graphControlsApp.provide('siteno', siteno);
            graphControlsApp.mount('.ts-legend-controls-container');
    
    
            const parameterSelectionApp = createApp(ParameterSelectionApp, {});
            parameterSelectionApp.use(ReduxConnectVue, {
                store,
                mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
                mapStateToPropsFactory: createStructuredSelector
            });
            parameterSelectionApp.provide('store', store);
            parameterSelectionApp.provide('siteno', siteno);
            parameterSelectionApp.provide('agencyCode', agencyCd);
            parameterSelectionApp.mount('.select-time-series-container');
    
        }
    
        // Once hydrograph data has been fetched, render the time series data.
    
        Promise.all(fetchDataPromises).then(() => {
    
            // 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));
    
            graphContainer.call(drawTimeSeriesGraphData, store, !thisShowOnlyGraph);
    
                    .call(drawTooltipCursorSlider, store);
    
            legendControlsContainer.call(drawTimeSeriesLegend, store);
    
                // eslint-disable-next-line vue/one-component-per-file
                const dataTablesApp = createApp(DataTablesApp, {});
                dataTablesApp.use(ReduxConnectVue, {
                    store,
                    mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
                    mapStateToPropsFactory: createStructuredSelector
                });
                dataTablesApp.provide('store', store);
                // data for DownLoadData component
                dataTablesApp.provide('siteno', siteno);
                dataTablesApp.provide('agencyCd', agencyCd);
    
                dataTablesApp.mount('#iv-data-table-container');
    
    
    Williams, Darius Shamar's avatar
    Williams, Darius Shamar committed
                const statisticsTableApp = createApp(StatisticsTableApp, {});
                statisticsTableApp.use(ReduxConnectVue, {
    
    Williams, Darius Shamar's avatar
    Williams, Darius Shamar committed
                    store,
                    mapDispatchToPropsFactory: (actionCreators) => (dispatch) => bindActionCreators(actionCreators, dispatch),
                    mapStateToPropsFactory: createStructuredSelector
                });
    
    Williams, Darius Shamar's avatar
    Williams, Darius Shamar committed
                statisticsTableApp.mount('.daily-statistical-data');
    
        })
        .catch(reason => {
            console.error(reason);
            throw reason;