Skip to content

Commit

Permalink
Added details editor styles filters and attributes (#2867)
Browse files Browse the repository at this point in the history
  • Loading branch information
kappu72 authored and offtherailz committed May 7, 2018
1 parent af77da7 commit d5eb5a2
Show file tree
Hide file tree
Showing 39 changed files with 972 additions and 165 deletions.
17 changes: 14 additions & 3 deletions web/client/api/geoserver/GeoFence.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ const assign = require('object-assign');

const ConfigUtils = require('../../utils/ConfigUtils');
const EMPTY_RULE = {
constraints: {},
constraints: {
allowedStyles: {style: []}
},
ipaddress: "",
layer: "",
request: "",
Expand All @@ -20,6 +22,15 @@ const EMPTY_RULE = {
username: "",
workspace: ""
};
const cleanConstraints = (rule) => {
if (!rule.constraints ) {
return rule;
}
let constraints = {...rule.constraints};
constraints.allowedStyles = constraints.allowedStyles && constraints.allowedStyles.style || [];
constraints.attributes = constraints.attributes && constraints.attributes.attribute || [];
return {...rule, constraints};
};
var Api = {

loadRules: function(page, rulesFiltersValues, entries = 10) {
Expand Down Expand Up @@ -72,7 +83,7 @@ var Api = {
if (!newRule.grant) {
newRule.grant = "ALLOW";
}
return axios.post('geofence/rest/rules', newRule, this.addBaseUrl({
return axios.post('geofence/rest/rules', cleanConstraints(newRule), this.addBaseUrl({
'headers': {
'Content': 'application/json'
}
Expand All @@ -83,7 +94,7 @@ var Api = {
// id, priority and grant aren't updatable
const {id, priority, grant, position, ...others} = rule;
const newRule = {...EMPTY_RULE, ...others};
return axios.put(`geofence/rest/rules/id/${id}`, newRule, this.addBaseUrl({
return axios.put(`geofence/rest/rules/id/${id}`, cleanConstraints(newRule), this.addBaseUrl({
'headers': {
'Content': 'application/json'
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright 2018, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
const React = require('react');
const Select = require('react-select');
const defaultOptions = [
{value: 'NONE', label: "NONE"},
{value: 'READONLY', label: 'READ ONLY'},
{value: 'READWRITE', label: 'READ WRITE'}
];

module.exports = ({options = defaultOptions, attribute, value, onChange = () => {}}) => (
<Select
name={`sel-${attribute.name}`}
clearable={false}
searchable={false}
onChange={({value: access}) => onChange({"name": attribute.name, access})}
value={value}
options={options}/>
);
49 changes: 49 additions & 0 deletions web/client/components/manager/rulesmanager/AvailableStyles.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Copyright 2018, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
const React = require('react');
const StylesList = require('./StylesList');
const Message = require("../../I18N/Message");
const Filter = require("../../misc/Filter");
const Portal = require("../../misc/Portal");
const {Col, Button, ButtonGroup} = require("react-bootstrap");
const ResizableModal = require("../../misc/ResizableModal");
const BorderLayout = require("../../layout/BorderLayout");

module.exports = ({styles = [], selectedStyles = [], onSelectionChange = () => {}, show = false, stylesFilter = '', filterPlaceholder = "Filter styles...", clearAll= () => {}, selectAll = () => {}, onFilter = () => {}, onClose = () => {}}) => {
const filteredStyle = stylesFilter && stylesFilter.length > 0 && styles.filter(st => st.title.toLowerCase().match(stylesFilter && stylesFilter.toLowerCase())) || styles;
return (
<Portal>
<div className="rules-manager-modal">
<ResizableModal
title={<Message msgId="rulesmanager.avstyle"/>}
show={show}
onClose={onClose}
>
<span className="ms-style-modal">
<BorderLayout
header={<span>
<Filter filterPlaceholder={filterPlaceholder} filterText={stylesFilter || ''} onFilter={onFilter}/>
<Col className="text-center">
<ButtonGroup>
<Button bsStyle="primary" bsSize="sm" onClick={clearAll}>
<Message msgId="rulesmanager.clearbtn"/>
</Button>
<Button bsStyle="primary" bsSize="sm" onClick={selectAll}>
<Message msgId="rulesmanager.selectbtn"/>
</Button>
</ButtonGroup>
</Col>
</span>}>
<StylesList styles={filteredStyle} selectedStyles={selectedStyles} onSelectionChange={onSelectionChange}/>
</BorderLayout>
</span>
</ResizableModal>
</div>
</Portal>);
};

36 changes: 36 additions & 0 deletions web/client/components/manager/rulesmanager/DefaultStyle.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright 2018, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
const React = require('react');
const StylesList = require('./StylesList');
const Message = require("../../I18N/Message");
const Filter = require("../../misc/Filter");
const Portal = require("../../misc/Portal");
const ResizableModal = require("../../misc/ResizableModal");
const BorderLayout = require("../../layout/BorderLayout");

module.exports = ({styles = [], selectedStyles = [], onSelectionChange = () => {}, show = false, stylesFilter = '', filterPlaceholder = "", onFilter = () => {}, onClose = () => {}}) => {
const filteredStyle = stylesFilter && stylesFilter.length > 0 && styles.filter(st => st.title.toLowerCase().match(stylesFilter && stylesFilter.toLowerCase())) || styles;
return (
<Portal>
<div className="rules-manager-modal">
<ResizableModal
title={<Message msgId="rulesmanager.defstyle"/>}
show={show}
onClose={onClose}
>
<span className="ms-style-modal">
<BorderLayout
header={<span><Filter filterPlaceholder={filterPlaceholder} filterText={stylesFilter} onFilter={onFilter}/></span>}>
<StylesList styles={filteredStyle} selectedStyles={selectedStyles} onSelectionChange={onSelectionChange}/>
</BorderLayout>
</span>
</ResizableModal>
</div>
</Portal>);
};

32 changes: 32 additions & 0 deletions web/client/components/manager/rulesmanager/StylesList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright 2018, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
const React = require('react');
const {Glyphicon} = require('react-bootstrap');
const SideCard = require('../../misc/cardgrids/SideCard');

module.exports = ({styles = [], selectedStyles = [], onSelectionChange = () => {}, className = ""}) => {
return (<span>
{styles.map((r, idx) => {
const isSelected = selectedStyles.filter(st => st === r.name).length > 0;
return (
<div key={idx}>
<SideCard
preview={<Glyphicon glyph={r.preview || 'geoserver'} />}
className={`ms-sm ${isSelected ? 'ms-selected' : ''} ${className}`}
title={r.title}
description={''}
caption={r._abstract || ''}
onClick={() => {
const newSelection = isSelected && selectedStyles.filter( s => s !== r.name) || selectedStyles.concat(r.name);
onSelectionChange(newSelection);
}}/>
</div>
);
})}
</span>);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const Rx = require("rxjs");
const { compose, withStateHandlers, defaultProps, createEventHandler, renameProp} = require('recompose');
const { compose, withStateHandlers, defaultProps, createEventHandler, withProps} = require('recompose');
const propsStreamFactory = require('../../../misc/enhancers/propsStreamFactory');
const {isObject} = require("lodash");
const stop = stream$ => stream$.filter(() => false);
Expand Down Expand Up @@ -111,7 +111,9 @@ module.exports = compose(
}),
withStateHandlers(({paginated, selected, initialData = []}) => ({
val: selected,
typing: false,
page: 0,
stopChange: false,
data: initialData,
emptyReq: 0,
pagination: {
Expand All @@ -121,28 +123,34 @@ module.exports = compose(
loadPrevPage: () => {},
loadNextPage: () => {}
}}), {
resetCombo: ({onValueSelected}, { initialData = []}) => () => {
resetCombo: (state, { initialData = []}) => () => {
return {
data: initialData,
page: 0,
val: undefined,
select: undefined
val: undefined
}; },
setData: ({count: oldCount}) => ({pagination, data, page = 0, count = oldCount} = {}) => ({
pagination,
data,
page,
count
}),
onChange: (state, {initialData = [], valueField}) => (val = "") => {
onChange: ({stopChange, val: oldVal, emptyReq}, {initialData = [], valueField}) => (val = "") => {
if (stopChange) {
return {stopChange: false};
}
const currentVal = isObject(val) && val[valueField] || val;
return currentVal.length === 0 && {val: currentVal, data: initialData} || {val: currentVal};
const newReq = oldVal && oldVal.length > 0 && currentVal.length === 0 ? emptyReq + 1 : emptyReq;
return currentVal.length === 0 && {typing: true, val: currentVal, data: initialData, emptyReq: newReq} || {typing: true, val: currentVal};
},
onToggle: ({ val = "", data, emptyReq}, {selected, onValueSelected, initialData = []}) => (open) => {
if (!open && val === "" && selected) {
onValueSelected();
return {typing: false};
}else if (!open && val !== selected) {
return {val: selected, data: initialData};
return {val: selected, data: initialData, typing: false};
}else if (!open) {
return {typing: false};
}else if (open && val.length === 0 && data.length === 0) {
return {emptyReq: emptyReq + 1};
}
Expand All @@ -152,8 +160,11 @@ module.exports = compose(
if (selectedVal !== selected) {
onValueSelected(selectedVal);
}
return {stopChange: true};
}
}),
propsStreamFactory,
renameProp("val", "selectedValue")
withProps(({val = "", selected = "", typing}) => {
return {selectedValue: typing ? val : selected};
})
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright 2018, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
const {compose, withStateHandlers, defaultProps} = require("recompose");
const withLocal = require("../../../misc/enhancers/localizedProps");

module.exports = compose(
defaultProps({
filterPlaceholder: "rulesmanager.placeholders.filter"
}),
withStateHandlers(({}
) => ({}),
{
onFilter: () => (stylesFilter) => ({
stylesFilter
})

}),
withLocal("filterPlaceholder")
);
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { compose, withStateHandlers, defaultProps, renameProp} = require('recompose');
const { compose, withStateHandlers, defaultProps, withProps} = require('recompose');
const propsStreamFactory = require('../../../misc/enhancers/propsStreamFactory');
const {isObject} = require("lodash");
const stop = stream$ => stream$.filter(() => false);
Expand All @@ -20,46 +20,55 @@ module.exports = compose(
paginated: false,
parentsFilter: {},
filter: "startsWith",
textField: "label",
valueField: "value",
dataStreamFactory,
onValueSelected: () => {},
onError: () => {},
loadingErroMsg: "",
loadingErrorMsg: "",
data: []
}),
withStateHandlers(({paginated, selected}) => ({
val: selected,
typing: false,
stopChange: false,
pagination: {
paginated: paginated,
firstPage: false,
lastPage: false,
loadPrevPage: () => {},
loadNextPage: () => {}
}}), {
resetCombo: (state, {emitOnReset, onValueSelected}) => () => {
if (emitOnReset) {
onValueSelected();
}
resetCombo: () => () => {
return {
val: undefined,
select: undefined
val: undefined
}; },
onChange: () => (val = "") => {
return {val};
onChange: ({stopChange}, {valueField}) => (val = "") => {

if (stopChange) {
return {stopChange: false};
}
const currentVal = isObject(val) && val[valueField] || val;
return {val: currentVal, typing: true};
},
onToggle: ({ val = ""}, {selected, onValueSelected}) => (open) => {
if (!open && val === "" && selected) {
onValueSelected();
return {typing: false};
}else if (!open && val !== selected) {
return {val: selected};
return {val: selected, typing: false};
}
},
onSelect: (state, {onValueSelected, selected, valueField}) => (select) => {
const selectedVal = isObject(select) && select[valueField] || select;
if (selectedVal !== selected) {
onValueSelected(selectedVal);
}
return {stopChange: true};
}
}),
propsStreamFactory,
renameProp("val", "selectedValue")
withProps(({val = "", selected = "", typing}) => {
return {selectedValue: typing ? val : selected};
})
);
Loading

0 comments on commit d5eb5a2

Please sign in to comment.