diff --git a/src/components/DataMap/DataMap.js b/src/components/DataMap/DataMap.js index 6e8b22fd..a493a377 100644 --- a/src/components/DataMap/DataMap.js +++ b/src/components/DataMap/DataMap.js @@ -93,6 +93,9 @@ import StaticControl from '../StaticControl'; import { geoJSONToLeafletLayers } from '../../core/geoJSON-leaflet'; import LayerOpacityControl from '../LayerOpacityControl'; +import { getWatershed } from '../../data-services/ce-backend'; +import { validateWatershedData } from '../../core/util'; + import './DataMap.css'; @@ -107,11 +110,13 @@ class DataMap extends React.Component { inactiveGeometryStyle: PropTypes.object.isRequired, children: PropTypes.node, pointSelect: PropTypes.bool, + watershedEnsemble: PropTypes.string, }; static defaultProps = { activeGeometryStyle: { color: '#3388ff' }, inactiveGeometryStyle: { color: '#777777' }, + watershedGeometryStyle: {color: '#000000' }, pointSelect: false, }; @@ -134,6 +139,8 @@ class DataMap extends React.Component { } } } + + displayWatershedBoundary = () => this.props.pointSelect && this.props.watershedEnsemble; // Handler for base map ref. @@ -217,10 +224,18 @@ class DataMap extends React.Component { this.props.onSetArea(this.layersToArea(this.state.geometryLayers)); }; - layerStyle = (index) => index > 0 ? - this.props.inactiveGeometryStyle : - this.props.activeGeometryStyle; - + layerStyle = (index) => { + if(index === 0) { + return this.props.activeGeometryStyle; + } + else if (this.displayWatershedBoundary()) { + return this.props.watershedGeometryStyle; + } + else { + return this.props.inactiveGeometryStyle; + } + } + addGeometryLayer = layer => { this.setState(prevState => { layer.setStyle(this.layerStyle(prevState.geometryLayers.length)); @@ -264,10 +279,29 @@ class DataMap extends React.Component { return layers; } - handleAreaCreated = e => this.addGeometryLayer(e.layer); + handleAreaCreated = e => { + //add the watershed boundary to the map if relevant + if(this.displayWatershedBoundary()) { + // get the latitude and longitude of the new point from its layer object + // we know the layer is a CircleMarker + // TODO: is there some leaflet built-in function for this, rather than + // an _attribute? + const outletLat = e.layer._latlng.lat; + const outletLon = e.layer._latlng.lng; + getWatershed({ + ensemble_name: this.props.watershedEnsemble, + area: `POINT (${outletLon} ${outletLat})`}) + .then(validateWatershedData) + .then(response => { + this.addGeometryLayers(geoJSONToLeafletLayers(response.data.boundary)); + }) + } + this.addGeometryLayer(e.layer); + }; handleAreaEdited = e => this.editGeometryLayers(this.eventLayers(e)); handleAreaDeleted = e => this.deleteGeometryLayers(this.eventLayers(e)); + handleUploadArea = (geoJSON) => { this.addGeometryLayers(geoJSONToLeafletLayers(geoJSON)); }; @@ -363,6 +397,8 @@ class DataMap extends React.Component { showLength: false, }, }} + //don't allow editing watershed boundary polygon + edit={this.displayWatershedBoundary() ? {edit: false} : {}} onCreated={this.handleAreaCreated} onEdited={this.handleAreaEdited} onDeleted={this.handleAreaDeleted} diff --git a/src/components/DataTool.js b/src/components/DataTool.js index 7c6929f9..1f0aac01 100644 --- a/src/components/DataTool.js +++ b/src/components/DataTool.js @@ -51,8 +51,8 @@ const navSpec = { { label: 'Extreme Streamflow', info: 'View flood frequency data for the Upper Fraser', - subpath: 'flood/:ensemble_name(upper_fraser)', - navSubpath: 'flood/upper_fraser', + subpath: 'flood/:ensemble_name(fraser)', + navSubpath: 'flood/fraser', render: (props) => , }, ], diff --git a/src/components/app-controllers/FloodAppController/FloodAppController.js b/src/components/app-controllers/FloodAppController/FloodAppController.js index 00ad9a45..630857e8 100644 --- a/src/components/app-controllers/FloodAppController/FloodAppController.js +++ b/src/components/app-controllers/FloodAppController/FloodAppController.js @@ -189,6 +189,7 @@ class FloodAppControllerDisplay extends React.Component { area={this.props.area} onSetArea={this.props.onChangeArea} pointSelect={true} + watershedEnsemble={this.props.ensemble_name} /> diff --git a/src/components/map-controllers/SingleMapController/SingleMapController.js b/src/components/map-controllers/SingleMapController/SingleMapController.js index de65daf5..0c68708c 100644 --- a/src/components/map-controllers/SingleMapController/SingleMapController.js +++ b/src/components/map-controllers/SingleMapController/SingleMapController.js @@ -4,6 +4,12 @@ * This controller coordinates a map displaying data extracted from * netCDF files as a colour-coded raster, as well as a menu of * viewing settings for the raster. + * + * It allows the user to select an area of interest by interacting + * with the map. This area can either be a polygon or a point, which is + * controlled by the pointSelect prop. If the selection area is a point, + * the watershed of which that point is the mouth will be displayed on + * the map if the watershedEnsemble prop has a non-null value. * * It is also responsible for passing user-drawn areas up to its * parent. @@ -56,7 +62,8 @@ export default class SingleMapController extends React.Component { meta: PropTypes.array.isRequired, area: PropTypes.object, onSetArea: PropTypes.func.isRequired, - pointSelect: PropTypes.bool.isRequired + pointSelect: PropTypes.bool.isRequired, + watershedEnsemble: PropTypes.string }; constructor(props) { @@ -238,6 +245,7 @@ export default class SingleMapController extends React.Component { onSetArea={this.props.onSetArea} area={this.props.area} pointSelect={this.props.pointSelect} + watershedEnsemble={this.props.watershedEnsemble} > diff --git a/src/data-services/ce-backend.js b/src/data-services/ce-backend.js index 7a20e1fb..88e71fb4 100644 --- a/src/data-services/ce-backend.js +++ b/src/data-services/ce-backend.js @@ -205,7 +205,8 @@ function guessExperimentFormatFromVariable(variable, experiment) { function getWatershedGeographyName(ensemble){ return { "bc_moti": "peace_watershed", - "upper_fraser": "upper_fraser_watershed" + "upper_fraser": "upper_fraser_watershed", + "fraser": "fraser_watershed", }[ensemble]; }