Skip to content

Commit

Permalink
Fixes #340, Draggable GetFeatureInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
offtherailz authored and mircobe87 committed Dec 24, 2015
1 parent f90a4a8 commit 1083173
Show file tree
Hide file tree
Showing 31 changed files with 621 additions and 78 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"proj4": "~2.3.6",
"react": "^0.13.3",
"react-bootstrap": "^0.25.2",
"react-draggable": "^0.8.5",
"react-intl": "^1.2.0",
"react-rangeslider": "^1.0.0",
"react-redux": "^3.0.1",
Expand Down
20 changes: 19 additions & 1 deletion web/client/actions/mapInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const CHANGE_MAPINFO_STATE = 'CHANGE_MAPINFO_STATE';
const NEW_MAPINFO_REQUEST = 'NEW_MAPINFO_REQUEST';
const PURGE_MAPINFO_RESULTS = 'PURGE_MAPINFO_RESULTS';
const CHANGE_MAPINFO_FORMAT = 'CHANGE_MAPINFO_FORMAT';
const SHOW_MAPINFO_MARKER = 'SHOW_MAPINFO_MARKER';
const HIDE_MAPINFO_MARKER = 'HIDE_MAPINFO_MARKER';

/**
* Private
Expand Down Expand Up @@ -133,6 +135,18 @@ function changeMapInfoFormat(mimeType) {
};
}

function showMapinfoMarker() {
return {
type: SHOW_MAPINFO_MARKER
};
}

function hideMapinfoMarker() {
return {
type: HIDE_MAPINFO_MARKER
};
}

module.exports = {
ERROR_FEATURE_INFO,
EXCEPTIONS_FEATURE_INFO,
Expand All @@ -141,9 +155,13 @@ module.exports = {
NEW_MAPINFO_REQUEST,
PURGE_MAPINFO_RESULTS,
CHANGE_MAPINFO_FORMAT,
SHOW_MAPINFO_MARKER,
HIDE_MAPINFO_MARKER,
getFeatureInfo,
changeMapInfoState,
newMapInfoRequest,
purgeMapInfoResults,
changeMapInfoFormat
changeMapInfoFormat,
showMapinfoMarker,
hideMapinfoMarker
};
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ let ResultList = React.createClass({
this.props.afterItemClick();
},
renderResults() {
return this.props.results.map((item)=> {return <NominatimResult item={item} onItemClick={this.onItemClick}/>; });
return this.props.results.map((item)=> {return <NominatimResult key={item.osm_id} item={item} onItemClick={this.onItemClick}/>; });
},
render() {
var notFoundMessage = this.props.notFoundMessage;
Expand Down
145 changes: 145 additions & 0 deletions web/client/components/map/leaflet/Feature.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* 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 L = require('leaflet');
const {isEqual} = require('lodash');

var coordsToLatLngF = function(coords) {
return new L.LatLng(coords[1], coords[0], coords[2]);
};

var coordsToLatLngs = function(coords, levelsDeep, coordsToLatLng) {
var latlngs = [];
var len = coords.length;
for (let i = 0, latlng; i < len; i++) {
latlng = levelsDeep ?
coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) :
(coordsToLatLng || this.coordsToLatLng)(coords[i]);

latlngs.push(latlng);
}

return latlngs;
};
var geometryToLayer = function(geojson, options) {

var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson;
var coords = geometry ? geometry.coordinates : null;
var layers = [];
var pointToLayer = options && options.pointToLayer;
var latlng;
var latlngs;
var i;
var len;
let coordsToLatLng = options && options.coordsToLatLng || coordsToLatLngF;

if (!coords && !geometry) {
return null;
}

switch (geometry.type) {
case 'Point':
latlng = coordsToLatLng(coords);
return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng);

case 'MultiPoint':
for (i = 0, len = coords.length; i < len; i++) {
latlng = coordsToLatLng(coords[i]);
layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng));
}
return new L.FeatureGroup(layers);

case 'LineString':
case 'MultiLineString':
latlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, coordsToLatLng);
return new L.Polyline(latlngs, options);

case 'Polygon':
case 'MultiPolygon':
latlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, coordsToLatLng);
return new L.Polygon(latlngs, options);

case 'GeometryCollection':
for (i = 0, len = geometry.geometries.length; i < len; i++) {
let layer = this.geometryToLayer({
geometry: geometry.geometries[i],
type: 'Feature',
properties: geojson.properties
}, options);

if (layer) {
layers.push(layer);
}
}
return new L.FeatureGroup(layers);

default:
throw new Error('Invalid GeoJSON object.');
}
};

let Feature = React.createClass({
propTypes: {
type: React.PropTypes.string,
styleName: React.PropTypes.string,
properties: React.PropTypes.object,
container: React.PropTypes.object, // TODO it must be a L.GeoJSON
geometry: React.PropTypes.object // TODO check for geojson format for geometry
},
componentDidMount() {
if (this.props.container) {
this._layer = geometryToLayer({
type: this.props.type,
geometry: this.props.geometry,
pointToLayer: this.props.styleName !== "marker" ? function(feature, latlng) {
return L.circleMarker(latlng, {
radius: 5,
color: "red",
weight: 1,
opacity: 1,
fillOpacity: 0
});
} : null}
);
this.props.container.addLayer(this._layer);
}
},
componentWillReceiveProps(newProps) {
if (!isEqual(newProps.properties, this.props.properties) || !isEqual(newProps.geometry, this.props.geometry)) {
this.props.container.removeLayer(this._layer);
this._layer = geometryToLayer({
type: newProps.type,
geometry: newProps.geometry,
pointToLayer: newProps.styleName !== "marker" ? function(feature, latlng) {
return L.circleMarker(latlng, {
radius: 5,
color: "red",
weight: 1,
opacity: 1,
fillOpacity: 0
});
} : null}
);
newProps.container.addLayer(this._layer);
}
},
shouldComponentUpdate(nextProps) {
return !isEqual(nextProps.properties, this.props.properties) || !isEqual(nextProps.geometry, this.props.geometry);
},
componentWillUnmount() {
if (this._layer) {
this.props.container.removeLayer(this._layer);
}
},
render() {
return null;
}
});

module.exports = Feature;
27 changes: 27 additions & 0 deletions web/client/components/map/leaflet/FeatureCollection.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* 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');


let Feature = React.createClass({
propTypes: {
type: React.PropTypes.string,
container: React.PropTypes.object, // TODO it must be a L.GeoJSON
geometry: React.PropTypes.object
},
componentDidMount() {
},
componentWillUnmount() {
},
render() {
return null;
}
});

module.exports = Feature;
18 changes: 17 additions & 1 deletion web/client/components/map/leaflet/Layer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,27 @@ const LeafletLayer = React.createClass({
if (newProps.position !== this.props.position) {
this.updateZIndex(newProps.position);
}
this.updateLayer(newProps, this.props);
},
componentWillUnmount() {
if (this.layer && this.props.map) {
this.props.map.removeLayer(this.layer);
}
},
render() {
return null;
if (this.props.children) {
const layer = this.layer;
const children = layer ? React.Children.map(this.props.children, child => {
return child ? React.cloneElement(child, {container: layer, styleName: this.props.options && this.props.options.styleName}) : null;
}) : null;
return (
<noscript>
{children}
</noscript>
);
}
return Layers.renderLayer(this.props.type, this.props.options, this.props.map, this.props.map.id, this.layer);

},
setLayerVisibility(visibility) {
var oldVisibility = this.props.options && this.props.options.visibility !== false;
Expand Down Expand Up @@ -75,6 +88,9 @@ const LeafletLayer = React.createClass({
}
}
},
updateLayer(newProps, oldProps) {
Layers.updateLayer(newProps.type, this.layer, newProps.options, oldProps.options);
},
addLayer() {
if (this.layer) {
this.props.map.addLayer(this.layer);
Expand Down
14 changes: 10 additions & 4 deletions web/client/components/map/leaflet/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ let LeafletMap = React.createClass({
// this uses the hook defined in ./SingleClick.js for leaflet 0.7.*
this.map.on('singleclick', (event) => {
if (this.props.onClick) {
this.props.onClick(event.containerPoint);
this.props.onClick({
pixel: event.containerPoint,
latlng: event.latlng
});
}
});
this.map.on('dragstart', () => { this.map.off('mousemove', this.mouseMoveEvent); });
Expand All @@ -86,9 +89,12 @@ let LeafletMap = React.createClass({
if (!event.layer.layerName) {
return;
}
this.props.onLayerLoading(event.layer.layerName);
event.layer.on('loading', (loadingEvent) => { this.props.onLayerLoading(loadingEvent.target.layerName); });
event.layer.on('load', (loadEvent) => { this.props.onLayerLoad(loadEvent.target.layerName); });
if (event && event.layer && event.layer.on) {
// TODO check event.layer.on is a function
this.props.onLayerLoading(event.layer.layerName);
event.layer.on('loading', (loadingEvent) => { this.props.onLayerLoading(loadingEvent.target.layerName); });
event.layer.on('load', (loadEvent) => { this.props.onLayerLoad(loadEvent.target.layerName); });
}
});

this.drawControl = null;
Expand Down
4 changes: 2 additions & 2 deletions web/client/components/map/leaflet/__tests__/Map-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ describe('LeafletMap', () => {
setTimeout(() => {
expect(spy.calls.length).toEqual(1);
expect(spy.calls[0].arguments.length).toEqual(1);
expect(spy.calls[0].arguments[0].x).toExist();
expect(spy.calls[0].arguments[0].y).toExist();
expect(spy.calls[0].arguments[0].pixel).toExist();
expect(spy.calls[0].arguments[0].latlng).toExist();
done();
}, 600);

Expand Down
3 changes: 2 additions & 1 deletion web/client/components/map/leaflet/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ module.exports = {
LMap: require('./Map.jsx'),
MeasurementSupport: require('./MeasurementSupport'),
Overview: require('./Overview'),
ScaleBar: require('./ScaleBar')
ScaleBar: require('./ScaleBar'),
Feature: require('./Feature')
};
35 changes: 35 additions & 0 deletions web/client/components/map/leaflet/plugins/VectorLayer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 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 Layers = require('../../../../utils/leaflet/Layers');
var L = require('leaflet');

var defaultStyle = {
radius: 5,
color: "red",
weight: 1,
opacity: 1,
fillOpacity: 0
};

var createVectorLayer = function(options) {
return L.geoJson([]/* options.features */, {
pointToLayer: options.styleName !== "marker" ? function(feature, latlng) {
return L.circleMarker(latlng, defaultStyle);
} : null
});
};

Layers.registerType('vector', {
create: (options) => {
return createVectorLayer(options);
},
render: () => {
return null;
}
});
3 changes: 2 additions & 1 deletion web/client/components/map/leaflet/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ module.exports = {
MapQuest: require('./MapQuest'),
OSMLayer: require('./OSMLayer'),
TileProviderLayer: require('./TileProviderLayer'),
WMSLayer: require('./WMSLayer')
WMSLayer: require('./WMSLayer'),
VectorLayer: require('./VectorLayer')
};
Loading

0 comments on commit 1083173

Please sign in to comment.