src/components/geonode.jsx
import React from 'react';
global.React = React;
import ReactDOM from 'react-dom';
global.ReactDOM = ReactDOM;
import 'core-js/fn/object/assign';
import ol from 'openlayers';
import {addLocaleData, IntlProvider} from 'react-intl';
global.IntlProvider = IntlProvider;
import injectTapEventPlugin from 'react-tap-event-plugin';
import Globe from '@boundlessgeo/sdk/components/Globe';
import QGISPrint from '@boundlessgeo/sdk/components/QGISPrint';
import Zoom from '@boundlessgeo/sdk/components/Zoom';
import Rotate from '@boundlessgeo/sdk/components/Rotate';
import HomeButton from '@boundlessgeo/sdk/components/HomeButton';
import MapPanel from '@boundlessgeo/sdk/components/MapPanel';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import Snackbar from 'material-ui/Snackbar';
import LayerList from '@boundlessgeo/sdk/components/LayerList';
import enLocaleData from 'react-intl/locale-data/en.js';
import InfoPopup from '@boundlessgeo/sdk/components/InfoPopup';
import MapConfigTransformService from '@boundlessgeo/sdk/services/MapConfigTransformService';
import MapConfigService from '@boundlessgeo/sdk/services/MapConfigService';
import WMSService from '@boundlessgeo/sdk/services/WMSService';
import enMessages from '@boundlessgeo/sdk/locale/en.js';
enMessages["loginmodal.helptext"] = "Login to GeoNode";
global.enMessages = enMessages;
import Save from './save';
import MapUrlLink from '../containers/MapUrlLink';
import {getLocalGeoServer,createThumbnail} from '../services/geonode';
import {getCRSFToken} from '../helper';
import '../css/app.css'
import '@boundlessgeo/sdk/dist/css/components.css';
global.checkUrlCORSCompatible = function(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
var response;
xhr.open("GET", url, true);
xhr.withCredentials = true;
xhr.onload = function() {
if (this.status >= 200 && this.status < 400 && xhr.response != null) {
// We don't care as long as it worked
resolve(true);
} else {
reject({
status: this.status,
statusText: this.statusText
});
}
};
xhr.onerror = function() {
reject({
status: this.status,
statusText: this.statusText
});
};
xhr.send();
});
};
// Needed for onTouchTap
// Can go away when react 1.0 release
// Check this repo:
// https://github.com/zilverline/react-tap-event-plugin
injectTapEventPlugin();
addLocaleData(enLocaleData);
var map = new ol.Map({
controls: [
new ol.control.Attribution({collapsible: false}),
new ol.control.ScaleLine()
],
layers: [new ol.layer.Tile({title: 'OSM Streets', type: 'base', source: new ol.source.OSM()})],
view: new ol.View({
center: [
0, 0
],
zoom: 3
})
});
window.setThumbnail = function(obj_id) {
createThumbnail(obj_id,map)
}
class GeoNodeViewer extends React.Component {
constructor(props) {
super(props);
this.state = {
tileServices: undefined,
errors: [],
errorOpen: false
};
this._local = getLocalGeoServer(props.config.sources, props.baseUrl);
}
getChildContext() {
return {
proxy: this.props.proxy,
requestHeaders: {
'X-CSRFToken': getCRSFToken()
},
muiTheme: getMuiTheme(this.props.theme)
};
}
componentWillMount() {
this.updateMap(this.props);
this.mode = this.props.mode || 'viewer';
this.edit = (this.mode === 'composer');
}
componentWillReceiveProps(props) {
this.updateMap(props);
}
updateMap(props) {
if (props.config) {
var tileServices = [];
var errors = [];
var filteredErrors = [];
if (props.zoomToLayer && props.config.map.layers[props.config.map.layers.length - 1].bbox) {
this._extent = props.config.map.layers[props.config.map.layers.length - 1].bbox;
}
MapConfigService.load(MapConfigTransformService.transform(props.config, errors, tileServices, props.crossOriginCredentials), map, this.props.proxy);
for (var i = 0, ii = errors.length; i < ii; ++i) {
// ignore the empty baselayer since we have checkbox now for base layer group
// ignore the empty layer from the local source
if (errors[i].layer.type !== 'OpenLayers.Layer' && errors[i].msg !== 'Unable to load layer undefined') {
if (window.console && window.console.warn) {
window.console.warn(errors[i]);
}
filteredErrors.push(errors[i]);
}
}
this.setState({errors: filteredErrors, errorOpen: true, tileServices: tileServices});
}
}
_handleRequestClose() {
this.setState({errorOpen: false});
}
_createLayerList() {
let layerList;
if (this._local) {
layerList = {
sources: [
{
title: this._local.title,
url: this._local.url,
type: 'WMS'
}
],
allowUserInput: true
};
} else {
layerList = {
sources: [
{
title: 'Local Geoserver',
url: this.props.server + '/geoserver/wms',
type: 'WMS'
}
],
allowUserInput: true
};
}
return layerList;
}
render() {
var error;
if (this.state.errors.length > 0) {
var msg = '';
for (var i = 0, ii = this.state.errors.length; i < ii; i++) {
msg += this.state.errors[i].msg + '. ';
}
error = (<Snackbar autoHideDuration={5000} open={this.state.errorOpen} message={msg} onRequestClose={this._handleRequestClose.bind(this)}/>);
}
let layerList,
save,
mapUrl;
if (this.edit) {
layerList = this._createLayerList();
if (this.props.server) {
save = (
<div id='save-button' className='geonode-save'><Save map={map}/></div>
);
mapUrl = (<MapUrlLink/>);
}
}
return (
<div id='content'>
{error}
<MapPanel useHistory={true} id='map' map={map} extent={this._extent}/>
<div id='globe-button'><Globe tooltipPosition='right' map={map}/></div>
<div id='print-button'><QGISPrint menu={false} map={map} layouts={this.props.printLayouts}/></div>
<div id='home-button'><HomeButton extent={this._extent} tooltipPosition='right' map={map}/></div>
<div id='layerlist'><LayerList showZoomTo={true} addBaseMap={true} baseMapTileServices={this.state.tileServices} addLayer={layerList} showTable={true} allowReordering={true} includeLegend={true} allowRemove={this.edit} tooltipPosition='left' allowStyling={this.edit || this.props.zoomToLayer} map={map}/></div>
<div id='zoom-buttons'><Zoom tooltipPosition='right' map={map}/></div>
<div id='rotate-button'><Rotate autoHide={true} tooltipPosition='right' map={map}/></div>
<div id='popup' className='ol-popup'><InfoPopup toggleGroup='navigation' toolId='nav' infoFormat='application/vnd.ogc.gml' map={map}/></div>
{save}
{mapUrl}
</div>
);
}
}
GeoNodeViewer.props = {
config: React.PropTypes.object,
loadMapConfig: React.PropTypes.bool,
proxy: React.PropTypes.string,
theme: React.PropTypes.object,
mode: React.PropTypes.string,
server: React.PropTypes.string,
printLayouts: React.PropTypes.array,
crossOriginCredentials: React.PropTypes.bool
};
GeoNodeViewer.defaultProps = {
theme: {
floatingActionButton: {
iconColor: '#fff',
color: '#2c689c'
},
toolbar: {
backgroundColor: '#333'
},
palette: {
primary1Color: '#2c689c',
primary2Color: '#2c689c',
primary3Color: '#2c689c',
accent1Color: '#2c689c',
accent2Color: '#2c689c',
accent3Color: '#2c689c',
textColor: '#2E506D',
secondaryTextColor: '#fff',
alternateTextColor: '#fff',
canvasColor: '#fff'
}
},
printLayouts: [
{
"width": 297.0,
"elements": [
{
"name": "Title",
"height": 12.105490848585688,
"width": 143.0648918469218,
"y": 2.7512479201331113,
"x": 5.777620632279534,
"font": "",
"type": "label",
"id": "cc8bd50f36e44ac3a3e5daf48d038f7c",
"size": 18
}, {
"height": 187.0,
"width": 286.0,
"grid": {
"intervalX": 0.0,
"intervalY": 0.0,
"annotationEnabled": false,
"crs": ""
},
"y": 17.0,
"x": 6.0,
"type": "map",
"id": "3bde6dd61cdf480eae1a67db59d74035"
}
],
"thumbnail": "geonode_thumbnail.png",
"name": "geonode",
"height": 210.0
}
]
};
GeoNodeViewer.childContextTypes = {
proxy: React.PropTypes.string,
requestHeaders: React.PropTypes.object,
muiTheme: React.PropTypes.object
};
export default GeoNodeViewer;
global.GeoNodeViewer = GeoNodeViewer;