Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapstore2 Elevation Slider tool #1697

Merged
merged 19 commits into from
Apr 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a83d168
Issue #1560. Fix Syntax error in themeEntries with node v6.10.0 and n…
mricca Mar 15, 2017
c52f255
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 15, 2017
029faf8
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 16, 2017
3bf499a
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 16, 2017
9014404
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 16, 2017
d9208dc
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 17, 2017
2f7f1ec
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 17, 2017
93cd97b
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 19, 2017
d1a2963
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 20, 2017
1f380ae
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 21, 2017
7710325
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 24, 2017
da1d8ae
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 29, 2017
9bc58a0
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 30, 2017
8f0c362
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 31, 2017
29b1696
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 31, 2017
963c9b5
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Mar 31, 2017
68bd416
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Apr 4, 2017
05e9c04
Merge branch 'master' of https://github.com/geosolutions-it/MapStore2
mricca Apr 6, 2017
ecc1f84
Issue #1693 Elevation Slider tool
mricca Apr 6, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
"react-swipeable-views": "0.11.1",
"react-twitter-widgets": "1.2.0",
"react-widgets": "3.4.6",
"recharts": "0.21.2",
"redux": "3.6.0",
"redux-logger": "2.6.1",
"redux-observable": "0.13.0",
Expand Down
4 changes: 4 additions & 0 deletions web/client/components/TOC/DefaultLayer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ var DefaultLayer = React.createClass({
activateSettingsTool: React.PropTypes.bool,
activateQueryTool: React.PropTypes.bool,
activateZoomTool: React.PropTypes.bool,
chartStyle: React.PropTypes.object,
settingsText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
opacityText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
elevationText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
saveText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
closeText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
confirmDeleteText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
Expand Down Expand Up @@ -118,6 +120,8 @@ var DefaultLayer = React.createClass({
includeDeleteButton={this.props.includeDeleteButtonInSettings}
titleText={this.props.settingsText}
opacityText={this.props.opacityText}
elevationText={this.props.elevationText}
chartStyle={this.props.chartStyle}
saveText={this.props.saveText}
closeText={this.props.closeText}
groups={this.props.groups}/>
Expand Down
20 changes: 19 additions & 1 deletion web/client/components/TOC/fragments/SettingsModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const ConfirmButton = require('../../buttons/ConfirmButton');
const General = require('./settings/General');
const Display = require('./settings/Display');
const WMSStyle = require('./settings/WMSStyle');
const Elevation = require('./settings/Elevation');
const Portal = require('../../misc/Portal');
const assign = require('object-assign');
const Message = require('../../I18N/Message');
Expand All @@ -32,25 +33,29 @@ const SettingsModal = React.createClass({
retrieveLayerData: React.PropTypes.func,
titleText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
opacityText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
elevationText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
saveText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
deleteText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
confirmDeleteText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
closeText: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
options: React.PropTypes.object,
chartStyle: React.PropTypes.object,
buttonSize: React.PropTypes.string,
closeGlyph: React.PropTypes.string,
panelStyle: React.PropTypes.object,
panelClassName: React.PropTypes.string,
includeCloseButton: React.PropTypes.bool,
includeDeleteButton: React.PropTypes.bool,
realtimeUpdate: React.PropTypes.bool,
groups: React.PropTypes.array
groups: React.PropTypes.array,
elevations: React.PropTypes.object
},
getDefaultProps() {
return {
id: "mapstore-layer-settings",
settings: {expanded: false},
options: {},
elevations: {},
updateSettings: () => {},
hideSettings: () => {},
updateNode: () => {},
Expand Down Expand Up @@ -123,14 +128,27 @@ const SettingsModal = React.createClass({
o/>);
}
},
renderElevationTab() {
if (this.props.element.type === "wms" && this.props.element.elevations) {
return (<Elevation
elevationText={this.props.elevationText}
chartStyle={this.props.chartStyle}
element={this.props.element}
elevations={this.props.element.elevations}
appState={this.state || {}}
onChange={(key, value) => this.updateParams({[key]: value}, this.props.realtimeUpdate)} />);
}
},
render() {
const general = this.renderGeneral();
const display = this.renderDisplay();
const style = this.renderStyleTab();
const elevation = this.renderElevationTab();
const tabs = (<Tabs defaultActiveKey={1} id="layerProperties-tabs">
<Tab eventKey={1} title={<Message msgId="layerProperties.general" />}>{general}</Tab>
<Tab eventKey={2} title={<Message msgId="layerProperties.display" />}>{display}</Tab>
<Tab eventKey={3} title={<Message msgId="layerProperties.style" />} disabled={!style} >{style}</Tab>
<Tab eventKey={4} title={<Message msgId="layerProperties.elevation" />} disabled={!elevation} >{elevation}</Tab>
</Tabs>);
const footer = (<span role="footer">
{this.props.includeCloseButton ? <Button bsSize={this.props.buttonSize} onClick={this.onClose}>{this.props.closeText}</Button> : <span/>}
Expand Down
117 changes: 117 additions & 0 deletions web/client/components/TOC/fragments/settings/Elevation.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* Copyright 2016, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const React = require('react');

const Slider = require('react-nouislider');
const ElevationChart = require('./ElevationChart');
require('react-widgets/lib/less/react-widgets.less');
require("./css/elevation.css");

module.exports = React.createClass({
propTypes: {
elevationText: React.PropTypes.node,
element: React.PropTypes.object,
elevations: React.PropTypes.object,
onChange: React.PropTypes.func,
appState: React.PropTypes.object,
chartStyle: React.PropTypes.object
},
getDefaultProps() {
return {
onChange: () => {}
};
},
shouldComponentUpdate(nextProps) {
if (nextProps.appState && nextProps.appState.initialState && nextProps.appState.initialState.params && nextProps.element.params) {
if (nextProps.appState.initialState.params[nextProps.elevations.name] !==
nextProps.element.params[nextProps.elevations.name]) {
return false;
}
return false;
}
return true;
},
renderElevationsChart(elevations) {
if (this.props.elevations.showChart) {
return (
<ElevationChart
onChange={this.props.onChange}
elevations={elevations}
chartStyle={this.props.chartStyle}/>
);
}
},
renderElevationsSlider(elevations) {
const values = elevations.values;
const min = 0;
const max = values.length - 1;
const dif = max - min;
const firstVal = parseFloat(values[0]);
const lastVal = parseFloat(values[values.length - 1]);
const start = this.props.element &&
this.props.element.params &&
this.props.element.params[this.props.elevations.name][0] || values[0];
const elevationName = {};
return (
<div id="mapstore-elevation">
<Slider
snap= {true}
start={[parseFloat((start))] || [0.0]}
range= {this.calculateRange(values, min, max, dif, firstVal, lastVal)}
behaviour= "tap"
pips= {{
mode: 'range',
stepped: true,
density: 10,
format: {
to: function( value ) {
return parseFloat(value).toFixed(1);
}
}
}}
tooltips={!this.props.elevations.showChart}
onChange={(value) => {
elevationName[this.props.elevations.name] = value;
this.props.onChange("params", Object.assign({}, elevationName));
}}/>
</div>
);
},
render() {
const elevations = this.props.elevations;
return (
<div>
<label
id="mapstore-elevation-label"
key="elevation-label"
className="control-label"
style={this.props.elevations.showChart ? {marginBottom: "10px"} : {marginBottom: "90px"}}>
{this.props.elevationText}: ({this.props.elevations.units})
</label>
{this.renderElevationsChart(elevations)}
<div>
<div key="elevation">
{this.renderElevationsSlider(elevations)}
</div>
</div>
</div>
);
},
calculateRange(values, min, max, dif, firstVal, lastVal) {
let arr = [];
let percText = "";
let range = {min: firstVal, max: lastVal};
values.forEach(function(currentValue, i) {
arr[i] = ((i - min) / dif) * 100;
percText = arr[i] + "%";
range[percText] = parseFloat(currentValue);
});
return range;
}
});
74 changes: 74 additions & 0 deletions web/client/components/TOC/fragments/settings/ElevationChart.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Copyright 2016, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const React = require('react');
const {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip} = require('recharts');
const ElevationChartTooltip = require('./ElevationChartTooltip');

module.exports = React.createClass({
propTypes: {
elevations: React.PropTypes.object,
chartStyle: React.PropTypes.object,
onChange: React.PropTypes.func
},
getDefaultProps() {
return {
elevations: {},
onChange: () => {},
chartStyle: {
margin: {
top: 5,
right: 20,
left: 18,
bottom: 45
},
width: 600,
height: 200
}
};
},
renderLineChart() {
return (
<LineChart margin={this.props.chartStyle.margin} width={this.props.chartStyle.width} height={this.props.chartStyle.height} data={this.formatData(this.props.elevations.values)}>
<XAxis
hide={true}
dataKey="name"/>
<YAxis
hide={true}/>
<Tooltip content={<ElevationChartTooltip/>}/>
<CartesianGrid
strokeDasharray="3 3"
horizontal={false}/>
<Line
type="monotone"
dataKey="value"
stroke="#82ca9d"
activeDot={{r: 8}}/>
</LineChart>
);
},
render() {
return (
<div>
{this.renderLineChart()}
</div>
);
},
formatData(values) {
let data = [];
values.map(function(o) {
data.push(
{
"name": this.props.elevations.name,
"value": parseFloat(this.props.elevations.positive ? o : -o)
}
);
}, this);
return data;
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright 2016, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

const React = require('react');

const CustomTooltip = React.createClass({
propTypes: {
type: React.PropTypes.string,
payload: React.PropTypes.array,
label: React.PropTypes.string,
active: React.PropTypes.bool
},
render() {
const {active} = this.props;

if (active) {
const { payload} = this.props;
return (
<div className="custom-tooltip">
<p className="label">{Math.abs(payload[0].value)}</p>
</div>
);
}
return null;
}
});

module.exports = CustomTooltip;
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright 2015, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

var React = require('react');
var ReactDOM = require('react-dom');
var ReactTestUtils = require('react-addons-test-utils');
var Elevation = require('../Elevation');

var expect = require('expect');

describe('test Layer Properties Elevation component', () => {
beforeEach((done) => {
document.body.innerHTML = '<div id="container"></div>';
setTimeout(done);
});

afterEach((done) => {
ReactDOM.unmountComponentAtNode(document.getElementById("container"));
document.body.innerHTML = '';
setTimeout(done);
});

it('tests component rendering', () => {
const l = {
name: 'testworkspace:testlayer',
title: 'Layer',
visibility: true,
storeIndex: 9,
type: 'shapefile',
url: 'base/web/client/test-resources/geoserver/wms',
params: {
"ELEVATION": ["1.5"]
},
elevations: {
name: "ELEVATION",
units: "Meters",
positive: false,
showChart: true,
values: ["1.5", "5.0", "10.0", "15.0", "20.0", "25.0", "30.0"]
}
};
const settings = {
options: {opacity: 1}
};
const comp = ReactDOM.render(
<Elevation
elevationText={"Text"}
element={l}
elevations={l.elevations}
settings={settings} />,
document.getElementById("container")
);

expect(comp).toExist();
const div = ReactTestUtils.scryRenderedDOMComponentsWithTag( comp, "div" );
expect(div).toExist();
});
});
Loading