Skip to content

Commit

Permalink
[exploreV2] mapStateToProps for fields (#1882)
Browse files Browse the repository at this point in the history
* Controls support for mapStateToProps

* Binding methods in the constructor

* Adressing comments

* Fixing tests
  • Loading branch information
mistercrunch authored Jan 6, 2017
1 parent 9a62d94 commit 2226716
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export default class EmbedCodeButton extends React.Component {
` width="${this.state.width}"\n` +
` height="${this.state.height}"\n` +
' seamless\n' +
' frameBorder="0" scrolling="no"\n' +
' frameBorder="0"\n' +
' scrolling="no"\n' +
` src="${srcLink}"\n` +
'>\n' +
'</iframe>'
Expand Down
14 changes: 7 additions & 7 deletions superset/assets/javascripts/explorev2/actions/exploreActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
const $ = window.$ = require('jquery');
const FAVESTAR_BASE_URL = '/superset/favstar/slice';

export const SET_FIELD_OPTIONS = 'SET_FIELD_OPTIONS';
export function setFieldOptions(options) {
return { type: SET_FIELD_OPTIONS, options };
}

export const SET_DATASOURCE_TYPE = 'SET_DATASOURCE_TYPE';
export function setDatasourceType(datasourceType) {
return { type: SET_DATASOURCE_TYPE, datasourceType };
}

export const SET_DATASOURCE = 'SET_DATASOURCE';
export function setDatasource(datasource) {
return { type: SET_DATASOURCE, datasource };
}

export const FETCH_STARTED = 'FETCH_STARTED';
export function fetchStarted() {
return { type: FETCH_STARTED };
Expand All @@ -27,7 +27,7 @@ export function fetchFailed(error) {
return { type: FETCH_FAILED, error };
}

export function fetchFieldOptions(datasourceId, datasourceType) {
export function fetchDatasourceMetadata(datasourceId, datasourceType) {
return function (dispatch) {
dispatch(fetchStarted());

Expand All @@ -38,7 +38,7 @@ export function fetchFieldOptions(datasourceId, datasourceType) {
type: 'GET',
url,
success: (data) => {
dispatch(setFieldOptions(data.field_options));
dispatch(setDatasource(data));
dispatch(fetchSucceeded());
},
error(error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Panel, Alert } from 'react-bootstrap';
import visTypes, { sectionsToRender, commonControlPanelSections } from '../stores/visTypes';
import ControlPanelSection from './ControlPanelSection';
import FieldSetRow from './FieldSetRow';
import FieldSet from './FieldSet';
import Filters from './Filters';

const propTypes = {
Expand All @@ -17,48 +18,65 @@ const propTypes = {
form_data: PropTypes.object.isRequired,
y_axis_zero: PropTypes.any,
alert: PropTypes.string,
exploreState: PropTypes.object.isRequired,
};

class ControlPanelsContainer extends React.Component {
constructor(props) {
super(props);
this.fieldOverrides = this.fieldOverrides.bind(this);
this.getFieldData = this.getFieldData.bind(this);
this.removeAlert = this.removeAlert.bind(this);
this.onChange = this.onChange.bind(this);
}
componentWillMount() {
const datasource_id = this.props.form_data.datasource;
const datasource_type = this.props.datasource_type;
if (datasource_id) {
this.props.actions.fetchFieldOptions(datasource_id, datasource_type);
this.props.actions.fetchDatasourceMetadata(datasource_id, datasource_type);
}
}

componentWillReceiveProps(nextProps) {
if (nextProps.form_data.datasource !== this.props.form_data.datasource) {
if (nextProps.form_data.datasource) {
this.props.actions.fetchFieldOptions(
this.props.actions.fetchDatasourceMetadata(
nextProps.form_data.datasource, nextProps.datasource_type);
}
}
}

onChange(name, value, label) {
this.props.actions.setFieldValue(this.props.datasource_type, name, value, label);
onChange(name, value) {
this.props.actions.setFieldValue(this.props.datasource_type, name, value);
}
getFieldData(fs) {
const fieldOverrides = this.fieldOverrides();
if (!this.props.fields) {
return null;
}
let fieldData = this.props.fields[fs] || {};
if (fieldOverrides.hasOwnProperty(fs)) {
const overrideData = fieldOverrides[fs];
fieldData = Object.assign({}, fieldData, overrideData);
}
if (fieldData.mapStateToProps) {
Object.assign(fieldData, fieldData.mapStateToProps(this.props.exploreState));
}
return fieldData;
}

sectionsToRender() {
return sectionsToRender(this.props.form_data.viz_type, this.props.datasource_type);
}

filterSectionsToRender() {
const filterSections = this.props.datasource_type === 'table' ?
[commonControlPanelSections.filters[0]] : commonControlPanelSections.filters;
return filterSections;
}

fieldOverrides() {
const viz = visTypes[this.props.form_data.viz_type];
return viz.fieldOverrides;
return viz.fieldOverrides || {};
}
removeAlert() {
this.props.actions.removeControlPanelAlert();
}

render() {
return (
<div className="scrollbar-container">
Expand All @@ -68,7 +86,7 @@ class ControlPanelsContainer extends React.Component {
{this.props.alert}
<i
className="fa fa-close pull-right"
onClick={this.removeAlert.bind(this)}
onClick={this.removeAlert}
style={{ cursor: 'pointer' }}
/>
</Alert>
Expand All @@ -81,12 +99,16 @@ class ControlPanelsContainer extends React.Component {
>
{section.fieldSetRows.map((fieldSets, i) => (
<FieldSetRow
key={`${section.label}-fieldSetRow-${i}`}
fieldSets={fieldSets}
fieldOverrides={this.fieldOverrides()}
onChange={this.onChange.bind(this)}
fields={this.props.fields}
form_data={this.props.form_data}
key={`fieldsetrow-${i}`}
fields={fieldSets.map(field => (
<FieldSet
name={field}
key={`field-${field}`}
onChange={this.onChange}
value={this.props.form_data[field]}
{...this.getFieldData(field)}
/>
))}
/>
))}
</ControlPanelSection>
Expand Down Expand Up @@ -119,6 +141,7 @@ function mapStateToProps(state) {
alert: state.controlPanelAlert,
isDatasourceMetaLoading: state.isDatasourceMetaLoading,
fields: state.fields,
exploreState: state,
};
}

Expand Down
55 changes: 13 additions & 42 deletions superset/assets/javascripts/explorev2/components/FieldSetRow.jsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,23 @@
import React, { PropTypes } from 'react';
import FieldSet from './FieldSet';

const NUM_COLUMNS = 12;

const propTypes = {
fields: PropTypes.object.isRequired,
fieldSets: PropTypes.array.isRequired,
fieldOverrides: PropTypes.object,
onChange: PropTypes.func,
form_data: PropTypes.object.isRequired,
fields: PropTypes.arrayOf(PropTypes.object).isRequired,
};

const defaultProps = {
fieldOverrides: {},
onChange: () => {},
};

export default class FieldSetRow extends React.Component {
getFieldData(fs) {
const { fields, fieldOverrides } = this.props;
let fieldData = fields[fs];
if (fieldOverrides.hasOwnProperty(fs)) {
const overrideData = fieldOverrides[fs];
fieldData = Object.assign({}, fieldData, overrideData);
}
return fieldData;
}
render() {
const colSize = NUM_COLUMNS / this.props.fieldSets.length;
return (
<div className="row space-2">
{this.props.fieldSets.map((fs) => {
const fieldData = this.getFieldData(fs);
return (
<div className={`col-lg-${colSize} col-xs-12`} key={fs}>
<FieldSet
name={fs}
onChange={this.props.onChange}
value={this.props.form_data[fs]}
{...fieldData}
/>
</div>
);
})}
</div>
);
}
function FieldSetRow(props) {
const colSize = NUM_COLUMNS / props.fields.length;
return (
<div className="row space-2">
{props.fields.map((field, i) => (
<div className={`col-lg-${colSize} col-xs-12`} key={i} >
{field}
</div>
))}
</div>
);
}

FieldSetRow.propTypes = propTypes;
FieldSetRow.defaultProps = defaultProps;
export default FieldSetRow;
20 changes: 2 additions & 18 deletions superset/assets/javascripts/explorev2/reducers/exploreReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,9 @@ export const exploreReducer = function (state, action) {
return Object.assign({}, state,
{ saveModalAlert: `fetching dashboards failed for ${action.userId}` });
},

[actions.SET_FIELD_OPTIONS]() {
const newState = Object.assign({}, state);
const optionsByFieldName = action.options;
const fieldNames = Object.keys(optionsByFieldName);

fieldNames.forEach((fieldName) => {
if (fieldName === 'filterable_cols') {
newState.filterColumnOpts = optionsByFieldName[fieldName];
} else {
newState.fields[fieldName].choices = optionsByFieldName[fieldName];
if (fieldName === 'metric' && state.viz.form_data.viz_type === 'dual_line') {
newState.fields.metric_2.choices = optionsByFieldName[fieldName];
}
}
});
return Object.assign({}, state, newState);
[actions.SET_DATASOURCE]() {
return Object.assign({}, state, { datasource: action.datasource });
},

[actions.SET_FILTER_COLUMN_OPTS]() {
return Object.assign({}, state, { filterColumnOpts: action.filterColumnOpts });
},
Expand Down
Loading

0 comments on commit 2226716

Please sign in to comment.