diff --git a/caravel/assets/javascripts/SqlLab/index.jsx b/caravel/assets/javascripts/SqlLab/index.jsx
index 6c9bd25e8e810..e0a7fa18c0c2b 100644
--- a/caravel/assets/javascripts/SqlLab/index.jsx
+++ b/caravel/assets/javascripts/SqlLab/index.jsx
@@ -10,20 +10,14 @@ import TabbedSqlEditors from './components/TabbedSqlEditors';
import QueryAutoRefresh from './components/QueryAutoRefresh';
import Alerts from './components/Alerts';
-import { bindActionCreators, compose, createStore } from 'redux';
+import { bindActionCreators, createStore } from 'redux';
import { connect, Provider } from 'react-redux';
import { initialState, sqlLabReducer } from './reducers';
-import persistState from 'redux-localstorage';
+import { enhancer } from '../../utils/common';
require('./main.css');
-let enhancer = compose(persistState());
-if (process.env.NODE_ENV === 'dev') {
- enhancer = compose(
- persistState(), window.devToolsExtension && window.devToolsExtension()
- );
-}
let store = createStore(sqlLabReducer, initialState, enhancer);
// jquery hack to highlight the navbar menu
diff --git a/caravel/assets/javascripts/SqlLab/reducers.js b/caravel/assets/javascripts/SqlLab/reducers.js
index dcdeac9c47428..5dce1877a4f0b 100644
--- a/caravel/assets/javascripts/SqlLab/reducers.js
+++ b/caravel/assets/javascripts/SqlLab/reducers.js
@@ -1,6 +1,9 @@
import shortid from 'shortid';
import * as actions from './actions';
import { now } from '../modules/dates';
+import
+ { addToArr, alterInArr, removeFromArr, addToObject, alterInObject }
+ from '../../utils/reducerUtils';
const defaultQueryEditor = {
id: shortid.generate(),
@@ -23,58 +26,6 @@ export const initialState = {
queriesLastUpdate: 0,
};
-function addToObject(state, arrKey, obj) {
- const newObject = Object.assign({}, state[arrKey]);
- const copiedObject = Object.assign({}, obj);
-
- if (!copiedObject.id) {
- copiedObject.id = shortid.generate();
- }
- newObject[copiedObject.id] = copiedObject;
- return Object.assign({}, state, { [arrKey]: newObject });
-}
-
-function alterInObject(state, arrKey, obj, alterations) {
- const newObject = Object.assign({}, state[arrKey]);
- newObject[obj.id] = (Object.assign({}, newObject[obj.id], alterations));
- return Object.assign({}, state, { [arrKey]: newObject });
-}
-
-function alterInArr(state, arrKey, obj, alterations) {
- // Finds an item in an array in the state and replaces it with a
- // new object with an altered property
- const idKey = 'id';
- const newArr = [];
- state[arrKey].forEach((arrItem) => {
- if (obj[idKey] === arrItem[idKey]) {
- newArr.push(Object.assign({}, arrItem, alterations));
- } else {
- newArr.push(arrItem);
- }
- });
- return Object.assign({}, state, { [arrKey]: newArr });
-}
-
-function removeFromArr(state, arrKey, obj, idKey = 'id') {
- const newArr = [];
- state[arrKey].forEach((arrItem) => {
- if (!(obj[idKey] === arrItem[idKey])) {
- newArr.push(arrItem);
- }
- });
- return Object.assign({}, state, { [arrKey]: newArr });
-}
-
-function addToArr(state, arrKey, obj) {
- const newObj = Object.assign({}, obj);
- if (!newObj.id) {
- newObj.id = shortid.generate();
- }
- const newState = {};
- newState[arrKey] = [...state[arrKey], newObj];
- return Object.assign({}, state, newState);
-}
-
export const sqlLabReducer = function (state, action) {
const actionHandlers = {
[actions.ADD_QUERY_EDITOR]() {
@@ -115,7 +66,8 @@ export const sqlLabReducer = function (state, action) {
[actions.START_QUERY]() {
const newState = addToObject(state, 'queries', action.query);
const sqlEditor = { id: action.query.sqlEditorId };
- return alterInArr(newState, 'queryEditors', sqlEditor, { latestQueryId: action.query.id });
+ return alterInArr(
+ newState, 'queryEditors', sqlEditor, { latestQueryId: action.query.id });
},
[actions.STOP_QUERY]() {
return alterInObject(state, 'queries', action.query, { state: 'stopped' });
@@ -156,7 +108,8 @@ export const sqlLabReducer = function (state, action) {
return alterInArr(state, 'queryEditors', action.queryEditor, { sql: action.sql });
},
[actions.QUERY_EDITOR_SET_AUTORUN]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { autorun: action.autorun });
+ return alterInArr(
+ state, 'queryEditors', action.queryEditor, { autorun: action.autorun });
},
[actions.ADD_WORKSPACE_QUERY]() {
return addToArr(state, 'workspaceQueries', action.query);
diff --git a/caravel/assets/javascripts/explorev2/actions/exploreActions.js b/caravel/assets/javascripts/explorev2/actions/exploreActions.js
new file mode 100644
index 0000000000000..52aeeb278b0a7
--- /dev/null
+++ b/caravel/assets/javascripts/explorev2/actions/exploreActions.js
@@ -0,0 +1,71 @@
+export const SET_DATASOURCE = 'SET_DATASOURCE';
+export const SET_VIZTYPE = 'SET_VIZTYPE';
+export const SET_TIME_FILTER = 'SET_TIME_FILTER';
+export const SET_GROUPBY = 'SET_GROUPBY';
+export const ADD_COLUMN = 'ADD_COLUMN';
+export const REMOVE_COLUMN = 'REMOVE_COLUMN';
+export const ADD_ORDERING = 'ADD_ORDERING';
+export const REMOVE_ORDERING = 'REMOVE_ORDERING';
+export const SET_TIME_STAMP = 'SET_TIME_STAMP';
+export const SET_ROW_LIMIT = 'SET_ROW_LIMIT';
+export const TOGGLE_SEARCHBOX = 'TOGGLE_SEARCHBOX';
+export const SET_SQL = 'SET_SQL';
+export const ADD_FILTER = 'ADD_FILTER';
+export const SET_FILTER = 'SET_FILTER';
+export const REMOVE_FILTER = 'REMOVE_FILTER';
+
+export function setDatasource(datasourceId) {
+ return { type: SET_DATASOURCE, datasourceId };
+}
+
+export function setVizType(vizType) {
+ return { type: SET_VIZTYPE, vizType };
+}
+
+export function setTimeFilter(timeFilter) {
+ return { type: SET_TIME_FILTER, timeFilter };
+}
+
+export function setGroupBy(groupBy) {
+ return { type: SET_GROUPBY, groupBy };
+}
+
+export function addColumn(column) {
+ return { type: ADD_COLUMN, column };
+}
+
+export function removeColumn(column) {
+ return { type: REMOVE_COLUMN, column };
+}
+
+export function addOrdering(ordering) {
+ return { type: ADD_ORDERING, ordering };
+}
+
+export function removeOrdering(ordering) {
+ return { type: REMOVE_ORDERING, ordering };
+}
+
+export function setTimeStamp(timeStampFormat) {
+ return { type: SET_TIME_STAMP, timeStampFormat };
+}
+
+export function setRowLimit(rowLimit) {
+ return { type: SET_ROW_LIMIT, rowLimit };
+}
+
+export function toggleSearchBox(searchBox) {
+ return { type: TOGGLE_SEARCHBOX, searchBox };
+}
+
+export function setSQL(sql) {
+ return { type: SET_SQL, sql };
+}
+
+export function addFilter(filter) {
+ return { type: ADD_FILTER, filter };
+}
+
+export function removeFilter(filter) {
+ return { type: REMOVE_FILTER, filter };
+}
diff --git a/caravel/assets/javascripts/explorev2/components/ChartContainer.jsx b/caravel/assets/javascripts/explorev2/components/ChartContainer.jsx
index 9915264dc7a53..3666e923a201a 100644
--- a/caravel/assets/javascripts/explorev2/components/ChartContainer.jsx
+++ b/caravel/assets/javascripts/explorev2/components/ChartContainer.jsx
@@ -1,12 +1,11 @@
import React from 'react';
import { Panel } from 'react-bootstrap';
-export default class ChartContainer extends React.Component {
- render() {
- return (
-