Skip to content

Commit

Permalink
geosolutions-it#10545: Option to disable identify popup in case of no…
Browse files Browse the repository at this point in the history
… results (geosolutions-it#10557)

* geosolutions-it#10545: Option to disable identify popup in case of no results
Description:
- handle adding an option called 'hidePopupIfNoResults' to hide the identify popup
- add unit tests
- add jsdoc

* geosolutions-it#10545: Option to disable identify popup in case of no results
Description:
- revert changes in popupSupport files for ol and leaflet + related tests files
- handle hide popup for map viewer with css for openlayers and leaflet approach
- add unit tests
- edit map-popup.less file to handle hide the popup

* geosolutions-it#10545: revert unnecessary changes
  • Loading branch information
mahmoudadel54 authored Oct 14, 2024
1 parent 554aa9b commit c5ed4d0
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 15 deletions.
4 changes: 4 additions & 0 deletions web/client/actions/__tests__/mapPopups-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});

5 changes: 5 additions & 0 deletions web/client/actions/mapPopups.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -26,3 +27,7 @@ export const removePopup = (id) => ({
export const cleanPopups = () => ({
type: CLEAN_MAP_POPUPS
});

export const enableHideEmptyPopupOption = () => ({
type: ENABLE_HIDE_EMPTY_POPUP
});
9 changes: 7 additions & 2 deletions web/client/components/data/identify/DefaultViewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -64,7 +65,8 @@ class DefaultViewer extends React.Component {
onPrevious: () => {},
setIndex: () => {},
isMobile: false,
disableInfoAlert: false
disableInfoAlert: false,
hidePopupIfNoResults: false
};

shouldComponentUpdate(nextProps) {
Expand Down Expand Up @@ -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 <span className="hidePopupIfNoResults"/>;
}
return (
<Alert bsStyle={"danger"}>
<h4><HTML msgId="noFeatureInfo"/></h4>
Expand Down
8 changes: 5 additions & 3 deletions web/client/components/data/identify/PopupViewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -46,16 +47,17 @@ 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,
format,
showEmptyMessageGFI,
missingResponses: (requests || []).length - (responses || []).length,
renderValidOnly,
loaded
loaded,
hidePopupIfNoResults
}));


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
<DefaultViewer hidePopupIfNoResults responses={responses} header={SwipeHeader}/>,
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();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => <div id="test-component"></div>);
const testHandlers = {
enableHideEmptyPopupOption: () => {}
};
const spyEnableHideEmptyPopupOption = expect.spyOn(testHandlers, 'enableHideEmptyPopupOption');
ReactDOM.render(
<Component enabled responses={[{}]} hidePopupIfNoResults enableHideEmptyPopupOption={testHandlers.enableHideEmptyPopupOption}/>,
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);
Expand Down
7 changes: 6 additions & 1 deletion web/client/components/data/identify/enhancers/identify.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ export const identifyLifecycle = compose(
setShowInMapPopup = () => {},
checkIdentifyIsMounted = () => {},
onInitPlugin = () => {},
pluginCfg = {}
pluginCfg = {},
enableHideEmptyPopupOption = () => {},
hidePopupIfNoResults = false
} = this.props;

// Initialize plugin configuration
Expand All @@ -91,6 +93,9 @@ export const identifyLifecycle = compose(
showAllResponses,
highlight: pluginCfg?.highlightEnabledFromTheStart || false
});
if (hidePopupIfNoResults) {
enableHideEmptyPopupOption(true);
}
if (enabled || showInMapPopup) {
changeMousePointer('pointer');
checkIdentifyIsMounted(true);
Expand Down
5 changes: 4 additions & 1 deletion web/client/plugins/Identify.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -265,7 +267,8 @@ const IdentifyPlugin = compose(
identifyIndex,
defaultViewerHandlers,
connect(() => ({}), {
setShowInMapPopup
setShowInMapPopup,
enableHideEmptyPopupOption
}),
identifyLifecycle
)(IdentifyContainer);
Expand Down
9 changes: 4 additions & 5 deletions web/client/plugins/map/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { projectionDefsSelector, isMouseMoveActiveSelector } from '../../selecto
import {
snappingLayerSelector
} from "../../selectors/draw";
import { mapPopupsSelector } from '../../selectors/mapPopups';

const Empty = () => { return <span/>; };

Expand Down Expand Up @@ -101,13 +102,11 @@ const pluginsCreator = (mapType, actions) => {

const LLayer = connect(null, {onWarning: warning})( components.Layer || Empty);

const EMPTY_POPUPS = [];
const PopupSupport = connect(
createSelector(
(state) => state.mapPopups && state.mapPopups.popups || EMPTY_POPUPS,
(popups) => ({
popups
})), {
mapPopupsSelector,
(popups) => ({popups})
), {
onPopupClose: removePopup
}
)(components.PopupSupport || Empty);
Expand Down
6 changes: 5 additions & 1 deletion web/client/reducers/__tests__/mapPopups-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ 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);
});
});
7 changes: 6 additions & 1 deletion web/client/reducers/mapPopups.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: []};
Expand All @@ -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;
}
Expand Down
36 changes: 36 additions & 0 deletions web/client/selectors/__tests__/mapPopups-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 {
mapPopupsSelector,
hideEmptyPopupSelector
} from '../mapPopups';

describe('Test mapPopups', () => {
it('test mapPopupsSelector', () => {
const popups = mapPopupsSelector({mapPopups: {popups: [{"key": "value"}]}});

expect(popups).toExist();
expect(popups).toEqual([{key: "value"}]);
});

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();
});
});
18 changes: 18 additions & 0 deletions web/client/selectors/mapPopups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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 mapPopupsSelector = (state) => state?.mapPopups && state?.mapPopups?.popups || [];
export const hideEmptyPopupSelector = (state) => state?.mapPopups && state?.mapPopups?.hideEmptyPopupOption || false;
4 changes: 3 additions & 1 deletion web/client/themes/default/less/map-popup.less
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down

0 comments on commit c5ed4d0

Please sign in to comment.