Skip to content

Commit 1d52a0a

Browse files
rueckstiessdurran
authored andcommitted
COMPASS-199 validation json editable (#559)
* COMPASS-199 make JSON view editable and disable view switcher if validator doc cannot be expressed by rule builder. * COMPASS-199 make JSON editable, validate JSON
1 parent 771d9e2 commit 1d52a0a

File tree

11 files changed

+186
-70
lines changed

11 files changed

+186
-70
lines changed

src/internal-packages/validation/lib/actions/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const ValidationActions = Reflux.createActions([
1313
'setRuleNullable',
1414
'setValidationLevel',
1515
'setValidationAction',
16+
'setValidatorDocument',
1617
'switchView',
1718
'saveChanges',
1819
'cancelChanges'

src/internal-packages/validation/lib/components/common/editable.jsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ class Editable extends React.Component {
2323
</div>
2424
);
2525
}
26+
if (this.props.editState === 'error') {
27+
return (
28+
<div className="pull-right">
29+
<Button
30+
bsStyle="link"
31+
bsSize="xsmall"
32+
onClick={this.props.onCancel}>Cancel
33+
</Button>
34+
</div>
35+
);
36+
}
2637
return null;
2738
}
2839

@@ -39,7 +50,7 @@ class Editable extends React.Component {
3950
case 'error':
4051
if (errorMsg) {
4152
return name ? `${name} could not be updated: ${errorMsg}` :
42-
`Error during update: ${errorMsg}`;
53+
`Error: ${errorMsg}`;
4354
}
4455
return name ? `${name} could not be updated.` : 'An error occurred during the update.';
4556
default: return '';

src/internal-packages/validation/lib/components/common/view-switcher.jsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ class ViewSwitcher extends React.Component {
1515
return _.map(this.props.buttonLabels, (label) => {
1616
const active = this.props.activeButton === label;
1717
return (
18-
<Button key={label} active={active} onClick={this.props.onClick.bind(this, label)}>
18+
<Button
19+
key={label}
20+
active={active}
21+
onClick={this.props.onClick.bind(this, label)}
22+
disabled={this.props.disabled}
23+
>
1924
{label}
2025
</Button>
2126
);
@@ -44,13 +49,15 @@ ViewSwitcher.propTypes = {
4449
label: React.PropTypes.string,
4550
buttonLabels: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
4651
activeButton: React.PropTypes.string,
47-
onClick: React.PropTypes.func
52+
onClick: React.PropTypes.func,
53+
disabled: React.PropTypes.bool
4854
};
4955

5056
ViewSwitcher.defaultProps = {
5157
label: '',
5258
activeButton: '',
53-
onClick: () => {}
59+
onClick: () => {},
60+
disabled: false
5461
};
5562

5663
ViewSwitcher.displayName = 'ViewSwitcher';

src/internal-packages/validation/lib/components/json-view.jsx

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,47 @@ const ValidationActions = require('../actions');
33
const OptionSelector = require('./common/option-selector');
44
const Editable = require('./common/editable');
55

6-
const ReactBootstrap = require('react-bootstrap');
7-
const Grid = ReactBootstrap.Grid;
8-
const Row = ReactBootstrap.Row;
9-
const Col = ReactBootstrap.Col;
6+
const {Grid, Row, Col, FormGroup, FormControl} = require('react-bootstrap');
107

118
// const debug = require('debug')('validation:json-view');
129

1310
class JSONView extends React.Component {
1411

12+
constructor(props) {
13+
super(props);
14+
this.state = {
15+
isValidJSON: true,
16+
input: props.validatorDoc ?
17+
JSON.stringify(props.validatorDoc.validator, null, 2) : '{}'
18+
};
19+
}
20+
21+
componentWillReceiveProps(newProps) {
22+
this.setState({
23+
input: JSON.stringify(newProps.validatorDoc.validator, null, 2)
24+
});
25+
}
26+
27+
onInputChanged(evt) {
28+
this.setState({
29+
input: evt.target.value
30+
});
31+
}
32+
33+
onBlur() {
34+
const doc = this.validate();
35+
if (doc) {
36+
ValidationActions.setValidatorDocument(doc);
37+
}
38+
}
39+
1540
/**
1641
* New value from the validation action dropdown chosen.
1742
*
1843
* @param {String} action the chosen action, one of `warn`, `error`.
1944
*/
2045
onActionSelect(action) {
21-
ValidationActions.setValidationAction(action);
46+
ValidationActions.setValidationAction(action, false);
2247
}
2348

2449
/**
@@ -27,14 +52,17 @@ class JSONView extends React.Component {
2752
* @param {String} level the chosen level, one of `off`, `moderate`, `strict`
2853
*/
2954
onLevelSelect(level) {
30-
ValidationActions.setValidationLevel(level);
55+
ValidationActions.setValidationLevel(level, false);
3156
}
3257

3358
/**
3459
* The "Cancel" button from the `Editable` component has been clicked.
3560
* Revert all changes to the server state.
3661
*/
3762
onCancel() {
63+
this.setState({
64+
isValidJSON: true
65+
});
3866
ValidationActions.cancelChanges();
3967
}
4068

@@ -46,19 +74,46 @@ class JSONView extends React.Component {
4674
ValidationActions.saveChanges();
4775
}
4876

77+
validate() {
78+
try {
79+
const doc = {
80+
validator: JSON.parse(this.state.input),
81+
validationLevel: this.props.validationLevel,
82+
validationAction: this.props.validationAction
83+
};
84+
this.setState({
85+
isValidJSON: true
86+
});
87+
return doc;
88+
} catch (e) {
89+
this.setState({
90+
isValidJSON: false
91+
});
92+
return false;
93+
}
94+
}
95+
4996
/**
5097
* Render status row component.
5198
*
5299
* @returns {React.Component} The component.
53100
*/
54101
render() {
102+
const editableProps = {
103+
editState: this.props.editState,
104+
childName: 'Validation',
105+
onCancel: this.onCancel.bind(this),
106+
onUpdate: this.onUpdate.bind(this)
107+
};
108+
109+
if (!this.state.isValidJSON) {
110+
editableProps.editState = 'error';
111+
editableProps.errorMessage = 'Input is not valid JSON.';
112+
delete editableProps.childName;
113+
}
114+
55115
return (
56-
<Editable
57-
editState={this.props.editState}
58-
childName="Validation"
59-
onCancel={this.onCancel.bind(this)}
60-
onUpdate={this.onUpdate.bind(this)}
61-
>
116+
<Editable {...editableProps} >
62117
<Grid fluid className="json-view">
63118
<Row className="header">
64119
<Col lg={12} md={12} sm={12} xs={12}>
@@ -85,11 +140,15 @@ class JSONView extends React.Component {
85140
<hr/>
86141
<Row>
87142
<Col lg={12} md={12} sm={12} xs={12}>
88-
<pre><code
89-
className="json-view code"
90-
// readOnly="readOnly"
91-
// disabled="disabled"
92-
>{JSON.stringify(this.props.validatorDoc, null, 2)}</code></pre>
143+
<FormGroup validationState={this.state.errorState}>
144+
<FormControl
145+
componentClass="textarea"
146+
className="json-input json-input-textarea"
147+
value={this.state.input}
148+
onChange={this.onInputChanged.bind(this)}
149+
onBlur={this.onBlur.bind(this)}
150+
/>
151+
</FormGroup>
93152
</Col>
94153
</Row>
95154
</Grid>

src/internal-packages/validation/lib/components/rule-builder.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class RuleBuilder extends React.Component {
3030
* @param {String} action the chosen action, one of `warn`, `error`.
3131
*/
3232
onActionSelect(action) {
33-
ValidationActions.setValidationAction(action);
33+
ValidationActions.setValidationAction(action, true);
3434
}
3535

3636
/**
@@ -39,7 +39,7 @@ class RuleBuilder extends React.Component {
3939
* @param {String} level the chosen level, one of `off`, `moderate`, `strict`
4040
*/
4141
onLevelSelect(level) {
42-
ValidationActions.setValidationLevel(level);
42+
ValidationActions.setValidationLevel(level, true);
4343
}
4444

4545
/**

src/internal-packages/validation/lib/components/validation.jsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,14 @@ class Validation extends React.Component {
4040
render() {
4141
const view = this.props.viewMode === 'Rule Builder' ?
4242
(
43-
<RuleBuilder
44-
validationRules={this.props.validationRules}
45-
validationAction={this.props.validationAction}
46-
validationLevel={this.props.validationLevel}
47-
editState={this.props.editState}
48-
/>
43+
<div className="validation validation-rule-builder-wrapper">
44+
<RuleBuilder
45+
validationRules={this.props.validationRules}
46+
validationAction={this.props.validationAction}
47+
validationLevel={this.props.validationLevel}
48+
editState={this.props.editState}
49+
/>
50+
</div>
4951
) : (
5052
<JSONView
5153
validatorDoc={this.props.validatorDoc}
@@ -54,20 +56,20 @@ class Validation extends React.Component {
5456
editState={this.props.editState}
5557
/>
5658
);
59+
60+
const activeButton = this.props.isExpressibleByRules ?
61+
this.props.viewMode : 'JSON';
62+
5763
return (
5864
<div className="validation">
5965
<Grid fluid>
60-
<StatusRow>
61-
<span>This is an example status row with a link.</span>
62-
{' '}
63-
<a href="#">more info</a>
64-
</StatusRow>
6566
<StatusRow>
6667
<ViewSwitcher
6768
label="View as:"
6869
buttonLabels={['Rule Builder', 'JSON']}
69-
activeButton={this.props.viewMode}
70+
activeButton={activeButton}
7071
onClick={this.switchView.bind(this)}
72+
disabled={!this.props.isExpressibleByRules}
7173
/>
7274
</StatusRow>
7375
{view}
@@ -80,6 +82,7 @@ class Validation extends React.Component {
8082
Validation.propTypes = {
8183
editState: React.PropTypes.oneOf(['unmodified', 'modified', 'updating', 'error', 'success']).isRequired,
8284
viewMode: React.PropTypes.oneOf(['Rule Builder', 'JSON']).isRequired,
85+
isExpressibleByRules: React.PropTypes.bool.isRequired,
8386
validationAction: React.PropTypes.oneOf(['warn', 'error']).isRequired,
8487
validatorDoc: React.PropTypes.object.isRequired,
8588
validationLevel: React.PropTypes.oneOf(['off', 'moderate', 'strict']).isRequired,
@@ -89,6 +92,7 @@ Validation.propTypes = {
8992
Validation.defaultProps = {
9093
editState: 'unmodified',
9194
viewMode: 'Rule Builder',
95+
isExpressibleByRules: true,
9296
validationAction: 'warn',
9397
validatorDoc: {},
9498
validationLevel: 'off',

0 commit comments

Comments
 (0)