From 88c97266244a2e5dc9107d86503320c634427c8d Mon Sep 17 00:00:00 2001 From: mahmoud adel <58145645+mahmoudadel54@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:20:21 +0200 Subject: [PATCH] #10637: fix Longitudinal profil does not close properly and it leads to conflicts between the longitudinal profil and measure plugin (#10806) * #10637: fix Longitudinal profil does not close properly and it leads to conflicts between the longitudinal profil and measure plugin Description: - fix issue of draw conflicts between longitudinal profil and measure plugin in longitudinalProfile epic by reset drawing in 'LPonDockClosedEpic' - add unit test * #10637: add drawOwner selector Description: - add drawOwner selector to be used in 'LPonDockClosedEpic' - add unit test --- .../__tests__/longitudinalProfile-test.js | 91 +++++++++++++++++++ web/client/epics/longitudinalProfile.js | 13 ++- web/client/selectors/__tests__/draw-test.js | 10 +- web/client/selectors/draw.js | 2 + 4 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 web/client/epics/__tests__/longitudinalProfile-test.js diff --git a/web/client/epics/__tests__/longitudinalProfile-test.js b/web/client/epics/__tests__/longitudinalProfile-test.js new file mode 100644 index 0000000000..a492f1f5be --- /dev/null +++ b/web/client/epics/__tests__/longitudinalProfile-test.js @@ -0,0 +1,91 @@ +/* + * Copyright 2025, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +import expect from 'expect'; + +import { + LPonDockClosedEpic +} from '../longitudinalProfile'; + +import { testEpic } from './epicTestUtils'; +import { setControlProperty } from '../../actions/controls'; +import { CONTROL_DOCK_NAME, CONTROL_NAME, LONGITUDINAL_OWNER, LONGITUDINAL_VECTOR_LAYER_ID, LONGITUDINAL_VECTOR_LAYER_ID_POINT } from '../../plugins/longitudinalProfile/constants'; +import { CHANGE_GEOMETRY } from '../../actions/longitudinalProfile'; +import { REMOVE_ADDITIONAL_LAYER } from '../../actions/additionallayers'; +import { UNREGISTER_EVENT_LISTENER } from '../../actions/map'; +import { CHANGE_DRAWING_STATUS } from '../../actions/draw'; + +describe('longitudinalProfile Epics', () => { + it('test default LPonDockClosedEpic epic', (done) => { + const epicResult = actions => { + const action1 = actions[0]; + const action2 = actions[1]; + const action3 = actions[2]; + const action4 = actions[3]; + expect(action1).toExist(); + expect(action1.type).toEqual(CHANGE_GEOMETRY); + expect(action1.geometry).toEqual(false); + expect(action2).toExist(); + expect(action2.type).toEqual(REMOVE_ADDITIONAL_LAYER); + expect(action2.owner).toEqual(LONGITUDINAL_OWNER); + expect(action2.id).toEqual(LONGITUDINAL_VECTOR_LAYER_ID); + expect(action3).toExist(); + expect(action3.type).toEqual(REMOVE_ADDITIONAL_LAYER); + expect(action3.owner).toEqual(LONGITUDINAL_OWNER); + expect(action3.id).toEqual(LONGITUDINAL_VECTOR_LAYER_ID_POINT); + expect(action4).toExist(); + expect(action4.type).toEqual(UNREGISTER_EVENT_LISTENER); + expect(action4.toolName).toEqual(CONTROL_NAME); + done(); + }; + testEpic(LPonDockClosedEpic, 4, [setControlProperty( + CONTROL_DOCK_NAME, 'enabled', false + )], epicResult, {}); + }); + it('test LPonDockClosedEpic epic if the drawing mode is active', (done) => { + const epicResult = actions => { + const action1 = actions[0]; + const action2 = actions[1]; + const action3 = actions[2]; + const action4 = actions[3]; + const action5 = actions[4]; + const action6 = actions[5]; + expect(action1).toExist(); + expect(action1.type).toEqual(CHANGE_GEOMETRY); + expect(action1.geometry).toEqual(false); + expect(action2).toExist(); + expect(action2.type).toEqual(REMOVE_ADDITIONAL_LAYER); + expect(action2.owner).toEqual(LONGITUDINAL_OWNER); + expect(action2.id).toEqual(LONGITUDINAL_VECTOR_LAYER_ID); + expect(action3).toExist(); + expect(action3.type).toEqual(REMOVE_ADDITIONAL_LAYER); + expect(action3.owner).toEqual(LONGITUDINAL_OWNER); + expect(action3.id).toEqual(LONGITUDINAL_VECTOR_LAYER_ID_POINT); + // stop drawing + expect(action4).toExist(); + expect(action4.type).toEqual(CHANGE_DRAWING_STATUS); + expect(action4.status).toEqual('stop'); + expect(action5).toExist(); + expect(action5.type).toEqual(CHANGE_DRAWING_STATUS); + expect(action5.status).toEqual('clean'); + expect(action6).toExist(); + expect(action6.type).toEqual(UNREGISTER_EVENT_LISTENER); + expect(action6.toolName).toEqual(CONTROL_NAME); + done(); + }; + testEpic(LPonDockClosedEpic, 6, [setControlProperty( + CONTROL_DOCK_NAME, 'enabled', false + )], epicResult, { + "draw": { + "drawMethod": "LineString", + "drawStatus": "start", + "drawOwner": CONTROL_NAME + } + }); + }); +}); diff --git a/web/client/epics/longitudinalProfile.js b/web/client/epics/longitudinalProfile.js index c2ebb858cb..e372a2a11b 100644 --- a/web/client/epics/longitudinalProfile.js +++ b/web/client/epics/longitudinalProfile.js @@ -5,7 +5,6 @@ * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ -import get from "lodash/get"; import isEmpty from "lodash/isEmpty"; import Rx from 'rxjs'; @@ -89,6 +88,7 @@ import {reprojectGeoJson, reproject} from "../utils/CoordinatesUtils"; import {selectLineFeature} from "../utils/LongitudinalProfileUtils"; import {buildIdentifyRequest} from "../utils/MapInfoUtils"; import {getFeatureInfo} from "../api/identify"; +import { drawerOwnerSelector } from "../selectors/draw"; const OFFSET = 550; @@ -124,6 +124,7 @@ export const LPonDrawActivatedEpic = (action$, store) => .switchMap(()=> { const state = store.getState(); const mode = dataSourceModeSelector(state); + const drawerOwner = drawerOwnerSelector(state); switch (mode) { case "draw": const startDrawingAction = changeDrawingStatus('start', "LineString", CONTROL_NAME, [], { stopAfterDrawing: true }); @@ -148,7 +149,7 @@ export const LPonDrawActivatedEpic = (action$, store) => case "select": return Rx.Observable.from([ purgeMapInfoResults(), hideMapinfoMarker(), - ...(get(store.getState(), 'draw.drawOwner', '') === CONTROL_NAME ? DEACTIVATE_ACTIONS : []), + ...(drawerOwner === CONTROL_NAME ? DEACTIVATE_ACTIONS : []), registerEventListener('click', CONTROL_NAME), ...(mapInfoEnabledSelector(state) ? [toggleMapInfoState()] : []) ]); @@ -157,7 +158,7 @@ export const LPonDrawActivatedEpic = (action$, store) => purgeMapInfoResults(), hideMapinfoMarker(), changeMapInfoState(mode !== undefined), - ...(get(store.getState(), 'draw.drawOwner', '') === CONTROL_NAME ? DEACTIVATE_ACTIONS : []), + ...(drawerOwner === CONTROL_NAME ? DEACTIVATE_ACTIONS : []), unRegisterEventListener('click', CONTROL_NAME) ]); } @@ -346,11 +347,15 @@ export const LPonDockClosedEpic = (action$, store) => action$.ofType(SET_CONTROL_PROPERTY) .filter(({control, property, value}) => control === CONTROL_DOCK_NAME && property === 'enabled' && value === false) .switchMap(() => { + const state = store.getState(); + const drawerOwner = drawerOwnerSelector(state); return Rx.Observable.from([ changeGeometry(false), removeAdditionalLayer({id: LONGITUDINAL_VECTOR_LAYER_ID, owner: LONGITUDINAL_OWNER}), removeAdditionalLayer({id: LONGITUDINAL_VECTOR_LAYER_ID_POINT, owner: LONGITUDINAL_OWNER}), - ...(isMaximizedSelector(store.getState()) ? [toggleMaximize()] : []) + ...(isMaximizedSelector(store.getState()) ? [toggleMaximize()] : []), + ...(drawerOwner === CONTROL_NAME ? DEACTIVATE_ACTIONS : []), + unRegisterEventListener('click', CONTROL_NAME) ]); }); diff --git a/web/client/selectors/__tests__/draw-test.js b/web/client/selectors/__tests__/draw-test.js index 1024bd7f1e..edbaf7cd3d 100644 --- a/web/client/selectors/__tests__/draw-test.js +++ b/web/client/selectors/__tests__/draw-test.js @@ -13,7 +13,7 @@ import { drawSupportActiveSelector, isSnappingActive, isSnappingLoading, - snappingConfig, snappingLayerSelector + snappingConfig, snappingLayerSelector, drawerOwnerSelector } from "../draw"; @@ -71,6 +71,14 @@ describe('draw changedGeometriesSelector', () => { expect(value.a).toBe(true); expect(value.b).toBe(false); }); + it('test drawerOwnerSelector selector', () => { + const value = drawerOwnerSelector({ + draw: { + drawOwner: "owner1" + } + }); + expect(value).toBe('owner1'); + }); describe('test availableSnappingLayers selector', () => { it('additional layers', () => { const value = availableSnappingLayers({ diff --git a/web/client/selectors/draw.js b/web/client/selectors/draw.js index bf1610c06d..6a1f03e358 100644 --- a/web/client/selectors/draw.js +++ b/web/client/selectors/draw.js @@ -25,6 +25,8 @@ export const isSnappingActive = state => get(state, 'draw.snapping', false); export const isSnappingLoading = state => get(state, 'draw.snappingIsLoading', false); export const snappingConfig = state => get(state, 'draw.snapConfig', false); +export const drawerOwnerSelector = state => get(state, 'draw.drawOwner', ''); + export const availableSnappingLayers = createShallowSelectorCreator( (a, b) => { return a === b