Skip to content

Commit

Permalink
[explore] viz type selector as modal (#2787)
Browse files Browse the repository at this point in the history
* [explore] viz type selector as modal

* Addressing comments

* Adressing comments
  • Loading branch information
mistercrunch authored May 30, 2017
1 parent 3a4cd3a commit 66403f1
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 12 deletions.
2 changes: 2 additions & 0 deletions superset/assets/javascripts/explore/components/Control.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import HiddenControl from './controls/HiddenControl';
import SelectControl from './controls/SelectControl';
import TextAreaControl from './controls/TextAreaControl';
import TextControl from './controls/TextControl';
import VizTypeControl from './controls/VizTypeControl';

const controlMap = {
CheckboxControl,
Expand All @@ -15,6 +16,7 @@ const controlMap = {
SelectControl,
TextAreaControl,
TextControl,
VizTypeControl,
};
const controlTypes = Object.keys(controlMap);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Label, Row, Col, FormControl, Modal } from 'react-bootstrap';
import visTypes from '../../stores/visTypes';
import ControlHeader from '../ControlHeader';

const propTypes = {
description: PropTypes.string,
label: PropTypes.string,
name: PropTypes.string.isRequired,
onChange: PropTypes.func,
value: PropTypes.string.isRequired,
};

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

export default class VizTypeControl extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
showModal: false,
filter: '',
};
this.toggleModal = this.toggleModal.bind(this);
this.changeSearch = this.changeSearch.bind(this);
}
onChange(vizType) {
this.props.onChange(vizType);
this.setState({ showModal: false });
}
toggleModal() {
this.setState({ showModal: !this.state.showModal });
}
changeSearch(event) {
this.setState({ filter: event.target.value });
}
renderVizType(vizType) {
const vt = vizType;
return (
<div
className={`viztype-selector-container ${vt === this.props.value ? 'selected' : ''}`}
onClick={this.onChange.bind(this, vt)}
>
<img
alt={`viz-type-${vt}`}
width="100%"
className={`viztype-selector ${this.props.value === vt ? 'selected' : ''}`}
src={`/static/assets/images/viz_thumbnails/${vt}.png`}
/>
<div className="viztype-label">
<strong>{visTypes[vt].label}</strong>
</div>
</div>);
}
render() {
const filter = this.state.filter;
const filteredVizTypes = Object.keys(visTypes)
.filter(vt => filter.length === 0 || visTypes[vt].label.toLowerCase().includes(filter));

const imgPerRow = 4;
const rows = [];
for (let i = 0; i <= filteredVizTypes.length; i += imgPerRow) {
rows.push(
<Row>
{filteredVizTypes.slice(i, i + imgPerRow).map(vt => (
<Col md={3} key={`grid-col-${vt}`}>
{this.renderVizType(vt)}
</Col>
))}
</Row>);
}
return (
<div>
<ControlHeader
{...this.props}
rightNode={
<a onClick={this.toggleModal}>edit</a>
}
/>
<Label onClick={this.toggleModal} style={{ cursor: 'pointer' }}>
{visTypes[this.props.value].label}
</Label>
<Modal show={this.state.showModal} onHide={this.toggleModal} bsSize="lg">
<Modal.Header closeButton>
<Modal.Title>Select a visualization type</Modal.Title>
</Modal.Header>
<Modal.Body>
<div>
<FormControl
id="formControlsText"
type="text"
bsSize="sm"
value={this.state.filter}
placeholder="Search / Filter"
onChange={this.changeSearch}
/>
</div>
{rows}
</Modal.Body>
</Modal>
</div>);
}
}

VizTypeControl.propTypes = propTypes;
VizTypeControl.defaultProps = defaultProps;
25 changes: 25 additions & 0 deletions superset/assets/javascripts/explore/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,28 @@
.background-transparent {
background-color: transparent !important;
}

.viztype-label {
text-align: center;
}

.viztype-selector-container {
cursor: pointer;
margin-top: 10px;
margin-bottom: 10px;
padding: 5px;
border: 1px solid #aaa;
}

.viztype-selector-container:hover {
border: 1px solid #000;
}

.viztype-selector-container.selected {
cursor: not-allowed;
opacity: 0.5;
}
.viztype-selector-container.selected {
cursor: not-allowed;
border: 1px solid #aaa;
}
9 changes: 1 addition & 8 deletions superset/assets/javascripts/explore/stores/controls.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import { formatSelectOptionsForRange, formatSelectOptions } from '../../modules/utils';
import visTypes from './visTypes';
import * as v from '../validators';

