mirror of
https://github.com/apache/superset.git
synced 2026-05-07 17:04:58 +00:00
Linted all, refactored VisualizeModal out
This commit is contained in:
@@ -22,7 +22,7 @@ export const REMOVE_WORKSPACE_QUERY = 'REMOVE_WORKSPACE_QUERY';
|
||||
export const SET_ACTIVE_QUERY_EDITOR = 'SET_ACTIVE_QUERY_EDITOR';
|
||||
|
||||
export function resetState() {
|
||||
return { type: RESET_STATE };
|
||||
return { type: RESET_STATE };
|
||||
}
|
||||
|
||||
export function addQueryEditor(queryEditor) {
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
import React from 'react';
|
||||
import { Button, OverlayTrigger, Tooltip } from 'react-bootstrap';
|
||||
|
||||
|
||||
class ButtonWithTooltip extends React.Component {
|
||||
render() {
|
||||
let tooltip = (
|
||||
<Tooltip id="tooltip">
|
||||
{this.props.tooltip}
|
||||
</Tooltip>
|
||||
);
|
||||
return (
|
||||
<OverlayTrigger
|
||||
overlay={tooltip}
|
||||
delayShow={300}
|
||||
placement={this.props.placement}
|
||||
delayHide={150}
|
||||
const ButtonWithTooltip = (props) => {
|
||||
let tooltip = (
|
||||
<Tooltip id="tooltip">
|
||||
{props.tooltip}
|
||||
</Tooltip>
|
||||
);
|
||||
return (
|
||||
<OverlayTrigger
|
||||
overlay={tooltip}
|
||||
delayShow={300}
|
||||
placement={props.placement}
|
||||
delayHide={150}
|
||||
>
|
||||
<Button
|
||||
onClick={props.onClick}
|
||||
bsStyle={props.bsStyle}
|
||||
disabled={props.disabled}
|
||||
className={props.className}
|
||||
>
|
||||
<Button
|
||||
onClick={this.props.onClick}
|
||||
bsStyle={this.props.bsStyle}
|
||||
disabled={this.props.disabled}
|
||||
className={this.props.className}
|
||||
>
|
||||
{this.props.children}
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
}
|
||||
{props.children}
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
};
|
||||
|
||||
ButtonWithTooltip.defaultProps = {
|
||||
onClick: () => {},
|
||||
disabled: false,
|
||||
|
||||
@@ -8,51 +8,52 @@ import QueryLink from './QueryLink';
|
||||
// CSS
|
||||
import 'react-select/dist/react-select.css';
|
||||
|
||||
class LeftPane extends React.Component {
|
||||
render() {
|
||||
let queryElements;
|
||||
if (this.props.workspaceQueries.length > 0) {
|
||||
queryElements = this.props.workspaceQueries.map((q) => <QueryLink query={q} />);
|
||||
} else {
|
||||
queryElements = (
|
||||
<Alert bsStyle="info">
|
||||
Use the save button on the SQL editor to save a query into this section for
|
||||
future reference
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="panel panel-default LeftPane">
|
||||
<div className="panel-heading">
|
||||
<h6 className="m-r-10">
|
||||
<i className="fa fa-flask" />
|
||||
SQL Lab <Label bsStyle="danger">ALPHA</Label>
|
||||
</h6>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
<div>
|
||||
<h6>
|
||||
<span className="fa-stack">
|
||||
<i className="fa fa-database fa-stack-lg"></i>
|
||||
<i className="fa fa-search fa-stack-1x"></i>
|
||||
</span> Saved Queries
|
||||
</h6>
|
||||
<div>
|
||||
{queryElements}
|
||||
</div>
|
||||
<hr />
|
||||
<Button onClick={this.props.actions.resetState.bind(this)}>
|
||||
Reset State
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
const LeftPane = (props) => {
|
||||
let queryElements;
|
||||
if (props.workspaceQueries.length > 0) {
|
||||
queryElements = props.workspaceQueries.map((q) => <QueryLink query={q} />);
|
||||
} else {
|
||||
queryElements = (
|
||||
<Alert bsStyle="info">
|
||||
Use the save button on the SQL editor to save a query into this section for
|
||||
future reference
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div className="panel panel-default LeftPane">
|
||||
<div className="panel-heading">
|
||||
<h6 className="m-r-10">
|
||||
<i className="fa fa-flask" />
|
||||
SQL Lab <Label bsStyle="danger">ALPHA</Label>
|
||||
</h6>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
<div>
|
||||
<h6>
|
||||
<span className="fa-stack">
|
||||
<i className="fa fa-database fa-stack-lg"></i>
|
||||
<i className="fa fa-search fa-stack-1x"></i>
|
||||
</span> Saved Queries
|
||||
</h6>
|
||||
<div>
|
||||
{queryElements}
|
||||
</div>
|
||||
<hr />
|
||||
<Button onClick={props.actions.resetState.bind(this)}>
|
||||
Reset State
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
LeftPane.propTypes = {
|
||||
workspaceQueries: React.PropTypes.array,
|
||||
actions: React.PropTypes.object,
|
||||
};
|
||||
|
||||
LeftPane.defaultProps = {
|
||||
workspaceQueries: [],
|
||||
};
|
||||
|
||||
@@ -7,30 +7,29 @@ import * as Actions from '../actions';
|
||||
import QueryTable from './QueryTable';
|
||||
import { Alert } from 'react-bootstrap';
|
||||
|
||||
class QueryLog extends React.Component {
|
||||
render() {
|
||||
const activeQeId = this.props.tabHistory[this.props.tabHistory.length - 1];
|
||||
const queries = this.props.queries.filter((q) => (q.sqlEditorId === activeQeId));
|
||||
if (queries.length > 0) {
|
||||
return (
|
||||
<QueryTable
|
||||
columns={['state', 'started', 'duration', 'rows', 'sql', 'actions']}
|
||||
queries={queries}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const QueryHistory = (props) => {
|
||||
const activeQeId = props.tabHistory[props.tabHistory.length - 1];
|
||||
const queries = props.queries.filter((q) => (q.sqlEditorId === activeQeId));
|
||||
if (queries.length > 0) {
|
||||
return (
|
||||
<Alert bsStyle="info">
|
||||
No query history yet...
|
||||
</Alert>
|
||||
<QueryTable
|
||||
columns={['state', 'started', 'duration', 'rows', 'sql', 'actions']}
|
||||
queries={queries}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
QueryLog.defaultProps = {
|
||||
return (
|
||||
<Alert bsStyle="info">
|
||||
No query history yet...
|
||||
</Alert>
|
||||
);
|
||||
};
|
||||
|
||||
QueryHistory.defaultProps = {
|
||||
queries: [],
|
||||
};
|
||||
|
||||
QueryLog.propTypes = {
|
||||
QueryHistory.propTypes = {
|
||||
queries: React.PropTypes.array,
|
||||
tabHistory: React.PropTypes.array,
|
||||
actions: React.PropTypes.object,
|
||||
@@ -48,4 +47,4 @@ function mapDispatchToProps(dispatch) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(QueryLog);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(QueryHistory);
|
||||
@@ -1,12 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Alert, Modal } from 'react-bootstrap';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as Actions from '../actions';
|
||||
|
||||
import Select from 'react-select';
|
||||
|
||||
import moment from 'moment';
|
||||
import { Table } from 'reactable';
|
||||
|
||||
@@ -14,6 +11,7 @@ import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||
import { github } from 'react-syntax-highlighter/dist/styles';
|
||||
|
||||
import Link from './Link';
|
||||
import VisualizeModal from './VisualizeModal';
|
||||
|
||||
// TODO move to CSS
|
||||
const STATE_COLOR_MAP = {
|
||||
@@ -35,9 +33,7 @@ class QueryTable extends React.Component {
|
||||
}
|
||||
showVisualizeModal(query) {
|
||||
this.setState({ showVisualizeModal: true });
|
||||
this.state.activeQuery = query;
|
||||
}
|
||||
changeChartType(event) {
|
||||
this.setState({ activeQuery: query });
|
||||
}
|
||||
render() {
|
||||
const data = this.props.queries.map((query) => {
|
||||
@@ -87,58 +83,13 @@ class QueryTable extends React.Component {
|
||||
|
||||
return q;
|
||||
}).reverse();
|
||||
let visualizeModalBody;
|
||||
if (this.state.activeQuery) {
|
||||
const cols = this.state.activeQuery.results.columns;
|
||||
visualizeModalBody = (
|
||||
<div>
|
||||
<Select
|
||||
name="select-chart-type"
|
||||
placeholder="[Chart Type]"
|
||||
options={[
|
||||
{ value: 'line', label: 'Time Series - Line Chart' },
|
||||
{ value: 'bar', label: 'Time Series - Bar Chart' },
|
||||
{ value: 'bar_dist', label: 'Distribution - Bar Chart' },
|
||||
{ value: 'pie', label: 'Pie Chart' },
|
||||
]}
|
||||
value={null}
|
||||
autosize={false}
|
||||
onChange={this.changeChartType.bind(this)}
|
||||
/>
|
||||
<Table
|
||||
className="table table-condensed"
|
||||
columns={['column', 'is_dimension', 'is_date', 'agg_func']}
|
||||
data={cols.map((col) => ({
|
||||
column: col,
|
||||
is_dimension: <input type="checkbox" className="form-control" />,
|
||||
is_date: <input type="checkbox" className="form-control" />,
|
||||
agg_func: (
|
||||
<Select
|
||||
options={[
|
||||
{ value: 'sum', label: 'SUM(x)' },
|
||||
{ value: 'min', label: 'MIN(x)' },
|
||||
{ value: 'max', label: 'MAX(x)' },
|
||||
{ value: 'avg', label: 'AVG(x)' },
|
||||
{ value: 'count_distinct', label: 'COUNT(DISTINCT x)' },
|
||||
]}
|
||||
/>
|
||||
),
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Modal show={this.state.showVisualizeModal} onHide={this.hideVisualizeModal.bind(this)}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>Visualize (mock)</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<Alert bsStyle="danger">Not functional - Work in progress!</Alert>
|
||||
{visualizeModalBody}
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
<VisualizeModal
|
||||
show={this.state.showVisualizeModal}
|
||||
query={this.state.activeQuery}
|
||||
onHide={this.hideVisualizeModal.bind(this)}
|
||||
/>
|
||||
<Table
|
||||
columns={['state', 'started', 'duration', 'rows', 'sql', 'actions']}
|
||||
className="table table-condensed"
|
||||
@@ -158,9 +109,8 @@ QueryTable.defaultProps = {
|
||||
queries: [],
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
};
|
||||
function mapStateToProps() {
|
||||
return {};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
|
||||
@@ -2,10 +2,31 @@ import React from 'react';
|
||||
import { Alert, Button } from 'react-bootstrap';
|
||||
import { Table } from 'reactable';
|
||||
|
||||
import VisualizeModal from './VisualizeModal';
|
||||
|
||||
|
||||
class ResultSet extends React.Component {
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
searchText: '',
|
||||
showModal: false,
|
||||
};
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return (
|
||||
this.state.searchText !== nextState.searchText ||
|
||||
this.state.showModal !== nextState.showModal
|
||||
);
|
||||
}
|
||||
changeSearch(event) {
|
||||
this.setState({ searchText: event.target.value });
|
||||
}
|
||||
showModal() {
|
||||
this.setState({ showModal: true });
|
||||
}
|
||||
hideModal() {
|
||||
this.setState({ showModal: false });
|
||||
}
|
||||
render() {
|
||||
const results = this.props.query.results;
|
||||
@@ -15,11 +36,18 @@ class ResultSet extends React.Component {
|
||||
<div className="ResultSetControls">
|
||||
<div className="clearfix">
|
||||
<div className="pull-left">
|
||||
<Button className="m-r-5"><i className="fa fa-line-chart" />Visualize</Button>
|
||||
<Button className="m-r-5"><i className="fa fa-file-text-o" />.CSV</Button>
|
||||
<Button className="m-r-5" onClick={this.showModal.bind(this)}>
|
||||
<i className="fa fa-line-chart m-l-1" /> Visualize
|
||||
</Button>
|
||||
<Button className="m-r-5"><i className="fa fa-file-text-o" /> .CSV</Button>
|
||||
</div>
|
||||
<div className="pull-right">
|
||||
<input type="text" className="form-control" placeholder="Search Results" />
|
||||
<input
|
||||
type="text"
|
||||
onChange={this.changeSearch.bind(this)}
|
||||
className="form-control"
|
||||
placeholder="Search Results"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -27,14 +55,24 @@ class ResultSet extends React.Component {
|
||||
}
|
||||
if (results.data.length > 0) {
|
||||
return (
|
||||
<div className="ResultSet">
|
||||
{controls}
|
||||
<Table
|
||||
data={results.data}
|
||||
columns={results.columns}
|
||||
sortable
|
||||
className="table table-condensed table-bordered"
|
||||
<div>
|
||||
<VisualizeModal
|
||||
show={this.state.showModal}
|
||||
query={this.props.query}
|
||||
onHide={this.hideModal.bind(this)}
|
||||
/>
|
||||
{controls}
|
||||
<div className="ResultSet">
|
||||
<Table
|
||||
data={results.data}
|
||||
columns={results.columns}
|
||||
sortable
|
||||
className="table table-condensed table-bordered"
|
||||
filterBy={this.state.searchText}
|
||||
filterable={results.columns}
|
||||
hideFilterInput
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -45,10 +83,12 @@ ResultSet.propTypes = {
|
||||
query: React.PropTypes.object,
|
||||
showControls: React.PropTypes.boolean,
|
||||
search: React.PropTypes.boolean,
|
||||
searchText: React.PropTypes.string,
|
||||
};
|
||||
ResultSet.defaultProps = {
|
||||
showControls: true,
|
||||
search: true,
|
||||
searchText: '',
|
||||
};
|
||||
|
||||
export default ResultSet;
|
||||
|
||||
@@ -1,38 +1,36 @@
|
||||
import { Tab, Tabs } from 'react-bootstrap';
|
||||
import QueryLog from './QueryLog';
|
||||
import QueryHistory from './QueryHistory';
|
||||
import ResultSet from './ResultSet';
|
||||
import React from 'react';
|
||||
|
||||
class SouthPane extends React.Component {
|
||||
render() {
|
||||
let results;
|
||||
if (this.props.latestQuery) {
|
||||
if (this.props.latestQuery.state === 'running') {
|
||||
results = (
|
||||
<img className="loading" alt="Loading.." src="/static/assets/images/loading.gif" />
|
||||
);
|
||||
} else if (this.props.latestQuery.state === 'failed') {
|
||||
results = <div className="alert alert-danger">{this.props.latestQuery.msg}</div>;
|
||||
} else if (this.props.latestQuery.state === 'success') {
|
||||
results = <ResultSet showControls query={this.props.latestQuery} />;
|
||||
}
|
||||
} else {
|
||||
results = <div className="alert alert-info">Run a query to display results here</div>;
|
||||
const SouthPane = (props) => {
|
||||
let results;
|
||||
if (props.latestQuery) {
|
||||
if (props.latestQuery.state === 'running') {
|
||||
results = (
|
||||
<img className="loading" alt="Loading.." src="/static/assets/images/loading.gif" />
|
||||
);
|
||||
} else if (props.latestQuery.state === 'failed') {
|
||||
results = <div className="alert alert-danger">{props.latestQuery.msg}</div>;
|
||||
} else if (props.latestQuery.state === 'success') {
|
||||
results = <ResultSet showControls query={props.latestQuery} />;
|
||||
}
|
||||
return (
|
||||
<Tabs bsStyle="pills">
|
||||
<Tab title="Results" eventKey={1}>
|
||||
<div style={{ overflow: 'auto' }}>
|
||||
{results}
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab title="Query Log" eventKey={2}>
|
||||
<QueryLog />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
);
|
||||
} else {
|
||||
results = <div className="alert alert-info">Run a query to display results here</div>;
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Tabs bsStyle="pills">
|
||||
<Tab title="Results" eventKey={1}>
|
||||
<div style={{ overflow: 'auto' }}>
|
||||
{results}
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab title="Query History" eventKey={2}>
|
||||
<QueryHistory />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
SouthPane.propTypes = {
|
||||
latestQuery: React.PropTypes.object,
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
const $ = window.$ = require('jquery');
|
||||
import React from 'react';
|
||||
import { Button, ButtonGroup, DropdownButton, Label, MenuItem, OverlayTrigger, Tooltip } from 'react-bootstrap';
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
DropdownButton,
|
||||
Label,
|
||||
MenuItem,
|
||||
OverlayTrigger,
|
||||
Tooltip,
|
||||
} from 'react-bootstrap';
|
||||
|
||||
import AceEditor from 'react-ace';
|
||||
import 'brace/mode/sql';
|
||||
@@ -29,6 +37,9 @@ class SqlEditor extends React.Component {
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
this.onMount();
|
||||
}
|
||||
onMount() {
|
||||
if (this.state.autorun) {
|
||||
this.setState({ autorun: false });
|
||||
this.props.actions.queryEditorSetAutorun(this.props.queryEditor, false);
|
||||
@@ -94,12 +105,9 @@ class SqlEditor extends React.Component {
|
||||
this.props.actions.stopQuery(this.props.latestQuery);
|
||||
}
|
||||
textChange(text) {
|
||||
this.setState({ sql: text })
|
||||
this.setState({ sql: text });
|
||||
this.props.actions.queryEditorSetSql(this.props.queryEditor, text);
|
||||
}
|
||||
notImplemented() {
|
||||
alert('Not implemented');
|
||||
}
|
||||
addWorkspaceQuery() {
|
||||
this.props.actions.addWorkspaceQuery({
|
||||
id: shortid.generate(),
|
||||
@@ -152,12 +160,12 @@ class SqlEditor extends React.Component {
|
||||
</ButtonGroup>
|
||||
);
|
||||
let limitWarning = null;
|
||||
const row_limit = 1000;
|
||||
if (this.props.latestQuery && this.props.latestQuery.rows === row_limit) {
|
||||
const rowLimit = 1000;
|
||||
if (this.props.latestQuery && this.props.latestQuery.rows === rowLimit) {
|
||||
const tooltip = (
|
||||
<Tooltip id="tooltip">
|
||||
It appears that the number of rows in the query results displayed
|
||||
was limited on the server side to the {row_limit} limit.
|
||||
was limited on the server side to the {rowLimit} limit.
|
||||
</Tooltip>
|
||||
);
|
||||
limitWarning = (
|
||||
@@ -219,9 +227,8 @@ SqlEditor.propTypes = {
|
||||
SqlEditor.defaultProps = {
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
};
|
||||
function mapStateToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
|
||||
@@ -123,9 +123,6 @@ class SqlEditorTopToolbar extends React.Component {
|
||||
that.setState({ databaseLoading: false });
|
||||
});
|
||||
}
|
||||
notImplemented() {
|
||||
alert('Not implemented');
|
||||
}
|
||||
closePopover(ref) {
|
||||
this.refs[ref].hide();
|
||||
}
|
||||
|
||||
@@ -35,10 +35,9 @@ class QueryEditors extends React.Component {
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const that = this;
|
||||
const editors = this.props.queryEditors.map((qe, i) => {
|
||||
let latestQuery;
|
||||
that.props.queries.forEach((q) => {
|
||||
this.props.queries.forEach((q) => {
|
||||
if (q.id === qe.latestQueryId) {
|
||||
latestQuery = q;
|
||||
}
|
||||
@@ -53,10 +52,10 @@ class QueryEditors extends React.Component {
|
||||
className="no-shadow"
|
||||
id="bg-vertical-dropdown-1"
|
||||
>
|
||||
<MenuItem eventKey="1" onClick={that.props.actions.removeQueryEditor.bind(that, qe)}>
|
||||
<MenuItem eventKey="1" onClick={this.props.actions.removeQueryEditor.bind(this, qe)}>
|
||||
<i className="fa fa-close" /> close tab
|
||||
</MenuItem>
|
||||
<MenuItem eventKey="2" onClick={that.renameTab.bind(that, qe)}>
|
||||
<MenuItem eventKey="2" onClick={this.renameTab.bind(this, qe)}>
|
||||
<i className="fa fa-i-cursor" /> rename tab
|
||||
</MenuItem>
|
||||
</DropdownButton>
|
||||
@@ -90,8 +89,9 @@ class QueryEditors extends React.Component {
|
||||
}
|
||||
QueryEditors.propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
tabHistory: React.PropTypes.array,
|
||||
queries: React.PropTypes.array,
|
||||
queryEditors: React.PropTypes.array,
|
||||
tabHistory: React.PropTypes.array,
|
||||
workspaceDatabase: React.PropTypes.object,
|
||||
};
|
||||
QueryEditors.defaultProps = {
|
||||
|
||||
@@ -12,10 +12,9 @@ import 'react-select/dist/react-select.css';
|
||||
class TableWorkspaceElement extends React.Component {
|
||||
selectStar() {
|
||||
let cols = '';
|
||||
const that = this;
|
||||
this.props.table.columns.forEach(function (col, i) {
|
||||
this.props.table.columns.forEach((col, i) => {
|
||||
cols += col.name;
|
||||
if (i < that.props.table.columns.length - 1) {
|
||||
if (i < this.props.table.columns.length - 1) {
|
||||
cols += ', ';
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import React from 'react';
|
||||
import { Alert, Modal } from 'react-bootstrap';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as Actions from '../actions';
|
||||
|
||||
import Select from 'react-select';
|
||||
import { Table } from 'reactable';
|
||||
|
||||
class VisualizeModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
chartType: null,
|
||||
};
|
||||
}
|
||||
changeChartType(event) {
|
||||
this.setState({ chartType: event.target.value });
|
||||
}
|
||||
render() {
|
||||
if (!(this.props.query)) {
|
||||
return <div />;
|
||||
}
|
||||
const cols = this.props.query.results.columns;
|
||||
const modal = (
|
||||
<div className="VisualizeModal">
|
||||
<Modal show={this.props.show} onHide={this.props.onHide}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>Visualize (mock)</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<Alert bsStyle="danger">Not functional - Work in progress!</Alert>
|
||||
<div>
|
||||
<Select
|
||||
name="select-chart-type"
|
||||
placeholder="[Chart Type]"
|
||||
options={[
|
||||
{ value: 'line', label: 'Time Series - Line Chart' },
|
||||
{ value: 'bar', label: 'Time Series - Bar Chart' },
|
||||
{ value: 'bar_dist', label: 'Distribution - Bar Chart' },
|
||||
{ value: 'pie', label: 'Pie Chart' },
|
||||
]}
|
||||
value={this.state.chartType}
|
||||
autosize={false}
|
||||
onChange={this.changeChartType.bind(this)}
|
||||
/>
|
||||
<Table
|
||||
className="table table-condensed"
|
||||
columns={['column', 'is_dimension', 'is_date', 'agg_func']}
|
||||
data={cols.map((col) => ({
|
||||
column: col,
|
||||
is_dimension: <input type="checkbox" className="form-control" />,
|
||||
is_date: <input type="checkbox" className="form-control" />,
|
||||
agg_func: (
|
||||
<Select
|
||||
options={[
|
||||
{ value: 'sum', label: 'SUM(x)' },
|
||||
{ value: 'min', label: 'MIN(x)' },
|
||||
{ value: 'max', label: 'MAX(x)' },
|
||||
{ value: 'avg', label: 'AVG(x)' },
|
||||
{ value: 'count_distinct', label: 'COUNT(DISTINCT x)' },
|
||||
]}
|
||||
/>
|
||||
),
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
return modal;
|
||||
}
|
||||
}
|
||||
VisualizeModal.propTypes = {
|
||||
query: React.PropTypes.object,
|
||||
show: React.PropTypes.boolean,
|
||||
onHide: React.PropTypes.function,
|
||||
};
|
||||
VisualizeModal.defaultProps = {
|
||||
show: false,
|
||||
};
|
||||
|
||||
function mapStateToProps() {
|
||||
return {};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(Actions, dispatch),
|
||||
};
|
||||
}
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(VisualizeModal);
|
||||
@@ -81,6 +81,9 @@ div.Workspace {
|
||||
.m-r-5 {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.m-l-1 {
|
||||
margin-left: 1px;
|
||||
}
|
||||
.m-r-10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@@ -142,4 +142,4 @@ export const sqlLabReducer = function (state, action) {
|
||||
return actionHandlers[action.type]();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user