Skip to content

Commit

Permalink
Improvements to apis
Browse files Browse the repository at this point in the history
  • Loading branch information
mbarto committed Apr 5, 2017
1 parent 5632853 commit 43dcac3
Show file tree
Hide file tree
Showing 15 changed files with 237 additions and 14 deletions.
6 changes: 5 additions & 1 deletion web/client/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@
right: 100px;
bottom: 100px;
}
#mapstore2-embedded, #map, .fill {
width: 100%;
height: 100%;
}
</style>
</head>
<body onload="init()">
<div id="container"></div>
<div id="container" class="ms2"></div>
<script id="ms2-api" src="dist/ms2-api.js"></script>
<script type="text/javascript">
function init() {
Expand Down
69 changes: 69 additions & 0 deletions web/client/components/share/ShareApi.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Copyright 2017, 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.
*/

/* DESCRIPTION
This component contains the code and the button for copy the embedded code
to the clipboard
*/

// components required
const React = require('react');
const CopyToClipboard = require('react-copy-to-clipboard');
const Message = require('../../components/I18N/Message');
const {Glyphicon, Col, Grid, Row, Tooltip, Button} = require('react-bootstrap');
const OverlayTrigger = require('../misc/OverlayTrigger');


// css required
require('./share.css');

const codeApi = require('raw-loader!./api-template.raw');

const ShareApi = React.createClass({
propTypes: {
shareUrl: React.PropTypes.string,
shareConfigUrl: React.PropTypes.string
},
getInitialState() {
return {copied: false};
},
render() {
const parsedCode = codeApi
.replace('__BASE__URL__', this.props.shareUrl)
.replace('__CONFIG__URL__', this.props.shareConfigUrl);
const tooltip = (<Tooltip placement="bottom" className="in" id="tooltip-bottom" style={{zIndex: 2001}}>
{this.state.copied ? <Message msgId="share.msgCopiedUrl"/> : <Message msgId="share.msgToCopyUrl"/>}
</Tooltip>);
const copyTo = (<OverlayTrigger placement="bottom" overlay={tooltip}>
<CopyToClipboard text={parsedCode} onCopy={ () => this.setState({copied: true}) } >
<Button className="buttonCopyTextArea" bsStyle="info" bsSize="large">
<Glyphicon glyph="copy" onMouseLeave={() => {this.setState({copied: false}); }} />
</Button>
</CopyToClipboard>
</OverlayTrigger>);
return (
<div className="input-link">
<Grid className="embed-box" fluid={true}>
<Row key="title">
<h4>
<Message msgId="share.apiLinkTitle"/>
</h4>
</Row>
<Row key="data" className="row-button">
<Col key="textarea" xs={10} sm={10} md={10}><textarea name="description" rows="6" value={parsedCode} enabled="false" readOnly /></Col>
<Col key="button" xs={2} sm={2} md={2}>
{copyTo}
</Col>
</Row>
</Grid>
</div>
);
}
});

module.exports = ShareApi;
21 changes: 16 additions & 5 deletions web/client/components/share/SharePanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ const Dialog = require('../misc/Dialog');
const ShareSocials = require('./ShareSocials');
const ShareLink = require('./ShareLink');
const ShareEmbed = require('./ShareEmbed');
const ShareApi = require('./ShareApi');
const ShareQRCode = require('./ShareQRCode');
const {Glyphicon} = require('react-bootstrap');
const {Glyphicon, Tabs, Tab} = require('react-bootstrap');
const Message = require('../../components/I18N/Message');

let SharePanel = React.createClass({
Expand All @@ -30,6 +31,8 @@ let SharePanel = React.createClass({
title: React.PropTypes.node,
shareUrl: React.PropTypes.string,
shareEmbeddedUrl: React.PropTypes.string,
shareApiUrl: React.PropTypes.string,
shareConfigUrl: React.PropTypes.string,
onClose: React.PropTypes.func,
getCount: React.PropTypes.func,
closeGlyph: React.PropTypes.string
Expand All @@ -46,6 +49,17 @@ let SharePanel = React.createClass({
/* if the property shareUrl is not defined it takes the url from location.href */
const shareUrl = this.props.shareUrl || location.href;
const shareEmbeddedUrl = this.props.shareEmbeddedUrl || this.props.shareUrl || location.href;
const shareApiUrl = this.props.shareApiUrl || this.props.shareUrl || location.href;
const social = <ShareSocials shareUrl={shareUrl} getCount={this.props.getCount}/>;
const direct = (<div><ShareLink shareUrl={shareUrl}/><ShareQRCode shareUrl={shareUrl}/></div>);
const code = (<div><ShareEmbed shareUrl={shareEmbeddedUrl}/>
<ShareApi shareUrl={shareApiUrl} shareConfigUrl={this.props.shareConfigUrl}/></div>);

const tabs = (<Tabs defaultActiveKey={1} id="sharePanel-tabs">
<Tab eventKey={1} title={<Message msgId="share.direct" />}>{direct}</Tab>
<Tab eventKey={2} title={<Message msgId="share.social" />}>{social}</Tab>
<Tab eventKey={3} title={<Message msgId="share.code" />}>{code}</Tab>
</Tabs>);

let sharePanel = (
<Dialog id="share-panel-dialog" className="modal-dialog modal-content share-win">
Expand All @@ -58,10 +72,7 @@ let SharePanel = React.createClass({
</button>
</span>
<div role="body" className="share-panels">
<ShareSocials shareUrl={shareUrl} getCount={this.props.getCount}/>
<ShareLink shareUrl={shareUrl}/>
<ShareEmbed shareUrl={shareEmbeddedUrl}/>
<ShareQRCode shareUrl={shareUrl}/>
{tabs}
</div>
</Dialog>);

Expand Down
46 changes: 46 additions & 0 deletions web/client/components/share/__tests__/ShareApi-test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Copyright 2017, 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 expect = require('expect');
const React = require('react');
const ReactDOM = require('react-dom');
const ShareApi = require('../ShareApi');
const ReactTestUtils = require('react-addons-test-utils');

describe("The ShareEmbed component", () => {
beforeEach((done) => {
document.body.innerHTML = '<div id="container"></div>';
setTimeout(done);
});

afterEach((done) => {
ReactDOM.unmountComponentAtNode(document.getElementById("container"));
document.body.innerHTML = '';
setTimeout(done);
});

it('is created with defaults', () => {
const cmpSharePanel = ReactDOM.render(<ShareApi/>, document.getElementById("container"));
expect(cmpSharePanel).toExist();

});

it('should have the address url in the textarea field', () => {
const url = location.href;
const shareConfigUrl = 'configurl';

const cmpSharePanel = ReactDOM.render(<ShareApi shareUrl={url} shareConfigUrl={shareConfigUrl}/>, document.getElementById("container"));
expect(cmpSharePanel).toExist();

const textareaEmbed = ReactDOM.findDOMNode(ReactTestUtils.scryRenderedDOMComponentsWithTag(cmpSharePanel, "textarea")[0]);
expect(textareaEmbed).toExist();
expect(textareaEmbed.value.indexOf(url) !== -1).toBe(true);
expect(textareaEmbed.value.indexOf(shareConfigUrl) !== -1).toBe(true);
});

});
41 changes: 41 additions & 0 deletions web/client/components/share/api-template.raw
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page with MapStore 2 API</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway" type='text/css'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.css" />
<link rel="stylesheet" href="https://cdn.jslibs.mapstore2.geo-solutions.it/leaflet/0.2.4/leaflet.draw.css" />
<link rel="shortcut icon" type="image/png" href="https://cdn.jslibs.mapstore2.geo-solutions.it/leaflet/favicon.ico" />
<script src="https://maps.google.com/maps/api/js?v=3"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.10/proj4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.js"></script>
<script src="https://cdn.jslibs.mapstore2.geo-solutions.it/leaflet/0.2.4/leaflet.draw.js"></script>
<style>
#container {
position: absolute;
top: 100px;
left: 100px;
right: 100px;
bottom: 100px;
}
#mapstore2-embedded, #map, .fill {
width: 100%;
height: 100%;
}
</style>
</head>
<body onload="init()">
<div id="container" class="ms2"></div>
<script id="ms2-api" src="__BASE__URL__dist/ms2-api.js"></script>
<script type="text/javascript">
function init() {
MapStore2.create('container',{
configUrl: "__CONFIG__URL__"
});
}
</script>
</body>
</html>
9 changes: 9 additions & 0 deletions web/client/jsapi/MapStore2.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const ReactDOM = require('react-dom');

const StandardApp = require('../components/app/StandardApp');
const LocaleUtils = require('../utils/LocaleUtils');
const ConfigUtils = require('../utils/ConfigUtils');
const {connect} = require('react-redux');

const {configureMap, loadMapConfig} = require('../actions/config');
Expand Down Expand Up @@ -319,6 +320,14 @@ const MapStore2 = {
});
});
};
if (options.noLocalConfig) {
ConfigUtils.setLocalConfigurationFile('');
ConfigUtils.setConfigProp('proxyUrl', options.proxy || null);
}

if (options.translations) {
ConfigUtils.setConfigProp('translationsPath', options.translations);
}
ReactDOM.render(<StandardApp onStoreInit={onStoreInit} themeCfg={themeCfg} className="fill" {...appConfig}/>, document.getElementById(container));
},
buildPluginsCfg,
Expand Down
18 changes: 17 additions & 1 deletion web/client/plugins/Share.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const assign = require('object-assign');
const {Glyphicon} = require('react-bootstrap');
const Message = require('../components/I18N/Message');
const {toggleControl} = require('../actions/controls');
const ConfigUtils = require('../utils/ConfigUtils');

const Url = require('url');


Expand All @@ -31,10 +33,24 @@ const getEmbeddedUrl = (url) => {
urlParsedObj.hash.substring(urlParsedObj.hash.lastIndexOf('/') + 1, urlParsedObj.hash.lastIndexOf('?'));
};

const getApiUrl = (url) => {
let urlParsedObj = Url.parse(url, true);

return urlParsedObj.protocol + '//' + urlParsedObj.host + urlParsedObj.path;
};

const getConfigUrl = (url) => {
let urlParsedObj = Url.parse(url, true);

return urlParsedObj.protocol + '//' + (urlParsedObj.host + urlParsedObj.path + ConfigUtils.getConfigProp('geoStoreUrl') + 'data/' + urlParsedObj.hash.substring(urlParsedObj.hash.lastIndexOf('/') + 1, urlParsedObj.hash.lastIndexOf('?'))).replace('//', '/');
};

const Share = connect((state) => ({
isVisible: state.controls && state.controls.share && state.controls.share.enabled,
shareUrl: location.href,
shareEmbeddedUrl: getEmbeddedUrl(location.href)
shareEmbeddedUrl: getEmbeddedUrl(location.href),
shareApiUrl: getApiUrl(location.href),
shareConfigUrl: getConfigUrl(location.href)
}), {
onClose: toggleControl.bind(null, 'share', null)
})(require('../components/share/SharePanel'));
Expand Down
4 changes: 3 additions & 1 deletion web/client/product/api.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const MapStore2 = require('../jsapi/MapStore2')
.withPlugins(require('./apiPlugins'), {
theme: {
path: getScriptPath() + '/themes'
}
},
noLocalConfig: true,
translations: getScriptPath() + '/../translations'
});
window.MapStore2 = MapStore2;
1 change: 0 additions & 1 deletion web/client/themes/default/base.less
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@
line-height: 1.428571429;
color: @ms2-color-text;
background-color: @ms2-color-background;
overflow: hidden;
}
4 changes: 4 additions & 0 deletions web/client/themes/default/ms2-theme.less
Original file line number Diff line number Diff line change
Expand Up @@ -1016,3 +1016,7 @@ select.form-control option {
height: 100%;
position: absolute !important;
}

