From 8deccc216c699cbf281074a3a5b60c90b66636f8 Mon Sep 17 00:00:00 2001 From: Matteo V Date: Wed, 20 Sep 2023 10:52:44 +0200 Subject: [PATCH] fix #9367 review of geo processing tool (#9351) --- ...ingTools-test.js => geoProcessing-test.js} | 17 +- ...geoProcessingTools.js => geoProcessing.js} | 99 +-- web/client/actions/layers.js | 6 +- web/client/configs/pluginsConfig.json | 8 +- ...ingTools-test.js => geoProcessing-test.js} | 144 +++- ...geoProcessingTools.js => geoProcessing.js} | 210 +++-- ...oProcessingTools.jsx => GeoProcessing.jsx} | 30 +- web/client/plugins/GeoProcessing/Buffer.jsx | 288 +++++++ .../plugins/GeoProcessing/Intersection.jsx | 383 +++++++++ .../IntersectionLayer.jsx | 33 +- web/client/plugins/GeoProcessing/Main.jsx | 112 +++ .../Panel.jsx | 18 +- .../SourceLayer.jsx | 37 +- web/client/plugins/GeoProcessing/processes.js | 142 ++++ .../plugins/GeoProcessingTools/Buffer.jsx | 183 ---- .../GeoProcessingTools/Intersection.jsx | 222 ----- .../plugins/GeoProcessingTools/Main.jsx | 264 ------ web/client/product/plugins.js | 2 +- ...ingTools-test.js => geoProcessing-test.js} | 90 +- ...geoProcessingTools.js => geoProcessing.js} | 56 +- web/client/reducers/layers.js | 27 +- web/client/reducers/maplayout.js | 2 +- .../selectors/__tests__/controls-test.js | 8 +- ...ingTools-test.js => geoProcessing-test.js} | 156 ++-- web/client/selectors/controls.js | 2 +- ...geoProcessingTools.js => geoProcessing.js} | 78 +- web/client/themes/default/icons.less | 786 +++++++++--------- web/client/themes/default/icons/icons.eot | Bin 85676 -> 86456 bytes web/client/themes/default/icons/icons.svg | 398 ++++----- web/client/themes/default/icons/icons.ttf | Bin 85520 -> 86300 bytes web/client/themes/default/icons/icons.woff | Bin 48156 -> 48644 bytes web/client/themes/default/icons/icons.woff2 | Bin 39432 -> 39816 bytes .../default/less/geo-processing-tools.less | 4 +- .../themes/default/svg/globe-settings.svg | 49 ++ web/client/translations/data.de-DE.json | 53 +- web/client/translations/data.en-US.json | 41 +- web/client/translations/data.es-ES.json | 39 +- web/client/translations/data.fr-FR.json | 39 +- web/client/translations/data.it-IT.json | 37 +- ...ingToolsUtils.js => GeoProcessingUtils.js} | 0 ...ils-test.js => GeoProcessingUtils-test.js} | 4 +- 41 files changed, 2322 insertions(+), 1745 deletions(-) rename web/client/actions/__tests__/{geoProcessingTools-test.js => geoProcessing-test.js} (96%) rename web/client/actions/{geoProcessingTools.js => geoProcessing.js} (85%) rename web/client/epics/__tests__/{geoProcessingTools-test.js => geoProcessing-test.js} (87%) rename web/client/epics/{geoProcessingTools.js => geoProcessing.js} (79%) rename web/client/plugins/{GeoProcessingTools.jsx => GeoProcessing.jsx} (75%) create mode 100644 web/client/plugins/GeoProcessing/Buffer.jsx create mode 100644 web/client/plugins/GeoProcessing/Intersection.jsx rename web/client/plugins/{GeoProcessingTools => GeoProcessing}/IntersectionLayer.jsx (88%) create mode 100644 web/client/plugins/GeoProcessing/Main.jsx rename web/client/plugins/{GeoProcessingTools => GeoProcessing}/Panel.jsx (79%) rename web/client/plugins/{GeoProcessingTools => GeoProcessing}/SourceLayer.jsx (85%) create mode 100644 web/client/plugins/GeoProcessing/processes.js delete mode 100644 web/client/plugins/GeoProcessingTools/Buffer.jsx delete mode 100644 web/client/plugins/GeoProcessingTools/Intersection.jsx delete mode 100644 web/client/plugins/GeoProcessingTools/Main.jsx rename web/client/reducers/__tests__/{geoProcessingTools-test.js => geoProcessing-test.js} (84%) rename web/client/reducers/{geoProcessingTools.js => geoProcessing.js} (88%) rename web/client/selectors/__tests__/{geoProcessingTools-test.js => geoProcessing-test.js} (69%) rename web/client/selectors/{geoProcessingTools.js => geoProcessing.js} (60%) mode change 100755 => 100644 web/client/themes/default/icons/icons.eot mode change 100755 => 100644 web/client/themes/default/icons/icons.svg mode change 100755 => 100644 web/client/themes/default/icons/icons.ttf mode change 100755 => 100644 web/client/themes/default/icons/icons.woff create mode 100644 web/client/themes/default/svg/globe-settings.svg rename web/client/utils/{GeoProcessingToolsUtils.js => GeoProcessingUtils.js} (100%) rename web/client/utils/__tests__/{GeoProcessingToolsUtils-test.js => GeoProcessingUtils-test.js} (94%) diff --git a/web/client/actions/__tests__/geoProcessingTools-test.js b/web/client/actions/__tests__/geoProcessing-test.js similarity index 96% rename from web/client/actions/__tests__/geoProcessingTools-test.js rename to web/client/actions/__tests__/geoProcessing-test.js index 2dba088888..cde8b35cde 100644 --- a/web/client/actions/__tests__/geoProcessingTools-test.js +++ b/web/client/actions/__tests__/geoProcessing-test.js @@ -18,8 +18,7 @@ import { increaseBufferedCounter, INCREASE_BUFFERED_COUNTER, increaseIntersectedCounter, INCREASE_INTERSECT_COUNTER, runningProcess, RUNNING_PROCESS, - runBufferProcess, RUN_BUFFER_PROCESS, - runIntersectionProcess, RUN_INTERSECTION_PROCESS, + runProcess, RUN_PROCESS, setBufferDistance, SET_BUFFER_DISTANCE, setBufferDistanceUom, SET_BUFFER_DISTANCE_UOM, setBufferQuadrantSegments, SET_BUFFER_QUADRANT_SEGMENTS, @@ -43,7 +42,7 @@ import { setIntersectionAreasEnabled, SET_INTERSECTION_AREAS_ENABLED, setSelectedLayerType, SET_SELECTED_LAYER_TYPE, toggleHighlightLayers, TOGGLE_HIGHLIGHT_LAYERS -} from '../geoProcessingTools'; +} from '../geoProcessing'; describe('Test Geo Processing Tools related actions', () => { it('checkWPSAvailability', () => { @@ -121,15 +120,11 @@ describe('Test Geo Processing Tools related actions', () => { }); }); it('runBufferProcess', () => { - const action = runBufferProcess(); + const process = "test"; + const action = runProcess(process); expect(action).toEqual({ - type: RUN_BUFFER_PROCESS - }); - }); - it('runIntersectionProcess', () => { - const action = runIntersectionProcess(); - expect(action).toEqual({ - type: RUN_INTERSECTION_PROCESS + type: RUN_PROCESS, + process }); }); it('setBufferDistance', () => { diff --git a/web/client/actions/geoProcessingTools.js b/web/client/actions/geoProcessing.js similarity index 85% rename from web/client/actions/geoProcessingTools.js rename to web/client/actions/geoProcessing.js index 7b25e83b47..e54541be34 100644 --- a/web/client/actions/geoProcessingTools.js +++ b/web/client/actions/geoProcessing.js @@ -8,7 +8,11 @@ */ export const GPT_TOOL_BUFFER = "buffer"; export const GPT_TOOL_INTERSECTION = "intersection"; -export const GPT_CONTROL_NAME = "GeoProcessingTools"; +export const GPT_CONTROL_NAME = "GeoProcessing"; +export const GPT_SOURCE_HIGHLIGHT_ID = "gpt-layer"; +export const GPT_INTERSECTION_HIGHLIGHT_ID = "gpt-layer-intersection"; +export const GPT_INTERSECTION_GROUP_ID = "intersection.layer"; +export const GPT_BUFFER_GROUP_ID = "buffered.layer"; export const CHECK_WPS_AVAILABILITY = "GPT:CHECK_WPS_AVAILABILITY"; export const CHECKING_WPS_AVAILABILITY = "GPT:CHECKING_WPS_AVAILABILITY"; @@ -20,8 +24,8 @@ export const INIT_PLUGIN = "GPT:INIT_PLUGIN"; export const INCREASE_BUFFERED_COUNTER = "GPT:INCREASE_BUFFERED_COUNTER"; export const INCREASE_INTERSECT_COUNTER = "GPT:INCREASE_INTERSECT_COUNTER"; export const RUNNING_PROCESS = "GPT:RUNNING_PROCESS"; -export const RUN_BUFFER_PROCESS = "GPT:RUN_BUFFER_PROCESS"; -export const RUN_INTERSECTION_PROCESS = "GPT:RUN_INTERSECTION_PROCESS"; +export const RESET = "GPT:RESET"; +export const RUN_PROCESS = "GPT:RUN_PROCESS"; export const SET_BUFFER_DISTANCE = "GPT:SET_BUFFER_DISTANCE"; export const SET_BUFFER_DISTANCE_UOM = "GPT:SET_BUFFER_DISTANCE_UOM"; export const SET_BUFFER_QUADRANT_SEGMENTS = "GPT:SET_BUFFER_QUADRANT_SEGMENTS"; @@ -49,12 +53,12 @@ export const TOGGLE_HIGHLIGHT_LAYERS = "GPT:TOGGLE_HIGHLIGHT_LAYERS"; /** * Actions for Geo Processing Tools * @memberof actions - * @name GeoProcessingTools + * @name GeoProcessing */ /** * action for checking WPS availability - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} layerId the layer id * @param {string} source can be "source" or "intersection" */ @@ -66,7 +70,7 @@ export const checkWPSAvailability = (layerId, source) => ({ /** * action for setting the WPS availability - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {boolean} status the status */ export const checkingWPSAvailability = (status) => ({ @@ -75,7 +79,7 @@ export const checkingWPSAvailability = (status) => ({ }); /** * action for setting the WPS availability - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {boolean} status the status */ export const checkingIntersectionWPSAvailability = (status) => ({ @@ -84,7 +88,7 @@ export const checkingIntersectionWPSAvailability = (status) => ({ }); /** * action for setting the error loading the describe feature type - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {boolean} layerId the layerId */ export const errorLoadingDFT = (layerId) => ({ @@ -93,7 +97,7 @@ export const errorLoadingDFT = (layerId) => ({ }); /** * action for triggering the get feature request given a source - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} layerId the layer id * @param {string} source can be "source" or "intersection" */ @@ -105,7 +109,7 @@ export const getFeatures = (layerId, source, page = 0) => ({ }); /** * action for initializing config of the plugin - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing */ export const initPlugin = (cfg) => ({ type: INIT_PLUGIN, @@ -113,44 +117,45 @@ export const initPlugin = (cfg) => ({ }); /** * action for triggering the increase of the number of buffered layers - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing */ export const increaseBufferedCounter = () => ({ type: INCREASE_BUFFERED_COUNTER }); /** * action for triggering the increase of the number of intersected layers - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing */ export const increaseIntersectedCounter = () => ({ type: INCREASE_INTERSECT_COUNTER }); +/** + * action that clears current status + * @memberof actions.geoProcessing + */ +export const reset = () => ({ + type: RESET +}); /** * action for changing the flag of the process running * @param {boolean} status the status - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing */ export const runningProcess = (status) => ({ type: RUNNING_PROCESS, status }); /** - * action for executing buffer process - * @memberof actions.geoProcessingTools - */ -export const runBufferProcess = () => ({ - type: RUN_BUFFER_PROCESS -}); -/** - * action for executing intersection process - * @memberof actions.geoProcessingTools + * action for executing any process + * @memberof actions.geoProcessing */ -export const runIntersectionProcess = () => ({ - type: RUN_INTERSECTION_PROCESS +export const runProcess = (process) => ({ + type: RUN_PROCESS, + process }); /** * action for triggering the set of the distance for the buffering - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {number} distance the distance in uom */ export const setBufferDistance = (distance) => ({ @@ -159,7 +164,7 @@ export const setBufferDistance = (distance) => ({ }); /** * action for triggering the set of the uom of the distance for the buffering - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} uom the distance in uom */ export const setBufferDistanceUom = (uom) => ({ @@ -168,7 +173,7 @@ export const setBufferDistanceUom = (uom) => ({ }); /** * action for triggering the set of the quadrantSegments for the buffering - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {number} quadrantSegments the quadrantSegments */ export const setBufferQuadrantSegments = (quadrantSegments) => ({ @@ -177,7 +182,7 @@ export const setBufferQuadrantSegments = (quadrantSegments) => ({ }); /** * action for triggering the set of the capStyle for the buffering - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} capStyle the capStyle */ export const setBufferCapStyle = (capStyle) => ({ @@ -187,7 +192,7 @@ export const setBufferCapStyle = (capStyle) => ({ /** * action for triggering the set feature request given a source - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} layerId the layer id * @param {string} source can be "source" or "intersection" * @param {object[]|object} data list of features or error @@ -201,7 +206,7 @@ export const setFeatures = (layerId, source, data, nextPage) => ({ }); /** * action for the loading flag of the features - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} status the status */ export const setFeatureSourceLoading = (status) => ({ @@ -210,7 +215,7 @@ export const setFeatureSourceLoading = (status) => ({ }); /** * action for the loading flag of the features of intersection layer - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} status the status */ export const setFeatureIntersectionLoading = (status) => ({ @@ -219,7 +224,7 @@ export const setFeatureIntersectionLoading = (status) => ({ }); /** * action for setting the layer to be invalid - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} layerId the layer id * @param {string} status the status */ @@ -231,7 +236,7 @@ export const setInvalidLayer = (layerId, status) => ({ /** * action that sets if needed WPS are available (geo:Buffer and gs:IntersectionFeatureCollection, gs:CollectGeometries) - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} layerId the layer id * @param {boolean} status the status * @param {string} source the source @@ -244,7 +249,7 @@ export const setWPSAvailability = (layerId, status, source) => ({ }); /** * action that sets the tool to use "buffer", or "intersection" - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} tool the tool id */ export const setSelectedTool = (tool) => ({ @@ -253,7 +258,7 @@ export const setSelectedTool = (tool) => ({ }); /** * action that sets the source layer id - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} layerId the layer id */ export const setSourceLayerId = (layerId) => ({ @@ -262,7 +267,7 @@ export const setSourceLayerId = (layerId) => ({ }); /** * action that sets the source feature id - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} featureId the feature id */ export const setSourceFeatureId = (featureId) => ({ @@ -271,7 +276,7 @@ export const setSourceFeatureId = (featureId) => ({ }); /** * action that sets the source feature - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} feature the feature obj with geom inside */ export const setSourceFeature = (feature) => ({ @@ -280,7 +285,7 @@ export const setSourceFeature = (feature) => ({ }); /** * action that sets the intersection layer id - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} layerId the layer id */ export const setIntersectionLayerId = (layerId) => ({ @@ -289,7 +294,7 @@ export const setIntersectionLayerId = (layerId) => ({ }); /** * action that sets the intersection feature id - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} featureId the layer id */ export const setIntersectionFeatureId = (featureId) => ({ @@ -298,7 +303,7 @@ export const setIntersectionFeatureId = (featureId) => ({ }); /** * action that sets the intersection feature - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} feature the feature obj with geom inside */ export const setIntersectionFeature = (feature) => ({ @@ -307,7 +312,7 @@ export const setIntersectionFeature = (feature) => ({ }); /** * action that sets the intersection firstAttributeToRetain - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} firstAttributeToRetain First feature collection attribute to include */ export const setIntersectionFirstAttribute = (firstAttributeToRetain) => ({ @@ -316,7 +321,7 @@ export const setIntersectionFirstAttribute = (firstAttributeToRetain) => ({ }); /** * action that sets the intersection secondAttributeToRetain - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} secondAttributeToRetain Second feature collection attribute to include */ export const setIntersectionSecondAttribute = (secondAttributeToRetain) => ({ @@ -325,7 +330,7 @@ export const setIntersectionSecondAttribute = (secondAttributeToRetain) => ({ }); /** * action that sets the intersectionMode - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} intersectionMode Specifies geometry computed for intersecting features. INTERSECTION (default) computes the spatial intersection of the inputs. FIRST copies geometry A. SECOND copies geometry B. */ export const setIntersectionMode = (intersectionMode) => ({ @@ -334,7 +339,7 @@ export const setIntersectionMode = (intersectionMode) => ({ }); /** * action that sets the percentageEnabled - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {boolean} percentagesEnabled Indicates whether to output feature area percentages (attributes percentageA and percentageB) */ export const setIntersectionPercentagesEnabled = (percentagesEnabled) => ({ @@ -344,7 +349,7 @@ export const setIntersectionPercentagesEnabled = (percentagesEnabled) => ({ /** * action that sets the areasEnabled - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {boolean} areasEnabled Indicates whether to output feature areas (attributes areaA and areaB) */ export const setIntersectionAreasEnabled = (areasEnabled) => ({ @@ -353,7 +358,7 @@ export const setIntersectionAreasEnabled = (areasEnabled) => ({ }); /** * action that sets the owner were the selection of the features must be done - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing * @param {string} source */ export const setSelectedLayerType = (source) => ({ @@ -362,7 +367,7 @@ export const setSelectedLayerType = (source) => ({ }); /** * action that toggles on / off highlight layers - * @memberof actions.geoProcessingTools + * @memberof actions.geoProcessing */ export const toggleHighlightLayers = () => ({ type: TOGGLE_HIGHLIGHT_LAYERS diff --git a/web/client/actions/layers.js b/web/client/actions/layers.js index f2133d7270..0d56ab5ca8 100644 --- a/web/client/actions/layers.js +++ b/web/client/actions/layers.js @@ -190,13 +190,15 @@ export function addLayer(layer, foreground = true) { * @param {string} group title of group * @param {string} parent parent group described with dot notation (eg parent.nested ) * @param {object} options Additional properties to assign to the group. They will override the default ones. + * @param {boolean} asFirst added at the top of the groups */ -export function addGroup(group, parent, options) { +export function addGroup(group, parent, options, asFirst = false) { return { type: ADD_GROUP, group, parent, - options + options, + asFirst }; } diff --git a/web/client/configs/pluginsConfig.json b/web/client/configs/pluginsConfig.json index b6a52b9a8f..30aef1aa0a 100644 --- a/web/client/configs/pluginsConfig.json +++ b/web/client/configs/pluginsConfig.json @@ -650,10 +650,10 @@ ] }, { - "name": "GeoProcessingTools", - "glyph": "star", - "title": "plugins.GeoProcessingTools.title", - "description": "plugins.GeoProcessingTools.description", + "name": "GeoProcessing", + "glyph": "globe-settings", + "title": "plugins.GeoProcessing.title", + "description": "plugins.GeoProcessing.description", "dependencies": [ "SidebarMenu" ] diff --git a/web/client/epics/__tests__/geoProcessingTools-test.js b/web/client/epics/__tests__/geoProcessing-test.js similarity index 87% rename from web/client/epics/__tests__/geoProcessingTools-test.js rename to web/client/epics/__tests__/geoProcessing-test.js index 01323c3d4d..1dd2b1d16c 100644 --- a/web/client/epics/__tests__/geoProcessingTools-test.js +++ b/web/client/epics/__tests__/geoProcessing-test.js @@ -20,12 +20,15 @@ import { resetSourceHighlightGPTEpic, resetIntersectHighlightGPTEpic, runIntersectProcessGPTEpic, + toggleHighlightLayersOnOpenCloseGPTEpic, toggleHighlightLayersGPTEpic, disableIdentifyGPTEpic, clickToSelectFeatureGPTEpic, LPlongitudinalMapLayoutGPTEpic -} from '../geoProcessingTools'; +} from '../geoProcessing'; import { + GPT_TOOL_INTERSECTION, + GPT_TOOL_BUFFER, GPT_CONTROL_NAME, SET_FEATURES, checkWPSAvailability, @@ -46,11 +49,10 @@ import { setSourceFeature, setIntersectionFeature, setSelectedLayerType, - runBufferProcess, - runIntersectionProcess, + runProcess, runningProcess, toggleHighlightLayers -} from '../../actions/geoProcessingTools'; +} from '../../actions/geoProcessing'; import { mergeOptionsByOwner, updateAdditionalLayer, @@ -64,6 +66,9 @@ import { import { updateMapLayout } from '../../actions/maplayout'; +import { + toggleControl +} from '../../actions/controls'; import { registerEventListener, zoomToExtent, @@ -85,7 +90,7 @@ import { purgeMapInfoResults, changeMapInfoState } from "../../actions/mapInfo"; -describe('geoProcessingTools epics', () => { +describe('geoProcessing epics', () => { let mockAxios; beforeEach(() => { mockAxios = new MockAdapter(axios); @@ -319,7 +324,7 @@ describe('geoProcessingTools epics', () => { } }] }, - geoProcessingTools: { + geoProcessing: { source: { layerId: "id" }, @@ -353,7 +358,7 @@ describe('geoProcessingTools epics', () => { } }] }, - geoProcessingTools: { + geoProcessing: { source: { layerId: "id" }, @@ -391,7 +396,7 @@ describe('geoProcessingTools epics', () => { } }] }, - geoProcessingTools: { + geoProcessing: { intersection: { layerId: "id" }, @@ -425,7 +430,7 @@ describe('geoProcessingTools epics', () => { } }] }, - geoProcessingTools: { + geoProcessing: { intersection: { layerId: "id" }, @@ -436,13 +441,13 @@ describe('geoProcessingTools epics', () => { }); }); it('runBufferProcess with geom collect', (done) => { - const NUM_ACTIONS = 6; + const NUM_ACTIONS = 7; mockAxios.onGet("mockUrl?service=WFS&version=1.1.0&request=GetFeature").reply(200, GET_FEATURES); mockAxios.onPost("mockUrl?service=WPS&version=1.0.0&REQUEST=Execute").reply(200, COLLECT_GEOM, { "content-type": "application/json" }); - const startActions = [runBufferProcess()]; + const startActions = [runProcess(GPT_TOOL_BUFFER)]; testEpic(addTimeoutEpic(runBufferProcessGPTEpic, 100), NUM_ACTIONS, startActions, actions => { expect(actions.length).toBe(NUM_ACTIONS); const [ @@ -451,14 +456,16 @@ describe('geoProcessingTools epics', () => { action3, action4, action5, - action6 + action6, + action7 ] = actions; expect(action1).toEqual(runningProcess(true)); expect(action2.type).toEqual(addGroup().type); expect(action3.type).toEqual(increaseBufferedCounter().type); expect(action4.type).toEqual(addLayer().type); - expect(action5.type).toEqual(showSuccessNotification().type); - expect(action6).toEqual(runningProcess(false)); + expect(action5.type).toEqual(zoomToExtent().type); + expect(action6.type).toEqual(showSuccessNotification().type); + expect(action7).toEqual(runningProcess(false)); done(); }, { layers: { @@ -471,7 +478,7 @@ describe('geoProcessingTools epics', () => { } }] }, - geoProcessingTools: { + geoProcessing: { source: { layerId: "id" }, @@ -482,12 +489,12 @@ describe('geoProcessingTools epics', () => { }); }); it('runBufferProcess without geom collect', (done) => { - const NUM_ACTIONS = 6; + const NUM_ACTIONS = 7; mockAxios.onGet("mockUrl?service=WFS&version=1.1.0&request=GetFeature").reply(200, GET_FEATURES); mockAxios.onPost("mockUrl?service=WPS&version=1.0.0&REQUEST=Execute").reply(200, COLLECT_GEOM, { "content-type": "application/json" }); - const startActions = [runBufferProcess()]; + const startActions = [runProcess(GPT_TOOL_BUFFER)]; testEpic(addTimeoutEpic(runBufferProcessGPTEpic, 100), NUM_ACTIONS, startActions, actions => { expect(actions.length).toBe(NUM_ACTIONS); const [ @@ -496,14 +503,17 @@ describe('geoProcessingTools epics', () => { action3, action4, action5, - action6 + action6, + action7 ] = actions; expect(action1).toEqual(runningProcess(true)); expect(action2.type).toEqual(addGroup().type); expect(action3.type).toEqual(increaseBufferedCounter().type); expect(action4.type).toEqual(addLayer().type); - expect(action5.type).toEqual(showSuccessNotification().type); - expect(action6).toEqual(runningProcess(false)); + expect(action5.type).toEqual(zoomToExtent().type); + expect(action6.type).toEqual(showSuccessNotification().type); + + expect(action7).toEqual(runningProcess(false)); done(); }, { layers: { @@ -516,7 +526,7 @@ describe('geoProcessingTools epics', () => { } }] }, - geoProcessingTools: { + geoProcessing: { source: { layerId: "id", featureId: "ft-id", @@ -592,7 +602,7 @@ describe('geoProcessingTools epics', () => { }, {}); }); it('runIntersectProcessGPTEpic with double geom collect', (done) => { - const NUM_ACTIONS = 6; + const NUM_ACTIONS = 7; mockAxios.onGet("mockUrl?service=WFS&version=1.1.0&request=GetFeature").reply(200, GET_FEATURES); mockAxios.onPost("mockUrl?service=WPS&version=1.0.0&REQUEST=Execute").reply(200, COLLECT_GEOM, { "content-type": "application/json" @@ -602,7 +612,7 @@ describe('geoProcessingTools epics', () => { "content-type": "application/json" }); - const startActions = [runIntersectionProcess()]; + const startActions = [runProcess(GPT_TOOL_INTERSECTION)]; testEpic(addTimeoutEpic(runIntersectProcessGPTEpic, 100), NUM_ACTIONS, startActions, actions => { expect(actions.length).toBe(NUM_ACTIONS); const [ @@ -611,14 +621,16 @@ describe('geoProcessingTools epics', () => { action3, action4, action5, - action6 + action6, + action7 ] = actions; expect(action1).toEqual(runningProcess(true)); expect(action2.type).toEqual(addGroup().type); expect(action3.type).toEqual(increaseIntersectedCounter().type); expect(action4.type).toEqual(addLayer().type); - expect(action5.type).toEqual(showSuccessNotification().type); - expect(action6).toEqual(runningProcess(false)); + expect(action5.type).toEqual(zoomToExtent().type); + expect(action6.type).toEqual(showSuccessNotification().type); + expect(action7).toEqual(runningProcess(false)); done(); }, { layers: { @@ -639,7 +651,7 @@ describe('geoProcessingTools epics', () => { } }] }, - geoProcessingTools: { + geoProcessing: { source: { layerId: "id" }, @@ -704,7 +716,7 @@ describe('geoProcessingTools epics', () => { done(); }, { - geoProcessingTools: { + geoProcessing: { selectedLayerId: "id", selectedLayerType: "source", source: { @@ -755,9 +767,83 @@ describe('geoProcessingTools epics', () => { done(); }, { controls: { - GeoProcessingTools: { + GeoProcessing: { + enabled: true + } + } + }); + }); + + it('toggleHighlightLayersOnOpenCloseGPTEpic closing tool', (done) => { + const NUM_ACTIONS = 1; + const startActions = [toggleControl(GPT_CONTROL_NAME)]; + testEpic(toggleHighlightLayersOnOpenCloseGPTEpic, NUM_ACTIONS, startActions, actions => { + expect(actions.length).toBe(NUM_ACTIONS); + const [ + action1 + ] = actions; + expect(action1.type).toEqual(mergeOptionsByOwner().type); + expect(action1.options.visibility).toEqual(false); + done(); + }, { + additionallayers: [{ + id: "gpt-layer-intersection", + owner: "gpt", + actionType: "overlay", + options: { + visibility: true + } + } + ], + controls: { + GeoProcessing: { + enabled: false + } + }, + geoProcessing: { + flags: { + showHighlightLayers: true + } + } + }); + }); + it('toggleHighlightLayersOnOpenCloseGPTEpic closing tool', (done) => { + const NUM_ACTIONS = 1; + const startActions = [toggleControl(GPT_CONTROL_NAME)]; + testEpic(toggleHighlightLayersOnOpenCloseGPTEpic, NUM_ACTIONS, startActions, actions => { + expect(actions.length).toBe(NUM_ACTIONS); + const [ + action1 + ] = actions; + expect(action1.type).toEqual(updateAdditionalLayer().type); + expect(action1.options.visibility).toEqual(true); + done(); + }, { + additionallayers: [{ + id: "gpt-layer-intersection", + owner: "gpt", + actionType: "overlay", + options: { + visibility: false + } + }, { + id: "gpt-layer", + owner: "gpt", + actionType: "overlay", + options: { + visibility: true + } + }], + controls: { + GeoProcessing: { enabled: true } + }, + geoProcessing: { + selectedTool: GPT_TOOL_BUFFER, + flags: { + showHighlightLayers: true + } } }); }); diff --git a/web/client/epics/geoProcessingTools.js b/web/client/epics/geoProcessing.js similarity index 79% rename from web/client/epics/geoProcessingTools.js rename to web/client/epics/geoProcessing.js index 1f62a7b12a..e5812825b7 100644 --- a/web/client/epics/geoProcessingTools.js +++ b/web/client/epics/geoProcessing.js @@ -34,7 +34,15 @@ import { TOGGLE_CONTROL } from "../actions/controls"; import { + GPT_TOOL_BUFFER, + GPT_TOOL_INTERSECTION, + GPT_INTERSECTION_HIGHLIGHT_ID, + GPT_SOURCE_HIGHLIGHT_ID, GPT_CONTROL_NAME, + GPT_INTERSECTION_GROUP_ID, + GPT_BUFFER_GROUP_ID, + + setSelectedLayerType, CHECK_WPS_AVAILABILITY, checkingIntersectionWPSAvailability, checkingWPSAvailability, @@ -44,8 +52,8 @@ import { getFeatures, increaseBufferedCounter, increaseIntersectedCounter, - RUN_BUFFER_PROCESS, - RUN_INTERSECTION_PROCESS, + RESET, + RUN_PROCESS, runningProcess, SET_INTERSECTION_FEATURE_ID, SET_INTERSECTION_LAYER_ID, @@ -61,7 +69,7 @@ import { SET_SELECTED_LAYER_TYPE, setWPSAvailability, TOGGLE_HIGHLIGHT_LAYERS -} from '../actions/geoProcessingTools'; +} from '../actions/geoProcessing'; import { getDescribeLayer } from '../actions/layerCapabilities'; @@ -69,7 +77,8 @@ import {addLayer, addGroup, UPDATE_NODE} from '../actions/layers'; import { zoomToExtent, CLICK_ON_MAP, - registerEventListener + registerEventListener, + unRegisterEventListener } from "../actions/map"; import { hideMapinfoMarker, @@ -88,6 +97,7 @@ import { describeProcess } from '../observables/wps/describe'; import executeProcess from '../observables/wps/execute'; import intersectXML from '../observables/wps/intersectionFeatureCollection'; import { + selectedToolSelector, sourceFeaturesSelector, sourceTotalCountSelector, intersectionTotalCountSelector, @@ -107,9 +117,10 @@ import { selectedLayerIdSelector, sourceFeatureSelector, showHighlightLayersSelector -} from '../selectors/geoProcessingTools'; +} from '../selectors/geoProcessing'; import {getLayerFromId as getLayerFromIdSelector, groupsSelector} from '../selectors/layers'; -import {isGeoProcessingToolsEnabledSelector} from '../selectors/controls'; +import {additionalLayersSelector} from '../selectors/additionallayers'; +import {isGeoProcessingEnabledSelector} from '../selectors/controls'; import {mapSelector} from '../selectors/map'; import {highlightStyleSelector, applyMapInfoStyle, mapInfoEnabledSelector} from '../selectors/mapInfo'; @@ -132,6 +143,9 @@ const DEACTIVATE_ACTIONS = [ /** * checks if a layer is a valid one that can be used in the gpt tool. * also checks if it is a raster using describe layer + * + * this is a unique epics for two layer fields "source" and "intersection" that are used in + * these two process "buffer" and "intersection", no need to generalize this now */ export const checkWPSAvailabilityGPTEpic = (action$, store) => action$ .ofType(CHECK_WPS_AVAILABILITY) @@ -207,6 +221,9 @@ export const checkWPSAvailabilityGPTEpic = (action$, store) => action$ }); /** * fetch all features ids + * + * this is a unique epic for fetching features of two layer fields "source" and "intersection" + * that are used in these two process "buffer" and "intersection", no need to generalize this now */ export const getFeaturesGPTEpic = (action$, store) => action$ .ofType(GET_FEATURES) @@ -234,7 +251,7 @@ export const getFeaturesGPTEpic = (action$, store) => action$ const layer = getLayerFromIdSelector(state, layerId); const maxFeatures = maxFeaturesSelector(state); const filterObj = null; - if (isNil(layer.describeFeatureType)) { + if (isNil(layer?.describeFeatureType)) { // throw error and notify user that a failure has happened return Rx.Observable.of(errorLoadingDFT(layerId)); } @@ -262,6 +279,9 @@ export const getFeaturesGPTEpic = (action$, store) => action$ }); /** * fetch the source feature geom by id + * + * this is a unique epic related to the "source" layer + * that are used in these two process "buffer" and "intersection", no need to generalize this */ export const getFeatureDataGPTEpic = (action$, store) => action$ .ofType(SET_SOURCE_FEATURE_ID) @@ -283,7 +303,7 @@ export const getFeatureDataGPTEpic = (action$, store) => action$ return Rx.Observable.from([ setSourceFeature(head(features)), updateAdditionalLayer( - "gpt-layer", + GPT_SOURCE_HIGHLIGHT_ID, "gpt", "overlay", { @@ -299,7 +319,7 @@ export const getFeatureDataGPTEpic = (action$, store) => action$ .catch(() => { return Rx.Observable.of(showErrorNotification({ title: "errorTitleDefault", - message: "GeoProcessingTools.notifications.errorGetFeature", + message: "GeoProcessing.notifications.errorGetFeature", autoDismiss: 6, position: "tc" })); @@ -307,6 +327,9 @@ export const getFeatureDataGPTEpic = (action$, store) => action$ }); /** * fetch the intersection feature geom by id + * + * this is a unique epic related to the "intersection" layer + * that are used in this process "intersection" */ export const getIntersectionFeatureDataGPTEpic = (action$, store) => action$ .ofType(SET_INTERSECTION_FEATURE_ID) @@ -328,7 +351,7 @@ export const getIntersectionFeatureDataGPTEpic = (action$, store) => action$ return Rx.Observable.from([ setIntersectionFeature(head(features)), updateAdditionalLayer( - "gpt-layer-intersection", + GPT_INTERSECTION_HIGHLIGHT_ID, "gpt", "overlay", { @@ -344,7 +367,7 @@ export const getIntersectionFeatureDataGPTEpic = (action$, store) => action$ .catch(() => { return Rx.Observable.of(showErrorNotification({ title: "errorTitleDefault", - message: "GeoProcessingTools.notifications.errorGetFeature", + message: "GeoProcessing.notifications.errorGetFeature", autoDismiss: 6, position: "tc" })); @@ -354,7 +377,8 @@ export const getIntersectionFeatureDataGPTEpic = (action$, store) => action$ * run buffer process and update toc with new layer geom */ export const runBufferProcessGPTEpic = (action$, store) => action$ - .ofType(RUN_BUFFER_PROCESS) + .ofType(RUN_PROCESS) + .filter(({process}) => process === GPT_TOOL_BUFFER ) .switchMap(({}) => { const state = store.getState(); const layerId = sourceLayerIdSelector(state); @@ -389,7 +413,8 @@ export const runBufferProcessGPTEpic = (action$, store) => action$ geometry3857: wktGeom, distance, quadrantSegments, - capStyle }), + capStyle + }), executeOptions, { headers: {'Content-Type': 'application/xml', 'Accept': `application/xml, application/json`} }); @@ -400,8 +425,19 @@ export const runBufferProcessGPTEpic = (action$, store) => action$ executeBufferProcess$(wktGeom, feature4326) .switchMap((geom) => { const groups = groupsSelector(state); - const groupExist = find(groups, ({id}) => id === "buffered.layers"); - return (!groupExist ? Rx.Observable.of( addGroup("Buffered layers", null, {id: "buffered.layers"})) : Rx.Observable.empty()) + const groupExist = find(groups, ({id}) => id === GPT_BUFFER_GROUP_ID); + const features = [ + reprojectGeoJson({ + id: 0, + geometry: geom, + type: "Feature" + }, "EPSG:3857", "EPSG:4326" ) + ]; + const extent = getGeoJSONExtent({ + features, + type: "FeatureCollection" + }); + return (!groupExist ? Rx.Observable.of( addGroup("Buffered layers", null, {id: GPT_BUFFER_GROUP_ID}, true)) : Rx.Observable.empty()) .concat( Rx.Observable.of( increaseBufferedCounter(), @@ -411,13 +447,17 @@ export const runBufferProcessGPTEpic = (action$, store) => action$ name: "Buffer Layer " + counter, title: "Buffer Layer " + counter, visibility: true, - group: "buffered.layers", - features: [ - reprojectGeoJson({ - id: 0, - geometry: geom, - type: "Feature" - }, "EPSG:3857", "EPSG:4326" )], + group: GPT_BUFFER_GROUP_ID, + bbox: { + crs: "EPSG:4326", + bounds: { + minx: extent[0], + miny: extent[1], + maxx: extent[2], + maxy: extent[3] + } + }, + features, style: { format: "geostyler", body: { @@ -426,18 +466,20 @@ export const runBufferProcessGPTEpic = (action$, store) => action$ symbolizers: [ { "kind": "Fill", - "outlineColor": "#3075e9", - "fillOpacity": 0, - "width": 3 + "outlineWidth": 3, + "outlineColor": "#ffac12", + "color": "#ffffff", + "fillOpacity": 0.3 } ] }] } } }), + zoomToExtent(extent, "EPSG:4326"), showSuccessNotification({ title: "notification.success", - message: "GeoProcessingTools.notifications.successfulBuffer", + message: "GeoProcessing.notifications.successfulBuffer", autoDismiss: 6, position: "tc" }) @@ -447,7 +489,7 @@ export const runBufferProcessGPTEpic = (action$, store) => action$ .catch(() => { return Rx.Observable.of(showErrorNotification({ title: "errorTitleDefault", - message: "GeoProcessingTools.notifications.errorBuffer", + message: "GeoProcessing.notifications.errorBuffer", autoDismiss: 6, position: "tc" })); @@ -465,7 +507,7 @@ export const runBufferProcessGPTEpic = (action$, store) => action$ }).catch(() => { return Rx.Observable.of(showErrorNotification({ title: "errorTitleDefault", - message: "GeoProcessingTools.notifications.errorBuffer", + message: "GeoProcessing.notifications.errorBuffer", autoDismiss: 6, position: "tc" })); @@ -497,7 +539,7 @@ export const resetSourceHighlightGPTEpic = (action$) => action$ .ofType(SET_SOURCE_LAYER_ID, SET_SOURCE_FEATURE_ID) .filter(a => a.layerId === "" || a.featureId === "") .switchMap(({}) => { - return Rx.Observable.of(removeAdditionalLayer({id: "gpt-layer"})); + return Rx.Observable.of(removeAdditionalLayer({id: GPT_SOURCE_HIGHLIGHT_ID})); }); /** * clear intersection highlight feature @@ -506,13 +548,14 @@ export const resetIntersectHighlightGPTEpic = (action$) => action$ .ofType(SET_INTERSECTION_LAYER_ID, SET_INTERSECTION_FEATURE_ID) .filter(a => a.layerId === "" || a.featureId === "") .switchMap(({}) => { - return Rx.Observable.of(removeAdditionalLayer({id: "gpt-layer-intersection"})); + return Rx.Observable.of(removeAdditionalLayer({id: GPT_INTERSECTION_HIGHLIGHT_ID})); }); /** * run intersection process and update toc with new layer geom */ export const runIntersectProcessGPTEpic = (action$, store) => action$ - .ofType(RUN_INTERSECTION_PROCESS) + .ofType(RUN_PROCESS) + .filter(({process}) => process === GPT_TOOL_INTERSECTION ) .switchMap(({}) => { const state = store.getState(); const layerId = sourceLayerIdSelector(state); @@ -521,6 +564,7 @@ export const runIntersectProcessGPTEpic = (action$, store) => action$ const sourceFeature = sourceFeatureSelector(state); const executeOptions = {}; const intersectionFeature = intersectionFeatureSelector(state); + const counter = intersectedLayersCounterSelector(state); let sourceFC$; let intersectionFC$; if (isEmpty(sourceFeature)) { @@ -550,7 +594,6 @@ export const runIntersectProcessGPTEpic = (action$, store) => action$ } return Rx.Observable.forkJoin(sourceFC$, intersectionFC$) .switchMap(([firstGeom, secondGeom]) => { - const counter = intersectedLayersCounterSelector(state); const executeProcess$ = executeProcess( layerUrl, @@ -572,8 +615,9 @@ export const runIntersectProcessGPTEpic = (action$, store) => action$ const intersection$ = executeProcess$ .switchMap((featureCollection) => { const groups = groupsSelector(state); - const groupExist = find(groups, ({id}) => id === "intersection.layers"); - return (!groupExist ? Rx.Observable.of( addGroup("Intersected Layers", null, {id: "intersection.layer"})) : Rx.Observable.empty()) + const groupExist = find(groups, (g) => g.id === GPT_INTERSECTION_GROUP_ID); + const extent = getGeoJSONExtent(featureCollection); + return (!groupExist ? Rx.Observable.of( addGroup("Intersected Layers", null, {id: GPT_INTERSECTION_GROUP_ID}, true)) : Rx.Observable.empty()) .concat( Rx.Observable.of( increaseIntersectedCounter(), @@ -581,10 +625,19 @@ export const runIntersectProcessGPTEpic = (action$, store) => action$ id: uuidV1(), type: "vector", name: "Intersection Layer " + counter, - group: "intersection.layer", + group: GPT_INTERSECTION_GROUP_ID, title: "Intersection Layer " + counter, visibility: true, features: featureCollection.features, + bbox: { + crs: "EPSG:4326", + bounds: { + minx: extent[0], + miny: extent[1], + maxx: extent[2], + maxy: extent[3] + } + }, style: { format: "geostyler", body: { @@ -593,18 +646,20 @@ export const runIntersectProcessGPTEpic = (action$, store) => action$ symbolizers: [ { "kind": "Fill", - "outlineColor": "#880000", - "fillOpacity": 0.5, - "width": 5 + "outlineWidth": 3, + "outlineColor": "#ffac12", + "color": "#ffffff", + "fillOpacity": 0.3 } ] }] } } }), + zoomToExtent(extent, "EPSG:4326"), showSuccessNotification({ title: "notification.success", - message: "GeoProcessingTools.notifications.successfulIntersection", + message: "GeoProcessing.notifications.successfulIntersection", autoDismiss: 6, position: "tc" }) @@ -613,7 +668,7 @@ export const runIntersectProcessGPTEpic = (action$, store) => action$ .catch(() => { return Rx.Observable.of(showErrorNotification({ title: "errorTitleDefault", - message: "GeoProcessingTools.notifications.errorIntersectGFI", + message: "GeoProcessing.notifications.errorIntersectGFI", autoDismiss: 6, position: "tc" })); @@ -635,22 +690,64 @@ export const toggleHighlightLayersGPTEpic = (action$, store) => action$ visibility: showHighlightLayers })); }); -export const toggleHighlightLayersOnOpencloseGPTEpic = (action$, store) => action$ +export const toggleHighlightLayersOnOpenCloseGPTEpic = (action$, store) => action$ .ofType(TOGGLE_CONTROL) .filter(action => action.control === GPT_CONTROL_NAME) .switchMap(() => { - const showHighlightLayers = showHighlightLayersSelector(store.getState()); - const isGPTEnabled = isGeoProcessingToolsEnabledSelector(store.getState()); - return Rx.Observable.of(mergeOptionsByOwner("gpt", { - visibility: isGPTEnabled ? showHighlightLayers : false - })); + const state = store.getState(); + const showHighlightLayers = showHighlightLayersSelector(state); + const isGPTEnabled = isGeoProcessingEnabledSelector(state); + const selectedTool = selectedToolSelector(state); + if (selectedTool === GPT_TOOL_BUFFER) { + const additionalLayers = additionalLayersSelector(state); + const bufferLayer = find(additionalLayers, ({id}) => id === GPT_SOURCE_HIGHLIGHT_ID ); + return bufferLayer?.id ? Rx.Observable.of( + updateAdditionalLayer( + bufferLayer.id, + bufferLayer.owner, + bufferLayer.actionType, + { + ...bufferLayer.options, + visibility: isGPTEnabled ? showHighlightLayers : false + } + ), + unRegisterEventListener('click', GPT_CONTROL_NAME), + ...(!isGPTEnabled ? [changeMapInfoState(true), setSelectedLayerType("")] : []) + ) : Rx.Observable.of( + unRegisterEventListener('click', GPT_CONTROL_NAME), + ...(!isGPTEnabled ? [changeMapInfoState(true), setSelectedLayerType("")] : []) + ); + } + // INTERSECTION enabled any + return Rx.Observable.of( + mergeOptionsByOwner("gpt", { + visibility: isGPTEnabled ? showHighlightLayers : false + }) + ).concat( + Rx.Observable.of( + unRegisterEventListener('click', GPT_CONTROL_NAME), + ...(!isGPTEnabled ? [changeMapInfoState(true), setSelectedLayerType("")] : []) + ) + ); }); + +export const unRegisterEventListenerOnReset = action$ => + action$ + .ofType(RESET) // add location change + .switchMap(() => { + return Rx.Observable.of( + unRegisterEventListener('click', GPT_CONTROL_NAME) + ); + }); + + /** * activate feature selection from map */ export const disableIdentifyGPTEpic = (action$, {getState}) => action$ .ofType(SET_SELECTED_LAYER_TYPE) + .filter(({source}) => !!source) .switchMap(({source}) => { const state = getState(); return Rx.Observable.from([ @@ -694,7 +791,7 @@ export const clickToSelectFeatureGPTEpic = (action$, {getState}) => updateFeatureId(features[0].id), showSuccessNotification({ title: "notification.success", - message: "GeoProcessingTools.notifications.featureFound", + message: "GeoProcessing.notifications.featureFound", autoDismiss: 10, position: "tc" }) @@ -702,7 +799,7 @@ export const clickToSelectFeatureGPTEpic = (action$, {getState}) => } return Rx.Observable.of(showWarningNotification({ title: "notification.warning", - message: "GeoProcessingTools.notifications.noFeatureInPoint", + message: "GeoProcessing.notifications.noFeatureInPoint", autoDismiss: 10, position: "tc" })); @@ -710,7 +807,7 @@ export const clickToSelectFeatureGPTEpic = (action$, {getState}) => .catch(() => { return Rx.Observable.of(showErrorNotification({ title: "errorTitleDefault", - message: "GeoProcessingTools.notifications.errorGFI", + message: "GeoProcessing.notifications.errorGFI", autoDismiss: 6, position: "tc" })); @@ -740,7 +837,7 @@ export const clickToSelectFeatureGPTEpic = (action$, {getState}) => */ export const LPlongitudinalMapLayoutGPTEpic = (action$, store) => action$.ofType(UPDATE_MAP_LAYOUT) - .filter(({source}) => isGeoProcessingToolsEnabledSelector(store.getState()) && source !== GPT_CONTROL_NAME) + .filter(({source}) => isGeoProcessingEnabledSelector(store.getState()) && source !== GPT_CONTROL_NAME) .map(({layout}) => { const action = updateMapLayout({ ...layout, @@ -754,3 +851,16 @@ export const LPlongitudinalMapLayoutGPTEpic = (action$, store) => return { ...action, source: GPT_CONTROL_NAME }; // add an argument to avoid infinite loop. }); + +/** + * hide intersection Feature when switching to Buffer + * show intersection Feature when switching to intersection if flag highlight is true + */ +export const removeHighlightsOnResetGPTEpic = (action$) => + action$.ofType(RESET) + .switchMap(() => { + return Rx.Observable.of( + removeAdditionalLayer({id: GPT_SOURCE_HIGHLIGHT_ID}), + removeAdditionalLayer({id: GPT_INTERSECTION_HIGHLIGHT_ID}) + ); + }); diff --git a/web/client/plugins/GeoProcessingTools.jsx b/web/client/plugins/GeoProcessing.jsx similarity index 75% rename from web/client/plugins/GeoProcessingTools.jsx rename to web/client/plugins/GeoProcessing.jsx index ed27c22904..d863ec57c3 100644 --- a/web/client/plugins/GeoProcessingTools.jsx +++ b/web/client/plugins/GeoProcessing.jsx @@ -9,10 +9,10 @@ import React from 'react'; import { Glyphicon } from 'react-bootstrap'; import Message from '../components/I18N/Message'; -import GeoProcessingToolsPanel from './GeoProcessingTools/Panel'; +import GeoProcessingPanel from './GeoProcessing/Panel'; import { toggleControl } from '../actions/controls'; -import * as epics from '../epics/geoProcessingTools'; -import geoProcessingTools from '../reducers/geoProcessingTools'; +import * as epics from '../epics/geoProcessing'; +import geoProcessing from '../reducers/geoProcessing'; import { createPlugin } from '../utils/PluginsUtils'; @@ -24,7 +24,7 @@ import { createPlugin } from '../utils/PluginsUtils'; * - "intersection" of two layers * the result is a new vector layer that is added in the TOC * - * @name GeoProcessingTools + * @name GeoProcessing * @memberof plugins * @class * @@ -40,7 +40,7 @@ import { createPlugin } from '../utils/PluginsUtils'; * @example * * { - * "name": "GeoProcessingTools", + * "name": "GeoProcessing", * "cfg": { * "selectedTool": "buffer", * "buffer": { @@ -51,27 +51,27 @@ import { createPlugin } from '../utils/PluginsUtils'; * } * */ -const GeoProcessingTools = createPlugin( - "GeoProcessingTools", +const GeoProcessing = createPlugin( + "GeoProcessing", { - component: GeoProcessingToolsPanel, + component: GeoProcessingPanel, containers: { SidebarMenu: { - name: 'GeoProcessingTools', + name: 'GeoProcessing', position: 2100, doNotHide: true, - tooltip: "GeoProcessingTools.tooltip.siderBarBtn", - text: , - icon: , // [ ] change this - action: toggleControl.bind(null, 'GeoProcessingTools', null), + tooltip: "GeoProcessing.tooltip.siderBarBtn", + text: , + icon: , + action: toggleControl.bind(null, 'GeoProcessing', null), priority: 10, toggle: true } }, reducers: { - geoProcessingTools + geoProcessing }, epics }); -export default GeoProcessingTools; +export default GeoProcessing; diff --git a/web/client/plugins/GeoProcessing/Buffer.jsx b/web/client/plugins/GeoProcessing/Buffer.jsx new file mode 100644 index 0000000000..702936d500 --- /dev/null +++ b/web/client/plugins/GeoProcessing/Buffer.jsx @@ -0,0 +1,288 @@ +/* + * Copyright 2023, 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 React, {useState} from 'react'; +import PropTypes from 'prop-types'; +import { + FormGroup, + InputGroup, + ControlLabel +} from 'react-bootstrap'; +import { connect } from 'react-redux'; +import Select from 'react-select'; +import { createSelector } from 'reselect'; + +import InfoPopover from '../../components/widgets/widget/InfoPopover'; +import SwitchButton from '../../components/misc/switch/SwitchButton'; +import Message from '../../components/I18N/Message'; +import FormControl from '../../components/misc/DebouncedFormControl'; +import SwitchPanel from '../../components/misc/switch/SwitchPanel'; +import SourceLayer from './SourceLayer'; +import { + runProcess, + setBufferDistance, + setBufferDistanceUom, + setBufferQuadrantSegments, + setBufferCapStyle, + toggleHighlightLayers +} from '../../actions/geoProcessing'; +import { + areAllWPSAvailableForSourceLayerSelector, + distanceSelector, + distanceUomSelector, + quadrantSegmentsSelector, + capStyleSelector, + isSourceLayerInvalidSelector, + sourceLayerIdSelector, + sourceFeatureSelector, + runningProcessSelector, + showHighlightLayersSelector +} from '../../selectors/geoProcessing'; +import tooltip from '../../components/misc/enhancers/tooltip'; +import { getMessageById } from '../../utils/LocaleUtils'; + +const Addon = tooltip(InputGroup.Addon); +const Buffer = ({ + areAllWPSAvailableForSourceLayer, + distance, + distanceUom, + quadrantSegments, + capStyle, + isSourceLayerInvalid, + process, + runningProcess, + showHighlightLayers, + sourceLayerId, + sourceFeature, + onRunProcess, + onSetBufferDistance, + onSetBufferDistanceUom, + onSetBufferQuadrantSegments, + onSetBufferCapStyle, + onToggleHighlightLayers +}, {messages}) => { + const [showBufferAdvancedSettings, setShowBufferAdvancedSettings] = + useState(false); + const [showWarning, onShowWarning] = useState(false); + + const handleOnChangeBufferDistance = (val) => { + onSetBufferDistance(val); + }; + const handleOnChangeBufferDistanceUom = (sel) => { + onSetBufferDistanceUom(sel?.value || ""); + }; + const handleOnChangeBufferQuadrantSegments = (val) => { + onSetBufferQuadrantSegments(val); + }; + const handleOnChangeBufferCapStyle = (sel) => { + onSetBufferCapStyle(sel?.value || ""); + }; + const handleOnToggleHighlightLayers = () => { + onToggleHighlightLayers(); + }; + + // confirm modal + const handleConfirmRunProcess = () => { + if (showHighlightLayers) { + onToggleHighlightLayers(); + } + process.actions.runProcessConfirm({ + onShowWarning, + onRunProcess + }); + }; + const handleCloseWarningModal = () => { + onShowWarning(false); + }; + return ( + <> + +
+
+ + + + + + + } + onChange={handleOnChangeBufferCapStyle} + options={[ + {value: "Round", label: }, + {value: "Flat", label: }, + {value: "Square", label: } + ]} + /> + + + + + + + + + + + + + + + + ); + +}; + +Buffer.propTypes = { + areAllWPSAvailableForSourceLayer: PropTypes.bool, + distance: PropTypes.number, + distanceUom: PropTypes.string, + quadrantSegments: PropTypes.number, + capStyle: PropTypes.string, + isSourceLayerInvalid: PropTypes.bool, + sourceLayerId: PropTypes.string, + sourceFeature: PropTypes.object, + process: PropTypes.object, + runningProcess: PropTypes.bool, + showHighlightLayers: PropTypes.bool, + onSetBufferDistance: PropTypes.func, + onRunProcess: PropTypes.func, + onSetBufferDistanceUom: PropTypes.func, + onSetBufferQuadrantSegments: PropTypes.func, + onSetBufferCapStyle: PropTypes.func, + onToggleHighlightLayers: PropTypes.func +}; + +const BufferConnected = connect( + createSelector( + [ + areAllWPSAvailableForSourceLayerSelector, + distanceSelector, + distanceUomSelector, + isSourceLayerInvalidSelector, + sourceLayerIdSelector, + sourceFeatureSelector, + quadrantSegmentsSelector, + capStyleSelector, + runningProcessSelector, + showHighlightLayersSelector + ], + ( + areAllWPSAvailableForSourceLayer, + distance, + distanceUom, + isSourceLayerInvalid, + sourceLayerId, + sourceFeature, + quadrantSegments, + capStyle, + runningProcess, + showHighlightLayers + ) => ({ + areAllWPSAvailableForSourceLayer, + distance, + distanceUom, + isSourceLayerInvalid, + sourceLayerId, + sourceFeature, + quadrantSegments, + capStyle, + runningProcess, + showHighlightLayers + })), + { + onSetBufferDistance: setBufferDistance, + onSetBufferDistanceUom: setBufferDistanceUom, + onSetBufferQuadrantSegments: setBufferQuadrantSegments, + onSetBufferCapStyle: setBufferCapStyle, + onToggleHighlightLayers: toggleHighlightLayers, + onRunProcess: runProcess + })(Buffer); + +Buffer.contextTypes = { + messages: PropTypes.object +}; + +export default BufferConnected; diff --git a/web/client/plugins/GeoProcessing/Intersection.jsx b/web/client/plugins/GeoProcessing/Intersection.jsx new file mode 100644 index 0000000000..7027074d6d --- /dev/null +++ b/web/client/plugins/GeoProcessing/Intersection.jsx @@ -0,0 +1,383 @@ +/* + * Copyright 2023, 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 React, {useState} from 'react'; +import PropTypes from 'prop-types'; +import { + FormGroup, + InputGroup, + ControlLabel +} from 'react-bootstrap'; +import { connect } from 'react-redux'; +import Select from 'react-select'; +import { createSelector } from 'reselect'; + +import SwitchButton from '../../components/misc/switch/SwitchButton'; +import InfoPopover from '../../components/widgets/widget/InfoPopover'; +import Message from '../../components/I18N/Message'; +import FormControl from '../../components/misc/DebouncedFormControl'; +import SwitchPanel from '../../components/misc/switch/SwitchPanel'; +import IntersectionLayer from './IntersectionLayer'; +import SourceLayer from './SourceLayer'; +import { + runProcess, + setIntersectionFirstAttribute, + setIntersectionSecondAttribute, + setIntersectionMode, + setIntersectionPercentagesEnabled, + setIntersectionAreasEnabled, + toggleHighlightLayers +} from '../../actions/geoProcessing'; +import { + areAllWPSAvailableForSourceLayerSelector, + areAllWPSAvailableForIntersectionLayerSelector, + areasEnabledSelector, + firstAttributeToRetainSelector, + intersectionModeSelector, + isIntersectionLayerInvalidSelector, + isIntersectionEnabledSelector, + isSourceLayerInvalidSelector, + sourceLayerIdSelector, + intersectionLayerIdSelector, + percentagesEnabledSelector, + runningProcessSelector, + secondAttributeToRetainSelector, + showHighlightLayersSelector, + sourceFeatureSelector, + intersectionFeatureSelector +} from '../../selectors/geoProcessing'; +import tooltip from '../../components/misc/enhancers/tooltip'; +import { getMessageById } from '../../utils/LocaleUtils'; + +const Addon = tooltip(InputGroup.Addon); +const Intersection = ({ + areAllWPSAvailableForIntersectionLayer, + areAllWPSAvailableForSourceLayer, + areasEnabled, + firstAttributeToRetain, + intersectionFeature, + intersectionLayerId, + intersectionMode, + isIntersectionEnabled, + isIntersectionLayerInvalid, + isSourceLayerInvalid, + percentagesEnabled, + process, + runningProcess, + secondAttributeToRetain, + showHighlightLayers, + sourceFeature, + sourceLayerId, + onSetIntersectionFirstAttribute, + onSetIntersectionSecondAttribute, + onSetIntersectionMode, + onSetIntersectionPercentagesEnabled, + onSetIntersectionAreasEnabled, + onToggleHighlightLayers, + onRunProcess +}, {messages}) => { + const [showAdvancedSettings, setShowAdvancedSettings] = useState(false); + const [showWarning, onShowWarning] = useState(false); + + const handleOnChangeFirstAttributeToRetain = (val) => { + onSetIntersectionFirstAttribute(val); + }; + const handleOnChangeSecondAttributeToRetain = (val) => { + onSetIntersectionSecondAttribute(val); + }; + const handleOnChangeIntersectionMode = (sel) => { + onSetIntersectionMode(sel?.value || ""); + }; + const handleOnChangePercentagesEnabled = (sel) => { + onSetIntersectionPercentagesEnabled(sel?.value || ""); + }; + const handleOnChangeAreasEnabled = (sel) => { + onSetIntersectionAreasEnabled(sel?.value || ""); + }; + const handleOnToggleHighlightLayers = () => { + onToggleHighlightLayers(); + }; + // confirm modal + const handleConfirmRunProcess = () => { + if (showHighlightLayers) { + onToggleHighlightLayers(); + } + process.actions.runProcessConfirm({ + onShowWarning, + onRunProcess + }); + }; + const handleCloseWarningModal = () => { + onShowWarning(false); + }; + return ( + <> + + + + } + expanded={showAdvancedSettings} + onSwitch={setShowAdvancedSettings}> + + + + + + + + + + + + + + + + + + + + + + + + + + + + }, + {value: "false", label: } + ]} + /> + + + + + + + + + + + } + noResultsText={} onChange={handleOnChangeIntersectionLayer} options={layers.map(f => ({value: f.id, label: f.title || f.name || f.id }))} /> {checkingWPSAvailabilityIntersection ? : - + - - { + return { + value: optionItem.value, + label: getMessageById(messages, optionItem.labelMsgId) + }; + })} /> + + {/* add here new processes */} + {selectedTool === GPT_TOOL_BUFFER ? : null} + {selectedTool === GPT_TOOL_INTERSECTION ? : null} + +
+ + ); + +}; + +MainComp.propTypes = { + selectedTool: PropTypes.string, + runningProcess: PropTypes.bool, + onReset: PropTypes.func, + onSetSelectedTool: PropTypes.func +}; + +MainComp.contextTypes = { + messages: PropTypes.object +}; + +const MainCompConnected = connect( + createSelector( + [ + selectedToolSelector, + runningProcessSelector + ], + ( + selectedTool, + runningProcess + ) => ({ + selectedTool, + runningProcess + })), + { + onReset: reset, + onSetSelectedTool: setSelectedTool + })(MainComp); + +export default MainCompConnected; diff --git a/web/client/plugins/GeoProcessingTools/Panel.jsx b/web/client/plugins/GeoProcessing/Panel.jsx similarity index 79% rename from web/client/plugins/GeoProcessingTools/Panel.jsx rename to web/client/plugins/GeoProcessing/Panel.jsx index 9ee8a5bbc1..daf80eb3da 100644 --- a/web/client/plugins/GeoProcessingTools/Panel.jsx +++ b/web/client/plugins/GeoProcessing/Panel.jsx @@ -13,10 +13,10 @@ import { createSelector } from 'reselect'; import Message from '../../components/I18N/Message'; import BorderLayout from '../../components/layout/BorderLayout'; import ResponsivePanel from "../../components/misc/panels/ResponsivePanel"; -import GeoProcessingToolsMain from './Main'; +import GeoProcessingMain from './Main'; import { toggleControl } from '../../actions/controls'; -import { initPlugin } from '../../actions/geoProcessingTools'; -import { isGeoProcessingToolsEnabledSelector } from '../../selectors/controls'; +import { initPlugin } from '../../actions/geoProcessing'; +import { isGeoProcessingEnabledSelector } from '../../selectors/controls'; import { dockStyleSelector } from '../../selectors/maplayout'; const PanelComp = ({ @@ -34,22 +34,22 @@ const PanelComp = ({ } + title={} onClose={onClose} - glyph="star" + glyph="globe-settings" style={dockStyle} > - + ) : null; @@ -66,7 +66,7 @@ PanelComp.propTypes = { const PanelCompConnected = connect( createSelector( [ - isGeoProcessingToolsEnabledSelector, + isGeoProcessingEnabledSelector, dockStyleSelector ], ( @@ -78,7 +78,7 @@ const PanelCompConnected = connect( })), { onMount: initPlugin, - onClose: toggleControl.bind(null, 'GeoProcessingTools', null) + onClose: toggleControl.bind(null, 'GeoProcessing', null) })(PanelComp); export default PanelCompConnected; diff --git a/web/client/plugins/GeoProcessingTools/SourceLayer.jsx b/web/client/plugins/GeoProcessing/SourceLayer.jsx similarity index 85% rename from web/client/plugins/GeoProcessingTools/SourceLayer.jsx rename to web/client/plugins/GeoProcessing/SourceLayer.jsx index 78deb91f26..141f1f2d8e 100644 --- a/web/client/plugins/GeoProcessingTools/SourceLayer.jsx +++ b/web/client/plugins/GeoProcessing/SourceLayer.jsx @@ -22,12 +22,11 @@ import tooltip from '../../components/misc/enhancers/tooltip'; import Loader from '../../components/misc/Loader'; import { checkWPSAvailability, - runBufferProcess, setSourceLayerId, getFeatures, setSelectedLayerType, setSourceFeatureId -} from '../../actions/geoProcessingTools'; +} from '../../actions/geoProcessing'; import { areAllWPSAvailableForSourceLayerSelector, checkingWPSAvailabilitySelector, @@ -41,7 +40,7 @@ import { isSourceFeaturesLoadingSelector, selectedLayerTypeSelector, wfsBackedLayersSelector -} from '../../selectors/geoProcessingTools'; +} from '../../selectors/geoProcessing'; const Addon = tooltip(InputGroup.Addon); @@ -76,29 +75,29 @@ const Source = ({ const handleOnChangeSourceFeatureId = (sel) => { onSetSourceFeatureId(sel?.value || ""); }; + const isDisableClickSelectFeature = !sourceLayerId || isSourceFeaturesLoading || checkingWPSAvailability; const handleOnClickToSelectSourceFeature = () => { - onSetSelectedLayerType(selectedLayerType === "source" ? "" : "source"); + if (!isDisableClickSelectFeature) { + onSetSelectedLayerType(selectedLayerType === "source" ? "" : "source"); + } }; return (<> - + - - } + noResultsText={} onChange={handleOnChangeSourceFeatureId} options={sourceFeatures.map(f => ({value: f.id, label: f.id }))} value={sourceFeatureId} @@ -136,9 +133,8 @@ const Source = ({ /> {isSourceFeaturesLoading ? : } { + return props.runningProcess || + props.isSourceLayerInvalid || + !(props.sourceLayerId && props.distance && props.areAllWPSAvailableForSourceLayer); + }, + runProcess: (props) => { + if (props.showHighlightLayers) { + props.onToggleHighlightLayers(); + } + if (isEmpty(props.sourceFeature)) { + props.onShowWarning(true); + } else { + props.onRunProcess(GPT_TOOL_BUFFER); + } + }, + runProcessConfirm: (props) => { + props.onShowWarning(false); + props.onRunProcess(GPT_TOOL_BUFFER); + + } + + }, + RunComponent: (props) => { + return (
+ + +
); + }, + ConfirmModal: (props) => { + return (} + fitContent + confirmText={} + cancelText={} + > +
+ +
+
); + } + }, + { + id: GPT_TOOL_INTERSECTION, + optionItem: { + value: GPT_TOOL_INTERSECTION, + labelMsgId: "GeoProcessing.intersectionTool" + }, + actions: { + isRunDisabled: (props) => { + return props.runningProcess || + !(props.isIntersectionEnabled && props.intersectionLayerId && props.sourceLayerId && props.areAllWPSAvailableForSourceLayer && props.areAllWPSAvailableForIntersectionLayer) || + props.isIntersectionLayerInvalid || + props.isSourceLayerInvalid; + }, + runProcess: (props) => { + if (props.showHighlightLayers) { + props.onToggleHighlightLayers(); + } + if (isEmpty(props.sourceFeature) || isEmpty(props.intersectionFeature)) { + props.onShowWarning(true); + } else { + props.onRunProcess(GPT_TOOL_INTERSECTION); + } + }, + runProcessConfirm: (props) => { + props.onShowWarning(false); + props.onRunProcess(GPT_TOOL_INTERSECTION); + + } + }, + RunComponent: (props) => { + return (
+ + +
); + }, + ConfirmModal: (props) => { + return (} + fitContent + confirmText={} + cancelText={} + > +
+ +
+
); + } + } +]; diff --git a/web/client/plugins/GeoProcessingTools/Buffer.jsx b/web/client/plugins/GeoProcessingTools/Buffer.jsx deleted file mode 100644 index 6ab43d3bff..0000000000 --- a/web/client/plugins/GeoProcessingTools/Buffer.jsx +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2023, 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 React, {useState} from 'react'; -import PropTypes from 'prop-types'; -import { - FormGroup, - InputGroup, - ControlLabel -} from 'react-bootstrap'; -import { connect } from 'react-redux'; -import Select from 'react-select'; -import { createSelector } from 'reselect'; - -import Message from '../../components/I18N/Message'; -import FormControl from '../../components/misc/DebouncedFormControl'; -import SwitchPanel from '../../components/misc/switch/SwitchPanel'; -import SourceLayer from './SourceLayer'; -import { - runBufferProcess, - setBufferDistance, - setBufferDistanceUom, - setBufferQuadrantSegments, - setBufferCapStyle -} from '../../actions/geoProcessingTools'; -import { - distanceSelector, - distanceUomSelector, - quadrantSegmentsSelector, - capStyleSelector, - runningProcessSelector -} from '../../selectors/geoProcessingTools'; - -const Buffer = ({ - distance, - distanceUom, - quadrantSegments, - capStyle, - runningProcess, - onSetBufferDistance, - onSetBufferDistanceUom, - onSetBufferQuadrantSegments, - onSetBufferCapStyle -}) => { - const [showBufferAdvancedSettings, setShowBufferAdvancedSettings] = useState(false); - - const handleOnChangeBufferDistance = (val) => { - onSetBufferDistance(val); - }; - const handleOnChangeBufferDistanceUom = (sel) => { - onSetBufferDistanceUom(sel?.value || ""); - }; - const handleOnChangeBufferQuadrantSegments = (val) => { - onSetBufferQuadrantSegments(val); - }; - const handleOnChangeBufferCapStyle = (sel) => { - onSetBufferCapStyle(sel?.value || ""); - }; - return ( - <> - -
-
- - - - - - - - - } - onChange={handleOnChangeBufferCapStyle} - options={[ - {value: "Round", label: }, - {value: "Flat", label: }, - {value: "Square", label: } - ]} /> - - - - ); - -}; - -Buffer.propTypes = { - distance: PropTypes.number, - distanceUom: PropTypes.string, - quadrantSegments: PropTypes.number, - capStyle: PropTypes.string, - runningProcess: PropTypes.bool, - onSetBufferDistance: PropTypes.func, - onSetBufferDistanceUom: PropTypes.func, - onSetBufferQuadrantSegments: PropTypes.func, - onSetBufferCapStyle: PropTypes.func -}; - -const BufferConnected = connect( - createSelector( - [ - distanceSelector, - distanceUomSelector, - quadrantSegmentsSelector, - capStyleSelector, - runningProcessSelector - ], - ( - distance, - distanceUom, - quadrantSegments, - capStyle, - runningProcess - ) => ({ - distance, - distanceUom, - quadrantSegments, - capStyle, - runningProcess - })), - { - onRunBufferProcess: runBufferProcess, - onSetBufferDistance: setBufferDistance, - onSetBufferDistanceUom: setBufferDistanceUom, - onSetBufferQuadrantSegments: setBufferQuadrantSegments, - onSetBufferCapStyle: setBufferCapStyle - })(Buffer); - -export default BufferConnected; diff --git a/web/client/plugins/GeoProcessingTools/Intersection.jsx b/web/client/plugins/GeoProcessingTools/Intersection.jsx deleted file mode 100644 index 92aba0a153..0000000000 --- a/web/client/plugins/GeoProcessingTools/Intersection.jsx +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2023, 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 React, {useState} from 'react'; -import PropTypes from 'prop-types'; -import { - FormGroup, - InputGroup, - ControlLabel -} from 'react-bootstrap'; -import { connect } from 'react-redux'; -import Select from 'react-select'; -import { createSelector } from 'reselect'; - -import Message from '../../components/I18N/Message'; -import FormControl from '../../components/misc/DebouncedFormControl'; -import SwitchPanel from '../../components/misc/switch/SwitchPanel'; -import IntersectionLayer from './IntersectionLayer'; -import SourceLayer from './SourceLayer'; -import { - setIntersectionFirstAttribute, - setIntersectionSecondAttribute, - setIntersectionMode, - setIntersectionPercentagesEnabled, - setIntersectionAreasEnabled -} from '../../actions/geoProcessingTools'; -import { - runningProcessSelector, - firstAttributeToRetainSelector, - secondAttributeToRetainSelector, - intersectionModeSelector, - percentagesEnabledSelector, - areasEnabledSelector -} from '../../selectors/geoProcessingTools'; - -const Intersection = ({ - firstAttributeToRetain, - secondAttributeToRetain, - intersectionMode, - percentagesEnabled, - areasEnabled, - runningProcess, - onSetIntersectionFirstAttribute, - onSetIntersectionSecondAttribute, - onSetIntersectionMode, - onSetIntersectionPercentagesEnabled, - onSetIntersectionAreasEnabled -}) => { - const [showAdvancedSettings, setShowAdvancedSettings] = useState(false); - - const handleOnChangeFirstAttributeToRetain = (val) => { - onSetIntersectionFirstAttribute(val); - }; - const handleOnChangeSecondAttributeToRetain = (val) => { - onSetIntersectionSecondAttribute(val); - }; - const handleOnChangeIntersectionMode = (sel) => { - onSetIntersectionMode(sel?.value || ""); - }; - const handleOnChangePercentagesEnabled = (val) => { - onSetIntersectionPercentagesEnabled(val); - }; - const handleOnChangeAreasEnabled = (val) => { - onSetIntersectionAreasEnabled(val); - }; - return ( - <> - - - - } - expanded={showAdvancedSettings} - onSwitch={setShowAdvancedSettings}> - - - - - - - - - - - - - - - - - - - - - - - - - - - }, - {value: "false", label: } - ]} - /> - - - - - - - - - - {selectedTool === GPT_TOOL_BUFFER ? : null} - {selectedTool === GPT_TOOL_INTERSECTION ? : null} - - - - - - - -
- - : - } - /> - - } - fitContent - confirmText={} - cancelText={} - > -
- -
-
-
-
- - ); - -}; - -MainComp.propTypes = { - areAllWPSAvailableForSourceLayer: PropTypes.bool, - areAllWPSAvailableForIntersectionLayer: PropTypes.bool, - distance: PropTypes.number, - intersectionLayerId: PropTypes.string, - isIntersectionEnabled: PropTypes.bool, - selectedTool: PropTypes.string, - showHighlightLayers: PropTypes.bool, - sourceLayerId: PropTypes.string, - sourceFeature: PropTypes.object, - intersectionFeature: PropTypes.object, - runningProcess: PropTypes.bool, - isIntersectionLayerInvalid: PropTypes.bool, - isSourceLayerInvalid: PropTypes.bool, - onRunBufferProcess: PropTypes.func, - onRunIntersectionProcess: PropTypes.func, - onSetSelectedTool: PropTypes.func, - onToggleHighlightLayers: PropTypes.func -}; - -MainComp.contextTypes = { - messages: PropTypes.object -}; - -const MainCompConnected = connect( - createSelector( - [ - areAllWPSAvailableForSourceLayerSelector, - areAllWPSAvailableForIntersectionLayerSelector, - distanceSelector, - intersectionLayerIdSelector, - isIntersectionEnabledSelector, - selectedToolSelector, - sourceLayerIdSelector, - runningProcessSelector, - showHighlightLayersSelector, - sourceFeatureSelector, - intersectionFeatureSelector, - isIntersectionLayerInvalidSelector, - isSourceLayerInvalidSelector - ], - ( - areAllWPSAvailableForSourceLayer, - areAllWPSAvailableForIntersectionLayer, - distance, - intersectionLayerId, - isIntersectionEnabled, - selectedTool, - sourceLayerId, - runningProcess, - showHighlightLayers, - sourceFeature, - intersectionFeature, - isIntersectionLayerInvalid, - isSourceLayerInvalid - ) => ({ - areAllWPSAvailableForSourceLayer, - areAllWPSAvailableForIntersectionLayer, - distance, - intersectionLayerId, - isIntersectionEnabled, - selectedTool, - sourceLayerId, - runningProcess, - showHighlightLayers, - sourceFeature, - intersectionFeature, - isIntersectionLayerInvalid, - isSourceLayerInvalid - })), - { - onRunBufferProcess: runBufferProcess, - onRunIntersectionProcess: runIntersectionProcess, - onSetSelectedTool: setSelectedTool, - onToggleHighlightLayers: toggleHighlightLayers - })(MainComp); - -export default MainCompConnected; diff --git a/web/client/product/plugins.js b/web/client/product/plugins.js index 80afe96b0f..ceef399b86 100644 --- a/web/client/product/plugins.js +++ b/web/client/product/plugins.js @@ -91,7 +91,7 @@ export const plugins = { GeoStoryImport: toModulePlugin('GeoStoryImport', () => import(/* webpackChunkName: 'plugins/geoStoryImport' */ '../plugins/GeoStoryImport')), DashboardSavePlugin: toModulePlugin('DashboardSave', () => import(/* webpackChunkName: 'plugins/dashboardSave' */ '../plugins/DashboardSave'), { exportedName: 'DashboardSave'}), DashboardSaveAsPlugin: toModulePlugin('DashboardSaveAs', () => import(/* webpackChunkName: 'plugins/dashboardSave' */ '../plugins/DashboardSave'), { exportedName: 'DashboardSaveAs'}), - GeoProcessingTools: toModulePlugin('GeoProcessingTools', () => import(/* webpackChunkName: 'plugins/GeoProcessingTools' */ '../plugins/GeoProcessingTools')), + GeoProcessing: toModulePlugin('GeoProcessing', () => import(/* webpackChunkName: 'plugins/GeoProcessing' */ '../plugins/GeoProcessing')), GeoStoryNavigationPlugin: toModulePlugin('GeoStoryNavigation', () => import(/* webpackChunkName: 'plugins/geoStoryNavigation' */ '../plugins/GeoStoryNavigation')), GroupManagerPlugin: toModulePlugin('GroupManager', () => import(/* webpackChunkName: 'plugins/groupManager' */ '../plugins/manager/GroupManager')), GlobeViewSwitcherPlugin: toModulePlugin('GlobeViewSwitcher', () => import(/* webpackChunkName: 'plugins/globeViewSwitcher' */ '../plugins/GlobeViewSwitcher')), diff --git a/web/client/reducers/__tests__/geoProcessingTools-test.js b/web/client/reducers/__tests__/geoProcessing-test.js similarity index 84% rename from web/client/reducers/__tests__/geoProcessingTools-test.js rename to web/client/reducers/__tests__/geoProcessing-test.js index 3d2dfe2379..f84fc834a3 100644 --- a/web/client/reducers/__tests__/geoProcessingTools-test.js +++ b/web/client/reducers/__tests__/geoProcessing-test.js @@ -8,7 +8,7 @@ import expect from 'expect'; -import geoProcessingTools from '../geoProcessingTools'; +import geoProcessing from '../geoProcessing'; import { checkingWPSAvailability, checkingIntersectionWPSAvailability, @@ -40,25 +40,25 @@ import { setIntersectionAreasEnabled, setSelectedLayerType, toggleHighlightLayers -} from '../../actions/geoProcessingTools'; +} from '../../actions/geoProcessing'; describe('Test Geo Processing Tools reducer', () => { it('CHECKING_WPS_AVAILABILITY', () => { const status = true; const action = checkingWPSAvailability(status); - const state = geoProcessingTools( undefined, action); + const state = geoProcessing( undefined, action); expect(state.flags.checkingWPSAvailability).toEqual(true); }); it('CHECKING_WPS_AVAILABILITY_INTERSECTION', () => { const status = true; const action = checkingIntersectionWPSAvailability(status); - const state = geoProcessingTools( undefined, action); + const state = geoProcessing( undefined, action); expect(state.flags.checkingWPSAvailabilityIntersection).toEqual(true); }); it('ERROR_LOADING_DFT', () => { const layerId = "id"; const action = errorLoadingDFT(layerId); - const state = geoProcessingTools( undefined, action); + const state = geoProcessing( undefined, action); expect(state.errorLoadingDFT[layerId]).toEqual(true); }); it('INIT_PLUGIN', () => { @@ -68,48 +68,48 @@ describe('Test Geo Processing Tools reducer', () => { } }; const action = initPlugin(cfg); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.buffer.distance).toEqual(1234); expect(state.intersection.counter).toEqual(0); }); it('INCREASE_BUFFERED_COUNTER', () => { const action = increaseBufferedCounter(); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.buffer.counter).toEqual(1); }); it('INCREASE_INTERSECT_COUNTER', () => { const action = increaseIntersectedCounter(); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.intersection.counter).toEqual(1); }); it('RUNNING_PROCESS', () => { const status = true; const action = runningProcess(status); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.flags.runningProcess).toEqual(true); }); it('SET_BUFFER_DISTANCE', () => { const distance = "123"; const action = setBufferDistance(distance); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.buffer.distance).toEqual(123); }); it('SET_BUFFER_DISTANCE_UOM', () => { const uom = "m"; const action = setBufferDistanceUom(uom); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.buffer.distanceUom).toEqual(uom); }); it('SET_BUFFER_QUADRANT_SEGMENTS', () => { const quadrantSegments = 100; const action = setBufferQuadrantSegments(quadrantSegments); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.buffer.quadrantSegments).toEqual(quadrantSegments); }); it('SET_BUFFER_CAP_STYLE', () => { const capStyle = "Round"; const action = setBufferCapStyle(capStyle); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.buffer.capStyle).toEqual(capStyle); }); it('SET_FEATURES from empty state', () => { @@ -123,7 +123,7 @@ describe('Test Geo Processing Tools reducer', () => { } }]}; const action = setFeatures(layerId, source, data); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.buffer.features).toEqual([{ geometry: { type: "Feature", @@ -145,7 +145,7 @@ describe('Test Geo Processing Tools reducer', () => { }; const nextPage = 2; const action = setFeatures(layerId, source, data, nextPage); - const state = geoProcessingTools({ + const state = geoProcessing({ source: { features: [{id: 1}] } @@ -164,26 +164,26 @@ describe('Test Geo Processing Tools reducer', () => { const source = "buffer"; const data = {message: "error"}; const action = setFeatures(layerId, source, data); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.buffer.error).toEqual(data); }); it('SET_FEATURE_SOURCE_LOADING', () => { const status = true; const action = setFeatureSourceLoading(status); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.flags.featuresSourceLoading).toEqual(status); }); it('SET_FEATURE_INTERSECTION_LOADING', () => { const status = true; const action = setFeatureIntersectionLoading(status); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.flags.featuresIntersectionLoading).toEqual(status); }); it('SET_INVALID_LAYER', () => { const layerId = "id"; const status = true; const action = setInvalidLayer(layerId, status); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.flags.invalid[layerId]).toEqual(status); }); it('SET_WPS_AVAILABILITY source', () => { @@ -191,7 +191,7 @@ describe('Test Geo Processing Tools reducer', () => { const status = true; const source = "source"; const action = setWPSAvailability(layerId, status, source); - const state = geoProcessingTools({ + const state = geoProcessing({ flags: { wpsAvailability: { layerId: false @@ -206,7 +206,7 @@ describe('Test Geo Processing Tools reducer', () => { const status = true; const source = "intersection"; const action = setWPSAvailability(layerId, status, source); - const state = geoProcessingTools({ + const state = geoProcessing({ flags: { wpsAvailabilityIntersection: { layerId: false @@ -219,28 +219,29 @@ describe('Test Geo Processing Tools reducer', () => { it('SET_SELECTED_TOOL', () => { const tool = "buffer"; const action = setSelectedTool(tool); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.selectedTool).toEqual(tool); }); it('SET_SOURCE_LAYER_ID', () => { const layerId = "id"; const action = setSourceLayerId(layerId); - let state = geoProcessingTools({}, action); - expect(state.selectedLayerId).toEqual(layerId); + let state = geoProcessing({}, action); + expect(state.selectedLayerId).toEqual(undefined); expect(state.source.layerId).toEqual(layerId); expect(state.source.features).toEqual([]); expect(state.source.feature).toEqual(undefined); expect(state.source.featureId).toEqual(""); - state = geoProcessingTools({ + state = geoProcessing({ ...state, + selectedLayerId: "old layer", source: { features: [{type: "Feature"}], feature: {type: "Feature"}, featureId: "ft" } }, setSourceLayerId("layerId")); - expect(state.selectedLayerId).toEqual("layerId"); + expect(state.selectedLayerId).toEqual("old layer"); expect(state.source.layerId).toEqual("layerId"); expect(state.source.features).toEqual([]); expect(state.source.features).toEqual([]); @@ -250,12 +251,12 @@ describe('Test Geo Processing Tools reducer', () => { it('SET_SOURCE_FEATURE_ID', () => { const featureId = "ftId"; const action = setSourceFeatureId(featureId); - const state = geoProcessingTools({}, action); + const state = geoProcessing({}, action); expect(state.source.featureId).toEqual(featureId); }); it('SET_SOURCE_FEATURE_ID clean up', () => { const action = setSourceFeatureId(""); - const state = geoProcessingTools({ + const state = geoProcessing({ source: { totalCount: 40, features: [{type: "Feature"}], @@ -276,7 +277,7 @@ describe('Test Geo Processing Tools reducer', () => { it('SET_SOURCE_FEATURE', () => { const feature = {geometry: {type: "Point"}}; const action = setSourceFeature(feature); - const state = geoProcessingTools({ + const state = geoProcessing({ source: { features: [] }, @@ -292,22 +293,23 @@ describe('Test Geo Processing Tools reducer', () => { it('SET_INTERSECTION_LAYER_ID', () => { const layerId = "id"; const action = setIntersectionLayerId(layerId); - let state = geoProcessingTools({}, action); - expect(state.selectedLayerId).toEqual(layerId); + let state = geoProcessing({}, action); + expect(state.selectedLayerId).toEqual(undefined); expect(state.intersection.layerId).toEqual(layerId); expect(state.intersection.features).toEqual([]); expect(state.intersection.feature).toEqual(undefined); expect(state.intersection.featureId).toEqual(""); - state = geoProcessingTools({ + state = geoProcessing({ ...state, + selectedLayerId: "old layer", intersection: { features: [{type: "Feature"}], feature: {type: "Feature"}, featureId: "ft" } }, setIntersectionLayerId("layerId")); - expect(state.selectedLayerId).toEqual("layerId"); + expect(state.selectedLayerId).toEqual("old layer"); expect(state.intersection.layerId).toEqual("layerId"); expect(state.intersection.features).toEqual([]); expect(state.intersection.feature).toEqual(undefined); @@ -316,12 +318,12 @@ describe('Test Geo Processing Tools reducer', () => { it('SET_INTERSECTION_FEATURE_ID', () => { const featureId = "ftId"; const action = setIntersectionFeatureId(featureId); - const state = geoProcessingTools({}, action); + const state = geoProcessing({}, action); expect(state.intersection.featureId).toEqual(featureId); }); it('SET_INTERSECTION_FEATURE_ID clean up', () => { const action = setIntersectionFeatureId(""); - const state = geoProcessingTools({ + const state = geoProcessing({ intersection: { totalCount: 40, features: [{type: "Feature"}], @@ -342,7 +344,7 @@ describe('Test Geo Processing Tools reducer', () => { it('SET_INTERSECTION_FEATURE', () => { const feature = {geometry: {type: "Point"}}; const action = setIntersectionFeature(feature); - const state = geoProcessingTools({ + const state = geoProcessing({ intersection: { features: [] }, @@ -357,37 +359,37 @@ describe('Test Geo Processing Tools reducer', () => { it('SET_INTERSECTION_FIRST_ATTRIBUTE', () => { const firstAttributeToRetain = "attr"; const action = setIntersectionFirstAttribute(firstAttributeToRetain); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.intersection.firstAttributeToRetain).toEqual(firstAttributeToRetain); }); it('SET_INTERSECTION_SECOND_ATTRIBUTE', () => { const secondAttributeToRetain = "attr"; const action = setIntersectionSecondAttribute(secondAttributeToRetain); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.intersection.secondAttributeToRetain).toEqual(secondAttributeToRetain); }); it('SET_INTERSECTION_MODE', () => { const intersectionMode = ""; const action = setIntersectionMode(intersectionMode); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.intersection.intersectionMode).toEqual(intersectionMode); }); it('SET_INTERSECTION_PERCENTAGES_ENABLED', () => { const percentagesEnabled = true; const action = setIntersectionPercentagesEnabled(percentagesEnabled); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.intersection.percentagesEnabled).toEqual(percentagesEnabled); }); it('SET_INTERSECTION_AREAS_ENABLED', () => { const areasEnabled = true; const action = setIntersectionAreasEnabled(areasEnabled); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.intersection.areasEnabled).toEqual(areasEnabled); }); it('SET_SELECTED_LAYER_TYPE source', () => { const source = "source"; const action = setSelectedLayerType(source); - const state = geoProcessingTools({source: { + const state = geoProcessing({source: { layerId: "layerId" }}, action); expect(state.selectedLayerType).toEqual(source); @@ -396,7 +398,7 @@ describe('Test Geo Processing Tools reducer', () => { it('SET_SELECTED_LAYER_TYPE intersection', () => { const source = "intersection"; const action = setSelectedLayerType(source); - const state = geoProcessingTools({intersection: { + const state = geoProcessing({intersection: { layerId: "layerId" }}, action); expect(state.selectedLayerType).toEqual(source); @@ -404,7 +406,7 @@ describe('Test Geo Processing Tools reducer', () => { }); it('TOGGLE_HIGHLIGHT_LAYERS', () => { const action = toggleHighlightLayers(); - const state = geoProcessingTools(undefined, action); + const state = geoProcessing(undefined, action); expect(state.flags.showHighlightLayers).toEqual(false); }); }); diff --git a/web/client/reducers/geoProcessingTools.js b/web/client/reducers/geoProcessing.js similarity index 88% rename from web/client/reducers/geoProcessingTools.js rename to web/client/reducers/geoProcessing.js index a892776629..d2254da865 100644 --- a/web/client/reducers/geoProcessingTools.js +++ b/web/client/reducers/geoProcessing.js @@ -16,6 +16,7 @@ import { INIT_PLUGIN, INCREASE_BUFFERED_COUNTER, INCREASE_INTERSECT_COUNTER, + RESET, RUNNING_PROCESS, SET_BUFFER_DISTANCE, SET_BUFFER_DISTANCE_UOM, @@ -40,22 +41,28 @@ import { SET_INTERSECTION_AREAS_ENABLED, SET_SELECTED_LAYER_TYPE, TOGGLE_HIGHLIGHT_LAYERS -} from '../actions/geoProcessingTools'; - -import { checkIfIntersectionIsPossible } from '../utils/GeoProcessingToolsUtils'; +} from '../actions/geoProcessing'; +import { + RESET_CONTROLS +} from '../actions/controls'; +import { LOCATION_CHANGE } from 'connected-react-router'; +import { checkIfIntersectionIsPossible } from '../utils/GeoProcessingUtils'; /** - * reducer for geoProcessingTools + * reducer for GeoProcessing * @memberof reducers - * @param {Object} action the action - * @return {Object} the new state + * @param {object} action the action + * @return {object} the new state * */ -function geoProcessingTools( state = { - selectedTool: GPT_TOOL_BUFFER || GPT_TOOL_INTERSECTION, + +const initialState = { + source: {}, buffer: { counter: 0 }, + selectedLayerId: "", + selectedLayerType: "", intersection: { counter: 0, intersectionMode: "INTERSECTION" @@ -65,6 +72,11 @@ function geoProcessingTools( state = { isIntersectionEnabled: true, runningProcess: false } +}; +function geoProcessing( state = { + selectedTool: GPT_TOOL_BUFFER || GPT_TOOL_INTERSECTION, + ...initialState + }, action) { switch (action.type) { case CHECKING_WPS_AVAILABILITY: { @@ -97,6 +109,7 @@ function geoProcessingTools( state = { return { ...state, ...action.cfg, + cfg: action.cfg, buffer: { ...state.buffer, ...(action.cfg.buffer || {}) @@ -125,6 +138,23 @@ function geoProcessingTools( state = { } }; } + case RESET: case RESET_CONTROLS: case LOCATION_CHANGE: { + return { + ...state, + ...initialState, + buffer: { + ...(state.cfg.buffer || {}), + ...initialState.buffer + }, + intersection: { + ...(state.cfg.intersection || {}), + ...initialState.intersection + }, + source: { + ...initialState.source + } + }; + } case RUNNING_PROCESS: { return { ...state, @@ -157,7 +187,7 @@ function geoProcessingTools( state = { ...state, buffer: { ...state.buffer, - quadrantSegments: action.quadrantSegments + quadrantSegments: Number(action.quadrantSegments) } }; } @@ -246,7 +276,8 @@ function geoProcessingTools( state = { case SET_SOURCE_LAYER_ID: { return { ...state, - selectedLayerId: action.layerId, + selectedLayerType: !action.layerId && state.selectedLayerType === "source" ? "" : state.selectedLayerType, + selectedLayerId: state.selectedLayerType === "source" ? action.layerId : state.selectedLayerId, source: { ...state.source, layerId: action.layerId, @@ -287,7 +318,8 @@ function geoProcessingTools( state = { case SET_INTERSECTION_LAYER_ID: { return { ...state, - selectedLayerId: action.layerId, + selectedLayerType: !action.layerId && state.selectedLayerType === "intersection" ? "" : state.selectedLayerType, + selectedLayerId: state.selectedLayerType === "intersection" ? action.layerId : state.selectedLayerId, intersection: { ...state.intersection, layerId: action.layerId, @@ -391,4 +423,4 @@ function geoProcessingTools( state = { } } -export default geoProcessingTools; +export default geoProcessing; diff --git a/web/client/reducers/layers.js b/web/client/reducers/layers.js index a0cf7e09ed..c608e6c7cf 100644 --- a/web/client/reducers/layers.js +++ b/web/client/reducers/layers.js @@ -87,16 +87,16 @@ const moveNode = (groups, node, groupId, newLayers, foreground = true) => { return newGroups; }; -const insertNode = (nodes, node, parent) => { +const insertNode = (nodes, node, parent, asFirst = false) => { if (!parent) { - return [...nodes, node]; + return asFirst ? [node, ...nodes] : [...nodes, node]; } return nodes.map(n => isString(n) ? n : (n.id === parent ? { ...n, nodes: [...n.nodes, node] } : { ...n, - nodes: insertNode(n.nodes, node, parent) + nodes: insertNode(n.nodes, node, parent, asFirst) })); }; @@ -367,14 +367,19 @@ function layers(state = { flat: [] }, action) { } case ADD_GROUP: { const id = uuidv1(); - const newGroups = insertNode(state.groups, { - id: action.parent ? (action.parent + '.' + id) : id, - title: action.group, - name: id, - nodes: [], - expanded: true, - ...action.options - }, action.parent); + const newGroups = insertNode( + state.groups, + { + id: action.parent ? (action.parent + '.' + id) : id, + title: action.group, + name: id, + nodes: [], + expanded: true, + ...action.options + }, + action.parent, + action.asFirst + ); return assign({}, state, { groups: newGroups }); diff --git a/web/client/reducers/maplayout.js b/web/client/reducers/maplayout.js index 925f6dbbda..c4107aee14 100644 --- a/web/client/reducers/maplayout.js +++ b/web/client/reducers/maplayout.js @@ -9,7 +9,7 @@ import {UPDATE_DOCK_PANELS, UPDATE_MAP_LAYOUT} from '../actions/maplayout'; import assign from 'object-assign'; -const DEFAULT_RIGHT_DOCK_PANELS = ['mapCatalog', 'mapTemplates', 'metadataexplorer', 'userExtensions', 'details']; +const DEFAULT_RIGHT_DOCK_PANELS = ['mapCatalog', 'mapTemplates', 'metadataexplorer', 'userExtensions', 'details', 'GeoProcessing']; const DEFAULT_LEFT_DOCK_PANELS = []; /** diff --git a/web/client/selectors/__tests__/controls-test.js b/web/client/selectors/__tests__/controls-test.js index 6f0f131ca3..4ffabf555c 100644 --- a/web/client/selectors/__tests__/controls-test.js +++ b/web/client/selectors/__tests__/controls-test.js @@ -18,7 +18,7 @@ import { showCoordinateEditorSelector, shareSelector, showConfirmDeleteMapModalSelector, - isGeoProcessingToolsEnabledSelector + isGeoProcessingEnabledSelector } from '../controls'; const state = { @@ -107,13 +107,13 @@ describe('Test controls selectors', () => { const showConfirmDelete = showConfirmDeleteMapModalSelector(state); expect(showConfirmDelete).toBe(true); }); - it('isGeoProcessingToolsEnabledSelector', () => { + it('isGeoProcessingEnabledSelector', () => { const controls = { - GeoProcessingTools: { + GeoProcessing: { enabled: true } }; - expect(isGeoProcessingToolsEnabledSelector({ + expect(isGeoProcessingEnabledSelector({ controls })).toEqual(true); }); diff --git a/web/client/selectors/__tests__/geoProcessingTools-test.js b/web/client/selectors/__tests__/geoProcessing-test.js similarity index 69% rename from web/client/selectors/__tests__/geoProcessingTools-test.js rename to web/client/selectors/__tests__/geoProcessing-test.js index 556bc9a071..511d54f9a1 100644 --- a/web/client/selectors/__tests__/geoProcessingTools-test.js +++ b/web/client/selectors/__tests__/geoProcessing-test.js @@ -49,114 +49,114 @@ import { selectedLayerTypeSelector, wfsBackedLayersSelector, maxFeaturesSelector -} from '../geoProcessingTools'; +} from '../geoProcessing'; import { GPT_CONTROL_NAME -} from '../../actions/geoProcessingTools'; +} from '../../actions/geoProcessing'; describe('Test Geo Processing Tools selectors', () => { it('distanceSelector', () => { - const geoProcessingTools = { + const geoProcessing = { buffer: { distance: 123 } }; - expect(distanceSelector({geoProcessingTools})).toEqual(123); + expect(distanceSelector({geoProcessing})).toEqual(123); expect(distanceSelector({})).toEqual(100); }); it('distanceUomSelector', () => { - const geoProcessingTools = { + const geoProcessing = { buffer: { uom: "m" } }; - expect(distanceUomSelector({geoProcessingTools})).toEqual("m"); + expect(distanceUomSelector({geoProcessing})).toEqual("m"); expect(distanceUomSelector()).toEqual("m"); }); it('quadrantSegmentsSelector', () => { - const geoProcessingTools = { + const geoProcessing = { buffer: { quadrantSegments: 123 } }; - expect(quadrantSegmentsSelector({geoProcessingTools})).toEqual(123); + expect(quadrantSegmentsSelector({geoProcessing})).toEqual(123); }); it('capStyleSelector', () => { - const geoProcessingTools = { + const geoProcessing = { buffer: { capStyle: "Round" } }; - expect(capStyleSelector({geoProcessingTools})).toEqual("Round"); + expect(capStyleSelector({geoProcessing})).toEqual("Round"); }); it('bufferedLayersCounterSelector', () => { - const geoProcessingTools = { + const geoProcessing = { buffer: { counter: 1 } }; - expect(bufferedLayersCounterSelector({geoProcessingTools})).toEqual(1); + expect(bufferedLayersCounterSelector({geoProcessing})).toEqual(1); expect(bufferedLayersCounterSelector({})).toEqual(0); }); it('sourceLayerIdSelector', () => { - const geoProcessingTools = { + const geoProcessing = { source: { layerId: 1 } }; - expect(sourceLayerIdSelector({geoProcessingTools})).toEqual(1); + expect(sourceLayerIdSelector({geoProcessing})).toEqual(1); }); it('sourceFeatureIdSelector', () => { - const geoProcessingTools = { + const geoProcessing = { source: { featureId: 1 } }; - expect(sourceFeatureIdSelector({geoProcessingTools})).toEqual(1); + expect(sourceFeatureIdSelector({geoProcessing})).toEqual(1); }); it('sourceFeatureSelector', () => { - const geoProcessingTools = { + const geoProcessing = { source: { feature: { type: "Feature" } } }; - expect(sourceFeatureSelector({geoProcessingTools})).toEqual({ + expect(sourceFeatureSelector({geoProcessing})).toEqual({ type: "Feature" }); }); it('sourceFeaturesSelector', () => { - const geoProcessingTools = { + const geoProcessing = { source: { features: [{ type: "Feature" }] } }; - expect(sourceFeaturesSelector({geoProcessingTools})).toEqual([{ + expect(sourceFeaturesSelector({geoProcessing})).toEqual([{ type: "Feature" }]); }); it('sourceTotalCountSelector', () => { - const geoProcessingTools = { + const geoProcessing = { source: { totalCount: 5 } }; - expect(sourceTotalCountSelector({geoProcessingTools})).toEqual(5); + expect(sourceTotalCountSelector({geoProcessing})).toEqual(5); }); it('sourceCurrentPageSelector', () => { - const geoProcessingTools = { + const geoProcessing = { source: { currentPage: 6 } }; - expect(sourceCurrentPageSelector({geoProcessingTools})).toEqual(6); + expect(sourceCurrentPageSelector({geoProcessing})).toEqual(6); }); it('isSourceLayerInvalidSelector', () => { const layerId = "layerId"; - const geoProcessingTools = { + const geoProcessing = { source: {layerId}, flags: { invalid: { @@ -164,115 +164,115 @@ describe('Test Geo Processing Tools selectors', () => { } } }; - expect(isSourceLayerInvalidSelector({geoProcessingTools})).toEqual(true); + expect(isSourceLayerInvalidSelector({geoProcessing})).toEqual(true); }); it('intersectionLayerIdSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { layerId: 1 } }; - expect(intersectionLayerIdSelector({geoProcessingTools})).toEqual(1); + expect(intersectionLayerIdSelector({geoProcessing})).toEqual(1); }); it('intersectionFeatureIdSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { featureId: 1 } }; - expect(intersectionFeatureIdSelector({geoProcessingTools})).toEqual(1); + expect(intersectionFeatureIdSelector({geoProcessing})).toEqual(1); }); it('intersectionFeatureSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { feature: { type: "Feature" } } }; - expect(intersectionFeatureSelector({geoProcessingTools})).toEqual({ + expect(intersectionFeatureSelector({geoProcessing})).toEqual({ type: "Feature" }); }); it('intersectionFeaturesSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { features: [{ type: "Feature" }] } }; - expect(intersectionFeaturesSelector({geoProcessingTools})).toEqual([{ + expect(intersectionFeaturesSelector({geoProcessing})).toEqual([{ type: "Feature" }]); }); it('intersectionTotalCountSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { totalCount: 2 } }; - expect(intersectionTotalCountSelector({geoProcessingTools})).toEqual(2); + expect(intersectionTotalCountSelector({geoProcessing})).toEqual(2); }); it('intersectionCurrentPageSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { currentPage: 5 } }; - expect(intersectionCurrentPageSelector({geoProcessingTools})).toEqual(5); + expect(intersectionCurrentPageSelector({geoProcessing})).toEqual(5); }); it('intersectedLayersCounterSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { counter: 2 } }; - expect(intersectedLayersCounterSelector({geoProcessingTools})).toEqual(2); + expect(intersectedLayersCounterSelector({geoProcessing})).toEqual(2); }); it('firstAttributeToRetainSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { firstAttributeToRetain: "firstAttributeToRetain" } }; - expect(firstAttributeToRetainSelector({geoProcessingTools})).toEqual("firstAttributeToRetain"); + expect(firstAttributeToRetainSelector({geoProcessing})).toEqual("firstAttributeToRetain"); }); it('secondAttributeToRetainSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { secondAttributeToRetain: "secondAttributeToRetain" } }; - expect(secondAttributeToRetainSelector({geoProcessingTools})).toEqual("secondAttributeToRetain"); + expect(secondAttributeToRetainSelector({geoProcessing})).toEqual("secondAttributeToRetain"); }); it('intersectionModeSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { intersectionMode: "intersectionMode" } }; - expect(intersectionModeSelector({geoProcessingTools})).toEqual("intersectionMode"); + expect(intersectionModeSelector({geoProcessing})).toEqual("intersectionMode"); }); it('percentagesEnabledSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { percentagesEnabled: true } }; - expect(percentagesEnabledSelector({geoProcessingTools})).toEqual(true); + expect(percentagesEnabledSelector({geoProcessing})).toEqual(true); }); it('areasEnabledSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { areasEnabled: true } }; - expect(areasEnabledSelector({geoProcessingTools})).toEqual(true); + expect(areasEnabledSelector({geoProcessing})).toEqual(true); }); it('isIntersectionLayerInvalidSelector', () => { const layerId = "layerId"; - const geoProcessingTools = { + const geoProcessing = { intersection: {layerId}, flags: { invalid: { @@ -280,32 +280,32 @@ describe('Test Geo Processing Tools selectors', () => { } } }; - expect(isIntersectionLayerInvalidSelector({geoProcessingTools})).toEqual(true); + expect(isIntersectionLayerInvalidSelector({geoProcessing})).toEqual(true); }); it('selectedToolSelector', () => { - const geoProcessingTools = { + const geoProcessing = { selectedTool: "buffer" }; - expect(selectedToolSelector({geoProcessingTools})).toEqual("buffer"); + expect(selectedToolSelector({geoProcessing})).toEqual("buffer"); }); it('isSourceFeaturesLoadingSelector', () => { - const geoProcessingTools = { + const geoProcessing = { flags: { featuresSourceLoading: true } }; - expect(isSourceFeaturesLoadingSelector({geoProcessingTools})).toEqual(true); + expect(isSourceFeaturesLoadingSelector({geoProcessing})).toEqual(true); }); it('isIntersectionFeaturesLoadingSelector', () => { - const geoProcessingTools = { + const geoProcessing = { flags: { featuresIntersectionLoading: true } }; - expect(isIntersectionFeaturesLoadingSelector({geoProcessingTools})).toEqual(true); + expect(isIntersectionFeaturesLoadingSelector({geoProcessing})).toEqual(true); }); it('areAllWPSAvailableForSourceLayerSelector', () => { - const geoProcessingTools = { + const geoProcessing = { source: { layerId: "layerId" }, @@ -315,10 +315,10 @@ describe('Test Geo Processing Tools selectors', () => { } } }; - expect(areAllWPSAvailableForSourceLayerSelector({geoProcessingTools})).toEqual(true); + expect(areAllWPSAvailableForSourceLayerSelector({geoProcessing})).toEqual(true); }); it('areAllWPSAvailableForIntersectionLayerSelector', () => { - const geoProcessingTools = { + const geoProcessing = { intersection: { layerId: "layerId" }, @@ -328,47 +328,47 @@ describe('Test Geo Processing Tools selectors', () => { } } }; - expect(areAllWPSAvailableForIntersectionLayerSelector({geoProcessingTools})).toEqual(true); + expect(areAllWPSAvailableForIntersectionLayerSelector({geoProcessing})).toEqual(true); }); it('checkingWPSAvailabilitySelector', () => { - const geoProcessingTools = { + const geoProcessing = { flags: { checkingWPSAvailability: true } }; - expect(checkingWPSAvailabilitySelector({geoProcessingTools})).toEqual(true); + expect(checkingWPSAvailabilitySelector({geoProcessing})).toEqual(true); }); it('checkingWPSAvailabilityIntersectionSelector', () => { - const geoProcessingTools = { + const geoProcessing = { flags: { checkingIntersectionWPSAvailability: true } }; - expect(checkingWPSAvailabilityIntersectionSelector({geoProcessingTools})).toEqual(true); + expect(checkingWPSAvailabilityIntersectionSelector({geoProcessing})).toEqual(true); }); it('isIntersectionEnabledSelector', () => { - const geoProcessingTools = { + const geoProcessing = { flags: { isIntersectionEnabled: true } }; - expect(isIntersectionEnabledSelector({geoProcessingTools})).toEqual(true); + expect(isIntersectionEnabledSelector({geoProcessing})).toEqual(true); }); it('runningProcessSelector', () => { - const geoProcessingTools = { + const geoProcessing = { flags: { runningProcess: true } }; - expect(runningProcessSelector({geoProcessingTools})).toEqual(true); + expect(runningProcessSelector({geoProcessing})).toEqual(true); }); it('showHighlightLayersSelector', () => { - const geoProcessingTools = { + const geoProcessing = { flags: { showHighlightLayers: true } }; - expect(showHighlightLayersSelector({geoProcessingTools})).toEqual(true); + expect(showHighlightLayersSelector({geoProcessing})).toEqual(true); }); it('isListeningClickSelector', () => { const map = { @@ -381,22 +381,22 @@ describe('Test Geo Processing Tools selectors', () => { expect(isListeningClickSelector({map})).toEqual(true); }); it('selectedLayerIdSelector', () => { - const geoProcessingTools = { + const geoProcessing = { selectedLayerId: "layerId" }; - expect(selectedLayerIdSelector({geoProcessingTools})).toEqual("layerId"); + expect(selectedLayerIdSelector({geoProcessing})).toEqual("layerId"); }); it('selectedLayerTypeSelector', () => { - const geoProcessingTools = { + const geoProcessing = { selectedLayerType: "source" }; - expect(selectedLayerTypeSelector({geoProcessingTools})).toEqual("source"); + expect(selectedLayerTypeSelector({geoProcessing})).toEqual("source"); }); it('maxFeaturesSelector', () => { - const geoProcessingTools = { + const geoProcessing = { maxFeatures: 10 }; - expect(maxFeaturesSelector({geoProcessingTools})).toEqual(10); + expect(maxFeaturesSelector({geoProcessing})).toEqual(10); }); it('test wfsBackedLayersSelector', () => { let layers = wfsBackedLayersSelector({}); diff --git a/web/client/selectors/controls.js b/web/client/selectors/controls.js index e618a13a8c..5e9f45ec6a 100644 --- a/web/client/selectors/controls.js +++ b/web/client/selectors/controls.js @@ -34,6 +34,6 @@ export const unsavedMapSelector = (state) => get(state, "controls.unsavedMap.ena export const unsavedMapSourceSelector = (state) => get(state, "controls.unsavedMap.source", ""); export const isIdentifyAvailable = (state) => get(state, "controls.info.available"); export const isLongitudinalProfileEnabledSelector = (state) => get(state, "controls.longitudinalProfile.enabled"); -export const isGeoProcessingToolsEnabledSelector = (state) => get(state, "controls.GeoProcessingTools.enabled", false); +export const isGeoProcessingEnabledSelector = (state) => get(state, "controls.GeoProcessing.enabled", false); export const showConfirmDeleteMapModalSelector = (state) => get(state, "controls.mapDelete.enabled", false); export const burgerMenuSelector = (state) => get(state, "controls.burgermenu.enabled", false); diff --git a/web/client/selectors/geoProcessingTools.js b/web/client/selectors/geoProcessing.js similarity index 60% rename from web/client/selectors/geoProcessingTools.js rename to web/client/selectors/geoProcessing.js index 986d5acec4..1abc03c08c 100644 --- a/web/client/selectors/geoProcessingTools.js +++ b/web/client/selectors/geoProcessing.js @@ -7,68 +7,68 @@ */ import {get} from "lodash"; -import {GPT_CONTROL_NAME} from "../actions/geoProcessingTools"; +import {GPT_CONTROL_NAME} from "../actions/geoProcessing"; import {mapSelector} from "../selectors/map"; import {layersSelector} from "../selectors/layers"; import {hasWFSService} from '../utils/LayersUtils'; // buffer -export const distanceSelector = state => state?.geoProcessingTools?.buffer?.distance || 100; -export const distanceUomSelector = state => state?.geoProcessingTools?.buffer?.distanceUom || "m"; -export const quadrantSegmentsSelector = state => state?.geoProcessingTools?.buffer?.quadrantSegments; -export const capStyleSelector = state => state?.geoProcessingTools?.buffer?.capStyle; -export const bufferedLayersCounterSelector = state => state?.geoProcessingTools?.buffer?.counter ?? 0; +export const distanceSelector = state => state?.geoProcessing?.buffer?.distance || 100; +export const distanceUomSelector = state => state?.geoProcessing?.buffer?.distanceUom || "m"; +export const quadrantSegmentsSelector = state => state?.geoProcessing?.buffer?.quadrantSegments; +export const capStyleSelector = state => state?.geoProcessing?.buffer?.capStyle; +export const bufferedLayersCounterSelector = state => state?.geoProcessing?.buffer?.counter ?? 0; // source -export const sourceLayerIdSelector = state => state?.geoProcessingTools?.source?.layerId; -export const sourceFeatureIdSelector = state => state?.geoProcessingTools?.source?.featureId; -export const sourceFeatureSelector = state => state?.geoProcessingTools?.source?.feature; -export const sourceFeaturesSelector = state => state?.geoProcessingTools?.source?.features || []; -export const sourceTotalCountSelector = state => state?.geoProcessingTools?.source?.totalCount || 0; -export const sourceCurrentPageSelector = state => state?.geoProcessingTools?.source?.currentPage || 0; +export const sourceLayerIdSelector = state => state?.geoProcessing?.source?.layerId; +export const sourceFeatureIdSelector = state => state?.geoProcessing?.source?.featureId; +export const sourceFeatureSelector = state => state?.geoProcessing?.source?.feature; +export const sourceFeaturesSelector = state => state?.geoProcessing?.source?.features || []; +export const sourceTotalCountSelector = state => state?.geoProcessing?.source?.totalCount || 0; +export const sourceCurrentPageSelector = state => state?.geoProcessing?.source?.currentPage || 0; export const isSourceLayerInvalidSelector = state => { const id = sourceLayerIdSelector(state); - return !!state?.geoProcessingTools?.flags?.invalid?.[id]; + return !!state?.geoProcessing?.flags?.invalid?.[id]; }; // intersection -export const intersectionLayerIdSelector = state => state?.geoProcessingTools?.intersection?.layerId; -export const intersectionFeatureIdSelector = state => state?.geoProcessingTools?.intersection?.featureId; -export const intersectionFeatureSelector = state => state?.geoProcessingTools?.intersection?.feature; -export const intersectionFeaturesSelector = state => state?.geoProcessingTools?.intersection?.features || []; -export const intersectionTotalCountSelector = state => state?.geoProcessingTools?.intersection?.totalCount || 0; -export const intersectionCurrentPageSelector = state => state?.geoProcessingTools?.intersection?.currentPage || 0; -export const intersectedLayersCounterSelector = state => state?.geoProcessingTools?.intersection?.counter ?? 0; -export const firstAttributeToRetainSelector = state => state?.geoProcessingTools?.intersection?.firstAttributeToRetain; -export const secondAttributeToRetainSelector = state => state?.geoProcessingTools?.intersection?.secondAttributeToRetain; -export const intersectionModeSelector = state => state?.geoProcessingTools?.intersection?.intersectionMode; -export const percentagesEnabledSelector = state => !!state?.geoProcessingTools?.intersection?.percentagesEnabled; -export const areasEnabledSelector = state => !!state?.geoProcessingTools?.intersection?.areasEnabled; +export const intersectionLayerIdSelector = state => state?.geoProcessing?.intersection?.layerId; +export const intersectionFeatureIdSelector = state => state?.geoProcessing?.intersection?.featureId; +export const intersectionFeatureSelector = state => state?.geoProcessing?.intersection?.feature; +export const intersectionFeaturesSelector = state => state?.geoProcessing?.intersection?.features || []; +export const intersectionTotalCountSelector = state => state?.geoProcessing?.intersection?.totalCount || 0; +export const intersectionCurrentPageSelector = state => state?.geoProcessing?.intersection?.currentPage || 0; +export const intersectedLayersCounterSelector = state => state?.geoProcessing?.intersection?.counter ?? 0; +export const firstAttributeToRetainSelector = state => state?.geoProcessing?.intersection?.firstAttributeToRetain; +export const secondAttributeToRetainSelector = state => state?.geoProcessing?.intersection?.secondAttributeToRetain; +export const intersectionModeSelector = state => state?.geoProcessing?.intersection?.intersectionMode; +export const percentagesEnabledSelector = state => state?.geoProcessing?.intersection?.percentagesEnabled; +export const areasEnabledSelector = state => state?.geoProcessing?.intersection?.areasEnabled; export const isIntersectionLayerInvalidSelector = state => { const id = intersectionLayerIdSelector(state); - return !!state?.geoProcessingTools?.flags?.invalid?.[id]; + return !!state?.geoProcessing?.flags?.invalid?.[id]; }; // flags -export const selectedToolSelector = state => state?.geoProcessingTools?.selectedTool; -export const isSourceFeaturesLoadingSelector = state => state?.geoProcessingTools?.flags?.featuresSourceLoading; -export const isIntersectionFeaturesLoadingSelector = state => state?.geoProcessingTools?.flags?.featuresIntersectionLoading; +export const selectedToolSelector = state => state?.geoProcessing?.selectedTool; +export const isSourceFeaturesLoadingSelector = state => state?.geoProcessing?.flags?.featuresSourceLoading; +export const isIntersectionFeaturesLoadingSelector = state => state?.geoProcessing?.flags?.featuresIntersectionLoading; export const areAllWPSAvailableForSourceLayerSelector = state => { const id = sourceLayerIdSelector(state); - return id ? state?.geoProcessingTools?.flags?.wpsAvailability?.[id] : null; + return id ? state?.geoProcessing?.flags?.wpsAvailability?.[id] : null; }; export const areAllWPSAvailableForIntersectionLayerSelector = state => { const id = intersectionLayerIdSelector(state); - return id ? state?.geoProcessingTools?.flags?.wpsAvailabilityIntersection?.[id] : null; + return id ? state?.geoProcessing?.flags?.wpsAvailabilityIntersection?.[id] : null; }; -export const checkingWPSAvailabilitySelector = state => !!state?.geoProcessingTools?.flags?.checkingWPSAvailability; -export const checkingWPSAvailabilityIntersectionSelector = state => !!state?.geoProcessingTools?.flags?.checkingIntersectionWPSAvailability; -export const isIntersectionEnabledSelector = state => !!state?.geoProcessingTools?.flags?.isIntersectionEnabled; -export const runningProcessSelector = state => !!state?.geoProcessingTools?.flags?.runningProcess; -export const showHighlightLayersSelector = state => !!state?.geoProcessingTools?.flags?.showHighlightLayers; +export const checkingWPSAvailabilitySelector = state => !!state?.geoProcessing?.flags?.checkingWPSAvailability; +export const checkingWPSAvailabilityIntersectionSelector = state => !!state?.geoProcessing?.flags?.checkingIntersectionWPSAvailability; +export const isIntersectionEnabledSelector = state => !!state?.geoProcessing?.flags?.isIntersectionEnabled; +export const runningProcessSelector = state => !!state?.geoProcessing?.flags?.runningProcess; +export const showHighlightLayersSelector = state => !!state?.geoProcessing?.flags?.showHighlightLayers; export const isListeningClickSelector = (state) => !!(get(mapSelector(state), 'eventListeners.click', []).find((el) => el === GPT_CONTROL_NAME)); -export const selectedLayerIdSelector = (state) => state?.geoProcessingTools?.selectedLayerId; -export const selectedLayerTypeSelector = (state) => state?.geoProcessingTools?.selectedLayerType; -export const maxFeaturesSelector = (state) => state?.geoProcessingTools?.maxFeatures || 10; +export const selectedLayerIdSelector = (state) => state?.geoProcessing?.selectedLayerId; +export const selectedLayerTypeSelector = (state) => state?.geoProcessing?.selectedLayerType; +export const maxFeaturesSelector = (state) => state?.geoProcessing?.maxFeatures || 10; export const wfsBackedLayersSelector = (state) => layersSelector(state) .filter(l => l.group !== "background") .filter(hasWFSService); diff --git a/web/client/themes/default/icons.less b/web/client/themes/default/icons.less index 1432f6184b..66c5fc001d 100644 --- a/web/client/themes/default/icons.less +++ b/web/client/themes/default/icons.less @@ -199,202 +199,203 @@ .glyphicon-geometry-collection:before { content: "\f19d"; } .glyphicon-geoserver:before { content: "\f19e"; } .glyphicon-geostory:before { content: "\f19f"; } -.glyphicon-globe:before { content: "\f1a0"; } -.glyphicon-grab-handle:before { content: "\f1a1"; } -.glyphicon-gray-scale:before { content: "\f1a2"; } -.glyphicon-grid-custom:before { content: "\f1a3"; } -.glyphicon-grid-regular:before { content: "\f1a4"; } -.glyphicon-hand-down:before { content: "\f1a5"; } -.glyphicon-hand-left:before { content: "\f1a6"; } -.glyphicon-hand-right:before { content: "\f1a7"; } -.glyphicon-hand-up:before { content: "\f1a8"; } -.glyphicon-hdd:before { content: "\f1a9"; } -.glyphicon-heart:before { content: "\f1aa"; } -.glyphicon-height-auto:before { content: "\f1ab"; } -.glyphicon-height-from-terrain:before { content: "\f1ac"; } -.glyphicon-height-view:before { content: "\f1ad"; } -.glyphicon-hide-marker:before { content: "\f1ae"; } -.glyphicon-home:before { content: "\f1af"; } -.glyphicon-hourglass:before { content: "\f1b0"; } -.glyphicon-import:before { content: "\f1b1"; } -.glyphicon-inbox:before { content: "\f1b2"; } -.glyphicon-info-sign:before { content: "\f1b3"; } -.glyphicon-italic:before { content: "\f1b4"; } -.glyphicon-layer-info:before { content: "\f1b5"; } -.glyphicon-leaf:before { content: "\f1b6"; } -.glyphicon-level-up:before { content: "\f1b7"; } -.glyphicon-line-dash:before { content: "\f1b8"; } -.glyphicon-line-minus:before { content: "\f1b9"; } -.glyphicon-line-plus:before { content: "\f1ba"; } -.glyphicon-line-remove:before { content: "\f1bb"; } -.glyphicon-line-trash:before { content: "\f1bc"; } -.glyphicon-line:before { content: "\f1bd"; } -.glyphicon-link:before { content: "\f1be"; } -.glyphicon-list-alt:before { content: "\f1bf"; } -.glyphicon-list:before { content: "\f1c0"; } -.glyphicon-lock:before { content: "\f1c1"; } -.glyphicon-log-in:before { content: "\f1c2"; } -.glyphicon-log-out:before { content: "\f1c3"; } -.glyphicon-loop:before { content: "\f1c4"; } -.glyphicon-magnet:before { content: "\f1c5"; } -.glyphicon-map-context:before { content: "\f1c6"; } -.glyphicon-map-edit:before { content: "\f1c7"; } -.glyphicon-map-filter:before { content: "\f1c8"; } -.glyphicon-map-marker:before { content: "\f1c9"; } -.glyphicon-map-synch:before { content: "\f1ca"; } -.glyphicon-map-view:before { content: "\f1cb"; } -.glyphicon-maps-catalog:before { content: "\f1cc"; } -.glyphicon-menu-hamburger:before { content: "\f1cd"; } -.glyphicon-minus-sign:before { content: "\f1ce"; } -.glyphicon-minus:before { content: "\f1cf"; } -.glyphicon-model-plus:before { content: "\f1d0"; } -.glyphicon-model:before { content: "\f1d1"; } -.glyphicon-mouse:before { content: "\f1d2"; } -.glyphicon-move-row-after:before { content: "\f1d3"; } -.glyphicon-move-row-before:before { content: "\f1d4"; } -.glyphicon-move:before { content: "\f1d5"; } -.glyphicon-muted:before { content: "\f1d6"; } -.glyphicon-new-window:before { content: "\f1d7"; } -.glyphicon-next:before { content: "\f1d8"; } -.glyphicon-off:before { content: "\f1d9"; } -.glyphicon-ok-circle:before { content: "\f1da"; } -.glyphicon-ok-sign:before { content: "\f1db"; } -.glyphicon-ok:before { content: "\f1dc"; } -.glyphicon-open:before { content: "\f1dd"; } -.glyphicon-option-horizontal:before { content: "\f1de"; } -.glyphicon-option-vertical:before { content: "\f1df"; } -.glyphicon-paperclip:before { content: "\f1e0"; } -.glyphicon-paste:before { content: "\f1e1"; } -.glyphicon-pause:before { content: "\f1e2"; } -.glyphicon-pencil-add:before { content: "\f1e3"; } -.glyphicon-pencil-edit:before { content: "\f1e4"; } -.glyphicon-pencil:before { content: "\f1e5"; } -.glyphicon-phone:before { content: "\f1e6"; } -.glyphicon-picture:before { content: "\f1e7"; } -.glyphicon-pie-chart:before { content: "\f1e8"; } -.glyphicon-plane:before { content: "\f1e9"; } -.glyphicon-play-circle:before { content: "\f1ea"; } -.glyphicon-play:before { content: "\f1eb"; } -.glyphicon-playback:before { content: "\f1ec"; } -.glyphicon-plug:before { content: "\f1ed"; } -.glyphicon-plus-sign:before { content: "\f1ee"; } -.glyphicon-plus-square:before { content: "\f1ef"; } -.glyphicon-plus:before { content: "\f1f0"; } -.glyphicon-point-coordinates:before { content: "\f1f1"; } -.glyphicon-point-dash:before { content: "\f1f2"; } -.glyphicon-point-minus:before { content: "\f1f3"; } -.glyphicon-point-plus:before { content: "\f1f4"; } -.glyphicon-point-remove:before { content: "\f1f5"; } -.glyphicon-point-trash:before { content: "\f1f6"; } -.glyphicon-point:before { content: "\f1f7"; } -.glyphicon-polygon-3d:before { content: "\f1f8"; } -.glyphicon-polygon-dash:before { content: "\f1f9"; } -.glyphicon-polygon-minus:before { content: "\f1fa"; } -.glyphicon-polygon-plus:before { content: "\f1fb"; } -.glyphicon-polygon-remove:before { content: "\f1fc"; } -.glyphicon-polygon-trash:before { content: "\f1fd"; } -.glyphicon-polygon:before { content: "\f1fe"; } -.glyphicon-polyline-3d:before { content: "\f1ff"; } -.glyphicon-polyline-dash:before { content: "\f200"; } -.glyphicon-polyline-minus:before { content: "\f201"; } -.glyphicon-polyline-plus:before { content: "\f202"; } -.glyphicon-polyline-remove:before { content: "\f203"; } -.glyphicon-polyline-trash:before { content: "\f204"; } -.glyphicon-polyline:before { content: "\f205"; } -.glyphicon-preview:before { content: "\f206"; } -.glyphicon-print:before { content: "\f207"; } -.glyphicon-pushpin:before { content: "\f208"; } -.glyphicon-qrcode:before { content: "\f209"; } -.glyphicon-question-sign:before { content: "\f20a"; } -.glyphicon-random:before { content: "\f20b"; } -.glyphicon-range-end:before { content: "\f20c"; } -.glyphicon-range-start:before { content: "\f20d"; } -.glyphicon-record:before { content: "\f20e"; } -.glyphicon-redo:before { content: "\f20f"; } -.glyphicon-refresh:before { content: "\f210"; } -.glyphicon-remove-circle:before { content: "\f211"; } -.glyphicon-remove-sign:before { content: "\f212"; } -.glyphicon-remove-square:before { content: "\f213"; } -.glyphicon-remove:before { content: "\f214"; } -.glyphicon-repeat:before { content: "\f215"; } -.glyphicon-resize-full:before { content: "\f216"; } -.glyphicon-resize-horizontal:before { content: "\f217"; } -.glyphicon-resize-small:before { content: "\f218"; } -.glyphicon-resize-vertical:before { content: "\f219"; } -.glyphicon-retweet:before { content: "\f21a"; } -.glyphicon-rgb:before { content: "\f21b"; } -.glyphicon-road:before { content: "\f21c"; } -.glyphicon-row-add:before { content: "\f21d"; } -.glyphicon-row-trash:before { content: "\f21e"; } -.glyphicon-save:before { content: "\f21f"; } -.glyphicon-saved:before { content: "\f220"; } -.glyphicon-scissors:before { content: "\f221"; } -.glyphicon-screenshot:before { content: "\f222"; } -.glyphicon-search-coords:before { content: "\f223"; } -.glyphicon-search:before { content: "\f224"; } -.glyphicon-send:before { content: "\f225"; } -.glyphicon-share-alt:before { content: "\f226"; } -.glyphicon-share:before { content: "\f227"; } -.glyphicon-sheet:before { content: "\f228"; } -.glyphicon-shopping-cart:before { content: "\f229"; } -.glyphicon-signal:before { content: "\f22a"; } -.glyphicon-size-extra-large:before { content: "\f22b"; } -.glyphicon-size-large:before { content: "\f22c"; } -.glyphicon-size-medium:before { content: "\f22d"; } -.glyphicon-size-small:before { content: "\f22e"; } -.glyphicon-slope:before { content: "\f22f"; } -.glyphicon-sort-by-alphabet-alt:before { content: "\f230"; } -.glyphicon-sort-by-alphabet:before { content: "\f231"; } -.glyphicon-sort-by-attributes-alt:before { content: "\f232"; } -.glyphicon-sort-by-attributes:before { content: "\f233"; } -.glyphicon-sort:before { content: "\f234"; } -.glyphicon-star-empty:before { content: "\f235"; } -.glyphicon-star:before { content: "\f236"; } -.glyphicon-stats:before { content: "\f237"; } -.glyphicon-step-backward:before { content: "\f238"; } -.glyphicon-step-forward:before { content: "\f239"; } -.glyphicon-stop:before { content: "\f23a"; } -.glyphicon-story-banner-section:before { content: "\f23b"; } -.glyphicon-story-carousel-section:before { content: "\f23c"; } -.glyphicon-story-immersive-content:before { content: "\f23d"; } -.glyphicon-story-immersive-section:before { content: "\f23e"; } -.glyphicon-story-media-section:before { content: "\f23f"; } -.glyphicon-story-paragraph-section:before { content: "\f240"; } -.glyphicon-story-title-section:before { content: "\f241"; } -.glyphicon-story-webpage-section:before { content: "\f242"; } -.glyphicon-tag:before { content: "\f243"; } -.glyphicon-tags:before { content: "\f244"; } -.glyphicon-tasks:before { content: "\f245"; } -.glyphicon-text-background:before { content: "\f246"; } -.glyphicon-text-colour:before { content: "\f247"; } -.glyphicon-text-height:before { content: "\f248"; } -.glyphicon-text-width:before { content: "\f249"; } -.glyphicon-th-large:before { content: "\f24a"; } -.glyphicon-th-list:before { content: "\f24b"; } -.glyphicon-th:before { content: "\f24c"; } -.glyphicon-thumbs-down:before { content: "\f24d"; } -.glyphicon-thumbs-up:before { content: "\f24e"; } -.glyphicon-time-current:before { content: "\f24f"; } -.glyphicon-time-offset:before { content: "\f250"; } -.glyphicon-time:before { content: "\f251"; } -.glyphicon-tint:before { content: "\f252"; } -.glyphicon-transfer:before { content: "\f253"; } -.glyphicon-trash-square:before { content: "\f254"; } -.glyphicon-trash:before { content: "\f255"; } -.glyphicon-unchecked:before { content: "\f256"; } -.glyphicon-undo:before { content: "\f257"; } -.glyphicon-unplug:before { content: "\f258"; } -.glyphicon-upload:before { content: "\f259"; } -.glyphicon-usd:before { content: "\f25a"; } -.glyphicon-user:before { content: "\f25b"; } -.glyphicon-vert-dashed:before { content: "\f25c"; } -.glyphicon-viewport-filter:before { content: "\f25d"; } -.glyphicon-warning-sign:before { content: "\f25e"; } -.glyphicon-webpage:before { content: "\f25f"; } -.glyphicon-wrench:before { content: "\f260"; } -.glyphicon-zoom-in:before { content: "\f261"; } -.glyphicon-zoom-out:before { content: "\f262"; } -.glyphicon-zoom-to:before { content: "\f263"; } +.glyphicon-globe-settings:before { content: "\f1a0"; } +.glyphicon-globe:before { content: "\f1a1"; } +.glyphicon-grab-handle:before { content: "\f1a2"; } +.glyphicon-gray-scale:before { content: "\f1a3"; } +.glyphicon-grid-custom:before { content: "\f1a4"; } +.glyphicon-grid-regular:before { content: "\f1a5"; } +.glyphicon-hand-down:before { content: "\f1a6"; } +.glyphicon-hand-left:before { content: "\f1a7"; } +.glyphicon-hand-right:before { content: "\f1a8"; } +.glyphicon-hand-up:before { content: "\f1a9"; } +.glyphicon-hdd:before { content: "\f1aa"; } +.glyphicon-heart:before { content: "\f1ab"; } +.glyphicon-height-auto:before { content: "\f1ac"; } +.glyphicon-height-from-terrain:before { content: "\f1ad"; } +.glyphicon-height-view:before { content: "\f1ae"; } +.glyphicon-hide-marker:before { content: "\f1af"; } +.glyphicon-home:before { content: "\f1b0"; } +.glyphicon-hourglass:before { content: "\f1b1"; } +.glyphicon-import:before { content: "\f1b2"; } +.glyphicon-inbox:before { content: "\f1b3"; } +.glyphicon-info-sign:before { content: "\f1b4"; } +.glyphicon-italic:before { content: "\f1b5"; } +.glyphicon-layer-info:before { content: "\f1b6"; } +.glyphicon-leaf:before { content: "\f1b7"; } +.glyphicon-level-up:before { content: "\f1b8"; } +.glyphicon-line-dash:before { content: "\f1b9"; } +.glyphicon-line-minus:before { content: "\f1ba"; } +.glyphicon-line-plus:before { content: "\f1bb"; } +.glyphicon-line-remove:before { content: "\f1bc"; } +.glyphicon-line-trash:before { content: "\f1bd"; } +.glyphicon-line:before { content: "\f1be"; } +.glyphicon-link:before { content: "\f1bf"; } +.glyphicon-list-alt:before { content: "\f1c0"; } +.glyphicon-list:before { content: "\f1c1"; } +.glyphicon-lock:before { content: "\f1c2"; } +.glyphicon-log-in:before { content: "\f1c3"; } +.glyphicon-log-out:before { content: "\f1c4"; } +.glyphicon-loop:before { content: "\f1c5"; } +.glyphicon-magnet:before { content: "\f1c6"; } +.glyphicon-map-context:before { content: "\f1c7"; } +.glyphicon-map-edit:before { content: "\f1c8"; } +.glyphicon-map-filter:before { content: "\f1c9"; } +.glyphicon-map-marker:before { content: "\f1ca"; } +.glyphicon-map-synch:before { content: "\f1cb"; } +.glyphicon-map-view:before { content: "\f1cc"; } +.glyphicon-maps-catalog:before { content: "\f1cd"; } +.glyphicon-menu-hamburger:before { content: "\f1ce"; } +.glyphicon-minus-sign:before { content: "\f1cf"; } +.glyphicon-minus:before { content: "\f1d0"; } +.glyphicon-model-plus:before { content: "\f1d1"; } +.glyphicon-model:before { content: "\f1d2"; } +.glyphicon-mouse:before { content: "\f1d3"; } +.glyphicon-move-row-after:before { content: "\f1d4"; } +.glyphicon-move-row-before:before { content: "\f1d5"; } +.glyphicon-move:before { content: "\f1d6"; } +.glyphicon-muted:before { content: "\f1d7"; } +.glyphicon-new-window:before { content: "\f1d8"; } +.glyphicon-next:before { content: "\f1d9"; } +.glyphicon-off:before { content: "\f1da"; } +.glyphicon-ok-circle:before { content: "\f1db"; } +.glyphicon-ok-sign:before { content: "\f1dc"; } +.glyphicon-ok:before { content: "\f1dd"; } +.glyphicon-open:before { content: "\f1de"; } +.glyphicon-option-horizontal:before { content: "\f1df"; } +.glyphicon-option-vertical:before { content: "\f1e0"; } +.glyphicon-paperclip:before { content: "\f1e1"; } +.glyphicon-paste:before { content: "\f1e2"; } +.glyphicon-pause:before { content: "\f1e3"; } +.glyphicon-pencil-add:before { content: "\f1e4"; } +.glyphicon-pencil-edit:before { content: "\f1e5"; } +.glyphicon-pencil:before { content: "\f1e6"; } +.glyphicon-phone:before { content: "\f1e7"; } +.glyphicon-picture:before { content: "\f1e8"; } +.glyphicon-pie-chart:before { content: "\f1e9"; } +.glyphicon-plane:before { content: "\f1ea"; } +.glyphicon-play-circle:before { content: "\f1eb"; } +.glyphicon-play:before { content: "\f1ec"; } +.glyphicon-playback:before { content: "\f1ed"; } +.glyphicon-plug:before { content: "\f1ee"; } +.glyphicon-plus-sign:before { content: "\f1ef"; } +.glyphicon-plus-square:before { content: "\f1f0"; } +.glyphicon-plus:before { content: "\f1f1"; } +.glyphicon-point-coordinates:before { content: "\f1f2"; } +.glyphicon-point-dash:before { content: "\f1f3"; } +.glyphicon-point-minus:before { content: "\f1f4"; } +.glyphicon-point-plus:before { content: "\f1f5"; } +.glyphicon-point-remove:before { content: "\f1f6"; } +.glyphicon-point-trash:before { content: "\f1f7"; } +.glyphicon-point:before { content: "\f1f8"; } +.glyphicon-polygon-3d:before { content: "\f1f9"; } +.glyphicon-polygon-dash:before { content: "\f1fa"; } +.glyphicon-polygon-minus:before { content: "\f1fb"; } +.glyphicon-polygon-plus:before { content: "\f1fc"; } +.glyphicon-polygon-remove:before { content: "\f1fd"; } +.glyphicon-polygon-trash:before { content: "\f1fe"; } +.glyphicon-polygon:before { content: "\f1ff"; } +.glyphicon-polyline-3d:before { content: "\f200"; } +.glyphicon-polyline-dash:before { content: "\f201"; } +.glyphicon-polyline-minus:before { content: "\f202"; } +.glyphicon-polyline-plus:before { content: "\f203"; } +.glyphicon-polyline-remove:before { content: "\f204"; } +.glyphicon-polyline-trash:before { content: "\f205"; } +.glyphicon-polyline:before { content: "\f206"; } +.glyphicon-preview:before { content: "\f207"; } +.glyphicon-print:before { content: "\f208"; } +.glyphicon-pushpin:before { content: "\f209"; } +.glyphicon-qrcode:before { content: "\f20a"; } +.glyphicon-question-sign:before { content: "\f20b"; } +.glyphicon-random:before { content: "\f20c"; } +.glyphicon-range-end:before { content: "\f20d"; } +.glyphicon-range-start:before { content: "\f20e"; } +.glyphicon-record:before { content: "\f20f"; } +.glyphicon-redo:before { content: "\f210"; } +.glyphicon-refresh:before { content: "\f211"; } +.glyphicon-remove-circle:before { content: "\f212"; } +.glyphicon-remove-sign:before { content: "\f213"; } +.glyphicon-remove-square:before { content: "\f214"; } +.glyphicon-remove:before { content: "\f215"; } +.glyphicon-repeat:before { content: "\f216"; } +.glyphicon-resize-full:before { content: "\f217"; } +.glyphicon-resize-horizontal:before { content: "\f218"; } +.glyphicon-resize-small:before { content: "\f219"; } +.glyphicon-resize-vertical:before { content: "\f21a"; } +.glyphicon-retweet:before { content: "\f21b"; } +.glyphicon-rgb:before { content: "\f21c"; } +.glyphicon-road:before { content: "\f21d"; } +.glyphicon-row-add:before { content: "\f21e"; } +.glyphicon-row-trash:before { content: "\f21f"; } +.glyphicon-save:before { content: "\f220"; } +.glyphicon-saved:before { content: "\f221"; } +.glyphicon-scissors:before { content: "\f222"; } +.glyphicon-screenshot:before { content: "\f223"; } +.glyphicon-search-coords:before { content: "\f224"; } +.glyphicon-search:before { content: "\f225"; } +.glyphicon-send:before { content: "\f226"; } +.glyphicon-share-alt:before { content: "\f227"; } +.glyphicon-share:before { content: "\f228"; } +.glyphicon-sheet:before { content: "\f229"; } +.glyphicon-shopping-cart:before { content: "\f22a"; } +.glyphicon-signal:before { content: "\f22b"; } +.glyphicon-size-extra-large:before { content: "\f22c"; } +.glyphicon-size-large:before { content: "\f22d"; } +.glyphicon-size-medium:before { content: "\f22e"; } +.glyphicon-size-small:before { content: "\f22f"; } +.glyphicon-slope:before { content: "\f230"; } +.glyphicon-sort-by-alphabet-alt:before { content: "\f231"; } +.glyphicon-sort-by-alphabet:before { content: "\f232"; } +.glyphicon-sort-by-attributes-alt:before { content: "\f233"; } +.glyphicon-sort-by-attributes:before { content: "\f234"; } +.glyphicon-sort:before { content: "\f235"; } +.glyphicon-star-empty:before { content: "\f236"; } +.glyphicon-star:before { content: "\f237"; } +.glyphicon-stats:before { content: "\f238"; } +.glyphicon-step-backward:before { content: "\f239"; } +.glyphicon-step-forward:before { content: "\f23a"; } +.glyphicon-stop:before { content: "\f23b"; } +.glyphicon-story-banner-section:before { content: "\f23c"; } +.glyphicon-story-carousel-section:before { content: "\f23d"; } +.glyphicon-story-immersive-content:before { content: "\f23e"; } +.glyphicon-story-immersive-section:before { content: "\f23f"; } +.glyphicon-story-media-section:before { content: "\f240"; } +.glyphicon-story-paragraph-section:before { content: "\f241"; } +.glyphicon-story-title-section:before { content: "\f242"; } +.glyphicon-story-webpage-section:before { content: "\f243"; } +.glyphicon-tag:before { content: "\f244"; } +.glyphicon-tags:before { content: "\f245"; } +.glyphicon-tasks:before { content: "\f246"; } +.glyphicon-text-background:before { content: "\f247"; } +.glyphicon-text-colour:before { content: "\f248"; } +.glyphicon-text-height:before { content: "\f249"; } +.glyphicon-text-width:before { content: "\f24a"; } +.glyphicon-th-large:before { content: "\f24b"; } +.glyphicon-th-list:before { content: "\f24c"; } +.glyphicon-th:before { content: "\f24d"; } +.glyphicon-thumbs-down:before { content: "\f24e"; } +.glyphicon-thumbs-up:before { content: "\f24f"; } +.glyphicon-time-current:before { content: "\f250"; } +.glyphicon-time-offset:before { content: "\f251"; } +.glyphicon-time:before { content: "\f252"; } +.glyphicon-tint:before { content: "\f253"; } +.glyphicon-transfer:before { content: "\f254"; } +.glyphicon-trash-square:before { content: "\f255"; } +.glyphicon-trash:before { content: "\f256"; } +.glyphicon-unchecked:before { content: "\f257"; } +.glyphicon-undo:before { content: "\f258"; } +.glyphicon-unplug:before { content: "\f259"; } +.glyphicon-upload:before { content: "\f25a"; } +.glyphicon-usd:before { content: "\f25b"; } +.glyphicon-user:before { content: "\f25c"; } +.glyphicon-vert-dashed:before { content: "\f25d"; } +.glyphicon-viewport-filter:before { content: "\f25e"; } +.glyphicon-warning-sign:before { content: "\f25f"; } +.glyphicon-webpage:before { content: "\f260"; } +.glyphicon-wrench:before { content: "\f261"; } +.glyphicon-zoom-in:before { content: "\f262"; } +.glyphicon-zoom-out:before { content: "\f263"; } +.glyphicon-zoom-to:before { content: "\f264"; } /* classes with icon code @@ -560,199 +561,200 @@ structure .glyphicon-{iconName}-content .glyphicon-geometry-collection-content { content: "\f19d"; } .glyphicon-geoserver-content { content: "\f19e"; } .glyphicon-geostory-content { content: "\f19f"; } -.glyphicon-globe-content { content: "\f1a0"; } -.glyphicon-grab-handle-content { content: "\f1a1"; } -.glyphicon-gray-scale-content { content: "\f1a2"; } -.glyphicon-grid-custom-content { content: "\f1a3"; } -.glyphicon-grid-regular-content { content: "\f1a4"; } -.glyphicon-hand-down-content { content: "\f1a5"; } -.glyphicon-hand-left-content { content: "\f1a6"; } -.glyphicon-hand-right-content { content: "\f1a7"; } -.glyphicon-hand-up-content { content: "\f1a8"; } -.glyphicon-hdd-content { content: "\f1a9"; } -.glyphicon-heart-content { content: "\f1aa"; } -.glyphicon-height-auto-content { content: "\f1ab"; } -.glyphicon-height-from-terrain-content { content: "\f1ac"; } -.glyphicon-height-view-content { content: "\f1ad"; } -.glyphicon-hide-marker-content { content: "\f1ae"; } -.glyphicon-home-content { content: "\f1af"; } -.glyphicon-hourglass-content { content: "\f1b0"; } -.glyphicon-import-content { content: "\f1b1"; } -.glyphicon-inbox-content { content: "\f1b2"; } -.glyphicon-info-sign-content { content: "\f1b3"; } -.glyphicon-italic-content { content: "\f1b4"; } -.glyphicon-layer-info-content { content: "\f1b5"; } -.glyphicon-leaf-content { content: "\f1b6"; } -.glyphicon-level-up-content { content: "\f1b7"; } -.glyphicon-line-dash-content { content: "\f1b8"; } -.glyphicon-line-minus-content { content: "\f1b9"; } -.glyphicon-line-plus-content { content: "\f1ba"; } -.glyphicon-line-remove-content { content: "\f1bb"; } -.glyphicon-line-trash-content { content: "\f1bc"; } -.glyphicon-line-content { content: "\f1bd"; } -.glyphicon-link-content { content: "\f1be"; } -.glyphicon-list-alt-content { content: "\f1bf"; } -.glyphicon-list-content { content: "\f1c0"; } -.glyphicon-lock-content { content: "\f1c1"; } -.glyphicon-log-in-content { content: "\f1c2"; } -.glyphicon-log-out-content { content: "\f1c3"; } -.glyphicon-loop-content { content: "\f1c4"; } -.glyphicon-magnet-content { content: "\f1c5"; } -.glyphicon-map-context-content { content: "\f1c6"; } -.glyphicon-map-edit-content { content: "\f1c7"; } -.glyphicon-map-filter-content { content: "\f1c8"; } -.glyphicon-map-marker-content { content: "\f1c9"; } -.glyphicon-map-synch-content { content: "\f1ca"; } -.glyphicon-map-view-content { content: "\f1cb"; } -.glyphicon-maps-catalog-content { content: "\f1cc"; } -.glyphicon-menu-hamburger-content { content: "\f1cd"; } -.glyphicon-minus-sign-content { content: "\f1ce"; } -.glyphicon-minus-content { content: "\f1cf"; } -.glyphicon-model-plus-content { content: "\f1d0"; } -.glyphicon-model-content { content: "\f1d1"; } -.glyphicon-mouse-content { content: "\f1d2"; } -.glyphicon-move-row-after-content { content: "\f1d3"; } -.glyphicon-move-row-before-content { content: "\f1d4"; } -.glyphicon-move-content { content: "\f1d5"; } -.glyphicon-muted-content { content: "\f1d6"; } -.glyphicon-new-window-content { content: "\f1d7"; } -.glyphicon-next-content { content: "\f1d8"; } -.glyphicon-off-content { content: "\f1d9"; } -.glyphicon-ok-circle-content { content: "\f1da"; } -.glyphicon-ok-sign-content { content: "\f1db"; } -.glyphicon-ok-content { content: "\f1dc"; } -.glyphicon-open-content { content: "\f1dd"; } -.glyphicon-option-horizontal-content { content: "\f1de"; } -.glyphicon-option-vertical-content { content: "\f1df"; } -.glyphicon-paperclip-content { content: "\f1e0"; } -.glyphicon-paste-content { content: "\f1e1"; } -.glyphicon-pause-content { content: "\f1e2"; } -.glyphicon-pencil-add-content { content: "\f1e3"; } -.glyphicon-pencil-edit-content { content: "\f1e4"; } -.glyphicon-pencil-content { content: "\f1e5"; } -.glyphicon-phone-content { content: "\f1e6"; } -.glyphicon-picture-content { content: "\f1e7"; } -.glyphicon-pie-chart-content { content: "\f1e8"; } -.glyphicon-plane-content { content: "\f1e9"; } -.glyphicon-play-circle-content { content: "\f1ea"; } -.glyphicon-play-content { content: "\f1eb"; } -.glyphicon-playback-content { content: "\f1ec"; } -.glyphicon-plug-content { content: "\f1ed"; } -.glyphicon-plus-sign-content { content: "\f1ee"; } -.glyphicon-plus-square-content { content: "\f1ef"; } -.glyphicon-plus-content { content: "\f1f0"; } -.glyphicon-point-coordinates-content { content: "\f1f1"; } -.glyphicon-point-dash-content { content: "\f1f2"; } -.glyphicon-point-minus-content { content: "\f1f3"; } -.glyphicon-point-plus-content { content: "\f1f4"; } -.glyphicon-point-remove-content { content: "\f1f5"; } -.glyphicon-point-trash-content { content: "\f1f6"; } -.glyphicon-point-content { content: "\f1f7"; } -.glyphicon-polygon-3d-content { content: "\f1f8"; } -.glyphicon-polygon-dash-content { content: "\f1f9"; } -.glyphicon-polygon-minus-content { content: "\f1fa"; } -.glyphicon-polygon-plus-content { content: "\f1fb"; } -.glyphicon-polygon-remove-content { content: "\f1fc"; } -.glyphicon-polygon-trash-content { content: "\f1fd"; } -.glyphicon-polygon-content { content: "\f1fe"; } -.glyphicon-polyline-3d-content { content: "\f1ff"; } -.glyphicon-polyline-dash-content { content: "\f200"; } -.glyphicon-polyline-minus-content { content: "\f201"; } -.glyphicon-polyline-plus-content { content: "\f202"; } -.glyphicon-polyline-remove-content { content: "\f203"; } -.glyphicon-polyline-trash-content { content: "\f204"; } -.glyphicon-polyline-content { content: "\f205"; } -.glyphicon-preview-content { content: "\f206"; } -.glyphicon-print-content { content: "\f207"; } -.glyphicon-pushpin-content { content: "\f208"; } -.glyphicon-qrcode-content { content: "\f209"; } -.glyphicon-question-sign-content { content: "\f20a"; } -.glyphicon-random-content { content: "\f20b"; } -.glyphicon-range-end-content { content: "\f20c"; } -.glyphicon-range-start-content { content: "\f20d"; } -.glyphicon-record-content { content: "\f20e"; } -.glyphicon-redo-content { content: "\f20f"; } -.glyphicon-refresh-content { content: "\f210"; } -.glyphicon-remove-circle-content { content: "\f211"; } -.glyphicon-remove-sign-content { content: "\f212"; } -.glyphicon-remove-square-content { content: "\f213"; } -.glyphicon-remove-content { content: "\f214"; } -.glyphicon-repeat-content { content: "\f215"; } -.glyphicon-resize-full-content { content: "\f216"; } -.glyphicon-resize-horizontal-content { content: "\f217"; } -.glyphicon-resize-small-content { content: "\f218"; } -.glyphicon-resize-vertical-content { content: "\f219"; } -.glyphicon-retweet-content { content: "\f21a"; } -.glyphicon-rgb-content { content: "\f21b"; } -.glyphicon-road-content { content: "\f21c"; } -.glyphicon-row-add-content { content: "\f21d"; } -.glyphicon-row-trash-content { content: "\f21e"; } -.glyphicon-save-content { content: "\f21f"; } -.glyphicon-saved-content { content: "\f220"; } -.glyphicon-scissors-content { content: "\f221"; } -.glyphicon-screenshot-content { content: "\f222"; } -.glyphicon-search-coords-content { content: "\f223"; } -.glyphicon-search-content { content: "\f224"; } -.glyphicon-send-content { content: "\f225"; } -.glyphicon-share-alt-content { content: "\f226"; } -.glyphicon-share-content { content: "\f227"; } -.glyphicon-sheet-content { content: "\f228"; } -.glyphicon-shopping-cart-content { content: "\f229"; } -.glyphicon-signal-content { content: "\f22a"; } -.glyphicon-size-extra-large-content { content: "\f22b"; } -.glyphicon-size-large-content { content: "\f22c"; } -.glyphicon-size-medium-content { content: "\f22d"; } -.glyphicon-size-small-content { content: "\f22e"; } -.glyphicon-slope-content { content: "\f22f"; } -.glyphicon-sort-by-alphabet-alt-content { content: "\f230"; } -.glyphicon-sort-by-alphabet-content { content: "\f231"; } -.glyphicon-sort-by-attributes-alt-content { content: "\f232"; } -.glyphicon-sort-by-attributes-content { content: "\f233"; } -.glyphicon-sort-content { content: "\f234"; } -.glyphicon-star-empty-content { content: "\f235"; } -.glyphicon-star-content { content: "\f236"; } -.glyphicon-stats-content { content: "\f237"; } -.glyphicon-step-backward-content { content: "\f238"; } -.glyphicon-step-forward-content { content: "\f239"; } -.glyphicon-stop-content { content: "\f23a"; } -.glyphicon-story-banner-section-content { content: "\f23b"; } -.glyphicon-story-carousel-section-content { content: "\f23c"; } -.glyphicon-story-immersive-content-content { content: "\f23d"; } -.glyphicon-story-immersive-section-content { content: "\f23e"; } -.glyphicon-story-media-section-content { content: "\f23f"; } -.glyphicon-story-paragraph-section-content { content: "\f240"; } -.glyphicon-story-title-section-content { content: "\f241"; } -.glyphicon-story-webpage-section-content { content: "\f242"; } -.glyphicon-tag-content { content: "\f243"; } -.glyphicon-tags-content { content: "\f244"; } -.glyphicon-tasks-content { content: "\f245"; } -.glyphicon-text-background-content { content: "\f246"; } -.glyphicon-text-colour-content { content: "\f247"; } -.glyphicon-text-height-content { content: "\f248"; } -.glyphicon-text-width-content { content: "\f249"; } -.glyphicon-th-large-content { content: "\f24a"; } -.glyphicon-th-list-content { content: "\f24b"; } -.glyphicon-th-content { content: "\f24c"; } -.glyphicon-thumbs-down-content { content: "\f24d"; } -.glyphicon-thumbs-up-content { content: "\f24e"; } -.glyphicon-time-current-content { content: "\f24f"; } -.glyphicon-time-offset-content { content: "\f250"; } -.glyphicon-time-content { content: "\f251"; } -.glyphicon-tint-content { content: "\f252"; } -.glyphicon-transfer-content { content: "\f253"; } -.glyphicon-trash-square-content { content: "\f254"; } -.glyphicon-trash-content { content: "\f255"; } -.glyphicon-unchecked-content { content: "\f256"; } -.glyphicon-undo-content { content: "\f257"; } -.glyphicon-unplug-content { content: "\f258"; } -.glyphicon-upload-content { content: "\f259"; } -.glyphicon-usd-content { content: "\f25a"; } -.glyphicon-user-content { content: "\f25b"; } -.glyphicon-vert-dashed-content { content: "\f25c"; } -.glyphicon-viewport-filter-content { content: "\f25d"; } -.glyphicon-warning-sign-content { content: "\f25e"; } -.glyphicon-webpage-content { content: "\f25f"; } -.glyphicon-wrench-content { content: "\f260"; } -.glyphicon-zoom-in-content { content: "\f261"; } -.glyphicon-zoom-out-content { content: "\f262"; } -.glyphicon-zoom-to-content { content: "\f263"; } +.glyphicon-globe-settings-content { content: "\f1a0"; } +.glyphicon-globe-content { content: "\f1a1"; } +.glyphicon-grab-handle-content { content: "\f1a2"; } +.glyphicon-gray-scale-content { content: "\f1a3"; } +.glyphicon-grid-custom-content { content: "\f1a4"; } +.glyphicon-grid-regular-content { content: "\f1a5"; } +.glyphicon-hand-down-content { content: "\f1a6"; } +.glyphicon-hand-left-content { content: "\f1a7"; } +.glyphicon-hand-right-content { content: "\f1a8"; } +.glyphicon-hand-up-content { content: "\f1a9"; } +.glyphicon-hdd-content { content: "\f1aa"; } +.glyphicon-heart-content { content: "\f1ab"; } +.glyphicon-height-auto-content { content: "\f1ac"; } +.glyphicon-height-from-terrain-content { content: "\f1ad"; } +.glyphicon-height-view-content { content: "\f1ae"; } +.glyphicon-hide-marker-content { content: "\f1af"; } +.glyphicon-home-content { content: "\f1b0"; } +.glyphicon-hourglass-content { content: "\f1b1"; } +.glyphicon-import-content { content: "\f1b2"; } +.glyphicon-inbox-content { content: "\f1b3"; } +.glyphicon-info-sign-content { content: "\f1b4"; } +.glyphicon-italic-content { content: "\f1b5"; } +.glyphicon-layer-info-content { content: "\f1b6"; } +.glyphicon-leaf-content { content: "\f1b7"; } +.glyphicon-level-up-content { content: "\f1b8"; } +.glyphicon-line-dash-content { content: "\f1b9"; } +.glyphicon-line-minus-content { content: "\f1ba"; } +.glyphicon-line-plus-content { content: "\f1bb"; } +.glyphicon-line-remove-content { content: "\f1bc"; } +.glyphicon-line-trash-content { content: "\f1bd"; } +.glyphicon-line-content { content: "\f1be"; } +.glyphicon-link-content { content: "\f1bf"; } +.glyphicon-list-alt-content { content: "\f1c0"; } +.glyphicon-list-content { content: "\f1c1"; } +.glyphicon-lock-content { content: "\f1c2"; } +.glyphicon-log-in-content { content: "\f1c3"; } +.glyphicon-log-out-content { content: "\f1c4"; } +.glyphicon-loop-content { content: "\f1c5"; } +.glyphicon-magnet-content { content: "\f1c6"; } +.glyphicon-map-context-content { content: "\f1c7"; } +.glyphicon-map-edit-content { content: "\f1c8"; } +.glyphicon-map-filter-content { content: "\f1c9"; } +.glyphicon-map-marker-content { content: "\f1ca"; } +.glyphicon-map-synch-content { content: "\f1cb"; } +.glyphicon-map-view-content { content: "\f1cc"; } +.glyphicon-maps-catalog-content { content: "\f1cd"; } +.glyphicon-menu-hamburger-content { content: "\f1ce"; } +.glyphicon-minus-sign-content { content: "\f1cf"; } +.glyphicon-minus-content { content: "\f1d0"; } +.glyphicon-model-plus-content { content: "\f1d1"; } +.glyphicon-model-content { content: "\f1d2"; } +.glyphicon-mouse-content { content: "\f1d3"; } +.glyphicon-move-row-after-content { content: "\f1d4"; } +.glyphicon-move-row-before-content { content: "\f1d5"; } +.glyphicon-move-content { content: "\f1d6"; } +.glyphicon-muted-content { content: "\f1d7"; } +.glyphicon-new-window-content { content: "\f1d8"; } +.glyphicon-next-content { content: "\f1d9"; } +.glyphicon-off-content { content: "\f1da"; } +.glyphicon-ok-circle-content { content: "\f1db"; } +.glyphicon-ok-sign-content { content: "\f1dc"; } +.glyphicon-ok-content { content: "\f1dd"; } +.glyphicon-open-content { content: "\f1de"; } +.glyphicon-option-horizontal-content { content: "\f1df"; } +.glyphicon-option-vertical-content { content: "\f1e0"; } +.glyphicon-paperclip-content { content: "\f1e1"; } +.glyphicon-paste-content { content: "\f1e2"; } +.glyphicon-pause-content { content: "\f1e3"; } +.glyphicon-pencil-add-content { content: "\f1e4"; } +.glyphicon-pencil-edit-content { content: "\f1e5"; } +.glyphicon-pencil-content { content: "\f1e6"; } +.glyphicon-phone-content { content: "\f1e7"; } +.glyphicon-picture-content { content: "\f1e8"; } +.glyphicon-pie-chart-content { content: "\f1e9"; } +.glyphicon-plane-content { content: "\f1ea"; } +.glyphicon-play-circle-content { content: "\f1eb"; } +.glyphicon-play-content { content: "\f1ec"; } +.glyphicon-playback-content { content: "\f1ed"; } +.glyphicon-plug-content { content: "\f1ee"; } +.glyphicon-plus-sign-content { content: "\f1ef"; } +.glyphicon-plus-square-content { content: "\f1f0"; } +.glyphicon-plus-content { content: "\f1f1"; } +.glyphicon-point-coordinates-content { content: "\f1f2"; } +.glyphicon-point-dash-content { content: "\f1f3"; } +.glyphicon-point-minus-content { content: "\f1f4"; } +.glyphicon-point-plus-content { content: "\f1f5"; } +.glyphicon-point-remove-content { content: "\f1f6"; } +.glyphicon-point-trash-content { content: "\f1f7"; } +.glyphicon-point-content { content: "\f1f8"; } +.glyphicon-polygon-3d-content { content: "\f1f9"; } +.glyphicon-polygon-dash-content { content: "\f1fa"; } +.glyphicon-polygon-minus-content { content: "\f1fb"; } +.glyphicon-polygon-plus-content { content: "\f1fc"; } +.glyphicon-polygon-remove-content { content: "\f1fd"; } +.glyphicon-polygon-trash-content { content: "\f1fe"; } +.glyphicon-polygon-content { content: "\f1ff"; } +.glyphicon-polyline-3d-content { content: "\f200"; } +.glyphicon-polyline-dash-content { content: "\f201"; } +.glyphicon-polyline-minus-content { content: "\f202"; } +.glyphicon-polyline-plus-content { content: "\f203"; } +.glyphicon-polyline-remove-content { content: "\f204"; } +.glyphicon-polyline-trash-content { content: "\f205"; } +.glyphicon-polyline-content { content: "\f206"; } +.glyphicon-preview-content { content: "\f207"; } +.glyphicon-print-content { content: "\f208"; } +.glyphicon-pushpin-content { content: "\f209"; } +.glyphicon-qrcode-content { content: "\f20a"; } +.glyphicon-question-sign-content { content: "\f20b"; } +.glyphicon-random-content { content: "\f20c"; } +.glyphicon-range-end-content { content: "\f20d"; } +.glyphicon-range-start-content { content: "\f20e"; } +.glyphicon-record-content { content: "\f20f"; } +.glyphicon-redo-content { content: "\f210"; } +.glyphicon-refresh-content { content: "\f211"; } +.glyphicon-remove-circle-content { content: "\f212"; } +.glyphicon-remove-sign-content { content: "\f213"; } +.glyphicon-remove-square-content { content: "\f214"; } +.glyphicon-remove-content { content: "\f215"; } +.glyphicon-repeat-content { content: "\f216"; } +.glyphicon-resize-full-content { content: "\f217"; } +.glyphicon-resize-horizontal-content { content: "\f218"; } +.glyphicon-resize-small-content { content: "\f219"; } +.glyphicon-resize-vertical-content { content: "\f21a"; } +.glyphicon-retweet-content { content: "\f21b"; } +.glyphicon-rgb-content { content: "\f21c"; } +.glyphicon-road-content { content: "\f21d"; } +.glyphicon-row-add-content { content: "\f21e"; } +.glyphicon-row-trash-content { content: "\f21f"; } +.glyphicon-save-content { content: "\f220"; } +.glyphicon-saved-content { content: "\f221"; } +.glyphicon-scissors-content { content: "\f222"; } +.glyphicon-screenshot-content { content: "\f223"; } +.glyphicon-search-coords-content { content: "\f224"; } +.glyphicon-search-content { content: "\f225"; } +.glyphicon-send-content { content: "\f226"; } +.glyphicon-share-alt-content { content: "\f227"; } +.glyphicon-share-content { content: "\f228"; } +.glyphicon-sheet-content { content: "\f229"; } +.glyphicon-shopping-cart-content { content: "\f22a"; } +.glyphicon-signal-content { content: "\f22b"; } +.glyphicon-size-extra-large-content { content: "\f22c"; } +.glyphicon-size-large-content { content: "\f22d"; } +.glyphicon-size-medium-content { content: "\f22e"; } +.glyphicon-size-small-content { content: "\f22f"; } +.glyphicon-slope-content { content: "\f230"; } +.glyphicon-sort-by-alphabet-alt-content { content: "\f231"; } +.glyphicon-sort-by-alphabet-content { content: "\f232"; } +.glyphicon-sort-by-attributes-alt-content { content: "\f233"; } +.glyphicon-sort-by-attributes-content { content: "\f234"; } +.glyphicon-sort-content { content: "\f235"; } +.glyphicon-star-empty-content { content: "\f236"; } +.glyphicon-star-content { content: "\f237"; } +.glyphicon-stats-content { content: "\f238"; } +.glyphicon-step-backward-content { content: "\f239"; } +.glyphicon-step-forward-content { content: "\f23a"; } +.glyphicon-stop-content { content: "\f23b"; } +.glyphicon-story-banner-section-content { content: "\f23c"; } +.glyphicon-story-carousel-section-content { content: "\f23d"; } +.glyphicon-story-immersive-content-content { content: "\f23e"; } +.glyphicon-story-immersive-section-content { content: "\f23f"; } +.glyphicon-story-media-section-content { content: "\f240"; } +.glyphicon-story-paragraph-section-content { content: "\f241"; } +.glyphicon-story-title-section-content { content: "\f242"; } +.glyphicon-story-webpage-section-content { content: "\f243"; } +.glyphicon-tag-content { content: "\f244"; } +.glyphicon-tags-content { content: "\f245"; } +.glyphicon-tasks-content { content: "\f246"; } +.glyphicon-text-background-content { content: "\f247"; } +.glyphicon-text-colour-content { content: "\f248"; } +.glyphicon-text-height-content { content: "\f249"; } +.glyphicon-text-width-content { content: "\f24a"; } +.glyphicon-th-large-content { content: "\f24b"; } +.glyphicon-th-list-content { content: "\f24c"; } +.glyphicon-th-content { content: "\f24d"; } +.glyphicon-thumbs-down-content { content: "\f24e"; } +.glyphicon-thumbs-up-content { content: "\f24f"; } +.glyphicon-time-current-content { content: "\f250"; } +.glyphicon-time-offset-content { content: "\f251"; } +.glyphicon-time-content { content: "\f252"; } +.glyphicon-tint-content { content: "\f253"; } +.glyphicon-transfer-content { content: "\f254"; } +.glyphicon-trash-square-content { content: "\f255"; } +.glyphicon-trash-content { content: "\f256"; } +.glyphicon-unchecked-content { content: "\f257"; } +.glyphicon-undo-content { content: "\f258"; } +.glyphicon-unplug-content { content: "\f259"; } +.glyphicon-upload-content { content: "\f25a"; } +.glyphicon-usd-content { content: "\f25b"; } +.glyphicon-user-content { content: "\f25c"; } +.glyphicon-vert-dashed-content { content: "\f25d"; } +.glyphicon-viewport-filter-content { content: "\f25e"; } +.glyphicon-warning-sign-content { content: "\f25f"; } +.glyphicon-webpage-content { content: "\f260"; } +.glyphicon-wrench-content { content: "\f261"; } +.glyphicon-zoom-in-content { content: "\f262"; } +.glyphicon-zoom-out-content { content: "\f263"; } +.glyphicon-zoom-to-content { content: "\f264"; } diff --git a/web/client/themes/default/icons/icons.eot b/web/client/themes/default/icons/icons.eot old mode 100755 new mode 100644 index 70e7db02604adbedf9debcc76ad007ac13195fea..c205cbde0458adb503dd70bc02625b8158889722 GIT binary patch delta 9902 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 B;fw$P delta 9221 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 diff --git a/web/client/themes/default/icons/icons.svg b/web/client/themes/default/icons/icons.svg old mode 100755 new mode 100644 index e3fc09ea8f..8170e2afbb --- a/web/client/themes/default/icons/icons.svg +++ b/web/client/themes/default/icons/icons.svg @@ -961,1178 +961,1184 @@ - + + 8{ela+nfelTCG;nN~_(~iR?9$ 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 delta 9258 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 N@r(1;o2w;8{s##=dBp$# diff --git a/web/client/themes/default/icons/icons.woff b/web/client/themes/default/icons/icons.woff old mode 100755 new mode 100644 index 0f9d374870071a41aa5bc9803dd89fe5c2973c18..33c8e3a3a04cf74ad967c933f884e69ed0c785b7 GIT binary patch delta 29910 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ð4%)ZIG+=~Oujn4F1{_k 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 tg$M}-2#{ig0vUV=TdRdCi*t0rxTd0e75wvkCwJ delta 29442 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­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 A`2YX_ diff --git a/web/client/themes/default/icons/icons.woff2 b/web/client/themes/default/icons/icons.woff2 index 2fe713821e0b58aff98396b77ed459091510b1b3..8ca6527f82a627d3c98d0393699789c6bbb3f921 100644 GIT binary patch literal 39816 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 Eh^l^dNdN!< literal 39432 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ⅈb(yh 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 kjLm{U_aE^f_y4|iSxOAhD`VEk .ms2-border-layout-body { padding: 15px; diff --git a/web/client/themes/default/svg/globe-settings.svg b/web/client/themes/default/svg/globe-settings.svg new file mode 100644 index 0000000000..9d52e15db1 --- /dev/null +++ b/web/client/themes/default/svg/globe-settings.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + diff --git a/web/client/translations/data.de-DE.json b/web/client/translations/data.de-DE.json index 9d2e231968..ba844d9ab2 100644 --- a/web/client/translations/data.de-DE.json +++ b/web/client/translations/data.de-DE.json @@ -3090,9 +3090,9 @@ "description": "Ermöglicht das Hinzufügen eines Filters zu einer Ebene", "title": "Ebenenfilter" }, - "GeoProcessingTools": { + "GeoProcessing": { "description": "Ermöglicht die Geoverarbeitung von Layern zur Generierung eines neuen Layers mithilfe von WPS-Prozessen für Puffer und Schnittpunkte", - "title": "Geo-Verarbeitungstools" + "title": "Geoverarbeitung" }, "HelpLink": { "description": "Eine Schaltfläche für den Zugriff auf die MapStore-Dokumentation", @@ -3904,13 +3904,13 @@ "dxfGeometryNotSupported": "Es wird nur LWPOLYLINE unterstützt" } }, - "GeoProcessingTools": { - "title": "Geoverarbeitungswerkzeuge", - "emptyTitle": "Diese WPS-Prozesse müssen in Geoserver installiert sein, um dieses Tool verwenden zu können:", + "GeoProcessing": { + "title": "Geoverarbeitung", + "emptyTitle": "Diese WPS-Prozesse müssen im Geoserver installiert sein, um diesen Prozess nutzen zu können:", "emptyDescription": "
  • geo:buffer
  • gs:IntersectionFeatureCollection
  • gs:CollectGeometries
", "sourceLayer": "Quellebene", "sourceFeature": "Quellfunktion", - "tool": "Wählen Sie ein zu verwendendes Werkzeug aus", + "tool": "Wählen Sie einen Prozess aus, den Sie verwenden möchten", "highlight": "Markieren Sie Funktionen", "bufferTool": "Puffer", "distance": "Distanz", @@ -3924,16 +3924,23 @@ "intersectionLayer": "Schnittebene", "intersectionFeature": "Kreuzungsfunktion", "advancedSettings": "Erweiterte Einstellungen", - "quadrantSegments": "Quadrantensegmente", - "capStyle": "Stil für die Pufferendkappen", + "quadrantSegments": "quadrantSegments", + "quadrantSegmentsTooltip": "Quadrantensegmente", + "capStyle": "capStyle", + "capStyleTooltip": "Stil für die Pufferendkappen", "round": "Runden", "flat": "Wohnung", "square": "Quadrat", - "firstAttributeToRetain": "Erstes einzuschließendes Feature-Sammlungsattribut", - "secondAttributeToRetain": "Zweites einzuschließendes Feature-Sammlungsattribut", - "intersectionMode": "Gibt die für sich überschneidende Features berechnete Geometrie an", - "percentagesEnabled": "Gibt an, ob Prozentsätze der Feature-Fläche ausgegeben werden sollen", - "areasEnabled": "Gibt an, ob Featurebereiche ausgegeben werden sollen", + "firstAttributeToRetain": "firstAttributeToRetain", + "secondAttributeToRetain": "secondAttributeToRetain", + "intersectionMode": "intersectionMode", + "percentagesEnabled": "percentagesEnabled", + "areasEnabled": "areasEnabled", + "firstAttributeToRetainTooltip": "Erstes einzuschließendes Feature-Sammlungsattribut", + "secondAttributeToRetainTooltip": "Zweites einzuschließendes Feature-Sammlungsattribut", + "intersectionModeTooltip": "Gibt die für sich überschneidende Features berechnete Geometrie an", + "percentagesEnabledTooltip": "Gibt an, ob Prozentsätze der Feature-Fläche ausgegeben werden sollen", + "areasEnabledTooltip": "Gibt an, ob Featurebereiche ausgegeben werden sollen", "noMatchedMode": "Kein Modus entspricht dem aktuellen Filter", "INTERSECTION": "ÜBERSCHNEIDUNG", "FIRST": "ERSTE", @@ -3958,16 +3965,16 @@ "warningCancel": "Abbrechen", "tooltip": { "clickToSelectFeature": "Klicken, um Funktion auszuwählen", - "invalidLayers": "Eine der von Ihnen ausgewählten Ebenen kann in diesem Werkzeug nicht verwendet werden", - "fillRequiredDataIntersection": "Bitte wählen Sie mindestens den Quell-Layer und den Schnittpunkt-Layer aus", - "fillRequiredDataBuffer": "Bitte wählen Sie mindestens die Quellebene aus", - "siderBarBtn": "GeoProcessing Tools", - "selectFeature": "Bitte wählen Sie eine Funktion aus", - "validFeature": "Diese Funktion ist gültig", - "invalidFeature": "Diese Funktion ist ungültig", - "selectLayer": "Bitte wählen Sie eine Ebene aus", - "validLayer": "Diese Ebene ist gültig und kann in diesem Tool verwendet werden", - "invalidLayer": "Dieser Layer unterstützt weder die erforderlichen WPS-Prozesse \ngeo:buffer\ngs:IntersectionFeatureCollection\ngs:CollectGeometries\n\noch handelt es sich um einen Raster-Layer." + "invalidLayers": "Eine der von Ihnen ausgewählten Ebenen kann in diesem Prozess nicht verwendet werden", + "fillRequiredDataIntersection": "Bitte wählen Sie mindestens den Quell-Layer und den Schnittpunkt-Layer aus", + "fillRequiredDataBuffer": "Bitte wählen Sie mindestens die Quellebene aus", + "siderBarBtn": "Geoverarbeitung", + "selectFeature": "Bitte wählen Sie eine Funktion aus", + "validFeature": "Diese Funktion ist gültig", + "invalidFeature": "Diese Funktion ist ungültig", + "selectLayer": "Bitte wählen Sie eine Ebene aus", + "validLayer": "Diese Ebene ist gültig und kann in diesem Prozess verwendet werden", + "invalidLayer": "Dieser Layer unterstützt weder die erforderlichen WPS-Prozesse \ngeo:buffer\ngs:IntersectionFeatureCollection\ngs:CollectGeometries\n\noch handelt es sich um einen Raster-Layer." } } } diff --git a/web/client/translations/data.en-US.json b/web/client/translations/data.en-US.json index d53ae0d6de..da89c8780c 100644 --- a/web/client/translations/data.en-US.json +++ b/web/client/translations/data.en-US.json @@ -3064,9 +3064,9 @@ "description": "Allows to add a filter to a layer", "title": "Filter Layer" }, - "GeoProcessingTools": { + "GeoProcessing": { "description": "Allows to geo process layers to generate a new one, using wps processes buffer and intersection", - "title": "Geo Processing Tools" + "title": "GeoProcessing" }, "HelpLink": { "description": "A button to access to MapStore documentation", @@ -3878,13 +3878,13 @@ "dxfGeometryNotSupported": "Only LWPOLYLINE is supported" } }, - "GeoProcessingTools": { - "title": "GeoProcessing Tools", - "emptyTitle": "These WPS proceses must be installed in Geoserver in order to use this tool:", + "GeoProcessing": { + "title": "GeoProcessing", + "emptyTitle": "These WPS processes must be installed in Geoserver in order to use this process:", "emptyDescription": "
  • geo:buffer
  • gs:IntersectionFeatureCollection
  • gs:CollectGeometries
", "sourceLayer": "Source Layer", "sourceFeature": "Source Feature", - "tool": "Select a tool to use", + "tool": "Select a process to use", "highlight": "Highlight features", "bufferTool": "Buffer", "distance": "Distance", @@ -3898,16 +3898,23 @@ "intersectionLayer": "Intersection Layer", "intersectionFeature": "Intersection Feature", "advancedSettings": "Advanced Settings", - "quadrantSegments": "Quadrant Segments", - "capStyle": "Style for the buffer end caps", + "quadrantSegments": "quadrantSegments", + "quadrantSegmentsTooltip": "Quadrant Segments", + "capStyle": "capStyle", + "capStyleTooltip": "Style for the buffer end caps", "round": "Round", "flat": "Flat", "square": "Square", - "firstAttributeToRetain": "First feature collection attribute to include", - "secondAttributeToRetain": "Second feature collection attribute to include", - "intersectionMode": "Specifies geometry computed for intersecting features", - "percentagesEnabled": "Indicates whether to output feature area percentages", - "areasEnabled": "Indicates whether to output feature areas", + "firstAttributeToRetain": "firstAttributeToRetain", + "secondAttributeToRetain": "secondAttributeToRetain", + "intersectionMode": "intersectionMode", + "percentagesEnabled": "percentagesEnabled", + "areasEnabled": "areasEnabled", + "firstAttributeToRetainTooltip": "First feature collection attribute to include", + "secondAttributeToRetainTooltip": "Second feature collection attribute to include", + "intersectionModeTooltip": "Specifies geometry computed for intersecting features", + "percentagesEnabledTooltip": "Indicates whether to output feature area percentages", + "areasEnabledTooltip": "Indicates whether to output feature areas", "noMatchedMode": "No mode matches the current filter", "INTERSECTION": "INTERSECTION", "FIRST": "FIRST", @@ -3919,7 +3926,7 @@ "errorGFI": "There was an error loading the feature", "errorGetFeature": "There was an error loading the feature in order to obtain its geometry", "layerNotSupported": "Selected layer is not supported. Please select WMS, WFS or vector layer.", - "noFeatureInPoint": "No feature was not found at selected point.", + "noFeatureInPoint": "No feature was found at selected point.", "featureFound": "A feature was found at selected point.", "noLayerSelected": "Please select layer first.", "successfulIntersection": "The intersection operation was successful and a new layer has ben created and added to the TOC", @@ -3932,15 +3939,15 @@ "warningCancel": "Cancel", "tooltip": { "clickToSelectFeature": "Click to select feature", - "invalidLayers": "One of the layers you have selected cannot be used within this tool", + "invalidLayers": "One of the layers you have selected cannot be used within this process", "fillRequiredDataIntersection": "Please select at least the source layer and the intersection layer", "fillRequiredDataBuffer": "Please select at least the source layer", - "siderBarBtn": "GeoProcessing Tools", + "siderBarBtn": "GeoProcessing", "selectFeature": "Please select a feature", "validFeature": "This feature is valid", "invalidFeature": "This feature is not valid", "selectLayer": "Please select a layer", - "validLayer": "This layer is valid and can be used in this tool", + "validLayer": "This layer is valid and can be used in this process", "invalidLayer": "This layer does not support the needed wps processes \ngeo:buffer\ngs:IntersectionFeatureCollection\ngs:CollectGeometries\n\nor it is a Raster layer" } } diff --git a/web/client/translations/data.es-ES.json b/web/client/translations/data.es-ES.json index f4d8df2af4..eed58d283c 100644 --- a/web/client/translations/data.es-ES.json +++ b/web/client/translations/data.es-ES.json @@ -3053,9 +3053,9 @@ "description": "Permite agregar un filtro a una capa", "title": "Capa de filtro" }, - "GeoProcessingTools": { + "GeoProcessing": { "description": "Permite geoprocesar capas para generar una nueva, utilizando procesos wps buffer e intersección", - "title": "Herramientas de procesamiento geográfico" + "title": "Geoprocesamiento" }, "HelpLink": { "description": "Un botón para acceder a la documentación de MapStore", @@ -3867,13 +3867,13 @@ "dxfGeometryNotSupported": "Solo se admite LWPOLYLINE" } }, - "GeoProcessingTools": { - "title": "Herramientas de geoprocesamiento", - "emptyTitle": "Estos procesos WPS deben estar instalados en Geoserver para poder utilizar esta herramienta:", + "GeoProcessing": { + "title": "Geoprocesamiento", + "emptyTitle": "Estos procesos WPS deben estar instalados en Geoserver para poder utilizar este proceso:", "emptyDescription": "
  • geo:buffer
  • gs:IntersectionFeatureCollection
  • gs:CollectGeometries
", "sourceLayer": "Capa de origen", "sourceFeature": "Característica de origen", - "tool": "Seleccione una herramienta para usar", + "tool": "Seleccione un proceso para usar", "highlight": "Características destacadas", "bufferTool": "Buffer", "distance": "Distancia", @@ -3887,16 +3887,23 @@ "intersectionLayer": "Capa de intersección", "intersectionFeature": "Característica de intersección", "advancedSettings": "Ajustes avanzados", - "quadrantSegments": "Segmentos de cuadrante", - "capStyle": "Estilo para las tapas de los extremos del búfer", + "quadrantSegments": "quadrantSegments", + "quadrantSegmentsTooltip": "Segmentos de cuadrante", + "capStyle": "capStyle", + "capStyleTooltip": "Estilo para las tapas de los extremos del búfer", "round": "Redonda", "flat": "Plana", "square": "Cuadrada", - "firstAttributeToRetain": "Primer atributo de colección de características para incluir", - "secondAttributeToRetain": "Segundo atributo de colección de características a incluir", - "intersectionMode": "Especifica la geometría calculada para las entidades de intersección", - "percentagesEnabled": "Indica si se deben generar porcentajes de áreas de características", - "areasEnabled": "Indica si generar áreas de características", + "firstAttributeToRetain": "firstAttributeToRetain", + "secondAttributeToRetain": "secondAttributeToRetain", + "intersectionMode": "intersectionMode", + "percentagesEnabled": "percentagesEnabled", + "areasEnabled": "areasEnabled", + "firstAttributeToRetainTooltip": "Primer atributo de colección de características para incluir", + "secondAttributeToRetainTooltip": "Segundo atributo de colección de características a incluir", + "intersectionModeTooltip": "Especifica la geometría calculada para las entidades de intersección", + "percentagesEnabledTooltip": "Indica si se deben generar porcentajes de áreas de características", + "areasEnabledTooltip": "Indica si generar áreas de características", "noMatchedMode": "Ningún modo coincide con el filtro actual", "INTERSECTION": "INTERSECCIÓN", "FIRST": "PRIMERA", @@ -3921,15 +3928,15 @@ "warningCancel": "Cancelar", "tooltip": { "clickToSelectFeature": "Haga clic para seleccionar la característica", - "invalidLayers": "Una de las capas que ha seleccionado no se puede usar dentro de esta herramienta", + "invalidLayers": "Una de las capas que ha seleccionado no se puede utilizar dentro de este proceso", "fillRequiredDataIntersection": "Seleccione al menos la capa de origen y la capa de intersección", "fillRequiredDataBuffer": "Seleccione al menos la capa de origen", - "siderBarBtn": "Herramientas de geoprocesamiento", + "siderBarBtn": "Geoprocesamiento", "selectFeature": "Seleccione una función", "validFeature": "Esta función es válida", "invalidFeature": "Esta función no es válida", "selectLayer": "Seleccione una capa", - "validLayer": "Esta capa es válida y se puede usar en esta herramienta", + "validLayer": "Esta capa es válida y se puede utilizar en este proceso.", "invalidLayer": "Esta capa no soporta los procesos wps necesarios \ngeo:buffer\ngs:IntersectionFeatureCollection\ngs:CollectGeometries\n\ni es una capa Raster" } } diff --git a/web/client/translations/data.fr-FR.json b/web/client/translations/data.fr-FR.json index 111a3e1f04..29563dd488 100644 --- a/web/client/translations/data.fr-FR.json +++ b/web/client/translations/data.fr-FR.json @@ -3054,9 +3054,9 @@ "description": "Permet d'ajouter un filtre à une couche", "title": "Filtre de couche" }, - "GeoProcessingTools": { + "GeoProcessing": { "description": "Permet de géo-traiter les couches pour en générer une nouvelle, en utilisant le tampon et l'intersection des processus wps", - "title": "Outils de traitement géographique" + "title": "Géotraitement" }, "HelpLink": { "description": "Un bouton pour accéder à la documentation MapStore", @@ -3867,13 +3867,13 @@ "dxfGeometryNotSupported": "Seul LWPOLYLINE est pris en charge" } }, - "GeoProcessingTools": { - "title": "Outils de géotraitement", - "emptyTitle": "Ces processus WPS doivent être installés dans Geoserver afin d'utiliser cet outil:", + "GeoProcessing": { + "title": "Géotraitement", + "emptyTitle": "Ces processus WPS doivent être installés dans Geoserver pour pouvoir utiliser ce processus:", "emptyDescription": "
  • geo:buffer
  • gs:IntersectionFeatureCollection
  • gs:CollectGeometries
", "sourceLayer": "Couche source", "sourceFeature": "Caractéristique source", - "tool": "Sélectionnez un outil à utiliser", + "tool": "Sélectionnez un processus à utiliser", "highlight": "Mettre en évidence les fonctionnalités", "bufferTool": "Tampon", "distance": "Distance", @@ -3887,16 +3887,23 @@ "intersectionLayer": "Couche d'intersection", "intersectionFeature": "Caractéristique d'intersection", "advancedSettings": "Réglages avancés", - "quadrantSegments": "Segments du quadrant", - "capStyle": "Style pour les embouts de tampon", + "quadrantSegments": "quadrantSegments", + "quadrantSegmentsTooltip": "Segments du quadrant", + "capStyle": "capStyle", + "capStyleTooltip": "Style pour les embouts de tampon", "round": "Ronde", "flat": "Plate", "square": "Carré", - "firstAttributeToRetain": "Premier attribut de collection d'entités à inclure", - "secondAttributeToRetain": "Deuxième attribut de collection d'entités à inclure", - "intersectionMode": "Spécifie la géométrie calculée pour les entités d'intersection", - "percentagesEnabled": "Indique s'il faut générer des pourcentages de surface d'entité", - "areasEnabled": "Indique s'il faut sortir les zones de caractéristiques", + "firstAttributeToRetain": "firstAttributeToRetain", + "secondAttributeToRetain": "secondAttributeToRetain", + "intersectionMode": "intersectionMode", + "percentagesEnabled": "percentagesEnabled", + "areasEnabled": "areasEnabled", + "firstAttributeToRetainTooltip": "Premier attribut de collection d'entités à inclure", + "secondAttributeToRetainTooltip": "Deuxième attribut de collection d'entités à inclure", + "intersectionModeTooltip": "Spécifie la géométrie calculée pour les entités d'intersection", + "percentagesEnabledTooltip": "Indique s'il faut générer des pourcentages de surface d'entité", + "areasEnabledTooltip": "Indique s'il faut sortir les zones de caractéristiques", "noMatchedMode": "Aucun mode ne correspond au filtre actuel", "INTERSECTION": "INTERSECTION", "FIRST": "D'ABORD", @@ -3921,15 +3928,15 @@ "warningCancel": "Annuler", "tooltip": { "clickToSelectFeature": "Cliquez pour sélectionner une fonctionnalité", - "invalidLayers": "L'un des calques que vous avez sélectionnés ne peut pas être utilisé dans cet outil", + "invalidLayers": "L'un des calques que vous avez sélectionnés ne peut pas être utilisé dans ce processus", "fillRequiredDataIntersection": "Veuillez sélectionner au moins la couche source et la couche d'intersection", "fillRequiredDataBuffer": "Veuillez sélectionner au moins la couche source", - "siderBarBtn": "Outils de géotraitement", + "siderBarBtn": "Géotraitement", "selectFeature": "Veuillez sélectionner une fonctionnalité", "validFeature": "Cette fonctionnalité est valide", "invalidFeature": "Cette fonctionnalité n'est pas valide", "selectLayer": "Veuillez sélectionner un calque", - "validLayer": "Cette couche est valide et peut être utilisée dans cet outil", + "validLayer": "Cette couche est valide et peut être utilisée dans ce processus", "invalidLayer": "Cette couche ne prend pas en charge les processus wps nécessaires \ngeo:buffer\ngs:IntersectionFeatureCollection\ngs:CollectGeometries\n\ni c'est une couche raster" } } diff --git a/web/client/translations/data.it-IT.json b/web/client/translations/data.it-IT.json index 07bcd63981..bed7a10c0c 100644 --- a/web/client/translations/data.it-IT.json +++ b/web/client/translations/data.it-IT.json @@ -3054,9 +3054,9 @@ "description": "Consente di aggiungere un filtro a un livello", "title": "Filtra Livello" }, - "GeoProcessingTools": { + "GeoProcessing": { "description": "Consente di geo processare i livelli utilizzando il buffer e l'intersezione dei processi wps", - "title": "Strumenti di elaborazione geospaziale" + "title": "Processi di Geoelaborazione" }, "HelpLink": { "description": "Un pulsante per accedere alla documentazione di MapStore", @@ -3867,13 +3867,13 @@ "dxfGeometryNotSupported": "Solo LWPOLYLINE è supportata nel DXF" } }, - "GeoProcessingTools": { - "title": "Strumenti di geoelaborazione", - "emptyTitle": "Questi processi WPS devono essere installati in geoserver per poter usare questo plugin:", + "GeoProcessing": { + "title": "Processi di Geoelaborazione", + "emptyTitle": "Questi processi WPS devono essere installati in geoserver per poter usare questo processo:", "emptyDescription": "
  • geo:buffer
  • gs:IntersectionFeatureCollection
  • gs:CollectGeometries
", "sourceLayer": "Livello sorgente", "sourceFeature": "Feature sorgente", - "tool": "Seleziona uno strumento", + "tool": "Seleziona un processo", "highlight": "Evidenzia le feature in mappa", "bufferTool": "Buffer", "distance": "Distanza", @@ -3887,16 +3887,23 @@ "intersectionLayer": "Livello intersezione", "intersectionFeature": "Feature intersezione", "advancedSettings": "Opzioni avanzate", - "quadrantSegments": "Segmenti", - "capStyle": "Style da usare", + "quadrantSegments": "quadrantSegments", + "quadrantSegmentsTooltip": "Segmenti", + "capStyle": "capStyle", + "capStyleTooltip": "Style da usare", "round": "Rotondo", "flat": "Piatto", "square": "Squadrato", - "firstAttributeToRetain": "Primo attributo della collezione di feature", - "secondAttributeToRetain": "Secondo attributo della collezione di feature", - "intersectionMode": "Specifica che tipo di geometria per intersecare le caratteristiche", - "percentagesEnabled": "Indica se indica se emettere le percentuali dell'area caratteristica", - "areasEnabled": "Indica se emettere aree caratteristiche", + "firstAttributeToRetain": "firstAttributeToRetain", + "secondAttributeToRetain": "secondAttributeToRetain", + "intersectionMode": "intersectionMode", + "percentagesEnabled": "percentagesEnabled", + "areasEnabled": "areasEnabled", + "firstAttributeToRetainTooltip": "Primo attributo della collezione di feature", + "secondAttributeToRetainTooltip": "Secondo attributo della collezione di feature", + "intersectionModeTooltip": "Specifica la geometria calcolata dalle features", + "percentagesEnabledTooltip": "Indica se emettere le percentuali dell'area feature", + "areasEnabledTooltip": "Indica se emettere aree features", "noMatchedMode": "Nessuna modalità corrisponde al filtro corrente", "INTERSECTION": "INTERSEZIONE", "FIRST": "PRIMO", @@ -3921,7 +3928,7 @@ "warningCancel": "Annulla", "tooltip": { "clickToSelectFeature": "Fai click per selezionare una feature", - "invalidLayers": "Uno dei livelli che hai selezionato non può essere utilizzato all'interno di questo strumento", + "invalidLayers": "Uno dei livelli che hai selezionato non può essere utilizzato all'interno di questo processo", "fillRequiredDataIntersection": "Seleziona almeno il livello di origine e il livello di intersezione", "fillRequiredDataBuffer": "Seleziona almeno il livello di origine", "siderBarBtn": "Strumenti di geoelaborazione", @@ -3929,7 +3936,7 @@ "validFeature": "Questa feature è valida", "invalidFeature": "Questa feature non è valida", "selectLayer": "Seleziona un livello", - "validLayer": "Questo livello è valido e può essere utilizzato in questo strumento", + "validLayer": "Questo livello è valido e può essere utilizzato in questo processo", "invalidLayer": "Questo livello non supporta i processi wps necessari \ngeo:buffer\ngs:IntersectionFeatureCollection\ngs:CollectGeometries\n\no è un livello raster" } } diff --git a/web/client/utils/GeoProcessingToolsUtils.js b/web/client/utils/GeoProcessingUtils.js similarity index 100% rename from web/client/utils/GeoProcessingToolsUtils.js rename to web/client/utils/GeoProcessingUtils.js diff --git a/web/client/utils/__tests__/GeoProcessingToolsUtils-test.js b/web/client/utils/__tests__/GeoProcessingUtils-test.js similarity index 94% rename from web/client/utils/__tests__/GeoProcessingToolsUtils-test.js rename to web/client/utils/__tests__/GeoProcessingUtils-test.js index ae488e9a30..41ae87d656 100644 --- a/web/client/utils/__tests__/GeoProcessingToolsUtils-test.js +++ b/web/client/utils/__tests__/GeoProcessingUtils-test.js @@ -9,10 +9,10 @@ import expect from 'expect'; import { checkIfIntersectionIsPossible -} from '../GeoProcessingToolsUtils'; +} from '../GeoProcessingUtils'; -describe('GeoProcessingToolsUtils', () => { +describe('GeoProcessingUtils', () => { const pointFT = { type: "Feature", geometry: {