Skip to content
11 changes: 11 additions & 0 deletions project/standard/templates/configs/pluginsConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,17 @@
"description": "plugins.Permalink.description",
"denyUserSelection": true
},
{
"name": "LayersSelection",
"glyph": "hand-down",
"title": "plugins.LayersSelection.title",
"description": "plugins.LayersSelection.description",
"dependencies": [
"Toolbar",
"BurgerMenu",
"SidebarMenu"
]
},
{
"name": "BackgroundSelector",
"title": "plugins.BackgroundSelector.title",
Expand Down
23 changes: 23 additions & 0 deletions web/client/configs/localConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,29 @@
"containerPosition": "header"
}
},
{
"name": "LayersSelection",
"cfg": {
"highlightOptions": {
"color": "#3388ff",
"dashArray": "",
"fillColor": "#3388ff",
"fillOpacity": 0.2,
"radius": 4,
"weight": 4
},
"queryOptions": {
"maxCount": -1
},
"selectTools": [
"Point",
"Line",
"Circle",
"Rectangle",
"Polygon"
]
}
},
Comment on lines +422 to +444
Copy link
Contributor

Choose a reason for hiding this comment

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

This plugin should be available only in contexts so we should remove it from localConfig.json

{ "name": "SecurityPopup" },
{
"name": "Map",
Expand Down
11 changes: 11 additions & 0 deletions web/client/configs/pluginsConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@
"title": "plugins.Permalink.title",
"description": "plugins.Permalink.description"
},
{
"name": "LayersSelection",
"glyph": "hand-down",
"title": "plugins.LayersSelection.title",
"description": "plugins.LayersSelection.description",
"dependencies": [
"Toolbar",
"BurgerMenu",
"SidebarMenu"
]
},
{
"name": "BackgroundSelector",
"title": "plugins.BackgroundSelector.title",
Expand Down
23 changes: 23 additions & 0 deletions web/client/configs/simple.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,29 @@
"zoomControl": false
}
},
{
"name": "LayersSelection",
"cfg": {
"highlightOptions": {
"color": "#3388ff",
"dashArray": "",
"fillColor": "#3388ff",
"fillOpacity": 0.2,
"radius": 4,
"weight": 4
},
"queryOptions": {
"maxCount": -1
},
"selectTools": [
"Point",
"Line",
"Circle",
"Rectangle",
"Polygon"
]
}
},
Comment on lines +92 to +114
Copy link
Contributor

Choose a reason for hiding this comment

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

This plugin should be available only in contexts so we should remove it from simple.json

{
"name": "Help"
},
Expand Down
96 changes: 96 additions & 0 deletions web/client/plugins/LayersSelection.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { get } from 'lodash';
import { Glyphicon } from 'react-bootstrap';

import { createPlugin } from '../utils/PluginsUtils';
import { layersSelector } from '../selectors/layers';
import { updateNode, addLayer, changeLayerProperties } from '../actions/layers';
import { zoomToExtent } from '../actions/map';
import controls from '../reducers/controls';
import { toggleControl } from '../actions/controls';
import Message from '../components/I18N/Message';

import SelectComponent from './layersSelection/components/LayersSelection';
import epics from './layersSelection/epics/layersSelection';
import select from './layersSelection/reducers/layersSelection';
import { storeConfiguration, cleanSelection, addOrUpdateSelection } from './layersSelection/actions/layersSelection';
import { getSelectSelections, getSelectQueryMaxFeatureCount } from './layersSelection/selectors/layersSelection';

