From bdb8f0edfb91bb5d199813702edb5d78d85199d4 Mon Sep 17 00:00:00 2001 From: gaetanbrl Date: Thu, 7 Nov 2024 15:26:49 +0100 Subject: [PATCH] Allow or disable geometry layer edition Fix karma Toolbar test fix linter --- .../TOC/fragments/LayerFields/index.jsx | 5 +- .../data/featuregrid/toolbars/Toolbar.jsx | 17 +++---- .../toolbars/__tests__/Toolbar-test.jsx | 47 ++++++++++++------- .../plugins/featuregrid/panels/index.jsx | 4 +- web/client/selectors/featuregrid.js | 22 ++++++++- 5 files changed, 64 insertions(+), 31 deletions(-) diff --git a/web/client/components/TOC/fragments/LayerFields/index.jsx b/web/client/components/TOC/fragments/LayerFields/index.jsx index b0f226f990..208da3744a 100644 --- a/web/client/components/TOC/fragments/LayerFields/index.jsx +++ b/web/client/components/TOC/fragments/LayerFields/index.jsx @@ -59,12 +59,13 @@ const LayerFields = ({ layer, updateFields = () => {}, ...props }) => { }; }, []); - const onChange = (name, attribute, value) => { + const onChange = (name, attribute, value, isGeometryType = false) => { const newFields = fields.map((field) => { if (field.name === name) { return { ...field, - [attribute]: value + [attribute]: value, + ...(isGeometryType ? {isGeometry: true} : {}) }; } return field; diff --git a/web/client/components/data/featuregrid/toolbars/Toolbar.jsx b/web/client/components/data/featuregrid/toolbars/Toolbar.jsx index 47a5b15e19..d8784094c1 100644 --- a/web/client/components/data/featuregrid/toolbars/Toolbar.jsx +++ b/web/client/components/data/featuregrid/toolbars/Toolbar.jsx @@ -61,20 +61,20 @@ const standardButtons = { visible={mode === "EDIT" && !hasChanges && !hasNewFeatures} onClick={events.switchViewMode} glyph="arrow-left"/>), - addFeature: ({disabled, mode, hasNewFeatures, hasChanges, hasSupportedGeometry = true, events = {}}) => ( (), - drawFeature: ({isDrawing = false, disabled, isSimpleGeom, mode, selectedCount, hasGeometry, hasSupportedGeometry = true, events = {}}) => ( (), @@ -103,12 +103,12 @@ const standardButtons = { visible={mode === "EDIT" && hasChanges || hasNewFeatures} onClick={events.clearFeatureEditing} glyph="remove-square"/>), - deleteGeometry: ({disabled, mode, hasGeometry, selectedCount, hasSupportedGeometry = true, events = {}}) => ( (), gridSettings: ({disabled, isColumnsOpen, selectedCount, mode, events = {}}) => ( events.setTimeSync && events.setTimeSync(!timeSync)} glyph="time" />), - snapToFeature: ({snapping, availableSnappingLayers = [], isSnappingLoading, snappingConfig, mode, mapType, editorHeight, pluginCfg, events = {}}) => ( ( { events.toggleSnapping && events.toggleSnapping(!snapping); }} @@ -317,6 +317,7 @@ export default React.memo((props = {}) => { setShowPopoverSync(getApi().getItem("showPopoverSync") !== null && pluginCfg?.showPopoverSync ? getApi().getItem("showPopoverSync") === "true" : pluginCfg?.showPopoverSync); } }, [props.mode]); + // const canEditGeometry = props.isEditingAllowed && return ( {sortBy(buttons.concat(toolbarItems), ["position"]).map(({Component}) => setShowPopoverSync(false)} mode={props?.mode ?? "VIEW"} disabled={props.disableToolbar} />)} diff --git a/web/client/components/data/featuregrid/toolbars/__tests__/Toolbar-test.jsx b/web/client/components/data/featuregrid/toolbars/__tests__/Toolbar-test.jsx index b89bb5cb72..e84afef7bd 100644 --- a/web/client/components/data/featuregrid/toolbars/__tests__/Toolbar-test.jsx +++ b/web/client/components/data/featuregrid/toolbars/__tests__/Toolbar-test.jsx @@ -149,16 +149,21 @@ describe('Featuregrid toolbar component', () => { createFeature: () => {} }; spyOn(events, "createFeature"); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); const el = document.getElementsByClassName("featuregrid-toolbar")[0]; expect(el).toExist(); let addButton = document.getElementById("fg-add-feature"); expect(isVisibleButton(addButton)).toBe(false); addButton.click(); expect(events.createFeature).toHaveBeenCalled(); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); + addButton = document.getElementById("fg-add-feature"); + ReactDOM.render(, document.getElementById("container")); addButton = document.getElementById("fg-add-feature"); expect(isVisibleButton(addButton)).toBe(true); + ReactDOM.render(, document.getElementById("container")); + addButton = document.getElementById("fg-add-feature"); + expect(isVisibleButton(addButton)).toBe(false); ReactDOM.render(, document.getElementById("container")); addButton = document.getElementById("fg-add-feature"); expect(isVisibleButton(addButton)).toBe(false); @@ -172,26 +177,29 @@ describe('Featuregrid toolbar component', () => { startDrawingFeature: () => {} }; spyOn(events, "startDrawingFeature"); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); const el = document.getElementsByClassName("featuregrid-toolbar")[0]; expect(el).toExist(); let button = document.getElementById("fg-draw-feature"); expect(isVisibleButton(button)).toBe(false); button.click(); expect(events.startDrawingFeature).toHaveBeenCalled(); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-draw-feature"); expect(isVisibleButton(button)).toBe(true); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-draw-feature"); expect(isVisibleButton(button)).toBe(false); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); + button = document.getElementById("fg-draw-feature"); + expect(isVisibleButton(button)).toBe(false); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-draw-feature"); expect(isVisibleButton(button)).toBe(true); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-draw-feature"); expect(isVisibleButton(button)).toBe(true); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-draw-feature"); expect(isVisibleButton(button)).toBe(false); }); @@ -257,16 +265,19 @@ describe('Featuregrid toolbar component', () => { expect(isVisibleButton(button)).toBe(false); button.click(); expect(events.deleteGeometry).toHaveBeenCalled(); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-delete-geometry"); expect(isVisibleButton(button)).toBe(false); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); + button = document.getElementById("fg-delete-geometry"); + expect(isVisibleButton(button)).toBe(false); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-delete-geometry"); expect(isVisibleButton(button)).toBe(true); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-delete-geometry"); expect(isVisibleButton(button)).toBe(false); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); button = document.getElementById("fg-delete-geometry"); expect(isVisibleButton(button)).toBe(false); }); @@ -390,15 +401,15 @@ describe('Featuregrid toolbar component', () => { }); describe('snap tool button', () => { it('visibility', () => { - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); expect(document.getElementById("snap-button")).toExist(); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); expect(document.getElementById("snap-button")).toNotExist(); }); it('active/inactive state', () => { - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); expect(document.getElementById("snap-button").className.split(' ')).toInclude('btn-success'); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); expect(document.getElementById("snap-button").className.split(' ')).toNotInclude('btn-success'); }); it('handler', () => { @@ -406,10 +417,10 @@ describe('Featuregrid toolbar component', () => { toggleSnapping: () => { } }; const spy = spyOn(events, "toggleSnapping"); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); document.getElementById("snap-button").click(); expect(spy.calls[0].arguments[0]).toBe(false); - ReactDOM.render(, document.getElementById("container")); + ReactDOM.render(, document.getElementById("container")); document.getElementById("snap-button").click(); expect(spy.calls[1].arguments[0]).toBe(true); }); diff --git a/web/client/plugins/featuregrid/panels/index.jsx b/web/client/plugins/featuregrid/panels/index.jsx index d07fc5af1b..b515a81881 100644 --- a/web/client/plugins/featuregrid/panels/index.jsx +++ b/web/client/plugins/featuregrid/panels/index.jsx @@ -47,7 +47,8 @@ import { timeSyncActive, isViewportFilterActive, isFilterByViewportSupported, - selectedLayerSelector + selectedLayerSelector, + canEditGeometrySelector } from '../../../selectors/featuregrid'; import { mapLayoutValuesSelector } from '../../../selectors/maplayout'; import {isCesium, mapTypeSelector} from '../../../selectors/maptype'; @@ -95,6 +96,7 @@ const Toolbar = connect( disableZoomAll: (state) => state && state.featuregrid.virtualScroll || featureCollectionResultSelector(state).features.length === 0, isSearchAllowed: (state) => !isCesium(state), isEditingAllowed: isEditingAllowedSelector, + canEditGeometry: canEditGeometrySelector, hasSupportedGeometry, isFilterActive, showTimeSyncButton: showTimeSync, diff --git a/web/client/selectors/featuregrid.js b/web/client/selectors/featuregrid.js index 8f460fa483..cdf6275d27 100644 --- a/web/client/selectors/featuregrid.js +++ b/web/client/selectors/featuregrid.js @@ -6,7 +6,7 @@ * LICENSE file in the root directory of this source tree. */ -import { head, get, isObject } from 'lodash'; +import { head, get, isObject, find } from 'lodash'; import { getLayerFromId } from './layers'; import { findGeometryProperty } from '../utils/ogc/WFS/base'; @@ -14,7 +14,7 @@ import { currentLocaleSelector } from './locale'; import { isSimpleGeomType } from '../utils/MapUtils'; import { toChangesMap } from '../utils/FeatureGridUtils'; import { layerDimensionSelectorCreator } from './dimension'; -import { isUserAllowedSelectorCreator } from './security'; +import { isUserAllowedSelectorCreator, userGroupsEnabledSelector, userRoleSelector } from './security'; import {isCesium, mapTypeSelector} from './maptype'; import { attributesSelector, describeSelector } from './query'; import { createShallowSelectorCreator } from "../utils/ReselectUtils"; @@ -202,6 +202,24 @@ export const isEditingAllowedSelector = (state) => { })(state); return (canEdit || isAllowed) && !isCesium(state); }; +// geometry can be editing according to geom field setting +export const canEditGeometrySelector = (state) => { + const fields = selectedLayerFieldsSelector(state); + const geomField = find(fields, {isGeometry: true}); + const canEdit = isEditingAllowedSelector(state); + + const userRole = userRoleSelector(state); + const userGroups = userGroupsEnabledSelector(state); + const spreadList = [userRole, ...userGroups]; + + let geomEditors = geomField?.allowedEditorsRoles; + if (!geomEditors) { + return canEdit; + } + geomEditors = geomEditors.split(","); + return geomEditors.some(value => spreadList.includes(value)); +}; + export const paginationSelector = state => get(state, "featuregrid.pagination"); export const useLayerFilterSelector = state => get(state, "featuregrid.useLayerFilter", true);