Skip to content
Snippets Groups Projects
Unverified Commit fd034430 authored by Bucknell, Mary S.'s avatar Bucknell, Mary S. Committed by GitHub
Browse files

Merge pull request #795 from mbucknell/iow-62

Iow 62 - Add Monitoring Location Name and number to graph output
parents 3621ee63 9604eaf0
No related branches found
No related tags found
No related merge requests found
......@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- Image server now accepts the period parameter which should be a ISO-8601 duration format.
However please note that NWIS only accepts periods using xxD.
- Image server shows site name and number above the graph
## [0.22.0](https://github.com/usgs/waterdataui/compare/waterdataui-0.21.0...waterdataui-0.22.0) - 2019-12-12
### Changed
......
......@@ -12,7 +12,8 @@ import { dispatch, link, provide } from '../../lib/redux';
import { addSVGAccessibility } from '../../accessibility';
import config from '../../config';
import { isLoadingTS, hasAnyTimeSeries } from '../../selectors/time-series-selector';
import {isLoadingTS, hasAnyTimeSeries, getMonitoringLocationName,
getAgencyCode} from '../../selectors/time-series-selector';
import { Actions } from '../../store';
import { callIf, mediaQuery } from '../../utils';
......@@ -231,9 +232,20 @@ const plotAllMedianPoints = function (elem, {visible, xscale, yscale, seriesPoin
};
const createTitle = function(elem) {
elem.append('div')
.classed('time-series-graph-title', true)
const createTitle = function(elem, siteNo, showMLName) {
let titleDiv = elem.append('div')
.classed('time-series-graph-title', true);
if (showMLName) {
titleDiv.append('div')
.call(link((elem, {mlName, agencyCode}) => {
elem.html(`${mlName}, ${agencyCode} ${siteNo}`);
}, createStructuredSelector({
mlName: getMonitoringLocationName(siteNo),
agencyCode: getAgencyCode(siteNo)
})));
}
titleDiv.append('div')
.call(link((elem, title) => {
elem.html(title);
}, titleSelector));
......@@ -262,11 +274,11 @@ const watermark = function (elem) {
}, layoutSelector));
};
export const timeSeriesGraph = function(elem) {
export const timeSeriesGraph = function(elem, siteNo, showMLName) {
elem.append('div')
.attr('class', 'hydrograph-container')
.call(watermark)
.call(createTitle)
.call(createTitle, siteNo, showMLName)
.call(createTooltipText)
.append('svg')
.attr('xmlns', 'http://www.w3.org/2000/svg')
......@@ -501,7 +513,17 @@ const dataLoadingAlert = function(elem, message) {
}
};
export const attachToNode = function (store, node, {siteno, parameter, compare, period, cursorOffset, showOnlyGraph = false} = {}) {
export const attachToNode = function (store,
node,
{
siteno,
parameter,
compare,
period,
cursorOffset,
showOnlyGraph = false,
showMLName = false
} = {}) {
const nodeElem = select(node);
if (!siteno) {
select(node).call(drawMessage, 'No data is available.');
......@@ -541,7 +563,7 @@ export const attachToNode = function (store, node, {siteno, parameter, compare,
// Set up rendering functions for the graph-container
nodeElem.select('.graph-container')
.call(link(controlDisplay, hasAnyTimeSeries))
.call(timeSeriesGraph, siteno)
.call(timeSeriesGraph, siteno, showMLName)
.call(callIf(!showOnlyGraph, cursorSlider))
.append('div')
.classed('ts-legend-controls-container', true)
......
......@@ -8,6 +8,10 @@ import { createSelector } from 'reselect';
*/
export const getVariables = state => state.series.variables ? state.series.variables : null;
export const getSourceInfo = state => state.series.sourceInfo || {};
export const getSiteCodes = state => state.series.siteCodes || {};
export const getMethods = state => state.series.methods ? state.series.methods : {};
export const getQueryInfo = state => state.series.queryInfo || {};
......@@ -33,6 +37,23 @@ export const hasAnyTimeSeries = state => state.series && state.series.timeSeries
* Selectors the return derived data from the state
*/
/*
* @param {String} siteno
* @return {String} monitoring loation name. Returns empty string if state does not contain siteNo.
*/
export const getMonitoringLocationName = memoize((siteNo) => createSelector(
getSourceInfo,
(sourceInfo) => siteNo in sourceInfo ? sourceInfo[siteNo].siteName || '' : ''
));
/*
* @param {String} siteno
* @return {String} agency code for siteno
*/
export const getAgencyCode = memoize((siteNo) => createSelector(
getSiteCodes,
(siteCodes) => siteNo in siteCodes ? siteCodes[siteNo].agencyCode || '' : ''
));
/*
* @return {Object} Variable details for the currently selected variable or null.
*/
......
import { getVariables, getCurrentVariableID, getCurrentDateRange, getCurrentVariable, getQueryInfo, getRequests, getCurrentParmCd, hasTimeSeries, getTsRequestKey, getTsQueryInfo, getRequestTimeRange, isLoadingTS, getTSRequest, getTimeSeriesCollectionIds, getIanaTimeZone, getNwisTimeZone } from './time-series-selector';
import { getVariables, getSourceInfo, getSiteCodes, getCurrentVariableID, getCurrentDateRange,
getMonitoringLocationName, getAgencyCode, getCurrentVariable, getQueryInfo, getRequests, getCurrentParmCd,
hasTimeSeries, getTsRequestKey, getTsQueryInfo, getRequestTimeRange, isLoadingTS, getTSRequest,
getTimeSeriesCollectionIds, getIanaTimeZone, getNwisTimeZone } from './time-series-selector';
describe('timeSeriesSelector', () => {
const TEST_VARS = {
......@@ -30,6 +33,54 @@ describe('timeSeriesSelector', () => {
});
});
describe('getSourceInfo', () => {
it('Return an empty object if series is empty', () => {
expect(getSourceInfo({
series: {}
})).toEqual({});
});
it('Return the sourceInfo if in series', () => {
expect(getSourceInfo({
series: {
sourceInfo: {
'0537000': {
siteName: 'Site Name'
}
}
}
})).toEqual({
'0537000': {
siteName: 'Site Name'
}
});
});
});
describe('getSiteCodes', () => {
it('Return an empty object if series is empty', () => {
expect(getSiteCodes({
series: {}
})).toEqual({});
});
it('Return the siteCodes if in series', () => {
expect(getSiteCodes({
series: {
siteCodes: {
'0537000': {
agencyCode: 'USGS'
}
}
}
})).toEqual({
'0537000': {
agencyCode: 'USGS'
}
});
});
});
describe('getQueryInfo', () => {
it('Return empty object if series is empty', () => {
expect(getQueryInfo({
......@@ -90,6 +141,56 @@ describe('timeSeriesSelector', () => {
});
});
describe('getMonitoringLocationName', () => {
const TEST_INFO = {
series: {
sourceInfo: {
'01010101': {
'siteName': 'My Site Name'
}
}
}
};
it('Returns empty string if state has no sourceInfo', () => {
expect(getMonitoringLocationName('12345678')({
series: {}
})).toBe('');
});
it('Returns empty string if siteNo is not in sourceInfo', () => {
expect(getMonitoringLocationName('12345678')(TEST_INFO)).toBe('');
});
it('Returns the monitoring location name for the site', () => {
expect(getMonitoringLocationName('01010101')(TEST_INFO)).toBe('My Site Name');
});
});
describe('getAgencyCode', () => {
const TEST_SITE_CODES = {
series: {
siteCodes: {
'01010101': {
'agencyCode': 'USGS'
}
}
}
};
it('Returns empty string if state has no siteCodes ', () => {
expect(getAgencyCode('12345678')({
series: {}
})).toBe('');
});
it('Returns empty string if siteNo is not in siteCodes', () => {
expect(getAgencyCode('12345678')(TEST_SITE_CODES)).toBe('');
});
it('Returns the agency code for the site', () => {
expect(getAgencyCode('01010101')(TEST_SITE_CODES)).toBe('USGS');
});
});
describe('getCurrentVariableID', () => {
it('Return the current variable ID', () => {
expect(getCurrentVariableID({
......
......@@ -13,7 +13,8 @@ const renderToResponse = function (res, {siteID, parameterCode, compare, period}
compare: compare,
period: period,
cursorOffset: false,
showOnlyGraph : true
showOnlyGraph : true,
showMLName: true
};
renderPNG({
pageURL: 'http://wdfn-graph-server',
......
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