From 104b377da49ccd4ebab9cde89527c4d221d09b5c Mon Sep 17 00:00:00 2001 From: mahmoudadel Date: Fri, 4 Oct 2024 18:38:36 +0300 Subject: [PATCH] #10545: Option to disable identify popup in case of no results Description: - handle adding an option called 'hidePopupIfNoResults' to hide the identify popup for mapviewer [for desktop and mobile] using css approach - add unit tests - add jsdoc - edit style in map-popup.less --- .../actions/__tests__/mapPopups-test.js | 4 +++ web/client/actions/mapPopups.js | 5 ++++ .../data/identify/DefaultViewer.jsx | 9 ++++-- .../components/data/identify/PopupViewer.jsx | 8 ++++-- .../identify/__tests__/DefaultViewer-test.jsx | 14 ++++++++++ .../enhancers/__tests__/identify-test.jsx | 12 ++++++++ .../data/identify/enhancers/identify.js | 7 ++++- web/client/plugins/Identify.jsx | 5 +++- .../reducers/__tests__/mapPopups-test.js | 5 ++++ web/client/reducers/mapPopups.js | 7 ++++- .../selectors/__tests__/mapPopups-test.js | 28 +++++++++++++++++++ web/client/selectors/mapPopups.js | 17 +++++++++++ web/client/themes/default/less/map-popup.less | 4 ++- 13 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 web/client/selectors/__tests__/mapPopups-test.js create mode 100644 web/client/selectors/mapPopups.js diff --git a/web/client/actions/__tests__/mapPopups-test.js b/web/client/actions/__tests__/mapPopups-test.js index 18296feba6..1af4ecc32a 100644 --- a/web/client/actions/__tests__/mapPopups-test.js +++ b/web/client/actions/__tests__/mapPopups-test.js @@ -26,5 +26,9 @@ describe('test map popups action creators', () => { const action = POPUP.cleanPopups(); expect(action.type).toEqual(POPUP.CLEAN_MAP_POPUPS); }); + it('enable hide empty popup option', () => { + const action = POPUP.enableHideEmptyPopupOption(); + expect(action.type).toEqual(POPUP.ENABLE_HIDE_EMPTY_POPUP); + }); }); diff --git a/web/client/actions/mapPopups.js b/web/client/actions/mapPopups.js index ed001897fc..66ab51c315 100644 --- a/web/client/actions/mapPopups.js +++ b/web/client/actions/mapPopups.js @@ -10,6 +10,7 @@ export const ADD_MAP_POPUP = 'MAP:ADD_POPUP'; export const REMOVE_MAP_POPUP = 'MAP:REMOVE_POPUP'; export const CLEAN_MAP_POPUPS = 'MAP:CLEAN_POPUPS'; +export const ENABLE_HIDE_EMPTY_POPUP = 'MAP:ENABLE_HIDE_EMPTY_POPUP'; export const addPopup = (id, options, single = true) => ({ type: ADD_MAP_POPUP, @@ -26,3 +27,7 @@ export const removePopup = (id) => ({ export const cleanPopups = () => ({ type: CLEAN_MAP_POPUPS }); + +export const enableHideEmptyPopupOption = () => ({ + type: ENABLE_HIDE_EMPTY_POPUP +}); diff --git a/web/client/components/data/identify/DefaultViewer.jsx b/web/client/components/data/identify/DefaultViewer.jsx index 8a18d5330c..ff02bfbc6d 100644 --- a/web/client/components/data/identify/DefaultViewer.jsx +++ b/web/client/components/data/identify/DefaultViewer.jsx @@ -40,7 +40,8 @@ class DefaultViewer extends React.Component { renderValidOnly: PropTypes.bool, loaded: PropTypes.bool, isMobile: PropTypes.bool, - disableInfoAlert: PropTypes.bool + disableInfoAlert: PropTypes.bool, + hidePopupIfNoResults: PropTypes.bool }; static defaultProps = { @@ -64,7 +65,8 @@ class DefaultViewer extends React.Component { onPrevious: () => {}, setIndex: () => {}, isMobile: false, - disableInfoAlert: false + disableInfoAlert: false, + hidePopupIfNoResults: false }; shouldComponentUpdate(nextProps) { @@ -147,6 +149,9 @@ class DefaultViewer extends React.Component { renderEmptyPages = () => { const {emptyResponses} = this.getResponseProperties(); if (this.props.missingResponses === 0 && emptyResponses) { + if (this.props.hidePopupIfNoResults) { + return ; + } return (