const D3_FORMAT_DOCS = 'D3 format syntax: https://github.com/d3/d3-format';
Expand Down Expand Up @@ -48,15 +47,9 @@ export const controls = {
},

viz_type: {
type: 'SelectControl',
type: 'VizTypeControl',
label: 'Visualization Type',
clearable: false,
default: 'table',
choices: Object.keys(visTypes).map(vt => [
vt,
visTypes[vt].label,
`/static/assets/images/viz_thumbnails/${vt}.png`,
]),
description: 'The type of visualization to display',
},

Expand Down
2 changes: 1 addition & 1 deletion superset/assets/javascripts/explore/stores/visTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ const visTypes = {
},

dual_line: {
label: 'Time Series - Dual Axis Line Chart',
label: 'Dual Axis Line Chart',
requiresTime: true,
controlPanelSections: [
{
Expand Down
8 changes: 5 additions & 3 deletions superset/assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"scripts": {
"test": "mocha --require ignore-styles --compilers js:babel-core/register --require spec/helpers/browser.js --recursive spec/**/*_spec.*",
"cover": "babel-node ./node_modules/.bin/istanbul cover _mocha -- --require spec/helpers/browser.js --recursive spec/**/*_spec.*",
"cover": "babel-node node_modules/.bin/babel-istanbul cover _mocha -- --require spec/helpers/browser.js --recursive spec/**/*_spec.*",
"dev": "NODE_ENV=dev webpack --watch --colors --progress --debug --output-pathinfo --devtool inline-source-map",
"prod": "NODE_ENV=production node --max_old_space_size=4096 ./node_modules/webpack/bin/webpack.js -p --colors --progress",
"build": "NODE_ENV=production webpack --colors --progress",
Expand Down Expand Up @@ -59,6 +59,7 @@
"immutability-helper": "^2.0.0",
"immutable": "^3.8.1",
"jquery": "^3.2.1",
"jsdom": "9.12.0",
"lodash.throttle": "^4.1.1",
"mapbox-gl": "^0.26.0",
"moment": "^2.14.1",
Expand Down Expand Up @@ -98,9 +99,10 @@
"devDependencies": {
"babel-cli": "^6.14.0",
"babel-core": "^6.10.4",
"babel-istanbul": "^0.12.2",
"babel-loader": "^6.2.4",
"babel-plugin-css-modules-transform": "^1.1.0",
"babel-polyfill": "^6.14.0",
"babel-polyfill": "^6.23.0",
"babel-preset-airbnb": "^2.1.1",
"babel-preset-es2015": "^6.14.0",
"babel-preset-react": "^6.11.1",
Expand All @@ -119,7 +121,7 @@
"ignore-styles": "^5.0.1",
"imports-loader": "^0.7.1",
"istanbul": "^1.0.0-alpha",
"jsdom": "^9.12.0",
"jsdom": "9.12.0",
"json-loader": "^0.5.4",
"less": "^2.6.1",
"less-loader": "^4.0.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import sinon from 'sinon';
import { expect } from 'chai';
import { describe, it, beforeEach } from 'mocha';
import { shallow } from 'enzyme';
import { Modal } from 'react-bootstrap';
import VizTypeControl from '../../../../javascripts/explore/components/controls/VizTypeControl';

const defaultProps = {
name: 'viz_type',
label: 'Visualization Type',
value: 'table',
onChange: sinon.spy(),
};

describe('VizTypeControl', () => {
let wrapper;

beforeEach(() => {
wrapper = shallow(<VizTypeControl {...defaultProps} />);
});

it('renders a Modal', () => {
expect(wrapper.find(Modal)).to.have.lengthOf(1);
});

it('calls onChange when toggled', () => {
const select = wrapper.find('.viztype-selector-container').first();
select.simulate('click');
expect(defaultProps.onChange.called).to.equal(true);
});
it('filters images based on text input', () => {
expect(wrapper.find('img').length).to.be.above(20);
wrapper.setState({ filter: 'time' });
expect(wrapper.find('img').length).to.be.below(10);
});
});
5 changes: 5 additions & 0 deletions superset/assets/stylesheets/less/cosmo/bootswatch.less
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,8 @@ hr {
}
}
.space-loop(6);

a {
cursor: pointer;
}

0 comments on commit 66403f1

Please sign in to comment.