diff --git a/package.json b/package.json
index 8bcfd71a0f..62106945dd 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,7 @@
"openlayers": "^3.8.2",
"proj4": "~2.3.6",
"react": "^0.13.3",
- "react-bootstrap": "^0.24.3",
+ "react-bootstrap": "^0.25.2",
"react-intl": "^1.2.0",
"react-redux": "^2.0.0",
"redux": "^2.0.0",
diff --git a/web/client/actions/__tests__/map-test.js b/web/client/actions/__tests__/map-test.js
index 655c6e8019..ab7354a744 100644
--- a/web/client/actions/__tests__/map-test.js
+++ b/web/client/actions/__tests__/map-test.js
@@ -9,17 +9,11 @@
var expect = require('expect');
var {
CHANGE_MAP_VIEW,
- ERROR_FEATURE_INFO,
- EXCEPTIONS_FEATURE_INFO,
- LOAD_FEATURE_INFO,
- CHANGE_MAPINFO_STATE,
- NEW_MAPINFO_REQUEST,
- PURGE_MAPINFO_RESULTS,
- getFeatureInfo,
+ CLICK_ON_MAP,
+ CHANGE_MOUSE_POINTER,
changeMapView,
- changeMapInfoState,
- newMapInfoRequest,
- purgeMapInfoResults
+ clickOnMap,
+ changeMousePointer
} = require('../map');
describe('Test correctness of the map actions', () => {
@@ -39,63 +33,21 @@ describe('Test correctness of the map actions', () => {
expect(retval.size).toBe(testSize);
});
- it('get feature info data', (done) => {
- getFeatureInfo('base/web/client/test-resources/featureInfo-response.json', {})((e) => {
- try {
- expect(e).toExist();
- expect(e.type).toBe(LOAD_FEATURE_INFO);
- done();
- } catch(ex) {
- done(ex);
- }
- });
- });
-
- it('get feature info exception', (done) => {
- getFeatureInfo('base/web/client/test-resources/featureInfo-exception.json', {})((e) => {
- try {
- expect(e).toExist();
- expect(e.type).toBe(EXCEPTIONS_FEATURE_INFO);
- done();
- } catch(ex) {
- done(ex);
- }
- });
- });
-
- it('get feature info error', (done) => {
- getFeatureInfo('requestError.json', {})((e) => {
- try {
- expect(e).toExist();
- expect(e.type).toBe(ERROR_FEATURE_INFO);
- done();
- } catch(ex) {
- done(ex);
- }
- });
- });
-
- it('change map info state', () => {
+ it('set a new clicked point', () => {
const testVal = "val";
- const retval = changeMapInfoState(testVal);
+ const retval = clickOnMap(testVal);
- expect(retval.type).toBe(CHANGE_MAPINFO_STATE);
- expect(retval.enabled).toExist();
- expect(retval.enabled).toBe(testVal);
+ expect(retval.type).toBe(CLICK_ON_MAP);
+ expect(retval.point).toExist();
+ expect(retval.point).toBe(testVal);
});
- it('add new info request', () => {
- const testVal = "val";
- const retval = newMapInfoRequest(testVal);
-
- expect(retval.type).toBe(NEW_MAPINFO_REQUEST);
- expect(retval.request).toExist();
- expect(retval.request).toBe(testVal);
- });
+ it('set a new mouse pointer', () => {
+ const testVal = 'pointer';
+ const retval = changeMousePointer(testVal);
- it('delete all results', () => {
- const retval = purgeMapInfoResults();
-
- expect(retval.type).toBe(PURGE_MAPINFO_RESULTS);
+ expect(retval).toExist();
+ expect(retval.type).toBe(CHANGE_MOUSE_POINTER);
+ expect(retval.pointer).toBe(testVal);
});
});
diff --git a/web/client/actions/__tests__/mapInfo-test.js b/web/client/actions/__tests__/mapInfo-test.js
new file mode 100644
index 0000000000..7f7b46e769
--- /dev/null
+++ b/web/client/actions/__tests__/mapInfo-test.js
@@ -0,0 +1,96 @@
+/**
+ * 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 expect = require('expect');
+var {
+ ERROR_FEATURE_INFO,
+ EXCEPTIONS_FEATURE_INFO,
+ LOAD_FEATURE_INFO,
+ CHANGE_MAPINFO_STATE,
+ NEW_MAPINFO_REQUEST,
+ PURGE_MAPINFO_RESULTS,
+ getFeatureInfo,
+ changeMapInfoState,
+ newMapInfoRequest,
+ purgeMapInfoResults
+} = require('../mapInfo');
+
+describe('Test correctness of the map actions', () => {
+
+ it('get feature info data', (done) => {
+ getFeatureInfo('base/web/client/test-resources/featureInfo-response.json', {p: "p"}, "meta")((e) => {
+ try {
+ expect(e).toExist();
+ expect(e.type).toBe(LOAD_FEATURE_INFO);
+ expect(e.data).toExist();
+ expect(e.requestParams).toExist();
+ expect(e.requestParams.p).toBe("p");
+ expect(e.layerMetadata).toBe("meta");
+ done();
+ } catch(ex) {
+ done(ex);
+ }
+ });
+ });
+
+ it('get feature info exception', (done) => {
+ getFeatureInfo('base/web/client/test-resources/featureInfo-exception.json', {p: "p"}, "meta")((e) => {
+ try {
+ expect(e).toExist();
+ expect(e.type).toBe(EXCEPTIONS_FEATURE_INFO);
+ expect(e.exceptions).toExist();
+ expect(e.requestParams).toExist();
+ expect(e.requestParams.p).toBe("p");
+ expect(e.layerMetadata).toBe("meta");
+ done();
+ } catch(ex) {
+ done(ex);
+ }
+ });
+ });
+
+ it('get feature info error', (done) => {
+ getFeatureInfo('requestError.json', {p: "p"}, "meta")((e) => {
+ try {
+ expect(e).toExist();
+ expect(e.type).toBe(ERROR_FEATURE_INFO);
+ expect(e.error).toExist();
+ expect(e.requestParams).toExist();
+ expect(e.requestParams.p).toBe("p");
+ expect(e.layerMetadata).toBe("meta");
+ done();
+ } catch(ex) {
+ done(ex);
+ }
+ });
+ });
+
+ it('change map info state', () => {
+ const testVal = "val";
+ const retval = changeMapInfoState(testVal);
+
+ expect(retval.type).toBe(CHANGE_MAPINFO_STATE);
+ expect(retval.enabled).toExist();
+ expect(retval.enabled).toBe(testVal);
+ });
+
+ it('add new info request', () => {
+ const testVal = "val";
+ const retval = newMapInfoRequest(testVal);
+
+ expect(retval.type).toBe(NEW_MAPINFO_REQUEST);
+ expect(retval.request).toExist();
+ expect(retval.request).toBe(testVal);
+ });
+
+ it('delete all results', () => {
+ const retval = purgeMapInfoResults();
+
+ expect(retval.type).toBe(PURGE_MAPINFO_RESULTS);
+ });
+});
diff --git a/web/client/actions/map.js b/web/client/actions/map.js
index c3f462ff65..b84d27cfb1 100644
--- a/web/client/actions/map.js
+++ b/web/client/actions/map.js
@@ -5,16 +5,10 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
-const assign = require('object-assign');
-const axios = require('axios');
const CHANGE_MAP_VIEW = 'CHANGE_MAP_VIEW';
-const LOAD_FEATURE_INFO = 'LOAD_FEATURE_INFO';
-const ERROR_FEATURE_INFO = 'ERROR_FEATURE_INFO';
-const EXCEPTIONS_FEATURE_INFO = 'EXCEPTIONS_FEATURE_INFO';
-const CHANGE_MAPINFO_STATE = 'CHANGE_MAPINFO_STATE';
-const NEW_MAPINFO_REQUEST = 'NEW_MAPINFO_REQUEST';
-const PURGE_MAPINFO_RESULTS = 'PURGE_MAPINFO_RESULTS';
+const CLICK_ON_MAP = 'CLICK_ON_MAP';
+const CHANGE_MOUSE_POINTER = 'CHANGE_MOUSE_POINTER';
function changeMapView(center, zoom, bbox, size) {
return {
@@ -26,104 +20,25 @@ function changeMapView(center, zoom, bbox, size) {
};
}
-/**
- * Private
- * @return a LOAD_FEATURE_INFO action with the response data to a wms GetFeatureInfo
- */
-function loadFeatureInfo(data) {
- return {
- type: LOAD_FEATURE_INFO,
- data: data
- };
-}
-
-/**
- * Private
- * @return a ERROR_FEATURE_INFO action with the error occured
- */
-function errorFeatureInfo(e) {
- return {
- type: ERROR_FEATURE_INFO,
- error: e
- };
-}
-
-/**
- * Private
- * @return a EXCEPTIONS_FEATURE_INFO action with the wms exception occured
- * during a GetFeatureInfo request.
- */
-function exceptionsFeatureInfo(exceptions) {
- return {
- type: EXCEPTIONS_FEATURE_INFO,
- exceptions: exceptions
- };
-}
-
-/**
- * Sends a wms GetFeatureInfo request and dispatches the right action
- * in case of success, error or exceptions.
- *
- * @param wmsBasePath {string} base path to the wms service
- * @param requestParams {object} map of params for a getfeatureinfo request.
- */
-function getFeatureInfo(wmsBasePath, requestParams) {
- const defaultParams = {
- service: 'WMS',
- version: '1.0.0',
- request: 'GetFeatureInfo',
- crs: 'EPSG:4326',
- info_format: 'application/json',
- feature_count: 50,
- x: 0,
- y: 0,
- exceptions: 'application/json'
- };
- const param = assign({}, defaultParams, requestParams);
- return (dispatch) => {
- return axios.get(wmsBasePath, {params: param}).then((response) => {
- if (response.data.exceptions) {
- dispatch(exceptionsFeatureInfo(response.data.exceptions));
- } else {
- dispatch(loadFeatureInfo(response.data));
- }
- }).catch((e) => {
- dispatch(errorFeatureInfo(e));
- });
- };
-}
-
-function changeMapInfoState(enabled) {
- return {
- type: CHANGE_MAPINFO_STATE,
- enabled: enabled
- };
-}
-
-function newMapInfoRequest(reqConfig) {
+function clickOnMap(point) {
return {
- type: NEW_MAPINFO_REQUEST,
- request: reqConfig
+ type: CLICK_ON_MAP,
+ point: point
};
}
-function purgeMapInfoResults() {
+function changeMousePointer(pointerType) {
return {
- type: PURGE_MAPINFO_RESULTS
+ type: CHANGE_MOUSE_POINTER,
+ pointer: pointerType
};
}
module.exports = {
CHANGE_MAP_VIEW,
- ERROR_FEATURE_INFO,
- EXCEPTIONS_FEATURE_INFO,
- LOAD_FEATURE_INFO,
- CHANGE_MAPINFO_STATE,
- NEW_MAPINFO_REQUEST,
- PURGE_MAPINFO_RESULTS,
- getFeatureInfo,
+ CLICK_ON_MAP,
+ CHANGE_MOUSE_POINTER,
changeMapView,
- changeMapInfoState,
- newMapInfoRequest,
- purgeMapInfoResults
+ clickOnMap,
+ changeMousePointer
};
diff --git a/web/client/actions/mapInfo.js b/web/client/actions/mapInfo.js
new file mode 100644
index 0000000000..286f0c6767
--- /dev/null
+++ b/web/client/actions/mapInfo.js
@@ -0,0 +1,122 @@
+/**
+ * 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.
+ */
+
+const assign = require('object-assign');
+const axios = require('axios');
+
+const LOAD_FEATURE_INFO = 'LOAD_FEATURE_INFO';
+const ERROR_FEATURE_INFO = 'ERROR_FEATURE_INFO';
+const EXCEPTIONS_FEATURE_INFO = 'EXCEPTIONS_FEATURE_INFO';
+const CHANGE_MAPINFO_STATE = 'CHANGE_MAPINFO_STATE';
+const NEW_MAPINFO_REQUEST = 'NEW_MAPINFO_REQUEST';
+const PURGE_MAPINFO_RESULTS = 'PURGE_MAPINFO_RESULTS';
+
+/**
+ * Private
+ * @return a LOAD_FEATURE_INFO action with the response data to a wms GetFeatureInfo
+ */
+function loadFeatureInfo(data, rParams, lMetaData) {
+ return {
+ type: LOAD_FEATURE_INFO,
+ data: data,
+ requestParams: rParams,
+ layerMetadata: lMetaData
+ };
+}
+
+/**
+ * Private
+ * @return a ERROR_FEATURE_INFO action with the error occured
+ */
+function errorFeatureInfo(e, rParams, lMetaData) {
+ return {
+ type: ERROR_FEATURE_INFO,
+ error: e,
+ requestParams: rParams,
+ layerMetadata: lMetaData
+ };
+}
+
+/**
+ * Private
+ * @return a EXCEPTIONS_FEATURE_INFO action with the wms exception occured
+ * during a GetFeatureInfo request.
+ */
+function exceptionsFeatureInfo(exceptions, rParams, lMetaData) {
+ return {
+ type: EXCEPTIONS_FEATURE_INFO,
+ exceptions: exceptions,
+ requestParams: rParams,
+ layerMetadata: lMetaData
+ };
+}
+
+/**
+ * Sends a wms GetFeatureInfo request and dispatches the right action
+ * in case of success, error or exceptions.
+ *
+ * @param wmsBasePath {string} base path to the wms service
+ * @param requestParams {object} map of params for a getfeatureinfo request.
+ */
+function getFeatureInfo(wmsBasePath, requestParams, lMetaData) {
+ const defaultParams = {
+ service: 'WMS',
+ version: '1.1.1',
+ request: 'GetFeatureInfo',
+ srs: 'EPSG:4326',
+ info_format: 'application/json',
+ x: 0,
+ y: 0,
+ exceptions: 'application/json'
+ };
+ const param = assign({}, defaultParams, requestParams);
+ return (dispatch) => {
+ return axios.get(wmsBasePath, {params: param}).then((response) => {
+ if (response.data.exceptions) {
+ dispatch(exceptionsFeatureInfo(response.data.exceptions, requestParams, lMetaData));
+ } else {
+ dispatch(loadFeatureInfo(response.data, requestParams, lMetaData));
+ }
+ }).catch((e) => {
+ dispatch(errorFeatureInfo(e, requestParams, lMetaData));
+ });
+ };
+}
+
+function changeMapInfoState(enabled) {
+ return {
+ type: CHANGE_MAPINFO_STATE,
+ enabled: enabled
+ };
+}
+
+function newMapInfoRequest(reqConfig) {
+ return {
+ type: NEW_MAPINFO_REQUEST,
+ request: reqConfig
+ };
+}
+
+function purgeMapInfoResults() {
+ return {
+ type: PURGE_MAPINFO_RESULTS
+ };
+}
+
+module.exports = {
+ ERROR_FEATURE_INFO,
+ EXCEPTIONS_FEATURE_INFO,
+ LOAD_FEATURE_INFO,
+ CHANGE_MAPINFO_STATE,
+ NEW_MAPINFO_REQUEST,
+ PURGE_MAPINFO_RESULTS,
+ getFeatureInfo,
+ changeMapInfoState,
+ newMapInfoRequest,
+ purgeMapInfoResults
+};
diff --git a/web/client/components/map/leaflet/Map.jsx b/web/client/components/map/leaflet/Map.jsx
index b1e1788ce1..1be5ebee8b 100644
--- a/web/client/components/map/leaflet/Map.jsx
+++ b/web/client/components/map/leaflet/Map.jsx
@@ -17,7 +17,8 @@ var LeafletMap = React.createClass({
projection: React.PropTypes.string,
onMapViewChanges: React.PropTypes.func,
onClick: React.PropTypes.func,
- mapOptions: React.PropTypes.object
+ mapOptions: React.PropTypes.object,
+ mousePointer: React.PropTypes.string
},
getDefaultProps() {
return {
@@ -43,10 +44,12 @@ var LeafletMap = React.createClass({
this.map.on('click', (event) => { this.props.onClick(event.containerPoint); });
this.updateMapInfoState();
+ this.setMousePointer(this.props.mousePointer);
// NOTE: this re-call render function after div creation to have the map initialized.
this.forceUpdate();
},
componentWillReceiveProps(newProps) {
+ this.setMousePointer(newProps.mousePointer);
const currentCenter = this.map.getCenter();
const centerIsUpdate = newProps.center.y === currentCenter.lat &&
newProps.center.x === currentCenter.lng;
@@ -89,6 +92,12 @@ var LeafletMap = React.createClass({
crs: 'EPSG:4326',
rotation: 0
}, size);
+ },
+ setMousePointer(pointer) {
+ if (this.map) {
+ const mapDiv = this.map.getContainer();
+ mapDiv.style.cursor = pointer || 'auto';
+ }
}
});
diff --git a/web/client/components/map/leaflet/__tests__/Map-test.jsx b/web/client/components/map/leaflet/__tests__/Map-test.jsx
index 063badd77a..b242ffe832 100644
--- a/web/client/components/map/leaflet/__tests__/Map-test.jsx
+++ b/web/client/components/map/leaflet/__tests__/Map-test.jsx
@@ -163,4 +163,31 @@ describe('LeafletMap', () => {
expect(leafletMap.getCenter().lat).toBe(44);
expect(leafletMap.getCenter().lng).toBe(10);
});
+
+ it('check if the map has "auto" cursor as default', () => {
+ const map = React.render(
+
+ , document.body);
+
+ const leafletMap = map.map;
+ const mapDiv = leafletMap.getContainer();
+ expect(mapDiv.style.cursor).toBe("auto");
+ });
+
+ it('check if the map can be created with a custom cursor', () => {
+ const map = React.render(
+
+ , document.body);
+
+ const leafletMap = map.map;
+ const mapDiv = leafletMap.getContainer();
+ expect(mapDiv.style.cursor).toBe("pointer");
+ });
});
diff --git a/web/client/components/map/openlayers/Map.jsx b/web/client/components/map/openlayers/Map.jsx
index e781f263ea..dfbff48b60 100644
--- a/web/client/components/map/openlayers/Map.jsx
+++ b/web/client/components/map/openlayers/Map.jsx
@@ -18,7 +18,8 @@ var OpenlayersMap = React.createClass({
projection: React.PropTypes.string,
onMapViewChanges: React.PropTypes.func,
onClick: React.PropTypes.func,
- mapOptions: React.PropTypes.object
+ mapOptions: React.PropTypes.object,
+ mousePointer: React.PropTypes.string
},
getDefaultProps() {
return {
@@ -84,11 +85,13 @@ var OpenlayersMap = React.createClass({
});
this.map = map;
+ this.setMousePointer(this.props.mousePointer);
// NOTE: this re-call render function after div creation to have the map initialized.
this.forceUpdate();
},
componentWillReceiveProps(newProps) {
var view = this.map.getView();
+ this.setMousePointer(newProps.mousePointer);
const currentCenter = this.normalizeCenter(view.getCenter());
const centerIsUpdated = newProps.center.y === currentCenter[1] &&
newProps.center.x === currentCenter[0];
@@ -117,6 +120,12 @@ var OpenlayersMap = React.createClass({
},
normalizeCenter: function(center) {
return ol.proj.transform(center, this.props.projection, 'EPSG:4326');
+ },
+ setMousePointer(pointer) {
+ if (this.map) {
+ const mapDiv = this.map.getViewport();
+ mapDiv.style.cursor = pointer || 'auto';
+ }
}
});
diff --git a/web/client/components/map/openlayers/__tests__/Map-test.jsx b/web/client/components/map/openlayers/__tests__/Map-test.jsx
index 086fec4588..abe6a32229 100644
--- a/web/client/components/map/openlayers/__tests__/Map-test.jsx
+++ b/web/client/components/map/openlayers/__tests__/Map-test.jsx
@@ -165,4 +165,31 @@ describe('OpenlayersMap', () => {
expect(olMap.getView().getCenter()[1]).toBe(44);
expect(olMap.getView().getCenter()[0]).toBe(10);
});
+
+ it('check if the map has "auto" cursor as default', () => {
+ const map = React.render(
+
+ , document.body);
+
+ const olMap = map.map;
+ const mapDiv = olMap.getViewport();
+ expect(mapDiv.style.cursor).toBe("auto");
+ });
+
+ it('check if the map can be created with a custom cursor', () => {
+ const map = React.render(
+
+ , document.body);
+
+ const olMap = map.map;
+ const mapDiv = olMap.getViewport();
+ expect(mapDiv.style.cursor).toBe("pointer");
+ });
});
diff --git a/web/client/components/misc/HtmlRenderer.jsx b/web/client/components/misc/HtmlRenderer.jsx
index c2295586d4..cfd8061dae 100644
--- a/web/client/components/misc/HtmlRenderer.jsx
+++ b/web/client/components/misc/HtmlRenderer.jsx
@@ -25,7 +25,7 @@ var HtmlRenderer = React.createClass({
};
},
render() {
- return
;
+ return ;
}
});
diff --git a/web/client/examples/viewer/components/GetFeatureInfo.jsx b/web/client/examples/viewer/components/GetFeatureInfo.jsx
index f0861b3eb5..409e3a4672 100644
--- a/web/client/examples/viewer/components/GetFeatureInfo.jsx
+++ b/web/client/examples/viewer/components/GetFeatureInfo.jsx
@@ -9,11 +9,16 @@
var React = require('react');
var BootstrapReact = require('react-bootstrap');
var Modal = BootstrapReact.Modal;
+var Tabs = BootstrapReact.Tabs;
+var Tab = BootstrapReact.Tab;
var I18N = require('../../../components/I18N/I18N');
var ToggleButton = require('../../../components/buttons/ToggleButton');
var HtmlRenderer = require('../../../components/misc/HtmlRenderer');
+var CoordinatesUtils = require('../../../utils/CoordinatesUtils');
+var assign = require('object-assign');
+
var GetFeatureInfo = React.createClass({
propTypes: {
htmlResponses: React.PropTypes.array,
@@ -21,37 +26,170 @@ var GetFeatureInfo = React.createClass({
btnText: React.PropTypes.string,
btnIcon: React.PropTypes.string,
enabled: React.PropTypes.bool,
- btnClick: React.PropTypes.func,
- onCloseResult: React.PropTypes.func
+ mapConfig: React.PropTypes.object,
+ layerFilter: React.PropTypes.func,
+ actions: React.PropTypes.shape({
+ getFeatureInfo: React.PropTypes.func,
+ changeMapInfoState: React.PropTypes.func,
+ purgeMapInfoResults: React.PropTypes.func,
+ changeMousePointer: React.PropTypes.func
+ }),
+ clickedMapPoint: React.PropTypes.shape({
+ x: React.PropTypes.number,
+ y: React.PropTypes.number
+ })
},
getDefaultProps() {
return {
enabled: false,
htmlResponses: [],
- btnClick() {}
+ mapConfig: {layers: []},
+ layerFilter(l) {
+ return l.visibility &&
+ l.type === 'wms' &&
+ (l.queryable === undefined || l.queryable) &&
+ l.group !== "background"
+ ;
+ },
+ actions: {
+ getFeatureInfo() {},
+ changeMapInfoState() {},
+ purgeMapInfoResults() {},
+ changeMousePointer() {}
+ }
};
},
getInitialState() {
return { showModal: true };
},
+ componentWillReceiveProps(newProps) {
+ // if there's a new clicked point on map and GetFeatureInfo is active
+ // it composes and sends a getFeatureInfo action.
+ if (
+ this.props.clickedMapPoint === undefined && newProps.clickedMapPoint !== undefined ||
+ this.props.clickedMapPoint !== undefined && newProps.clickedMapPoint !== undefined && (
+ this.props.clickedMapPoint.x !== newProps.clickedMapPoint.x ||
+ this.props.clickedMapPoint.y !== newProps.clickedMapPoint.y
+ )
+ ) {
+ if (newProps.enabled) {
+ const wmsVisibleLayers = newProps.mapConfig.layers.filter(newProps.layerFilter);
+ const {bounds, crs} = this.reprojectBbox(newProps.mapConfig.bbox, newProps.mapConfig.projection);
+ for (let l = 0; l < wmsVisibleLayers.length; l++) {
+ const layer = wmsVisibleLayers[l];
+ const requestConf = {
+ layers: layer.name,
+ query_layers: layer.name,
+ x: newProps.clickedMapPoint.x,
+ y: newProps.clickedMapPoint.y,
+ height: newProps.mapConfig.size.height,
+ width: newProps.mapConfig.size.width,
+ srs: crs,
+ bbox: bounds.minx + "," +
+ bounds.miny + "," +
+ bounds.maxx + "," +
+ bounds.maxy,
+ info_format: "text/html"
+ };
+ const layerMetadata = {
+ title: layer.title
+ };
+ const url = layer.url.replace(/[?].*$/g, '');
+ newProps.actions.getFeatureInfo(url, requestConf, layerMetadata);
+ }
+ }
+ }
+
+ if (newProps.enabled && !this.props.enabled) {
+ this.props.actions.changeMousePointer('pointer');
+ } else if (!newProps.enabled && this.props.enabled) {
+ this.props.actions.changeMousePointer('auto');
+ }
+ },
+ onToggleButtonClick(btnEnabled) {
+ this.props.actions.changeMapInfoState(!btnEnabled);
+ },
+ onModalHiding() {
+ this.props.actions.purgeMapInfoResults();
+ },
+ // returns a array of tabs where each one contains feature info for
+ // a specific layer.
getModalContent(responses) {
var output = [];
var content = "";
- const regexp = /^.*(.*)<\/body>.*$/g;
+ var title = "";
+ var style = "";
+ const regexpBody = /^[\s\S]*([\s\S]*)<\/body>[\s\S]*$/i;
+ const regexpStyle = /(
diff --git a/web/client/reducers/__tests__/config-test.js b/web/client/reducers/__tests__/config-test.js
index 3811555dfb..804cc1f87e 100644
--- a/web/client/reducers/__tests__/config-test.js
+++ b/web/client/reducers/__tests__/config-test.js
@@ -54,4 +54,18 @@ describe('Test the mapConfig reducer', () => {
expect(state.bbox).toBe(0);
expect(state.size).toBe(0);
});
+
+ it('sets a new mouse pointer used over the map', () => {
+ const action = {
+ type: 'CHANGE_MOUSE_POINTER',
+ pointer: "testPointer"
+ };
+
+ var state = mapConfig({}, action);
+ expect(state.mousePointer).toBe(action.pointer);
+
+ state = mapConfig({prop: 'prop'}, action);
+ expect(state.prop).toBe('prop');
+ expect(state.mousePointer).toBe(action.pointer);
+ });
});
diff --git a/web/client/reducers/__tests__/mapInfo-test.js b/web/client/reducers/__tests__/mapInfo-test.js
index a04eafbf0e..3e460428a7 100644
--- a/web/client/reducers/__tests__/mapInfo-test.js
+++ b/web/client/reducers/__tests__/mapInfo-test.js
@@ -15,57 +15,98 @@ describe('Test the mapInfo reducer', () => {
});
it('creates a general error ', () => {
- let state = mapInfo({}, {type: 'ERROR_FEATURE_INFO', error: "error"});
+ let testAction = {
+ type: 'ERROR_FEATURE_INFO',
+ error: "error",
+ requestParams: "params",
+ layerMetadata: "meta"
+ };
+
+ let state = mapInfo({}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(1);
- expect(state.responses[0]).toBe("error");
+ expect(state.responses[0].response).toBe("error");
+ expect(state.responses[0].queryParams).toBe("params");
+ expect(state.responses[0].layerMetadata).toBe("meta");
- state = mapInfo({responses: []}, {type: 'ERROR_FEATURE_INFO', error: "error"});
+ state = mapInfo({responses: []}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(1);
- expect(state.responses[0]).toBe("error");
+ expect(state.responses[0].response).toBe("error");
+ expect(state.responses[0].queryParams).toBe("params");
+ expect(state.responses[0].layerMetadata).toBe("meta");
- state = mapInfo({responses: ["test"]}, {type: 'ERROR_FEATURE_INFO', error: "error"});
+ state = mapInfo({responses: ["test"]}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(2);
expect(state.responses[0]).toBe("test");
- expect(state.responses[1]).toBe("error");
+ expect(state.responses[1].response).toBe("error");
+ expect(state.responses[1].queryParams).toBe("params");
+ expect(state.responses[1].layerMetadata).toBe("meta");
});
it('creates an wms feature info exception', () => {
- let state = mapInfo({}, {type: 'EXCEPTIONS_FEATURE_INFO', exceptions: "exception"});
+ let testAction = {
+ type: 'EXCEPTIONS_FEATURE_INFO',
+ exceptions: "exception",
+ requestParams: "params",
+ layerMetadata: "meta"
+ };
+
+ let state = mapInfo({}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(1);
- expect(state.responses[0]).toBe("exception");
+ expect(state.responses[0].response).toBe("exception");
+ expect(state.responses[0].queryParams).toBe("params");
+ expect(state.responses[0].layerMetadata).toBe("meta");
- state = mapInfo({responses: []}, {type: 'EXCEPTIONS_FEATURE_INFO', exceptions: "exception"});
+ state = mapInfo({responses: []}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(1);
- expect(state.responses[0]).toBe("exception");
+ expect(state.responses[0].response).toBe("exception");
+ expect(state.responses[0].queryParams).toBe("params");
+ expect(state.responses[0].layerMetadata).toBe("meta");
- state = mapInfo({responses: ["test"]}, {type: 'EXCEPTIONS_FEATURE_INFO', exceptions: "exception"});
+
+ state = mapInfo({responses: ["test"]}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(2);
expect(state.responses[0]).toBe("test");
- expect(state.responses[1]).toBe("exception");
+ expect(state.responses[1].response).toBe("exception");
+ expect(state.responses[1].queryParams).toBe("params");
+ expect(state.responses[1].layerMetadata).toBe("meta");
+
});
it('creates a feature info data from succesfull request', () => {
- let state = mapInfo({}, {type: 'LOAD_FEATURE_INFO', data: "data"});
+ let testAction = {
+ type: 'LOAD_FEATURE_INFO',
+ data: "data",
+ requestParams: "params",
+ layerMetadata: "meta"
+ };
+
+ let state = mapInfo({}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(1);
- expect(state.responses[0]).toBe("data");
+ expect(state.responses[0].response).toBe("data");
+ expect(state.responses[0].queryParams).toBe("params");
+ expect(state.responses[0].layerMetadata).toBe("meta");
- state = mapInfo({responses: []}, {type: 'LOAD_FEATURE_INFO', data: "data"});
+ state = mapInfo({responses: []}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(1);
- expect(state.responses[0]).toBe("data");
+ expect(state.responses[0].response).toBe("data");
+ expect(state.responses[0].queryParams).toBe("params");
+ expect(state.responses[0].layerMetadata).toBe("meta");
- state = mapInfo({responses: ["test"]}, {type: 'LOAD_FEATURE_INFO', data: "data"});
+ state = mapInfo({responses: ["test"]}, testAction);
expect(state.responses).toExist();
expect(state.responses.length).toBe(2);
expect(state.responses[0]).toBe("test");
- expect(state.responses[1]).toBe("data");
+ expect(state.responses[1].response).toBe("data");
+ expect(state.responses[1].queryParams).toBe("params");
+ expect(state.responses[1].layerMetadata).toBe("meta");
});
it('creates a new mapinfo request', () => {
@@ -100,6 +141,16 @@ describe('Test the mapInfo reducer', () => {
expect(state.responses.length).toBe(0);
});
+ it('set a new point on map which has been clicked', () => {
+ let state = mapInfo({}, {type: 'CLICK_ON_MAP', point: "p"});
+ expect(state.clickPoint).toExist();
+ expect(state.clickPoint).toBe('p');
+
+ state = mapInfo({clickPoint: 'oldP'}, {type: 'CLICK_ON_MAP', point: "p"});
+ expect(state.clickPoint).toExist();
+ expect(state.clickPoint).toBe('p');
+ });
+
it('enables map info', () => {
let state = mapInfo({}, {type: 'CHANGE_MAPINFO_STATE', enabled: true});
expect(state).toExist();
diff --git a/web/client/reducers/config.js b/web/client/reducers/config.js
index 6ddf46c190..ad646101c8 100644
--- a/web/client/reducers/config.js
+++ b/web/client/reducers/config.js
@@ -7,7 +7,7 @@
*/
var {MAP_CONFIG_LOADED, MAP_CONFIG_LOAD_ERROR} = require('../actions/config');
-var {CHANGE_MAP_VIEW} = require('../actions/map');
+var {CHANGE_MAP_VIEW, CHANGE_MOUSE_POINTER} = require('../actions/map');
var ConfigUtils = require('../utils/ConfigUtils');
var assign = require('object-assign');
@@ -27,6 +27,10 @@ function mapConfig(state = null, action) {
bbox: action.bbox,
size: action.size
});
+ case CHANGE_MOUSE_POINTER:
+ return assign({}, state, {
+ mousePointer: action.pointer
+ });
default:
return state;
}
diff --git a/web/client/reducers/mapInfo.js b/web/client/reducers/mapInfo.js
index 2118db2d15..49ffda815b 100644
--- a/web/client/reducers/mapInfo.js
+++ b/web/client/reducers/mapInfo.js
@@ -6,14 +6,16 @@
* LICENSE file in the root directory of this source tree.
*/
+var {CLICK_ON_MAP} = require('../actions/map');
+
var {
+ ERROR_FEATURE_INFO,
+ EXCEPTIONS_FEATURE_INFO,
+ LOAD_FEATURE_INFO,
CHANGE_MAPINFO_STATE,
NEW_MAPINFO_REQUEST,
- LOAD_FEATURE_INFO,
- EXCEPTIONS_FEATURE_INFO,
- ERROR_FEATURE_INFO,
PURGE_MAPINFO_RESULTS
-} = require('../actions/map');
+} = require('../actions/mapInfo');
const assign = require('object-assign');
@@ -49,11 +51,16 @@ function mapInfo(state = null, action) {
* else is a [string] (for eg. if HTML data has been requested)
*/
let newResponses;
+ let obj = {
+ response: action.data,
+ queryParams: action.requestParams,
+ layerMetadata: action.layerMetadata
+ };
if (state.responses) {
newResponses = state.responses.slice();
- newResponses.push(action.data);
+ newResponses.push(obj);
} else {
- newResponses = [action.data];
+ newResponses = [obj];
}
return assign({}, state, {
responses: newResponses
@@ -68,11 +75,16 @@ function mapInfo(state = null, action) {
* }, ...]
*/
let newResponses;
+ let obj = {
+ response: action.exceptions,
+ queryParams: action.requestParams,
+ layerMetadata: action.layerMetadata
+ };
if (state.responses) {
newResponses = state.responses.slice();
- newResponses.push(action.exceptions);
+ newResponses.push(obj);
} else {
- newResponses = [action.exceptions];
+ newResponses = [obj];
}
return assign({}, state, {
responses: newResponses
@@ -89,16 +101,26 @@ function mapInfo(state = null, action) {
* }
*/
let newResponses;
+ let obj = {
+ response: action.error,
+ queryParams: action.requestParams,
+ layerMetadata: action.layerMetadata
+ };
if (state.responses) {
newResponses = state.responses.slice();
- newResponses.push(action.error);
+ newResponses.push(obj);
} else {
- newResponses = [action.error];
+ newResponses = [obj];
}
return assign({}, state, {
responses: newResponses
});
}
+ case CLICK_ON_MAP: {
+ return assign({}, state, {
+ clickPoint: action.point
+ });
+ }
default:
return state;
}
diff --git a/web/client/translations/data.en-US b/web/client/translations/data.en-US
index 764a14ee5f..7b919f9820 100644
--- a/web/client/translations/data.en-US
+++ b/web/client/translations/data.en-US
@@ -46,6 +46,7 @@
"maps_title": "Maps",
"locales_combo": "Language:"
},
- "getFeatureInfoTitle": "Feature Info"
+ "getFeatureInfoTitle": "Feature Info",
+ "noFeatureInfo": "There is no information available for the feature you clicked"
}
}
diff --git a/web/client/translations/data.it-IT b/web/client/translations/data.it-IT
index dbb7d323f0..ca25687c6e 100644
--- a/web/client/translations/data.it-IT
+++ b/web/client/translations/data.it-IT
@@ -46,6 +46,7 @@
"maps_title": "Mappe",
"locales_combo": "Lingua:"
},
- "getFeatureInfoTitle": "Informazioni Sulle Feature"
+ "getFeatureInfoTitle": "Informazioni Sulle Feature",
+ "noFeatureInfo": "Non ci sono informazioni disponibili per la feature selezionata"
}
}
diff --git a/web/client/utils/CoordinatesUtils.js b/web/client/utils/CoordinatesUtils.js
index 844bb88259..271af2e148 100644
--- a/web/client/utils/CoordinatesUtils.js
+++ b/web/client/utils/CoordinatesUtils.js
@@ -15,6 +15,30 @@ var CoordinatesUtils = {
return assign({}, Proj4js.transform(sourceProj, destProj, Proj4js.toPoint(point)), {srs: dest});
},
+ /**
+ * Reprojects a bounding box.
+ *
+ * @param bbox {array} [minx, miny, maxx, maxy]
+ * @param source {string} SRS of the given bbox
+ * @param dest {string} SRS of the returned bbox
+ *
+ * @return {array} [minx, miny, maxx, maxy]
+ */
+ reprojectBbox: function(bbox, source, dest) {
+ let points = {
+ sw: [bbox[0], bbox[1]],
+ ne: [bbox[2], bbox[3]]
+ };
+ let projPoints = [];
+ for (let p in points) {
+ if (points.hasOwnProperty(p)) {
+ let {x, y} = CoordinatesUtils.reproject(points[p], source, dest);
+ projPoints.push(x);
+ projPoints.push(y);
+ }
+ }
+ return projPoints;
+ },
normalizeSRS: function(srs) {
return srs === 'EPSG:900913' ? 'EPSG:3857' : srs;
}
diff --git a/web/client/utils/__tests__/CoordinatesUtils-test.js b/web/client/utils/__tests__/CoordinatesUtils-test.js
index 3e43dc394e..53e87ad3cb 100644
--- a/web/client/utils/__tests__/CoordinatesUtils-test.js
+++ b/web/client/utils/__tests__/CoordinatesUtils-test.js
@@ -28,4 +28,14 @@ describe('CoordinatesUtils', () => {
expect(transformed.y).toNotBe(13);
expect(transformed.srs).toBe('EPSG:900913');
});
+ it('convert lat lon bbox to marcator bbox', () => {
+ var bbox = [44, 12, 45, 13];
+ var projbbox = CoordinatesUtils.reprojectBbox(bbox, 'EPSG:4326', 'EPSG:900913');
+
+ expect(projbbox).toExist();
+ expect(projbbox.length).toBe(4);
+ for (let i = 0; i < 4; i++) {
+ expect(projbbox[i]).toNotBe(bbox[i]);
+ }
+ });
});
diff --git a/webpack.config.js b/webpack.config.js
index db9e3c1226..6091594062 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -48,6 +48,7 @@ module.exports = {
target: "http://mapstore.geo-solutions.it"
}, {
path: new RegExp("/mapstore/proxy(.*)"),
+ rewrite: rewriteUrl("/http_proxy/proxy$1"),
target: "http://localhost:8083"
}]
},