Skip to content

Commit f108cb2

Browse files
authored
#10111: Enhance GeoFence attribute rule (#10145)
1 parent ad29db2 commit f108cb2

4 files changed

Lines changed: 86 additions & 9 deletions

File tree

web/client/api/geofence/RuleService.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ const EMPTY_RULE = {
2020
workspace: ""
2121
};
2222

23-
const cleanConstraints = (rule) => {
23+
export const cleanConstraints = (rule) => {
2424
if (!rule.constraints) {
2525
return rule;
2626
} else if (rule.grant === "DENY") {
2727
const { constraints: omit, ...r } = rule;
2828
return r;
2929
}
3030
let constraints = { ...rule.constraints };
31-
constraints.allowedStyles = constraints.allowedStyles && constraints.allowedStyles.style || [];
32-
constraints.attributes = constraints.attributes && constraints.attributes.attribute || [];
33-
constraints.restrictedAreaWkt = constraints.restrictedAreaWkt || "";
31+
constraints.allowedStyles = constraints?.allowedStyles?.style ?? [];
32+
constraints.attributes = constraints?.attributes?.attribute ?? [];
33+
if (!constraints.restrictedAreaWkt) constraints.restrictedAreaWkt = null; // cannot be empty string, may cause API call to fail
3434
return { ...rule, constraints };
3535
};
3636

web/client/api/geofence/__tests__/RuleService-test.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import RULES from 'raw-loader!../../../test-resources/geofence/rest/rules/rules_
1414

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

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

111+
it("test cleanConstraints", () => {
112+
let rule = {};
113+
expect(cleanConstraints(rule)).toEqual(rule);
114+
const grant = "DENY";
115+
rule = {constraints: "some", grant};
116+
expect(cleanConstraints(rule)).toEqual({grant});
117+
rule = {constraints: {allowedStyles: undefined, attributes: null, restrictedAreaWkt: ""}};
118+
expect(cleanConstraints(rule)).toEqual({constraints: {allowedStyles: [], attributes: [], restrictedAreaWkt: null}});
119+
rule = {constraints: {allowedStyles: {style: {"color": "#000"}}, attributes: {attribute: [{access: "READONLY", name: "ID"}]}, restrictedAreaWkt: "POLYGON((10 10, 10, 20, 20 20, 20 10, 10 10))"}};
120+
expect(cleanConstraints(rule)).toEqual({
121+
constraints: {
122+
allowedStyles: rule.constraints.allowedStyles.style,
123+
attributes: rule.constraints.attributes.attribute,
124+
restrictedAreaWkt: rule.constraints.restrictedAreaWkt
125+
}
126+
});
127+
});
111128
});

web/client/components/manager/rulesmanager/ruleseditor/AttributesEditor.jsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
import { castArray } from 'lodash';
10-
import React from 'react';
9+
import React, { useEffect } from 'react';
1110
import { Col, Grid, Row } from 'react-bootstrap';
11+
import castArray from 'lodash/castArray';
12+
import isEmpty from 'lodash/isEmpty';
1213

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

2324
export default ({attributes = [], constraints = {}, setOption = () => {}, active = false, setEditedAttributes = () => {}, editedAttributes = []}) => {
2425
const onChange = (at) => {
25-
const {attributes: attrs} = constraints;
26-
const attribute = ((attrs && attrs?.attribute?.length) ? attrs.attribute : (attrs?.attribute) ? [attrs.attribute] : [] || []).filter(e => e.name !== at.name).concat(at);
26+
let {attributes: {attribute = []} = {}} = constraints ?? {};
27+
attribute = castArray(attribute).map(attr => at.name === attr.name ? at : attr);
2728
setOption({key: "attributes", value: {attribute}});
2829
// add it to edited attribute
2930
if (!editedAttributes.includes(at.name)) setEditedAttributes(at.name);
3031
};
32+
useEffect(() => {
33+
if (!isEmpty(attributes)) {
34+
const _constraints = attributes.map(attr => ({name: attr.name, access: "READONLY"}));
35+
const {attributes: {attribute = []} = {}} = constraints ?? {};
36+
const modifiedAttribute = _constraints.map(attr => {
37+
return castArray(attribute).find(a=> a.name === attr.name) ?? attr;
38+
});
39+
setOption({key: "attributes", value: {attribute: modifiedAttribute}});
40+
}
41+
}, [attributes]);
3142
return (
3243
<Grid className="ms-rule-editor" fluid style={{ width: '100%', display: active ? 'block' : 'none'}}>
3344
<Row>

web/client/components/manager/rulesmanager/ruleseditor/__tests__/AttributesEditor-test.jsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import React from 'react';
1010

1111
import ReactDOM from 'react-dom';
1212
import expect from 'expect';
13+
import TestUtils from "react-dom/test-utils";
1314
import AttributesEditor from '../AttributesEditor.jsx';
1415
const constraints = {
1516
attributes: {
@@ -51,6 +52,54 @@ describe('Attributes Editor component', () => {
5152
expect(rows).toExist();
5253
expect(rows.length).toBe(3);
5354
});
55+
it('render attributes on setOption', (done) => {
56+
TestUtils.act(() => {
57+
ReactDOM.render(<AttributesEditor
58+
setOption={(value) => {
59+
try {
60+
expect(value.key).toBe('attributes');
61+
expect(value.value).toEqual({"attribute": [{"name": "the_geom", "access": "READONLY"}, {"access": "READONLY", "name": "cat"}]});
62+
} catch (e) {
63+
done(e);
64+
}
65+
done();
66+
}}
67+
attributes={attributes} active
68+
constraints={constraints}
69+
/>, document.getElementById("container"));
70+
});
71+
const container = document.getElementById('container');
72+
const rows = container.querySelectorAll('.row');
73+
expect(rows).toBeTruthy();
74+
});
75+
it('render attributes on change value', (done) => {
76+
TestUtils.act(() => {
77+
ReactDOM.render(<AttributesEditor
78+
setOption={(value) => {
79+
try {
80+
const isModified = value.value?.attribute?.some(attr => attr.access === 'READWRITE');
81+
if (isModified) {
82+
expect(value.key).toBe('attributes');
83+
expect(value.value).toEqual({"attribute": [{"name": "cat", "access": "READWRITE"}]});
84+
}
85+
} catch (e) {
86+
done(e);
87+
}
88+
done();
89+
}}
90+
attributes={attributes} active
91+
constraints={constraints}
92+
/>, document.getElementById("container"));
93+
});
94+
const container = document.getElementById('container');
95+
const rows = container.querySelectorAll('.row');
96+
expect(rows).toBeTruthy();
97+
const rule = document.querySelectorAll('.Select-control')[1];
98+
expect(rule).toBeTruthy();
99+
TestUtils.Simulate.mouseDown(rule, { button: 0 });
100+
TestUtils.Simulate.keyDown(rule, { keyCode: 40, key: 'ArrowDown' });
101+
TestUtils.Simulate.keyDown(rule, { key: 'Enter', keyCode: 13 });
102+
});
54103
it('render attributes with highlighted DD', () => {
55104
ReactDOM.render(<AttributesEditor editedAttributes={["cat"]} attributes={attributes} active constraints={constraints} />, document.getElementById("container"));
56105
const container = document.getElementById('container');

0 commit comments

Comments
 (0)