Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added filter in ControlPanelsContainer for explore V2 #1647

Merged
merged 6 commits into from
Nov 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 3 additions & 14 deletions superset/assets/javascripts/explorev2/actions/exploreActions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint camelcase: 0 */
const $ = window.$ = require('jquery');

const FAVESTAR_BASE_URL = '/superset/favstar/slice';

export const SET_FIELD_OPTIONS = 'SET_FIELD_OPTIONS';
Expand Down Expand Up @@ -89,19 +88,9 @@ export function removeFilter(filter) {
return { type: REMOVE_FILTER, filter };
}

export const CHANGE_FILTER_FIELD = 'CHANGE_FILTER_FIELD';
export function changeFilterField(filter, field) {
return { type: CHANGE_FILTER_FIELD, filter, field };
}

export const CHANGE_FILTER_OP = 'CHANGE_FILTER_OP';
export function changeFilterOp(filter, op) {
return { type: CHANGE_FILTER_OP, filter, op };
}

export const CHANGE_FILTER_VALUE = 'CHANGE_FILTER_VALUE';
export function changeFilterValue(filter, value) {
return { type: CHANGE_FILTER_VALUE, filter, value };
export const CHANGE_FILTER = 'CHANGE_FILTER';
export function changeFilter(filter, field, value) {
return { type: CHANGE_FILTER, filter, field, value };
}

export const SET_FIELD_VALUE = 'SET_FIELD_VALUE';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { bindActionCreators } from 'redux';
import * as actions from '../actions/exploreActions';
import { connect } from 'react-redux';
import { Panel, Alert } from 'react-bootstrap';
import { visTypes, sectionsToRender } from '../stores/store';
import { visTypes, sectionsToRender, commonControlPanelSections } from '../stores/store';
import ControlPanelSection from './ControlPanelSection';
import FieldSetRow from './FieldSetRow';
import Filters from './Filters';

const propTypes = {
datasource_type: PropTypes.string.isRequired,
Expand Down Expand Up @@ -44,6 +45,12 @@ class ControlPanelsContainer extends React.Component {
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;
Expand Down Expand Up @@ -86,7 +93,20 @@ class ControlPanelsContainer extends React.Component {
))}
</ControlPanelSection>
))}
{/* TODO: add filters section */}
{this.filterSectionsToRender().map((section) => (
<ControlPanelSection
key={section.label}
label={section.label}
tooltip={section.description}
>
<Filters
filterColumnOpts={[]}
filters={this.props.form_data.filters}
actions={this.props.actions}
prefix={section.prefix}
/>
</ControlPanelSection>
))}
</div>
</div>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import ControlPanelsContainer from './ControlPanelsContainer';
import SaveModal from './SaveModal';
import QueryAndSaveBtns from '../../explore/components/QueryAndSaveBtns';
import { autoQueryFields } from '../stores/store';
import { getParamObject } from '../../modules/utils.js';

const $ = require('jquery');