/**
* Select plugin that enables layer feature selection in the map.
* It connects Redux state and actions to the SelectComponent UI.
* Uses selectors to retrieve visibility, layers, selection results, and feature count.
*
* @function
* @returns {Object} A plugin definition object used by the application to render and control the Select tool.
*/
export default createPlugin('Select', {
Copy link
Contributor

Choose a reason for hiding this comment

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

The map viewer remains empty because the configured name here is wrong.
The name should be LayersSelection.

component: connect(
createSelector([
(state) => get(state, 'controls.select.enabled'),
layersSelector,
getSelectSelections,
getSelectQueryMaxFeatureCount
], (isVisible, layers, selections, maxFeatureCount) => ({
isVisible,
layers,
selections,
maxFeatureCount
})),
{
onClose: toggleControl.bind(null, 'select', null),
onUpdateNode: updateNode,
storeConfiguration,
cleanSelection,
addOrUpdateSelection,
zoomToExtent,
addLayer,
changeLayerProperties
}
)(SelectComponent),
options: {
disablePluginIf: "{state('router') && (state('router').endsWith('new') || state('router').includes('newgeostory') || state('router').endsWith('dashboard'))}"
Copy link
Contributor

Choose a reason for hiding this comment

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

This disablePluginIf configuration does not seem related to this plugin. We should remove it

},
reducers: {
...controls,
Copy link
Contributor

Choose a reason for hiding this comment

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

A reducer should not be spread. In this case if we want also to ensure controls reducer is included we should review reducers as:

reducers: {
  controls,
  layersSelection
}

And instead of select I propose to change the name of reducer to layersSelection

select
},
epics: epics,
containers: {
BurgerMenu: {
name: 'select',
position: 1000,
priority: 2,
doNotHide: true,
text: <Message msgId="layersSelection.title"/>,
tooltip: <Message msgId="layersSelection.tooltip"/>,
icon: <Glyphicon glyph="hand-down"/>,
action: toggleControl.bind(null, 'select', null),
toggle: true
},
SidebarMenu: {
name: 'select',
position: 1000,
priority: 1,
doNotHide: true,
text: <Message msgId="layersSelection.title"/>,
tooltip: <Message msgId="layersSelection.tooltip"/>,
icon: <Glyphicon glyph="hand-down"/>,
action: toggleControl.bind(null, 'select', null),
toggle: true
},
Toolbar: {
name: 'select',
alwaysVisible: true,
position: 2,
priority: 0,
doNotHide: true,
tooltip: <Message msgId="layersSelection.title"/>,
icon: <Glyphicon glyph="hand-down"/>,
action: toggleControl.bind(null, 'select', null),
toggle: true
}
}
});
5 changes: 4 additions & 1 deletion web/client/plugins/TOC/components/LayersTree.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const loopGroupCondition = (groupNode, condition) => {
* @prop {string} noFilteredResultsMsgId message id for no result on filter
* @prop {object} config optional configuration available for the nodes
* @prop {boolean} config.sortable activate the possibility to sort nodes
* @prop {component} treeHeader display a header on top of the layer tree
*/
const LayersTree = ({
tree,
Expand All @@ -90,7 +91,8 @@ const LayersTree = ({
nodeToolItems,
nodeContentItems,
singleDefaultGroup = isSingleDefaultGroup(tree),
theme
theme,
treeHeader
}) => {

const containerNode = useRef();
Expand Down Expand Up @@ -151,6 +153,7 @@ const LayersTree = ({
event.preventDefault();
}}
>
{treeHeader ?? null}
{(root || []).map((node, index) => {
return (
<DefaultLayerOrGroup
Expand Down
10 changes: 8 additions & 2 deletions web/client/plugins/TOC/components/TOC.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {
* @prop {boolean} config.layerOptions.hideLegend hide the legend of the layer
* @prop {object} config.layerOptions.legendOptions additional options for WMS legend
* @prop {boolean} config.layerOptions.hideFilter hide the filter button in the layer nodes
* @prop {component} treeHeader display a header on top of the layer tree
*/
export function ControlledTOC({
tree,
Expand All @@ -77,7 +78,8 @@ export function ControlledTOC({
nodeToolItems,
nodeContentItems,
singleDefaultGroup,
theme
theme,
treeHeader
}) {
return (
<LayersTree
Expand All @@ -104,6 +106,7 @@ export function ControlledTOC({
nodeToolItems={nodeToolItems}
nodeContentItems={nodeContentItems}
singleDefaultGroup={singleDefaultGroup}
treeHeader={treeHeader}
/>
);
}
Expand Down Expand Up @@ -140,6 +143,7 @@ export function ControlledTOC({
* @prop {boolean} config.layerOptions.hideLegend hide the legend of the layer
* @prop {object} config.layerOptions.legendOptions additional options for WMS legend
* @prop {boolean} config.layerOptions.hideFilter hide the filter button in the layer nodes
* @prop {component} treeHeader display a header on top of the layer tree
*/
function TOC({
map = { layers: [], groups: [] },
Expand All @@ -154,7 +158,8 @@ function TOC({
singleDefaultGroup,
nodeItems,
theme,
filterText
filterText,
treeHeader
}) {
const { layers } = splitMapAndLayers(map) || {};
const tree = denormalizeGroups(layers.flat || [], layers.groups || []).groups;
Expand Down Expand Up @@ -218,6 +223,7 @@ function TOC({
nodeToolItems={nodeToolItems}
nodeContentItems={nodeContentItems}
singleDefaultGroup={singleDefaultGroup}
treeHeader={treeHeader}
/>
);
}
Expand Down
44 changes: 44 additions & 0 deletions web/client/plugins/layersSelection/actions/layersSelection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
export const SELECT_CLEAN_SELECTION = "SELECT:CLEAN_SELECTION";
export const SELECT_STORE_CFG = "SELECT:STORE_CFG";
export const ADD_OR_UPDATE_SELECTION = "SELECT:ADD_OR_UPDATE_SELECTION";

/**
* Action creator to clean the current selection based on geometry type.
*
* @param {string} geomType - The type of geometry to clean (e.g., "Point", "Polygon").
* @returns {{ type: string, geomType: string }} The action object.
*/
export function cleanSelection(geomType) {
return {
type: SELECT_CLEAN_SELECTION,
geomType
};
}

/**
* Action creator to store configuration settings related to selection.
*
* @param {Object} cfg - Configuration object to store.
* @returns {{ type: string, cfg: Object }} The action object.
*/
export function storeConfiguration(cfg) {
return {
type: SELECT_STORE_CFG,
cfg
};
}

/**
* Action creator to add or update a layer selection with GeoJSON data.
*
* @param {string} layer - The name or ID of the layer.
* @param {Object} geoJsonData - The GeoJSON data representing the selection.
* @returns {{ type: string, layer: string, geoJsonData: Object }} The action object.
*/
export function addOrUpdateSelection(layer, geoJsonData) {
return {
type: ADD_OR_UPDATE_SELECTION,
layer,
geoJsonData
};
}
40 changes: 40 additions & 0 deletions web/client/plugins/layersSelection/assets/select.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.ms-resizable-modal > .modal-content.select-dialog {
top: 0vh;
right: -100vw;
}

.select-content * .ms-node-title {
font-weight: bold;
}

.select-content * .ms-node-header-info > .ms-node-header-addons:nth-child(3) {
flex: 1 ;
justify-content: space-between;
}

.features-count-displayer{
display: flex;
}

.title-container {
display: flex;
}

.title-icon {
height: 100%;
width: auto;
margin-right: 0.5em;
}

.title-title {
flex-grow: 1;
text-align: center;
}

.tree-header {
background-color: #E9EDF4;
}

.features-count {
font-weight: bold;
}
Loading