Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Applying necessary changes to cadastrapp to support MapStore layout changes #156

Merged
merged 6 commits into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why need this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This basically is the copy of selector from upstream repo. isDock needed to apply offset from the right equal to sidebar width. If it's false - sidebar width + panel width offset is applied instead.

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' : ''));