diff --git a/assets/index.json b/assets/index.json
index fd1b6f5..4f4d86f 100644
--- a/assets/index.json
+++ b/assets/index.json
@@ -14,7 +14,7 @@
}
},
"dependencies": [
- "BurgerMenu"
+ "SidebarMenu"
]
}
]
diff --git a/js/extension/actions/cadastrapp.js b/js/extension/actions/cadastrapp.js
index e2d5f18..39f1211 100644
--- a/js/extension/actions/cadastrapp.js
+++ b/js/extension/actions/cadastrapp.js
@@ -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
});
/**
diff --git a/js/extension/cadastrapp.css b/js/extension/cadastrapp.css
index 939484d..97ea19d 100644
--- a/js/extension/cadastrapp.css
+++ b/js/extension/cadastrapp.css
@@ -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 {
diff --git a/js/extension/components/misc/panels/DockContainer.jsx b/js/extension/components/misc/panels/DockContainer.jsx
new file mode 100644
index 0000000..bc14197
--- /dev/null
+++ b/js/extension/components/misc/panels/DockContainer.jsx
@@ -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 (
+
+ {children}
+
+ );
+};
+
+export default DockContainer;
diff --git a/js/extension/epics/mapSelection.js b/js/extension/epics/mapSelection.js
index e5b43bd..aace814 100644
--- a/js/extension/epics/mapSelection.js
+++ b/js/extension/epics/mapSelection.js
@@ -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';
@@ -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
@@ -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(
@@ -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.
diff --git a/js/extension/epics/setup.js b/js/extension/epics/setup.js
index 2442eeb..d43a298 100644
--- a/js/extension/epics/setup.js
+++ b/js/extension/epics/setup.js
@@ -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';
@@ -18,8 +18,7 @@ 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,
@@ -27,12 +26,24 @@ import {
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
@@ -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(() => {
@@ -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()] : [])]);
+ });
diff --git a/js/extension/plugins/Extension.jsx b/js/extension/plugins/Extension.jsx
index ea2524d..05beae2 100644
--- a/js/extension/plugins/Extension.jsx
+++ b/js/extension/plugins/Extension.jsx
@@ -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";
@@ -13,6 +13,7 @@ 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);
@@ -20,6 +21,8 @@ const compose = (...functions) => args => functions.reduceRight((arg, fn) => fn(
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),
@@ -48,7 +51,18 @@ export default {
icon: ,
doNotHide: true,
action: toggleControl.bind(null, CONTROL_NAME, null),
- priority: 1
+ priority: 2
+ },
+ SidebarMenu: {
+ name: "cadastrapp",
+ icon: ,
+ tooltip: "cadastrapp.title",
+ text: ,
+ doNotHide: true,
+ action: toggleControl.bind(null, CONTROL_NAME, null),
+ toggle: true,
+ priority: 1,
+ position: 1000
}
}
};
diff --git a/js/extension/plugins/cadastrapp/Main.jsx b/js/extension/plugins/cadastrapp/Main.jsx
index 39f3ca2..8dcdb55 100644
--- a/js/extension/plugins/cadastrapp/Main.jsx
+++ b/js/extension/plugins/cadastrapp/Main.jsx
@@ -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.
@@ -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 (
-
-
-
-
-
);
+ return (
+
+
+ {({ width }) => ( 1 ? width : dockWidth}
+ position="right"
+ bsStyle="primary"
+ style={dockStyle}>
+
+
+
+
+
+
+ )}
+
+
+ );
});
diff --git a/js/extension/selectors/maplayout.js b/js/extension/selectors/maplayout.js
new file mode 100644
index 0000000..2cf3867
--- /dev/null
+++ b/js/extension/selectors/maplayout.js
@@ -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' : ''));