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

Fix #2661 First implementation of map widget #2721

Merged
merged 14 commits into from
Mar 19, 2018
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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 @@ -181,6 +181,7 @@
"redux-thunk": "0.1.0",
"redux-undo": "0.5.0",
"reselect": "2.5.1",
"resize-observer-polyfill": "1.5.0",
"rxjs": "5.1.1",
"screenfull": "3.1.0",
"shpjs": "3.4.2",
Expand Down
2 changes: 1 addition & 1 deletion utility/translations/findMissingTranslations.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,6 @@ files.forEach(file => {
if (fail) {
throw Error("i18n files failed");
}
log('## mandatory translations checks passed!! ##');
log('## mandatory translations checks passed!! ##\n');


146 changes: 146 additions & 0 deletions web/client/components/map/BaseMap.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

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.

Copy link
Contributor

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"

Copy link
Member Author

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.

Copy link
Member Author

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

* 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;
146 changes: 146 additions & 0 deletions web/client/components/map/__tests__/BaseMap-test-chrome.jsx
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');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't work for Firefox?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maptype is cesium

Copy link
Contributor

Choose a reason for hiding this comment

The 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();

});

});
Loading