diff --git a/web/client/components/data/identify/PopupViewer.jsx b/web/client/components/data/identify/PopupViewer.jsx index 399467a0e1..f7a59859d6 100644 --- a/web/client/components/data/identify/PopupViewer.jsx +++ b/web/client/components/data/identify/PopupViewer.jsx @@ -17,6 +17,7 @@ import Viewer from './DefaultViewer'; import {isArray, isUndefined} from 'lodash'; import SwipeHeader from './SwipeHeader'; import { identifyFloatingToolSelector } from '../../../selectors/map'; +import { hideEmptyPopupSelector } from '../../../selectors/mapPopups'; /** * Container that render only the selected result @@ -46,8 +47,8 @@ const selector = createSelector([ generalInfoFormatSelector, showEmptyMessageGFISelector, identifyFloatingToolSelector, - isLoadedResponseSelector], -(responses, validResponses, requests, format, showEmptyMessageGFI, renderValidOnly, loaded) => ({ + isLoadedResponseSelector, hideEmptyPopupSelector], +(responses, validResponses, requests, format, showEmptyMessageGFI, renderValidOnly, loaded, hidePopupIfNoResults) => ({ responses, validResponses, requests, @@ -55,7 +56,8 @@ const selector = createSelector([ showEmptyMessageGFI, missingResponses: (requests || []).length - (responses || []).length, renderValidOnly, - loaded + loaded, + hidePopupIfNoResults })); diff --git a/web/client/components/data/identify/__tests__/DefaultViewer-test.jsx b/web/client/components/data/identify/__tests__/DefaultViewer-test.jsx index 9fbe93fffd..3c8f19a47e 100644 --- a/web/client/components/data/identify/__tests__/DefaultViewer-test.jsx +++ b/web/client/components/data/identify/__tests__/DefaultViewer-test.jsx @@ -269,4 +269,18 @@ describe('DefaultViewer', () => { expect(gfiViewer.childNodes[1].childNodes.length).toBe(1); }); + it('test DefaultViewer component with hover identify if hidePopupIfNoResults = true', () => { + const responses = []; + ReactDOM.render( + , + document.getElementById("container") + ); + + const container = document.getElementById('container'); + let gfiViewer = container.querySelector('.mapstore-identify-viewer'); + expect(gfiViewer).toBeTruthy(); + expect(gfiViewer.childNodes.length).toBe(1); + expect(document.querySelector(".hidePopupIfNoResults")).toBeTruthy(); + expect(document.querySelector(".hidePopupIfNoResults").innerHTML).toBeFalsy(); + }); }); diff --git a/web/client/components/data/identify/enhancers/__tests__/identify-test.jsx b/web/client/components/data/identify/enhancers/__tests__/identify-test.jsx index 1ba1708dc8..27369942cb 100644 --- a/web/client/components/data/identify/enhancers/__tests__/identify-test.jsx +++ b/web/client/components/data/identify/enhancers/__tests__/identify-test.jsx @@ -187,6 +187,18 @@ describe("test identify enhancers", () => { ); expect(spyIdentifyIsMounted.calls.length).toEqual(1); }); + it("test identifyLifecycle component for call enableHideEmptyPopupOption if hidePopupIfNoResults prop = true", () => { + const Component = identifyLifecycle(() =>
); + const testHandlers = { + enableHideEmptyPopupOption: () => {} + }; + const spyEnableHideEmptyPopupOption = expect.spyOn(testHandlers, 'enableHideEmptyPopupOption'); + ReactDOM.render( + , + document.getElementById("container") + ); + expect(spyEnableHideEmptyPopupOption.calls.length).toEqual(1); + }); it("Identify should run when enabled prop is true and showInMapPopup prop is false", () => { let run = sampleComponentDidMount({enabled: true, showInMapPopup: false}); expect(run.checkIdentifyIsMounted).toBe(true); diff --git a/web/client/components/data/identify/enhancers/identify.js b/web/client/components/data/identify/enhancers/identify.js index 03724ec45e..fd66c04056 100644 --- a/web/client/components/data/identify/enhancers/identify.js +++ b/web/client/components/data/identify/enhancers/identify.js @@ -79,7 +79,9 @@ export const identifyLifecycle = compose( setShowInMapPopup = () => {}, checkIdentifyIsMounted = () => {}, onInitPlugin = () => {}, - pluginCfg = {} + pluginCfg = {}, + enableHideEmptyPopupOption = () => {}, + hidePopupIfNoResults = false } = this.props; // Initialize plugin configuration @@ -91,6 +93,9 @@ export const identifyLifecycle = compose( showAllResponses, highlight: pluginCfg?.highlightEnabledFromTheStart || false }); + if (hidePopupIfNoResults) { + enableHideEmptyPopupOption(true); + } if (enabled || showInMapPopup) { changeMousePointer('pointer'); checkIdentifyIsMounted(true); diff --git a/web/client/plugins/Identify.jsx b/web/client/plugins/Identify.jsx index 30479ae208..fdce0a4edb 100644 --- a/web/client/plugins/Identify.jsx +++ b/web/client/plugins/Identify.jsx @@ -38,6 +38,7 @@ import { checkIdentifyIsMounted, onInitPlugin } from '../actions/mapInfo'; +import { enableHideEmptyPopupOption } from '../actions/mapPopups'; import DefaultViewerComp from '../components/data/identify/DefaultViewer'; import { defaultViewerDefaultProps, defaultViewerHandlers } from '../components/data/identify/enhancers/defaultViewer'; import { identifyLifecycle } from '../components/data/identify/enhancers/identify'; @@ -196,6 +197,7 @@ const identifyDefaultProps = defaultProps({ * @prop cfg.dock {bool} true shows dock panel, false shows modal * @prop cfg.draggable {boolean} draggable info window, when modal * @prop cfg.showHighlightFeatureButton {boolean} show the highlight feature button if the interrogation returned valid features (openlayers only) + * @prop cfg.hidePopupIfNoResults {boolean} hide/show the identify popup in case of no results * @prop cfg.highlightEnabledFromTheStart {boolean} the highlight feature button will be activated by default if true * @prop cfg.viewerOptions.container {expression} the container of the viewer, expression from the context * @prop cfg.viewerOptions.header {expression} the header of the viewer, expression from the context{expression} @@ -265,7 +267,8 @@ const IdentifyPlugin = compose( identifyIndex, defaultViewerHandlers, connect(() => ({}), { - setShowInMapPopup + setShowInMapPopup, + enableHideEmptyPopupOption }), identifyLifecycle )(IdentifyContainer); diff --git a/web/client/reducers/__tests__/mapPopups-test.js b/web/client/reducers/__tests__/mapPopups-test.js index 71d4fc480a..3103212049 100644 --- a/web/client/reducers/__tests__/mapPopups-test.js +++ b/web/client/reducers/__tests__/mapPopups-test.js @@ -37,5 +37,10 @@ describe('mapPopups reducer', () => { expect(state.popups).toExist(); expect(state.popups.length).toBe(0); }); + it('ENABLE_HIDE_EMPTY_POPUP ', () => { + const state = reducer(initialState, ACTIONS.enableHideEmptyPopupOption()); + expect(state.popups).toExist(); + expect(state.hideEmptyPopupOption).toEqual(true); + }); }); diff --git a/web/client/reducers/mapPopups.js b/web/client/reducers/mapPopups.js index b6cbce9b06..1d8103664b 100644 --- a/web/client/reducers/mapPopups.js +++ b/web/client/reducers/mapPopups.js @@ -6,7 +6,7 @@ * LICENSE file in the root directory of this source tree. */ -import {ADD_MAP_POPUP, REMOVE_MAP_POPUP, CLEAN_MAP_POPUPS} from '../actions/mapPopups'; +import {ADD_MAP_POPUP, REMOVE_MAP_POPUP, CLEAN_MAP_POPUPS, ENABLE_HIDE_EMPTY_POPUP} from '../actions/mapPopups'; import {arrayDelete} from '../utils/ImmutableUtils'; const initialState = {popups: []}; @@ -23,6 +23,11 @@ export default function(state = initialState, action) { case CLEAN_MAP_POPUPS: { return {...state, popups: []}; } + case ENABLE_HIDE_EMPTY_POPUP: { + return { + ...state, hideEmptyPopupOption: true + }; + } default: return state; } diff --git a/web/client/selectors/__tests__/mapPopups-test.js b/web/client/selectors/__tests__/mapPopups-test.js new file mode 100644 index 0000000000..0e4efea1f2 --- /dev/null +++ b/web/client/selectors/__tests__/mapPopups-test.js @@ -0,0 +1,28 @@ +/* +* Copyright 2024, 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 { + hideEmptyPopupSelector +} from '../mapPopups'; + +describe('Test mapPopups', () => { + it('test hideEmptyPopupSelector true', () => { + const hideEmptyPopupOption = hideEmptyPopupSelector({mapPopups: {popups: [{"key": "value"}], hideEmptyPopupOption: true}}); + + expect(hideEmptyPopupOption).toExist(); + expect(hideEmptyPopupOption).toBe(true); + }); + it('test hideEmptyPopupSelector false', () => { + const hideEmptyPopupOption = hideEmptyPopupSelector({mapPopups: {popups: [{"key": "value"}], hideEmptyPopupOption: false}}); + + expect(hideEmptyPopupOption).toBeFalsy(); + }); +}); diff --git a/web/client/selectors/mapPopups.js b/web/client/selectors/mapPopups.js new file mode 100644 index 0000000000..38decf9066 --- /dev/null +++ b/web/client/selectors/mapPopups.js @@ -0,0 +1,17 @@ +/* +* Copyright 2024, 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. +*/ + + +/** + * selects mapPopups state + * @name mapPopups + * @memberof selectors + * @static + */ + +export const hideEmptyPopupSelector = (state) => state?.mapPopups && state?.mapPopups?.hideEmptyPopupOption || false; diff --git a/web/client/themes/default/less/map-popup.less b/web/client/themes/default/less/map-popup.less index 06fde5d26f..c703a04b8d 100644 --- a/web/client/themes/default/less/map-popup.less +++ b/web/client/themes/default/less/map-popup.less @@ -33,7 +33,9 @@ .map-popup-ol:before { .border-top-color-var(@theme-vars[main-border-color]); } - + .map-popup-ol:has(.hidePopupIfNoResults), .ms-leaflet-popup:has(.hidePopupIfNoResults) { + display: none; + } .ol-popup-closer { .ms-popup-close-button(); }