From a663d3528ed6ef7686b8d651db0638e7e4269747 Mon Sep 17 00:00:00 2001 From: ssoper <ssoper@usgs.gov> Date: Mon, 30 Dec 2019 14:35:35 -0600 Subject: [PATCH] Reorganize code --- .../components/hydrograph/date-controls.js | 12 +- .../hydrograph/date-controls.spec.js | 5 +- .../scripts/components/hydrograph/index.js | 15 +- .../components/hydrograph/index.spec.js | 5 + .../scripts/components/hydrograph/legend.js | 15 +- .../components/hydrograph/legend.spec.js | 231 +++++++++++------- .../hydrograph/time-series-graph.js | 14 +- .../hydrograph/time-series-graph.spec.js | 34 +-- 8 files changed, 180 insertions(+), 151 deletions(-) diff --git a/assets/src/scripts/components/hydrograph/date-controls.js b/assets/src/scripts/components/hydrograph/date-controls.js index 30fb5756b..214719538 100644 --- a/assets/src/scripts/components/hydrograph/date-controls.js +++ b/assets/src/scripts/components/hydrograph/date-controls.js @@ -1,9 +1,11 @@ -import {dispatch, link} from '../../lib/redux'; -import {hasAnyTimeSeries, isLoadingTS} from '../../selectors/time-series-selector'; -import {DateTime} from 'luxon'; -import {Actions} from '../../store'; -import {createStructuredSelector} from 'reselect'; +import { DateTime } from 'luxon'; +import { createStructuredSelector } from 'reselect'; + +import { dispatch, link } from '../../lib/redux'; + import { loadingIndicator } from './index'; +import { isLoadingTS, hasAnyTimeSeries } from '../../selectors/time-series-selector'; +import { Actions } from '../../store'; export const drawDateRangeControls = function(elem, siteno) { diff --git a/assets/src/scripts/components/hydrograph/date-controls.spec.js b/assets/src/scripts/components/hydrograph/date-controls.spec.js index b6e8b5a4f..bd93f6905 100644 --- a/assets/src/scripts/components/hydrograph/date-controls.spec.js +++ b/assets/src/scripts/components/hydrograph/date-controls.spec.js @@ -1,7 +1,8 @@ import { select } from 'd3-selection'; -import {Actions, configureStore} from '../../store'; -import {attachToNode} from './index'; +import { Actions, configureStore } from '../../store'; + +import { attachToNode } from './index'; const TEST_STATE = { series: { diff --git a/assets/src/scripts/components/hydrograph/index.js b/assets/src/scripts/components/hydrograph/index.js index 55a097f53..2f2101881 100644 --- a/assets/src/scripts/components/hydrograph/index.js +++ b/assets/src/scripts/components/hydrograph/index.js @@ -16,7 +16,7 @@ import { drawDateRangeControls } from './date-controls'; import { lineSegmentsByParmCdSelector } from './drawing-data'; import { drawGraphControls } from './graph-controls'; import { SPARK_LINE_DIM, layoutSelector } from './layout'; -import { drawSimpleLegend, legendMarkerRowsSelector } from './legend'; +import { drawTimeSeriesLegend } from './legend'; import { drawMethodPicker } from './method-picker'; import { plotSeriesSelectTable, availableTimeSeriesSelector } from './parameters'; import { timeSeriesScalesByParmCdSelector } from './scales'; @@ -41,17 +41,6 @@ const drawMessage = function(elem, message) { .html(message); }; - -export const timeSeriesLegend = function(elem) { - elem.append('div') - .classed('hydrograph-container', true) - .call(link(drawSimpleLegend, createStructuredSelector({ - legendMarkerRows: legendMarkerRowsSelector, - layout: layoutSelector - }))); -}; - - /** * Modify styling to hide or display the elem. * @@ -138,7 +127,7 @@ export const attachToNode = function (store, .call(callIf(!showOnlyGraph, cursorSlider)) .append('div') .classed('ts-legend-controls-container', true) - .call(timeSeriesLegend); + .call(drawTimeSeriesLegend); // Add UI interactive elements and the provisional data alert. if (!showOnlyGraph) { diff --git a/assets/src/scripts/components/hydrograph/index.spec.js b/assets/src/scripts/components/hydrograph/index.spec.js index bd11ab013..f5d4ea067 100644 --- a/assets/src/scripts/components/hydrograph/index.spec.js +++ b/assets/src/scripts/components/hydrograph/index.spec.js @@ -171,6 +171,11 @@ describe('Loading indicators and data alerts', () => { select('#hydrograph').remove(); }); + it('empty graph displays warning', () => { + attachToNode({}, graphNode, {}); + expect(graphNode.innerHTML).toContain('No data is available'); + }); + describe('hiding/showing provisional alert', () => { it('Expects the provisional alert to be visible when time series data is provided', () => { diff --git a/assets/src/scripts/components/hydrograph/legend.js b/assets/src/scripts/components/hydrograph/legend.js index eb0381eaa..3d7db8dc1 100644 --- a/assets/src/scripts/components/hydrograph/legend.js +++ b/assets/src/scripts/components/hydrograph/legend.js @@ -1,14 +1,15 @@ // functions to facilitate legend creation for a d3 plot import { set } from 'd3-collection'; import memoize from 'fast-memoize'; -import { createSelector } from 'reselect'; +import {createSelector, createStructuredSelector} from 'reselect'; -import { CIRCLE_RADIUS } from './layout'; +import {CIRCLE_RADIUS, layoutSelector} from './layout'; import { defineLineMarker, defineTextOnlyMarker, defineRectangleMarker } from './markers'; import { currentVariableLineSegmentsSelector, HASH_ID, MASK_DESC } from './drawing-data'; import config from '../../config'; import { getCurrentVariableMedianMetadata } from '../../selectors/median-statistics-selector'; import { mediaQuery } from '../../utils'; +import {link} from '../../lib/redux'; const TS_LABEL = { 'current': 'Current: ', @@ -221,3 +222,13 @@ export const legendMarkerRowsSelector = createSelector( displayItems => createLegendMarkers(displayItems) ); + +export const drawTimeSeriesLegend = function(elem) { + elem.append('div') + .classed('hydrograph-container', true) + .call(link(drawSimpleLegend, createStructuredSelector({ + legendMarkerRows: legendMarkerRowsSelector, + layout: layoutSelector + }))); +}; + diff --git a/assets/src/scripts/components/hydrograph/legend.spec.js b/assets/src/scripts/components/hydrograph/legend.spec.js index aed285f90..6eb29f548 100644 --- a/assets/src/scripts/components/hydrograph/legend.spec.js +++ b/assets/src/scripts/components/hydrograph/legend.spec.js @@ -1,9 +1,99 @@ -import { select } from 'd3-selection'; -import { drawSimpleLegend, legendMarkerRowsSelector } from './legend'; +import { select, selectAll } from 'd3-selection'; +import { drawSimpleLegend, legendMarkerRowsSelector, drawTimeSeriesLegend } from './legend'; import { lineMarker, rectangleMarker, textOnlyMarker } from './markers'; +import {Actions, configureStore} from '../../store'; +import {provide} from '../../lib/redux'; describe('Legend module', () => { + const TEST_DATA = { + series: { + timeSeries: { + '00060:current': { + tsKey: 'current:P7D', + startTime: new Date('2018-03-06T15:45:00.000Z'), + endTime: new Date('2018-03-13T13:45:00.000Z'), + variable: '45807197', + points: [{ + value: 10, + qualifiers: ['P'], + approved: false, + estimated: false + }, { + value: null, + qualifiers: ['P', 'ICE'], + approved: false, + estimated: false + }, { + value: null, + qualifiers: ['P', 'FLD'], + approved: false, + estimated: false + }] + }, + + '00065:compare': { + tsKey: 'compare:P7D', + startTime: new Date('2017-03-06T15:45:00.000Z'), + endTime: new Date('2017-03-13T13:45:00.000Z'), + variable: '45807202', + points: [{ + value: 1, + qualifiers: ['A'], + approved: false, + estimated: false + }, { + value: 2, + qualifiers: ['A'], + approved: false, + estimated: false + }, { + value: 3, + qualifiers: ['E'], + approved: false, + estimated: false + }] + } + }, + variables: { + '45807197': { + variableCode: {value: '00060'}, + variableName: 'Streamflow', + variableDescription: 'Discharge, cubic feet per second', + oid: '45807197' + }, + '45807202': { + variableCode: {value: '00065'}, + variableName: 'Gage height', + oid: '45807202' + } + } + }, + statisticsData: { + median: { + '00060': { + '1': [{ + month_nu: '2', + day_nu: '25', + p50_va: '43', + begin_yr: '1970', + end_yr: '2017', + loc_web_ds: 'This method' + }] + } + } + }, + timeSeriesState: { + currentVariableID: '45807197', + currentDateRange: 'P7D', + showSeries: { + current: true, + compare: true, + median: true + } + } + }; + describe('drawSimpleLegend', () => { let container; @@ -82,94 +172,6 @@ describe('Legend module', () => { describe('legendMarkerRowSelector', () => { - const TEST_DATA = { - series: { - timeSeries: { - '00060:current': { - tsKey: 'current:P7D', - startTime: new Date('2018-03-06T15:45:00.000Z'), - endTime: new Date('2018-03-13T13:45:00.000Z'), - variable: '45807197', - points: [{ - value: 10, - qualifiers: ['P'], - approved: false, - estimated: false - }, { - value: null, - qualifiers: ['P', 'ICE'], - approved: false, - estimated: false - }, { - value: null, - qualifiers: ['P', 'FLD'], - approved: false, - estimated: false - }] - }, - - '00065:compare': { - tsKey: 'compare:P7D', - startTime: new Date('2017-03-06T15:45:00.000Z'), - endTime: new Date('2017-03-13T13:45:00.000Z'), - variable: '45807202', - points: [{ - value: 1, - qualifiers: ['A'], - approved: false, - estimated: false - }, { - value: 2, - qualifiers: ['A'], - approved: false, - estimated: false - }, { - value: 3, - qualifiers: ['E'], - approved: false, - estimated: false - }] - } - }, - variables: { - '45807197': { - variableCode: {value: '00060'}, - variableName: 'Streamflow', - variableDescription: 'Discharge, cubic feet per second', - oid: '45807197' - }, - '45807202': { - variableCode: {value: '00065'}, - variableName: 'Gage height', - oid: '45807202' - } - } - }, - statisticsData: { - median: { - '00060': { - '1': [{ - month_nu: '2', - day_nu: '25', - p50_va: '43', - begin_yr: '1970', - end_yr: '2017', - loc_web_ds: 'This method' - }] - } - } - }, - timeSeriesState: { - currentVariableID: '45807197', - currentDateRange: 'P7D', - showSeries: { - current: true, - compare: true, - median: true - } - } - }; - it('Should return no markers if no time series to show', () => { let newData = { ...TEST_DATA, @@ -237,4 +239,53 @@ describe('Legend module', () => { expect(result[0][3].type).toEqual(rectangleMarker); }); }); + + describe('legends should render', () => { + + let graphNode; + + beforeEach(() => { + let body = select('body'); + let component = body.append('div') + .attr('id', 'hydrograph'); + component.append('div').attr('class', 'loading-indicator-container'); + component.append('div').attr('class', 'graph-container'); + component.append('div').attr('class', 'select-time-series-container'); + component.append('div').attr('class', 'provisional-data-alert'); + + graphNode = document.getElementById('hydrograph'); + + jasmine.Ajax.install(); + }); + + afterEach(() => { + jasmine.Ajax.uninstall(); + select('#hydrograph').remove(); + }); + + let store; + + beforeEach(() => { + store = configureStore(TEST_DATA); + select(graphNode) + .call(provide(store)) + .call(drawTimeSeriesLegend); + }); + + it('Should have 6 legend markers', () => { + expect(selectAll('.legend g').size()).toBe(6); + expect(selectAll('.legend g line.median-step').size()).toBe(1); + }); + + it('Should have 6 legend markers after the compare time series is removed', () => { + store.dispatch(Actions.toggleTimeSeries('compare', false)); + expect(selectAll('.legend g').size()).toBe(6); + }); + + it('Should have 4 legend marker after the compare and median time series are removed', () => { + store.dispatch(Actions.toggleTimeSeries('compare', false)); + store.dispatch(Actions.toggleTimeSeries('median', false)); + expect(selectAll('.legend g').size()).toBe(4); + }); + }); }); diff --git a/assets/src/scripts/components/hydrograph/time-series-graph.js b/assets/src/scripts/components/hydrograph/time-series-graph.js index 023d5c8ac..1255ee18f 100644 --- a/assets/src/scripts/components/hydrograph/time-series-graph.js +++ b/assets/src/scripts/components/hydrograph/time-series-graph.js @@ -1,22 +1,24 @@ import { extent } from 'd3-array'; import { line as d3Line, curveStepAfter } from 'd3-shape'; -import {createTooltipFocus, createTooltipText} from './tooltip'; + import {link} from '../../lib/redux'; -import {CIRCLE_RADIUS_SINGLE_PT, layoutSelector} from './layout'; + import {addSVGAccessibility} from '../../accessibility'; -import {createStructuredSelector} from 'reselect'; -import {descriptionSelector, isVisibleSelector, titleSelector} from './time-series'; import {appendAxes, axesSelector} from './axes'; +import config from '../../config'; import { currentVariableLineSegmentsSelector, getCurrentVariableMedianStatPoints, HASH_ID, MASK_DESC } from './drawing-data'; +import {CIRCLE_RADIUS_SINGLE_PT, layoutSelector} from './layout'; +import {createStructuredSelector} from 'reselect'; import {xScaleSelector, yScaleSelector} from './scales'; -import config from '../../config'; -import {mediaQuery} from '../../utils'; +import {descriptionSelector, isVisibleSelector, titleSelector} from './time-series'; import {getAgencyCode, getMonitoringLocationName} from '../../selectors/time-series-selector'; +import {createTooltipFocus, createTooltipText} from './tooltip'; +import {mediaQuery} from '../../utils'; const plotDataLine = function(elem, {visible, lines, tsKey, xScale, yScale}) { diff --git a/assets/src/scripts/components/hydrograph/time-series-graph.spec.js b/assets/src/scripts/components/hydrograph/time-series-graph.spec.js index 8801c0e8e..27c9242e8 100644 --- a/assets/src/scripts/components/hydrograph/time-series-graph.spec.js +++ b/assets/src/scripts/components/hydrograph/time-series-graph.spec.js @@ -1,5 +1,5 @@ import { select, selectAll } from 'd3-selection'; -import {attachToNode, timeSeriesLegend} from './index'; +import { attachToNode } from './index'; import {Actions, configureStore} from '../../store'; import {provide} from '../../lib/redux'; import {drawTimeSeriesGraph} from './time-series-graph'; @@ -172,11 +172,6 @@ describe('time series graph', () => { select('#hydrograph').remove(); }); - it('empty graph displays warning', () => { - attachToNode({}, graphNode, {}); - expect(graphNode.innerHTML).toContain('No data is available'); - }); - it('single data point renders', () => { const store = configureStore(TEST_STATE); select(graphNode) @@ -324,33 +319,6 @@ describe('time series graph', () => { //TODO: Consider adding a test which checks that the y axis is rescaled by // examining the contents of the text labels. - describe('legends should render', () => { - let store; - - beforeEach(() => { - store = configureStore(TEST_STATE); - select(graphNode) - .call(provide(store)) - .call(timeSeriesLegend); - }); - - it('Should have 6 legend markers', () => { - expect(selectAll('.legend g').size()).toBe(6); - expect(selectAll('.legend g line.median-step').size()).toBe(1); - }); - - it('Should have four legend markers after the compare time series is removed', () => { - store.dispatch(Actions.toggleTimeSeries('compare', false)); - expect(selectAll('.legend g').size()).toBe(4); - }); - - it('Should have two legend marker after the compare and median time series are removed', () => { - store.dispatch(Actions.toggleTimeSeries('compare', false)); - store.dispatch(Actions.toggleTimeSeries('median', false)); - expect(selectAll('.legend g').size()).toBe(2); - }); - }); - describe('compare line', () => { let store; -- GitLab