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

Allow editing by fields and set fields value from general fields settings #10524

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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: 8 additions & 0 deletions web/client/actions/featuregrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const LOAD_MORE_FEATURES = "LOAD_MORE_FEATURES";
export const GRID_QUERY_RESULT = 'FEATUREGRID:QUERY_RESULT';
export const SET_TIME_SYNC = "FEATUREGRID:SET_TIME_SYNC";
export const SET_PAGINATION = "FEATUREGRID:SET_PAGINATION";
export const GRID_ROW_UPDATE = "FEATUREGRID:GRID_ROW_UPDATE";

export function toggleShowAgain() {
return {
Expand Down Expand Up @@ -262,6 +263,13 @@ export function featureModified(features, updated) {
updated
};
}
export function gridRowUpdate(features, updated) {
return {
type: GRID_ROW_UPDATE,
features,
updated
};
}
export function createNewFeatures(features) {
return {
type: CREATE_NEW_FEATURE,
Expand Down
5 changes: 3 additions & 2 deletions web/client/components/TOC/fragments/LayerFields/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class AutocompleteEditor extends AttributeEditor {
autocompleteStreamFactory: PropTypes.func,
url: PropTypes.string,
typeName: PropTypes.string,
value: PropTypes.string
value: PropTypes.string,
disabled: PropTypes.bool
};
static defaultProps = {
isValid: () => true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class DateTimeEditor extends AttributeEditor {
calendar: PropTypes.bool,
time: PropTypes.bool,
onChange: PropTypes.func,
onBlur: PropTypes.func
onBlur: PropTypes.func,
disabled: PropTypes.bool
};

static contextTypes = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class DropDownEditor extends AttributeEditor {
filter: PropTypes.string,
values: PropTypes.array,
labels: PropTypes.array,
emptyValue: PropTypes.string
emptyValue: PropTypes.string,
disabled: PropTypes.bool
};
static defaultProps = {
isValid: () => true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export default class FormatEditor extends React.Component {
dataType: PropTypes.string,
column: PropTypes.object,
formatRegex: PropTypes.string,
onTemporaryChanges: PropTypes.func
onTemporaryChanges: PropTypes.func,
disabled: PropTypes.bool
};

static defaultProps = {
Expand Down Expand Up @@ -61,6 +62,7 @@ export default class FormatEditor extends React.Component {
render() {
return (<input
{...this.props.inputProps}
disabled={this.props?.disabled}
style={!this.state.validated || this.state.isValid ? {} : {
borderColor: 'red'
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export default class NumberEditor extends React.Component {
minValue: PropTypes.number,
maxValue: PropTypes.number,
column: PropTypes.object,
onTemporaryChanges: PropTypes.func
onTemporaryChanges: PropTypes.func,
disabled: PropTypes.bool
};

static defaultProps = {
Expand Down Expand Up @@ -80,6 +81,7 @@ export default class NumberEditor extends React.Component {
render() {
return (<IntlNumberFormControl
{...this.props.inputProps}
disabled={this.props?.disabled}
style={!this.state.validated || this.state.isValid ? {} : {
borderColor: 'red'
}}
Expand Down
8 changes: 5 additions & 3 deletions web/client/components/data/featuregrid/enhancers/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,13 @@ const featuresToGrid = compose(
options: props.options?.propertyName
}, {
getHeaderRenderer,
getEditor: (desc) => {
getEditor: (desc, field) => {
const generalProps = {
onTemporaryChanges: props.gridEvents && props.gridEvents.onTemporaryChanges,
autocompleteEnabled: props.autocompleteEnabled,
url: props.url,
typeName: props.typeName
typeName: props.typeName,
disabled: field && field?.editable === false
};
const regexProps = {attribute: desc.name, url: props.url, typeName: props.typeName};
const rules = props.customEditorsOptions && props.customEditorsOptions.rules || [];
Expand All @@ -169,7 +170,8 @@ const featuresToGrid = compose(
if (!isNil(editor)) {
return editor;
}
return props.editors(desc.localType, generalProps);
const typeEditor = props.editors(desc.localType, generalProps);
return typeEditor;
},
getFilterRenderer: getFilterRendererFunc,
getFormatter: (desc) => getFormatter(desc, (props.fields ?? []).find(f => f.name === desc.name)),
Expand Down
17 changes: 9 additions & 8 deletions web/client/components/data/featuregrid/toolbars/Toolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}}) => (<TButton
addFeature: ({disabled, mode, hasNewFeatures, hasChanges, canEditGeometry, hasSupportedGeometry = true, events = {}}) => (<TButton
id="add-feature"
keyProp="add-feature"
tooltipId="featuregrid.toolbar.addNewFeatures"
disabled={disabled}
visible={mode === "EDIT" && !hasNewFeatures && !hasChanges && hasSupportedGeometry}
visible={mode === "EDIT" && canEditGeometry && !hasNewFeatures && !hasChanges && hasSupportedGeometry}
onClick={events.createFeature}
glyph="row-add"/>),
drawFeature: ({isDrawing = false, disabled, isSimpleGeom, mode, selectedCount, hasGeometry, hasSupportedGeometry = true, events = {}}) => (<TButton
drawFeature: ({isDrawing = false, disabled, isSimpleGeom, mode, selectedCount, canEditGeometry, hasGeometry, hasSupportedGeometry = true, events = {}}) => (<TButton
id="draw-feature"
keyProp="draw-feature"
tooltipId={getDrawFeatureTooltip(isDrawing, isSimpleGeom)}
disabled={disabled}
visible={mode === "EDIT" && selectedCount === 1 && (!hasGeometry || hasGeometry && !isSimpleGeom) && hasSupportedGeometry}
visible={mode === "EDIT" && selectedCount === 1 && canEditGeometry && (!hasGeometry || hasGeometry && !isSimpleGeom) && hasSupportedGeometry}
onClick={events.startDrawingFeature}
active={isDrawing}
glyph="pencil-add"/>),
Expand Down Expand Up @@ -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 = {}}) => (<TButton
deleteGeometry: ({disabled, mode, hasGeometry, selectedCount, canEditGeometry, hasSupportedGeometry = true, events = {}}) => (<TButton
id="delete-geometry"
keyProp="delete-geometry"
tooltipId="featuregrid.toolbar.deleteGeometry"
disabled={disabled}
visible={mode === "EDIT" && hasGeometry && selectedCount === 1 && hasSupportedGeometry}
visible={mode === "EDIT" && hasGeometry && selectedCount === 1 && hasSupportedGeometry && canEditGeometry}
onClick={events.deleteGeometry}
glyph="polygon-trash"/>),
gridSettings: ({disabled, isColumnsOpen, selectedCount, mode, events = {}}) => (<TButton
Expand Down Expand Up @@ -170,11 +170,11 @@ const standardButtons = {
active={timeSync}
onClick={() => events.setTimeSync && events.setTimeSync(!timeSync)}
glyph="time" />),
snapToFeature: ({snapping, availableSnappingLayers = [], isSnappingLoading, snappingConfig, mode, mapType, editorHeight, pluginCfg, events = {}}) => (<TSplitButton
snapToFeature: ({snapping, availableSnappingLayers = [], canEditGeometry, isSnappingLoading, snappingConfig, mode, mapType, editorHeight, pluginCfg, events = {}}) => (<TSplitButton
id="snap-button"
keyProp="snap-button"
tooltipId={snapping ? "featuregrid.toolbar.disableSnapping" : "featuregrid.toolbar.enableSnapping"}
visible={mode === "EDIT" && (pluginCfg?.snapTool ?? true) && mapType === MapLibraries.OPENLAYERS}
visible={mode === "EDIT" && (pluginCfg?.snapTool ?? true) && mapType === MapLibraries.OPENLAYERS && canEditGeometry}
onClick={() => {
events.toggleSnapping && events.toggleSnapping(!snapping);
}}
Expand Down Expand Up @@ -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 (<ButtonGroup id="featuregrid-toolbar" className="featuregrid-toolbar featuregrid-toolbar-margin">

{sortBy(buttons.concat(toolbarItems), ["position"]).map(({Component}) => <Component {...props} showPopoverSync={showPopover} hideSyncPopover={() => setShowPopoverSync(false)} mode={props?.mode ?? "VIEW"} disabled={props.disableToolbar} />)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,21 @@ describe('Featuregrid toolbar component', () => {
createFeature: () => {}
};
spyOn(events, "createFeature");
ReactDOM.render(<Toolbar events={events} mode="VIEW" isEditingAllowed/>, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="VIEW" isEditingAllowed canEditGeometry/>, 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(<Toolbar events={events} mode="EDIT" isEditingAllowed/>, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" isEditingAllowed canEditGeometry/>, document.getElementById("container"));
addButton = document.getElementById("fg-add-feature");
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry/>, document.getElementById("container"));
addButton = document.getElementById("fg-add-feature");
expect(isVisibleButton(addButton)).toBe(true);
ReactDOM.render(<Toolbar events={events} mode="EDIT" isEditingAllowed canEditGeometry={false}/>, document.getElementById("container"));
addButton = document.getElementById("fg-add-feature");
expect(isVisibleButton(addButton)).toBe(false);
ReactDOM.render(<Toolbar events={events} mode="EDIT" hasChanges/>, document.getElementById("container"));
addButton = document.getElementById("fg-add-feature");
expect(isVisibleButton(addButton)).toBe(false);
Expand All @@ -172,26 +177,29 @@ describe('Featuregrid toolbar component', () => {
startDrawingFeature: () => {}
};
spyOn(events, "startDrawingFeature");
ReactDOM.render(<Toolbar events={events} mode="VIEW" isEditingAllowed/>, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="VIEW" isEditingAllowed canEditGeometry/>, 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(<Toolbar events={events} mode="EDIT" selectedCount={1} hasGeometry isSimpleGeom={false} />, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry selectedCount={1} hasGeometry isSimpleGeom={false} />, document.getElementById("container"));
button = document.getElementById("fg-draw-feature");
expect(isVisibleButton(button)).toBe(true);
ReactDOM.render(<Toolbar events={events} mode="EDIT" selectedCount={1} hasGeometry isSimpleGeom />, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" isEditingAllowed canEditGeometry={false} selectedCount={1} hasGeometry isSimpleGeom={false} />, document.getElementById("container"));
button = document.getElementById("fg-draw-feature");
expect(isVisibleButton(button)).toBe(false);
ReactDOM.render(<Toolbar events={events} mode="EDIT" selectedCount={1} hasGeometry={false} />, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry selectedCount={1} hasGeometry isSimpleGeom />, document.getElementById("container"));
button = document.getElementById("fg-draw-feature");
expect(isVisibleButton(button)).toBe(false);
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry selectedCount={1} hasGeometry={false} />, document.getElementById("container"));
button = document.getElementById("fg-draw-feature");
expect(isVisibleButton(button)).toBe(true);
ReactDOM.render(<Toolbar events={events} mode="EDIT" selectedCount={1} hasGeometry={false} isSimpleGeom={false} isDrawing/>, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry selectedCount={1} hasGeometry={false} isSimpleGeom={false} isDrawing/>, document.getElementById("container"));
button = document.getElementById("fg-draw-feature");
expect(isVisibleButton(button)).toBe(true);
ReactDOM.render(<Toolbar events={events} mode="EDIT" selectedCount={2}/>, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry selectedCount={2}/>, document.getElementById("container"));
button = document.getElementById("fg-draw-feature");
expect(isVisibleButton(button)).toBe(false);
});
Expand Down Expand Up @@ -257,16 +265,19 @@ describe('Featuregrid toolbar component', () => {
expect(isVisibleButton(button)).toBe(false);
button.click();
expect(events.deleteGeometry).toHaveBeenCalled();
ReactDOM.render(<Toolbar events={events} mode="EDIT" selectedCount={1} />, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry selectedCount={1} />, document.getElementById("container"));
button = document.getElementById("fg-delete-geometry");
expect(isVisibleButton(button)).toBe(false);
ReactDOM.render(<Toolbar events={events} mode="EDIT" selectedCount={1} hasGeometry />, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry={false} selectedCount={1} hasGeometry />, document.getElementById("container"));
button = document.getElementById("fg-delete-geometry");
expect(isVisibleButton(button)).toBe(false);
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry selectedCount={1} hasGeometry />, document.getElementById("container"));
button = document.getElementById("fg-delete-geometry");
expect(isVisibleButton(button)).toBe(true);
ReactDOM.render(<Toolbar events={events} mode="VIEW" selectedCount={1} hasGeometry />, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="VIEW" canEditGeometry ={1} hasGeometry />, document.getElementById("container"));
button = document.getElementById("fg-delete-geometry");
expect(isVisibleButton(button)).toBe(false);
ReactDOM.render(<Toolbar events={events} mode="EDIT" selectedCount={2} hasGeometry/>, document.getElementById("container"));
ReactDOM.render(<Toolbar events={events} mode="EDIT" canEditGeometry selectedCount={2} hasGeometry/>, document.getElementById("container"));
button = document.getElementById("fg-delete-geometry");
expect(isVisibleButton(button)).toBe(false);
});
Expand Down Expand Up @@ -390,26 +401,26 @@ describe('Featuregrid toolbar component', () => {
});
describe('snap tool button', () => {
it('visibility', () => {
ReactDOM.render(<Toolbar mapType="openlayers" pluginCfg={{ snapTool: true }} mode="EDIT" disableZoomAll />, document.getElementById("container"));
ReactDOM.render(<Toolbar mapType="openlayers" pluginCfg={{ snapTool: true }} canEditGeometry mode="EDIT" disableZoomAll />, document.getElementById("container"));
expect(document.getElementById("snap-button")).toExist();
ReactDOM.render(<Toolbar mode="VIEW" disableZoomAll />, document.getElementById("container"));
ReactDOM.render(<Toolbar mode="VIEW" canEditGeometry disableZoomAll />, document.getElementById("container"));
expect(document.getElementById("snap-button")).toNotExist();
});
it('active/inactive state', () => {
ReactDOM.render(<Toolbar mapType="openlayers" snapping pluginCfg={{ snapTool: true }} mode="EDIT" disableZoomAll />, document.getElementById("container"));
ReactDOM.render(<Toolbar mapType="openlayers" snapping pluginCfg={{ snapTool: true }} canEditGeometry mode="EDIT" disableZoomAll />, document.getElementById("container"));
expect(document.getElementById("snap-button").className.split(' ')).toInclude('btn-success');
ReactDOM.render(<Toolbar mapType="openlayers" pluginCfg={{ snapTool: true }} mode="EDIT" disableZoomAll />, document.getElementById("container"));
ReactDOM.render(<Toolbar mapType="openlayers" pluginCfg={{ snapTool: true }} mode="EDIT" canEditGeometry disableZoomAll />, document.getElementById("container"));
expect(document.getElementById("snap-button").className.split(' ')).toNotInclude('btn-success');
});
it('handler', () => {
const events = {
toggleSnapping: () => { }
};
const spy = spyOn(events, "toggleSnapping");
ReactDOM.render(<Toolbar mapType="openlayers" events={events} snapping pluginCfg={{ snapTool: true }} mode="EDIT" disableZoomAll />, document.getElementById("container"));
ReactDOM.render(<Toolbar mapType="openlayers" canEditGeometry events={events} snapping pluginCfg={{ snapTool: true }} mode="EDIT" disableZoomAll />, document.getElementById("container"));
document.getElementById("snap-button").click();
expect(spy.calls[0].arguments[0]).toBe(false);
ReactDOM.render(<Toolbar mapType="openlayers" events={events} pluginCfg={{ snapTool: true }} mode="EDIT" disableZoomAll />, document.getElementById("container"));
ReactDOM.render(<Toolbar mapType="openlayers" canEditGeometry events={events} pluginCfg={{ snapTool: true }} mode="EDIT" disableZoomAll />, document.getElementById("container"));
document.getElementById("snap-button").click();
expect(spy.calls[1].arguments[0]).toBe(true);
});
Expand Down
Loading
Loading