Skip to content

Commit

Permalink
[explorev2] Fields can validate input and handle errors
Browse files Browse the repository at this point in the history
As a result here, TextField does its own validation and now casts
the values it sends to Int or Float if set to do so.
  • Loading branch information
mistercrunch committed Jan 13, 2017
1 parent 99b84d2 commit 73b4470
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 18 deletions.
7 changes: 5 additions & 2 deletions superset/assets/javascripts/explorev2/components/FieldSet.jsx
Expand Up @@ -42,8 +42,11 @@ export default class FieldSet extends React.PureComponent {
this.validate = this.validate.bind(this);
this.onChange = this.onChange.bind(this);
}
onChange(value) {
const validationErrors = this.validate(value);
onChange(value, errors) {
let validationErrors = this.validate(value);
if (errors && errors.length > 0) {
validationErrors = validationErrors.concat(errors);
}
this.props.actions.setFieldValue(this.props.name, value, validationErrors);
}
validate(value) {
Expand Down
44 changes: 39 additions & 5 deletions superset/assets/javascripts/explorev2/components/TextField.jsx
@@ -1,34 +1,68 @@
import React, { PropTypes } from 'react';
import { FormGroup, FormControl } from 'react-bootstrap';
import * as v from '../validators';

const propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string,
description: PropTypes.string,
onChange: PropTypes.func,
value: PropTypes.string,
value: PropTypes.oneOf([
PropTypes.string,
PropTypes.number,
]),
isFloat: PropTypes.bool,
isInt: PropTypes.bool,
};

const defaultProps = {
label: null,
description: null,
onChange: () => {},
value: '',
isInt: false,
isFloat: false,
};

export default class TextField extends React.Component {
constructor(props) {
super(props);
const value = props.value ? props.value.toString() : '';
this.state = { value };
this.onChange = this.onChange.bind(this);
}
onChange(event) {
this.props.onChange(event.target.value);
let value = event.target.value || '';
this.setState({ value });

// Validation & casting
const errors = [];
if (this.props.isFloat) {
const error = v.numeric(value);
if (error) {
errors.push(error);
} else {
value = parseFloat(value);
}
}
if (this.props.isInt) {
const error = v.integer(value);
if (error) {
errors.push(error);
} else {
value = parseInt(value, 10);
}
}
this.props.onChange(value, errors);
}
render() {
const value = this.props.value || '';
return (
<FormGroup controlId="formInlineName" bsSize="small">
<FormControl
type="text"
placeholder=""
onChange={this.onChange.bind(this)}
value={value}
onChange={this.onChange}
value={this.state.value}
/>
</FormGroup>
);
Expand Down
22 changes: 11 additions & 11 deletions superset/assets/javascripts/explorev2/stores/fields.js
Expand Up @@ -514,7 +514,7 @@ export const fields = {
treemap_ratio: {
type: 'TextField',
label: 'Ratio',
validators: [v.numeric],
isFloat: true,
default: 0.5 * (1 + Math.sqrt(5)), // d3 default, golden ratio
description: 'Target aspect ratio for treemap tiles.',
},
Expand Down Expand Up @@ -567,7 +567,7 @@ export const fields = {
rolling_periods: {
type: 'TextField',
label: 'Periods',
validators: [v.integer],
isInt: true,
description: 'Defines the size of the rolling window function, ' +
'relative to the time granularity selected',
},
Expand Down Expand Up @@ -666,7 +666,7 @@ export const fields = {
compare_lag: {
type: 'TextField',
label: 'Comparison Period Lag',
validators: [v.integer],
isInt: true,
description: 'Based on granularity, number of time periods to compare against',
},

Expand Down Expand Up @@ -793,15 +793,15 @@ export const fields = {

size_from: {
type: 'TextField',
validators: [v.integer],
isInt: true,
label: 'Font Size From',
default: '20',
description: 'Font size for the smallest value in the list',
},

size_to: {
type: 'TextField',
validators: [v.integer],
isInt: true,
label: 'Font Size To',
default: '150',
description: 'Font size for the biggest value in the list',
Expand Down Expand Up @@ -917,7 +917,7 @@ export const fields = {
type: 'TextField',
label: 'Period Ratio',
default: '',
validators: [v.integer],
isInt: true,
description: '[integer] Number of period to compare against, ' +
'this is relative to the granularity selected',
},
Expand All @@ -934,7 +934,7 @@ export const fields = {
time_compare: {
type: 'TextField',
label: 'Time Shift',
validators: [v.integer],
isInt: true,
default: null,
description: 'Overlay a timeseries from a ' +
'relative time period. Expects relative time delta ' +
Expand Down Expand Up @@ -1022,15 +1022,15 @@ export const fields = {
type: 'TextField',
label: 'Opacity',
default: 1,
validators: [v.numeric],
isFloat: true,
description: 'Opacity of all clusters, points, and labels. ' +
'Between 0 and 1.',
},

viewport_zoom: {
type: 'TextField',
label: 'Zoom',
validators: [v.numeric],
isFloat: true,
default: 11,
description: 'Zoom level of the map',
places: 8,
Expand All @@ -1040,7 +1040,7 @@ export const fields = {
type: 'TextField',
label: 'Default latitude',
default: 37.772123,
validators: [v.numeric],
isFloat: true,
description: 'Latitude of default viewport',
places: 8,
},
Expand All @@ -1049,7 +1049,7 @@ export const fields = {
type: 'TextField',
label: 'Default longitude',
default: -122.405293,
validators: [v.numeric],
isFloat: true,
description: 'Longitude of default viewport',
places: 8,
},
Expand Down

0 comments on commit 73b4470

Please sign in to comment.