diff --git a/.babel_cache/.gitkeep b/.babel_cache/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/.gitignore b/.gitignore index 041c862dafb25..0455fd53b9aab 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ profiles.clj /resources/frontend_client/app/dist/ /node_modules/ /.js_hint_output/ +/.babel_cache diff --git a/Gulpfile.js b/Gulpfile.js index 26fe35a6e304e..13e347a79bc4d 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -3,14 +3,16 @@ var gulp = require('gulp'), concat = require('gulp-concat'), react = require('gulp-react'), - myth = require('gulp-myth'); + myth = require('gulp-myth'), + webpack = require('gulp-webpack'); var basePath = 'resources/frontend_client/app/'; var SRC = { css: [basePath + 'css/**/*.css', basePath + 'components/**/*.css'], jsx: [basePath + 'query_builder/*.js'], - appJS: [basePath + '**/*.js', '!' + basePath + 'bower_components/**/*.js', '!' + basePath + 'dist/*.js', '!' + basePath + 'query_builder/*.js', '!' + basePath + '/test/**/*.js'] + appJS: [basePath + '**/*.js', '!' + basePath + 'bower_components/**/*.js', '!' + basePath + 'dist/*.js', '!' + basePath + 'query_builder/*.js', '!' + basePath + '/test/**/*.js'], + js: [basePath + '**/*.js', '!' + basePath + 'bower_components/**/*.js', '!' + basePath + 'dist/*.js', '!' + basePath + '/test/**/*.js'] }; var DEST = { @@ -60,3 +62,14 @@ gulp.task('watch', function(){ gulp.task('build', ['css', 'jsx', 'build-js']); gulp.task('default', ['build', 'watch']); + +gulp.task("webpack", function() { + return gulp.src(SRC.js) + .pipe(webpack(require("./webpack.config"))) + .pipe(gulp.dest(DEST.js)); +}); + +gulp.task("webpack-watch", function() { + gulp.watch(SRC.js, ["webpack"]); + gulp.watch(SRC.css, ['css']); +}); diff --git a/package.json b/package.json index 1ae2d45295baf..17e15c4c2a02a 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,31 @@ { - "name": "corvus", - "private": true, - "version": "0.0.0", - "description": "Expa Analytics", - "repository": "https://github.com/expa/data", - "license": "private", - "engines": { - "node": "0.10.25" - }, - "dependencies": { - "bower": "1.3.12", - "gulp": "^3.8.8", - "gulp-concat": "^2.4.0", - "gulp-myth": "^1.0.1", - "gulp-jsx": "^0.7.0", - "gulp-react": "^2.0.0" - }, - "devDependencies": { - "http-server": "^0.6.1", - "jsxhint": "0.13.3", - "karma": "~0.10", - "karma-junit-reporter": "^0.2.2", - "protractor": "~0.20.1", - "shelljs": "^0.2.6" - }, - "scripts": { - "postinstall": "./node_modules/bower/bin/bower install --allow-root --config.interactive=false" - } + "name": "corvus", + "private": true, + "version": "0.0.0", + "description": "Expa Analytics", + "repository": "https://github.com/expa/data", + "license": "private", + "engines": { + "node": "0.10.25" + }, + "dependencies": { + "bower": "1.3.12", + "gulp": "^3.8.8", + "gulp-concat": "^2.4.0", + "gulp-jsx": "^0.7.0", + "gulp-myth": "^1.0.1", + "gulp-react": "^2.0.0", + "react": "^0.12.2" + }, + "devDependencies": { + "http-server": "^0.6.1", + "jsxhint": "0.13.3", + "karma": "~0.10", + "karma-junit-reporter": "^0.2.2", + "protractor": "~0.20.1", + "shelljs": "^0.2.6" + }, + "scripts": { + "postinstall": "./node_modules/bower/bin/bower install --allow-root --config.interactive=false" + } } diff --git a/resources/frontend_client/app/card/card.charting.js b/resources/frontend_client/app/card/card.charting.js index 665281431c741..f35dcf6eb1d8b 100644 --- a/resources/frontend_client/app/card/card.charting.js +++ b/resources/frontend_client/app/card/card.charting.js @@ -565,7 +565,7 @@ function GeoHeatmapChartRenderer(id, card, result) { }); } -var CardRenderer = { +export var CardRenderer = { /// get the size render settings for card if applicable _getSizeSettings: function(cardOrDimension) { if (typeof cardOrDimension === "object") { diff --git a/resources/frontend_client/app/card/card.controllers.js b/resources/frontend_client/app/card/card.controllers.js index 2d44aff654d1d..e6909bf262e27 100644 --- a/resources/frontend_client/app/card/card.controllers.js +++ b/resources/frontend_client/app/card/card.controllers.js @@ -1,5 +1,10 @@ 'use strict'; -/*global _, document, confirm, QueryHeader, NativeQueryEditor, GuiQueryEditor, ResultQueryEditor, QueryVisualization*/ +/*global _, document, confirm*/ + +import GuiQueryEditor from '../query_builder/gui_query_editor.react'; +import NativeQueryEditor from '../query_builder/native_query_editor.react'; +import QueryHeader from '../query_builder/header.react'; +import QueryVisualization from '../query_builder/visualization.react'; // Card Controllers var CardControllers = angular.module('corvus.card.controllers', []); diff --git a/resources/frontend_client/app/query_builder/action_button.react.js b/resources/frontend_client/app/query_builder/action_button.react.js index f8df8975be106..63c30d69a537d 100644 --- a/resources/frontend_client/app/query_builder/action_button.react.js +++ b/resources/frontend_client/app/query_builder/action_button.react.js @@ -1,7 +1,11 @@ 'use strict'; -/*global cx, setTimeout, clearTimeout, OnClickOutside, SelectionModule, Icon*/ +/*global setTimeout, clearTimeout, OnClickOutside*/ -var ActionButton = React.createClass({ +import Icon from './icon.react'; + +var cx = React.addons.classSet; + +export default React.createClass({ displayName: 'ActionButton', propTypes: { actionFn: React.PropTypes.func.isRequired diff --git a/resources/frontend_client/app/query_builder/add_to_dashboard.react.js b/resources/frontend_client/app/query_builder/add_to_dashboard.react.js index a278fb754bff8..9bbb36fc57f8a 100644 --- a/resources/frontend_client/app/query_builder/add_to_dashboard.react.js +++ b/resources/frontend_client/app/query_builder/add_to_dashboard.react.js @@ -1,7 +1,13 @@ 'use strict'; -/*global cx, OnClickOutside, Popover, AddToDashboardPopover, SelectionModule, Icon, ReactCSSTransitionGroup*/ +/*global OnClickOutside*/ -var AddToDashboard = React.createClass({ +import AddToDashboardPopover from './add_to_dashboard_popover.react'; +import Icon from './icon.react'; +import Popover from './popover.react'; + +var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; + +export default React.createClass({ displayName: 'AddToDashboard', propTypes: { card: React.PropTypes.object.isRequired, diff --git a/resources/frontend_client/app/query_builder/add_to_dashboard_popover.react.js b/resources/frontend_client/app/query_builder/add_to_dashboard_popover.react.js index 928a25a130cea..546a366aa1f44 100644 --- a/resources/frontend_client/app/query_builder/add_to_dashboard_popover.react.js +++ b/resources/frontend_client/app/query_builder/add_to_dashboard_popover.react.js @@ -1,7 +1,13 @@ 'use strict'; -/*global cx, ReactCSSTransitionGroup, OnClickOutside, FormField, SelectionModule, Icon */ +/*global OnClickOutside*/ -var AddToDashboardPopover = React.createClass({ +import FormField from './form_field.react'; +import Icon from './icon.react'; + +var cx = React.addons.classSet; +var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; + +export default React.createClass({ displayName: 'AddToDashboardPopover', propTypes: { card: React.PropTypes.object.isRequired, diff --git a/resources/frontend_client/app/query_builder/aggregation_widget.react.js b/resources/frontend_client/app/query_builder/aggregation_widget.react.js index 04f9a76f94c51..6cdd2cb319a39 100644 --- a/resources/frontend_client/app/query_builder/aggregation_widget.react.js +++ b/resources/frontend_client/app/query_builder/aggregation_widget.react.js @@ -1,7 +1,9 @@ 'use strict'; -/*global _, DateFilter, SelectionModule, Icon */ +/*global _ */ -var AggregationWidget = React.createClass({ +import SelectionModule from './selection_module.react'; + +export default React.createClass({ displayName: 'AggregationWidget', propTypes: { aggregation: React.PropTypes.array.isRequired, diff --git a/resources/frontend_client/app/query_builder/database_selector.react.js b/resources/frontend_client/app/query_builder/database_selector.react.js index 8509c7629b1f0..656dceed37b1b 100644 --- a/resources/frontend_client/app/query_builder/database_selector.react.js +++ b/resources/frontend_client/app/query_builder/database_selector.react.js @@ -1,7 +1,8 @@ 'use strict'; -/*global SelectionModule*/ -var DatabaseSelector = React.createClass({ +import SelectionModule from './selection_module.react'; + +export default React.createClass({ displayName: 'DatabaseSelector', propTypes: { currentDatabaseId: React.PropTypes.number.isRequired, diff --git a/resources/frontend_client/app/query_builder/date_filter.react.js b/resources/frontend_client/app/query_builder/date_filter.react.js index e0da7715a8753..2949d3411cfae 100644 --- a/resources/frontend_client/app/query_builder/date_filter.react.js +++ b/resources/frontend_client/app/query_builder/date_filter.react.js @@ -1,7 +1,7 @@ 'use strict'; /*global moment, DatePicker*/ -var DateFilter = React.createClass({ +export default React.createClass({ displayName: 'DateFilter', propTypes: { date: React.PropTypes.string, diff --git a/resources/frontend_client/app/query_builder/filter_widget.react.js b/resources/frontend_client/app/query_builder/filter_widget.react.js index c8e9c077a1fa7..0caccd461660d 100644 --- a/resources/frontend_client/app/query_builder/filter_widget.react.js +++ b/resources/frontend_client/app/query_builder/filter_widget.react.js @@ -1,7 +1,10 @@ 'use strict'; -/*global DateFilter, SelectionModule, Icon */ -var FilterWidget = React.createClass({ +import DateFilter from './date_filter.react'; +import Icon from './icon.react'; +import SelectionModule from './selection_module.react'; + +export default React.createClass({ displayName: 'FilterWidget', propTypes: { filter: React.PropTypes.array.isRequired, diff --git a/resources/frontend_client/app/query_builder/form_field.react.js b/resources/frontend_client/app/query_builder/form_field.react.js index 7020380f7d9cf..4bfb4d137f85b 100644 --- a/resources/frontend_client/app/query_builder/form_field.react.js +++ b/resources/frontend_client/app/query_builder/form_field.react.js @@ -1,7 +1,10 @@ 'use strict'; -/*global cx, OnClickOutside, SelectionModule*/ +/*global OnClickOutside*/ -var FormField = React.createClass({ +var cx = React.addons.classSet; + + +export default React.createClass({ displayName: 'FormField', propTypes: { fieldName: React.PropTypes.string.isRequired, diff --git a/resources/frontend_client/app/query_builder/gui_query_editor.react.js b/resources/frontend_client/app/query_builder/gui_query_editor.react.js index 623745a775dcb..d6877ad6be66d 100644 --- a/resources/frontend_client/app/query_builder/gui_query_editor.react.js +++ b/resources/frontend_client/app/query_builder/gui_query_editor.react.js @@ -1,9 +1,19 @@ 'use strict'; -/*global _, cx, AggregationWidget, FilterWidget, LimitWidget, SortWidget, RunButton, SelectionModule, DatabaseSelector, Icon*/ - +/*global _*/ + +import AggregationWidget from './aggregation_widget.react'; +import DatabaseSelector from './database_selector.react'; +import FilterWidget from './filter_widget.react'; +import Icon from './icon.react'; +import LimitWidget from './limit_widget.react'; +import RunButton from './run_button.react'; +import SelectionModule from './selection_module.react'; +import SortWidget from './sort_widget.react'; + +var cx = React.addons.classSet; var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; -var GuiQueryEditor = React.createClass({ +export default React.createClass({ displayName: 'GuiQueryEditor', propTypes: { databases: React.PropTypes.array.isRequired, diff --git a/resources/frontend_client/app/query_builder/header.react.js b/resources/frontend_client/app/query_builder/header.react.js index 6e33db8b1832d..d1344143dc888 100644 --- a/resources/frontend_client/app/query_builder/header.react.js +++ b/resources/frontend_client/app/query_builder/header.react.js @@ -1,10 +1,17 @@ 'use strict'; -/*global setTimeout, clearTimeout, Saver, ActionButton, Popover, Icon, QueryModeToggle, AddToDashboard*/ +/*global setTimeout, clearTimeout*/ -var cx = React.addons.classSet, - ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; +import ActionButton from './action_button.react'; +import AddToDashboard from './add_to_dashboard.react'; +import Icon from './icon.react'; +import Popover from './popover.react'; +import QueryModeToggle from './query_mode_toggle.react'; +import Saver from './saver.react'; -var QueryHeader = React.createClass({ +var cx = React.addons.classSet; +var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; + +export default React.createClass({ displayName: 'QueryHeader', propTypes: { card: React.PropTypes.object.isRequired, diff --git a/resources/frontend_client/app/query_builder/icon.react.js b/resources/frontend_client/app/query_builder/icon.react.js index d94d63977200b..0fb7cf1128fb4 100644 --- a/resources/frontend_client/app/query_builder/icon.react.js +++ b/resources/frontend_client/app/query_builder/icon.react.js @@ -1,7 +1,7 @@ 'use strict'; /* global ICON_PATHS */ -var Icon = React.createClass({ +export default React.createClass({ displayName: 'Icon', getDefaultProps: function () { return { diff --git a/resources/frontend_client/app/query_builder/limit_widget.react.js b/resources/frontend_client/app/query_builder/limit_widget.react.js index 0c15923f65800..d5988296fc471 100644 --- a/resources/frontend_client/app/query_builder/limit_widget.react.js +++ b/resources/frontend_client/app/query_builder/limit_widget.react.js @@ -1,7 +1,9 @@ 'use strict'; -/*global DateFilter, SelectionModule, Icon */ -var LimitWidget = React.createClass({ +import Icon from './icon.react'; +import SelectionModule from './selection_module.react'; + +export default React.createClass({ displayName: 'LimitWidget', propTypes: { limit: React.PropTypes.number, diff --git a/resources/frontend_client/app/query_builder/native_query_editor.react.js b/resources/frontend_client/app/query_builder/native_query_editor.react.js index d35eb3bb95ea4..fe1d8f7044d98 100644 --- a/resources/frontend_client/app/query_builder/native_query_editor.react.js +++ b/resources/frontend_client/app/query_builder/native_query_editor.react.js @@ -1,7 +1,10 @@ 'use strict'; -/*global ace, RunButton, SelectionModule, DatabaseSelector*/ +/*global ace*/ -var NativeQueryEditor = React.createClass({ +import RunButton from './run_button.react'; +import DatabaseSelector from './database_selector.react'; + +export default React.createClass({ displayName: 'NativeQueryEditor', propTypes: { databases: React.PropTypes.array.isRequired, diff --git a/resources/frontend_client/app/query_builder/popover.react.js b/resources/frontend_client/app/query_builder/popover.react.js index 50dcd34c869f7..f299b87c1d2e8 100644 --- a/resources/frontend_client/app/query_builder/popover.react.js +++ b/resources/frontend_client/app/query_builder/popover.react.js @@ -1,7 +1,7 @@ 'use strict'; -/*global document, cx, Tether*/ +/*global document, Tether*/ -var Popover = React.createClass({ +export default React.createClass({ displayName: 'Popover', componentWillMount: function() { @@ -72,4 +72,4 @@ var Popover = React.createClass({ render: function() { return ; } -}); \ No newline at end of file +}); diff --git a/resources/frontend_client/app/query_builder/popover_content.react.js b/resources/frontend_client/app/query_builder/popover_content.react.js index fdd21f52359d6..56d46f1d72477 100644 --- a/resources/frontend_client/app/query_builder/popover_content.react.js +++ b/resources/frontend_client/app/query_builder/popover_content.react.js @@ -1,5 +1,4 @@ 'use strict'; -/*global cx, OnClickOutside, Popover, AddToDashboardPopover, SelectionModule, AddToDashIcon, ReactCSSTransitionGroup*/ // this feels a little silly, but we have this component ONLY so that we can add the OnClickOutside functionality on an // arbitrary set of html content. I wish we could do that more easily diff --git a/resources/frontend_client/app/query_builder/popover_with_trigger.react.js b/resources/frontend_client/app/query_builder/popover_with_trigger.react.js index b4935c4b3e9c6..862062d10f390 100644 --- a/resources/frontend_client/app/query_builder/popover_with_trigger.react.js +++ b/resources/frontend_client/app/query_builder/popover_with_trigger.react.js @@ -1,5 +1,9 @@ 'use strict'; -/*global document, cx, PopoverContent, Tether*/ +/*global document, Tether*/ + +import PopoverContent from './popover_content.react' + +var cx = React.addons.classSet; var PopoverWithTrigger = React.createClass({ displayName: 'PopoverWithTrigger', @@ -99,4 +103,4 @@ var PopoverWithTrigger = React.createClass({ ); } -}); \ No newline at end of file +}); diff --git a/resources/frontend_client/app/query_builder/query_mode_toggle.react.js b/resources/frontend_client/app/query_builder/query_mode_toggle.react.js index 4314f8644e37e..87dc929b50a29 100644 --- a/resources/frontend_client/app/query_builder/query_mode_toggle.react.js +++ b/resources/frontend_client/app/query_builder/query_mode_toggle.react.js @@ -1,7 +1,11 @@ 'use strict'; -/*global cx, OnClickOutside, SelectionModule*/ +/*global OnClickOutside*/ -var QueryModeToggle = React.createClass({ +import SelectionModule from './selection_module.react'; + +var cx = React.addons.classSet; + +export default React.createClass({ displayName: 'QueryModeToggle', propTypes: { currentQueryMode: React.PropTypes.string.isRequired, diff --git a/resources/frontend_client/app/query_builder/run_button.react.js b/resources/frontend_client/app/query_builder/run_button.react.js index 6b7a2e2e3345c..1fcfd7e49af7e 100644 --- a/resources/frontend_client/app/query_builder/run_button.react.js +++ b/resources/frontend_client/app/query_builder/run_button.react.js @@ -1,6 +1,6 @@ 'use strict'; -var RunButton = React.createClass({ +export default React.createClass({ displayName: 'RunButton', propTypes: { canRun: React.PropTypes.bool.isRequired, diff --git a/resources/frontend_client/app/query_builder/saver.react.js b/resources/frontend_client/app/query_builder/saver.react.js index e88d5890feaa5..ef0908cdbc426 100644 --- a/resources/frontend_client/app/query_builder/saver.react.js +++ b/resources/frontend_client/app/query_builder/saver.react.js @@ -1,7 +1,11 @@ 'use strict'; -/*global cx, OnClickOutside, FormField, SelectionModule*/ +/*global OnClickOutside*/ -var Saver = React.createClass({ +import FormField from './form_field.react'; + +var cx = React.addons.classSet; + +export default React.createClass({ displayName: 'Saver', propTypes: { card: React.PropTypes.object.isRequired, diff --git a/resources/frontend_client/app/query_builder/search_bar.react.js b/resources/frontend_client/app/query_builder/search_bar.react.js index 94249d84cbe78..ca9c126475417 100644 --- a/resources/frontend_client/app/query_builder/search_bar.react.js +++ b/resources/frontend_client/app/query_builder/search_bar.react.js @@ -1,6 +1,6 @@ 'use strict'; -var SearchBar = React.createClass({ +export default React.createClass({ displayName: 'SearchBar', propTypes: { filter: React.PropTypes.string.isRequired, diff --git a/resources/frontend_client/app/query_builder/selection_module.react.js b/resources/frontend_client/app/query_builder/selection_module.react.js index b84e4be1cd9de..37f88a7284192 100644 --- a/resources/frontend_client/app/query_builder/selection_module.react.js +++ b/resources/frontend_client/app/query_builder/selection_module.react.js @@ -1,7 +1,12 @@ 'use strict'; -/*global cx, OnClickOutside, SearchBar, Icon*/ +/*global OnClickOutside*/ -var SelectionModule = React.createClass({ +import Icon from './icon.react'; +import SearchBar from './search_bar.react'; + +var cx = React.addons.classSet; + +export default React.createClass({ displayName:'SelectionModule', propTypes: { action: React.PropTypes.func.isRequired, diff --git a/resources/frontend_client/app/query_builder/sort_widget.react.js b/resources/frontend_client/app/query_builder/sort_widget.react.js index 4466ab05119c9..543d3dddd80b9 100644 --- a/resources/frontend_client/app/query_builder/sort_widget.react.js +++ b/resources/frontend_client/app/query_builder/sort_widget.react.js @@ -1,7 +1,10 @@ 'use strict'; -/*global DateFilter, SelectionModule, Icon */ -var SortWidget = React.createClass({ +import DateFilter from './date_filter.react'; +import Icon from './icon.react'; +import SelectionModule from './search_bar.react'; + +export default React.createClass({ displayName: 'SortWidget', propTypes: { sort: React.PropTypes.array.isRequired, diff --git a/resources/frontend_client/app/query_builder/visualization.react.js b/resources/frontend_client/app/query_builder/visualization.react.js index a2e8a77a3bc6e..7645a2977d866 100644 --- a/resources/frontend_client/app/query_builder/visualization.react.js +++ b/resources/frontend_client/app/query_builder/visualization.react.js @@ -1,9 +1,14 @@ 'use strict'; -/*global cx, CardRenderer, PopoverWithTrigger, QueryVisualizationTable, QueryVisualizationChart*/ +import { CardRenderer } from '../card/card.charting'; +import PopoverWithTrigger from './popover_with_trigger.react'; +import QueryVisualizationTable from './visualization_table.react'; +import QueryVisualizationChart from './visualization_chart.react'; + +var cx = React.addons.classSet; var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; -var QueryVisualization = React.createClass({ +export default React.createClass({ displayName: 'QueryVisualization', propTypes: { visualizationSettingsApi: React.PropTypes.object.isRequired, diff --git a/resources/frontend_client/app/query_builder/visualization_chart.react.js b/resources/frontend_client/app/query_builder/visualization_chart.react.js index 456f113dfefd6..6b88f34483c3d 100644 --- a/resources/frontend_client/app/query_builder/visualization_chart.react.js +++ b/resources/frontend_client/app/query_builder/visualization_chart.react.js @@ -1,7 +1,8 @@ 'use strict'; -/*global CardRenderer*/ -var QueryVisualizationChart = React.createClass({ +import { CardRenderer } from '../card/card.charting'; + +export default React.createClass({ displayName: 'QueryVisualizationChart', propTypes: { visualizationSettingsApi: React.PropTypes.object.isRequired, diff --git a/resources/frontend_client/app/query_builder/visualization_table.react.js b/resources/frontend_client/app/query_builder/visualization_table.react.js index 4be1dda0b45f1..ad1a6cb7eb010 100644 --- a/resources/frontend_client/app/query_builder/visualization_table.react.js +++ b/resources/frontend_client/app/query_builder/visualization_table.react.js @@ -1,7 +1,6 @@ 'use strict'; -/*global */ -var QueryVisualizationTable = React.createClass({ +export default React.createClass({ displayName: 'QueryVisualizationTable', propTypes: { data: React.PropTypes.object diff --git a/resources/frontend_client/index.html b/resources/frontend_client/index.html index f3993006c8efb..715beb192f232 100644 --- a/resources/frontend_client/index.html +++ b/resources/frontend_client/index.html @@ -101,7 +101,7 @@ - + @@ -138,8 +138,9 @@ - - + + +