Skip to content

Commit

Permalink
Applying necessary changes to cadastrapp to support MapStore layout c…
Browse files Browse the repository at this point in the history
…hanges (#156)

* Cadastrapp changes to support new SidebarMenu plugin

* Minor fixes and priority change for BurgerMenu

* Make cadastrapp write to layout.rightPanel property to make it's possible to track if cadastrapp panel is open.

* - Fix of dependency for cadastrapp;
- Making menu item toggleable;
- Alternative set of actions for cadastrapp when tool should be toggled without affecting drawing status
- Close feature editor when cadastrapp is open.
- Reset annotation editing session when cadastrapp selection tool is activated.
- Toggle cadastrapp tool off when annotation triggers drawing.

* Function documentation

* Merging epics into one.
  • Loading branch information
alexander-fedorenko authored May 10, 2022
1 parent d0ea5e9 commit c0e3237
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 37 deletions.
2 changes: 1 addition & 1 deletion assets/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
}
},
"dependencies": [
"BurgerMenu"
"SidebarMenu"
]
}
]
Expand Down
6 changes: 4 additions & 2 deletions js/extension/actions/cadastrapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@ export const tearDown = () => ({
/**
* Toggles map selection in one of the modes available
* @param {string} selectionType type of selection (constants.SELECTION_TYPES)
* @param {boolean} resetDraw should it reset draw status or not
*/
export const toggleSelectionTool = (selectionType) => ({
export const toggleSelectionTool = (selectionType, resetDraw = true) => ({
type: TOGGLE_SELECTION,
selectionType
selectionType,
resetDraw
});

/**
Expand Down
4 changes: 2 additions & 2 deletions js/extension/cadastrapp.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
overflow: hidden;
top: 0;
right: 0;
height: calc(100% - 30px);
width: 660px;
height: 100%;
width: 100%;
z-index: 1000;
}
.cadastrapp .top {
Expand Down
33 changes: 33 additions & 0 deletions js/extension/components/misc/panels/DockContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import classnames from "classnames";

/**
* Wrapper for DockablePanel with main intension to support applying of custom styling to make dock panels have proper
* offset depending on the sidebars presence on the page
* @memberof components.misc.panels
* @name DockContainer
* @param id {string} - id applied to the container
* @param children {JSX.Element}
* @param dockStyle {object} - style object obtained from mapLayoutValuesSelector and used to calculate offsets
* @param className {string} - class name
* @param style - style object to apply to the container. Can be used to overwrite styles applied by dockStyle calculations
* @returns {JSX.Element}
* @constructor
*/
const DockContainer = ({ id, children, dockStyle, className, style = {}}) => {
const persistentStyle = {
width: `calc(100% - ${(dockStyle?.right ?? 0) + (dockStyle?.left ?? 0)}px)`,
transform: `translateX(-${(dockStyle?.right ?? 0)}px)`,
pointerEvents: 'none'
};
return (
<div id={id} className={classnames({
...(className ? {[className]: true} : {}),
'dock-container': true
})} style={{...persistentStyle, ...style}}>
{children}
</div>
);
};

export default DockContainer;
15 changes: 11 additions & 4 deletions js/extension/epics/mapSelection.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
} from '../selectors/cadastrapp';
import { getLayerJSONFeature } from '@mapstore/observables/wfs';
import { wrapStartStop } from '@mapstore/observables/epics';
import { MOUSE_MOVE, MOUSE_OUT, registerEventListener, unRegisterEventListener } from '@mapstore/actions/map';
import {MOUSE_MOVE, MOUSE_OUT, unRegisterEventListener} from '@mapstore/actions/map';
import { addPopup, cleanPopups } from '@mapstore/actions/mapPopups';
import { mapSelector } from '@mapstore/selectors/map';

Expand All @@ -46,11 +46,18 @@ const CLEAN_ACTION = changeDrawingStatus("clean");
const DEACTIVATE_ACTIONS = [
CLEAN_ACTION,
changeDrawingStatus("stop"),
registerEventListener(MOUSE_EVENT, CONTROL_NAME),
unRegisterEventListener(MOUSE_EVENT, CONTROL_NAME),
loading(0, "plotSelection") // reset loading if stopped due to close
];
export const ON_DRAW_DEACTIVATE_ACTIONS = [
unRegisterEventListener(MOUSE_EVENT, CONTROL_NAME),
loading(0, "plotSelection") // reset loading if stopped due to close
];

const deactivate = () => Rx.Observable.from(DEACTIVATE_ACTIONS);

export const deactivateOnAnotherDraw = () => Rx.Observable.from(ON_DRAW_DEACTIVATE_ACTIONS);

/**
* Extract the drawMethod for DrawSupport from the method
* @param {string} selection the current tool selected
Expand Down Expand Up @@ -123,7 +130,7 @@ const getGeometry = point => {
* Handle map selection tools and events
*/
export const cadastrappMapSelection = (action$, {getState = () => {}}) =>
action$.ofType(TOGGLE_SELECTION).switchMap(({selectionType}) => {
action$.ofType(TOGGLE_SELECTION).switchMap(({selectionType, resetDraw}) => {
if (selectionType) {
const startDrawingAction = changeDrawingStatus('start', drawMethod(selectionType), 'cadastrapp', [], { stopAfterDrawing: true });
return action$.ofType(END_DRAWING).flatMap(
Expand Down Expand Up @@ -178,7 +185,7 @@ export const cadastrappMapSelection = (action$, {getState = () => {}}) =>
.concat(deactivate()); // on close, deactivate any draw session remaining
}
// if the selection type is not present, it means has been reset, so deactivate any drawing tool
return deactivate();
return !resetDraw ? deactivateOnAnotherDraw() : deactivate();
});
/**
* Retrieves the geometry of the ufFeature, when not present, and shows the LandedPropertyInformation with this data.
Expand Down
95 changes: 76 additions & 19 deletions js/extension/epics/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { wrapStartStop } from '@mapstore/observables/epics';
import { error } from '@mapstore/actions/notifications';
import { updateAdditionalLayer, removeAdditionalLayer } from '@mapstore/actions/additionallayers';
import { hideMapinfoMarker, toggleMapInfoState } from '@mapstore/actions/mapInfo';
import { UPDATE_MAP_LAYOUT, updateMapLayout } from '../../../MapStore2/web/client/actions/maplayout';
import { UPDATE_MAP_LAYOUT, updateMapLayout } from '@mapstore/actions/maplayout';

import { registerEventListener, unRegisterEventListener } from '@mapstore/actions/map';
import { cleanPopups } from '@mapstore/actions/mapPopups';
Expand All @@ -18,21 +18,32 @@ import {
} from '../constants';

import { getConfiguration } from '../api';
import get from 'lodash/get';
import { configurationSelector } from '../selectors/cadastrapp';
import {findIndex, keys, get} from "lodash";

import {
SETUP,
TEAR_DOWN,
setConfiguration,
setupCompleted,
loading,
toggleSelectionTool
toggleSelectionTool, TOGGLE_SELECTION
} from '../actions/cadastrapp';
import { SET_CONTROL_PROPERTIES, setControlProperty } from '@mapstore/actions/controls';
import {
SET_CONTROL_PROPERTIES,
SET_CONTROL_PROPERTY,
TOGGLE_CONTROL,
setControlProperty
} from '@mapstore/actions/controls';
import {closeFeatureGrid, OPEN_FEATURE_GRID} from "@mapstore/actions/featuregrid";
import {resetCoordEditor, START_DRAWING} from "@mapstore/actions/annotations";
import {configurationSelector, currentSelectionToolSelector} from '../selectors/cadastrapp';
import {isFeatureGridOpen} from "@mapstore/selectors/featuregrid";
import {coordinateEditorEnabledSelector} from "@mapstore/selectors/annotations";
import {CHANGE_DRAWING_STATUS} from "@mapstore/actions/draw";

// size o
const OFFSET = 660; // size of cadastrapp. Maybe parametrize. Now in css + this constant
const OFFSET = 550; // size of cadastrapp. Maybe parametrize. Now in css + this constant
const shutdownList = ['metadataexplorer', 'measure', 'details', 'mapcatalog', 'maptemplates', 'userExtensions', 'FeatureEditor'];

/**
* utility function to check if the cadastrapp panel is open
Expand All @@ -54,7 +65,8 @@ export const cadastrappSetup = (action$, store) =>
let initStream$ = Rx.Observable.defer(() => getConfiguration())
.switchMap(data => {
return Rx.Observable.of(setConfiguration(data));
});
})
.startWith(...(isFeatureGridOpen ? [closeFeatureGrid()] : []));
const mapInfoEnabled = get(store.getState(), "mapInfo.enabled");
return initStream$.concat(
Rx.Observable.defer(() => {
Expand Down Expand Up @@ -123,34 +135,79 @@ export const cadastrappMapLayout = (action$, store) =>
})
.map(({layout}) => {
const action = updateMapLayout({
layout,
right: OFFSET,
...layout,
right: OFFSET + (layout?.right ?? 0),
boundingMapRect: {
...(layout.boundingMapRect || {}),
right: OFFSET
}
right: OFFSET + (layout?.boundingSidebarRect?.right ?? 0)
},
rightPanel: true
});
return { ...action, source: 'cadastrapp' }; // add an argument to avoid infinite loop.
});

export const cadastrappCloseAnnotationsOnToolToggledOn = (action$, store) =>
action$.ofType(TOGGLE_SELECTION)
.filter(({ selectionType }) => !!selectionType && coordinateEditorEnabledSelector(store.getState())
)
.map(() => {
return resetCoordEditor();
});

/**
* Auto-closes cadastrapp when catalog is open
* Auto-closes cadastrapp when one of the shutdown-trigger tools is open or when Feature editor is open
*/
export const cadastrappAutoClose = (action$, store) =>
action$.ofType(SET_CONTROL_PROPERTIES)
action$.ofType(SET_CONTROL_PROPERTIES, SET_CONTROL_PROPERTY, TOGGLE_CONTROL, OPEN_FEATURE_GRID)
.filter(() => isCadastrappOpen(store))
.filter(({ control, properties }) => control === "metadataexplorer" && properties?.enabled) // open the catalog from TOC
.map( () => setControlProperty(CONTROL_NAME, "enabled", false));
.filter(({control, property, properties = [], type}) => {
const state = store.getState();
const controlState = state.controls[control]?.enabled;
switch (type) {
case OPEN_FEATURE_GRID:
return true;
case SET_CONTROL_PROPERTY:
case TOGGLE_CONTROL:
return (property === 'enabled' || !property) && controlState && shutdownList.includes(control);
default:
return findIndex(keys(properties), prop => prop === 'enabled') > -1 && controlState && shutdownList.includes(control);
}
})
.map( () => {
return setControlProperty(CONTROL_NAME, "enabled", false);
});

export const toggleCadastrapToolOnAnnotationsDrawing = (action$, store) =>
action$.ofType(START_DRAWING, CHANGE_DRAWING_STATUS)
.filter(({type, status, owner}) => {
const currentSelectionTool = currentSelectionToolSelector(store.getState());
switch (type) {
case CHANGE_DRAWING_STATUS:
return !!currentSelectionTool && status === 'drawOrEdit' && owner === 'annotations';
case START_DRAWING:
default:
return !!currentSelectionTool;
}
})
.switchMap( () => {
let actions = [
toggleSelectionTool(null, false)
];
return Rx.Observable.from(actions);
});

/**
* Intercept cadastrapp close event.
* - Removes the cadastre layer from the map
*/
export const cadastrappTearDown = (action$, {getState = ()=>{}}) =>
action$.ofType(TEAR_DOWN).switchMap(() =>
Rx.Observable.from([
toggleSelectionTool(),
action$.ofType(TEAR_DOWN).switchMap(() => {
const cadastrappIsDrawOwner = get(getState(), 'draw.drawOwner', false) === 'cadastrapp';
return Rx.Observable.from([
toggleSelectionTool(null, cadastrappIsDrawOwner),
removeAdditionalLayer({id: CADASTRAPP_RASTER_LAYER_ID, owner: CADASTRAPP_OWNER}),
removeAdditionalLayer({id: CADASTRAPP_VECTOR_LAYER_ID, owner: CADASTRAPP_OWNER}),
cleanPopups(),
unRegisterEventListener(MOUSE_EVENT, CONTROL_NAME) // Reset map's mouse event trigger
]).concat([...(!get(getState(), "mapInfo.enabled") ? [toggleMapInfoState()] : [])]));
]).concat([...(!get(getState(), "mapInfo.enabled") ? [toggleMapInfoState()] : [])]);
});
18 changes: 16 additions & 2 deletions js/extension/plugins/Extension.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { connect } from "react-redux";
import { setControlProperty, toggleControl } from "@mapstore/actions/controls";
import { toggleControl } from "@mapstore/actions/controls";

import {Glyphicon} from 'react-bootstrap';
import Message from "@mapstore/components/I18N/Message";
Expand All @@ -13,13 +13,16 @@ import { CONTROL_NAME } from '../constants';
import {setUp, tearDown} from '../actions/cadastrapp';
import cadastrapp from '../reducers/cadastrapp';
import * as epics from '../epics/cadastrapp';
import {mapLayoutValuesSelector} from "@js/extension/selectors/maplayout";

const compose = (...functions) => args => functions.reduceRight((arg, fn) => fn(arg), args);


const Cadastrapp = compose(
connect((state) => ({
enabled: state.controls && state.controls[CONTROL_NAME] && state.controls[CONTROL_NAME].enabled || false,
dockStyle: mapLayoutValuesSelector(state, { right: true, height: true}, true),
dockWidth: 550,
withButton: false
}), {
open: () => toggleControl(CONTROL_NAME, "enabled", true),
Expand Down Expand Up @@ -48,7 +51,18 @@ export default {
icon: <Glyphicon glyph="th" />,
doNotHide: true,
action: toggleControl.bind(null, CONTROL_NAME, null),
priority: 1
priority: 2
},
SidebarMenu: {
name: "cadastrapp",
icon: <Glyphicon glyph="th" />,
tooltip: "cadastrapp.title",
text: <Message msgId="cadastrapp.title"/>,
doNotHide: true,
action: toggleControl.bind(null, CONTROL_NAME, null),
toggle: true,
priority: 1,
position: 1000
}
}
};
34 changes: 27 additions & 7 deletions js/extension/plugins/cadastrapp/Main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import Header from './Header';
import { CONTROL_NAME } from '../../constants';
import LandedProperty from './LandedProperty';
import {configurationSelector} from "@js/extension/selectors/cadastrapp";
import DockPanel from "@mapstore/components/misc/panels/DockPanel";
import ContainerDimensions from "react-container-dimensions";
import DockContainer from "@js/extension/components/misc/panels/DockContainer";

/**
* Main Container of Cadastrapp.
Expand All @@ -16,14 +19,31 @@ import {configurationSelector} from "@js/extension/selectors/cadastrapp";
export default connect(state => ({
enabled: state.controls && state.controls[CONTROL_NAME] && state.controls[CONTROL_NAME].enabled || false,
configuration: configurationSelector(state)
}))(function Main({ enabled, ...props }) {
}))(function Main({ enabled, dockStyle, dockWidth, ...props }) {
if (!enabled) {
return null;
}
return (<div className="cadastrapp">
<Header/>
<MainToolbar {...props} />
<MainPanel {...props} />
<LandedProperty />
</div>);
return (
<DockContainer
dockStyle={dockStyle}
id="cadastrapp-container"
style={{pointerEvents: 'none'}}
>
<ContainerDimensions>
{({ width }) => (<DockPanel
open
size={dockWidth / width > 1 ? width : dockWidth}
position="right"
bsStyle="primary"
style={dockStyle}>
<div className="cadastrapp">
<Header/>
<MainToolbar {...props} />
<MainPanel {...props} />
<LandedProperty />
</div>
</DockPanel>)}
</ContainerDimensions>
</DockContainer>
);
});
29 changes: 29 additions & 0 deletions js/extension/selectors/maplayout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {mapLayoutSelector} from "@mapstore/selectors/maplayout";
import {memoize} from "lodash";

export const boundingSidebarRectSelector = (state) => state.maplayout && state.maplayout.boundingSidebarRect || {};

/**
* Retrieve only specific attribute from map layout
* @function
* @memberof selectors.mapLayout
* @param {object} state the state
* @param {object} attributes attributes to retrieve, bool {left: true}
* @param {boolean} isDock flag to use dock paddings instead of toolbar paddings
* @return {object} selected attributes of layout of the map
*/
export const mapLayoutValuesSelector = memoize((state, attributes = {}, isDock = false) => {
const layout = mapLayoutSelector(state);
const boundingSidebarRect = boundingSidebarRectSelector(state);
return layout && Object.keys(layout).filter(key =>
attributes[key]).reduce((a, key) => {
if (isDock) {
return ({...a, [key]: (boundingSidebarRect[key] ?? layout[key])});
}
return ({...a, [key]: layout[key]});
},
{}) || {};
}, (state, attributes, isDock) =>
JSON.stringify(mapLayoutSelector(state)) +
JSON.stringify(boundingSidebarRectSelector(state)) +
JSON.stringify(attributes) + (isDock ? '_isDock' : ''));

0 comments on commit c0e3237

Please sign in to comment.