Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created store and reducers #1108

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions caravel/assets/javascripts/SqlLab/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wonder if this should go in a reduxUtils.js file rather than just common utils...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry merged in too early ;( I'll fix this in my next refactor_explore PR

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np, just a thought for another PR 👌


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
Expand Down
61 changes: 7 additions & 54 deletions caravel/assets/javascripts/SqlLab/reducers.js
Original file line number Diff line number Diff line change
@@ -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(),
Expand All @@ -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]() {
Expand Down Expand Up @@ -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' });
Expand Down Expand Up @@ -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);
Expand Down
71 changes: 71 additions & 0 deletions caravel/assets/javascripts/explorev2/actions/exploreActions.js
Original file line number Diff line number Diff line change
@@ -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 };
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from 'react';
import { Panel } from 'react-bootstrap';

export default class ChartContainer extends React.Component {
render() {
return (
<Panel header="Chart title">
chart goes here
</Panel>
);
}
}
const ChartContainer = function () {
return (
<Panel header="Chart title">
chart goes here
</Panel>
);
};
export default ChartContainer;
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from 'react';
import { Panel } from 'react-bootstrap';

export default class ControlPanelsContainer extends React.Component {
render() {
return (
<Panel>
control panels here
</Panel>
);
}
}
const ControlPanelsContainer = function () {
return (
<Panel>
control panels here
</Panel>
);
};
export default ControlPanelsContainer;
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ import ChartContainer from './ChartContainer';
import ControlPanelsContainer from './ControlPanelsContainer';
import QueryAndSaveButtons from './QueryAndSaveButtons';

export default class ExploreViewContainer extends React.Component {
render() {
return (
<div className="container-fluid">
<div className="row">
<div className="col-sm-3">
<QueryAndSaveButtons
canAdd="True"
onQuery={() => { console.log('clicked query') }}
/>
<br /><br />
<ControlPanelsContainer />
</div>
<div className="col-sm-9">
<ChartContainer />
</div>
const ExploreViewContainer = function () {
return (
<div className="container-fluid">
<div className="row">
<div className="col-sm-3">
<QueryAndSaveButtons
canAdd="True"
onQuery={() => { console.log('clicked query'); }}
/>
<br /><br />
<ControlPanelsContainer />
</div>
<div className="col-sm-9">
<ChartContainer />
</div>
</div>
);
}
}
</div>
);
};

export default ExploreViewContainer;
22 changes: 19 additions & 3 deletions caravel/assets/javascripts/explorev2/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,28 @@ import React from 'react';
import ReactDOM from 'react-dom';
import ExploreViewContainer from './components/ExploreViewContainer';

import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { enhancer } from '../../utils/common';

import { initialState } from './stores/store';

const exploreViewContainer = document.getElementById('js-explore-view-container');
const bootstrapData = exploreViewContainer.getAttribute('data-bootstrap');

import { exploreReducer } from './reducers/exploreReducer';

const bootstrappedState = Object.assign(initialState, {
datasources: bootstrapData.datasources,
viz: bootstrapData.viz,
});
const store = createStore(exploreReducer, bootstrappedState, enhancer);

ReactDOM.render(
<ExploreViewContainer
data={bootstrapData}
/>,
<Provider store={store}>
<ExploreViewContainer
data={bootstrapData}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any data from the server in bootstrapData that can be used to bootstrap the initial state? i think we get vizType and datasourceID

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so above we probably want to do

const bootstrappedState = Object.assign(initialState, {
  datasourceId: bootstrapData.datasourceId,
  vizType: bootstrapData.vizType
});

const store = createStore(exploreReducer, bootstrappedState, enhancer);

/>
</Provider>,
exploreViewContainer
);
65 changes: 65 additions & 0 deletions caravel/assets/javascripts/explorev2/reducers/exploreReducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as actions from '../actions/exploreActions';
import { addToArr, removeFromArr } from '../../../utils/reducerUtils';

export const exploreReducer = function (state, action) {
const actionHandlers = {
[actions.SET_DATASOURCE]() {
return Object.assign({}, state, { datasourceId: action.datasourceId });
},
[actions.SET_VIZTYPE]() {
return Object.assign({}, state, { vizType: action.vizType });
},
[actions.SET_TIME_FILTER]() {
return Object.assign({}, state, { timeFilter: action.timeFilter });
},
[actions.SET_GROUPBY]() {
return Object.assign({}, state, { groupBy: action.groupBy });
},
[actions.ADD_COLUMN]() {
return Object.assign({}, state, { columns: [...state.columns, action.column] });
},
[actions.REMOVE_COLUMN]() {
const newColumns = [];
state.columns.forEach((c) => {
if (c !== action.column) {
newColumns.push(c);
}
});
return Object.assign({}, state, { columns: newColumns });
},
[actions.ADD_ORDERING]() {
return Object.assign({}, state, { orderings: [...state.orderings, action.ordering] });
},
[actions.REMOVE_ORDERING]() {
const newOrderings = [];
state.orderings.forEach((o) => {
if (o !== action.ordering) {
newOrderings.push(o);
}
});
return Object.assign({}, state, { orderings: newOrderings });
},
[actions.SET_TIME_STAMP]() {
return Object.assign({}, state, { timeStampFormat: action.timeStampFormat });
},
[actions.SET_ROW_LIMIT]() {
return Object.assign({}, state, { rowLimit: action.rowLimit });
},
[actions.TOGGLE_SEARCHBOX]() {
return Object.assign({}, state, { searchBox: action.searchBox });
},
[actions.SET_SQL]() {
return Object.assign({}, state, { SQL: action.sql });
},
[actions.ADD_FILTER]() {
return addToArr(state, 'filters', action.filter);
},
[actions.REMOVE_FILTER]() {
return removeFromArr(state, 'filters', action.filter);
},
};
if (action.type in actionHandlers) {
return actionHandlers[action.type]();
}
return state;
};
Loading