const propTypes = {
Expand Down Expand Up @@ -47,18 +49,7 @@ class ExploreViewContainer extends React.Component {
}

onQuery(form_data) {
const data = {};
Object.keys(form_data).forEach((field) => {
// filter out null fields
if (form_data[field] !== null && field !== 'datasource') {
data[field] = form_data[field];
}
});
// V2 tag temporarily for updating url
// Todo: remove after launch
data.V2 = true;
data.datasource_id = this.props.form_data.datasource;
data.datasource_type = this.props.datasource_type;
const data = getParamObject(form_data, this.props.datasource_type);
this.queryFormData(data);

const params = $.param(data, true);
Expand Down
92 changes: 92 additions & 0 deletions superset/assets/javascripts/explorev2/components/Filter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from 'react';
// import { Tab, Row, Col, Nav, NavItem } from 'react-bootstrap';
import Select from 'react-select';
import { Button } from 'react-bootstrap';

const propTypes = {
actions: React.PropTypes.object.isRequired,
filterColumnOpts: React.PropTypes.array,
prefix: React.PropTypes.string,
filter: React.PropTypes.object.isRequired,
};

const defaultProps = {
filterColumnOpts: [],
prefix: 'flt',
};

export default class Filter extends React.Component {
constructor(props) {
super(props);
const opChoices = this.props.prefix === 'flt' ?
['in', 'not in'] : ['==', '!=', '>', '<', '>=', '<='];
this.state = {
opChoices,
};
}
changeCol(filter, colOpt) {
const val = (colOpt) ? colOpt.value : null;
this.props.actions.changeFilter(filter, 'col', val);
}
changeOp(filter, opOpt) {
const val = (opOpt) ? opOpt.value : null;
this.props.actions.changeFilter(filter, 'op', val);
}
changeValue(filter, event) {
this.props.actions.changeFilter(filter, 'value', event.target.value);
}
removeFilter(filter) {
this.props.actions.removeFilter(filter);
}
render() {
return (
<div>
<div className="row space-1">
<Select
className="col-lg-12"
multi={false}
name="select-column"
placeholder="Select column"
options={this.props.filterColumnOpts.map((o) => ({ value: o, label: o }))}
value={this.props.filter.col}
autosize={false}
onChange={this.changeCol.bind(this, this.props.filter)}
/>
</div>
<div className="row space-1">
<Select
className="col-lg-4"
multi={false}
name="select-op"
placeholder="Select operator"
options={this.state.opChoices.map((o) => ({ value: o, label: o }))}
value={this.props.filter.op}
autosize={false}
onChange={this.changeOp.bind(this, this.props.filter)}
/>
<div className="col-lg-6">
<input
type="text"
onChange={this.changeValue.bind(this, this.props.filter)}
value={this.props.filter.value}
className="form-control input-sm"
placeholder="Filter value"
/>
</div>
<div className="col-lg-2">
<Button
id="remove-button"
bsSize="small"
onClick={this.removeFilter.bind(this, this.props.filter)}
>
<i className="fa fa-minus" />
</Button>
</div>
</div>
</div>
);
}
}

Filter.propTypes = propTypes;
Filter.defaultProps = defaultProps;
113 changes: 31 additions & 82 deletions superset/assets/javascripts/explorev2/components/Filters.jsx
Original file line number Diff line number Diff line change
@@ -1,109 +1,63 @@
import React from 'react';
// import { Tab, Row, Col, Nav, NavItem } from 'react-bootstrap';
import Select from 'react-select';
import Filter from './Filter';
import { Button } from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actions from '../actions/exploreActions';
import shortid from 'shortid';

const propTypes = {
actions: React.PropTypes.object,
actions: React.PropTypes.object.isRequired,
filterColumnOpts: React.PropTypes.array,
filters: React.PropTypes.array,
prefix: React.PropTypes.string,
};

const defaultProps = {
filterColumnOpts: [],
filters: [],
prefix: 'flt',
};

class Filters extends React.Component {
constructor(props) {
super(props);
this.state = {
opOpts: ['in', 'not in'],
};
}
changeField(filter, fieldOpt) {
const val = (fieldOpt) ? fieldOpt.value : null;
this.props.actions.changeFilterField(filter, val);
}
changeOp(filter, opOpt) {
const val = (opOpt) ? opOpt.value : null;
this.props.actions.changeFilterOp(filter, val);
}
changeValue(filter, value) {
this.props.actions.changeFilterValue(filter, value);
}
removeFilter(filter) {
this.props.actions.removeFilter(filter);
}
addFilter() {
this.props.actions.addFilter({
id: shortid.generate(),
field: null,
prefix: this.props.prefix,
col: null,
op: null,
value: null,
});
}
render() {
const filters = this.props.filters.map((filter) => (
<div>
<Select
className="row"
multi={false}
name="select-column"
placeholder="Select column"
options={this.props.filterColumnOpts}
value={filter.field}
autosize={false}
onChange={this.changeField.bind(this, filter)}
/>
<div className="row">
<Select
className="col-sm-3"
multi={false}
name="select-op"
placeholder="Select operator"
options={this.state.opOpts.map((o) => ({ value: o, label: o }))}
value={filter.op}
autosize={false}
onChange={this.changeOp.bind(this, filter)}
const filters = [];
this.props.filters.forEach((filter) => {
// only display filters with current prefix
if (filter.prefix === this.props.prefix) {
filters.push(
<Filter
filterColumnOpts={this.props.filterColumnOpts}
actions={this.props.actions}
prefix={this.props.prefix}
filter={filter}
/>
<div className="col-sm-6">
<input
type="text"
onChange={this.changeValue.bind(this, filter)}
className="form-control input-sm"
placeholder="Filter value"
/>
</div>
<div className="col-sm-3">
);
}
});
return (
<div>
{filters}
<div className="row space-2">
<div className="col-lg-2">
<Button
bsStyle="primary"
onClick={this.removeFilter.bind(this, filter)}
id="add-button"
bsSize="sm"
onClick={this.addFilter.bind(this)}
>
<i className="fa fa-minus" />
<i className="fa fa-plus" /> &nbsp; Add Filter
</Button>
</div>
</div>
</div>
)
);
return (
<div className="panel space-1">
<div className="panel-header">Filters</div>
<div className="panel-body">
{filters}
<Button
bsStyle="primary"
onClick={this.addFilter.bind(this)}
>
<i className="fa fa-plus" />Add Filter
</Button>
</div>
</div>
);
}
}
Expand All @@ -114,14 +68,9 @@ Filters.defaultProps = defaultProps;
function mapStateToProps(state) {
return {
filterColumnOpts: state.filterColumnOpts,
filters: state.filters,
};
}

function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(actions, dispatch),
filters: state.viz.form_data.filters,
};
}

export default connect(mapStateToProps, mapDispatchToProps)(Filters);
export { Filters };
export default connect(mapStateToProps, () => ({}))(Filters);
12 changes: 2 additions & 10 deletions superset/assets/javascripts/explorev2/components/SaveModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import $ from 'jquery';
import { Modal, Alert, Button, Radio } from 'react-bootstrap';
import Select from 'react-select';
import { connect } from 'react-redux';
import { getParamObject } from '../../modules/utils.js';

const propTypes = {
can_edit: PropTypes.bool,
Expand Down Expand Up @@ -57,10 +58,8 @@ class SaveModal extends React.Component {
saveOrOverwrite(gotodash) {
this.setState({ alert: null });
this.props.actions.removeSaveModalAlert();
const params = {};
const params = getParamObject(this.props.form_data, this.props.datasource_type);
const sliceParams = {};
params.datasource_id = this.props.form_data.datasource;
params.datasource_type = this.props.datasource_type;
params.datasource_name = this.props.form_data.datasource_name;

let sliceName = null;
Expand All @@ -76,12 +75,6 @@ class SaveModal extends React.Component {
sliceParams.slice_name = this.props.form_data.slice_name;
}

Object.keys(this.props.form_data).forEach((field) => {
if (this.props.form_data[field] !== null && field !== 'slice_name') {
params[field] = this.props.form_data[field];
}
});

const addToDash = this.state.addToDash;
sliceParams.add_to_dash = addToDash;
let dashboard = null;
Expand All @@ -105,7 +98,6 @@ class SaveModal extends React.Component {
default:
dashboard = null;
}
params.V2 = true;
sliceParams.goto_dash = gotodash;
const baseUrl = '/superset/explore/' +
`${this.props.datasource_type}/${this.props.form_data.datasource}/`;
Expand Down
Loading