diff --git a/.gitignore b/.gitignore index eb93aa3c20e..4e17f90a989 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.pyc +caravel/assets/coverage/* changelog.sh .DS_Store .coverage diff --git a/caravel/assets/.eslintignore b/caravel/assets/.eslintignore index 7b1f78cba3c..b282235ac08 100644 --- a/caravel/assets/.eslintignore +++ b/caravel/assets/.eslintignore @@ -5,6 +5,5 @@ dist/* images/* node_modules/* node_modules*/* -spec/* stylesheets/* vendor/* diff --git a/caravel/assets/javascripts/SqlLab/actions.js b/caravel/assets/javascripts/SqlLab/actions.js index f805dce4114..9634a6a83ab 100644 --- a/caravel/assets/javascripts/SqlLab/actions.js +++ b/caravel/assets/javascripts/SqlLab/actions.js @@ -18,8 +18,6 @@ export const QUERY_EDITOR_SET_TITLE = 'QUERY_EDITOR_SET_TITLE'; export const QUERY_EDITOR_SET_AUTORUN = 'QUERY_EDITOR_SET_AUTORUN'; export const QUERY_EDITOR_SET_SQL = 'QUERY_EDITOR_SET_SQL'; export const SET_DATABASES = 'SET_DATABASES'; -export const ADD_WORKSPACE_QUERY = 'ADD_WORKSPACE_QUERY'; -export const REMOVE_WORKSPACE_QUERY = 'REMOVE_WORKSPACE_QUERY'; export const SET_ACTIVE_QUERY_EDITOR = 'SET_ACTIVE_QUERY_EDITOR'; export const ADD_ALERT = 'ADD_ALERT'; export const REMOVE_ALERT = 'REMOVE_ALERT'; @@ -141,7 +139,8 @@ export function setDatabases(databases) { } export function addQueryEditor(queryEditor) { - return { type: ADD_QUERY_EDITOR, queryEditor }; + const newQe = Object.assign({}, queryEditor, { id: shortid.generate() }); + return { type: ADD_QUERY_EDITOR, queryEditor: newQe }; } export function cloneQueryToNewTab(query) { @@ -153,7 +152,9 @@ export function setNetworkStatus(networkOn) { } export function addAlert(alert) { - return { type: ADD_ALERT, alert }; + const o = Object.assign({}, alert); + o.id = shortid.generate(); + return { type: ADD_ALERT, o }; } export function removeAlert(alert) { @@ -208,13 +209,6 @@ export function removeTable(table) { return { type: REMOVE_TABLE, table }; } -export function addWorkspaceQuery(query) { - return { type: ADD_WORKSPACE_QUERY, query }; -} - -export function removeWorkspaceQuery(query) { - return { type: REMOVE_WORKSPACE_QUERY, query }; -} export function refreshQueries(alteredQueries) { return { type: REFRESH_QUERIES, alteredQueries }; } diff --git a/caravel/assets/javascripts/SqlLab/components/Alerts.jsx b/caravel/assets/javascripts/SqlLab/components/Alerts.jsx index 0ad6d845ecd..f009fdd2f1a 100644 --- a/caravel/assets/javascripts/SqlLab/components/Alerts.jsx +++ b/caravel/assets/javascripts/SqlLab/components/Alerts.jsx @@ -1,8 +1,5 @@ import React from 'react'; import { Alert } from 'react-bootstrap'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import * as Actions from '../actions'; class Alerts extends React.Component { removeAlert(alert) { @@ -11,6 +8,7 @@ class Alerts extends React.Component { render() { const alerts = this.props.alerts.map((alert) => @@ -33,9 +31,4 @@ Alerts.propTypes = { actions: React.PropTypes.object, }; -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators(Actions, dispatch), - }; -} -export default connect(null, mapDispatchToProps)(Alerts); +export default Alerts; diff --git a/caravel/assets/javascripts/SqlLab/components/App.jsx b/caravel/assets/javascripts/SqlLab/components/App.jsx index 6e2fa2f990c..dd46ef10f0c 100644 --- a/caravel/assets/javascripts/SqlLab/components/App.jsx +++ b/caravel/assets/javascripts/SqlLab/components/App.jsx @@ -48,7 +48,7 @@ class App extends React.Component { } return (
- +
{content} @@ -60,6 +60,7 @@ class App extends React.Component { App.propTypes = { alerts: React.PropTypes.array, + actions: React.PropTypes.object, }; function mapStateToProps(state) { @@ -73,4 +74,5 @@ function mapDispatchToProps(dispatch) { }; } +export { App }; export default connect(mapStateToProps, mapDispatchToProps)(App); diff --git a/caravel/assets/javascripts/SqlLab/components/ButtonWithTooltip.jsx b/caravel/assets/javascripts/SqlLab/components/ButtonWithTooltip.jsx deleted file mode 100644 index e98da5a9d9c..00000000000 --- a/caravel/assets/javascripts/SqlLab/components/ButtonWithTooltip.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react'; -import { Button, OverlayTrigger, Tooltip } from 'react-bootstrap'; - -const ButtonWithTooltip = (props) => { - let tooltip = ( - - {props.tooltip} - - ); - return ( - - - - ); -}; - -ButtonWithTooltip.defaultProps = { - onClick: () => {}, - disabled: false, - placement: 'top', - bsStyle: 'default', -}; - -ButtonWithTooltip.propTypes = { - bsSize: React.PropTypes.string, - bsStyle: React.PropTypes.string, - children: React.PropTypes.element, - className: React.PropTypes.string, - disabled: React.PropTypes.bool, - onClick: React.PropTypes.func, - placement: React.PropTypes.string, - tooltip: React.PropTypes.string, -}; - -export default ButtonWithTooltip; diff --git a/caravel/assets/javascripts/SqlLab/components/CopyQueryTabUrl.jsx b/caravel/assets/javascripts/SqlLab/components/CopyQueryTabUrl.jsx index cd0a6e75e25..3b725d5cc12 100644 --- a/caravel/assets/javascripts/SqlLab/components/CopyQueryTabUrl.jsx +++ b/caravel/assets/javascripts/SqlLab/components/CopyQueryTabUrl.jsx @@ -3,11 +3,11 @@ import CopyToClipboard from '../../components/CopyToClipboard'; import { getShortUrl } from '../../../utils/common'; const propTypes = { - qe: React.PropTypes.object, + queryEditor: React.PropTypes.object, }; const defaultProps = { - qe: null, + queryEditor: null, }; export default class CopyQueryTabUrl extends React.Component { @@ -20,7 +20,7 @@ export default class CopyQueryTabUrl extends React.Component { componentWillMount() { const params = []; - const qe = this.props.qe; + const qe = this.props.queryEditor; if (qe.dbId) params.push('dbid=' + qe.dbId); if (qe.title) params.push('title=' + encodeURIComponent(qe.title)); if (qe.schema) params.push('schema=' + encodeURIComponent(qe.schema)); diff --git a/caravel/assets/javascripts/SqlLab/components/DataPreviewModal.jsx b/caravel/assets/javascripts/SqlLab/components/DataPreviewModal.jsx index 989b94148ce..40e078d284b 100644 --- a/caravel/assets/javascripts/SqlLab/components/DataPreviewModal.jsx +++ b/caravel/assets/javascripts/SqlLab/components/DataPreviewModal.jsx @@ -32,7 +32,7 @@ class DataPreviewModal extends React.Component { - + ); diff --git a/caravel/assets/javascripts/SqlLab/components/DatabaseSelect.jsx b/caravel/assets/javascripts/SqlLab/components/DatabaseSelect.jsx index 55c1166e038..6719db52191 100644 --- a/caravel/assets/javascripts/SqlLab/components/DatabaseSelect.jsx +++ b/caravel/assets/javascripts/SqlLab/components/DatabaseSelect.jsx @@ -1,9 +1,6 @@ const $ = window.$ = require('jquery'); import React from 'react'; -import { bindActionCreators } from 'redux'; import Select from 'react-select'; -import { connect } from 'react-redux'; -import * as Actions from '../actions'; class DatabaseSelect extends React.Component { constructor(props) { @@ -53,15 +50,4 @@ DatabaseSelect.propTypes = { valueRenderer: React.PropTypes.func, }; -DatabaseSelect.defaultProps = { - onChange: () => {}, - databaseId: null, -}; - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators(Actions, dispatch), - }; -} - -export default connect(null, mapDispatchToProps)(DatabaseSelect); +export default DatabaseSelect; diff --git a/caravel/assets/javascripts/SqlLab/components/Link.jsx b/caravel/assets/javascripts/SqlLab/components/Link.jsx index 4fff9db7e01..2f322dc82b7 100644 --- a/caravel/assets/javascripts/SqlLab/components/Link.jsx +++ b/caravel/assets/javascripts/SqlLab/components/Link.jsx @@ -1,6 +1,24 @@ import React from 'react'; import { OverlayTrigger, Tooltip } from 'react-bootstrap'; +const propTypes = { + children: React.PropTypes.node, + className: React.PropTypes.string, + href: React.PropTypes.string, + onClick: React.PropTypes.func, + placement: React.PropTypes.string, + style: React.PropTypes.object, + tooltip: React.PropTypes.string, +}; +const defaultProps = { + className: '', + href: '#', + onClick: () => {}, + placement: 'top', + style: {}, + tooltip: null, +}; + class Link extends React.Component { render() { @@ -34,21 +52,7 @@ class Link extends React.Component { return link; } } -Link.propTypes = { - children: React.PropTypes.object, - className: React.PropTypes.string, - href: React.PropTypes.string, - onClick: React.PropTypes.func, - placement: React.PropTypes.string, - style: React.PropTypes.object, - tooltip: React.PropTypes.string, -}; -Link.defaultProps = { - disabled: false, - href: '#', - tooltip: null, - placement: 'top', - onClick: () => {}, -}; +Link.propTypes = propTypes; +Link.defaultProps = defaultProps; export default Link; diff --git a/caravel/assets/javascripts/SqlLab/components/QueryAutoRefresh.jsx b/caravel/assets/javascripts/SqlLab/components/QueryAutoRefresh.jsx index 609b106a675..851ab35001a 100644 --- a/caravel/assets/javascripts/SqlLab/components/QueryAutoRefresh.jsx +++ b/caravel/assets/javascripts/SqlLab/components/QueryAutoRefresh.jsx @@ -30,14 +30,10 @@ class QueryAutoRefresh extends React.Component { if (Object.keys(data).length > 0) { this.props.actions.refreshQueries(data); } - if (!this.props.networkOn) { - this.props.actions.setNetworkStatus(true); - } + this.props.actions.setNetworkStatus(true); }) .fail(() => { - if (this.props.networkOn) { - this.props.actions.setNetworkStatus(false); - } + this.props.actions.setNetworkStatus(false); }); } render() { @@ -47,7 +43,6 @@ class QueryAutoRefresh extends React.Component { QueryAutoRefresh.propTypes = { actions: React.PropTypes.object, queriesLastUpdate: React.PropTypes.number, - networkOn: React.PropTypes.bool, }; QueryAutoRefresh.defaultProps = { // queries: null, @@ -56,7 +51,6 @@ QueryAutoRefresh.defaultProps = { function mapStateToProps(state) { return { queriesLastUpdate: state.queriesLastUpdate, - networkOn: state.networkOn, }; } diff --git a/caravel/assets/javascripts/SqlLab/components/QueryHistory.jsx b/caravel/assets/javascripts/SqlLab/components/QueryHistory.jsx index 3d66296778b..aa661a24606 100644 --- a/caravel/assets/javascripts/SqlLab/components/QueryHistory.jsx +++ b/caravel/assets/javascripts/SqlLab/components/QueryHistory.jsx @@ -1,28 +1,23 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import * as Actions from '../actions'; - import QueryTable from './QueryTable'; import { Alert } from 'react-bootstrap'; +const propTypes = { + queries: React.PropTypes.array.isRequired, + actions: React.PropTypes.object.isRequired, +}; + const QueryHistory = (props) => { - const activeQeId = props.tabHistory[props.tabHistory.length - 1]; - const queriesArray = []; - for (const id in props.queries) { - if (props.queries[id].sqlEditorId === activeQeId) { - queriesArray.push(props.queries[id]); - } - } - if (queriesArray.length > 0) { + if (props.queries.length > 0) { return ( ); } @@ -32,27 +27,6 @@ const QueryHistory = (props) => { ); }; +QueryHistory.propTypes = propTypes; -QueryHistory.defaultProps = { - queries: {}, -}; - -QueryHistory.propTypes = { - queries: React.PropTypes.object, - tabHistory: React.PropTypes.array, - actions: React.PropTypes.object, -}; - -function mapStateToProps(state) { - return { - queries: state.queries, - tabHistory: state.tabHistory, - }; -} -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators(Actions, dispatch), - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(QueryHistory); +export default QueryHistory; diff --git a/caravel/assets/javascripts/SqlLab/components/QueryLink.jsx b/caravel/assets/javascripts/SqlLab/components/QueryLink.jsx deleted file mode 100644 index da9f0b5d21b..00000000000 --- a/caravel/assets/javascripts/SqlLab/components/QueryLink.jsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; -import Link from './Link'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import * as Actions from '../actions'; -import shortid from 'shortid'; - -class QueryLink extends React.Component { - popTab() { - const qe = { - id: shortid.generate(), - title: this.props.query.title, - dbId: this.props.query.dbId, - autorun: false, - sql: this.props.query.sql, - }; - this.props.actions.addQueryEditor(qe); - } - render() { - return ( -
-
- -
- - × - -
-
-
-
- ); - } -} - -QueryLink.propTypes = { - query: React.PropTypes.object, - actions: React.PropTypes.object, -}; - -QueryLink.defaultProps = { -}; - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators(Actions, dispatch), - }; -} -export default connect(null, mapDispatchToProps)(QueryLink); - diff --git a/caravel/assets/javascripts/SqlLab/components/QuerySearch.jsx b/caravel/assets/javascripts/SqlLab/components/QuerySearch.jsx index 912366b9081..a4f963fe500 100644 --- a/caravel/assets/javascripts/SqlLab/components/QuerySearch.jsx +++ b/caravel/assets/javascripts/SqlLab/components/QuerySearch.jsx @@ -7,6 +7,10 @@ import QueryTable from './QueryTable'; import DatabaseSelect from './DatabaseSelect'; import { STATUS_OPTIONS } from '../common'; +const propTypes = { + actions: React.PropTypes.object.isRequired, +}; + class QuerySearch extends React.Component { constructor(props) { super(props); @@ -132,11 +136,11 @@ class QuerySearch extends React.Component { onUserClicked={this.onUserClicked.bind(this)} onDbClicked={this.onDbClicked.bind(this)} queries={this.state.queriesArray} + actions={this.props.actions} />
); } } - - +QuerySearch.propTypes = propTypes; export default QuerySearch; diff --git a/caravel/assets/javascripts/SqlLab/components/QueryTable.jsx b/caravel/assets/javascripts/SqlLab/components/QueryTable.jsx index 5d75a98e236..03b24788782 100644 --- a/caravel/assets/javascripts/SqlLab/components/QueryTable.jsx +++ b/caravel/assets/javascripts/SqlLab/components/QueryTable.jsx @@ -1,9 +1,5 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import * as Actions from '../actions'; - import moment from 'moment'; import { Table } from 'reactable'; import { Label, ProgressBar } from 'react-bootstrap'; @@ -67,6 +63,9 @@ class QueryTable extends React.Component { clearQueryResults(query) { this.props.actions.clearQueryResults(query); } + removeQuery(query) { + this.props.actions.removeQuery(query); + } render() { const data = this.props.queries.map((query) => { @@ -111,7 +110,7 @@ class QueryTable extends React.Component { modalTitle={'Data preview'} beforeOpen={this.openAsyncResults.bind(this, query)} onExit={this.clearQueryResults.bind(this, query)} - modalBody={} + modalBody={} /> ); } else { @@ -163,7 +162,7 @@ class QueryTable extends React.Component {
); @@ -198,13 +197,4 @@ class QueryTable extends React.Component { QueryTable.propTypes = propTypes; QueryTable.defaultProps = defaultProps; -function mapStateToProps() { - return {}; -} -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators(Actions, dispatch), - }; -} -export { QueryTable }; -export default connect(mapStateToProps, mapDispatchToProps)(QueryTable); +export default QueryTable; diff --git a/caravel/assets/javascripts/SqlLab/components/ResultSet.jsx b/caravel/assets/javascripts/SqlLab/components/ResultSet.jsx index e8c4375b91a..63ea5f7050a 100644 --- a/caravel/assets/javascripts/SqlLab/components/ResultSet.jsx +++ b/caravel/assets/javascripts/SqlLab/components/ResultSet.jsx @@ -3,10 +3,6 @@ import { Alert, Button, ButtonGroup, ProgressBar } from 'react-bootstrap'; import { Table } from 'reactable'; import shortid from 'shortid'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import * as Actions from '../actions'; - import VisualizeModal from './VisualizeModal'; import HighlightedSql from './HighlightedSql'; @@ -116,7 +112,7 @@ class ResultSet extends React.Component { if (this.props.showSql) { sql = ; } - if (['running', 'pending', 'fetching'].includes(query.state)) { + if (['running', 'pending', 'fetching'].indexOf(query.state) > -1) { let progressBar; if (query.progress > 0 && query.state === 'running') { progressBar = ( @@ -191,12 +187,4 @@ class ResultSet extends React.Component { ResultSet.propTypes = propTypes; ResultSet.defaultProps = defaultProps; -function mapStateToProps() { - return {}; -} -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators(Actions, dispatch), - }; -} -export default connect(mapStateToProps, mapDispatchToProps)(ResultSet); +export default ResultSet; diff --git a/caravel/assets/javascripts/SqlLab/components/SouthPane.jsx b/caravel/assets/javascripts/SqlLab/components/SouthPane.jsx index 1941cc93101..506aaee29a8 100644 --- a/caravel/assets/javascripts/SqlLab/components/SouthPane.jsx +++ b/caravel/assets/javascripts/SqlLab/components/SouthPane.jsx @@ -3,16 +3,21 @@ import QueryHistory from './QueryHistory'; import ResultSet from './ResultSet'; import React from 'react'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import * as Actions from '../actions'; import shortid from 'shortid'; +const propTypes = { + queries: React.PropTypes.array.isRequired, + actions: React.PropTypes.object.isRequired, +}; + const SouthPane = function (props) { - let results =
; - const latestQuery = props.latestQuery; + let latestQuery; + if (props.queries.length > 0) { + latestQuery = props.queries[props.queries.length - 1]; + } + let results; if (latestQuery) { - results = ; + results = ; } else { results = Run a query to display results here; } @@ -25,24 +30,12 @@ const SouthPane = function (props) {
- + ); }; +SouthPane.propTypes = propTypes; -SouthPane.propTypes = { - latestQuery: React.PropTypes.object, - actions: React.PropTypes.object, -}; - -SouthPane.defaultProps = { -}; - -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators(Actions, dispatch), - }; -} -export default connect(null, mapDispatchToProps)(SouthPane); +export default SouthPane; diff --git a/caravel/assets/javascripts/SqlLab/components/SqlEditor.jsx b/caravel/assets/javascripts/SqlLab/components/SqlEditor.jsx index a3abdc36ee5..2190be7161d 100644 --- a/caravel/assets/javascripts/SqlLab/components/SqlEditor.jsx +++ b/caravel/assets/javascripts/SqlLab/components/SqlEditor.jsx @@ -18,16 +18,29 @@ import 'brace/mode/sql'; import 'brace/theme/github'; import 'brace/ext/language_tools'; -import { bindActionCreators } from 'redux'; -import { connect } from 'react-redux'; -import * as Actions from '../actions'; - import shortid from 'shortid'; import SouthPane from './SouthPane'; import Timer from './Timer'; import SqlEditorLeftBar from './SqlEditorLeftBar'; +const propTypes = { + actions: React.PropTypes.object.isRequired, + database: React.PropTypes.object, + latestQuery: React.PropTypes.object, + networkOn: React.PropTypes.bool, + tables: React.PropTypes.array.isRequired, + queries: React.PropTypes.array.isRequired, + queryEditor: React.PropTypes.object.isRequired, +}; + +const defaultProps = { + networkOn: true, + database: null, + latestQuery: null, +}; + + class SqlEditor extends React.Component { constructor(props) { super(props); @@ -72,15 +85,6 @@ class SqlEditor extends React.Component { this.setState({ sql: text }); this.props.actions.queryEditorSetSql(this.props.queryEditor, text); } - addWorkspaceQuery() { - this.props.actions.addWorkspaceQuery({ - id: shortid.generate(), - sql: this.state.sql, - dbId: this.props.queryEditor.dbId, - schema: this.props.queryEditor.schema, - title: this.props.queryEditor.title, - }); - } ctasChange() {} visualize() {} ctasChanged(event) { @@ -130,7 +134,9 @@ class SqlEditor extends React.Component { {runButtons} ); - if (this.props.latestQuery && ['running', 'pending'].includes(this.props.latestQuery.state)) { + if ( + this.props.latestQuery && + ['running', 'pending'].indexOf(this.props.latestQuery.state) > -1) { runButtons = (