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

FeatureInfo coordinates in aeronautical format #3676

Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 2 additions & 5 deletions web/client/components/I18N/Number.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
const PropTypes = require('prop-types');
const React = require('react');
const {isNil} = require('lodash');
const {FormattedNumber} = require('react-intl');
class NumberFormat extends React.Component {
static propTypes = {
Expand All @@ -18,12 +19,8 @@ class NumberFormat extends React.Component {
intl: PropTypes.object
};

static defaultProps = {
value: new Date()
};

render() {
return this.context.intl ? <FormattedNumber value={this.props.value} {...this.props.numberParams}/> : <span>{this.props.value && this.props.value.toString() || ''}</span>;
return this.context.intl ? <FormattedNumber value={this.props.value} {...this.props.numberParams} /> : <span>{!isNil(this.props.value) && !isNaN(this.props.value) && this.props.value.toString && this.props.value.toString() || ''}</span>;
}
}

Expand Down
22 changes: 3 additions & 19 deletions web/client/components/data/identify/GeocodeViewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const React = require('react');
const ResizableModal = require('../../misc/ResizableModal');
const Portal = require('../../misc/Portal');
const Message = require('../../I18N/Message');
const {Glyphicon, Row, Col} = require('react-bootstrap');
const {Glyphicon} = require('react-bootstrap');

/**
* Component for rendering lat and lng of the current selected point
Expand All @@ -23,23 +23,8 @@ const {Glyphicon, Row, Col} = require('react-bootstrap');
* @prop {node} revGeocodeDisplayName text/info displayed on modal
*/

module.exports = ({latlng, enableRevGeocode, hideRevGeocode = () => {}, showModalReverse, revGeocodeDisplayName, showCoordinateEditor = false}) => {

let lngCorrected = null;
if (latlng) {
/* lngCorrected is the converted longitude in order to have the value between
the range (-180 / +180).*/
lngCorrected = latlng && Math.round(latlng.lng * 100000) / 100000;
/* the following formula apply the converion */
lngCorrected = lngCorrected - 360 * Math.floor(lngCorrected / 360 + 0.5);
}

return enableRevGeocode && latlng && lngCorrected ? (
<Row key="ms-geocode-coords" className="ms-geoscode-viewer text-center" style={{display: showCoordinateEditor ? "none" : "block"}}>
{!showCoordinateEditor &&
(<Col xs={12}>
<div className="ms-geocode-coords">{latlng ? 'Lat: ' + (Math.round(latlng.lat * 100000) / 100000) + '- Long: ' + lngCorrected : null}</div>
</Col>)}
module.exports = ({latlng, enableRevGeocode, hideRevGeocode = () => {}, showModalReverse, revGeocodeDisplayName}) => {
return enableRevGeocode && latlng ? (
<Portal>
<ResizableModal
fade
Expand All @@ -59,6 +44,5 @@ module.exports = ({latlng, enableRevGeocode, hideRevGeocode = () => {}, showModa
</div>
</ResizableModal>
</Portal>
</Row>
) : null;
};
19 changes: 10 additions & 9 deletions web/client/components/data/identify/IdentifyContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const DockablePanel = require('../../misc/panels/DockablePanel');
const GeocodeViewer = require('./GeocodeViewer');
const ResizableModal = require('../../misc/ResizableModal');
const Portal = require('../../misc/Portal');

const Coordinate = require('./coordinates/Coordinate');
/**
* Component for rendering Identify Container inside a Dockable container
* @memberof components.data.identify
Expand All @@ -26,9 +26,6 @@ const Portal = require('../../misc/Portal');
* @prop {function} getToolButtons must return an array of object representing the toolbar buttons, eg (props) => [{ glyph: 'info-sign', tooltip: 'hello!'}]
* @prop {function} getNavigationButtons must return an array of navigation buttons, eg (props) => [{ glyph: 'info-sign', tooltip: 'hello!'}]
*/

const IdentifyEditor = require('../../../plugins/identify/IdentifyEditor');

module.exports = props => {
const {
enabled,
Expand Down Expand Up @@ -98,15 +95,19 @@ module.exports = props => {
style={dockStyle}
showFullscreen={showFullscreen}
zIndex={zIndex}
header={[enabledCoordEditorButton && showCoordinateEditor &&
<IdentifyEditor
header={[
<Coordinate
key="coordinate-editor"
removeVisible={false}
formatCoord={formatCoord}
coordinate={point.latlng ? {lat: point.latlng.lat, lon: lngCorrected } : {lat: "", lon: ""}}
enabledCoordEditorButton={enabledCoordEditorButton}
onChange={onChangeClickPoint}
onChangeFormat={onChangeFormat}
/> || null,
edit={showCoordinateEditor}
coordinate={{
lat: latlng && latlng.lat,
lon: lngCorrected
}}
/>,
<GeocodeViewer latlng={latlng} revGeocodeDisplayName={revGeocodeDisplayName} {...props}/>,
<Row key="button-row" className="text-center" style={{position: 'relative'}}>
<Col key="tools" xs={12}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,55 +24,6 @@ describe('GeocodeViewer', () => {
setTimeout(done);
});

it('creates the GeocodeViewer component with defaults', () => {
ReactDOM.render(
<GeocodeViewer />,
document.getElementById("container")
);
const geocodeViewer = document.getElementsByClassName('ms-geoscode-viewer');
expect(geocodeViewer.length).toBe(0);
});

it('creates the GeocodeViewer no lat lng', () => {
ReactDOM.render(
<GeocodeViewer enableRevGeocode/>,
document.getElementById("container")
);
const geocodeViewer = document.getElementsByClassName('ms-geoscode-viewer');
expect(geocodeViewer.length).toBe(0);
});

it('creates the GeocodeViewer enable, showCoordinateEditor=false', () => {
ReactDOM.render(
<GeocodeViewer
enableRevGeocode
showCoordinateEditor={false}
latlng={{lat: 40, lng: 10}}
lngCorrected={10}/>,
document.getElementById("container")
);
const geocodeViewer = document.getElementsByClassName('ms-geoscode-viewer');
expect(geocodeViewer.length).toBe(1);
const coords = document.getElementsByClassName('ms-geocode-coords')[0];
expect(coords.innerHTML.indexOf('Lat:') !== -1).toBe(true);
expect(coords.innerHTML.indexOf('Long:') !== -1).toBe(true);
});

it('creates the GeocodeViewer enable, showCoordinateEditor=true', () => {
ReactDOM.render(
<GeocodeViewer
enableRevGeocode
showCoordinateEditor
latlng={{lat: 40, lng: 10}}
lngCorrected={10}/>,
document.getElementById("container")
);
const geocodeViewer = document.getElementsByClassName('ms-geoscode-viewer');
expect(geocodeViewer.length).toBe(1);
const coords = document.getElementsByClassName('ms-geocode-coords')[0];
expect(coords).toNotExist();
});

it('creates the GeocodeViewer hide', () => {
ReactDOM.render(
<GeocodeViewer
Expand Down
40 changes: 40 additions & 0 deletions web/client/components/data/identify/coordinates/Coordinate.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2019, 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 Editor = require('./Editor');
const Viewer = require('./Viewer');

/**
* Visualize the coordinate editor or viewer for the point clicked
* @prop {object} coordinate coordinate in format `lat` `lon`
* @prop {string} formatCoord `decimal` or `aeronautical`
* @prop {boolean} edit true to visualize in edit mode
* @prop {function} onChange handler to change the point coordinates. 2st argument is the key `lat` or `lon`, 2nd argument is the new numeric value.
* @prop {function} onChangeFormat handler to change the formatCoord. 1st argument is the formatCoord string.
*/
module.exports = ({
coordinate = {},
formatCoord,
edit,
onChange = () => {},
onChangeFormat = () => {}
}) =>
edit ?
(<Editor
removeVisible={false}
formatCoord={formatCoord}
coordinate={coordinate || {lat: "", lon: ""}}
onChange={onChange}
onChangeFormat={onChangeFormat}
/>)
: (<Viewer
className="text-center"
formatCoord={formatCoord}
coordinate={coordinate || { lat: "", lon: "" }}
/>);

Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
*/

const React = require('react');
const CoordinatesRow = require('../../components/misc/coordinateeditors/CoordinatesRow');
const CoordinatesRow = require('../../../misc/coordinateeditors/CoordinatesRow');

const IdentifyEditor = (props) => (
const Editor = (props) => (
<CoordinatesRow
key="IdentifyEditor"
format={props.formatCoord || "decimal"}
Expand All @@ -28,12 +28,12 @@ const IdentifyEditor = (props) => (
}}
key={"GFI row coord editor"}
component={props.coordinate || {}}
customClassName="GFI-coord-editor"
customClassName="coord-editor"
isDraggable={false}
showDraggable={false}
formatVisible
showLabels
removeVisible={false}
/>);

module.exports = IdentifyEditor;
module.exports = Editor;
59 changes: 59 additions & 0 deletions web/client/components/data/identify/coordinates/Viewer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2019, 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 { Row, Col } = require('react-bootstrap');
const {isNil} = require('lodash');
const NumberFormat = require('../../../I18N/Number');
const decimalToAeronautical = require('../../../misc/coordinateeditors/enhancers/decimalToAeronautical');

/**
* Format 1 decimal coordinate into degrees, minutes, seconds, direction format.
* @prop {value} value to format
*
*/
const AeronauticalCoordinate = decimalToAeronautical(({
degrees = 0,
minutes = 0,
seconds = 0,
direction,
integerFormat,
decimalFormat
}) => (<span className="coordinate-dms">
<NumberFormat key="latD" numberParams={integerFormat} value={degrees} />
<span>°&nbsp;</span><NumberFormat key="latM" numberParams={integerFormat} value={minutes} /><span>&apos;&nbsp;</span>
<NumberFormat key="latS" numberParams={decimalFormat} value={seconds} /><span>&apos;&apos;&nbsp;</span>
&nbsp;<span>{direction}</span>
</span>));

/**
* Display coordinates in "decimal" or "aeronautical" formats.
* TODO: maybe is better move formatting components in some common place.
*/
module.exports = ({
integerFormat = {style: "decimal", minimumIntegerDigits: 2, maximumFractionDigits: 0},
decimalFormat = {style: "decimal", minimumIntegerDigits: 2, maximumFractionDigits: 4, minimumFractionDigits: 4},
coordinate = {},
formatCoord = "decimal",
className
}) =>
(<Row className={className}>
{
(<Col xs={12}>
{(isNil(coordinate.lat) || isNil(coordinate.lon))
? null
: formatCoord === "decimal"
? <div className="ms-coordinates-decimal">Lat: <NumberFormat value={(Math.round(coordinate.lat * 100000) / 100000)} /> - Long: <NumberFormat value={coordinate.lon} /></div>
: <div className="ms-coordinates-aeronautical">
<span>Lat: <AeronauticalCoordinate integerFormat={integerFormat} decimalFormat={decimalFormat} value={coordinate.lat} /></span>
<span> - </span>
<span> Long: <AeronauticalCoordinate coordinate="lon" integerFormat={integerFormat} decimalFormat={decimalFormat} value={coordinate.lon} /></span>
</div>
}
</Col>)}
</Row>);

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2019, 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 ReactDOM = require('react-dom');
const ReactTestUtils = require('react-dom/test-utils');

const expect = require('expect');
const Coordinate = require('../Coordinate');
describe('Identify Coordinate 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('Coordinate rendering with defaults', () => {
ReactDOM.render(<Coordinate />, document.getElementById("container"));
const container = document.getElementById('container');
const el = container.querySelector('.text-center');
expect(el).toExist();
});
it('Coordinate rendering with content', () => {
ReactDOM.render(<Coordinate coordinate={{lat: 1, lon: 1}} />, document.getElementById("container"));
const container = document.getElementById('container');
const el = container.querySelector('.ms-coordinates-decimal');
expect(el).toExist();
});
it('Coordinate edit mode', () => {
ReactDOM.render(<Coordinate edit coordinate={{ lat: 1, lon: 1 }} />, document.getElementById("container"));
const container = document.getElementById('container');
const el = container.querySelector('.coord-editor');
expect(el).toExist();
});
it('Test Editor onChangeFormat correctly passed', () => {
const actions = {
onChangeFormat: () => { }
};
const spyonChange = expect.spyOn(actions, 'onChangeFormat');
ReactDOM.render(<Coordinate edit onChangeFormat={actions.onChangeFormat} />, document.getElementById("container"));
ReactTestUtils.Simulate.click(document.querySelector('a > span')); // <-- trigger event callback
expect(spyonChange).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const React = require('react');
const ReactDOM = require('react-dom');
const ReactTestUtils = require('react-dom/test-utils');
const expect = require('expect');
const Editor = require('../Editor');
describe('Identify Coordinate Editor 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('Editor rendering with defaults', () => {
ReactDOM.render(<Editor />, document.getElementById("container"));
const container = document.getElementById('container');
const el = container.querySelector('.coord-editor');
expect(el).toExist();
});
it('Test Editor onChange correctly passed and argument mapping', () => {
const actions = {
onChange: () => {}
};
const spyonChange = expect.spyOn(actions, 'onChange');
ReactDOM.render(<Editor onChange={actions.onChange} />, document.getElementById("container"));
ReactTestUtils.Simulate.change(document.querySelector('input'), { target: { value: 20} }); // <-- trigger event callback
expect(spyonChange).toHaveBeenCalled();
expect(spyonChange.calls[0].arguments[0]).toBe('lat');
expect(spyonChange.calls[0].arguments[1]).toBe(20);
});
it('Test Editor onChangeFormat correctly passed', () => {
const actions = {
onChangeFormat: () => { }
};
const spyonChange = expect.spyOn(actions, 'onChangeFormat');
ReactDOM.render(<Editor onChangeFormat={actions.onChangeFormat} />, document.getElementById("container"));
ReactTestUtils.Simulate.click(document.querySelector('a > span')); // <-- trigger event callback
expect(spyonChange).toHaveBeenCalled();
});
});
Loading