-
Notifications
You must be signed in to change notification settings - Fork 410
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
Fix #2661 First implementation of map widget #2721
Changes from 10 commits
59227ec
1fb9a0d
7ad6f75
d0b3eac
042f54d
12c9405
0262403
96b1030
b4c0708
b02bad0
53abde7
1a9027e
b04ab28
26e3333
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/* | ||
* Copyright 2018, 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 PropTypes = require('prop-types'); | ||
const { isString } = require('lodash'); | ||
|
||
/** | ||
* Base map component that renders a map. | ||
* It is implementation independent. | ||
* The implementation of the layer is provided by the `plugins` property | ||
* @prop {string} id the id of the map div | ||
* @prop {object} options. Options to pass to the map component (generically constant) | ||
* @prop {object} map the map properties (projection...) This is generically the dynamic part of the map options. | ||
* @prop {object[]} layers the layers to add to the map | ||
* @prop {object} plugins specific implementation of the components to render. | ||
* Must contain implementations for: | ||
* - Map React component for Map | ||
* - Layer React component for Layer | ||
* - Feature (optional) React component for vector Feature | ||
* - tools (optional) any support tool you want to use | ||
* @prop {array} tools. A list of tools (string name or object with `name` and other options as attribute) to add to the map. | ||
* @prop {object} eventHandlers handlers for map events | ||
* Each tool must be implemented in plugins.tools | ||
* | ||
*/ | ||
class BaseMap extends React.Component { | ||
static propTypes = { | ||
id: PropTypes.string, | ||
options: PropTypes.object, | ||
map: PropTypes.object, | ||
mapStateSource: PropTypes.string, | ||
eventHandlers: PropTypes.object, | ||
layers: PropTypes.array, | ||
plugins: PropTypes.any, | ||
tools: PropTypes.array, | ||
getLayerProps: PropTypes.func | ||
}; | ||
|
||
static defaultProps = { | ||
id: '__base_map__', | ||
options: {}, | ||
map: {}, | ||
tools: [], | ||
eventHandlers: { | ||
onMapViewChanges: () => {}, | ||
onClick: () => {}, | ||
onMouseMove: () => {}, | ||
onLayerLoading: () => {}, | ||
onLayerError: () => {} | ||
} | ||
}; | ||
|
||
getTool = (tool) => { | ||
const { plugins } = this.props; | ||
if (isString(tool)) { | ||
return { | ||
name: tool, | ||
impl: plugins.tools[tool] | ||
}; | ||
} | ||
return { | ||
name: tool.name, | ||
impl: plugins.tools[tool.name], | ||
...tool | ||
}; | ||
}; | ||
|
||
renderLayers = () => { | ||
const projection = this.props.map.projection || 'EPSG:3857'; | ||
const { plugins } = this.props; | ||
const { Layer } = plugins; | ||
return this.props.layers.map((layer, index) => { | ||
return ( | ||
<Layer | ||
type={layer.type} | ||
srs={projection} | ||
position={index} | ||
key={layer.id || layer.name} | ||
options={layer} | ||
> | ||
{this.renderLayerContent(layer, projection)} | ||
</Layer> | ||
); | ||
}); | ||
}; | ||
|
||
renderLayerContent = (layer, projection) => { | ||
if (layer.features && layer.type === "vector") { | ||
const { plugins } = this.props; | ||
const { Feature } = plugins; | ||
return layer.features.map((feature) => { | ||
return ( | ||
<Feature | ||
key={feature.id} | ||
msId={feature.id} | ||
type={feature.type} | ||
crs={projection} | ||
geometry={feature.geometry} | ||
msId={feature.id} | ||
featuresCrs={layer.featuresCrs || 'EPSG:4326'} | ||
// FEATURE STYLE OVERWRITE LAYER STYLE | ||
layerStyle={layer.style} | ||
style={feature.style || layer.style || null} | ||
properties={feature.properties} /> | ||
); | ||
}); | ||
} | ||
return null; | ||
}; | ||
|
||
renderTools = () => { | ||
return this.props.tools.map((tool) => { | ||
const {impl: Tool, name, ...options} = this.getTool(tool); | ||
return <Tool key={name} {...options} />; | ||
}); | ||
}; | ||
|
||
render() { | ||
const {plugins} = this.props; | ||
const {Map} = plugins; | ||
if (this.props.map) { | ||
return ( | ||
<Map | ||
id={this.props.id} | ||
zoomControl={false} | ||
center={{ x: 0, y: 0 }} | ||
zoom={1} | ||
mapStateSource={this.props.mapStateSource || this.props.id} | ||
{...this.props.options} | ||
{...this.props.map} | ||
{...this.props.eventHandlers} | ||
> | ||
{this.renderLayers()} | ||
{this.renderTools()} | ||
</Map> | ||
); | ||
} | ||
return null; | ||
} | ||
} | ||
module.exports = BaseMap; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/* | ||
* Copyright 2018, 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'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why it doesn't work for Firefox? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maptype is cesium There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, got it, because of Cesium |
||
const ReactDOM = require('react-dom'); | ||
const expect = require('expect'); | ||
|
||
const BaseMap = require('../BaseMap'); | ||
const mapType = require('../enhancers/mapType'); | ||
const TestMap = mapType(BaseMap); | ||
|
||
const LAYER_OSM = { | ||
"id": "mapnik__1", | ||
"group": "background", | ||
"source": "osm", | ||
"name": "mapnik", | ||
"title": "Open Street Map", | ||
"type": "osm", | ||
"visibility": true, | ||
"singleTile": false, | ||
"dimensions": [], | ||
"hideLoading": false, | ||
"handleClickOnLayer": false | ||
}; | ||
const VECTOR_SAMPLE = { | ||
"id": "annotations", | ||
"features": [ | ||
{ | ||
"type": "Feature", | ||
"properties": { | ||
"title": "Title", | ||
"id": "25cbbbb0-1625-11e8-a091-639e3ca0149f" | ||
}, | ||
"geometry": { | ||
"type": "MultiPolygon", | ||
"coordinates": [ | ||
[ | ||
[ | ||
[ | ||
-9.272079296695848, | ||
25.633162709158384 | ||
], | ||
[ | ||
0.17443093439845475, | ||
38.01066790632649 | ||
], | ||
[ | ||
11.823370741927429, | ||
17.650189135909482 | ||
], | ||
[ | ||
-9.272079296695848, | ||
25.633162709158384 | ||
] | ||
] | ||
] | ||
] | ||
}, | ||
"style": { | ||
"type": "MultiPolygon", | ||
"MultiPolygon": { | ||
"color": "#ffcc33", | ||
"opacity": 1, | ||
"weight": 3, | ||
"fillColor": "#ffffff", | ||
"fillOpacity": 0.2, | ||
"editing": { | ||
"fill": 1 | ||
} | ||
}, | ||
"Polygon": { | ||
"color": "#ffcc33", | ||
"opacity": 1, | ||
"weight": 3, | ||
"fillColor": "#ffffff", | ||
"fillOpacity": 0.2, | ||
"editing": { | ||
"fill": 1 | ||
} | ||
}, | ||
"highlight": false | ||
} | ||
} | ||
], | ||
"name": "Annotations", | ||
"style": { | ||
"type": "MultiPolygon", | ||
"MultiPolygon": { | ||
"color": "#ffcc33", | ||
"opacity": 1, | ||
"weight": 3, | ||
"fillColor": "#ffffff", | ||
"fillOpacity": 0.2, | ||
"editing": { | ||
"fill": 1 | ||
} | ||
}, | ||
"Polygon": { | ||
"color": "#ffcc33", | ||
"opacity": 1, | ||
"weight": 3, | ||
"fillColor": "#ffffff", | ||
"fillOpacity": 0.2, | ||
"editing": { | ||
"fill": 1 | ||
} | ||
} | ||
}, | ||
"type": "vector", | ||
"visibility": true, | ||
"singleTile": false, | ||
"dimensions": [ | ||
|
||
], | ||
"hideLoading": true, | ||
"handleClickOnLayer": true | ||
}; | ||
const SAMPLE_LAYERS_1 = [LAYER_OSM, VECTOR_SAMPLE]; | ||
|
||
window.CESIUM_BASE_URL = "web/client/libs/Cesium/Build/Cesium"; | ||
|
||
describe('BaseMap', () => { | ||
beforeEach((done) => { | ||
document.body.innerHTML = '<div id="container"></div>'; | ||
setTimeout(done); | ||
}); | ||
afterEach((done) => { | ||
ReactDOM.unmountComponentAtNode(document.getElementById("container")); | ||
document.body.innerHTML = ''; | ||
setTimeout(done); | ||
}); | ||
it('test cesium map', () => { | ||
const map = ReactDOM.render(<TestMap mapType="cesium" id="myMap" layers={SAMPLE_LAYERS_1} />, document.getElementById("container")); | ||
expect(map).toExist(); | ||
const el = ReactDOM.findDOMNode(map); | ||
expect(el).toExist(); | ||
expect(el.id).toBe("myMap"); | ||
expect(el.querySelector('canvas')).toExist(); | ||
|
||
}); | ||
|
||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this component replace this one: https://github.com/geosolutions-it/MapStore2/blob/master/web/client/plugins/Map.jsx#L119 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I developed it also for this purpose. It's a simplified and more clear version of it. Some property mapping, transformation should be enough to replace it in the future.
Didn't want to replace a so important element at this stage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would go for replace it now, unless we want to replace it "mai"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I know. But now base map has a minimal support and is not enough tested. if I replace it I've got to fully support cesium and other minor things that are out of scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could open a separate issue for that