.mapstore2-embedded {
overflow: hidden;
}
4 changes: 4 additions & 0 deletions web/client/translations/data.de-DE
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,10 @@
"socialIntro": "In deinem bevorzugten sozialen Netzwerk",
"directLinkTitle": "Über einen direkten Link",
"embeddedLinkTitle": "Über einen eingebetteten Code",
"apiLinkTitle": "API verwenden",
"social": "Social",
"direct": "Link",
"code": "Embed",
"QRCodeLinkTitle": "QR code",
"msgCopiedUrl":"Kopiert",
"msgToCopyUrl":"Klicke um zu kopieren"
Expand Down
4 changes: 4 additions & 0 deletions web/client/translations/data.en-US
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,10 @@
"socialIntro": "In your favourite social network",
"directLinkTitle": "Via a direct link",
"embeddedLinkTitle": "Via the embedded code",
"apiLinkTitle": "Using APIs",
"social": "Social",
"direct": "Link",
"code": "Embed",
"QRCodeLinkTitle": "qr code",
"msgCopiedUrl":"Copied",
"msgToCopyUrl":"Click to copy"
Expand Down
4 changes: 4 additions & 0 deletions web/client/translations/data.fr-FR
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,10 @@
"socialIntro": "via votre réseau social favori",
"directLinkTitle": "Via un lien direct",
"embeddedLinkTitle": "Via le code intégré",
"apiLinkTitle": "Via le APIs",
"social": "Social",
"direct": "Link",
"code": "Embed",
"QRCodeLinkTitle": "qr code",
"msgCopiedUrl":"Copié",
"msgToCopyUrl":"Cliquer pour copier"
Expand Down
4 changes: 4 additions & 0 deletions web/client/translations/data.it-IT
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,11 @@
"titlePanel": "Condividi la mappa",
"socialIntro": "Sul tuo social preferito",
"directLinkTitle": "Con un Link diretto",
"social": "Social",
"direct": "Link",
"code": "Embed",
"embeddedLinkTitle": "Con il codice embedded",
"apiLinkTitle": "Usando le API",
"QRCodeLinkTitle": "Usando il QR Code",
"msgCopiedUrl":"Copiato",
"msgToCopyUrl":"Clicca per copiare"
Expand Down
16 changes: 11 additions & 5 deletions web/client/utils/ConfigUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var axios = require('axios');

const {isArray} = require('lodash');
const assign = require('object-assign');
const {Promise} = require('es6-promise');

const epsg4326 = Proj4js ? new Proj4js.Proj('EPSG:4326') : null;
const centerPropType = React.PropTypes.shape({
Expand Down Expand Up @@ -57,11 +58,16 @@ var ConfigUtils = {
localConfigFile = file;
},
loadConfiguration: function() {
return axios.get(localConfigFile).then(response => {
if (typeof response.data === 'object') {
defaultConfig = assign({}, defaultConfig, response.data);
}
return defaultConfig;
if (localConfigFile) {
return axios.get(localConfigFile).then(response => {
if (typeof response.data === 'object') {
defaultConfig = assign({}, defaultConfig, response.data);
}
return defaultConfig;
});
}
return new Promise((resolve) => {
resolve(defaultConfig);
});
},

Expand Down

0 comments on commit 43dcac3

Please sign in to comment.