Skip to content
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
3 changes: 2 additions & 1 deletion build/docma-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@
"web/client/plugins/BackgroundSelector.jsx",
"web/client/plugins/BurgerMenu.jsx",
"web/client/plugins/CRSSelector.jsx",
"web/client/plugins/CameraPosition.jsx",
"web/client/plugins/Context.jsx",
"web/client/plugins/ContextCreator.jsx",
"web/client/plugins/ContextExport.jsx",
Expand Down Expand Up @@ -346,4 +347,4 @@
]
}
]
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"@mapbox/geojsonhint": "3.3.0",
"@mapbox/togeojson": "0.16.2",
"@mapstore/patcher": "https://github.com/geosolutions-it/Patcher/tarball/master",
"@math.gl/geoid": "^4.1.0",
"@turf/along": "6.5.0",
"@turf/area": "6.5.0",
"@turf/bbox": "4.1.0",
Expand Down
180 changes: 108 additions & 72 deletions web/client/components/mapcontrols/mouseposition/CRSSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,88 +7,124 @@
*/

import PropTypes from 'prop-types';
import React from 'react';
import React, { useRef } from 'react';
import { ControlLabel, FormControl, FormGroup } from 'react-bootstrap';
import ReactDOM from 'react-dom';

import {filterCRSList, getAvailableCRS} from '../../../utils/CoordinatesUtils';
import { filterCRSList, getAvailableCRS } from '../../../utils/CoordinatesUtils';
import FlexBox from '../../layout/FlexBox';

class CRSSelector extends React.Component {
static propTypes = {
id: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.func, PropTypes.string, PropTypes.object]),
availableCRS: PropTypes.object,
filterAllowedCRS: PropTypes.array,
projectionDefs: PropTypes.array,
additionalCRS: PropTypes.object,
crs: PropTypes.string,
enabled: PropTypes.bool,
onCRSChange: PropTypes.func,
useRawInput: PropTypes.bool
};
/**
* CRSSelector allows to select a crs from a combobox or using a raw input.
* @memberof components.mousePosition
* @class
* @prop {string} id the id of the component
* @prop {string|object|function} label the label shown next to the combobox (if editCRS is true)
* @prop {object} availableCRS list of available crs to be used in the combobox
* @prop {string[]} filterAllowedCRS list of allowed crs in the combobox list
* @prop {object[]} projectionDefs list of additional project definitions
* @prop {object} additionalCRS additional crs to be added to the list
* @prop {string} crs the current selected crs
* @prop {boolean} enabled if true shows the component
* @prop {function} onCRSChange callback when a new crs is selected
* @prop {boolean} useRawInput if true shows a raw input instead of a combobox
*/

