Skip to content
Snippets Groups Projects
Commit 3342b219 authored by Bucknell, Mary S.'s avatar Bucknell, Mary S.
Browse files

Start of refactor of the time-span-controls starting with the calendar dates.

parent b6268d96
No related branches found
No related tags found
No related merge requests found
...@@ -3,7 +3,7 @@ import {createStructuredSelector} from 'reselect'; ...@@ -3,7 +3,7 @@ import {createStructuredSelector} from 'reselect';
import config from 'ui/config'; import config from 'ui/config';
import {link} from 'ui/lib/d3-redux'; import {link} from 'ui/lib/d3-redux';
import {getSelectedParameterCode, getSelectedDateRange} from 'ml/selectors/hydrograph-state-selector'; import {getSelectedParameterCode, getSelectedTimeSpan} from 'ml/selectors/hydrograph-state-selector';
import {getTimeRange} from 'ml/selectors/hydrograph-data-selector'; import {getTimeRange} from 'ml/selectors/hydrograph-data-selector';
import {retrieveMedianStatistics, retrievePriorYearIVData} from 'ml/store/hydrograph-data'; import {retrieveMedianStatistics, retrievePriorYearIVData} from 'ml/store/hydrograph-data';
...@@ -58,15 +58,15 @@ export const drawGraphControls = function(elem, store, siteno) { ...@@ -58,15 +58,15 @@ export const drawGraphControls = function(elem, store, siteno) {
} }
}) })
// Sets the state of the toggle // Sets the state of the toggle
.call(link(store,function(elem, {checked, selectedDateRange, parameterCode}) { .call(link(store,function(elem, {checked, selectedTimeSpan, parameterCode}) {
elem.property('checked', checked) elem.property('checked', checked)
.attr('disabled', .attr('disabled',
hasIVData(parameterCode) && hasIVData(parameterCode) &&
selectedDateRange !== 'custom' && config.ALLOW_COMPARE_DATA_FOR_PERIODS.includes(selectedDateRange) ? typeof selectedTimeSpan === 'string' && config.ALLOW_COMPARE_DATA_FOR_PERIODS.includes(selectedTimeSpan) ?
null : true); null : true);
}, createStructuredSelector({ }, createStructuredSelector({
checked: isVisible('compare'), checked: isVisible('compare'),
selectedDateRange: getSelectedDateRange, selectedTimeSpan: getSelectedTimeSpan,
parameterCode: getSelectedParameterCode parameterCode: getSelectedParameterCode
}))); })));
compareControlDiv.append('label') compareControlDiv.append('label')
......
...@@ -12,7 +12,7 @@ import {renderTimeSeriesUrlParams} from 'ml/url-params'; ...@@ -12,7 +12,7 @@ import {renderTimeSeriesUrlParams} from 'ml/url-params';
import {retrieveHydrographData} from 'ml/store/hydrograph-data'; import {retrieveHydrographData} from 'ml/store/hydrograph-data';
import {retrieveHydrographParameters} from 'ml/store/hydrograph-parameters'; import {retrieveHydrographParameters} from 'ml/store/hydrograph-parameters';
import {setSelectedParameterCode, setCompareDataVisibility, setSelectedCustomDateRange, setSelectedDateRange, import {setSelectedParameterCode, setCompareDataVisibility, setSelectedTimeSpan,
setSelectedIVMethodID setSelectedIVMethodID
} from 'ml/store/hydrograph-state'; } from 'ml/store/hydrograph-state';
...@@ -90,12 +90,14 @@ export const attachToNode = function(store, ...@@ -90,12 +90,14 @@ export const attachToNode = function(store,
store.dispatch(setSelectedParameterCode(parameterCode)); store.dispatch(setSelectedParameterCode(parameterCode));
store.dispatch(setCompareDataVisibility(initialLoadCompare)); store.dispatch(setCompareDataVisibility(initialLoadCompare));
if (period) { if (period) {
store.dispatch(setSelectedDateRange(period)); store.dispatch(setSelectedTimeSpan(period));
} else if (startDT && endDT) { } else if (startDT && endDT) {
store.dispatch(setSelectedDateRange('custom')); store.dispatch(setSelectedTimeSpan({
store.dispatch(setSelectedCustomDateRange(startDT, endDT)); start: startDT,
end: endDT
}));
} else { } else {
store.dispatch(setSelectedDateRange('P7D')); store.dispatch(setSelectedTimeSpan('P7D'));
} }
// Fetch waterwatch flood levels // Fetch waterwatch flood levels
......
import {select} from 'd3-selection'; import {select} from 'd3-selection';
import {getSelectedCustomDateRange, getSelectedDateRange} from 'ml/selectors/hydrograph-state-selector'; import {drawTimeSpanControls} from './time-span-controls';
import {drawDateRangeControls} from './date-controls';
import {drawDownloadForm} from './download-data'; import {drawDownloadForm} from './download-data';
/* /*
...@@ -13,6 +11,7 @@ const appendButton = function(listContainer, {faIcon, buttonLabel, idOfDivToCont ...@@ -13,6 +11,7 @@ const appendButton = function(listContainer, {faIcon, buttonLabel, idOfDivToCont
.attr('class', 'usa-button-group__item') .attr('class', 'usa-button-group__item')
.append('button') .append('button')
.attr('class', 'usa-button') .attr('class', 'usa-button')
.attr('role', 'checkbox')
.attr('aria-expanded', false) .attr('aria-expanded', false)
.attr('aria-controls', idOfDivToControl) .attr('aria-controls', idOfDivToControl)
.attr('ga-on', 'click') .attr('ga-on', 'click')
...@@ -69,7 +68,7 @@ export const drawSelectActions = function(container, store, siteno) { ...@@ -69,7 +68,7 @@ export const drawSelectActions = function(container, store, siteno) {
container.append('div') container.append('div')
.attr('id', 'change-time-span-container') .attr('id', 'change-time-span-container')
.attr('hidden', true) .attr('hidden', true)
.call(drawDateRangeControls, store, siteno, getSelectedDateRange(state), getSelectedCustomDateRange(state)); .call(drawTimeSpanControls, store, siteno);
container.append('div') container.append('div')
.attr('id', 'download-graph-data-container') .attr('id', 'download-graph-data-container')
.attr('hidden', true) .attr('hidden', true)
......
...@@ -5,10 +5,10 @@ import {datePicker, dateRangePicker} from 'uswds-components'; ...@@ -5,10 +5,10 @@ import {datePicker, dateRangePicker} from 'uswds-components';
import config from 'ui/config'; import config from 'ui/config';
import {getInputsForRetrieval} from 'ml/selectors/hydrograph-state-selector'; import {getInputsForRetrieval, getSelectedTimeSpan} from 'ml/selectors/hydrograph-state-selector';
import {retrieveHydrographData} from 'ml/store/hydrograph-data'; import {retrieveHydrographData} from 'ml/store/hydrograph-data';
import {clearGraphBrushOffset, setSelectedDateRange, setSelectedCustomDateRange} from 'ml/store/hydrograph-state'; import {clearGraphBrushOffset, setSelectedTimeSpan} from 'ml/store/hydrograph-state';
import {showDataIndicators} from './data-indicator'; import {showDataIndicators} from './data-indicator';
...@@ -106,29 +106,25 @@ const drawCustomDaysBeforeForm = function(container, store, siteno, initialDateR ...@@ -106,29 +106,25 @@ const drawCustomDaysBeforeForm = function(container, store, siteno, initialDateR
* @param {String} label - label for the date picker * @param {String} label - label for the date picker
* @param {String} initialDate - ISO 8601 Date format * @param {String} initialDate - ISO 8601 Date format
*/ */
const drawDatePicker = function(container, id, label, initialDate) { const drawDatePicker = function(container, id, ariaLabel, initialDate) {
container.append('label') const formGroup = container.append('div')
.attr('class', 'usa-label') .attr('class', 'usa-form-group');
.attr('id', `${id}-label`) formGroup.append('div')
.attr('for', id)
.text(label);
container.append('div')
.attr('class', 'usa-hint') .attr('class', 'usa-hint')
.attr('id', `${id}-hint`) .attr('id', `${id}-hint`)
.text('mm/dd/yyyy') .text('mm/dd/yyyy');
.append('div') formGroup.append('div')
.attr('class', 'usa-date-picker') .attr('class', 'usa-date-picker time-span-date-range-picker')
.attr('data-default-value', initialDate) .attr('data-default-value', initialDate ? initialDate : null)
.attr('data-min-date', '1900-01-01') .append('input')
.attr('data-max-date', '2100-12-31') .attr('class', 'usa-input')
.append('input') .attr('type', 'text')
.attr('class', 'usa-input') .attr('maxlength', 10)
.attr('type', 'text') .attr('size', 10)
.attr('id', id) .attr('id', id)
.attr('name', id) .attr('name', id)
.attr('aria-describedby', `${id}-label ${id}-hint`) .attr('aria-label', ariaLabel)
.attr('type', 'text'); .attr('aria-describedby', `${id}-hint`);
}; };
/* /*
...@@ -136,112 +132,27 @@ const drawDatePicker = function(container, id, label, initialDate) { ...@@ -136,112 +132,27 @@ const drawDatePicker = function(container, id, label, initialDate) {
* @param {D3 selection} container * @param {D3 selection} container
* @param {Redux store} store * @param {Redux store} store
* @param {String} siteno * @param {String} siteno
* @param {String} initialDateRange - if 'custom' then this container is made visible
* @param {Object} initialCustomDateRange - has start and end String properties containing an ISO 8601 date string
* and is used to set the initial values of the calendar pickers
*/ */
const drawDateRangeForm = function(container, store, siteno) { const drawDateRangeForm = function(container, store) {
const calendarDaysContainer = container.append('div') const initialTimeSpan = getSelectedTimeSpan(store.getState());
.attr('id', 'ts-customdaterange-select-container') const hasInitialDateRange = !isISODuration(initialTimeSpan);
.attr('role', 'customdate') container.append('span')
.attr('class', 'usa-form') .text('Date range:');
.attr('aria-label', 'Custom date specification') const dateRangePickerContainer = container.append('div')
.attr('hidden', !isCustomPeriod(initialDateRange) ? null : true); .attr('class', 'usa-date-range-picker')
.call(drawDatePicker, 'start-date', 'Start date', hasInitialDateRange ? initialTimeSpan.start : '');
const dateRangePickerContainer = calendarDaysContainer.append('div') dateRangePickerContainer.append('span').text('to');
.attr('class', 'usa-date-range-picker'); dateRangePickerContainer.call(drawDatePicker, 'end-date', 'End date', hasInitialDateRange ? initialTimeSpan.end : '');
dateRangePickerContainer.append('div')
.attr('id', 'start-date-form-group')
.attr('class', 'usa-form-group')
.call(drawDatePicker, 'custom-start-date', 'Start Date', initialCustomDateRange ? initialCustomDateRange.start : '');
dateRangePickerContainer.append('div')
.attr('id', 'end-date-form-group')
.attr('class', 'usa-form-group')
.call(drawDatePicker, 'custom-end-date', 'End Date', initialCustomDateRange ? initialCustomDateRange.end : '');
const calendarDaysValidationContainer = calendarDaysContainer.append('div')
.attr('class', 'usa-alert usa-alert--warning usa-alert--validation')
.attr('id', 'custom-date-alert-container')
.attr('hidden', true);
const dateAlertBody = calendarDaysValidationContainer.append('div')
.attr('class', 'usa-alert__body')
.attr('id', 'custom-date-alert');
dateAlertBody.append('h3')
.attr('class', 'usa-alert__heading')
.text('Date requirements');
// required to init the USWDS date picker after page load before calling the // required to init the USWDS date picker after page load before calling the
// dateRangePicker on function // dateRangePicker on function
datePicker.init(dateRangePickerContainer.node()); datePicker.init(dateRangePickerContainer.node());
// required to init the USWDS date range picker after page load // required to init the USWDS date range picker after page load
dateRangePicker.on(dateRangePickerContainer.node()); dateRangePicker.on(dateRangePickerContainer.node());
// Adds controls for the calendar day submit button
const calendarDaysSubmitContainer = calendarDaysContainer.append('div')
.attr('class', 'submit-button');
calendarDaysSubmitContainer.append('button')
.attr('class', 'usa-button')
.attr('id', 'custom-date-submit-calendar')
.attr('ga-on', 'click')
.attr('ga-event-category', 'TimeSeriesGraph')
.attr('ga-event-action', 'customDateSubmit')
.text('Display data on graph')
.on('click', function() {
const startDateStr = calendarDaysContainer.select('#custom-start-date').property('value');
const endDateStr = calendarDaysContainer.select('#custom-end-date').property('value');
if (startDateStr.length === 0 || endDateStr.length === 0) {
dateAlertBody.selectAll('p').remove();
dateAlertBody.append('p')
.text('Both start and end dates must be specified.');
calendarDaysValidationContainer.attr('hidden', null);
} else {
const startTime = DateTime.fromFormat(startDateStr, 'LL/dd/yyyy', {zone: config.locationTimeZone}).toMillis();
const endTime = DateTime.fromFormat(endDateStr, 'LL/dd/yyyy', {zone: config.locationTimeZone}).toMillis();
if (startTime > endTime) {
dateAlertBody.selectAll('p').remove();
dateAlertBody.append('p')
.text('The start date must precede the end date.');
calendarDaysValidationContainer.attr('hidden', null);
} else {
calendarDaysValidationContainer.attr('hidden', true);
store.dispatch(clearGraphBrushOffset());
store.dispatch(setSelectedCustomDateRange(DateTime.fromMillis(startTime, {zone: config.locationTimeZone}).toISODate(),
DateTime.fromMillis(endTime, {zone: config.locationTimeZone}).toISODate()));
store.dispatch(setSelectedDateRange('custom'));
showDataIndicators(true, store);
store.dispatch(retrieveHydrographData(siteno, getInputsForRetrieval(store.getState())))
.then(() => {
showDataIndicators(false, store);
});
}
}
});
}; };
/* export const drawTimeSpanControls = function(container, store, siteno) {
* Renders the date controls used to set the time range. This can be done by using short cut selections or by container.append('div')
* using the custom date range form. .attr('class', 'date-range-container')
* @param {D3 selection} elem .call(drawDateRangeForm, store);
* @param {Redux store} store
* @param {String} siteno
* @param {String} initialDateRange
* @param {Object} initialCustomDateRange - has string start and end components containing an ISO 8601 date string
*/
export const drawDateRangeControls = function(elem, store, siteno, initialDateRange, initialCustomDateRange) {
// Add a container that holds the custom selection radio buttons and the form fields
elem.append('div')
.attr('id', 'ts-daterange-select-container')
.attr('role', 'radiogroup')
.attr('aria-label', 'Time interval select')
.call(drawSelectRadioButtons, store, siteno, initialDateRange);
elem.append('div')
.attr('id', 'container-radio-group-and-form-buttons')
.call(drawCustomRadioButtons, initialDateRange)
.call(drawCustomDaysBeforeForm, store, siteno, initialDateRange)
.call(drawCustomCalendarDaysForm, store, siteno, initialDateRange, initialCustomDateRange);
setCustomFormVisibility(showCustomContainer(initialDateRange));
};
export const drawTimeSpanControl = function(container, store, siteno) {
}; };
import {createStructuredSelector} from 'reselect'; import {createStructuredSelector} from 'reselect';
import {listen} from 'ui/lib/d3-redux'; import {listen} from 'ui/lib/d3-redux';
import {getPrimaryMethods} from 'ml/selectors/hydrograph-data-selector'; import {getPrimaryMethods} from 'ml/selectors/hydrograph-data-selector';
import {isCompareIVDataVisible, getSelectedIVMethodID, getSelectedDateRange, getSelectedCustomDateRange, import {isCompareIVDataVisible, getSelectedIVMethodID, getSelectedTimeSpan,
getSelectedParameterCode getSelectedParameterCode
} from 'ml/selectors/hydrograph-state-selector'; } from 'ml/selectors/hydrograph-state-selector';
...@@ -21,23 +22,11 @@ export const renderTimeSeriesUrlParams = function(store) { ...@@ -21,23 +22,11 @@ export const renderTimeSeriesUrlParams = function(store) {
methodId: getSelectedIVMethodID, methodId: getSelectedIVMethodID,
methods: getPrimaryMethods, methods: getPrimaryMethods,
compare: isCompareIVDataVisible, compare: isCompareIVDataVisible,
currentDateRange: getSelectedDateRange, timeSpan: getSelectedTimeSpan
customDateRange: getSelectedCustomDateRange }), ({parameterCode, methodId, methods, compare, timeSpan}) => {
}), ({parameterCode, methodId, methods, compare, currentDateRange, customDateRange}) => { const timeSpanIsDuration = typeof timeSpan === 'string';
let params = new window.URLSearchParams(); let params = new window.URLSearchParams();
/* filter the 'currentDateRange', which comes in one of two forms
* 'P{some number}{Day or Year code}' (like P30D or P1Y) or the word 'custom'.
* In this case, 'custom' is a selection not using the 'period query', such as start and end date calendar dates.
* If the user selection is the default of 'P7D' or of the type 'custom', we will leave it as is.
* Otherwise, we will filter the code so it is generic and in the form of 'P'
* so that it will work for any arbitrary number of days in query parameters such as P20D.
*/
const filteredCurrentDateRange =
currentDateRange === 'P7D' ? 'P7D' :
currentDateRange === 'custom' ? currentDateRange :
currentDateRange !== null ? currentDateRange.substr(0, 1) : '';
if (parameterCode) { if (parameterCode) {
params.set('parameterCode', parameterCode); params.set('parameterCode', parameterCode);
} }
...@@ -45,17 +34,13 @@ export const renderTimeSeriesUrlParams = function(store) { ...@@ -45,17 +34,13 @@ export const renderTimeSeriesUrlParams = function(store) {
if (Object.keys(methods).length > 1) { if (Object.keys(methods).length > 1) {
params.set('timeSeriesId', methodId); params.set('timeSeriesId', methodId);
} }
if (timeSpanIsDuration) {
switch(filteredCurrentDateRange) { params.set('period', timeSpan);
case 'P7D': } else {
break; params.set('startDT', timeSpan.start);
case 'P': params.set('endDT', timeSpan.end);
params.set('period', currentDateRange);
break;
case 'custom':
params.set('startDT', customDateRange.start);
params.set('endDT', customDateRange.end);
} }
if (compare) { if (compare) {
params.set('compare', true); params.set('compare', true);
} }
......
...@@ -3,58 +3,26 @@ ...@@ -3,58 +3,26 @@
*/ */
@import './variables'; @import './variables';
#ts-daterange-select-container { #ts-method-select-container {
ul { @include u-margin-bottom(2);
display: inline-block;
li {
display: inline-block;
label {
margin: 0;
@include u-margin-bottom(1);
width: 110px;
}
}
}
} }
#container-radio-group-and-form-buttons {
border: solid 1px color('black'); #change-time-span-container {
@include u-margin-bottom(1); @include u-padding(2);
#ts-custom-date-radio-group { .date-range-container {
@include u-padding-left(1); div {
p {
@include u-text('bold');
@include u-margin-bottom(1);
}
ul {
display: inline-block; display: inline-block;
li {
display: inline-block;
@include u-padding-right(1);
}
} }
} .usa-date-picker {
#ts-custom-days-before-today-select-container { width: 11rem;
@include u-padding-right(1);
@include u-padding-bottom(1);
@include u-padding-left(1);
.usa-label {
@include u-text('bold');
} }
}
#ts-customdaterange-select-container { .usa-date-picker__calendar {
@include u-padding-right(1); width: units($theme-input-max-width);
@include u-padding-bottom(1);
@include u-padding-left(1);
label {
@include u-text('bold');
} }
} }
} }
#ts-method-select-container {
@include u-margin-bottom(2);
}
#download-graph-data-container > div { #download-graph-data-container > div {
@include grid-row; @include grid-row;
@include grid-gap; @include grid-gap;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment