Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

Cherry-picks: Several bug fixes and react HMR #114

Merged
merged 8 commits into from
Sep 18, 2018
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
2 changes: 1 addition & 1 deletion superset/assets/.babelrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"presets" : ["airbnb", "react", "env"],
"plugins": ["syntax-dynamic-import"],
"plugins": ["syntax-dynamic-import", "react-hot-loader/babel"]
}
3 changes: 2 additions & 1 deletion superset/assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"react-dnd-html5-backend": "^2.5.4",
"react-dom": "^15.6.2",
"react-gravatar": "^2.6.1",
"react-hot-loader": "^4.3.6",
"react-map-gl": "^3.0.4",
"react-markdown": "^3.3.0",
"react-redux": "^5.0.2",
Expand All @@ -113,7 +114,7 @@
"react-syntax-highlighter": "^5.7.0",
"react-virtualized": "9.3.0",
"react-virtualized-select": "2.4.0",
"reactable": "^0.14.1",
"reactable": "^1.1.0",
"redux": "^3.5.2",
"redux-localstorage": "^0.4.1",
"redux-thunk": "^2.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import { shallow } from 'enzyme';
import { describe, it } from 'mocha';
import { expect } from 'chai';

import App from '../../../src/welcome/App';
import Welcome from '../../../src/welcome/Welcome';

describe('App', () => {
describe('Welcome', () => {
const mockedProps = {};
it('is valid', () => {
expect(
React.isValidElement(<App {...mockedProps} />),
React.isValidElement(<Welcome {...mockedProps} />),
).to.equal(true);
});
it('renders 4 Tab, Panel, and Row components', () => {
const wrapper = shallow(<App {...mockedProps} />);
const wrapper = shallow(<Welcome {...mockedProps} />);
expect(wrapper.find(Tab)).to.have.length(3);
expect(wrapper.find(Panel)).to.have.length(3);
expect(wrapper.find(Row)).to.have.length(3);
Expand Down
51 changes: 51 additions & 0 deletions superset/assets/src/SqlLab/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { createStore, compose, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import thunkMiddleware from 'redux-thunk';
import { hot } from 'react-hot-loader';

import getInitialState from './getInitialState';
import rootReducer from './reducers';
import { initEnhancer } from '../reduxUtils';
import { initJQueryAjax } from '../modules/utils';
import App from './components/App';
import { appSetup } from '../common';

import './main.less';
import '../../stylesheets/reactable-pagination.css';
import '../components/FilterableTable/FilterableTableStyles.css';

appSetup();
initJQueryAjax();

const appContainer = document.getElementById('app');
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
const state = getInitialState(bootstrapData);

const store = createStore(
rootReducer,
state,
compose(
applyMiddleware(thunkMiddleware),
initEnhancer(),
),
);

// Highlight the navbar menu
const menus = document.querySelectorAll('.nav.navbar-nav li.dropdown');
const sqlLabMenu = Array.prototype.slice.apply(menus)
.find(element => element.innerText.trim() === 'SQL Lab');
if (sqlLabMenu) {
const classes = sqlLabMenu.getAttribute('class');
if (classes.indexOf('active') === -1) {
sqlLabMenu.setAttribute('class', `${classes} active`);
}
}

const Application = () => (
<Provider store={store}>
<App />
</Provider>
);

export default hot(module)(Application);
46 changes: 5 additions & 41 deletions superset/assets/src/SqlLab/index.jsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,8 @@
import React from 'react';
import { render } from 'react-dom';
import { createStore, compose, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import thunkMiddleware from 'redux-thunk';
import ReactDOM from 'react-dom';
import App from './App';

import getInitialState from './getInitialState';
import rootReducer from './reducers';
import { initEnhancer } from '../reduxUtils';
import { initJQueryAjax } from '../modules/utils';
import App from './components/App';
import { appSetup } from '../common';

import './main.less';
import '../../stylesheets/reactable-pagination.css';
import '../components/FilterableTable/FilterableTableStyles.css';

appSetup();
initJQueryAjax();

const appContainer = document.getElementById('app');
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
const state = getInitialState(bootstrapData);

const store = createStore(
rootReducer,
state,
compose(
applyMiddleware(thunkMiddleware),
initEnhancer(),
),
);

// jquery hack to highlight the navbar menu
$('a:contains("SQL Lab")')
.parent()
.addClass('active');

render(
<Provider store={store}>
<App />
</Provider>,
appContainer,
ReactDOM.render(
<App />,
document.getElementById('app'),
);
15 changes: 15 additions & 0 deletions superset/assets/src/addSlice/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { hot } from 'react-hot-loader';
import { appSetup } from '../common';
import AddSliceContainer from './AddSliceContainer';

appSetup();

const addSliceContainer = document.getElementById('js-add-slice-container');
const bootstrapData = JSON.parse(addSliceContainer.getAttribute('data-bootstrap'));

const App = () => (
<AddSliceContainer datasources={bootstrapData.datasources} />
);

export default hot(module)(App);
12 changes: 3 additions & 9 deletions superset/assets/src/addSlice/index.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { appSetup } from '../common';
import AddSliceContainer from './AddSliceContainer';

appSetup();

const addSliceContainer = document.getElementById('js-add-slice-container');
const bootstrapData = JSON.parse(addSliceContainer.getAttribute('data-bootstrap'));
import App from './App';

ReactDOM.render(
<AddSliceContainer datasources={bootstrapData.datasources} />,
addSliceContainer,
<App />,
document.getElementById('js-add-slice-container'),
);
36 changes: 36 additions & 0 deletions superset/assets/src/dashboard/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import thunk from 'redux-thunk';
import { createStore, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import { hot } from 'react-hot-loader';

import { initEnhancer } from '../reduxUtils';
import { appSetup } from '../common';
import { initJQueryAjax } from '../modules/utils';
import DashboardContainer from './containers/Dashboard';
import getInitialState from './reducers/getInitialState';
import rootReducer from './reducers/index';

appSetup();
initJQueryAjax();

const appContainer = document.getElementById('app');
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
const initState = getInitialState(bootstrapData);

const store = createStore(
rootReducer,
initState,
compose(
applyMiddleware(thunk),
initEnhancer(false),
),
);

const App = () => (
<Provider store={store}>
<DashboardContainer />
</Provider>
);

export default hot(module)(App);
34 changes: 2 additions & 32 deletions superset/assets/src/dashboard/index.jsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import App from './App';

import { initEnhancer } from '../reduxUtils';
import { appSetup } from '../common';
import { initJQueryAjax } from '../modules/utils';
import DashboardContainer from './containers/Dashboard';
import getInitialState from './reducers/getInitialState';
import rootReducer from './reducers/index';

appSetup();
initJQueryAjax();

const appContainer = document.getElementById('app');
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
const initState = getInitialState(bootstrapData);

const store = createStore(
rootReducer,
initState,
compose(
applyMiddleware(thunk),
initEnhancer(false),
),
);

ReactDOM.render(
<Provider store={store}>
<DashboardContainer />
</Provider>,
appContainer,
);
ReactDOM.render(<App />, document.getElementById('app'));
92 changes: 92 additions & 0 deletions superset/assets/src/explore/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* eslint no-undef: 2 */
import React from 'react';
import { hot } from 'react-hot-loader';
import { createStore, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';

import shortid from 'shortid';
import { now } from '../modules/dates';
import { initEnhancer } from '../reduxUtils';
import { getChartKey } from './exploreUtils';
import ToastPresenter from '../messageToasts/containers/ToastPresenter';
import { getControlsState, getFormDataFromControls } from './store';
import { initJQueryAjax } from '../modules/utils';
import ExploreViewContainer from './components/ExploreViewContainer';
import rootReducer from './reducers/index';
import getToastsFromPyFlashMessages from '../messageToasts/utils/getToastsFromPyFlashMessages';

import { appSetup } from '../common';
import './main.css';
import '../../stylesheets/reactable-pagination.css';

appSetup();
initJQueryAjax();

const exploreViewContainer = document.getElementById('app');
const bootstrapData = JSON.parse(exploreViewContainer.getAttribute('data-bootstrap'));
const controls = getControlsState(bootstrapData, bootstrapData.form_data);
const rawFormData = { ...bootstrapData.form_data };

delete bootstrapData.form_data;
delete bootstrapData.common.locale;
delete bootstrapData.common.language_pack;

// Initial state
const bootstrappedState = {
...bootstrapData,
rawFormData,
controls,
filterColumnOpts: [],
isDatasourceMetaLoading: false,
isStarred: false,
};
const slice = bootstrappedState.slice;
const sliceFormData = slice
? getFormDataFromControls(getControlsState(bootstrapData, slice.form_data))
: null;
const chartKey = getChartKey(bootstrappedState);
const initState = {
charts: {
[chartKey]: {
id: chartKey,
chartAlert: null,
chartStatus: 'loading',
chartUpdateEndTime: null,
chartUpdateStartTime: now(),
latestQueryFormData: getFormDataFromControls(controls),
sliceFormData,
queryRequest: null,
queryResponse: null,
triggerQuery: true,
lastRendered: 0,
},
},
saveModal: {
dashboards: [],
saveModalAlert: null,
},
explore: bootstrappedState,
impressionId: shortid.generate(),
messageToasts: getToastsFromPyFlashMessages((bootstrapData.common || {}).flash_messages || []),
};

const store = createStore(
rootReducer,
initState,
compose(
applyMiddleware(thunk),
initEnhancer(false),
),
);

const App = () => (
<Provider store={store}>
<div>
<ExploreViewContainer />
<ToastPresenter />
</div>
</Provider>
);

export default hot(module)(App);
Loading