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

#10111: Enhance GeoFence attribute rule #10145

Merged
merged 2 commits into from
Apr 4, 2024
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
8 changes: 4 additions & 4 deletions web/client/api/geofence/RuleService.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ const EMPTY_RULE = {
workspace: ""
};

const cleanConstraints = (rule) => {
export const cleanConstraints = (rule) => {
if (!rule.constraints) {
return rule;
} else if (rule.grant === "DENY") {
const { constraints: omit, ...r } = rule;
return r;
}
let constraints = { ...rule.constraints };
constraints.allowedStyles = constraints.allowedStyles && constraints.allowedStyles.style || [];
constraints.attributes = constraints.attributes && constraints.attributes.attribute || [];
constraints.restrictedAreaWkt = constraints.restrictedAreaWkt || "";
constraints.allowedStyles = constraints?.allowedStyles?.style ?? [];
constraints.attributes = constraints?.attributes?.attribute ?? [];
if (!constraints.restrictedAreaWkt) constraints.restrictedAreaWkt = null; // cannot be empty string, may cause API call to fail
return { ...rule, constraints };
};

Expand Down
19 changes: 18 additions & 1 deletion web/client/api/geofence/__tests__/RuleService-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import RULES from 'raw-loader!../../../test-resources/geofence/rest/rules/rules_

import axios from '../../../libs/ajax';
import GF_RULE from '../../../test-resources/geofence/rest/rules/full_rule1.json';
import ruleServiceFactory from '../RuleService';
import ruleServiceFactory, { cleanConstraints } from '../RuleService';

const RuleService = ruleServiceFactory({
addBaseUrl: (opts) => ({...opts, baseURL: BASE_URL}),
Expand Down Expand Up @@ -108,4 +108,21 @@ describe('RuleService API for GeoFence StandAlone', () => {
});
// TODO: updateRules, cleanCache

it("test cleanConstraints", () => {
let rule = {};
expect(cleanConstraints(rule)).toEqual(rule);
const grant = "DENY";
rule = {constraints: "some", grant};
expect(cleanConstraints(rule)).toEqual({grant});
rule = {constraints: {allowedStyles: undefined, attributes: null, restrictedAreaWkt: ""}};
expect(cleanConstraints(rule)).toEqual({constraints: {allowedStyles: [], attributes: [], restrictedAreaWkt: null}});
rule = {constraints: {allowedStyles: {style: {"color": "#000"}}, attributes: {attribute: [{access: "READONLY", name: "ID"}]}, restrictedAreaWkt: "POLYGON((10 10, 10, 20, 20 20, 20 10, 10 10))"}};
expect(cleanConstraints(rule)).toEqual({
constraints: {
allowedStyles: rule.constraints.allowedStyles.style,
attributes: rule.constraints.attributes.attribute,
restrictedAreaWkt: rule.constraints.restrictedAreaWkt
}
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
* LICENSE file in the root directory of this source tree.
*/

import { castArray } from 'lodash';
import React from 'react';
import React, { useEffect } from 'react';
import { Col, Grid, Row } from 'react-bootstrap';
import castArray from 'lodash/castArray';
import isEmpty from 'lodash/isEmpty';

import Message from '../../../I18N/Message';
import Select from '../AttributeAccessSelect';
Expand All @@ -22,12 +23,22 @@ const getAttributeValue = (name, constraints) => {

export default ({attributes = [], constraints = {}, setOption = () => {}, active = false, setEditedAttributes = () => {}, editedAttributes = []}) => {
const onChange = (at) => {
const {attributes: attrs} = constraints;
const attribute = ((attrs && attrs?.attribute?.length) ? attrs.attribute : (attrs?.attribute) ? [attrs.attribute] : [] || []).filter(e => e.name !== at.name).concat(at);
let {attributes: {attribute = []} = {}} = constraints ?? {};
attribute = castArray(attribute).map(attr => at.name === attr.name ? at : attr);
setOption({key: "attributes", value: {attribute}});
// add it to edited attribute
if (!editedAttributes.includes(at.name)) setEditedAttributes(at.name);
};
useEffect(() => {
if (!isEmpty(attributes)) {
const _constraints = attributes.map(attr => ({name: attr.name, access: "READONLY"}));
const {attributes: {attribute = []} = {}} = constraints ?? {};
const modifiedAttribute = _constraints.map(attr => {
return castArray(attribute).find(a=> a.name === attr.name) ?? attr;
});
setOption({key: "attributes", value: {attribute: modifiedAttribute}});
}
}, [attributes]);
return (
<Grid className="ms-rule-editor" fluid style={{ width: '100%', display: active ? 'block' : 'none'}}>
<Row>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React from 'react';

import ReactDOM from 'react-dom';
import expect from 'expect';
import TestUtils from "react-dom/test-utils";
import AttributesEditor from '../AttributesEditor.jsx';
const constraints = {
attributes: {
Expand Down Expand Up @@ -51,6 +52,54 @@ describe('Attributes Editor component', () => {
expect(rows).toExist();
expect(rows.length).toBe(3);
});
it('render attributes on setOption', (done) => {
TestUtils.act(() => {
ReactDOM.render(<AttributesEditor
setOption={(value) => {
try {
expect(value.key).toBe('attributes');
expect(value.value).toEqual({"attribute": [{"name": "the_geom", "access": "READONLY"}, {"access": "READONLY", "name": "cat"}]});
} catch (e) {
done(e);
}
done();
}}
attributes={attributes} active
constraints={constraints}
/>, document.getElementById("container"));
});
const container = document.getElementById('container');
const rows = container.querySelectorAll('.row');
expect(rows).toBeTruthy();
});
it('render attributes on change value', (done) => {
TestUtils.act(() => {
ReactDOM.render(<AttributesEditor
setOption={(value) => {
try {
const isModified = value.value?.attribute?.some(attr => attr.access === 'READWRITE');
if (isModified) {
expect(value.key).toBe('attributes');
expect(value.value).toEqual({"attribute": [{"name": "cat", "access": "READWRITE"}]});
}
} catch (e) {
done(e);
}
done();
}}
attributes={attributes} active
constraints={constraints}
/>, document.getElementById("container"));
});
const container = document.getElementById('container');
const rows = container.querySelectorAll('.row');
expect(rows).toBeTruthy();
const rule = document.querySelectorAll('.Select-control')[1];
expect(rule).toBeTruthy();
TestUtils.Simulate.mouseDown(rule, { button: 0 });
TestUtils.Simulate.keyDown(rule, { keyCode: 40, key: 'ArrowDown' });
TestUtils.Simulate.keyDown(rule, { key: 'Enter', keyCode: 13 });
});
it('render attributes with highlighted DD', () => {
ReactDOM.render(<AttributesEditor editedAttributes={["cat"]} attributes={attributes} active constraints={constraints} />, document.getElementById("container"));
const container = document.getElementById('container');
Expand Down
Loading