diff --git a/package.json b/package.json index 2378e9c490..26305de3d5 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "react-dom": "0.14.8", "react-draggable": "1.3.4", "react-dropzone": "3.4.0", - "react-intl": "https://github.com/geosolutions-it/react-intl/tarball/react_014_1x", + "react-intl": "2.2.3", "react-joyride": "1.10.1", "react-nouislider": "1.11.0", "react-overlays": "0.6.3", diff --git a/web/client/components/I18N/Date.jsx b/web/client/components/I18N/Date.jsx index 1e9ff61314..e90957a823 100644 --- a/web/client/components/I18N/Date.jsx +++ b/web/client/components/I18N/Date.jsx @@ -10,13 +10,11 @@ var {FormattedDate} = require('react-intl'); var DateFormat = React.createClass({ propTypes: { - locale: React.PropTypes.string, value: React.PropTypes.object, dateParams: React.PropTypes.object }, contextTypes: { - locale: React.PropTypes.string, - messages: React.PropTypes.object + intl: React.PropTypes.object }, getDefaultProps() { return { @@ -24,8 +22,7 @@ var DateFormat = React.createClass({ }; }, render() { - var locale = this.props.locale || this.context.locale; - return ; + return this.context.intl ? : {this.props.value && this.props.value.toString() || ''}; } }); diff --git a/web/client/components/I18N/HTML.jsx b/web/client/components/I18N/HTML.jsx index 4abbf101a6..3c7b6474c9 100644 --- a/web/client/components/I18N/HTML.jsx +++ b/web/client/components/I18N/HTML.jsx @@ -11,23 +11,14 @@ var FormattedHTMLMessage = ReactIntl.FormattedHTMLMessage; var Message = React.createClass({ propTypes: { - locale: React.PropTypes.string, - messages: React.PropTypes.object, msgId: React.PropTypes.string.isRequired, msgParams: React.PropTypes.object }, contextTypes: { - locale: React.PropTypes.string, - messages: React.PropTypes.object + intl: React.PropTypes.object }, render() { - var locale = this.props.locale || this.context.locale; - var messages = this.props.messages || this.context.messages; - let message = messages; - this.props.msgId.split('.').forEach(part => { - message = message[part]; - }); - return ; + return this.context.intl ? : {this.props.msgId || ""}; } }); module.exports = Message; diff --git a/web/client/components/I18N/Localized.jsx b/web/client/components/I18N/Localized.jsx index fdd1057d3f..c789ee66ca 100644 --- a/web/client/components/I18N/Localized.jsx +++ b/web/client/components/I18N/Localized.jsx @@ -5,9 +5,11 @@ * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ -var React = require('react'); +const React = require('react'); -var Localized = React.createClass({ +const {IntlProvider} = require('react-intl'); + +const Localized = React.createClass({ propTypes: { locale: React.PropTypes.string, messages: React.PropTypes.object, @@ -31,11 +33,27 @@ var Localized = React.createClass({ children = children(); } - return React.Children.only(children); + return ( + {children} + ); + // return React.Children.only(children); } else if (this.props.loadingError) { return
{this.props.loadingError}
; } return null; + }, + flattenMessages(messages, prefix = '') { + return Object.keys(messages).reduce((previous, current) => { + return (typeof messages[current] === 'string') ? { + [prefix + current]: messages[current], + ...previous + } : { + ...this.flattenMessages(messages[current], prefix + current + '.'), + ...previous + }; + }, {}); } }); diff --git a/web/client/components/I18N/Message.jsx b/web/client/components/I18N/Message.jsx index 7f966fc579..814058a600 100644 --- a/web/client/components/I18N/Message.jsx +++ b/web/client/components/I18N/Message.jsx @@ -10,25 +10,16 @@ const ReactIntl = require('react-intl'); const FormattedMessage = ReactIntl.FormattedMessage; -const LocaleUtils = require('../../utils/LocaleUtils'); - -var Message = React.createClass({ +const Message = React.createClass({ propTypes: { - locale: React.PropTypes.string, - messages: React.PropTypes.object, msgId: React.PropTypes.string.isRequired, msgParams: React.PropTypes.object }, contextTypes: { - locale: React.PropTypes.string, - messages: React.PropTypes.object + intl: React.PropTypes.object }, render() { - var locale = this.props.locale || this.context.locale; - var messages = this.props.messages || this.context.messages; - let message = LocaleUtils.getMessageById(messages, this.props.msgId); - - return message ? : ; + return this.context.intl ? : {this.props.msgId || ""}; } }); diff --git a/web/client/components/I18N/Number.jsx b/web/client/components/I18N/Number.jsx new file mode 100644 index 0000000000..6e88795f5f --- /dev/null +++ b/web/client/components/I18N/Number.jsx @@ -0,0 +1,29 @@ +/** + * 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 React = require('react'); +var {FormattedNumber} = require('react-intl'); + +var NumberFormat = React.createClass({ + propTypes: { + value: React.PropTypes.object, + numberParams: React.PropTypes.object + }, + contextTypes: { + intl: React.PropTypes.object + }, + getDefaultProps() { + return { + value: new Date() + }; + }, + render() { + return this.context.intl ? : {this.props.value && this.props.value.toString() || ''}; + } +}); + +module.exports = NumberFormat; diff --git a/web/client/components/I18N/__tests__/18N.HTML-test.jsx b/web/client/components/I18N/__tests__/18N.HTML-test.jsx index 842813ef33..de73677acb 100644 --- a/web/client/components/I18N/__tests__/18N.HTML-test.jsx +++ b/web/client/components/I18N/__tests__/18N.HTML-test.jsx @@ -10,6 +10,7 @@ var expect = require('expect'); var React = require('react/addons'); var ReactDOM = require('react-dom'); var I18N = require('../I18N'); +var Localized = require('../Localized'); var ita = { "locale": "it-IT", @@ -45,7 +46,7 @@ describe('This test for I18N.HTML', () => { var currentData = data["en-US"]; var testMsg = currentData.messages[msgId]; - const cmp = ReactDOM.render(, document.getElementById("container")); + const cmp = ReactDOM.render(, document.getElementById("container")); expect(cmp).toExist(); const cmpDom = ReactDOM.findDOMNode(cmp); @@ -57,7 +58,7 @@ describe('This test for I18N.HTML', () => { var currentData = data["it-IT"]; var testMsg = currentData.messages[msgId]; - const cmp = ReactDOM.render(, document.getElementById("container")); + const cmp = ReactDOM.render(, document.getElementById("container")); expect(cmp).toExist(); const cmpDom = ReactDOM.findDOMNode(cmp); diff --git a/web/client/components/I18N/__tests__/I18N.Message-test.jsx b/web/client/components/I18N/__tests__/I18N.Message-test.jsx index c45f1a8a00..945c9a0881 100644 --- a/web/client/components/I18N/__tests__/I18N.Message-test.jsx +++ b/web/client/components/I18N/__tests__/I18N.Message-test.jsx @@ -10,6 +10,7 @@ var expect = require('expect'); var React = require('react'); var ReactDOM = require('react-dom'); var I18N = require('../I18N'); +var Localized = require('../Localized'); var ita = { "locale": "it-IT", @@ -45,7 +46,7 @@ describe('This test for I18N.Message', () => { var currentData = data["en-US"]; var testMsg = currentData.messages[msgId]; - const cmp = ReactDOM.render(, document.getElementById("container")); + const cmp = ReactDOM.render(, document.getElementById("container")); expect(cmp).toExist(); const cmpDom = ReactDOM.findDOMNode(cmp); @@ -57,7 +58,7 @@ describe('This test for I18N.Message', () => { var currentData = data["it-IT"]; var testMsg = currentData.messages[msgId]; - const cmp = ReactDOM.render(, document.getElementById("container")); + const cmp = ReactDOM.render(, document.getElementById("container")); expect(cmp).toExist(); const cmpDom = ReactDOM.findDOMNode(cmp); diff --git a/web/client/components/catalog/SharingLink.jsx b/web/client/components/catalog/SharingLink.jsx index 9f90e00892..996a885aab 100644 --- a/web/client/components/catalog/SharingLink.jsx +++ b/web/client/components/catalog/SharingLink.jsx @@ -16,8 +16,6 @@ const SharingLink = React.createClass({ url: React.PropTypes.string.isRequired, labelId: React.PropTypes.string, onCopy: React.PropTypes.func, - messages: React.PropTypes.object, - locale: React.PropTypes.string, bsSize: React.PropTypes.string, addAuthentication: React.PropTypes.bool }, @@ -48,7 +46,7 @@ const SharingLink = React.createClass({ this.setState({showCopiedToolTip: false})}> diff --git a/web/client/components/catalog/__tests__/SharingLink-test.jsx b/web/client/components/catalog/__tests__/SharingLink-test.jsx index 2f30e22276..3b19cfe5fb 100644 --- a/web/client/components/catalog/__tests__/SharingLink-test.jsx +++ b/web/client/components/catalog/__tests__/SharingLink-test.jsx @@ -7,7 +7,8 @@ */ const React = require('react'); const ReactDOM = require('react-dom'); -const SharingLink = require('../SharingLink.jsx'); +const SharingLink = require('../SharingLink'); +const Localized = require('../../I18N/Localized'); const expect = require('expect'); const TestUtils = require('react-addons-test-utils'); @@ -51,7 +52,7 @@ describe('Tests for SharingLink', () => { // creating the messages object const messages = {'link': 'Link'}; // intanciating the component - const component = ReactDOM.render(, + const component = ReactDOM.render(, document.getElementById('container')); expect(component).toExist(); // expecting a dom node to be available diff --git a/web/client/components/mapcontrols/measure/MeasureComponent.jsx b/web/client/components/mapcontrols/measure/MeasureComponent.jsx index fdb186b33e..1a9057ef47 100644 --- a/web/client/components/mapcontrols/measure/MeasureComponent.jsx +++ b/web/client/components/mapcontrols/measure/MeasureComponent.jsx @@ -9,8 +9,7 @@ const React = require('react'); const {Panel, ButtonGroup, Tooltip, Glyphicon, Button} = require('react-bootstrap'); const ToggleButton = require('../../buttons/ToggleButton'); -const ReactIntl = require('react-intl'); -const FormattedNumber = ReactIntl.FormattedNumber; +var NumberFormat = require('../../I18N/Number'); const lineRuleIcon = require('./img/line-ruler.png'); const areaRuleIcon = require('./img/area-ruler.png'); @@ -122,9 +121,9 @@ const MeasureComponent = React.createClass({ return (

{this.props.lengthLabel}: - {this.props.uom.length.label}

+ {this.props.uom.length.label}

{this.props.areaLabel}: - {this.props.uom.area.label}

+ {this.props.uom.area.label}

{this.props.bearingLabel}: {this.props.formatBearing(this.props.measurement.bearing || 0)}

diff --git a/web/client/components/mapcontrols/measure/MeasureResults.jsx b/web/client/components/mapcontrols/measure/MeasureResults.jsx index 750a86ee49..6d933e53ac 100644 --- a/web/client/components/mapcontrols/measure/MeasureResults.jsx +++ b/web/client/components/mapcontrols/measure/MeasureResults.jsx @@ -12,8 +12,7 @@ const Draggable = require('react-draggable'); const Dialog = require('../../misc/Dialog'); const Message = require('../../../plugins/locale/Message'); -const ReactIntl = require('react-intl'); -const FormattedNumber = ReactIntl.FormattedNumber; +const NumberFormat = require('../../I18N/Number'); const measureUtils = require('../../../utils/MeasureUtils'); const {isEqual} = require('lodash'); @@ -104,8 +103,8 @@ const MeasureResults = React.createClass({ let decimalFormat = {style: "decimal", minimumIntegerDigits: 1, maximumFractionDigits: 2, minimumFractionDigits: 2}; return (
-

{this.props.lengthLabel}: {this.props.uom.length.label}

-

{this.props.areaLabel}: {this.props.uom.area.label}

+

{this.props.lengthLabel}: {this.props.uom.length.label}

+

{this.props.areaLabel}: {this.props.uom.area.label}

{this.props.bearingLabel}: {measureUtils.getFormattedBearingValue(this.props.measurement.bearing)}

); diff --git a/web/client/components/mapcontrols/measure/__tests__/MeasureComponent-test.jsx b/web/client/components/mapcontrols/measure/__tests__/MeasureComponent-test.jsx index b2aed87e94..9d1c0e17ec 100644 --- a/web/client/components/mapcontrols/measure/__tests__/MeasureComponent-test.jsx +++ b/web/client/components/mapcontrols/measure/__tests__/MeasureComponent-test.jsx @@ -10,8 +10,7 @@ var expect = require('expect'); var React = require('react/addons'); var ReactDOM = require('react-dom'); var MeasureComponent = require('../MeasureComponent'); -var ReactIntl = require('react-intl'); -var FormattedNumber = ReactIntl.FormattedNumber; +var NumberFormat = require('../../../I18N/Number'); describe("test the MeasureComponent", () => { beforeEach((done) => { @@ -233,7 +232,7 @@ describe("test the MeasureComponent", () => { let testDiv = document.createElement("div"); document.body.appendChild(testDiv); - let val = ReactDOM.findDOMNode(ReactDOM.render((km), testDiv)); + let val = ReactDOM.findDOMNode(ReactDOM.render((km), testDiv)); cmp.setProps({ measurement: {len: 10000} }, () => { @@ -243,7 +242,7 @@ describe("test the MeasureComponent", () => { const areaSpan = document.getElementById('measure-area-res'); expect(areaSpan).toExist(); - val = ReactDOM.findDOMNode(ReactDOM.render((km²), testDiv)); + val = ReactDOM.findDOMNode(ReactDOM.render((km²), testDiv)); cmp.setProps({ measurement: {geomType: 'Polygon', area: 1000000} }, () => { diff --git a/web/client/components/mapcontrols/mouseposition/MousePositionLabelDD.jsx b/web/client/components/mapcontrols/mouseposition/MousePositionLabelDD.jsx index 57946943ae..0e0e3797a7 100644 --- a/web/client/components/mapcontrols/mouseposition/MousePositionLabelDD.jsx +++ b/web/client/components/mapcontrols/mouseposition/MousePositionLabelDD.jsx @@ -8,8 +8,7 @@ var React = require('react'); var BootstrapReact = require('react-bootstrap'); var Label = BootstrapReact.Label; -var ReactIntl = require('react-intl'); -var FormattedNumber = ReactIntl.FormattedNumber; +var NumberFormat = require('../../I18N/Number'); var MousePositionLabelDD = React.createClass({ propTypes: { @@ -24,9 +23,9 @@ var MousePositionLabelDD = React.createClass({ return (
); diff --git a/web/client/components/mapcontrols/mouseposition/MousePositionLabelDM.jsx b/web/client/components/mapcontrols/mouseposition/MousePositionLabelDM.jsx index f8b85752f5..ff8bcb1284 100644 --- a/web/client/components/mapcontrols/mouseposition/MousePositionLabelDM.jsx +++ b/web/client/components/mapcontrols/mouseposition/MousePositionLabelDM.jsx @@ -8,8 +8,7 @@ var React = require('react'); var BootstrapReact = require('react-bootstrap'); var Label = BootstrapReact.Label; -var ReactIntl = require('react-intl'); -var FormattedNumber = ReactIntl.FormattedNumber; +var NumberFormat = require('../../I18N/Number'); var MousePositionLabelDM = React.createClass({ propTypes: { @@ -36,12 +35,12 @@ var MousePositionLabelDM = React.createClass({ return (
); } diff --git a/web/client/components/mapcontrols/mouseposition/MousePositionLabelDMS.jsx b/web/client/components/mapcontrols/mouseposition/MousePositionLabelDMS.jsx index e756f70eef..aac90f2ced 100644 --- a/web/client/components/mapcontrols/mouseposition/MousePositionLabelDMS.jsx +++ b/web/client/components/mapcontrols/mouseposition/MousePositionLabelDMS.jsx @@ -8,8 +8,7 @@ var React = require('react'); var BootstrapReact = require('react-bootstrap'); var Label = BootstrapReact.Label; -var ReactIntl = require('react-intl'); -var FormattedNumber = ReactIntl.FormattedNumber; +var NumberFormat = require('../../I18N/Number'); var MousePositionLabelDMS = React.createClass({ propTypes: { @@ -39,14 +38,14 @@ var MousePositionLabelDMS = React.createClass({ return (
); } diff --git a/web/client/components/mapcontrols/mouseposition/MousePositionLabelDMSNW.jsx b/web/client/components/mapcontrols/mouseposition/MousePositionLabelDMSNW.jsx index f6ef54e9f1..e38831dc3b 100644 --- a/web/client/components/mapcontrols/mouseposition/MousePositionLabelDMSNW.jsx +++ b/web/client/components/mapcontrols/mouseposition/MousePositionLabelDMSNW.jsx @@ -8,8 +8,7 @@ var React = require('react'); var BootstrapReact = require('react-bootstrap'); var Label = BootstrapReact.Label; -var ReactIntl = require('react-intl'); -var FormattedNumber = ReactIntl.FormattedNumber; +var NumberFormat = require('../../I18N/Number'); var MousePositionLabelDMS = React.createClass({ propTypes: { @@ -40,12 +39,12 @@ var MousePositionLabelDMS = React.createClass({
); } diff --git a/web/client/components/mapcontrols/mouseposition/MousePositionLabelYX.jsx b/web/client/components/mapcontrols/mouseposition/MousePositionLabelYX.jsx index 16db6adcb9..63d8c570a2 100644 --- a/web/client/components/mapcontrols/mouseposition/MousePositionLabelYX.jsx +++ b/web/client/components/mapcontrols/mouseposition/MousePositionLabelYX.jsx @@ -8,8 +8,7 @@ var React = require('react'); var BootstrapReact = require('react-bootstrap'); var Label = BootstrapReact.Label; -var ReactIntl = require('react-intl'); -var FormattedNumber = ReactIntl.FormattedNumber; +var NumberFormat = require('../../I18N/Number'); var MousePositionLabelYX = React.createClass({ propTypes: { @@ -23,9 +22,9 @@ var MousePositionLabelYX = React.createClass({ return (
); } diff --git a/web/client/product/pages/MapViewer.jsx b/web/client/product/pages/MapViewer.jsx index 9e8aa8966f..fe4c3ab1d0 100644 --- a/web/client/product/pages/MapViewer.jsx +++ b/web/client/product/pages/MapViewer.jsx @@ -20,13 +20,16 @@ const {resetControls} = require('../../actions/controls'); const MapViewer = require('../../containers/MapViewer'); +let oldLocation; + const MapViewerPage = React.createClass({ propTypes: { mode: React.PropTypes.string, params: React.PropTypes.object, loadMapConfig: React.PropTypes.func, reset: React.PropTypes.func, - plugins: React.PropTypes.object + plugins: React.PropTypes.object, + location: React.PropTypes.object }, getDefaultProps() { return { @@ -34,8 +37,8 @@ const MapViewerPage = React.createClass({ }; }, componentWillMount() { - if (this.props.params.mapType && this.props.params.mapId) { - + if (this.props.params.mapType && this.props.params.mapId && oldLocation !== this.props.location) { + oldLocation = this.props.location; if (!ConfigUtils.getDefaults().ignoreMobileCss) { if (this.props.mode === 'mobile') { require('../assets/css/mobile.css'); diff --git a/web/client/utils/LocaleUtils.js b/web/client/utils/LocaleUtils.js index 02bdd0b0c3..52bfc0b864 100644 --- a/web/client/utils/LocaleUtils.js +++ b/web/client/utils/LocaleUtils.js @@ -5,7 +5,16 @@ * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ -var url = require('url'); +const url = require('url'); + +const {addLocaleData} = require('react-intl'); + +const en = require('react-intl/locale-data/en'); +const it = require('react-intl/locale-data/it'); +const fr = require('react-intl/locale-data/fr'); +const de = require('react-intl/locale-data/de'); + +addLocaleData([...en, ...it, ...fr, ...de]); let supportedLocales = { "it": { @@ -26,7 +35,7 @@ let supportedLocales = { } }; -var LocaleUtils = { +const LocaleUtils = { ensureIntl(callback) { require.ensure(['intl', 'intl/locale-data/jsonp/en.js', 'intl/locale-data/jsonp/it.js', 'intl/locale-data/jsonp/fr.js', 'intl/locale-data/jsonp/de.js'], (require) => { global.Intl = require('intl');