From 366ecefbaaf4cc31234cc981ebab7eb420efe019 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Thu, 13 Apr 2017 15:04:09 -0700 Subject: [PATCH] Bumping the JS libs to fix the build (#2616) * bumping the js libs * New linting rules * More linting * More * Done linting * npm >=4.5.0 * Bumping node * Tweaking the build * Fixing the damn build * Fixing the apps --- .pylintrc | 2 +- .travis.yml | 4 +- superset/assets/.eslintrc | 21 ++++++ superset/assets/javascripts/SqlLab/actions.js | 5 +- .../SqlLab/components/AceEditorWrapper.jsx | 16 ++--- .../javascripts/SqlLab/components/App.jsx | 14 ++-- .../SqlLab/components/ColumnElement.jsx | 70 +++++++++---------- .../SqlLab/components/DataPreviewModal.jsx | 2 +- .../SqlLab/components/HighlightedSql.jsx | 19 +++-- .../javascripts/SqlLab/components/Link.jsx | 4 +- .../SqlLab/components/QueryAutoRefresh.jsx | 1 + .../SqlLab/components/QueryHistory.jsx | 2 +- .../SqlLab/components/QuerySearch.jsx | 48 +++++++------ .../SqlLab/components/QueryTable.jsx | 2 +- .../SqlLab/components/ResultSet.jsx | 10 +-- .../SqlLab/components/SaveQuery.jsx | 6 +- .../SqlLab/components/SouthPane.jsx | 12 ++-- .../SqlLab/components/SqlEditor.jsx | 8 +-- .../SqlLab/components/SqlEditorLeftBar.jsx | 36 +++++----- .../SqlLab/components/TabbedSqlEditors.jsx | 16 +++-- .../SqlLab/components/TableElement.jsx | 7 +- .../SqlLab/components/VisualizeModal.jsx | 4 +- superset/assets/javascripts/SqlLab/index.jsx | 19 +++-- .../assets/javascripts/SqlLab/reducers.js | 10 +-- superset/assets/javascripts/common.js | 13 +++- .../javascripts/components/AlertsWrapper.jsx | 2 +- .../javascripts/components/AsyncSelect.jsx | 11 +-- .../components/CopyToClipboard.jsx | 2 +- .../javascripts/components/ModalTrigger.jsx | 2 +- superset/assets/javascripts/css-theme.js | 4 +- .../javascripts/dashboard/Dashboard.jsx | 37 +++++----- .../dashboard/components/CodeModal.jsx | 5 +- .../dashboard/components/Controls.jsx | 20 +++--- .../dashboard/components/CssEditor.jsx | 3 +- .../dashboard/components/GridLayout.jsx | 4 +- .../dashboard/components/Header.jsx | 2 +- .../components/RefreshIntervalModal.jsx | 3 +- .../dashboard/components/SaveModal.jsx | 5 +- .../dashboard/components/SliceAdder.jsx | 6 +- .../dashboard/components/SliceCell.jsx | 8 +-- .../explorev2/actions/exploreActions.js | 6 +- .../explorev2/components/ChartContainer.jsx | 56 ++++++++------- .../explorev2/components/Control.jsx | 4 +- .../components/ControlPanelsContainer.jsx | 4 +- .../components/DisplayQueryButton.jsx | 7 +- .../explorev2/components/EmbedCodeButton.jsx | 9 ++- .../components/ExploreActionButtons.jsx | 6 +- .../components/ExploreViewContainer.jsx | 8 +-- .../explorev2/components/QueryAndSaveBtns.jsx | 5 +- .../{SaveModal.js => SaveModal.jsx} | 2 +- .../components/URLShortLinkButton.jsx | 6 +- .../explorev2/components/controls/Filter.jsx | 5 +- .../components/controls/HiddenControl.jsx | 8 +-- .../components/controls/SelectControl.jsx | 6 +- .../assets/javascripts/explorev2/index.jsx | 19 +++-- .../explorev2/reducers/exploreReducer.js | 2 +- .../javascripts/explorev2/stores/controls.jsx | 46 ++++++------ .../javascripts/explorev2/stores/store.js | 4 +- .../javascripts/explorev2/stores/visTypes.js | 2 +- superset/assets/javascripts/modules/colors.js | 2 +- superset/assets/javascripts/modules/dates.js | 2 +- .../assets/javascripts/modules/superset.js | 12 ++-- superset/assets/javascripts/modules/utils.js | 4 +- .../profile/components/CreatedContent.jsx | 4 +- .../profile/components/Favorites.jsx | 4 +- .../profile/components/RecentActivity.jsx | 3 +- .../profile/components/TableLoader.jsx | 2 +- superset/assets/javascripts/profile/index.jsx | 12 ++-- superset/assets/javascripts/reduxUtils.js | 2 +- superset/assets/javascripts/welcome.js | 15 ++-- superset/assets/package.json | 52 +++++++------- .../components/AsyncSelect_spec.jsx | 9 +-- .../components/CopyToClipboard_spec.jsx | 2 +- .../components/ModalTrigger_spec.jsx | 2 +- .../javascripts/dashboard/CodeModal_spec.jsx | 4 +- .../javascripts/dashboard/CssEditor_spec.jsx | 4 +- .../dashboard/RefreshIntervalModal_spec.jsx | 4 +- .../javascripts/dashboard/SliceCell_spec.jsx | 4 +- ...ntrol_spec.js => CheckboxControl_spec.jsx} | 1 + ...pec.js => ControlPanelsContainer_spec.jsx} | 0 ...ControlRow_spec.js => ControlRow_spec.jsx} | 0 .../components/ExploreActionButtons_spec.jsx | 2 +- ...Control_spec.js => FilterControl_spec.jsx} | 2 +- .../{Filter_spec.js => Filter_spec.jsx} | 2 +- ..._spec.js => RunQueryActionButton_spec.jsx} | 2 +- .../{SaveModal_spec.js => SaveModal_spec.jsx} | 5 +- ...Control_spec.js => SelectControl_spec.jsx} | 0 .../{TextArea_spec.js => TextArea_spec.jsx} | 0 .../spec/javascripts/explorev2/utils_spec.jsx | 14 ++-- .../spec/javascripts/profile/App_spec.jsx | 5 +- .../profile/CreatedContent_spec.jsx | 6 +- .../javascripts/profile/Favorites_spec.jsx | 7 +- .../profile/RecentActivity_spec.jsx | 7 +- .../javascripts/profile/Security_spec.jsx | 5 +- .../javascripts/profile/UserInfo_spec.jsx | 5 +- .../javascripts/sqllab/AlertsWrapper_spec.jsx | 2 +- .../spec/javascripts/sqllab/App_spec.jsx | 2 +- .../javascripts/sqllab/ColumnElement_spec.jsx | 7 +- .../sqllab/CopyQueryTabUrl_spec.jsx | 5 +- .../sqllab/HighlightedSql_spec.jsx | 5 +- .../spec/javascripts/sqllab/Link_spec.jsx | 4 +- .../javascripts/sqllab/QuerySearch_spec.jsx | 5 +- .../javascripts/sqllab/QueryTable_spec.jsx | 7 +- .../javascripts/sqllab/ResultSet_spec.jsx | 7 +- .../javascripts/sqllab/SaveQuery_spec.jsx | 6 +- .../sqllab/SqlEditorLeftBar_spec.jsx | 9 +-- .../javascripts/sqllab/SqlEditor_spec.jsx | 7 +- .../sqllab/TabbedSqlEditors_spec.jsx | 5 +- .../javascripts/sqllab/TableElement_spec.jsx | 12 ++-- .../spec/javascripts/sqllab/Timer_spec.jsx | 3 +- .../sqllab/VisualizeModal_spec.jsx | 6 +- .../spec/javascripts/sqllab/fixtures.js | 2 +- .../spec/javascripts/sqllab/reducers_spec.js | 5 +- superset/assets/utils/common.js | 3 +- superset/assets/visualizations/big_number.js | 4 +- superset/assets/visualizations/cal_heatmap.js | 4 +- .../assets/visualizations/directed_force.js | 2 +- superset/assets/visualizations/filter_box.jsx | 12 ++-- superset/assets/visualizations/histogram.js | 22 +++--- superset/assets/visualizations/horizon.js | 16 ++--- superset/assets/visualizations/mapbox.jsx | 10 ++- superset/assets/visualizations/nvd3_vis.js | 14 ++-- .../visualizations/parallel_coordinates.js | 7 +- superset/assets/visualizations/pivot_table.js | 8 ++- superset/assets/visualizations/sankey.js | 10 +-- superset/assets/visualizations/sunburst.js | 8 +-- superset/assets/visualizations/table.js | 23 +++--- superset/assets/visualizations/treemap.js | 13 ++-- superset/assets/visualizations/word_cloud.js | 14 ++-- superset/assets/visualizations/world_map.js | 4 +- superset/assets/webpack.config.js | 14 ++-- superset/connectors/druid/models.py | 1 + 132 files changed, 611 insertions(+), 553 deletions(-) rename superset/assets/javascripts/explorev2/components/{SaveModal.js => SaveModal.jsx} (99%) rename superset/assets/spec/javascripts/explorev2/components/{CheckboxControl_spec.js => CheckboxControl_spec.jsx} (99%) rename superset/assets/spec/javascripts/explorev2/components/{ControlPanelsContainer_spec.js => ControlPanelsContainer_spec.jsx} (100%) rename superset/assets/spec/javascripts/explorev2/components/{ControlRow_spec.js => ControlRow_spec.jsx} (100%) rename superset/assets/spec/javascripts/explorev2/components/{FilterControl_spec.js => FilterControl_spec.jsx} (95%) rename superset/assets/spec/javascripts/explorev2/components/{Filter_spec.js => Filter_spec.jsx} (97%) rename superset/assets/spec/javascripts/explorev2/components/{RunQueryActionButton_spec.js => RunQueryActionButton_spec.jsx} (99%) rename superset/assets/spec/javascripts/explorev2/components/{SaveModal_spec.js => SaveModal_spec.jsx} (99%) rename superset/assets/spec/javascripts/explorev2/components/{SelectControl_spec.js => SelectControl_spec.jsx} (100%) rename superset/assets/spec/javascripts/explorev2/components/{TextArea_spec.js => TextArea_spec.jsx} (100%) diff --git a/.pylintrc b/.pylintrc index 4117d685bd..27b41d7b42 100644 --- a/.pylintrc +++ b/.pylintrc @@ -65,7 +65,7 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=standarderror-builtin,long-builtin,dict-view-method,intern-builtin,suppressed-message,no-absolute-import,unpacking-in-except,apply-builtin,delslice-method,indexing-exception,old-raise-syntax,print-statement,cmp-builtin,reduce-builtin,useless-suppression,coerce-method,input-builtin,cmp-method,raw_input-builtin,nonzero-method,backtick,basestring-builtin,setslice-method,reload-builtin,oct-method,map-builtin-not-iterating,execfile-builtin,old-octal-literal,zip-builtin-not-iterating,buffer-builtin,getslice-method,metaclass-assignment,xrange-builtin,long-suffix,round-builtin,range-builtin-not-iterating,next-method-called,dict-iter-method,parameter-unpacking,unicode-builtin,unichr-builtin,import-star-module-level,raising-string,filter-builtin-not-iterating,old-ne-operator,using-cmp-argument,coerce-builtin,file-builtin,old-division,hex-method +disable=standarderror-builtin,long-builtin,dict-view-method,intern-builtin,suppressed-message,no-absolute-import,unpacking-in-except,apply-builtin,delslice-method,indexing-exception,old-raise-syntax,print-statement,cmp-builtin,reduce-builtin,useless-suppression,coerce-method,input-builtin,cmp-method,raw_input-builtin,nonzero-method,backtick,basestring-builtin,setslice-method,reload-builtin,oct-method,map-builtin-not-iterating,execfile-builtin,old-octal-literal,zip-builtin-not-iterating,buffer-builtin,getslice-method,metaclass-assignment,xrange-builtin,long-suffix,round-builtin,range-builtin-not-iterating,next-method-called,dict-iter-method,parameter-unpacking,unicode-builtin,unichr-builtin,import-star-module-level,raising-string,filter-builtin-not-iterating,old-ne-operator,using-cmp-argument,coerce-builtin,file-builtin,old-division,hex-method,invalid-unary-operand-type [REPORTS] diff --git a/.travis.yml b/.travis.yml index 1ab01948ff..1c2690a7f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ cache: env: global: - TRAVIS_CACHE=$HOME/.travis_cache/ - - TRAVIS_NODE_VERSION="5.11" + - TRAVIS_NODE_VERSION="6.10.2" matrix: - TOX_ENV=javascript - TOX_ENV=pylint @@ -23,7 +23,7 @@ env: - TOX_ENV=py27-mysql - TOX_ENV=py27-sqlite before_install: - - npm install -g npm@'>=3.9.5' + - npm install -g npm@'>=4.5.0' before_script: - mysql -e 'drop database if exists superset; create database superset DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci' -u root - mysql -u root -e "CREATE USER 'mysqluser'@'localhost' IDENTIFIED BY 'mysqluserpassword';" diff --git a/superset/assets/.eslintrc b/superset/assets/.eslintrc index 955a1e12a0..c8b076604c 100644 --- a/superset/assets/.eslintrc +++ b/superset/assets/.eslintrc @@ -17,5 +17,26 @@ "func-names": 0, "react/jsx-no-bind": 0, "no-confusing-arrow": 0, + + "jsx-a11y/no-static-element-interactions": 0, + "jsx-a11y/anchor-has-content": 0, + "react/require-default-props": 0, + "no-plusplus": 0, + "no-mixed-operators": 0, + "no-continue": 0, + "no-bitwise": 0, + "no-undef": 0, + "no-multi-assign": 0, + "react/no-array-index-key": 0, + "no-restricted-properties": 0, + "no-prototype-builtins": 0, + "jsx-a11y/href-no-hash": 0, + "react/forbid-prop-types": 0, + "class-methods-use-this": 0, + "import/no-named-as-default": 0, + "import/prefer-default-export": 0, + "react/no-unescaped-entities": 0, + "react/no-unused-prop-types": 0, + "react/no-string-refs": 0, } } diff --git a/superset/assets/javascripts/SqlLab/actions.js b/superset/assets/javascripts/SqlLab/actions.js index c2612b419c..2e60a4c8ba 100644 --- a/superset/assets/javascripts/SqlLab/actions.js +++ b/superset/assets/javascripts/SqlLab/actions.js @@ -1,6 +1,7 @@ /* global notify */ import shortid from 'shortid'; import { now } from '../modules/dates'; + const $ = require('jquery'); export const RESET_STATE = 'RESET_STATE'; @@ -262,7 +263,7 @@ export function addTable(query, tableName, schemaName) { queryEditorId: query.id, schema: schemaName, expanded: true, - }), dataPreviewQuery) + }), dataPreviewQuery), ); // Run query to get preview data for table dispatch(runQuery(dataPreviewQuery)); @@ -272,7 +273,7 @@ export function addTable(query, tableName, schemaName) { addAlert({ msg: 'Error occurred while fetching metadata', bsStyle: 'danger', - }) + }), ); }); diff --git a/superset/assets/javascripts/SqlLab/components/AceEditorWrapper.jsx b/superset/assets/javascripts/SqlLab/components/AceEditorWrapper.jsx index 2ded35c8ed..f9d9d7871d 100644 --- a/superset/assets/javascripts/SqlLab/components/AceEditorWrapper.jsx +++ b/superset/assets/javascripts/SqlLab/components/AceEditorWrapper.jsx @@ -59,15 +59,9 @@ class AceEditorWrapper extends React.PureComponent { this.setState({ sql: nextProps.sql }); } } - textChange(text) { - this.setState({ sql: text }); - } onBlur() { this.props.onBlur(this.state.sql); } - getCompletions(aceEditor, session, pos, prefix, callback) { - callback(null, this.state.words); - } onEditorLoad(editor) { editor.commands.addCommand({ name: 'runQuery', @@ -87,10 +81,10 @@ class AceEditorWrapper extends React.PureComponent { let words = []; const columns = {}; const tables = props.tables || []; - tables.forEach(t => { + tables.forEach((t) => { words.push({ name: t.name, value: t.name, score: 55, meta: 'table' }); const cols = t.columns || []; - cols.forEach(col => { + cols.forEach((col) => { columns[col.name] = null; // using an object as a unique set }); }); @@ -107,6 +101,12 @@ class AceEditorWrapper extends React.PureComponent { } }); } + getCompletions(aceEditor, session, pos, prefix, callback) { + callback(null, this.state.words); + } + textChange(text) { + this.setState({ sql: text }); + } render() { return ( 0) { - name = {col.name}; - icons = col.keys.map((key, i) => ( - - - {tooltipTitleMap[key.type]} -
-
-                  {JSON.stringify(key, null, '  ')}
-                
- - } - > - -
-
- )); - } - return ( -
-
- {name}{icons} -
-
- {col.type} -
-
); +export default function ColumnElement(props) { + const col = props.column; + let name = col.name; + let icons; + if (col.keys && col.keys.length > 0) { + name = {col.name}; + icons = col.keys.map((key, i) => ( + + + {tooltipTitleMap[key.type]} +
+
+                {JSON.stringify(key, null, '  ')}
+              
+ + } + > + +
+
+ )); } + return ( +
+
+ {name}{icons} +
+
+ {col.type} +
+
); } ColumnElement.propTypes = propTypes; - -export default ColumnElement; diff --git a/superset/assets/javascripts/SqlLab/components/DataPreviewModal.jsx b/superset/assets/javascripts/SqlLab/components/DataPreviewModal.jsx index cbea27fdf2..79e4b5cc16 100644 --- a/superset/assets/javascripts/SqlLab/components/DataPreviewModal.jsx +++ b/superset/assets/javascripts/SqlLab/components/DataPreviewModal.jsx @@ -1,9 +1,9 @@ -import * as Actions from '../actions'; import React from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { Modal } from 'react-bootstrap'; +import * as Actions from '../actions'; import ResultSet from './ResultSet'; const propTypes = { diff --git a/superset/assets/javascripts/SqlLab/components/HighlightedSql.jsx b/superset/assets/javascripts/SqlLab/components/HighlightedSql.jsx index e649125fac..7636cdae45 100644 --- a/superset/assets/javascripts/SqlLab/components/HighlightedSql.jsx +++ b/superset/assets/javascripts/SqlLab/components/HighlightedSql.jsx @@ -25,38 +25,35 @@ class HighlightedSql extends React.Component { }; } shrinkSql() { - const props = this.props; - const sql = props.sql || ''; + const sql = this.props.sql || ''; let lines = sql.split('\n'); - if (lines.length >= props.maxLines) { - lines = lines.slice(0, props.maxLines); + if (lines.length >= this.props.maxLines) { + lines = lines.slice(0, this.props.maxLines); lines.push('{...}'); } return lines.map((line) => { - if (line.length > props.maxWidth) { - return line.slice(0, props.maxWidth) + '{...}'; + if (line.length > this.props.maxWidth) { + return line.slice(0, this.props.maxWidth) + '{...}'; } return line; }) .join('\n'); } triggerNode() { - const props = this.props; - let shownSql = props.shrink ? this.shrinkSql(props.sql) : props.sql; + const shownSql = this.props.shrink ? this.shrinkSql(this.props.sql) : this.props.sql; return ( {shownSql} ); } generateModal() { - const props = this.props; let rawSql; - if (props.rawSql && props.rawSql !== this.props.sql) { + if (this.props.rawSql && this.props.rawSql !== this.props.sql) { rawSql = (

Raw SQL

- {props.rawSql} + {this.props.rawSql}
); diff --git a/superset/assets/javascripts/SqlLab/components/Link.jsx b/superset/assets/javascripts/SqlLab/components/Link.jsx index b4cd16fd32..af53f97aa2 100644 --- a/superset/assets/javascripts/SqlLab/components/Link.jsx +++ b/superset/assets/javascripts/SqlLab/components/Link.jsx @@ -22,7 +22,7 @@ const defaultProps = { class Link extends React.PureComponent { render() { - let tooltip = ( + const tooltip = ( {this.props.tooltip} @@ -34,7 +34,7 @@ class Link extends React.PureComponent { style={this.props.style} className={'Link ' + this.props.className} > - {this.props.children} + {this.props.children} ); if (this.props.tooltip) { diff --git a/superset/assets/javascripts/SqlLab/components/QueryAutoRefresh.jsx b/superset/assets/javascripts/SqlLab/components/QueryAutoRefresh.jsx index cd7746b92e..e96fcba6ef 100644 --- a/superset/assets/javascripts/SqlLab/components/QueryAutoRefresh.jsx +++ b/superset/assets/javascripts/SqlLab/components/QueryAutoRefresh.jsx @@ -4,6 +4,7 @@ import { connect } from 'react-redux'; import * as Actions from '../actions'; const $ = require('jquery'); + const QUERY_UPDATE_FREQ = 2000; const QUERY_UPDATE_BUFFER_MS = 5000; diff --git a/superset/assets/javascripts/SqlLab/components/QueryHistory.jsx b/superset/assets/javascripts/SqlLab/components/QueryHistory.jsx index aa661a2460..5356206ae3 100644 --- a/superset/assets/javascripts/SqlLab/components/QueryHistory.jsx +++ b/superset/assets/javascripts/SqlLab/components/QueryHistory.jsx @@ -1,7 +1,7 @@ import React from 'react'; +import { Alert } from 'react-bootstrap'; import QueryTable from './QueryTable'; -import { Alert } from 'react-bootstrap'; const propTypes = { queries: React.PropTypes.array.isRequired, diff --git a/superset/assets/javascripts/SqlLab/components/QuerySearch.jsx b/superset/assets/javascripts/SqlLab/components/QuerySearch.jsx index bc68caff08..5a32adc984 100644 --- a/superset/assets/javascripts/SqlLab/components/QuerySearch.jsx +++ b/superset/assets/javascripts/SqlLab/components/QuerySearch.jsx @@ -1,4 +1,3 @@ -const $ = window.$ = require('jquery'); import React from 'react'; import { Button } from 'react-bootstrap'; import Select from 'react-select'; @@ -8,8 +7,11 @@ import { now, epochTimeXHoursAgo, import { STATUS_OPTIONS, TIME_OPTIONS } from '../constants'; import AsyncSelect from '../../components/AsyncSelect'; +const $ = window.$ = require('jquery'); + const propTypes = { actions: React.PropTypes.object.isRequired, + height: React.PropTypes.integer, }; class QuerySearch extends React.PureComponent { @@ -75,7 +77,7 @@ class QuerySearch extends React.PureComponent { } insertParams(baseUrl, params) { const validParams = params.filter( - function (p) { return p !== ''; } + function (p) { return p !== ''; }, ); return baseUrl + '?' + validParams.join('&'); } @@ -94,7 +96,7 @@ class QuerySearch extends React.PureComponent { return options; } dbMutator(data) { - const options = data.result.map((db) => ({ value: db.id, label: db.database_name })); + const options = data.result.map(db => ({ value: db.id, label: db.database_name })); this.props.actions.setDatabases(data.result); if (data.result.length === 0) { this.props.actions.addAlert({ @@ -154,8 +156,8 @@ class QuerySearch extends React.PureComponent { ({ value: t, label: t }))} + options={TIME_OPTIONS.map(t => ({ value: t, label: t }))} value={this.state.to} autosize={false} onChange={this.changeTo.bind(this)} @@ -175,7 +177,7 @@ class QuerySearch extends React.PureComponent { , - appContainer + appContainer, ); diff --git a/superset/assets/javascripts/SqlLab/reducers.js b/superset/assets/javascripts/SqlLab/reducers.js index 7204a1cfa4..121809b6d6 100644 --- a/superset/assets/javascripts/SqlLab/reducers.js +++ b/superset/assets/javascripts/SqlLab/reducers.js @@ -2,7 +2,7 @@ import shortid from 'shortid'; import * as actions from './actions'; import { now } from '../modules/dates'; import { addToObject, alterInObject, alterInArr, removeFromArr, getFromArr, addToArr } - from '../reduxUtils.js'; + from '../reduxUtils'; export function getInitialState(defaultDbId) { const defaultQueryEditor = { @@ -36,7 +36,7 @@ export const sqlLabReducer = function (state, action) { return addToArr(newState, 'queryEditors', action.queryEditor); }, [actions.CLONE_QUERY_TO_NEW_TAB]() { - const progenitor = state.queryEditors.find((qe) => + const progenitor = state.queryEditors.find(qe => qe.id === state.tabHistory[state.tabHistory.length - 1]); const qe = { id: shortid.generate(), @@ -52,7 +52,7 @@ export const sqlLabReducer = function (state, action) { [actions.REMOVE_QUERY_EDITOR]() { let newState = removeFromArr(state, 'queryEditors', action.queryEditor); // List of remaining queryEditor ids - const qeIds = newState.queryEditors.map((qe) => qe.id); + const qeIds = newState.queryEditors.map(qe => qe.id); const queries = {}; Object.keys(state.queries).forEach((k) => { const query = state.queries[k]; @@ -61,7 +61,7 @@ export const sqlLabReducer = function (state, action) { } }); let tabHistory = state.tabHistory.slice(); - tabHistory = tabHistory.filter((id) => qeIds.indexOf(id) > -1); + tabHistory = tabHistory.filter(id => qeIds.indexOf(id) > -1); newState = Object.assign({}, newState, { tabHistory, queries }); return newState; }, @@ -187,7 +187,7 @@ export const sqlLabReducer = function (state, action) { return alterInObject(state, 'queries', action.query, alts); }, [actions.SET_ACTIVE_QUERY_EDITOR]() { - const qeIds = state.queryEditors.map((qe) => qe.id); + const qeIds = state.queryEditors.map(qe => qe.id); if (qeIds.indexOf(action.queryEditor.id) > -1) { const tabHistory = state.tabHistory.slice(); tabHistory.push(action.queryEditor.id); diff --git a/superset/assets/javascripts/common.js b/superset/assets/javascripts/common.js index fd35e6a114..8ecfbe5822 100644 --- a/superset/assets/javascripts/common.js +++ b/superset/assets/javascripts/common.js @@ -1,5 +1,8 @@ -const $ = require('jquery'); +/* eslint-disable global-require */ +import $ from 'jquery'; + const utils = require('./modules/utils'); + $(document).ready(function () { $(':checkbox[data-checkbox-api-prefix]').change(function () { const $this = $(this); @@ -8,3 +11,11 @@ $(document).ready(function () { utils.toggleCheckbox(prefix, '#' + id); }); }); + +export function appSetup() { + // A set of hacks to allow apps to run within a FAB template + // this allows for the server side generated menus to function + window.$ = $; + window.jQuery = $; + require('bootstrap'); +} diff --git a/superset/assets/javascripts/components/AlertsWrapper.jsx b/superset/assets/javascripts/components/AlertsWrapper.jsx index 529c2a1024..bb3c2d6dc8 100644 --- a/superset/assets/javascripts/components/AlertsWrapper.jsx +++ b/superset/assets/javascripts/components/AlertsWrapper.jsx @@ -5,7 +5,7 @@ export default class AlertsWrapper extends React.PureComponent { render() { return ( { + ref={(ref) => { global.notify = ref; }} offset={14} diff --git a/superset/assets/javascripts/components/AsyncSelect.jsx b/superset/assets/javascripts/components/AsyncSelect.jsx index fbf988c48d..3b7e6f0632 100644 --- a/superset/assets/javascripts/components/AsyncSelect.jsx +++ b/superset/assets/javascripts/components/AsyncSelect.jsx @@ -1,7 +1,8 @@ -const $ = window.$ = require('jquery'); import React from 'react'; import Select from 'react-select'; +const $ = window.$ = require('jquery'); + const propTypes = { dataEndpoint: React.PropTypes.string.isRequired, onChange: React.PropTypes.func.isRequired, @@ -13,7 +14,7 @@ const propTypes = { const defaultProps = { placeholder: 'Select ...', - valueRenderer: (o) => (
{o.label}
), + valueRenderer: o => (
{o.label}
), }; class AsyncSelect extends React.PureComponent { @@ -27,6 +28,9 @@ class AsyncSelect extends React.PureComponent { componentDidMount() { this.fetchOptions(); } + onChange(opt) { + this.props.onChange(opt); + } fetchOptions() { this.setState({ isLoading: true }); const mutator = this.props.mutator; @@ -34,9 +38,6 @@ class AsyncSelect extends React.PureComponent { this.setState({ options: mutator ? mutator(data) : data, isLoading: false }); }); } - onChange(opt) { - this.props.onChange(opt); - } render() { return (
diff --git a/superset/assets/javascripts/components/CopyToClipboard.jsx b/superset/assets/javascripts/components/CopyToClipboard.jsx index 92de59ceeb..07330e5f70 100644 --- a/superset/assets/javascripts/components/CopyToClipboard.jsx +++ b/superset/assets/javascripts/components/CopyToClipboard.jsx @@ -97,7 +97,7 @@ export default class CopyToClipboard extends React.Component { onClick={this.onClick.bind(this)} onMouseOut={this.onMouseOut} > - {this.props.copyNode} + {this.props.copyNode} ); diff --git a/superset/assets/javascripts/components/ModalTrigger.jsx b/superset/assets/javascripts/components/ModalTrigger.jsx index 58734b0a29..00fbf0492b 100644 --- a/superset/assets/javascripts/components/ModalTrigger.jsx +++ b/superset/assets/javascripts/components/ModalTrigger.jsx @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; import { Modal } from 'react-bootstrap'; -import Button from './Button'; import cx from 'classnames'; +import Button from './Button'; const propTypes = { triggerNode: PropTypes.node.isRequired, diff --git a/superset/assets/javascripts/css-theme.js b/superset/assets/javascripts/css-theme.js index c03b05acf8..8fab234f65 100644 --- a/superset/assets/javascripts/css-theme.js +++ b/superset/assets/javascripts/css-theme.js @@ -1,2 +1,2 @@ -require('../stylesheets/less/index.less'); -require('../stylesheets/react-select/select.less'); +import '../stylesheets/less/index.less'; +import '../stylesheets/react-select/select.less'; diff --git a/superset/assets/javascripts/dashboard/Dashboard.jsx b/superset/assets/javascripts/dashboard/Dashboard.jsx index c3da6df30d..1fbd72c21d 100644 --- a/superset/assets/javascripts/dashboard/Dashboard.jsx +++ b/superset/assets/javascripts/dashboard/Dashboard.jsx @@ -1,18 +1,19 @@ -const $ = window.$ = require('jquery'); -const jQuery = window.jQuery = require('jquery'); // eslint-disable-line -const px = require('../modules/superset'); -const d3 = require('d3'); -const urlLib = require('url'); -const utils = require('../modules/utils'); -const { Alert } = require('react-bootstrap'); - import React from 'react'; import { render } from 'react-dom'; +import d3 from 'd3'; +import { Alert } from 'react-bootstrap'; + import GridLayout from './components/GridLayout'; import Header from './components/Header'; +import { appSetup } from '../common'; -require('bootstrap'); -require('../../stylesheets/dashboard.css'); +import '../../stylesheets/dashboard.css'; + +const px = require('../modules/superset'); +const urlLib = require('url'); +const utils = require('../modules/utils'); + +appSetup(); export function getInitialState(boostrapData) { const dashboard = Object.assign({}, utils.controllerInterface, boostrapData.dashboard_data); @@ -20,7 +21,7 @@ export function getInitialState(boostrapData) { dashboard.posDict = {}; if (dashboard.position_json) { - dashboard.position_json.forEach(position => { + dashboard.position_json.forEach((position) => { dashboard.posDict[position.slice_id] = position; }); } @@ -52,19 +53,19 @@ function renderAlert() { button on the top right to save your changes.
, - document.getElementById('alert-container') + document.getElementById('alert-container'), ); } function initDashboardView(dashboard) { render(
, - document.getElementById('dashboard-header') + document.getElementById('dashboard-header'), ); // eslint-disable-next-line no-param-reassign dashboard.reactGridLayout = render( , - document.getElementById('grid-container') + document.getElementById('grid-container'), ); // Displaying widget controls on hover @@ -74,7 +75,7 @@ function initDashboardView(dashboard) { }, function () { $(this).find('.chart-controls').fadeOut(300); - } + }, ); $('div.grid-container').css('visibility', 'visible'); @@ -100,7 +101,7 @@ export function dashboardContainer(dashboard, datasources) { filters: {}, init() { this.sliceObjects = []; - dashboard.slices.forEach(data => { + dashboard.slices.forEach((data) => { if (data.error) { const html = `
${data.error}
`; $(`#slice_${data.slice_id}`).find('.token').html(html); @@ -235,7 +236,7 @@ export function dashboardContainer(dashboard, datasources) { const dash = this; const maxRandomDelay = Math.max(interval * 0.2, 5000); const refreshAll = () => { - dash.sliceObjects.forEach(slice => { + dash.sliceObjects.forEach((slice) => { const force = !dash.firstLoad; setTimeout(() => { slice.render(force); @@ -258,7 +259,7 @@ export function dashboardContainer(dashboard, datasources) { }, refreshExcept(sliceId) { const immune = this.metadata.filter_immune_slices || []; - this.sliceObjects.forEach(slice => { + this.sliceObjects.forEach((slice) => { if (slice.data.slice_id !== sliceId && immune.indexOf(slice.data.slice_id) === -1) { slice.render(); const sliceSeletor = $(`#${slice.data.slice_id}-cell`); diff --git a/superset/assets/javascripts/dashboard/components/CodeModal.jsx b/superset/assets/javascripts/dashboard/components/CodeModal.jsx index 3346dabf5e..322fb00ff2 100644 --- a/superset/assets/javascripts/dashboard/components/CodeModal.jsx +++ b/superset/assets/javascripts/dashboard/components/CodeModal.jsx @@ -9,14 +9,13 @@ const propTypes = { }; const defaultProps = { + codeCallback: () => {}, }; export default class CodeModal extends React.PureComponent { constructor(props) { super(props); - this.state = { - refreshFrequency: props.initialRefreshFrequency, - }; + this.state = { code: props.code }; } beforeOpen() { let code = this.props.code; diff --git a/superset/assets/javascripts/dashboard/components/Controls.jsx b/superset/assets/javascripts/dashboard/components/Controls.jsx index 463a75ffb3..4248a6055f 100644 --- a/superset/assets/javascripts/dashboard/components/Controls.jsx +++ b/superset/assets/javascripts/dashboard/components/Controls.jsx @@ -1,8 +1,6 @@ -const $ = window.$ = require('jquery'); - import React from 'react'; - import { ButtonGroup } from 'react-bootstrap'; + import Button from '../../components/Button'; import CssEditor from './CssEditor'; import RefreshIntervalModal from './RefreshIntervalModal'; @@ -10,6 +8,8 @@ import SaveModal from './SaveModal'; import CodeModal from './CodeModal'; import SliceAdder from './SliceAdder'; +const $ = window.$ = require('jquery'); + const propTypes = { dashboard: React.PropTypes.object.isRequired, }; @@ -22,14 +22,9 @@ class Controls extends React.PureComponent { cssTemplates: [], }; } - refresh() { - this.props.dashboard.sliceObjects.forEach((slice) => { - slice.render(true); - }); - } componentWillMount() { $.get('/csstemplateasyncmodelview/api/read', (data) => { - const cssTemplates = data.result.map((row) => ({ + const cssTemplates = data.result.map(row => ({ value: row.template_name, css: row.css, label: row.template_name, @@ -37,6 +32,11 @@ class Controls extends React.PureComponent { this.setState({ cssTemplates }); }); } + refresh() { + this.props.dashboard.sliceObjects.forEach((slice) => { + slice.render(true); + }); + } changeCss(css) { this.setState({ css }); this.props.dashboard.onChange(); @@ -99,7 +99,7 @@ class Controls extends React.PureComponent { ); diff --git a/superset/assets/javascripts/dashboard/components/CssEditor.jsx b/superset/assets/javascripts/dashboard/components/CssEditor.jsx index 5009d1b573..4aab39efce 100644 --- a/superset/assets/javascripts/dashboard/components/CssEditor.jsx +++ b/superset/assets/javascripts/dashboard/components/CssEditor.jsx @@ -1,12 +1,11 @@ import React from 'react'; - -import ModalTrigger from '../../components/ModalTrigger'; import Select from 'react-select'; import AceEditor from 'react-ace'; import 'brace/mode/css'; import 'brace/theme/github'; +import ModalTrigger from '../../components/ModalTrigger'; const propTypes = { initialCss: React.PropTypes.string, diff --git a/superset/assets/javascripts/dashboard/components/GridLayout.jsx b/superset/assets/javascripts/dashboard/components/GridLayout.jsx index 0d3a0d919d..4dd56559f7 100644 --- a/superset/assets/javascripts/dashboard/components/GridLayout.jsx +++ b/superset/assets/javascripts/dashboard/components/GridLayout.jsx @@ -1,10 +1,12 @@ -import $ from 'jquery'; import React, { PropTypes } from 'react'; import { Responsive, WidthProvider } from 'react-grid-layout'; +import $ from 'jquery'; + import SliceCell from './SliceCell'; require('react-grid-layout/css/styles.css'); require('react-resizable/css/styles.css'); + const ResponsiveReactGridLayout = WidthProvider(Responsive); const propTypes = { diff --git a/superset/assets/javascripts/dashboard/components/Header.jsx b/superset/assets/javascripts/dashboard/components/Header.jsx index 3e8e407f86..f7730fce4f 100644 --- a/superset/assets/javascripts/dashboard/components/Header.jsx +++ b/superset/assets/javascripts/dashboard/components/Header.jsx @@ -25,7 +25,7 @@ class Header extends React.PureComponent {
- {!this.props.dashboard.standalone_mode && + {!this.props.dashboard.standalone_mode && }
diff --git a/superset/assets/javascripts/dashboard/components/RefreshIntervalModal.jsx b/superset/assets/javascripts/dashboard/components/RefreshIntervalModal.jsx index 719302d585..3da95e5ded 100644 --- a/superset/assets/javascripts/dashboard/components/RefreshIntervalModal.jsx +++ b/superset/assets/javascripts/dashboard/components/RefreshIntervalModal.jsx @@ -1,7 +1,6 @@ import React from 'react'; - -import ModalTrigger from '../../components/ModalTrigger'; import Select from 'react-select'; +import ModalTrigger from '../../components/ModalTrigger'; const propTypes = { triggerNode: React.PropTypes.node.isRequired, diff --git a/superset/assets/javascripts/dashboard/components/SaveModal.jsx b/superset/assets/javascripts/dashboard/components/SaveModal.jsx index a0fb30bb1a..ade62bf6a4 100644 --- a/superset/assets/javascripts/dashboard/components/SaveModal.jsx +++ b/superset/assets/javascripts/dashboard/components/SaveModal.jsx @@ -1,11 +1,10 @@ -const $ = window.$ = require('jquery'); - import React from 'react'; import { Button, FormControl, FormGroup, Radio } from 'react-bootstrap'; import { getAjaxErrorMsg, showModal } from '../../modules/utils'; - import ModalTrigger from '../../components/ModalTrigger'; +const $ = window.$ = require('jquery'); + const propTypes = { css: React.PropTypes.string, dashboard: React.PropTypes.object.isRequired, diff --git a/superset/assets/javascripts/dashboard/components/SliceAdder.jsx b/superset/assets/javascripts/dashboard/components/SliceAdder.jsx index 6995964276..34f20a1bca 100644 --- a/superset/assets/javascripts/dashboard/components/SliceAdder.jsx +++ b/superset/assets/javascripts/dashboard/components/SliceAdder.jsx @@ -1,7 +1,9 @@ import $ from 'jquery'; import React, { PropTypes } from 'react'; import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table'; + import ModalTrigger from '../../components/ModalTrigger'; + require('react-bootstrap-table/css/react-bootstrap-table.css'); const propTypes = { @@ -39,7 +41,7 @@ class SliceAdder extends React.Component { this.slicesRequest = $.ajax({ url: uri, type: 'GET', - success: response => { + success: (response) => { // Prepare slice data for table const slices = response.result.map(slice => ({ id: slice.id, @@ -54,7 +56,7 @@ class SliceAdder extends React.Component { slicesLoaded: true, }); }, - error: error => { + error: (error) => { this.errored = true; this.setState({ errorMsg: this.props.dashboard.getAjaxErrorMsg(error), diff --git a/superset/assets/javascripts/dashboard/components/SliceCell.jsx b/superset/assets/javascripts/dashboard/components/SliceCell.jsx index 36a82ce219..5d8cb04d24 100644 --- a/superset/assets/javascripts/dashboard/components/SliceCell.jsx +++ b/superset/assets/javascripts/dashboard/components/SliceCell.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/no-danger */ import React, { PropTypes } from 'react'; const propTypes = { @@ -62,9 +63,7 @@ function SliceCell({ expandedSlices, removeSlice, slice }) { expandedSlices[String(slice.slice_id)] ? {} : { display: 'none' } } dangerouslySetInnerHTML={{ __html: slice.description_markeddown }} - > - - + />
@@ -76,8 +75,7 @@ function SliceCell({ expandedSlices, removeSlice, slice }) {
-
+ />
diff --git a/superset/assets/javascripts/explorev2/actions/exploreActions.js b/superset/assets/javascripts/explorev2/actions/exploreActions.js index ad3d53160e..2594a91598 100644 --- a/superset/assets/javascripts/explorev2/actions/exploreActions.js +++ b/superset/assets/javascripts/explorev2/actions/exploreActions.js @@ -1,8 +1,10 @@ /* eslint camelcase: 0 */ -const $ = window.$ = require('jquery'); -const FAVESTAR_BASE_URL = '/superset/favstar/slice'; import { getExploreUrl } from '../exploreUtils'; +const $ = window.$ = require('jquery'); + +const FAVESTAR_BASE_URL = '/superset/favstar/slice'; + export const SET_DATASOURCE_TYPE = 'SET_DATASOURCE_TYPE'; export function setDatasourceType(datasourceType) { return { type: SET_DATASOURCE_TYPE, datasourceType }; diff --git a/superset/assets/javascripts/explorev2/components/ChartContainer.jsx b/superset/assets/javascripts/explorev2/components/ChartContainer.jsx index 75cb64c99e..5f10ef4f6b 100644 --- a/superset/assets/javascripts/explorev2/components/ChartContainer.jsx +++ b/superset/assets/javascripts/explorev2/components/ChartContainer.jsx @@ -34,6 +34,9 @@ const propTypes = { viz_type: PropTypes.string.isRequired, formData: PropTypes.object, latestQueryFormData: PropTypes.object, + queryResponse: PropTypes.object, + triggerRender: PropTypes.bool, + standalone: PropTypes.bool, }; class ChartContainer extends React.PureComponent { @@ -45,17 +48,6 @@ class ChartContainer extends React.PureComponent { }; } - renderViz() { - this.props.actions.renderTriggered(); - const mockSlice = this.getMockedSliceObject(); - this.setState({ mockSlice }); - try { - visMap[this.props.viz_type](mockSlice, this.props.queryResponse); - } catch (e) { - this.props.actions.chartRenderingFailed(e); - } - } - componentDidUpdate(prevProps) { if ( this.props.queryResponse && @@ -95,8 +87,8 @@ class ChartContainer extends React.PureComponent { }, height: getHeight, show: () => { }, - get: (n) => ($(this.state.selector).get(n)), - find: (classname) => ($(this.state.selector).find(classname)), + get: n => ($(this.state.selector).get(n)), + find: classname => ($(this.state.selector).find(classname)), }, width: () => this.chartContainerRef.getBoundingClientRect().width, @@ -149,6 +141,10 @@ class ChartContainer extends React.PureComponent { this.props.actions.removeChartAlert(); } + runQuery() { + this.props.actions.runQuery(this.props.formData, true); + } + renderChartTitle() { let title; if (this.props.slice) { @@ -159,6 +155,17 @@ class ChartContainer extends React.PureComponent { return title; } + renderViz() { + this.props.actions.renderTriggered(); + const mockSlice = this.getMockedSliceObject(); + this.setState({ mockSlice }); + try { + visMap[this.props.viz_type](mockSlice, this.props.queryResponse); + } catch (e) { + this.props.actions.chartRenderingFailed(e); + } + } + renderAlert() { const msg = (
@@ -204,7 +211,7 @@ class ChartContainer extends React.PureComponent { }
{ this.chartContainerRef = ref; }} + ref={(ref) => { this.chartContainerRef = ref; }} className={this.props.viz_type} style={{ opacity: loading ? '0.25' : '1', @@ -213,9 +220,6 @@ class ChartContainer extends React.PureComponent {
); } - runQuery() { - this.props.actions.runQuery(this.props.formData, true); - } render() { if (this.props.standalone) { @@ -262,17 +266,17 @@ class ChartContainer extends React.PureComponent { {this.props.chartStatus === 'success' && this.props.queryResponse && this.props.queryResponse.is_cached && - - } 0) { - validators.forEach(f => { + validators.forEach((f) => { const v = f(value); if (v) { validationErrors.push(v); diff --git a/superset/assets/javascripts/explorev2/components/ControlPanelsContainer.jsx b/superset/assets/javascripts/explorev2/components/ControlPanelsContainer.jsx index d5fa7ea0d0..1d07e19d9a 100644 --- a/superset/assets/javascripts/explorev2/components/ControlPanelsContainer.jsx +++ b/superset/assets/javascripts/explorev2/components/ControlPanelsContainer.jsx @@ -1,7 +1,6 @@ /* eslint camelcase: 0 */ import React, { PropTypes } from 'react'; import { bindActionCreators } from 'redux'; -import * as actions from '../actions/exploreActions'; import { connect } from 'react-redux'; import { Panel, Alert } from 'react-bootstrap'; import { sectionsToRender } from '../stores/visTypes'; @@ -9,6 +8,7 @@ import ControlPanelSection from './ControlPanelSection'; import ControlRow from './ControlRow'; import Control from './Control'; import controls from '../stores/controls'; +import * as actions from '../actions/exploreActions'; const propTypes = { actions: PropTypes.object.isRequired, @@ -54,7 +54,7 @@ class ControlPanelsContainer extends React.Component { /> } - {this.sectionsToRender().map((section) => ( + {this.sectionsToRender().map(section => ( { const modalBody = data.language ? - + ( {data.query} - + ) :
{data.query}
; this.setState({ modalBody }); diff --git a/superset/assets/javascripts/explorev2/components/EmbedCodeButton.jsx b/superset/assets/javascripts/explorev2/components/EmbedCodeButton.jsx index 3efe2bba29..4225043338 100644 --- a/superset/assets/javascripts/explorev2/components/EmbedCodeButton.jsx +++ b/superset/assets/javascripts/explorev2/components/EmbedCodeButton.jsx @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react'; -import CopyToClipboard from './../../components/CopyToClipboard'; import { Popover, OverlayTrigger } from 'react-bootstrap'; +import CopyToClipboard from './../../components/CopyToClipboard'; const propTypes = { slice: PropTypes.object.isRequired, @@ -56,14 +56,13 @@ export default class EmbedCodeButton extends React.Component { rows="4" readOnly className="form-control input-sm" - > - + />
} + copyNode={} />
@@ -112,7 +111,7 @@ export default class EmbedCodeButton extends React.Component { overlay={this.renderPopover()} > -   +   ); diff --git a/superset/assets/javascripts/explorev2/components/ExploreActionButtons.jsx b/superset/assets/javascripts/explorev2/components/ExploreActionButtons.jsx index bb30c9821b..604e90af36 100644 --- a/superset/assets/javascripts/explorev2/components/ExploreActionButtons.jsx +++ b/superset/assets/javascripts/explorev2/components/ExploreActionButtons.jsx @@ -27,8 +27,9 @@ export default function ExploreActionButtons({ canDownload, slice, query, queryE className="btn btn-default btn-sm" title="Export to .json" target="_blank" + rel="noopener noreferrer" > - .json + .json - .csv + .csv {`[ ${control.label} ] `} {control.validationErrors.join('. ')} - + , ); } } @@ -143,7 +143,7 @@ class ExploreViewContainer extends React.Component { overflow: 'hidden', }} > - {this.state.showModal && + {this.state.showModal && - Save as + Save as {errorMessage && diff --git a/superset/assets/javascripts/explorev2/components/SaveModal.js b/superset/assets/javascripts/explorev2/components/SaveModal.jsx similarity index 99% rename from superset/assets/javascripts/explorev2/components/SaveModal.js rename to superset/assets/javascripts/explorev2/components/SaveModal.jsx index 6be4650549..a98ceaadae 100644 --- a/superset/assets/javascripts/explorev2/components/SaveModal.js +++ b/superset/assets/javascripts/explorev2/components/SaveModal.jsx @@ -146,7 +146,7 @@ class SaveModal extends React.Component { checked={this.state.action === 'overwrite'} onChange={this.changeAction.bind(this, 'overwrite')} > - {`Overwrite slice ${this.props.slice.slice_name}`} + {`Overwrite slice ${this.props.slice.slice_name}`} } diff --git a/superset/assets/javascripts/explorev2/components/URLShortLinkButton.jsx b/superset/assets/javascripts/explorev2/components/URLShortLinkButton.jsx index 02d513118f..1fa572e5e3 100644 --- a/superset/assets/javascripts/explorev2/components/URLShortLinkButton.jsx +++ b/superset/assets/javascripts/explorev2/components/URLShortLinkButton.jsx @@ -32,11 +32,11 @@ export default class URLShortLinkButton extends React.Component { } + copyNode={} />    - + ); @@ -52,7 +52,7 @@ export default class URLShortLinkButton extends React.Component { overlay={this.renderPopover()} > -   +   ); diff --git a/superset/assets/javascripts/explorev2/components/controls/Filter.jsx b/superset/assets/javascripts/explorev2/components/controls/Filter.jsx index fec66c4d43..a7dc1f0841 100644 --- a/superset/assets/javascripts/explorev2/components/controls/Filter.jsx +++ b/superset/assets/javascripts/explorev2/components/controls/Filter.jsx @@ -1,9 +1,10 @@ -const $ = window.$ = require('jquery'); import React, { PropTypes } from 'react'; import Select from 'react-select'; import { Button, Row, Col } from 'react-bootstrap'; import SelectControl from './SelectControl'; +const $ = window.$ = require('jquery'); + const operatorsArr = [ { val: 'in', type: 'array', useSelect: true, multi: true }, { val: 'not in', type: 'array', useSelect: true, multi: true }, @@ -17,7 +18,7 @@ const operatorsArr = [ { val: 'LIKE', type: 'string', datasourceTypes: ['table'] }, ]; const operators = {}; -operatorsArr.forEach(op => { +operatorsArr.forEach((op) => { operators[op.val] = op; }); diff --git a/superset/assets/javascripts/explorev2/components/controls/HiddenControl.jsx b/superset/assets/javascripts/explorev2/components/controls/HiddenControl.jsx index 4720789160..087694436d 100644 --- a/superset/assets/javascripts/explorev2/components/controls/HiddenControl.jsx +++ b/superset/assets/javascripts/explorev2/components/controls/HiddenControl.jsx @@ -13,11 +13,9 @@ const defaultProps = { onChange: () => {}, }; -export default class HiddenControl extends React.PureComponent { - render() { - // This wouldn't be necessary but might as well - return ; - } +export default function HiddenControl(props) { + // This wouldn't be necessary but might as well + return ; } HiddenControl.propTypes = propTypes; diff --git a/superset/assets/javascripts/explorev2/components/controls/SelectControl.jsx b/superset/assets/javascripts/explorev2/components/controls/SelectControl.jsx index e16f9d6f36..8f14e1e62b 100644 --- a/superset/assets/javascripts/explorev2/components/controls/SelectControl.jsx +++ b/superset/assets/javascripts/explorev2/components/controls/SelectControl.jsx @@ -42,13 +42,13 @@ export default class SelectControl extends React.PureComponent { let optionValue = opt ? opt.value : null; // if multi, return options values as an array if (this.props.multi) { - optionValue = opt ? opt.map((o) => o.value) : null; + optionValue = opt ? opt.map(o => o.value) : null; } this.props.onChange(optionValue); } getOptions(props) { // Accepts different formats of input - const options = props.choices.map(c => { + const options = props.choices.map((c) => { let option; if (Array.isArray(c)) { const label = c.length > 1 ? c[1] : c[0]; @@ -75,7 +75,7 @@ export default class SelectControl extends React.PureComponent { if (!Array.isArray(valuesToAdd)) { valuesToAdd = [valuesToAdd]; } - valuesToAdd.forEach(v => { + valuesToAdd.forEach((v) => { if (values.indexOf(v) < 0) { options.push({ value: v, label: v }); } diff --git a/superset/assets/javascripts/explorev2/index.jsx b/superset/assets/javascripts/explorev2/index.jsx index e72b8c3941..a35c90bd5f 100644 --- a/superset/assets/javascripts/explorev2/index.jsx +++ b/superset/assets/javascripts/explorev2/index.jsx @@ -1,22 +1,20 @@ /* eslint camelcase: 0 */ import React from 'react'; import ReactDOM from 'react-dom'; -import ExploreViewContainer from './components/ExploreViewContainer'; import { createStore, applyMiddleware, compose } from 'redux'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; + import { now } from '../modules/dates'; import { initEnhancer } from '../reduxUtils'; import AlertsWrapper from '../components/AlertsWrapper'; import { getControlsState, getFormDataFromControls } from './stores/store'; import { initJQueryAjaxCSRF } from '../modules/utils'; +import ExploreViewContainer from './components/ExploreViewContainer'; +import { exploreReducer } from './reducers/exploreReducer'; +import { appSetup } from '../common'; - -// jquery and bootstrap required to make bootstrap dropdown menu's work -const $ = window.$ = require('jquery'); // eslint-disable-line -const jQuery = window.jQuery = require('jquery'); // eslint-disable-line -require('bootstrap'); -require('./main.css'); +appSetup(); initJQueryAjaxCSRF(); const exploreViewContainer = document.getElementById('js-explore-view-container'); @@ -24,7 +22,6 @@ const bootstrapData = JSON.parse(exploreViewContainer.getAttribute('data-bootstr const controls = getControlsState(bootstrapData, bootstrapData.form_data); delete bootstrapData.form_data; -import { exploreReducer } from './reducers/exploreReducer'; // Initial state const bootstrappedState = Object.assign( @@ -41,11 +38,11 @@ const bootstrappedState = Object.assign( queryResponse: null, triggerQuery: true, triggerRender: false, - } + }, ); const store = createStore(exploreReducer, bootstrappedState, - compose(applyMiddleware(thunk), initEnhancer(false)) + compose(applyMiddleware(thunk), initEnhancer(false)), ); ReactDOM.render( @@ -55,5 +52,5 @@ ReactDOM.render( , - exploreViewContainer + exploreViewContainer, ); diff --git a/superset/assets/javascripts/explorev2/reducers/exploreReducer.js b/superset/assets/javascripts/explorev2/reducers/exploreReducer.js index 503e758b38..9957372dd6 100644 --- a/superset/assets/javascripts/explorev2/reducers/exploreReducer.js +++ b/superset/assets/javascripts/explorev2/reducers/exploreReducer.js @@ -77,7 +77,7 @@ export const exploreReducer = function (state, action) { { chartStatus: 'success', queryResponse: action.queryResponse, - } + }, ); }, [actions.CHART_UPDATE_STARTED]() { diff --git a/superset/assets/javascripts/explorev2/stores/controls.jsx b/superset/assets/javascripts/explorev2/stores/controls.jsx index 59028bb463..7829a4902a 100644 --- a/superset/assets/javascripts/explorev2/stores/controls.jsx +++ b/superset/assets/javascripts/explorev2/stores/controls.jsx @@ -1,5 +1,5 @@ -import { formatSelectOptionsForRange, formatSelectOptions } from '../../modules/utils'; import React from 'react'; +import { formatSelectOptionsForRange, formatSelectOptions } from '../../modules/utils'; import visTypes from './visTypes'; import * as v from '../validators'; @@ -67,7 +67,7 @@ export const controls = { validators: [v.nonEmpty], default: control => control.choices && control.choices.length > 0 ? [control.choices[0][0]] : null, - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo : [], }), description: 'One or many metrics to display', @@ -79,7 +79,7 @@ export const controls = { label: 'Ordering', default: [], description: 'One or many metrics to display', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.order_by_choices : [], }), }, @@ -91,7 +91,7 @@ export const controls = { description: 'Choose the metric', default: control => control.choices && control.choices.length > 0 ? control.choices[0][0] : null, - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo : null, }), }, @@ -102,7 +102,7 @@ export const controls = { choices: [], default: [], description: 'Choose a metric for right axis', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo : [], }), }, @@ -261,7 +261,7 @@ export const controls = { label: 'Color Metric', default: null, description: 'A metric to use for color', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo : [], }), }, @@ -286,7 +286,7 @@ export const controls = { label: 'Group by', default: [], description: 'One or many controls to group by', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.gb_cols : [], }), }, @@ -295,7 +295,7 @@ export const controls = { type: 'SelectControl', multi: true, label: 'Columns', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.gb_cols : [], }), default: [], @@ -308,7 +308,7 @@ export const controls = { label: 'Columns', default: [], description: 'Columns to display', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.all_cols : [], }), }, @@ -318,7 +318,7 @@ export const controls = { label: 'X', default: null, description: 'Columns to display', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.all_cols : [], }), }, @@ -328,7 +328,7 @@ export const controls = { label: 'Y', default: null, description: 'Columns to display', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.all_cols : [], }), }, @@ -436,7 +436,7 @@ export const controls = { 'column in the table or. Also note that the ' + 'filter below is applied against this column or ' + 'expression', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.granularity_sqla : [], }), }, @@ -450,7 +450,7 @@ export const controls = { 'your time column and defines a new time granularity. ' + 'The options here are defined on a per database ' + 'engine basis in the Superset source code.', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.time_grain_sqla : null, }), }, @@ -577,7 +577,7 @@ export const controls = { label: 'Sort By', default: null, description: 'Metric used to define the top series', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo : [], }), }, @@ -606,7 +606,7 @@ export const controls = { description: 'Defines the grouping of entities. ' + 'Each series is shown as a specific color on the chart and ' + 'has a legend toggle', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.gb_cols : [], }), }, @@ -616,7 +616,7 @@ export const controls = { label: 'Entity', default: null, description: 'This define the element to be plotted on the chart', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.gb_cols : [], }), }, @@ -626,7 +626,7 @@ export const controls = { label: 'X Axis', default: null, description: 'Metric assigned to the [X] axis', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo : [], }), }, @@ -636,7 +636,7 @@ export const controls = { label: 'Y Axis', default: null, description: 'Metric assigned to the [Y] axis', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo : [], }), }, @@ -645,7 +645,7 @@ export const controls = { type: 'SelectControl', label: 'Bubble Size', default: null, - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo : [], }), }, @@ -1009,7 +1009,7 @@ export const controls = { 'Numerical columns will be aggregated with the aggregator. ' + 'Non-numerical columns will be used to label points. ' + 'Leave empty to get a count of points in each cluster.', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.all_cols : [], }), }, @@ -1057,7 +1057,7 @@ export const controls = { description: 'The radius of individual points (ones that are not in a cluster). ' + 'Either a numerical column or `Auto`, which scales the point based ' + 'on the largest cluster', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: [].concat([['Auto', 'Auto']], state.datasource.all_cols), }), }, @@ -1176,7 +1176,7 @@ export const controls = { label: '', default: [], description: '', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ datasource: state.datasource, }), }, @@ -1186,7 +1186,7 @@ export const controls = { label: '', default: [], description: '', - mapStateToProps: (state) => ({ + mapStateToProps: state => ({ choices: (state.datasource) ? state.datasource.metrics_combo .concat(state.datasource.filterable_cols) : [], datasource: state.datasource, diff --git a/superset/assets/javascripts/explorev2/stores/store.js b/superset/assets/javascripts/explorev2/stores/store.js index d0e31c0508..c3e98b0abc 100644 --- a/superset/assets/javascripts/explorev2/stores/store.js +++ b/superset/assets/javascripts/explorev2/stores/store.js @@ -4,7 +4,7 @@ import visTypes, { sectionsToRender } from './visTypes'; export function getFormDataFromControls(controlsState) { const formData = {}; - Object.keys(controlsState).forEach(controlName => { + Object.keys(controlsState).forEach((controlName) => { formData[controlName] = controlsState[controlName].value; }); return formData; @@ -78,7 +78,7 @@ export function applyDefaultFormData(form_data) { const controlNames = getControlNames(vizType, datasourceType); const controlOverrides = viz.controlOverrides || {}; const formData = {}; - controlNames.forEach(k => { + controlNames.forEach((k) => { const control = Object.assign({}, controls[k]); if (controlOverrides[k]) { Object.assign(control, controlOverrides[k]); diff --git a/superset/assets/javascripts/explorev2/stores/visTypes.js b/superset/assets/javascripts/explorev2/stores/visTypes.js index e28a4ccdcf..5d00d6a525 100644 --- a/superset/assets/javascripts/explorev2/stores/visTypes.js +++ b/superset/assets/javascripts/explorev2/stores/visTypes.js @@ -762,6 +762,6 @@ export function sectionsToRender(vizType, datasourceType) { datasourceType === 'table' ? sections.sqlaTimeSeries : sections.druidTimeSeries, viz.controlPanelSections, datasourceType === 'table' ? sections.sqlClause : [], - datasourceType === 'table' ? sections.filters[0] : sections.filters + datasourceType === 'table' ? sections.filters[0] : sections.filters, ); } diff --git a/superset/assets/javascripts/modules/colors.js b/superset/assets/javascripts/modules/colors.js index 71068175db..56c88afd2a 100644 --- a/superset/assets/javascripts/modules/colors.js +++ b/superset/assets/javascripts/modules/colors.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -const d3 = require('d3'); +import d3 from 'd3'; // Color related utility functions go in this object export const bnbColors = [ diff --git a/superset/assets/javascripts/modules/dates.js b/superset/assets/javascripts/modules/dates.js index b1e808677a..81dd9177eb 100644 --- a/superset/assets/javascripts/modules/dates.js +++ b/superset/assets/javascripts/modules/dates.js @@ -9,7 +9,7 @@ function UTC(dttm) { dttm.getUTCDate(), dttm.getUTCHours(), dttm.getUTCMinutes(), - dttm.getUTCSeconds() + dttm.getUTCSeconds(), ); } export const tickMultiFormat = d3.time.format.multi([ diff --git a/superset/assets/javascripts/modules/superset.js b/superset/assets/javascripts/modules/superset.js index d95d159acb..1fb0cd9864 100644 --- a/superset/assets/javascripts/modules/superset.js +++ b/superset/assets/javascripts/modules/superset.js @@ -1,12 +1,12 @@ -import $ from 'jquery'; -const utils = require('./utils'); -// vis sources /* eslint camel-case: 0 */ +import $ from 'jquery'; import Mustache from 'mustache'; -import vizMap from '../../visualizations/main.js'; +import vizMap from '../../visualizations/main'; import { getExploreUrl } from '../explorev2/exploreUtils'; import { applyDefaultFormData } from '../explorev2/stores/store'; +const utils = require('./utils'); + /* eslint wrap-iife: 0*/ const px = function () { let slice; @@ -217,14 +217,14 @@ const px = function () { timer = setInterval(stopwatch, 10); $('#timer').removeClass('label-danger label-success'); $('#timer').addClass('label-warning'); - $.getJSON(this.jsonEndpoint(), queryResponse => { + $.getJSON(this.jsonEndpoint(), (queryResponse) => { try { vizMap[formData.viz_type](this, queryResponse); this.done(queryResponse); } catch (e) { this.error('An error occurred while rendering the visualization: ' + e); } - }).fail(err => { + }).fail((err) => { this.error(err.responseText, err); }); }, diff --git a/superset/assets/javascripts/modules/utils.js b/superset/assets/javascripts/modules/utils.js index 9edaabf965..a8ed50344a 100644 --- a/superset/assets/javascripts/modules/utils.js +++ b/superset/assets/javascripts/modules/utils.js @@ -143,8 +143,8 @@ export function formatSelectOptionsForRange(start, end) { } export function formatSelectOptions(options) { - return options.map((opt) => - [opt, opt.toString()] + return options.map(opt => + [opt, opt.toString()], ); } diff --git a/superset/assets/javascripts/profile/components/CreatedContent.jsx b/superset/assets/javascripts/profile/components/CreatedContent.jsx index d779e19892..81fc26c141 100644 --- a/superset/assets/javascripts/profile/components/CreatedContent.jsx +++ b/superset/assets/javascripts/profile/components/CreatedContent.jsx @@ -17,7 +17,7 @@ class CreatedContent extends React.PureComponent { }; } renderSliceTable() { - const mutator = (data) => data.map(slice => ({ + const mutator = data => data.map(slice => ({ slice: {slice.title}, favorited: moment.utc(slice.dttm).fromNow(), _favorited: slice.dttm, @@ -34,7 +34,7 @@ class CreatedContent extends React.PureComponent { ); } renderDashboardTable() { - const mutator = (data) => data.map(dash => ({ + const mutator = data => data.map(dash => ({ dashboard: {dash.title}, favorited: moment.utc(dash.dttm).fromNow(), _favorited: dash.dttm, diff --git a/superset/assets/javascripts/profile/components/Favorites.jsx b/superset/assets/javascripts/profile/components/Favorites.jsx index 147d1b210f..6a7518224c 100644 --- a/superset/assets/javascripts/profile/components/Favorites.jsx +++ b/superset/assets/javascripts/profile/components/Favorites.jsx @@ -17,7 +17,7 @@ export default class Favorites extends React.PureComponent { }; } renderSliceTable() { - const mutator = (data) => data.map(slice => ({ + const mutator = data => data.map(slice => ({ slice: {slice.title}, creator: {slice.creator}, favorited: moment.utc(slice.dttm).fromNow(), @@ -35,7 +35,7 @@ export default class Favorites extends React.PureComponent { ); } renderDashboardTable() { - const mutator = (data) => data.map(dash => ({ + const mutator = data => data.map(dash => ({ dashboard: {dash.title}, creator: {dash.creator}, favorited: moment.utc(dash.dttm).fromNow(), diff --git a/superset/assets/javascripts/profile/components/RecentActivity.jsx b/superset/assets/javascripts/profile/components/RecentActivity.jsx index 3077e7e630..ceecf7cb12 100644 --- a/superset/assets/javascripts/profile/components/RecentActivity.jsx +++ b/superset/assets/javascripts/profile/components/RecentActivity.jsx @@ -1,8 +1,9 @@ import React from 'react'; -import TableLoader from './TableLoader'; import moment from 'moment'; import $ from 'jquery'; +import TableLoader from './TableLoader'; + const propTypes = { user: React.PropTypes.object, }; diff --git a/superset/assets/javascripts/profile/components/TableLoader.jsx b/superset/assets/javascripts/profile/components/TableLoader.jsx index b5128589da..76323d8bce 100644 --- a/superset/assets/javascripts/profile/components/TableLoader.jsx +++ b/superset/assets/javascripts/profile/components/TableLoader.jsx @@ -44,7 +44,7 @@ export default class TableLoader extends React.PureComponent { {this.state.data.map((row, i) => ( - {columns.map(col => { + {columns.map((col) => { if (row.hasOwnProperty('_' + col)) { return (
diff --git a/superset/assets/javascripts/profile/index.jsx b/superset/assets/javascripts/profile/index.jsx index 913dfca705..adf371e699 100644 --- a/superset/assets/javascripts/profile/index.jsx +++ b/superset/assets/javascripts/profile/index.jsx @@ -1,15 +1,13 @@ +/* eslint no-unused-vars: 0 */ import React from 'react'; import ReactDOM from 'react-dom'; import { Badge, Col, Label, Row, Tabs, Tab, Panel } from 'react-bootstrap'; - import App from './components/App'; +import { appSetup } from '../common'; -const $ = window.$ = require('jquery'); -/* eslint no-unused-vars: 0 */ -const jQuery = window.jQuery = $; -require('bootstrap'); -require('./main.css'); +import './main.css'; +appSetup(); const profileViewContainer = document.getElementById('app'); const bootstrap = JSON.parse(profileViewContainer.getAttribute('data-bootstrap')); @@ -17,5 +15,5 @@ const bootstrap = JSON.parse(profileViewContainer.getAttribute('data-bootstrap') const user = bootstrap.user; ReactDOM.render( , - profileViewContainer + profileViewContainer, ); diff --git a/superset/assets/javascripts/reduxUtils.js b/superset/assets/javascripts/reduxUtils.js index bf430768a8..fc42083d56 100644 --- a/superset/assets/javascripts/reduxUtils.js +++ b/superset/assets/javascripts/reduxUtils.js @@ -99,7 +99,7 @@ export function areObjectsEqual(obj1, obj2) { if (!obj1 || !obj2) { return false; } - if (! Object.keys(obj1).length !== Object.keys(obj2).length) { + if (!Object.keys(obj1).length !== Object.keys(obj2).length) { return false; } for (const id in obj1) { diff --git a/superset/assets/javascripts/welcome.js b/superset/assets/javascripts/welcome.js index 8a326f0853..82415f95bf 100644 --- a/superset/assets/javascripts/welcome.js +++ b/superset/assets/javascripts/welcome.js @@ -1,15 +1,16 @@ -const $ = window.$ = require('jquery'); /* eslint no-unused-vars: 0 */ -const jQuery = window.jQuery = $; -require('../stylesheets/welcome.css'); -require('bootstrap'); - -require('datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css'); import 'datatables.net'; import dt from 'datatables.net-bs'; +import d3 from 'd3'; + +import '../stylesheets/welcome.css'; +import { appSetup } from './common'; + +appSetup(); +require('datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css'); + dt(window, $); -const d3 = require('d3'); function modelViewTable(selector, modelView, orderCol, order) { // Builds a dataTable from a flask appbuilder api endpoint let url = '/' + modelView.toLowerCase() + '/api/read'; diff --git a/superset/assets/package.json b/superset/assets/package.json index 2a3129113f..1d94dbef17 100644 --- a/superset/assets/package.json +++ b/superset/assets/package.json @@ -39,9 +39,10 @@ "homepage": "https://github.com/airbnb/superset#readme", "dependencies": { "autobind-decorator": "^1.3.3", + "babel-register": "^6.24.1", "bootstrap": "^3.3.6", "bootstrap-datepicker": "^1.6.0", - "brace": "^0.9.1", + "brace": "^0.10.0", "brfs": "^1.4.3", "cal-heatmap": "3.6.2", "classnames": "^2.2.5", @@ -52,29 +53,30 @@ "d3-tip": "^0.7.1", "datamaps": "^0.5.8", "datatables-bootstrap3-plugin": "^0.5.0", + "datatables.net": "^1.10.13", "datatables.net-bs": "^1.10.12", "font-awesome": "^4.6.3", "gridster": "^0.5.6", "immutability-helper": "^2.0.0", "immutable": "^3.8.1", - "jquery": "^2.2.1", + "jquery": "^3.2.1", "lodash.throttle": "^4.1.1", "mapbox-gl": "^0.26.0", "moment": "^2.14.1", "moments": "0.0.2", "mustache": "^2.2.1", "nvd3": "1.8.5", - "react": "^15.3.2", + "react": "^15.5.1", "react-ace": "^4.1.5", "react-addons-css-transition-group": "^15.4.2", "react-addons-shallow-compare": "^15.4.2", "react-alert": "^1.0.14", "react-bootstrap": "^0.30.3", - "react-bootstrap-table": "^2.3.8", - "react-dom": "^15.3.2", + "react-bootstrap-table": "^3.1.7", + "react-dom": "^15.5.1", "react-draggable": "^2.1.2", "react-gravatar": "^2.6.1", - "react-grid-layout": "^0.13.1", + "react-grid-layout": "^0.14.4", "react-map-gl": "^1.7.0", "react-redux": "^5.0.2", "react-resizable": "^1.3.3", @@ -87,11 +89,10 @@ "redux-localstorage": "^0.4.1", "redux-thunk": "^2.1.0", "shortid": "^2.2.6", - "style-loader": "^0.13.0", "supercluster": "https://github.com/georgeke/supercluster/tarball/ac3492737e7ce98e07af679623aad452373bbc40", "topojson": "^1.6.22", "urijs": "^1.18.10", - "victory": "^0.17.0", + "victory": "^0.18.4", "viewport-mercator-project": "^2.1.0" }, "devDependencies": { @@ -105,31 +106,32 @@ "babel-preset-es2015": "^6.14.0", "babel-preset-react": "^6.11.1", "chai": "^3.5.0", - "codeclimate-test-reporter": "^0.3.3", - "css-loader": "^0.23.1", + "codeclimate-test-reporter": "^0.4.1", + "css-loader": "^0.28.0", "enzyme": "^2.0.0", - "eslint": "^2.13.1", - "eslint-config-airbnb": "^9.0.1", - "eslint-plugin-import": "^1.11.1", - "eslint-plugin-jsx-a11y": "^1.2.0", - "eslint-plugin-react": "^5.2.2", + "eslint": "^3.19.0", + "eslint-config-airbnb": "^14.1.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^4.0.0", + "eslint-plugin-react": "^6.10.3", "exports-loader": "^0.6.3", - "file-loader": "^0.8.5", + "file-loader": "^0.11.1", "github-changes": "^1.0.4", "ignore-styles": "^5.0.1", - "imports-loader": "^0.6.5", + "imports-loader": "^0.7.1", "istanbul": "^1.0.0-alpha", - "jsdom": "^8.0.1", + "jsdom": "^9.12.0", "json-loader": "^0.5.4", "less": "^2.6.1", - "less-loader": "^2.2.2", - "mocha": "^2.4.5", - "react-addons-test-utils": "^15.3.2", - "sinon": "^1.17.6", - "style-loader": "^0.13.0", + "less-loader": "^4.0.3", + "mocha": "^3.2.0", + "react-addons-test-utils": "^15.5.1", + "react-test-renderer": "^15.5.1", + "sinon": "^2.1.0", + "style-loader": "^0.16.1", "transform-loader": "^0.2.3", "url-loader": "^0.5.7", - "webpack": "^1.13.1", - "webworkify-webpack": "1.0.6" + "webpack": "^2.3.3", + "webworkify-webpack": "2.0.4" } } diff --git a/superset/assets/spec/javascripts/components/AsyncSelect_spec.jsx b/superset/assets/spec/javascripts/components/AsyncSelect_spec.jsx index fb802357f4..b415d27f88 100644 --- a/superset/assets/spec/javascripts/components/AsyncSelect_spec.jsx +++ b/superset/assets/spec/javascripts/components/AsyncSelect_spec.jsx @@ -1,11 +1,12 @@ import React from 'react'; import Select from 'react-select'; -import AsyncSelect from '../../../javascripts/components/AsyncSelect'; import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; import sinon from 'sinon'; +import AsyncSelect from '../../../javascripts/components/AsyncSelect'; + describe('AsyncSelect', () => { const mockedProps = { dataEndpoint: '/slicemodelview/api/read', @@ -14,20 +15,20 @@ describe('AsyncSelect', () => { }; it('is valid element', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('has one select', () => { const wrapper = shallow( - + , ); expect(wrapper.find(Select)).to.have.length(1); }); it('calls onChange on select change', () => { const wrapper = shallow( - + , ); wrapper.find(Select).simulate('change', { value: 1 }); expect(mockedProps.onChange).to.have.property('callCount', 1); diff --git a/superset/assets/spec/javascripts/components/CopyToClipboard_spec.jsx b/superset/assets/spec/javascripts/components/CopyToClipboard_spec.jsx index a5f0ee3f7f..e6e7408a4c 100644 --- a/superset/assets/spec/javascripts/components/CopyToClipboard_spec.jsx +++ b/superset/assets/spec/javascripts/components/CopyToClipboard_spec.jsx @@ -11,7 +11,7 @@ describe('CopyToClipboard', () => { it('renders', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); }); diff --git a/superset/assets/spec/javascripts/components/ModalTrigger_spec.jsx b/superset/assets/spec/javascripts/components/ModalTrigger_spec.jsx index a498c2c113..3fb7d3eb58 100644 --- a/superset/assets/spec/javascripts/components/ModalTrigger_spec.jsx +++ b/superset/assets/spec/javascripts/components/ModalTrigger_spec.jsx @@ -13,7 +13,7 @@ describe('ModalTrigger', () => { it('is a valid element', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); }); diff --git a/superset/assets/spec/javascripts/dashboard/CodeModal_spec.jsx b/superset/assets/spec/javascripts/dashboard/CodeModal_spec.jsx index 5a430bc3d5..b71401ecd6 100644 --- a/superset/assets/spec/javascripts/dashboard/CodeModal_spec.jsx +++ b/superset/assets/spec/javascripts/dashboard/CodeModal_spec.jsx @@ -1,9 +1,9 @@ import React from 'react'; -import CodeModal from '../../../javascripts/dashboard/components/CodeModal'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import CodeModal from '../../../javascripts/dashboard/components/CodeModal'; describe('CodeModal', () => { const mockedProps = { @@ -11,7 +11,7 @@ describe('CodeModal', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders the trigger node', () => { diff --git a/superset/assets/spec/javascripts/dashboard/CssEditor_spec.jsx b/superset/assets/spec/javascripts/dashboard/CssEditor_spec.jsx index 58cac9d868..1da5624cf9 100644 --- a/superset/assets/spec/javascripts/dashboard/CssEditor_spec.jsx +++ b/superset/assets/spec/javascripts/dashboard/CssEditor_spec.jsx @@ -1,9 +1,9 @@ import React from 'react'; -import CssEditor from '../../../javascripts/dashboard/components/CssEditor'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import CssEditor from '../../../javascripts/dashboard/components/CssEditor'; describe('CssEditor', () => { const mockedProps = { @@ -11,7 +11,7 @@ describe('CssEditor', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders the trigger node', () => { diff --git a/superset/assets/spec/javascripts/dashboard/RefreshIntervalModal_spec.jsx b/superset/assets/spec/javascripts/dashboard/RefreshIntervalModal_spec.jsx index 8cf89be8da..7537074765 100644 --- a/superset/assets/spec/javascripts/dashboard/RefreshIntervalModal_spec.jsx +++ b/superset/assets/spec/javascripts/dashboard/RefreshIntervalModal_spec.jsx @@ -1,9 +1,9 @@ import React from 'react'; -import RefreshIntervalModal from '../../../javascripts/dashboard/components/RefreshIntervalModal'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import RefreshIntervalModal from '../../../javascripts/dashboard/components/RefreshIntervalModal'; describe('RefreshIntervalModal', () => { const mockedProps = { @@ -11,7 +11,7 @@ describe('RefreshIntervalModal', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders the trigger node', () => { diff --git a/superset/assets/spec/javascripts/dashboard/SliceCell_spec.jsx b/superset/assets/spec/javascripts/dashboard/SliceCell_spec.jsx index d693ecac65..cc3e046ff5 100644 --- a/superset/assets/spec/javascripts/dashboard/SliceCell_spec.jsx +++ b/superset/assets/spec/javascripts/dashboard/SliceCell_spec.jsx @@ -1,10 +1,10 @@ import React from 'react'; -import SliceCell from '../../../javascripts/dashboard/components/SliceCell'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; import { slice } from './fixtures'; +import SliceCell from '../../../javascripts/dashboard/components/SliceCell'; describe('SliceCell', () => { const mockedProps = { @@ -14,7 +14,7 @@ describe('SliceCell', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders five links', () => { diff --git a/superset/assets/spec/javascripts/explorev2/components/CheckboxControl_spec.js b/superset/assets/spec/javascripts/explorev2/components/CheckboxControl_spec.jsx similarity index 99% rename from superset/assets/spec/javascripts/explorev2/components/CheckboxControl_spec.js rename to superset/assets/spec/javascripts/explorev2/components/CheckboxControl_spec.jsx index 90bcb217c8..0a94f4abf8 100644 --- a/superset/assets/spec/javascripts/explorev2/components/CheckboxControl_spec.js +++ b/superset/assets/spec/javascripts/explorev2/components/CheckboxControl_spec.jsx @@ -5,6 +5,7 @@ import sinon from 'sinon'; import { expect } from 'chai'; import { describe, it, beforeEach } from 'mocha'; import { shallow } from 'enzyme'; + import CheckboxControl from '../../../../javascripts/explorev2/components/controls/CheckboxControl'; const defaultProps = { diff --git a/superset/assets/spec/javascripts/explorev2/components/ControlPanelsContainer_spec.js b/superset/assets/spec/javascripts/explorev2/components/ControlPanelsContainer_spec.jsx similarity index 100% rename from superset/assets/spec/javascripts/explorev2/components/ControlPanelsContainer_spec.js rename to superset/assets/spec/javascripts/explorev2/components/ControlPanelsContainer_spec.jsx diff --git a/superset/assets/spec/javascripts/explorev2/components/ControlRow_spec.js b/superset/assets/spec/javascripts/explorev2/components/ControlRow_spec.jsx similarity index 100% rename from superset/assets/spec/javascripts/explorev2/components/ControlRow_spec.js rename to superset/assets/spec/javascripts/explorev2/components/ControlRow_spec.jsx diff --git a/superset/assets/spec/javascripts/explorev2/components/ExploreActionButtons_spec.jsx b/superset/assets/spec/javascripts/explorev2/components/ExploreActionButtons_spec.jsx index c85de1b413..a67124e4cc 100644 --- a/superset/assets/spec/javascripts/explorev2/components/ExploreActionButtons_spec.jsx +++ b/superset/assets/spec/javascripts/explorev2/components/ExploreActionButtons_spec.jsx @@ -18,7 +18,7 @@ describe('ExploreActionButtons', () => { it('renders', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); diff --git a/superset/assets/spec/javascripts/explorev2/components/FilterControl_spec.js b/superset/assets/spec/javascripts/explorev2/components/FilterControl_spec.jsx similarity index 95% rename from superset/assets/spec/javascripts/explorev2/components/FilterControl_spec.js rename to superset/assets/spec/javascripts/explorev2/components/FilterControl_spec.jsx index 63b3f35aeb..02fef03cd8 100644 --- a/superset/assets/spec/javascripts/explorev2/components/FilterControl_spec.js +++ b/superset/assets/spec/javascripts/explorev2/components/FilterControl_spec.jsx @@ -30,7 +30,7 @@ describe('FilterControl', () => { it('renders Filters', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); diff --git a/superset/assets/spec/javascripts/explorev2/components/Filter_spec.js b/superset/assets/spec/javascripts/explorev2/components/Filter_spec.jsx similarity index 97% rename from superset/assets/spec/javascripts/explorev2/components/Filter_spec.js rename to superset/assets/spec/javascripts/explorev2/components/Filter_spec.jsx index 121032bd4d..e265d6f3f2 100644 --- a/superset/assets/spec/javascripts/explorev2/components/Filter_spec.js +++ b/superset/assets/spec/javascripts/explorev2/components/Filter_spec.jsx @@ -34,7 +34,7 @@ describe('Filter', () => { it('renders Filters', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); diff --git a/superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.js b/superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.jsx similarity index 99% rename from superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.js rename to superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.jsx index 509caa969e..c78d1c75c4 100644 --- a/superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.js +++ b/superset/assets/spec/javascripts/explorev2/components/RunQueryActionButton_spec.jsx @@ -24,7 +24,7 @@ describe('RunQueryActionButton', () => { it('is a valid react element', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); diff --git a/superset/assets/spec/javascripts/explorev2/components/SaveModal_spec.js b/superset/assets/spec/javascripts/explorev2/components/SaveModal_spec.jsx similarity index 99% rename from superset/assets/spec/javascripts/explorev2/components/SaveModal_spec.js rename to superset/assets/spec/javascripts/explorev2/components/SaveModal_spec.jsx index 157d5ffcbb..7c3a4a5423 100644 --- a/superset/assets/spec/javascripts/explorev2/components/SaveModal_spec.js +++ b/superset/assets/spec/javascripts/explorev2/components/SaveModal_spec.jsx @@ -2,11 +2,12 @@ import React from 'react'; import { expect } from 'chai'; import { describe, it, beforeEach } from 'mocha'; import { shallow } from 'enzyme'; -import { defaultFormData } from '../../../../javascripts/explorev2/stores/store'; -import { SaveModal } from '../../../../javascripts/explorev2/components/SaveModal'; import { Modal, Button, Radio } from 'react-bootstrap'; import sinon from 'sinon'; +import { defaultFormData } from '../../../../javascripts/explorev2/stores/store'; +import { SaveModal } from '../../../../javascripts/explorev2/components/SaveModal'; + const defaultProps = { can_edit: true, onHide: () => ({}), diff --git a/superset/assets/spec/javascripts/explorev2/components/SelectControl_spec.js b/superset/assets/spec/javascripts/explorev2/components/SelectControl_spec.jsx similarity index 100% rename from superset/assets/spec/javascripts/explorev2/components/SelectControl_spec.js rename to superset/assets/spec/javascripts/explorev2/components/SelectControl_spec.jsx diff --git a/superset/assets/spec/javascripts/explorev2/components/TextArea_spec.js b/superset/assets/spec/javascripts/explorev2/components/TextArea_spec.jsx similarity index 100% rename from superset/assets/spec/javascripts/explorev2/components/TextArea_spec.js rename to superset/assets/spec/javascripts/explorev2/components/TextArea_spec.jsx diff --git a/superset/assets/spec/javascripts/explorev2/utils_spec.jsx b/superset/assets/spec/javascripts/explorev2/utils_spec.jsx index 111dccc951..6747188a7f 100644 --- a/superset/assets/spec/javascripts/explorev2/utils_spec.jsx +++ b/superset/assets/spec/javascripts/explorev2/utils_spec.jsx @@ -1,7 +1,7 @@ import { it, describe } from 'mocha'; import { expect } from 'chai'; import URI from 'urijs'; -import { getExploreUrl } from '../../../javascripts/explorev2/exploreUtils.js'; +import { getExploreUrl } from '../../../javascripts/explorev2/exploreUtils'; describe('utils', () => { const formData = { @@ -19,41 +19,41 @@ describe('utils', () => { compareURI( URI(getExploreUrl(formData, 'base', false, 'http://superset.com')), - URI('/superset/explore/table/1/').search({ form_data: sFormData }) + URI('/superset/explore/table/1/').search({ form_data: sFormData }), ); }); it('getExploreUrl generates proper json url', () => { compareURI( URI(getExploreUrl(formData, 'json', false, 'superset.com')), - URI('/superset/explore_json/table/1/').search({ form_data: sFormData }) + URI('/superset/explore_json/table/1/').search({ form_data: sFormData }), ); }); it('getExploreUrl generates proper json forced url', () => { compareURI( URI(getExploreUrl(formData, 'json', true, 'superset.com')), URI('/superset/explore_json/table/1/') - .search({ form_data: sFormData, force: 'true' }) + .search({ form_data: sFormData, force: 'true' }), ); }); it('getExploreUrl generates proper csv URL', () => { compareURI( URI(getExploreUrl(formData, 'csv', false, 'superset.com')), URI('/superset/explore_json/table/1/') - .search({ form_data: sFormData, csv: 'true' }) + .search({ form_data: sFormData, csv: 'true' }), ); }); it('getExploreUrl generates proper standalone URL', () => { compareURI( URI(getExploreUrl(formData, 'standalone', false, 'superset.com')), URI('/superset/explore/table/1/') - .search({ form_data: sFormData, standalone: 'true' }) + .search({ form_data: sFormData, standalone: 'true' }), ); }); it('getExploreUrl preserves main URLs params', () => { compareURI( URI(getExploreUrl(formData, 'json', false, 'superset.com?foo=bar')), URI('/superset/explore_json/table/1/') - .search({ foo: 'bar', form_data: sFormData }) + .search({ foo: 'bar', form_data: sFormData }), ); }); }); diff --git a/superset/assets/spec/javascripts/profile/App_spec.jsx b/superset/assets/spec/javascripts/profile/App_spec.jsx index d85add18b0..6484416cf8 100644 --- a/superset/assets/spec/javascripts/profile/App_spec.jsx +++ b/superset/assets/spec/javascripts/profile/App_spec.jsx @@ -1,10 +1,11 @@ import React from 'react'; -import App from '../../../javascripts/profile/components/App'; import { Col, Row, Tab } from 'react-bootstrap'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; + import { user } from './fixtures'; +import App from '../../../javascripts/profile/components/App'; describe('App', () => { const mockedProps = { @@ -12,7 +13,7 @@ describe('App', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders 2 Col', () => { diff --git a/superset/assets/spec/javascripts/profile/CreatedContent_spec.jsx b/superset/assets/spec/javascripts/profile/CreatedContent_spec.jsx index d15e00b168..64e72fccb4 100644 --- a/superset/assets/spec/javascripts/profile/CreatedContent_spec.jsx +++ b/superset/assets/spec/javascripts/profile/CreatedContent_spec.jsx @@ -1,10 +1,10 @@ import React from 'react'; -import CreatedContent from '../../../javascripts/profile/components/CreatedContent'; -import TableLoader from '../../../javascripts/profile/components/TableLoader'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; import { user } from './fixtures'; +import CreatedContent from '../../../javascripts/profile/components/CreatedContent'; +import TableLoader from '../../../javascripts/profile/components/TableLoader'; describe('CreatedContent', () => { @@ -13,7 +13,7 @@ describe('CreatedContent', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders 2 TableLoader', () => { diff --git a/superset/assets/spec/javascripts/profile/Favorites_spec.jsx b/superset/assets/spec/javascripts/profile/Favorites_spec.jsx index 4a7908c1dd..592dc43933 100644 --- a/superset/assets/spec/javascripts/profile/Favorites_spec.jsx +++ b/superset/assets/spec/javascripts/profile/Favorites_spec.jsx @@ -1,10 +1,11 @@ import React from 'react'; -import Favorites from '../../../javascripts/profile/components/Favorites'; -import TableLoader from '../../../javascripts/profile/components/TableLoader'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; + import { user } from './fixtures'; +import Favorites from '../../../javascripts/profile/components/Favorites'; +import TableLoader from '../../../javascripts/profile/components/TableLoader'; describe('Favorites', () => { const mockedProps = { @@ -12,7 +13,7 @@ describe('Favorites', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders 2 TableLoader', () => { diff --git a/superset/assets/spec/javascripts/profile/RecentActivity_spec.jsx b/superset/assets/spec/javascripts/profile/RecentActivity_spec.jsx index 8c293fb237..64a1908e80 100644 --- a/superset/assets/spec/javascripts/profile/RecentActivity_spec.jsx +++ b/superset/assets/spec/javascripts/profile/RecentActivity_spec.jsx @@ -1,10 +1,11 @@ import React from 'react'; -import RecentActivity from '../../../javascripts/profile/components/RecentActivity'; -import TableLoader from '../../../javascripts/profile/components/TableLoader'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; + import { user } from './fixtures'; +import RecentActivity from '../../../javascripts/profile/components/RecentActivity'; +import TableLoader from '../../../javascripts/profile/components/TableLoader'; describe('RecentActivity', () => { @@ -13,7 +14,7 @@ describe('RecentActivity', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders a TableLoader', () => { diff --git a/superset/assets/spec/javascripts/profile/Security_spec.jsx b/superset/assets/spec/javascripts/profile/Security_spec.jsx index acce932404..1ea7387add 100644 --- a/superset/assets/spec/javascripts/profile/Security_spec.jsx +++ b/superset/assets/spec/javascripts/profile/Security_spec.jsx @@ -1,9 +1,10 @@ import React from 'react'; -import Security from '../../../javascripts/profile/components/Security'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; + import { user, userNoPerms } from './fixtures'; +import Security from '../../../javascripts/profile/components/Security'; describe('Security', () => { @@ -12,7 +13,7 @@ describe('Security', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders 2 role labels', () => { diff --git a/superset/assets/spec/javascripts/profile/UserInfo_spec.jsx b/superset/assets/spec/javascripts/profile/UserInfo_spec.jsx index c775965fd3..360443635b 100644 --- a/superset/assets/spec/javascripts/profile/UserInfo_spec.jsx +++ b/superset/assets/spec/javascripts/profile/UserInfo_spec.jsx @@ -1,11 +1,12 @@ import React from 'react'; -import UserInfo from '../../../javascripts/profile/components/UserInfo'; import Gravatar from 'react-gravatar'; import { Panel } from 'react-bootstrap'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; + import { user } from './fixtures'; +import UserInfo from '../../../javascripts/profile/components/UserInfo'; describe('UserInfo', () => { @@ -14,7 +15,7 @@ describe('UserInfo', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders a Gravatar', () => { diff --git a/superset/assets/spec/javascripts/sqllab/AlertsWrapper_spec.jsx b/superset/assets/spec/javascripts/sqllab/AlertsWrapper_spec.jsx index 7e1f2e9945..167d24a2ff 100644 --- a/superset/assets/spec/javascripts/sqllab/AlertsWrapper_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/AlertsWrapper_spec.jsx @@ -1,8 +1,8 @@ import React from 'react'; -import AlertsWrapper from '../../../javascripts/components/AlertsWrapper'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import AlertsWrapper from '../../../javascripts/components/AlertsWrapper'; describe('AlertsWrapper', () => { it('is valid', () => { diff --git a/superset/assets/spec/javascripts/sqllab/App_spec.jsx b/superset/assets/spec/javascripts/sqllab/App_spec.jsx index 43cfc0d027..84da35c0a8 100644 --- a/superset/assets/spec/javascripts/sqllab/App_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/App_spec.jsx @@ -1,8 +1,8 @@ import React from 'react'; -import App from '../../../javascripts/SqlLab/components/App'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import App from '../../../javascripts/SqlLab/components/App'; describe('App', () => { it('is valid', () => { diff --git a/superset/assets/spec/javascripts/sqllab/ColumnElement_spec.jsx b/superset/assets/spec/javascripts/sqllab/ColumnElement_spec.jsx index 2d5a8a3f2d..236576c4cf 100644 --- a/superset/assets/spec/javascripts/sqllab/ColumnElement_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/ColumnElement_spec.jsx @@ -1,10 +1,11 @@ import React from 'react'; -import ColumnElement from '../../../javascripts/SqlLab/components/ColumnElement'; -import { mockedActions, table } from './fixtures'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import { mockedActions, table } from './fixtures'; +import ColumnElement from '../../../javascripts/SqlLab/components/ColumnElement'; + describe('ColumnElement', () => { const mockedProps = { @@ -13,7 +14,7 @@ describe('ColumnElement', () => { }; it('is valid with props', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders a proper primary key', () => { diff --git a/superset/assets/spec/javascripts/sqllab/CopyQueryTabUrl_spec.jsx b/superset/assets/spec/javascripts/sqllab/CopyQueryTabUrl_spec.jsx index 909faffe37..895e2c3b60 100644 --- a/superset/assets/spec/javascripts/sqllab/CopyQueryTabUrl_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/CopyQueryTabUrl_spec.jsx @@ -1,16 +1,17 @@ import React from 'react'; -import CopyQueryTabUrl from '../../../javascripts/SqlLab/components/CopyQueryTabUrl'; import { describe, it } from 'mocha'; import { expect } from 'chai'; import { initialState } from './fixtures'; +import CopyQueryTabUrl from '../../../javascripts/SqlLab/components/CopyQueryTabUrl'; + describe('CopyQueryTabUrl', () => { const mockedProps = { queryEditor: initialState.queryEditors[0], }; it('is valid with props', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); }); diff --git a/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx b/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx index 6fb91051f0..a800d3f060 100644 --- a/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx @@ -1,11 +1,12 @@ import React from 'react'; -import HighlightedSql from '../../../javascripts/SqlLab/components/HighlightedSql'; -import ModalTrigger from '../../../javascripts/components/ModalTrigger'; import SyntaxHighlighter from 'react-syntax-highlighter'; import { mount, shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import HighlightedSql from '../../../javascripts/SqlLab/components/HighlightedSql'; +import ModalTrigger from '../../../javascripts/components/ModalTrigger'; + describe('HighlightedSql', () => { const sql = "SELECT * FROM test WHERE something='fkldasjfklajdslfkjadlskfjkldasjfkladsjfkdjsa'"; diff --git a/superset/assets/spec/javascripts/sqllab/Link_spec.jsx b/superset/assets/spec/javascripts/sqllab/Link_spec.jsx index ca3afa5e75..083874ad55 100644 --- a/superset/assets/spec/javascripts/sqllab/Link_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/Link_spec.jsx @@ -1,9 +1,9 @@ import React from 'react'; -import Link from '../../../javascripts/SqlLab/components/Link'; import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import Link from '../../../javascripts/SqlLab/components/Link'; describe('Link', () => { const mockedProps = { @@ -15,7 +15,7 @@ describe('Link', () => { }); it('renders with props', () => { expect( - React.isValidElement(TEST) + React.isValidElement(TEST), ).to.equal(true); }); it('renders an anchor tag', () => { diff --git a/superset/assets/spec/javascripts/sqllab/QuerySearch_spec.jsx b/superset/assets/spec/javascripts/sqllab/QuerySearch_spec.jsx index a2dd71d23b..be0bbebb8d 100644 --- a/superset/assets/spec/javascripts/sqllab/QuerySearch_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/QuerySearch_spec.jsx @@ -1,19 +1,20 @@ import React from 'react'; import Select from 'react-select'; import { Button } from 'react-bootstrap'; -import QuerySearch from '../../../javascripts/SqlLab/components/QuerySearch'; import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; import sinon from 'sinon'; +import QuerySearch from '../../../javascripts/SqlLab/components/QuerySearch'; + describe('QuerySearch', () => { const mockedProps = { actions: {}, }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); const wrapper = shallow(); diff --git a/superset/assets/spec/javascripts/sqllab/QueryTable_spec.jsx b/superset/assets/spec/javascripts/sqllab/QueryTable_spec.jsx index f732e4b1bc..3400d85b9b 100644 --- a/superset/assets/spec/javascripts/sqllab/QueryTable_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/QueryTable_spec.jsx @@ -1,10 +1,11 @@ import React from 'react'; -import QueryTable from '../../../javascripts/SqlLab/components/QueryTable'; -import { queries } from './fixtures'; import { mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import { queries } from './fixtures'; +import QueryTable from '../../../javascripts/SqlLab/components/QueryTable'; + describe('QueryTable', () => { const mockedProps = { @@ -15,7 +16,7 @@ describe('QueryTable', () => { }); it('is valid with props', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders a proper table', () => { diff --git a/superset/assets/spec/javascripts/sqllab/ResultSet_spec.jsx b/superset/assets/spec/javascripts/sqllab/ResultSet_spec.jsx index c992e7bf1c..b31433af3c 100644 --- a/superset/assets/spec/javascripts/sqllab/ResultSet_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/ResultSet_spec.jsx @@ -1,11 +1,12 @@ import React from 'react'; -import ResultSet from '../../../javascripts/SqlLab/components/ResultSet'; import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; -import { queries } from './fixtures'; import { Table } from 'reactable'; +import ResultSet from '../../../javascripts/SqlLab/components/ResultSet'; +import { queries } from './fixtures'; + describe('ResultSet', () => { const mockedProps = { query: queries[0], @@ -15,7 +16,7 @@ describe('ResultSet', () => { }); it('renders with props', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders a Table', () => { diff --git a/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx b/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx index 43371e6fc4..3c8953fbc4 100644 --- a/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx @@ -1,10 +1,10 @@ import React from 'react'; -import SaveQuery from '../../../javascripts/SqlLab/components/SaveQuery'; import { Overlay, Popover, FormControl } from 'react-bootstrap'; import { shallow, mount } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import SaveQuery from '../../../javascripts/SqlLab/components/SaveQuery'; describe('SavedQuery', () => { const mockedProps = { @@ -16,12 +16,12 @@ describe('SavedQuery', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('is valid with props', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('has an Overlay and a Popover', () => { diff --git a/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx b/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx index f6acdf7cca..42fcd14c6b 100644 --- a/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx @@ -1,11 +1,12 @@ import React from 'react'; -import SqlEditorLeftBar from '../../../javascripts/SqlLab/components/SqlEditorLeftBar'; -import TableElement from '../../../javascripts/SqlLab/components/TableElement'; import { mount } from 'enzyme'; -import { table, defaultQueryEditor } from './fixtures'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import { table, defaultQueryEditor } from './fixtures'; +import SqlEditorLeftBar from '../../../javascripts/SqlLab/components/SqlEditorLeftBar'; +import TableElement from '../../../javascripts/SqlLab/components/TableElement'; + describe('SqlEditorLeftBar', () => { const mockedProps = { @@ -14,7 +15,7 @@ describe('SqlEditorLeftBar', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders a TableElement', () => { diff --git a/superset/assets/spec/javascripts/sqllab/SqlEditor_spec.jsx b/superset/assets/spec/javascripts/sqllab/SqlEditor_spec.jsx index a76094e1ca..0244c0dd50 100644 --- a/superset/assets/spec/javascripts/sqllab/SqlEditor_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/SqlEditor_spec.jsx @@ -1,10 +1,11 @@ import React from 'react'; -import SqlEditor from '../../../javascripts/SqlLab/components/SqlEditor'; -import SqlEditorLeftBar from '../../../javascripts/SqlLab/components/SqlEditorLeftBar'; import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; + import { initialState, queries, table } from './fixtures'; +import SqlEditor from '../../../javascripts/SqlLab/components/SqlEditor'; +import SqlEditorLeftBar from '../../../javascripts/SqlLab/components/SqlEditorLeftBar'; describe('SqlEditor', () => { const mockedProps = { @@ -17,7 +18,7 @@ describe('SqlEditor', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('render a SqlEditorLeftBar', () => { diff --git a/superset/assets/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx b/superset/assets/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx index 3f1a22992d..96648c9799 100644 --- a/superset/assets/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx @@ -1,10 +1,11 @@ import React from 'react'; -import { TabbedSqlEditors } from '../../../javascripts/SqlLab/components/TabbedSqlEditors'; import { Tab } from 'react-bootstrap'; import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; + import { initialState } from './fixtures'; +import { TabbedSqlEditors } from '../../../javascripts/SqlLab/components/TabbedSqlEditors'; describe('TabbedSqlEditors', () => { const mockedProps = { @@ -17,7 +18,7 @@ describe('TabbedSqlEditors', () => { }; it('is valid', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('shallow mounts', () => { diff --git a/superset/assets/spec/javascripts/sqllab/TableElement_spec.jsx b/superset/assets/spec/javascripts/sqllab/TableElement_spec.jsx index 90a11682b7..f28d43d9c3 100644 --- a/superset/assets/spec/javascripts/sqllab/TableElement_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/TableElement_spec.jsx @@ -1,12 +1,12 @@ import React from 'react'; -import Link from '../../../javascripts/SqlLab/components/Link'; -import TableElement from '../../../javascripts/SqlLab/components/TableElement'; -import ColumnElement from '../../../javascripts/SqlLab/components/ColumnElement'; -import { mockedActions, table } from './fixtures'; import { mount, shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import Link from '../../../javascripts/SqlLab/components/Link'; +import TableElement from '../../../javascripts/SqlLab/components/TableElement'; +import ColumnElement from '../../../javascripts/SqlLab/components/ColumnElement'; +import { mockedActions, table } from './fixtures'; describe('TableElement', () => { const mockedProps = { @@ -16,12 +16,12 @@ describe('TableElement', () => { }; it('renders', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders with props', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('has 2 Link elements', () => { diff --git a/superset/assets/spec/javascripts/sqllab/Timer_spec.jsx b/superset/assets/spec/javascripts/sqllab/Timer_spec.jsx index 133ecaee8b..4d62a7ae11 100644 --- a/superset/assets/spec/javascripts/sqllab/Timer_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/Timer_spec.jsx @@ -1,8 +1,9 @@ import React from 'react'; -import Timer from '../../../javascripts/components/Timer'; import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; + +import Timer from '../../../javascripts/components/Timer'; import { now } from '../../../javascripts/modules/dates'; diff --git a/superset/assets/spec/javascripts/sqllab/VisualizeModal_spec.jsx b/superset/assets/spec/javascripts/sqllab/VisualizeModal_spec.jsx index 80c26b7c16..c23529d36c 100644 --- a/superset/assets/spec/javascripts/sqllab/VisualizeModal_spec.jsx +++ b/superset/assets/spec/javascripts/sqllab/VisualizeModal_spec.jsx @@ -1,11 +1,11 @@ import React from 'react'; -import VisualizeModal from '../../../javascripts/SqlLab/components/VisualizeModal'; -import { queries } from './fixtures'; import { Modal } from 'react-bootstrap'; import { shallow } from 'enzyme'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import { queries } from './fixtures'; +import VisualizeModal from '../../../javascripts/SqlLab/components/VisualizeModal'; describe('VisualizeModal', () => { const mockedProps = { @@ -17,7 +17,7 @@ describe('VisualizeModal', () => { }); it('renders with props', () => { expect( - React.isValidElement() + React.isValidElement(), ).to.equal(true); }); it('renders a Modal', () => { diff --git a/superset/assets/spec/javascripts/sqllab/fixtures.js b/superset/assets/spec/javascripts/sqllab/fixtures.js index fb854da67d..3e3d9c38fc 100644 --- a/superset/assets/spec/javascripts/sqllab/fixtures.js +++ b/superset/assets/spec/javascripts/sqllab/fixtures.js @@ -1,5 +1,5 @@ -import * as actions from '../../../javascripts/SqlLab/actions'; import sinon from 'sinon'; +import * as actions from '../../../javascripts/SqlLab/actions'; export const mockedActions = sinon.stub(Object.assign({}, actions)); diff --git a/superset/assets/spec/javascripts/sqllab/reducers_spec.js b/superset/assets/spec/javascripts/sqllab/reducers_spec.js index 9795b85340..f777503e01 100644 --- a/superset/assets/spec/javascripts/sqllab/reducers_spec.js +++ b/superset/assets/spec/javascripts/sqllab/reducers_spec.js @@ -1,7 +1,8 @@ -import * as r from '../../../javascripts/SqlLab/reducers'; -import * as actions from '../../../javascripts/SqlLab/actions'; import { beforeEach, describe, it } from 'mocha'; import { expect } from 'chai'; + +import * as r from '../../../javascripts/SqlLab/reducers'; +import * as actions from '../../../javascripts/SqlLab/actions'; import { alert, table, initialState } from './fixtures'; describe('sqlLabReducer', () => { diff --git a/superset/assets/utils/common.js b/superset/assets/utils/common.js index 592f708c0e..2e143a12c8 100644 --- a/superset/assets/utils/common.js +++ b/superset/assets/utils/common.js @@ -1,6 +1,7 @@ /* global notify */ /* eslint global-require: 0 */ import $ from 'jquery'; + const d3 = window.d3 || require('d3'); export const EARTH_CIRCUMFERENCE_KM = 40075.16; @@ -31,7 +32,7 @@ export function rgbLuminance(r, g, b) { export function getParamFromQuery(query, param) { const vars = query.split('&'); - for (let i = 0; i < vars.length; i++) { + for (let i = 0; i < vars.length; i += 1) { const pair = vars[i].split('='); if (decodeURIComponent(pair[0]) === param) { return decodeURIComponent(pair[1]); diff --git a/superset/assets/visualizations/big_number.js b/superset/assets/visualizations/big_number.js index 9089443d4a..fbb6ab77cc 100644 --- a/superset/assets/visualizations/big_number.js +++ b/superset/assets/visualizations/big_number.js @@ -36,8 +36,8 @@ function bigNumberVis(slice, payload) { } } } - const dateExt = d3.extent(data, (d) => d[0]); - const valueExt = d3.extent(data, (d) => d[1]); + const dateExt = d3.extent(data, d => d[0]); + const valueExt = d3.extent(data, d => d[1]); const margin = 20; const scaleX = d3.time.scale.utc().domain(dateExt).range([margin, width - margin]); diff --git a/superset/assets/visualizations/cal_heatmap.js b/superset/assets/visualizations/cal_heatmap.js index e80635088b..6b34acbf1a 100644 --- a/superset/assets/visualizations/cal_heatmap.js +++ b/superset/assets/visualizations/cal_heatmap.js @@ -15,7 +15,7 @@ function calHeatmap(slice, payload) { const cal = new CalHeatMap(); const timestamps = data.timestamps; - const extents = d3.extent(Object.keys(timestamps), (key) => timestamps[key]); + const extents = d3.extent(Object.keys(timestamps), key => timestamps[key]); const step = (extents[1] - extents[0]) / 5; try { @@ -28,7 +28,7 @@ function calHeatmap(slice, payload) { subDomain: data.subdomain, range: data.range, browsing: true, - legend: [extents[0], extents[0] + step, extents[0] + step * 2, extents[0] + step * 3], + legend: [extents[0], extents[0] + step, extents[0] + (step * 2), extents[0] + (step * 3)], }); } catch (e) { slice.error(e); diff --git a/superset/assets/visualizations/directed_force.js b/superset/assets/visualizations/directed_force.js index 4c23a0f821..ce0fea1800 100644 --- a/superset/assets/visualizations/directed_force.js +++ b/superset/assets/visualizations/directed_force.js @@ -55,7 +55,7 @@ const directedForceVis = function (slice, json) { path.attr('d', function (d) { const dx = d.target.x - d.source.x; const dy = d.target.y - d.source.y; - const dr = Math.sqrt(dx * dx + dy * dy); + const dr = Math.sqrt((dx * dx) + (dy * dy)); return ( 'M' + d.source.x + ',' + diff --git a/superset/assets/visualizations/filter_box.jsx b/superset/assets/visualizations/filter_box.jsx index 34f6b7ff81..95f93ed7cd 100644 --- a/superset/assets/visualizations/filter_box.jsx +++ b/superset/assets/visualizations/filter_box.jsx @@ -1,15 +1,13 @@ // JS import d3 from 'd3'; - import React from 'react'; import ReactDOM from 'react-dom'; - import Select from 'react-select'; -import '../stylesheets/react-select/select.less'; import { Button } from 'react-bootstrap'; +import '../stylesheets/react-select/select.less'; +import { TIME_CHOICES } from './constants'; import './filter_box.css'; -import { TIME_CHOICES } from './constants.js'; const propTypes = { origSelectedValues: React.PropTypes.object, @@ -42,7 +40,7 @@ class FilterBox extends React.Component { let vals = null; if (options) { if (Array.isArray(options)) { - vals = options.map((opt) => opt.value); + vals = options.map(opt => opt.value); } else { vals = options.value; } @@ -61,7 +59,7 @@ class FilterBox extends React.Component { if (!choices.includes(val)) { choices.push(val); } - const options = choices.map((s) => ({ value: s, label: s })); + const options = choices.map(s => ({ value: s, label: s })); return (
{field.replace('__', '')} @@ -147,7 +145,7 @@ function filterBox(slice, payload) { origSelectedValues={slice.getFilters() || {}} instantFiltering={fd.instant_filtering} />, - document.getElementById(slice.containerId) + document.getElementById(slice.containerId), ); } diff --git a/superset/assets/visualizations/histogram.js b/superset/assets/visualizations/histogram.js index 91db7df7e1..16af9c44ce 100644 --- a/superset/assets/visualizations/histogram.js +++ b/superset/assets/visualizations/histogram.js @@ -1,5 +1,5 @@ -import { category21 } from '../javascripts/modules/colors'; import d3 from 'd3'; +import { category21 } from '../javascripts/modules/colors'; require('./histogram.css'); @@ -36,10 +36,10 @@ function histogram(slice, payload) { const bins = d3.layout.histogram().bins(numBins)(data); // Set the x-values - x.domain(bins.map((d) => d.x)) + x.domain(bins.map(d => d.x)) .rangeRoundBands([0, width], 0.1); // Set the y-values - y.domain([0, d3.max(bins, (d) => d.y)]) + y.domain([0, d3.max(bins, d => d.y)]) .range([height, 0]); // Create the svg value with the bins @@ -73,14 +73,14 @@ function histogram(slice, payload) { bar.exit().remove(); // Set the Height and Width for each bar bar.attr('width', x.rangeBand()) - .attr('x', (d) => x(d.x)) - .attr('y', (d) => y(d.y)) - .attr('height', (d) => y.range()[0] - y(d.y)) - .style('fill', (d) => category21(d.length)) + .attr('x', d => x(d.x)) + .attr('y', d => y(d.y)) + .attr('height', d => y.range()[0] - y(d.y)) + .style('fill', d => category21(d.length)) .order(); // Find maximum length to position the ticks on top of the bar correctly - const maxLength = d3.max(bins, (d) => d.length); + const maxLength = d3.max(bins, d => d.length); function textAboveBar(d) { return d.length / maxLength < 0.1; } @@ -100,12 +100,12 @@ function histogram(slice, payload) { } return y(d.y) - padding; }) - .attr('x', (d) => x(d.x) + (x.rangeBand() / 2)) + .attr('x', d => x(d.x) + (x.rangeBand() / 2)) .attr('text-anchor', 'middle') .attr('font-weight', 'bold') .attr('font-size', '15px') - .text((d) => formatNumber(d.y)) - .attr('fill', (d) => textAboveBar(d) ? 'black' : 'white') + .text(d => formatNumber(d.y)) + .attr('fill', d => textAboveBar(d) ? 'black' : 'white') .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); // Update the x-axis diff --git a/superset/assets/visualizations/horizon.js b/superset/assets/visualizations/horizon.js index e2f1587230..b676b95446 100644 --- a/superset/assets/visualizations/horizon.js +++ b/superset/assets/visualizations/horizon.js @@ -2,7 +2,7 @@ // Copied and modified from // https://github.com/kmandov/d3-horizon-chart import d3 from 'd3'; -require('./horizon.css'); +import './horizon.css'; const horizonChart = function () { let colors = [ @@ -49,7 +49,7 @@ const horizonChart = function () { context.imageSmoothingEnabled = false; // update the y scale, based on the data extents - const ext = extent || d3.extent(data, (d) => d.y); + const ext = extent || d3.extent(data, d => d.y); const max = Math.max(-ext[0], ext[1]); y.domain([0, max]); @@ -61,8 +61,8 @@ const horizonChart = function () { // context.translate(0.5, 0.5); // the data frame currently being shown: - const startIndex = ~~ Math.max(0, -(offsetX / step)); - const endIndex = ~~ Math.min(data.length, startIndex + width / step); + const startIndex = Math.floor(Math.max(0, -(offsetX / step))); + const endIndex = Math.floor(Math.min(data.length, startIndex + (width / step))); // skip drawing if there's no data to be drawn if (startIndex > data.length) { @@ -75,7 +75,7 @@ const horizonChart = function () { // draw positive bands let value; let bExtents; - for (let b = 0; b < bands; b++) { + for (let b = 0; b < bands; b += 1) { context.fillStyle = colors[bands + b]; // Adjust the range based on the current band index. @@ -200,12 +200,12 @@ function horizonViz(slice, payload) { payload.data.forEach(function (d) { allValues = allValues.concat(d.values); }); - extent = d3.extent(allValues, (d) => d.y); + extent = d3.extent(allValues, d => d.y); } else if (fd.horizon_color_scale === 'change') { payload.data.forEach(function (series) { const t0y = series.values[0].y; // value at time 0 - series.values = series.values.map((d) => - Object.assign({}, d, { y: d.y - t0y }) + series.values = series.values.map(d => + Object.assign({}, d, { y: d.y - t0y }), ); }); } diff --git a/superset/assets/visualizations/mapbox.jsx b/superset/assets/visualizations/mapbox.jsx index eceed728ac..8c9fc22d62 100644 --- a/superset/assets/visualizations/mapbox.jsx +++ b/superset/assets/visualizations/mapbox.jsx @@ -1,10 +1,9 @@ /* eslint-disable no-param-reassign */ - import d3 from 'd3'; import React from 'react'; import ReactDOM from 'react-dom'; import MapGL from 'react-map-gl'; -import ScatterPlotOverlay from 'react-map-gl/dist/overlays/scatterplot.react.js'; +import ScatterPlotOverlay from 'react-map-gl/dist/overlays/scatterplot.react'; import Immutable from 'immutable'; import supercluster from 'supercluster'; import ViewportMercator from 'viewport-mercator-project'; @@ -109,7 +108,7 @@ class ScatterPlotGlowOverlay extends ScatterPlotOverlay { const fontHeight = d3.round(scaledRadius * 0.5, 1); const gradient = ctx.createRadialGradient( pixelRounded[0], pixelRounded[1], scaledRadius, - pixelRounded[0], pixelRounded[1], 0 + pixelRounded[0], pixelRounded[1], 0, ); gradient.addColorStop(1, 'rgba(' + rgb[1] + ', ' + rgb[2] + ', ' + rgb[3] + ', 0.8)'); @@ -277,7 +276,6 @@ function mapbox(slice, json) { const div = d3.select(slice.selector); const DEFAULT_POINT_RADIUS = 60; const DEFAULT_MAX_ZOOM = 16; - let clusterer; // Validate mapbox color const rgb = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(json.data.color); @@ -314,7 +312,7 @@ function mapbox(slice, json) { }; } - clusterer = supercluster({ + const clusterer = supercluster({ radius: json.data.clusteringRadius, maxZoom: DEFAULT_MAX_ZOOM, metricKey: 'metric', @@ -333,7 +331,7 @@ function mapbox(slice, json) { pointRadius={DEFAULT_POINT_RADIUS} aggregatorName={aggName} />, - div.node() + div.node(), ); } diff --git a/superset/assets/visualizations/nvd3_vis.js b/superset/assets/visualizations/nvd3_vis.js index 7a90afb9fa..c76269f76b 100644 --- a/superset/assets/visualizations/nvd3_vis.js +++ b/superset/assets/visualizations/nvd3_vis.js @@ -1,14 +1,16 @@ // JS import $ from 'jquery'; +import throttle from 'lodash.throttle'; +import d3 from 'd3'; + import { category21 } from '../javascripts/modules/colors'; import { timeFormatFactory, formatDate } from '../javascripts/modules/dates'; import { customizeToolTip } from '../javascripts/modules/utils'; -import throttle from 'lodash.throttle'; -const d3 = require('d3'); -const nv = require('nvd3'); import { TIME_STAMP_OPTIONS } from '../javascripts/explorev2/stores/controls'; +const nv = require('nvd3'); + // CSS require('../node_modules/nvd3/build/nv.d3.min.css'); require('./nvd3_vis.css'); @@ -68,7 +70,7 @@ function getMaxLabelSize(container, axisClass, widthOrHeight) { // axis class = .nv-x // x axis on time series line chart const labelEls = container.find(`.${axisClass} .tick text`); const labelDimensions = labelEls.map(i => labelEls[i].getBoundingClientRect()[widthOrHeight]); - const max = Math.max.apply(Math, labelDimensions); + const max = Math.max(...labelDimensions); return max; } @@ -185,7 +187,7 @@ function nvd3Vis(slice, payload) { if (a.x < b.x) return -1; if (a.x > b.x) return 1; return 0; - } + }, ); }); } @@ -346,7 +348,7 @@ function nvd3Vis(slice, payload) { } } if (vizType !== 'bullet') { - chart.color((d) => category21(d[colorKey])); + chart.color(d => category21(d[colorKey])); } if (fd.x_axis_label && fd.x_axis_label !== '' && chart.xAxis) { diff --git a/superset/assets/visualizations/parallel_coordinates.js b/superset/assets/visualizations/parallel_coordinates.js index f0c4554f91..facbe00276 100644 --- a/superset/assets/visualizations/parallel_coordinates.js +++ b/superset/assets/visualizations/parallel_coordinates.js @@ -1,10 +1,11 @@ -const $ = require('jquery'); import d3 from 'd3'; +import '../vendor/parallel_coordinates/d3.parcoords.css'; +import './parallel_coordinates.css'; + d3.parcoords = require('../vendor/parallel_coordinates/d3.parcoords.js'); d3.divgrid = require('../vendor/parallel_coordinates/divgrid.js'); -require('../vendor/parallel_coordinates/d3.parcoords.css'); -require('./parallel_coordinates.css'); +const $ = require('jquery'); function parallelCoordVis(slice, payload) { $('#code').attr('rows', '15'); diff --git a/superset/assets/visualizations/pivot_table.js b/superset/assets/visualizations/pivot_table.js index ec9958f793..a3b6bc9278 100644 --- a/superset/assets/visualizations/pivot_table.js +++ b/superset/assets/visualizations/pivot_table.js @@ -1,11 +1,13 @@ +import 'datatables.net'; +import dt from 'datatables.net-bs'; + import { fixDataTableBodyHeight } from '../javascripts/modules/utils'; + const $ = require('jquery'); require('./pivot_table.css'); - require('datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css'); -import 'datatables.net'; -import dt from 'datatables.net-bs'; + dt(window, $); module.exports = function (slice, payload) { diff --git a/superset/assets/visualizations/sankey.js b/superset/assets/visualizations/sankey.js index 0a015e78b1..80e8980b8e 100644 --- a/superset/assets/visualizations/sankey.js +++ b/superset/assets/visualizations/sankey.js @@ -1,10 +1,10 @@ /* eslint-disable no-param-reassign */ -import { category21 } from '../javascripts/modules/colors'; import d3 from 'd3'; +import { category21 } from '../javascripts/modules/colors'; +import './sankey.css'; d3.sankey = require('d3-sankey').sankey; -require('./sankey.css'); function sankeyVis(slice, payload) { const div = d3.select(slice.selector); @@ -100,7 +100,7 @@ function sankeyVis(slice, payload) { .append('path') .attr('class', 'link') .attr('d', path) - .style('stroke-width', (d) => Math.max(1, d.dy)) + .style('stroke-width', d => Math.max(1, d.dy)) .sort((a, b) => b.dy - a.dy) .on('mouseover', onmouseover) .on('mouseout', onmouseout); @@ -109,7 +109,7 @@ function sankeyVis(slice, payload) { d3.select(this) .attr( 'transform', - `translate(${d.x},${(d.y = Math.max(0, Math.min(height - d.dy, d3.event.y)))})` + `translate(${d.x},${(d.y = Math.max(0, Math.min(height - d.dy, d3.event.y)))})`, ); sankey.relayout(); link.attr('d', path); @@ -130,7 +130,7 @@ function sankeyVis(slice, payload) { .on('dragstart', function () { this.parentNode.appendChild(this); }) - .on('drag', dragmove) + .on('drag', dragmove), ); const minRectHeight = 5; node.append('rect') diff --git a/superset/assets/visualizations/sunburst.js b/superset/assets/visualizations/sunburst.js index 2c240ebafa..34143c0be3 100644 --- a/superset/assets/visualizations/sunburst.js +++ b/superset/assets/visualizations/sunburst.js @@ -34,8 +34,8 @@ function sunburstVis(slice, payload) { .value(function (d) { return d.m1; }); const arc = d3.svg.arc() - .startAngle((d) => d.x) - .endAngle((d) => d.x + d.dx) + .startAngle(d => d.x) + .endAngle(d => d.x + d.dx) .innerRadius(function (d) { return Math.sqrt(d.y); }) @@ -345,7 +345,7 @@ function sunburstVis(slice, payload) { if (fd.metric !== fd.secondary_metric) { colorByCategory = false; - ext = d3.extent(nodes, (d) => d.m2 / d.m1); + ext = d3.extent(nodes, d => d.m2 / d.m1); colorScale = d3.scale.linear() .domain([ext[0], ext[0] + ((ext[1] - ext[0]) / 2), ext[1]]) .range(['#00D1C1', 'white', '#FFB400']); @@ -360,7 +360,7 @@ function sunburstVis(slice, payload) { }) .attr('d', arc) .attr('fill-rule', 'evenodd') - .style('fill', (d) => colorByCategory ? category21(d.name) : colorScale(d.m2 / d.m1)) + .style('fill', d => colorByCategory ? category21(d.name) : colorScale(d.m2 / d.m1)) .style('opacity', 1) .on('mouseenter', mouseenter); diff --git a/superset/assets/visualizations/table.js b/superset/assets/visualizations/table.js index b8b4efcb61..eae3edc751 100644 --- a/superset/assets/visualizations/table.js +++ b/superset/assets/visualizations/table.js @@ -1,13 +1,14 @@ import d3 from 'd3'; -import { fixDataTableBodyHeight } from '../javascripts/modules/utils'; -import { timeFormatFactory, formatDate } from '../javascripts/modules/dates'; - -require('./table.css'); -const $ = require('jquery'); - -require('datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css'); +import 'datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css'; import 'datatables.net'; import dt from 'datatables.net-bs'; + +import { fixDataTableBodyHeight } from '../javascripts/modules/utils'; +import { timeFormatFactory, formatDate } from '../javascripts/modules/dates'; +import './table.css'; + +const $ = require('jquery'); + dt(window, $); function tableVis(slice, payload) { @@ -24,13 +25,13 @@ function tableVis(slice, payload) { function col(c) { const arr = []; - for (let i = 0; i < data.records.length; i++) { + for (let i = 0; i < data.records.length; i += 1) { arr.push(data.records[i][c]); } return arr; } const maxes = {}; - for (let i = 0; i < metrics.length; i++) { + for (let i = 0; i < metrics.length; i += 1) { maxes[metrics[i]] = d3.max(col(metrics[i])); } @@ -63,14 +64,14 @@ function tableVis(slice, payload) { .enter() .append('tr') .selectAll('td') - .data(row => data.columns.map(c => { + .data(row => data.columns.map((c) => { const val = row[c]; let html; const isMetric = metrics.indexOf(c) >= 0; if (c === 'timestamp') { html = timestampFormatter(val); } - if (typeof(val) === 'string') { + if (typeof (val) === 'string') { html = ``; } if (isMetric) { diff --git a/superset/assets/visualizations/treemap.js b/superset/assets/visualizations/treemap.js index 77479a94c8..1e025935e6 100644 --- a/superset/assets/visualizations/treemap.js +++ b/superset/assets/visualizations/treemap.js @@ -44,7 +44,7 @@ function treemap(slice, payload) { const grandparent = svg.append('g') .attr('class', 'grandparent') - .attr('transform', 'translate(0,' + (margin.top + navBarBuffer / 2) + ')'); + .attr('transform', 'translate(0,' + (margin.top + (navBarBuffer / 2)) + ')'); grandparent.append('rect') .attr('width', width) @@ -52,12 +52,13 @@ function treemap(slice, payload) { grandparent.append('text') .attr('x', width / 2) - .attr('y', navBarHeight / 2 + navBarTitleSize / 2) + .attr('y', (navBarHeight / 2) + (navBarTitleSize / 2)) .style('font-size', navBarTitleSize + 'px') .style('text-anchor', 'middle'); const initialize = function (root) { - root.x = root.y = 0; + root.x = 0; + root.y = 0; root.dx = width; root.dy = height; root.depth = 0; @@ -86,8 +87,8 @@ function treemap(slice, payload) { if (d._children) { treemap.nodes({ _children: d._children }); d._children.forEach(function (c) { - c.x = d.x + c.x * d.dx; - c.y = d.y + c.y * d.dy; + c.x = d.x + (c.x * d.dx); + c.y = d.y + (c.y * d.dy); c.dx *= d.dx; c.dy *= d.dy; c.parent = d; @@ -229,7 +230,7 @@ function treemap(slice, payload) { div.selectAll('*').remove(); const width = slice.width(); const height = slice.height() / payload.data.length; - for (let i = 0, l = payload.data.length; i < l; i ++) { + for (let i = 0, l = payload.data.length; i < l; i += 1) { _draw(payload.data[i], width, height, slice.formData); } } diff --git a/superset/assets/visualizations/word_cloud.js b/superset/assets/visualizations/word_cloud.js index 311a0f29c6..5d445c7db7 100644 --- a/superset/assets/visualizations/word_cloud.js +++ b/superset/assets/visualizations/word_cloud.js @@ -14,11 +14,11 @@ function wordCloudChart(slice, payload) { const rotation = fd.rotation; let fRotation; if (rotation === 'square') { - fRotation = () => ~~(Math.random() * 2) * 90; + fRotation = () => Math.floor((Math.random() * 2) * 90); } else if (rotation === 'flat') { fRotation = () => 0; } else { - fRotation = () => (~~(Math.random() * 6) - 3) * 30; + fRotation = () => Math.floor(((Math.random() * 6) - 3) * 30); } const size = [slice.width(), slice.height()]; @@ -40,12 +40,12 @@ function wordCloudChart(slice, payload) { .data(words) .enter() .append('text') - .style('font-size', (d) => d.size + 'px') + .style('font-size', d => d.size + 'px') .style('font-family', 'Impact') - .style('fill', (d) => category21(d.text)) + .style('fill', d => category21(d.text)) .attr('text-anchor', 'middle') - .attr('transform', (d) => `translate(${d.x}, ${d.y}) rotate(${d.rotate})`) - .text((d) => d.text); + .attr('transform', d => `translate(${d.x}, ${d.y}) rotate(${d.rotate})`) + .text(d => d.text); } const layout = cloudLayout() @@ -54,7 +54,7 @@ function wordCloudChart(slice, payload) { .padding(5) .rotate(fRotation) .font('serif') - .fontSize((d) => scale(d.size)) + .fontSize(d => scale(d.size)) .on('end', draw); layout.start(); diff --git a/superset/assets/visualizations/world_map.js b/superset/assets/visualizations/world_map.js index d014a6ff86..a9ab714a5e 100644 --- a/superset/assets/visualizations/world_map.js +++ b/superset/assets/visualizations/world_map.js @@ -13,7 +13,7 @@ function worldMapChart(slice, payload) { div.selectAll('*').remove(); const fd = slice.formData; // Ignore XXX's to get better normalization - let data = payload.data.filter((d) => (d.country && d.country !== 'XXX')); + let data = payload.data.filter(d => (d.country && d.country !== 'XXX')); const ext = d3.extent(data, function (d) { return d.m1; @@ -29,7 +29,7 @@ function worldMapChart(slice, payload) { .domain([ext[0], ext[1]]) .range(['#FFF', 'black']); - data = data.map((d) => Object.assign({}, d, { + data = data.map(d => Object.assign({}, d, { radius: radiusScale(d.m2), fillColor: colorScale(d.m1), })); diff --git a/superset/assets/webpack.config.js b/superset/assets/webpack.config.js index 1d4b973f9f..ed71afdac2 100644 --- a/superset/assets/webpack.config.js +++ b/superset/assets/webpack.config.js @@ -26,7 +26,6 @@ const config = { }, resolve: { extensions: [ - '', '.js', '.jsx', ], @@ -43,12 +42,12 @@ const config = { loaders: [ { test: /datatables\.net.*/, - loader: 'imports?define=>false', + loader: 'imports-loader?define=>false', }, { test: /\.jsx?$/, exclude: APP_DIR + '/node_modules', - loader: 'babel', + loader: 'babel-loader', query: { presets: [ 'airbnb', @@ -61,7 +60,7 @@ const config = { { test: /\.react\.js$/, include: APP_DIR + '/node_modules/react-map-gl/src/overlays', - loader: 'babel', + loader: 'babel-loader', }, /* for require('*.css') */ { @@ -95,7 +94,7 @@ const config = { { test: /\.less$/, include: APP_DIR, - loader: 'style!css!less', + loader: 'style-loader!css-loader!less-loader', }, /* for mapbox */ { @@ -108,11 +107,6 @@ const config = { loader: 'transform/cacheable?brfs', }, ], - postLoaders: [{ - include: /node_modules\/mapbox-gl/, - loader: 'transform', - query: 'brfs', - }], }, externals: { cheerio: 'window', diff --git a/superset/connectors/druid/models.py b/superset/connectors/druid/models.py index f03af3d4c9..f4587fa1d9 100644 --- a/superset/connectors/druid/models.py +++ b/superset/connectors/druid/models.py @@ -1,3 +1,4 @@ +# pylint: disable=invalid-unary-operand-type from collections import OrderedDict import json import logging