mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2024-12-28 15:31:15 +01:00
Added JSON error to expression editor
This commit is contained in:
parent
97a61afc24
commit
1b3d8b5b79
5 changed files with 75 additions and 31 deletions
|
@ -34,10 +34,26 @@ export default class ExpressionProperty extends React.Component {
|
||||||
|
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super();
|
super();
|
||||||
|
this.state = {
|
||||||
|
jsonError: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onJSONInvalid = (err) => {
|
||||||
|
this.setState({
|
||||||
|
jsonError: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onJSONValid = () => {
|
||||||
|
this.setState({
|
||||||
|
jsonError: false,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {errors, fieldName, fieldType, value, canUndo} = this.props;
|
const {errors, fieldName, fieldType, value, canUndo} = this.props;
|
||||||
|
const {jsonError} = this.state;
|
||||||
const undoDisabled = canUndo ? !canUndo() : true;
|
const undoDisabled = canUndo ? !canUndo() : true;
|
||||||
|
|
||||||
const deleteStopBtn = (
|
const deleteStopBtn = (
|
||||||
|
@ -62,21 +78,31 @@ export default class ExpressionProperty extends React.Component {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const fieldError = errors[fieldType+"."+fieldName];
|
const fieldKey = fieldType === undefined ? fieldName : `${fieldType}.${fieldName}`;
|
||||||
const errorKeyStart = `${fieldType}.${fieldName}[`;
|
|
||||||
const foundErrors = Object.entries(errors).filter(([key, error]) => {
|
const fieldError = errors[fieldKey];
|
||||||
return key.startsWith(errorKeyStart);
|
const errorKeyStart = `${fieldKey}[`;
|
||||||
});
|
const foundErrors = [];
|
||||||
let message = foundErrors.map(([key, error]) => {
|
|
||||||
return error.message;
|
if (jsonError) {
|
||||||
}).join("");
|
foundErrors.push({message: "Invalid JSON"});
|
||||||
if (fieldError) {
|
}
|
||||||
message = fieldError.message + message;
|
else {
|
||||||
|
Object.entries(errors)
|
||||||
|
.filter(([key, error]) => {
|
||||||
|
return key.startsWith(errorKeyStart);
|
||||||
|
})
|
||||||
|
.forEach(([key, error]) => {
|
||||||
|
return foundErrors.push(error);
|
||||||
|
})
|
||||||
|
|
||||||
|
if (fieldError) {
|
||||||
|
foundErrors.push(fieldError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const error = message ? {message} : undefined;
|
|
||||||
|
|
||||||
return <InputBlock
|
return <InputBlock
|
||||||
error={error}
|
error={foundErrors}
|
||||||
fieldSpec={this.props.fieldSpec}
|
fieldSpec={this.props.fieldSpec}
|
||||||
label={labelFromFieldName(this.props.fieldName)}
|
label={labelFromFieldName(this.props.fieldName)}
|
||||||
action={deleteStopBtn}
|
action={deleteStopBtn}
|
||||||
|
@ -86,6 +112,8 @@ export default class ExpressionProperty extends React.Component {
|
||||||
className="maputnik-expression-editor"
|
className="maputnik-expression-editor"
|
||||||
onFocus={this.props.onFocus}
|
onFocus={this.props.onFocus}
|
||||||
onBlur={this.props.onBlur}
|
onBlur={this.props.onBlur}
|
||||||
|
onJSONInvalid={this.onJSONInvalid}
|
||||||
|
onJSONValid={this.onJSONValid}
|
||||||
layer={value}
|
layer={value}
|
||||||
lineNumbers={false}
|
lineNumbers={false}
|
||||||
maxHeight={200}
|
maxHeight={200}
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import capitalize from 'lodash.capitalize'
|
import capitalize from 'lodash.capitalize'
|
||||||
|
|
||||||
export default function labelFromFieldName(fieldName) {
|
export default function labelFromFieldName(fieldName) {
|
||||||
let label = fieldName.split('-').slice(1).join(' ')
|
let label;
|
||||||
return capitalize(label)
|
const parts = fieldName.split('-');
|
||||||
|
if (parts.length > 1) {
|
||||||
|
label = fieldName.split('-').slice(1).join(' ');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
label = fieldName;
|
||||||
|
}
|
||||||
|
return capitalize(label);
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,7 @@ export default class CombiningFilterEditor extends React.Component {
|
||||||
<InputBlock
|
<InputBlock
|
||||||
key="top"
|
key="top"
|
||||||
fieldSpec={fieldSpec}
|
fieldSpec={fieldSpec}
|
||||||
label={"Compound filter"}
|
label={"Filter"}
|
||||||
action={actions}
|
action={actions}
|
||||||
>
|
>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
|
@ -273,14 +273,6 @@ export default class CombiningFilterEditor extends React.Component {
|
||||||
else {
|
else {
|
||||||
let {filter} = this.props;
|
let {filter} = this.props;
|
||||||
|
|
||||||
const errorMessage = Object.entries(errors)
|
|
||||||
.filter(([k, v]) => k.match(/filter(\[\d+\])?/))
|
|
||||||
.map(([k, v]) => {
|
|
||||||
return v.message;
|
|
||||||
})
|
|
||||||
.join("\n")
|
|
||||||
const error = errorMessage ? {message: errorMessage} : null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ExpressionProperty
|
<ExpressionProperty
|
||||||
|
@ -288,10 +280,10 @@ export default class CombiningFilterEditor extends React.Component {
|
||||||
this.setState({displaySimpleFilter: true});
|
this.setState({displaySimpleFilter: true});
|
||||||
this.props.onChange(defaultFilter);
|
this.props.onChange(defaultFilter);
|
||||||
}}
|
}}
|
||||||
fieldName="filter-compound-filter"
|
fieldName="filter"
|
||||||
fieldSpec={fieldSpec}
|
fieldSpec={fieldSpec}
|
||||||
value={filter}
|
value={filter}
|
||||||
error={error}
|
errors={errors}
|
||||||
onChange={this.props.onChange}
|
onChange={this.props.onChange}
|
||||||
/>
|
/>
|
||||||
{this.state.valueIsSimpleFilter &&
|
{this.state.valueIsSimpleFilter &&
|
||||||
|
|
|
@ -19,7 +19,7 @@ class InputBlock extends React.Component {
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
fieldSpec: PropTypes.object,
|
fieldSpec: PropTypes.object,
|
||||||
wideMode: PropTypes.bool,
|
wideMode: PropTypes.bool,
|
||||||
error: PropTypes.object,
|
error: PropTypes.array,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
|
@ -41,6 +41,8 @@ class InputBlock extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const errors = [].concat(this.props.error || []);
|
||||||
|
|
||||||
return <div style={this.props.style}
|
return <div style={this.props.style}
|
||||||
data-wd-key={this.props["data-wd-key"]}
|
data-wd-key={this.props["data-wd-key"]}
|
||||||
className={classnames({
|
className={classnames({
|
||||||
|
@ -71,9 +73,11 @@ class InputBlock extends React.Component {
|
||||||
<div className="maputnik-input-block-content">
|
<div className="maputnik-input-block-content">
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</div>
|
</div>
|
||||||
{this.props.error &&
|
{errors.length > 0 &&
|
||||||
<div className="maputnik-inline-error">
|
<div className="maputnik-inline-error">
|
||||||
{this.props.error.message}
|
{[].concat(this.props.error).map(error => {
|
||||||
|
return <div>{error.message}</div>
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{this.props.fieldSpec &&
|
{this.props.fieldSpec &&
|
||||||
|
|
|
@ -30,6 +30,8 @@ class JSONEditor extends React.Component {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
onFocus: PropTypes.func,
|
onFocus: PropTypes.func,
|
||||||
onBlur: PropTypes.func,
|
onBlur: PropTypes.func,
|
||||||
|
onJSONValid: PropTypes.func,
|
||||||
|
onJSONInvalid: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -41,6 +43,8 @@ class JSONEditor extends React.Component {
|
||||||
},
|
},
|
||||||
onFocus: () => {},
|
onFocus: () => {},
|
||||||
onBlur: () => {},
|
onBlur: () => {},
|
||||||
|
onJSONInvalid: () => {},
|
||||||
|
onJSONValid: () => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -114,11 +118,20 @@ class JSONEditor extends React.Component {
|
||||||
const newCode = this._doc.getValue();
|
const newCode = this._doc.getValue();
|
||||||
|
|
||||||
if (this.state.prevValue !== newCode) {
|
if (this.state.prevValue !== newCode) {
|
||||||
|
let parsedLayer, err;
|
||||||
try {
|
try {
|
||||||
const parsedLayer = JSON.parse(newCode)
|
parsedLayer = JSON.parse(newCode);
|
||||||
|
} catch(_err) {
|
||||||
|
err = _err;
|
||||||
|
console.warn(_err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
this.props.onJSONInvalid();
|
||||||
|
}
|
||||||
|
else {
|
||||||
this.props.onChange(parsedLayer)
|
this.props.onChange(parsedLayer)
|
||||||
} catch(err) {
|
this.props.onJSONValid();
|
||||||
console.warn(err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue