parent
5952632816
commit
a9803f335f
|
@ -95,15 +95,6 @@
|
|||
}
|
||||
&-form {
|
||||
&-field {
|
||||
&-error {
|
||||
input,
|
||||
select {
|
||||
border-color: rgb(220, 0, 0);
|
||||
&:focus {
|
||||
border-color: rgb(220, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
min-height: $input-height;
|
||||
padding: 1px 0;
|
||||
@extend %clearfix;
|
||||
|
@ -131,3 +122,13 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-field-error {
|
||||
input,
|
||||
select {
|
||||
border-color: rgb(220, 0, 0);
|
||||
&:focus {
|
||||
border-color: rgb(220, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,5 +106,10 @@ export default [
|
|||
field: 'max',
|
||||
title: 'Maximum value',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
field: 'valueDescriptions',
|
||||
title: 'Value descriptions',
|
||||
type: 'map'
|
||||
}
|
||||
];
|
||||
|
|
|
@ -2,9 +2,10 @@ import React, { Component } from 'react';
|
|||
|
||||
export default class Field extends Component {
|
||||
render() {
|
||||
const { title, htmlFor, children } = this.props;
|
||||
const { title, htmlFor, children, valid } = this.props;
|
||||
const errorCls = valid === false ? ' form-field-error' : '';
|
||||
return (
|
||||
<div className="form-field form-field--small">
|
||||
<div className={ `form-field form-field--small${errorCls}` }>
|
||||
<label htmlFor={htmlFor}>{title}</label>
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Field from './Field';
|
||||
|
||||
export default class MapField extends Component {
|
||||
static propTypes = {
|
||||
fieldSpec: PropTypes.any,
|
||||
signal: PropTypes.any,
|
||||
isExpanded: PropTypes.any,
|
||||
signalEdited: PropTypes.any,
|
||||
updateField: PropTypes.any,
|
||||
valid: PropTypes.any,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
valid: true,
|
||||
mapString: '',
|
||||
};
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.componentDidUpdate({}, {});
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.isExpanded !== this.props.isExpanded) {
|
||||
const entryPairs = Array.from(this.props.signalEdited.entries());
|
||||
const mapString = entryPairs.reduce((str, [value, desc]) => `${str + value} "${desc}" `, '').trim();
|
||||
this.setState({ mapString });
|
||||
}
|
||||
}
|
||||
|
||||
onChange(ev) {
|
||||
const mapString = ev.target.value;
|
||||
this.setState({ mapString });
|
||||
|
||||
if ((mapString.split('"').length - 1) % 2 !== 0) {
|
||||
this.setState({ valid: false });
|
||||
return;
|
||||
}
|
||||
let splitted = Array.from(mapString.matchAll(/[^\s"]+|"([^"]*)"/g));
|
||||
if (splitted.length % 2 !== 0) {
|
||||
this.setState({ valid: false });
|
||||
return;
|
||||
}
|
||||
|
||||
splitted = splitted.map(([match, group]) => group || match);
|
||||
const res = new Map();
|
||||
for (let i = 0; i < splitted.length; i += 2) {
|
||||
res.set(splitted[i], splitted[i+1]);
|
||||
}
|
||||
|
||||
this.setState({ valid: true });
|
||||
this.props.updateField(this.props.fieldSpec, res);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { fieldSpec, signal, isExpanded } = this.props;
|
||||
|
||||
const htmlFor = `${signal.name}_${fieldSpec.field}`;
|
||||
let valueCol;
|
||||
|
||||
if (isExpanded) {
|
||||
valueCol = <input id={htmlFor} type="text" value={this.state.mapString} onChange={this.onChange} />;
|
||||
} else {
|
||||
valueCol = <span>{signal[fieldSpec.field]}</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Field title={typeof fieldSpec.title === 'function' ? fieldSpec.title(signal) : fieldSpec.title}
|
||||
htmlFor={htmlFor} valid={this.props.valid && this.state.valid}>
|
||||
{valueCol}
|
||||
</Field>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,8 @@ export default ({
|
|||
signal,
|
||||
isExpanded,
|
||||
signalEdited,
|
||||
updateField
|
||||
updateField,
|
||||
valid
|
||||
}) => {
|
||||
const { field, title } = fieldSpec;
|
||||
const htmlFor = `${signal.name}_${field}`;
|
||||
|
@ -36,6 +37,7 @@ export default ({
|
|||
<Field
|
||||
title={typeof title === 'function' ? title(signal) : title}
|
||||
htmlFor={htmlFor}
|
||||
valid={valid}
|
||||
>
|
||||
{valueCol}
|
||||
</Field>
|
||||
|
|
|
@ -8,7 +8,8 @@ export default ({
|
|||
signal,
|
||||
isExpanded,
|
||||
signalEdited,
|
||||
updateField
|
||||
updateField,
|
||||
valid
|
||||
}) => {
|
||||
let valueCol;
|
||||
const { field, title } = fieldSpec;
|
||||
|
@ -41,6 +42,7 @@ export default ({
|
|||
<Field
|
||||
title={typeof title === 'function' ? title(signal) : title}
|
||||
htmlFor={htmlFor}
|
||||
valid={valid}
|
||||
>
|
||||
{valueCol}
|
||||
</Field>
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
import FIELDS from './FIELDS';
|
||||
import NumberField from './NumberField';
|
||||
import StringField from './StringField';
|
||||
import OptionField from './OptionField';
|
||||
import MapField from './MapField';
|
||||
|
||||
const FieldMap = {
|
||||
number: NumberField,
|
||||
option: OptionField,
|
||||
string: StringField
|
||||
string: StringField,
|
||||
map: MapField,
|
||||
};
|
||||
|
||||
export default ({
|
||||
|
@ -23,15 +24,16 @@ export default ({
|
|||
<div className="signals-legend-entry-form">
|
||||
{FIELDS.map((field) => {
|
||||
const Node = FieldMap[field.type];
|
||||
const errorClass = fieldError === field.field ? 'signals-legend-entry-form-field-error' : null;
|
||||
const valid = fieldError !== field.field;
|
||||
return (
|
||||
<div className={cx("signals-legend-entry-form-field", errorClass)} key={field.field}>
|
||||
<div className="signals-legend-entry-form-field" key={field.field}>
|
||||
<Node
|
||||
fieldSpec={field}
|
||||
signal={signal}
|
||||
isExpanded={isExpanded}
|
||||
signalEdited={getSignalEdited(field.field)}
|
||||
updateField={update}
|
||||
valid={valid}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -6,7 +6,8 @@ export default ({
|
|||
signal,
|
||||
isExpanded,
|
||||
signalEdited,
|
||||
updateField
|
||||
updateField,
|
||||
valid
|
||||
}) => {
|
||||
const { field, title } = fieldSpec;
|
||||
const htmlFor = `${signal.name}_${field}`;
|
||||
|
@ -30,6 +31,7 @@ export default ({
|
|||
<Field
|
||||
title={typeof title === 'function' ? title(signal) : title}
|
||||
htmlFor={htmlFor}
|
||||
valid={valid}
|
||||
>
|
||||
{valueCol}
|
||||
</Field>
|
||||
|
|
Loading…
Reference in New Issue