static defaultProps = {
id: "mapstore-crsselector",
availableCRS: getAvailableCRS(),
crs: null,
onCRSChange: function() {},
enabled: false,
useRawInput: false
};
const CRSSelector = (props) => {
const {
id,
label,
availableCRS,
filterAllowedCRS,
projectionDefs,
additionalCRS,
crs,
enabled,
onCRSChange,
useRawInput
} = props;

render() {
var val;
var label;
var list = [];
let availableCRS = {};
if (Object.keys(this.props.availableCRS).length) {
availableCRS = filterCRSList(this.props.availableCRS, this.props.filterAllowedCRS, this.props.additionalCRS, this.props.projectionDefs );
}
for (let crs in availableCRS) {
if (availableCRS.hasOwnProperty(crs)) {
val = crs;
label = availableCRS[crs].label;
list.push(<option value={val} key={val}>{label}</option>);
}
}
const formRef = useRef(null);

if (this.props.enabled && this.props.useRawInput) {
return (
<select
id={this.props.id}
value={this.props.crs}
onChange={this.launchNewCRSAction}
bsSize="small"
>
{list}
</select>);
} else if (this.props.enabled && !this.props.useRawInput) {
return (
<FormGroup>
<ControlLabel>{this.props.label}</ControlLabel>
<FormControl
componentClass="select"
id={this.props.id}
value={this.props.crs}
onChange={this.launchNewCRSAction}
bsSize="small"
>
{list}
</FormControl>
</FormGroup>);
const launchNewCRSAction = (ev) => {
if (useRawInput) {
onCRSChange(ev.target.value);
} else {
const element = ReactDOM.findDOMNode(formRef.current);
const selectNode = element.getElementsByTagName('select').item(0);
onCRSChange(selectNode.value);
}
};

if (!enabled) {
return null;
}

launchNewCRSAction = (ev) => {
if (this.props.useRawInput) {
this.props.onCRSChange(ev.target.value);
} else {
let element = ReactDOM.findDOMNode(this);
let selectNode = element.getElementsByTagName('select').item(0);
this.props.onCRSChange(selectNode.value);
}
};
}
const filteredCRS = Object.keys(availableCRS).length
? filterCRSList(availableCRS, filterAllowedCRS, additionalCRS, projectionDefs)
: {};

const options = Object.entries(filteredCRS).map(([crsKey, crsValue]) => (
<option value={crsKey} key={crsKey}>{crsValue.label}</option>
));

if (useRawInput) {
return (
<select
id={id}
value={crs}
onChange={launchNewCRSAction}
bsSize="small"
>
{options}
</select>
);
}

return (
<FlexBox
ref={formRef}
component={FormGroup}
centerChildrenVertically
gap="sm"
>
<ControlLabel style={{ margin: 0, fontWeight: 'normal', minWidth: 'max-content' }}>
{label}
</ControlLabel>
<FormControl
componentClass="select"
id={id}
value={crs}
onChange={launchNewCRSAction}
bsSize="small"
style={{ borderRadius: 4 }}
Comment on lines +91 to +100
Copy link
Contributor

Choose a reason for hiding this comment

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

please move all the inline styles inside the less theme. Also let's reduce the width of this selector to 90px
image

>
{options}
</FormControl>
</FlexBox>
);
};

CRSSelector.propTypes = {
id: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.func, PropTypes.string, PropTypes.object]),
availableCRS: PropTypes.object,
filterAllowedCRS: PropTypes.array,
projectionDefs: PropTypes.array,
additionalCRS: PropTypes.object,
crs: PropTypes.string,
enabled: PropTypes.bool,
onCRSChange: PropTypes.func,
useRawInput: PropTypes.bool
};

CRSSelector.defaultProps = {
id: "mapstore-crsselector",
availableCRS: getAvailableCRS(),
crs: null,
onCRSChange: function() {},
enabled: false,
useRawInput: false
};

export default CRSSelector;
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright 2025, 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.
*/

import PropTypes from "prop-types";
import React from "react";
import { ControlLabel, FormControl, FormGroup } from "react-bootstrap";
import FlexBox from "../../layout/FlexBox";
import { getMessageById } from "../../../utils/LocaleUtils";

/**
* HeightTypeSelector allows to select a height type from a combobox.
* @memberof components.mousePosition
* @class
* @prop {string} id the id of the component
* @prop {string|object|function} label the label shown next to the combobox (if editHeight is true)
* @prop {string[]} filterAllowedHeight list of allowed height type in the combobox list. Accepted values are "Ellipsoidal" and "MSL"
* @prop {string} heightType the current selected height type
* @prop {boolean} enabled if true shows the component
* @prop {function} onHeightTypeChange callback when a new height type is selected
*/

const HeightTypeSelector = (props, context) => {
const {
id,
label,
availableHeightTypes,
heightType,
enabled,
onHeightTypeChange
} = props;

if (!enabled) {
return null;
}

const options = availableHeightTypes.map(({ value, labelId }) => (
<option value={value} key={value}>
{getMessageById(context.messages, labelId)}
</option>
));

return (
<FlexBox component={FormGroup} centerChildrenVertically gap="sm">
<ControlLabel style={{ margin: 0, fontWeight: 'normal', minWidth: 'max-content' }}>
{label}
</ControlLabel>
<FormControl
componentClass="select"
id={id}
value={heightType}
onChange={(e) => onHeightTypeChange(e.target.value)}
bsSize="small"
style={{ borderRadius: 4 }}
>
{options}
</FormControl>
Comment on lines +49 to +61
Copy link
Contributor

Choose a reason for hiding this comment

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

all inline styles should be inside a less/css file

</FlexBox>
);
};

HeightTypeSelector.propTypes = {
id: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.func, PropTypes.string, PropTypes.object]),
filterAllowedHeight: PropTypes.array,
heightType: PropTypes.string,
enabled: PropTypes.bool,
onHeightTypeChange: PropTypes.func
};

HeightTypeSelector.contextTypes = {
messages: PropTypes.object
};

HeightTypeSelector.defaultProps = {
id: "mapstore-heightselector",
heightType: null,
onHeightTypeChange: function() {},
enabled: false
};

export default HeightTypeSelector;
Loading
Loading