mirror of https://github.com/apache/superset.git
get rid of global `notify` (#5355)
* [toasts] get rid of notify globals, refactor messageToasts for use by entire app * [remove notify] use arrow func in ajax call * fix lint + tests * actually fix tests from messageToast refactor * add 'test:one' npm script * debugger * [toasts] convert bootstrap flash messages to toasts in explore + sqllab * [toasts][tests] import from right file
This commit is contained in:
parent
f9352af80e
commit
19ac6e1231
|
@ -9,6 +9,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"test": "mocha --require ignore-styles --compilers js:babel-core/register --require spec/helpers/browser.js 'spec/**/*_spec.*'",
|
||||
"test:one": "mocha --require ignore-styles --compilers js:babel-core/register --require spec/helpers/browser.js",
|
||||
"cover": "babel-node node_modules/.bin/babel-istanbul cover _mocha -- --require ignore-styles spec/helpers/browser.js 'spec/**/*_spec.*'",
|
||||
"dev": "NODE_ENV=dev webpack --watch --colors --progress --debug --output-pathinfo --devtool eval-cheap-source-map",
|
||||
"dev-slow": "NODE_ENV=dev webpack --watch --colors --progress --debug --output-pathinfo --devtool inline-source-map",
|
||||
|
@ -89,7 +90,6 @@
|
|||
"react-ace": "^5.10.0",
|
||||
"react-addons-css-transition-group": "^15.6.0",
|
||||
"react-addons-shallow-compare": "^15.4.2",
|
||||
"react-alert": "^2.3.0",
|
||||
"react-bootstrap": "^0.31.5",
|
||||
"react-bootstrap-slider": "2.1.5",
|
||||
"react-bootstrap-table": "^4.3.1",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import { expect } from 'chai';
|
||||
import { describe, it } from 'mocha';
|
||||
import { shallow } from 'enzyme';
|
||||
|
@ -13,11 +14,14 @@ describe('URLShortLinkButton', () => {
|
|||
emailContent: 'mock content',
|
||||
};
|
||||
|
||||
it('renders', () => {
|
||||
expect(React.isValidElement(<URLShortLinkButton {...defaultProps} />)).to.equal(true);
|
||||
});
|
||||
function setup() {
|
||||
const mockStore = configureStore([]);
|
||||
const store = mockStore({});
|
||||
return shallow(<URLShortLinkButton {...defaultProps} />, { context: { store } }).dive();
|
||||
}
|
||||
|
||||
it('renders OverlayTrigger', () => {
|
||||
const wrapper = shallow(<URLShortLinkButton {...defaultProps} />);
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find(OverlayTrigger)).have.length(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,7 +23,7 @@ import {
|
|||
} from '../../../../src/dashboard/actions/dashboardLayout';
|
||||
|
||||
import { setUnsavedChanges } from '../../../../src/dashboard/actions/dashboardState';
|
||||
import { addInfoToast } from '../../../../src/dashboard/actions/messageToasts';
|
||||
import { addInfoToast } from '../../../../src/messageToasts/actions';
|
||||
|
||||
import {
|
||||
DASHBOARD_GRID_TYPE,
|
||||
|
|
|
@ -2,7 +2,7 @@ import chartQueries from './mockChartQueries';
|
|||
import { dashboardLayout } from './mockDashboardLayout';
|
||||
import dashboardInfo from './mockDashboardInfo';
|
||||
import dashboardState from './mockDashboardState';
|
||||
import messageToasts from './mockMessageToasts';
|
||||
import messageToasts from '../../messageToasts/mockMessageToasts';
|
||||
import datasources from './mockDatasource';
|
||||
import sliceEntities from './mockSliceEntities';
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import { expect } from 'chai';
|
||||
import { describe, it, beforeEach } from 'mocha';
|
||||
import { describe, it } from 'mocha';
|
||||
import { shallow } from 'enzyme';
|
||||
import { Modal } from 'react-bootstrap';
|
||||
import DatasourceControl from '../../../../src/explore/components/controls/DatasourceControl';
|
||||
|
@ -26,13 +27,14 @@ const defaultProps = {
|
|||
};
|
||||
|
||||
describe('DatasourceControl', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<DatasourceControl {...defaultProps} />);
|
||||
});
|
||||
function setup() {
|
||||
const mockStore = configureStore([]);
|
||||
const store = mockStore({});
|
||||
return shallow(<DatasourceControl {...defaultProps} />, { context: { store } }).dive();
|
||||
}
|
||||
|
||||
it('renders a Modal', () => {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find(Modal)).to.have.lengthOf(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* eslint-disable no-unused-expressions */
|
||||
import React from 'react';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import { expect } from 'chai';
|
||||
import { describe, it } from 'mocha';
|
||||
import { shallow } from 'enzyme';
|
||||
|
@ -10,18 +10,25 @@ import ColumnOption from '../../../../src/components/ColumnOption';
|
|||
import AggregateOption from '../../../../src/explore/components/AggregateOption';
|
||||
|
||||
describe('MetricDefinitionOption', () => {
|
||||
const mockStore = configureStore([]);
|
||||
const store = mockStore({});
|
||||
|
||||
function setup(props) {
|
||||
return shallow(<MetricDefinitionOption {...props} />, { context: { store } }).dive();
|
||||
}
|
||||
|
||||
it('renders a MetricOption given a saved metric', () => {
|
||||
const wrapper = shallow(<MetricDefinitionOption option={{ metric_name: 'a_saved_metric' }} />);
|
||||
const wrapper = setup({ option: { metric_name: 'a_saved_metric' } });
|
||||
expect(wrapper.find(MetricOption)).to.have.lengthOf(1);
|
||||
});
|
||||
|
||||
it('renders a ColumnOption given a column', () => {
|
||||
const wrapper = shallow(<MetricDefinitionOption option={{ column_name: 'a_column' }} />);
|
||||
const wrapper = setup({ option: { column_name: 'a_column' } });
|
||||
expect(wrapper.find(ColumnOption)).to.have.lengthOf(1);
|
||||
});
|
||||
|
||||
it('renders an AggregateOption given an aggregate metric', () => {
|
||||
const wrapper = shallow(<MetricDefinitionOption option={{ aggregate_name: 'an_aggregate' }} />);
|
||||
const wrapper = setup({ option: { aggregate_name: 'an_aggregate' } });
|
||||
expect(wrapper.find(AggregateOption)).to.have.lengthOf(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"extends": "prettier",
|
||||
"plugins": ["prettier"],
|
||||
"rules": {
|
||||
"prefer-template": 2,
|
||||
"new-cap": 2,
|
||||
"no-restricted-syntax": 2,
|
||||
"guard-for-in": 2,
|
||||
"prefer-arrow-callback": 2,
|
||||
"func-names": 2,
|
||||
"react/jsx-no-bind": 2,
|
||||
"no-confusing-arrow": 2,
|
||||
"jsx-a11y/no-static-element-interactions": 2,
|
||||
"jsx-a11y/anchor-has-content": 2,
|
||||
"react/require-default-props": 2,
|
||||
"no-plusplus": 2,
|
||||
"no-mixed-operators": 0,
|
||||
"no-continue": 2,
|
||||
"no-bitwise": 2,
|
||||
"no-undef": 2,
|
||||
"no-multi-assign": 2,
|
||||
"no-restricted-properties": 2,
|
||||
"no-prototype-builtins": 2,
|
||||
"jsx-a11y/href-no-hash": 2,
|
||||
"class-methods-use-this": 2,
|
||||
"import/no-named-as-default": 2,
|
||||
"import/prefer-default-export": 2,
|
||||
"react/no-unescaped-entities": 2,
|
||||
"react/no-string-refs": 2,
|
||||
"react/jsx-indent": 0,
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
|
@ -3,9 +3,9 @@ import { shallow } from 'enzyme';
|
|||
import { describe, it } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
import mockMessageToasts from '../fixtures/mockMessageToasts';
|
||||
import Toast from '../../../../src/dashboard/components/Toast';
|
||||
import ToastPresenter from '../../../../src/dashboard/components/ToastPresenter';
|
||||
import mockMessageToasts from '../mockMessageToasts';
|
||||
import Toast from '../../../../src/messageToasts/components/Toast';
|
||||
import ToastPresenter from '../../../../src/messageToasts/components/ToastPresenter';
|
||||
|
||||
describe('ToastPresenter', () => {
|
||||
const props = {
|
|
@ -4,8 +4,8 @@ import { shallow } from 'enzyme';
|
|||
import { describe, it } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
import mockMessageToasts from '../fixtures/mockMessageToasts';
|
||||
import Toast from '../../../../src/dashboard/components/Toast';
|
||||
import mockMessageToasts from '../mockMessageToasts';
|
||||
import Toast from '../../../../src/messageToasts/components/Toast';
|
||||
|
||||
describe('Toast', () => {
|
||||
const props = {
|
|
@ -1,7 +1,4 @@
|
|||
import {
|
||||
INFO_TOAST,
|
||||
DANGER_TOAST,
|
||||
} from '../../../../src/dashboard/util/constants';
|
||||
import { INFO_TOAST, DANGER_TOAST } from '../../../src/messageToasts/constants';
|
||||
|
||||
export default [
|
||||
{ id: 'info_id', toastType: INFO_TOAST, text: 'info toast' },
|
|
@ -1,11 +1,8 @@
|
|||
import { describe, it } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
import {
|
||||
ADD_TOAST,
|
||||
REMOVE_TOAST,
|
||||
} from '../../../../src/dashboard/actions/messageToasts';
|
||||
import messageToastsReducer from '../../../../src/dashboard/reducers/messageToasts';
|
||||
import { ADD_TOAST, REMOVE_TOAST } from '../../../../src/messageToasts/actions';
|
||||
import messageToastsReducer from '../../../../src/messageToasts/reducers';
|
||||
|
||||
describe('messageToasts reducer', () => {
|
||||
it('should return initial state', () => {
|
|
@ -0,0 +1,35 @@
|
|||
import { describe, it } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
import {
|
||||
DANGER_TOAST,
|
||||
INFO_TOAST,
|
||||
SUCCESS_TOAST,
|
||||
} from '../../../../src/messageToasts/constants';
|
||||
|
||||
import getToastsFromPyFlashMessages from '../../../../src/messageToasts/utils/getToastsFromPyFlashMessages';
|
||||
|
||||
describe('getToastsFromPyFlashMessages', () => {
|
||||
it('should return an info toast', () => {
|
||||
const toast = getToastsFromPyFlashMessages([['info', 'info test']])[0];
|
||||
expect(toast).to.deep.include({ toastType: INFO_TOAST, text: 'info test' });
|
||||
});
|
||||
|
||||
it('should return a success toast', () => {
|
||||
const toast = getToastsFromPyFlashMessages([
|
||||
['success', 'success test'],
|
||||
])[0];
|
||||
expect(toast).to.deep.include({
|
||||
toastType: SUCCESS_TOAST,
|
||||
text: 'success test',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a danger toast', () => {
|
||||
const toast = getToastsFromPyFlashMessages([['danger', 'danger test']])[0];
|
||||
expect(toast).to.deep.include({
|
||||
toastType: DANGER_TOAST,
|
||||
text: 'danger test',
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,31 +0,0 @@
|
|||
import React from 'react';
|
||||
import { describe, it } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { shallow } from 'enzyme';
|
||||
import AlertContainer from 'react-alert';
|
||||
import AlertsWrapper from '../../../src/components/AlertsWrapper';
|
||||
|
||||
describe('AlertsWrapper', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<AlertsWrapper />);
|
||||
});
|
||||
|
||||
it('is valid', () => {
|
||||
expect(React.isValidElement(<AlertsWrapper />)).to.equal(true);
|
||||
});
|
||||
|
||||
it('renders AlertContainer', () => {
|
||||
expect(wrapper.find(AlertContainer)).to.have.length(1);
|
||||
});
|
||||
|
||||
it('expects AlertContainer to have correct props', () => {
|
||||
const alertContainerProps = wrapper.find(AlertContainer).props();
|
||||
expect(alertContainerProps.offset).to.be.equal(14);
|
||||
expect(alertContainerProps.position).to.be.equal('top right');
|
||||
expect(alertContainerProps.theme).to.be.equal('dark');
|
||||
expect(alertContainerProps.time).to.be.equal(5000);
|
||||
expect(alertContainerProps.transition).to.be.equal('fade');
|
||||
});
|
||||
});
|
|
@ -14,23 +14,24 @@ import { sqlLabReducer } from '../../../src/SqlLab/reducers';
|
|||
describe('App', () => {
|
||||
const middlewares = [thunk];
|
||||
const mockStore = configureStore(middlewares);
|
||||
const store = mockStore(sqlLabReducer(undefined, {}));
|
||||
const store = mockStore({ sqlLab: sqlLabReducer(undefined, {}), messageToasts: [] });
|
||||
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<App />, {
|
||||
context: { store },
|
||||
}).dive();
|
||||
wrapper = shallow(<App />, { context: { store } }).dive();
|
||||
});
|
||||
|
||||
it('is valid', () => {
|
||||
expect(React.isValidElement(<App />)).to.equal(true);
|
||||
});
|
||||
|
||||
it('should handler resize', () => {
|
||||
sinon.spy(wrapper.instance(), 'getHeight');
|
||||
wrapper.instance().handleResize();
|
||||
expect(wrapper.instance().getHeight.callCount).to.equal(1);
|
||||
wrapper.instance().getHeight.restore();
|
||||
});
|
||||
|
||||
it('should render', () => {
|
||||
expect(wrapper.find('.SqlLab')).to.have.length(1);
|
||||
expect(wrapper.find(TabbedSqlEditors)).to.have.length(1);
|
||||
|
|
|
@ -7,7 +7,7 @@ import CopyQueryTabUrl from '../../../src/SqlLab/components/CopyQueryTabUrl';
|
|||
|
||||
describe('CopyQueryTabUrl', () => {
|
||||
const mockedProps = {
|
||||
queryEditor: initialState.queryEditors[0],
|
||||
queryEditor: initialState.sqlLab.queryEditors[0],
|
||||
};
|
||||
it('is valid with props', () => {
|
||||
expect(
|
||||
|
|
|
@ -20,6 +20,7 @@ describe('SqlEditorLeftBar', () => {
|
|||
queryEditorSetDb: sinon.stub(),
|
||||
setDatabases: sinon.stub(),
|
||||
addTable: sinon.stub(),
|
||||
addDangerToast: sinon.stub(),
|
||||
},
|
||||
tables: [table],
|
||||
queryEditor: defaultQueryEditor,
|
||||
|
|
|
@ -11,7 +11,7 @@ describe('SqlEditor', () => {
|
|||
const mockedProps = {
|
||||
actions: {},
|
||||
database: {},
|
||||
queryEditor: initialState.queryEditors[0],
|
||||
queryEditor: initialState.sqlLab.queryEditors[0],
|
||||
latestQuery: queries[0],
|
||||
tables: [table],
|
||||
queries,
|
||||
|
|
|
@ -22,10 +22,12 @@ describe('TabbedSqlEditors', () => {
|
|||
'dfsadfs',
|
||||
'newEditorId',
|
||||
];
|
||||
|
||||
const tables = [Object.assign({}, table[0], {
|
||||
dataPreviewQueryId: 'B1-VQU1zW',
|
||||
queryEditorId: 'newEditorId',
|
||||
})];
|
||||
|
||||
const queryEditors = [{
|
||||
autorun: false,
|
||||
dbId: 1,
|
||||
|
@ -47,8 +49,8 @@ describe('TabbedSqlEditors', () => {
|
|||
databases: {},
|
||||
tables: [],
|
||||
queries: {},
|
||||
queryEditors: initialState.queryEditors,
|
||||
tabHistory: initialState.tabHistory,
|
||||
queryEditors: initialState.sqlLab.queryEditors,
|
||||
tabHistory: initialState.sqlLab.tabHistory,
|
||||
editorHeight: '',
|
||||
getHeight: () => ('100px'),
|
||||
database: {},
|
||||
|
@ -163,7 +165,7 @@ describe('TabbedSqlEditors', () => {
|
|||
wrapper.setState({ hideLeftBar: true });
|
||||
|
||||
const firstTab = wrapper.find(Tab).first();
|
||||
expect(firstTab.props().eventKey).to.contain(initialState.queryEditors[0].id);
|
||||
expect(firstTab.props().eventKey).to.contain(initialState.sqlLab.queryEditors[0].id);
|
||||
expect(firstTab.find(SqlEditor)).to.have.length(1);
|
||||
|
||||
const lastTab = wrapper.find(Tab).last();
|
||||
|
|
|
@ -17,17 +17,16 @@ import { VISUALIZE_VALIDATION_ERRORS } from '../../../src/SqlLab/constants';
|
|||
import VisualizeModal from '../../../src/SqlLab/components/VisualizeModal';
|
||||
import * as exploreUtils from '../../../src/explore/exploreUtils';
|
||||
|
||||
global.notify = {
|
||||
info: () => {},
|
||||
error: () => {},
|
||||
};
|
||||
|
||||
describe('VisualizeModal', () => {
|
||||
const middlewares = [thunk];
|
||||
const mockStore = configureStore(middlewares);
|
||||
const initialState = sqlLabReducer({}, {});
|
||||
initialState.common = {
|
||||
conf: { SUPERSET_WEBSERVER_TIMEOUT: 45 },
|
||||
const initialState = {
|
||||
sqlLab: {
|
||||
...sqlLabReducer(undefined, {}),
|
||||
common: {
|
||||
conf: { SUPERSET_WEBSERVER_TIMEOUT: 45 },
|
||||
},
|
||||
},
|
||||
};
|
||||
const store = mockStore(initialState);
|
||||
const mockedProps = {
|
||||
|
@ -277,7 +276,7 @@ describe('VisualizeModal', () => {
|
|||
});
|
||||
|
||||
it('should build visualize advise for long query', () => {
|
||||
const longQuery = Object.assign({}, queries[0], { endDttm: 1476910666798 });
|
||||
const longQuery = { ...queries[0], endDttm: 1476910666798 };
|
||||
const props = {
|
||||
show: true,
|
||||
query: longQuery,
|
||||
|
@ -334,29 +333,46 @@ describe('VisualizeModal', () => {
|
|||
expect(spyCall.args[0].data.data).to.equal(JSON.stringify(mockOptions));
|
||||
});
|
||||
it('should open new window', () => {
|
||||
const infoToastSpy = sinon.spy();
|
||||
|
||||
datasourceSpy.callsFake(() => {
|
||||
const d = $.Deferred();
|
||||
d.resolve('done');
|
||||
return d.promise();
|
||||
});
|
||||
wrapper.setProps({ actions: { createDatasource: datasourceSpy } });
|
||||
|
||||
wrapper.setProps({
|
||||
actions: {
|
||||
createDatasource: datasourceSpy,
|
||||
addInfoToast: infoToastSpy,
|
||||
},
|
||||
});
|
||||
|
||||
wrapper.instance().visualize();
|
||||
expect(exploreUtils.exportChart.callCount).to.equal(1);
|
||||
expect(exploreUtils.exportChart.getCall(0).args[0].datasource).to.equal('107__table');
|
||||
expect(infoToastSpy.callCount).to.equal(1);
|
||||
});
|
||||
it('should notify error', () => {
|
||||
it('should add error toast', () => {
|
||||
const dangerToastSpy = sinon.spy();
|
||||
|
||||
datasourceSpy.callsFake(() => {
|
||||
const d = $.Deferred();
|
||||
d.reject('error message');
|
||||
return d.promise();
|
||||
});
|
||||
wrapper.setProps({ actions: { createDatasource: datasourceSpy } });
|
||||
sinon.spy(notify, 'error');
|
||||
|
||||
|
||||
wrapper.setProps({
|
||||
actions: {
|
||||
createDatasource: datasourceSpy,
|
||||
addDangerToast: dangerToastSpy,
|
||||
},
|
||||
});
|
||||
|
||||
wrapper.instance().visualize();
|
||||
expect(exploreUtils.exportChart.callCount).to.equal(0);
|
||||
expect(notify.error.callCount).to.equal(1);
|
||||
expect(dangerToastSpy.callCount).to.equal(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,13 +20,15 @@ describe('async actions', () => {
|
|||
|
||||
describe('saveQuery', () => {
|
||||
it('makes the ajax request', () => {
|
||||
actions.saveQuery(query);
|
||||
const thunk = actions.saveQuery(query);
|
||||
thunk((/* mockDispatch */) => {});
|
||||
expect(ajaxStub.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('calls correct url', () => {
|
||||
const url = '/savedqueryviewapi/api/create';
|
||||
actions.saveQuery(query);
|
||||
const thunk = actions.saveQuery(query);
|
||||
thunk((/* mockDispatch */) => {});
|
||||
expect(ajaxStub.getCall(0).args[0].url).to.equal(url);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -319,15 +319,18 @@ export const runningQuery = {
|
|||
export const cachedQuery = Object.assign({}, queries[0], { cached: true });
|
||||
|
||||
export const initialState = {
|
||||
alerts: [],
|
||||
queries: {},
|
||||
databases: {},
|
||||
queryEditors: [defaultQueryEditor],
|
||||
tabHistory: [defaultQueryEditor.id],
|
||||
tables: [],
|
||||
workspaceQueries: [],
|
||||
queriesLastUpdate: 0,
|
||||
activeSouthPaneTab: 'Results',
|
||||
sqlLab: {
|
||||
alerts: [],
|
||||
queries: {},
|
||||
databases: {},
|
||||
queryEditors: [defaultQueryEditor],
|
||||
tabHistory: [defaultQueryEditor.id],
|
||||
tables: [],
|
||||
workspaceQueries: [],
|
||||
queriesLastUpdate: 0,
|
||||
activeSouthPaneTab: 'Results',
|
||||
},
|
||||
messageToasts: [],
|
||||
};
|
||||
|
||||
export const query = {
|
||||
|
|
|
@ -3,12 +3,17 @@ import { expect } from 'chai';
|
|||
|
||||
import * as r from '../../../src/SqlLab/reducers';
|
||||
import * as actions from '../../../src/SqlLab/actions';
|
||||
import { alert, table, initialState } from './fixtures';
|
||||
import { table, initialState as mockState } from './fixtures';
|
||||
|
||||
const initialState = mockState.sqlLab;
|
||||
|
||||
describe('sqlLabReducer', () => {
|
||||
describe('CLONE_QUERY_TO_NEW_TAB', () => {
|
||||
const testQuery = { sql: 'SELECT * FROM...', dbId: 1, id: 'flasj233' };
|
||||
let newState = Object.assign({}, initialState, { queries: { [testQuery.id]: testQuery } });
|
||||
let newState = {
|
||||
...initialState,
|
||||
queries: { [testQuery.id]: testQuery },
|
||||
};
|
||||
beforeEach(() => {
|
||||
newState = r.sqlLabReducer(newState, actions.cloneQueryToNewTab(testQuery));
|
||||
});
|
||||
|
@ -29,24 +34,12 @@ describe('sqlLabReducer', () => {
|
|||
expect(newState.tabHistory[1]).to.eq(newState.queryEditors[1].id);
|
||||
});
|
||||
});
|
||||
describe('Alerts', () => {
|
||||
const state = Object.assign({}, initialState);
|
||||
let newState;
|
||||
it('should add one alert', () => {
|
||||
newState = r.sqlLabReducer(state, actions.addAlert(alert));
|
||||
expect(newState.alerts).to.have.lengthOf(1);
|
||||
});
|
||||
it('should remove one alert', () => {
|
||||
newState = r.sqlLabReducer(newState, actions.removeAlert(newState.alerts[0]));
|
||||
expect(newState.alerts).to.have.lengthOf(0);
|
||||
});
|
||||
});
|
||||
describe('Query editors actions', () => {
|
||||
let newState;
|
||||
let defaultQueryEditor;
|
||||
let qe;
|
||||
beforeEach(() => {
|
||||
newState = Object.assign({}, initialState);
|
||||
newState = { ...initialState };
|
||||
defaultQueryEditor = newState.queryEditors[0];
|
||||
qe = Object.assign({}, defaultQueryEditor);
|
||||
newState = r.sqlLabReducer(newState, actions.addQueryEditor(qe));
|
||||
|
@ -134,8 +127,8 @@ describe('sqlLabReducer', () => {
|
|||
let query;
|
||||
let newQuery;
|
||||
beforeEach(() => {
|
||||
newState = Object.assign({}, initialState);
|
||||
newQuery = Object.assign({}, query);
|
||||
newState = { ...initialState };
|
||||
newQuery = { ...query };
|
||||
});
|
||||
it('should start a query', () => {
|
||||
newState = r.sqlLabReducer(newState, actions.startQuery(newQuery));
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
/* global notify */
|
||||
/* global window */
|
||||
/* eslint no-undef: 2 */
|
||||
import $ from 'jquery';
|
||||
import shortid from 'shortid';
|
||||
import { now } from '../modules/dates';
|
||||
import { t } from '../locales';
|
||||
import {
|
||||
addSuccessToast as addSuccessToastAction,
|
||||
addDangerToast as addDangerToastAction,
|
||||
addInfoToast as addInfoToastAction,
|
||||
} from '../messageToasts/actions';
|
||||
import { COMMON_ERR_MESSAGES } from '../common';
|
||||
|
||||
const $ = require('jquery');
|
||||
|
||||
export const RESET_STATE = 'RESET_STATE';
|
||||
export const ADD_QUERY_EDITOR = 'ADD_QUERY_EDITOR';
|
||||
export const CLONE_QUERY_TO_NEW_TAB = 'CLONE_QUERY_TO_NEW_TAB';
|
||||
|
@ -28,8 +33,6 @@ export const QUERY_EDITOR_PERSIST_HEIGHT = 'QUERY_EDITOR_PERSIST_HEIGHT';
|
|||
export const SET_DATABASES = 'SET_DATABASES';
|
||||
export const SET_ACTIVE_QUERY_EDITOR = 'SET_ACTIVE_QUERY_EDITOR';
|
||||
export const SET_ACTIVE_SOUTHPANE_TAB = 'SET_ACTIVE_SOUTHPANE_TAB';
|
||||
export const ADD_ALERT = 'ADD_ALERT';
|
||||
export const REMOVE_ALERT = 'REMOVE_ALERT';
|
||||
export const REFRESH_QUERIES = 'REFRESH_QUERIES';
|
||||
export const RUN_QUERY = 'RUN_QUERY';
|
||||
export const START_QUERY = 'START_QUERY';
|
||||
|
@ -46,21 +49,31 @@ export const CREATE_DATASOURCE_STARTED = 'CREATE_DATASOURCE_STARTED';
|
|||
export const CREATE_DATASOURCE_SUCCESS = 'CREATE_DATASOURCE_SUCCESS';
|
||||
export const CREATE_DATASOURCE_FAILED = 'CREATE_DATASOURCE_FAILED';
|
||||
|
||||
export const addInfoToast = addInfoToastAction;
|
||||
export const addSuccessToast = addSuccessToastAction;
|
||||
export const addDangerToast = addDangerToastAction;
|
||||
|
||||
export function resetState() {
|
||||
return { type: RESET_STATE };
|
||||
}
|
||||
|
||||
export function saveQuery(query) {
|
||||
const url = '/savedqueryviewapi/api/create';
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url,
|
||||
data: query,
|
||||
success: () => notify.success(t('Your query was saved')),
|
||||
error: () => notify.error(t('Your query could not be saved')),
|
||||
dataType: 'json',
|
||||
});
|
||||
return { type: SAVE_QUERY };
|
||||
return (dispatch) => {
|
||||
const url = '/savedqueryviewapi/api/create';
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url,
|
||||
data: query,
|
||||
success: () => {
|
||||
dispatch(addSuccessToast(t('Your query was saved')));
|
||||
},
|
||||
error: () => {
|
||||
dispatch(addDangerToast(t('Your query could not be saved')));
|
||||
},
|
||||
dataType: 'json',
|
||||
});
|
||||
return { type: SAVE_QUERY };
|
||||
};
|
||||
}
|
||||
|
||||
export function startQuery(query) {
|
||||
|
@ -144,7 +157,7 @@ export function runQuery(query) {
|
|||
select_as_cta: query.ctas,
|
||||
templateParams: query.templateParams,
|
||||
};
|
||||
const sqlJsonUrl = '/superset/sql_json/' + location.search;
|
||||
const sqlJsonUrl = '/superset/sql_json/' + window.location.search;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
|
@ -191,10 +204,10 @@ export function postStopQuery(query) {
|
|||
url: stopQueryUrl,
|
||||
data: stopQueryRequestData,
|
||||
success() {
|
||||
notify.success(t('Query was stopped.'));
|
||||
dispatch(addSuccessToast(t('Query was stopped.')));
|
||||
},
|
||||
error() {
|
||||
notify.error(t('Failed at stopping query.'));
|
||||
dispatch(addDangerToast(t('Failed at stopping query.')));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -216,16 +229,6 @@ export function cloneQueryToNewTab(query) {
|
|||
return { type: CLONE_QUERY_TO_NEW_TAB, query };
|
||||
}
|
||||
|
||||
export function addAlert(alert) {
|
||||
const o = Object.assign({}, alert);
|
||||
o.id = shortid.generate();
|
||||
return { type: ADD_ALERT, alert: o };
|
||||
}
|
||||
|
||||
export function removeAlert(alert) {
|
||||
return { type: REMOVE_ALERT, alert };
|
||||
}
|
||||
|
||||
export function setActiveQueryEditor(queryEditor) {
|
||||
return { type: SET_ACTIVE_QUERY_EDITOR, queryEditor };
|
||||
}
|
||||
|
@ -314,7 +317,7 @@ export function addTable(query, tableName, schemaName) {
|
|||
isMetadataLoading: false,
|
||||
});
|
||||
dispatch(mergeTable(newTable));
|
||||
notify.error(t('Error occurred while fetching table metadata'));
|
||||
dispatch(addDangerToast(t('Error occurred while fetching table metadata')));
|
||||
});
|
||||
|
||||
url = `/superset/extra_table_metadata/${query.dbId}/${tableName}/${schemaName}/`;
|
||||
|
@ -327,7 +330,7 @@ export function addTable(query, tableName, schemaName) {
|
|||
isExtraMetadataLoading: false,
|
||||
});
|
||||
dispatch(mergeTable(newTable));
|
||||
notify.error(t('Error occurred while fetching table metadata'));
|
||||
dispatch(addDangerToast(t('Error occurred while fetching table metadata')));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -389,7 +392,9 @@ export function popStoredQuery(urlId) {
|
|||
};
|
||||
dispatch(addQueryEditor(queryEditorProps));
|
||||
},
|
||||
error: () => notify.error(t('The query couldn\'t be loaded')),
|
||||
error: () => {
|
||||
dispatch(addDangerToast(t('The query couldn\'t be loaded')));
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -409,7 +414,9 @@ export function popSavedQuery(saveQueryId) {
|
|||
};
|
||||
dispatch(addQueryEditor(queryEditorProps));
|
||||
},
|
||||
error: () => notify.error(t('The query couldn\'t be loaded')),
|
||||
error: () => {
|
||||
dispatch(addDangerToast(t('The query couldn\'t be loaded')));
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,15 +2,14 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import $ from 'jquery';
|
||||
|
||||
import TabbedSqlEditors from './TabbedSqlEditors';
|
||||
import QueryAutoRefresh from './QueryAutoRefresh';
|
||||
import QuerySearch from './QuerySearch';
|
||||
import AlertsWrapper from '../../components/AlertsWrapper';
|
||||
import ToastPresenter from '../../messageToasts/containers/ToastPresenter';
|
||||
import * as Actions from '../actions';
|
||||
|
||||
const $ = window.$ = require('jquery');
|
||||
|
||||
class App extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -39,8 +38,10 @@ class App extends React.PureComponent {
|
|||
const alertEl = $('#sqllab-alerts');
|
||||
const headerEl = $('header .navbar');
|
||||
const headerHeight = headerEl.outerHeight() + parseInt(headerEl.css('marginBottom'), 10);
|
||||
const searchHeaderHeight = searchHeaderEl.length > 0 ?
|
||||
searchHeaderEl.outerHeight() + parseInt(searchHeaderEl.css('marginBottom'), 10) : 0;
|
||||
const searchHeaderHeight =
|
||||
searchHeaderEl.length > 0
|
||||
? searchHeaderEl.outerHeight() + parseInt(searchHeaderEl.css('marginBottom'), 10)
|
||||
: 0;
|
||||
const tabsHeight = tabsEl.length > 0 ? tabsEl.outerHeight() : searchHeaderHeight;
|
||||
const warningHeight = warningEl.length > 0 ? warningEl.outerHeight() : 0;
|
||||
const alertHeight = alertEl.length > 0 ? alertEl.outerHeight() : 0;
|
||||
|
@ -71,27 +72,17 @@ class App extends React.PureComponent {
|
|||
}
|
||||
return (
|
||||
<div className="App SqlLab">
|
||||
<AlertsWrapper initMessages={this.props.initMessages} />
|
||||
<div className="container-fluid">
|
||||
{content}
|
||||
</div>
|
||||
<div className="container-fluid">{content}</div>
|
||||
<ToastPresenter />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
App.propTypes = {
|
||||
alerts: PropTypes.array,
|
||||
actions: PropTypes.object,
|
||||
initMessages: PropTypes.array,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
alerts: state.alerts,
|
||||
initMessages: state.flash_messages,
|
||||
};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(Actions, dispatch),
|
||||
|
@ -99,4 +90,7 @@ function mapDispatchToProps(dispatch) {
|
|||
}
|
||||
|
||||
export { App };
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(App);
|
||||
export default connect(
|
||||
null,
|
||||
mapDispatchToProps,
|
||||
)(App);
|
||||
|
|
|
@ -57,10 +57,10 @@ QueryAutoRefresh.propTypes = {
|
|||
queriesLastUpdate: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
function mapStateToProps({ sqlLab }) {
|
||||
return {
|
||||
queries: state.queries,
|
||||
queriesLastUpdate: state.queriesLastUpdate,
|
||||
queries: sqlLab.queries,
|
||||
queriesLastUpdate: sqlLab.queriesLastUpdate,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint no-undef: 2 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'react-bootstrap';
|
||||
|
@ -14,7 +15,7 @@ import { STATUS_OPTIONS, TIME_OPTIONS } from '../constants';
|
|||
import AsyncSelect from '../../components/AsyncSelect';
|
||||
import { t } from '../../locales';
|
||||
|
||||
const $ = (window.$ = require('jquery'));
|
||||
const $ = require('jquery');
|
||||
|
||||
const propTypes = {
|
||||
actions: PropTypes.object.isRequired,
|
||||
|
@ -127,10 +128,7 @@ class QuerySearch extends React.PureComponent {
|
|||
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({
|
||||
bsStyle: 'danger',
|
||||
msg: t("It seems you don't have access to any database"),
|
||||
});
|
||||
this.props.actions.addDangerToast(t("It seems you don't have access to any database"));
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
|
|
@ -97,9 +97,9 @@ class SouthPane extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
function mapStateToProps({ sqlLab }) {
|
||||
return {
|
||||
activeSouthPaneTab: state.activeSouthPaneTab,
|
||||
activeSouthPaneTab: sqlLab.activeSouthPaneTab,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* global window */
|
||||
/* eslint no-undef: 2 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import throttle from 'lodash.throttle';
|
||||
|
@ -126,7 +128,7 @@ class SqlEditor extends React.PureComponent {
|
|||
this.props.actions.queryEditorSetSql(this.props.queryEditor, sql);
|
||||
}
|
||||
runQuery() {
|
||||
this.startQuery(!this.props.database.allow_run_sync);
|
||||
this.startQuery(!(this.props.database || {}).allow_run_sync);
|
||||
}
|
||||
startQuery(runAsync = false, ctas = false) {
|
||||
const qe = this.props.queryEditor;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* global notify */
|
||||
/* global window */
|
||||
/* eslint no-undef: 2 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'react-bootstrap';
|
||||
|
@ -9,7 +10,7 @@ import TableElement from './TableElement';
|
|||
import AsyncSelect from '../../components/AsyncSelect';
|
||||
import { t } from '../../locales';
|
||||
|
||||
const $ = window.$ = require('jquery');
|
||||
const $ = require('jquery');
|
||||
|
||||
const propTypes = {
|
||||
queryEditor: PropTypes.object.isRequired,
|
||||
|
@ -62,10 +63,7 @@ class SqlEditorLeftBar extends React.PureComponent {
|
|||
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({
|
||||
bsStyle: 'danger',
|
||||
msg: t('It seems you don\'t have access to any database'),
|
||||
});
|
||||
this.props.actions.addDangerToast(t('It seems you don\'t have access to any database'));
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
@ -88,7 +86,7 @@ class SqlEditorLeftBar extends React.PureComponent {
|
|||
})
|
||||
.fail(() => {
|
||||
this.setState({ tableLoading: false, tableOptions: [], tableLength: 0 });
|
||||
notify.error(t('Error while fetching table list'));
|
||||
this.props.actions.addDangerToast(t('Error while fetching table list'));
|
||||
});
|
||||
} else {
|
||||
this.setState({ tableLoading: false, tableOptions: [], filterOptions: null });
|
||||
|
@ -129,7 +127,7 @@ class SqlEditorLeftBar extends React.PureComponent {
|
|||
})
|
||||
.fail(() => {
|
||||
this.setState({ schemaLoading: false, schemaOptions: [] });
|
||||
notify.error(t('Error while fetching schema list'));
|
||||
this.props.actions.addDangerToast(t('Error while fetching schema list'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +157,9 @@ class SqlEditorLeftBar extends React.PureComponent {
|
|||
'_od_DatabaseAsync=asc'
|
||||
}
|
||||
onChange={this.onDatabaseChange.bind(this)}
|
||||
onAsyncError={() => notify.error(t('Error while fetching database list'))}
|
||||
onAsyncError={() => {
|
||||
this.props.actions.addDangerToast(t('Error while fetching database list'));
|
||||
}}
|
||||
value={this.props.queryEditor.dbId}
|
||||
databaseId={this.props.queryEditor.dbId}
|
||||
actions={this.props.actions}
|
||||
|
|
|
@ -231,14 +231,14 @@ class TabbedSqlEditors extends React.PureComponent {
|
|||
TabbedSqlEditors.propTypes = propTypes;
|
||||
TabbedSqlEditors.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
function mapStateToProps({ sqlLab }) {
|
||||
return {
|
||||
databases: state.databases,
|
||||
queryEditors: state.queryEditors,
|
||||
queries: state.queries,
|
||||
tabHistory: state.tabHistory,
|
||||
tables: state.tables,
|
||||
defaultDbId: state.defaultDbId,
|
||||
databases: sqlLab.databases,
|
||||
queryEditors: sqlLab.queryEditors,
|
||||
queries: sqlLab.queries,
|
||||
tabHistory: sqlLab.tabHistory,
|
||||
tables: sqlLab.tables,
|
||||
defaultDbId: sqlLab.defaultDbId,
|
||||
};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global notify */
|
||||
/* eslint no-undef: 2 */
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
@ -168,13 +168,13 @@ class VisualizeModal extends React.PureComponent {
|
|||
if (mainGroupBy) {
|
||||
formData.groupby = [mainGroupBy.name];
|
||||
}
|
||||
notify.info(t('Creating a data source and popping a new tab'));
|
||||
this.props.actions.addInfoToast(t('Creating a data source and creating a new tab'));
|
||||
|
||||
// open new window for data visualization
|
||||
exportChart(formData);
|
||||
})
|
||||
.fail(() => {
|
||||
notify.error(this.props.errorMessage);
|
||||
this.props.actions.addDangerToast(this.props.errorMessage);
|
||||
});
|
||||
}
|
||||
changeDatasourceName(event) {
|
||||
|
@ -295,11 +295,11 @@ class VisualizeModal extends React.PureComponent {
|
|||
VisualizeModal.propTypes = propTypes;
|
||||
VisualizeModal.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
function mapStateToProps({ sqlLab }) {
|
||||
return {
|
||||
datasource: state.datasource,
|
||||
errorMessage: state.errorMessage,
|
||||
timeout: state.common ? state.common.conf.SUPERSET_WEBSERVER_TIMEOUT : null,
|
||||
datasource: sqlLab.datasource,
|
||||
errorMessage: sqlLab.errorMessage,
|
||||
timeout: sqlLab.common ? sqlLab.common.conf.SUPERSET_WEBSERVER_TIMEOUT : null,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* eslint no-undef: 2 */
|
||||
import shortid from 'shortid';
|
||||
import { t } from '../locales';
|
||||
import getToastsFromPyFlashMessages from '../messageToasts/utils/getToastsFromPyFlashMessages';
|
||||
|
||||
export default function getInitialState({ defaultDbId, ...restBootstrapData }) {
|
||||
const defaultQueryEditor = {
|
||||
id: shortid.generate(),
|
||||
title: t('Untitled Query'),
|
||||
sql: 'SELECT *\nFROM\nWHERE',
|
||||
selectedText: null,
|
||||
latestQueryId: null,
|
||||
autorun: false,
|
||||
dbId: defaultDbId,
|
||||
};
|
||||
|
||||
return {
|
||||
sqlLab: {
|
||||
alerts: [],
|
||||
queries: {},
|
||||
databases: {},
|
||||
queryEditors: [defaultQueryEditor],
|
||||
tabHistory: [defaultQueryEditor.id],
|
||||
tables: [],
|
||||
queriesLastUpdate: 0,
|
||||
activeSouthPaneTab: 'Results',
|
||||
...restBootstrapData,
|
||||
},
|
||||
messageToasts: getToastsFromPyFlashMessages(
|
||||
(restBootstrapData.common || {}).flash_messages || [],
|
||||
),
|
||||
};
|
||||
}
|
|
@ -4,7 +4,8 @@ import { createStore, compose, applyMiddleware } from 'redux';
|
|||
import { Provider } from 'react-redux';
|
||||
import thunkMiddleware from 'redux-thunk';
|
||||
|
||||
import { getInitialState, sqlLabReducer } from './reducers';
|
||||
import getInitialState from './getInitialState';
|
||||
import rootReducer from './reducers';
|
||||
import { initEnhancer } from '../reduxUtils';
|
||||
import { initJQueryAjax } from '../modules/utils';
|
||||
import App from './components/App';
|
||||
|
@ -19,13 +20,21 @@ initJQueryAjax();
|
|||
|
||||
const appContainer = document.getElementById('app');
|
||||
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
|
||||
const state = Object.assign({}, getInitialState(bootstrapData.defaultDbId), bootstrapData);
|
||||
const state = getInitialState(bootstrapData);
|
||||
|
||||
const store = createStore(
|
||||
sqlLabReducer, state, compose(applyMiddleware(thunkMiddleware), initEnhancer()));
|
||||
rootReducer,
|
||||
state,
|
||||
compose(
|
||||
applyMiddleware(thunkMiddleware),
|
||||
initEnhancer(),
|
||||
),
|
||||
);
|
||||
|
||||
// jquery hack to highlight the navbar menu
|
||||
$('a:contains("SQL Lab")').parent().addClass('active');
|
||||
$('a:contains("SQL Lab")')
|
||||
.parent()
|
||||
.addClass('active');
|
||||
|
||||
render(
|
||||
<Provider store={store}>
|
||||
|
|
|
@ -1,34 +1,20 @@
|
|||
import { combineReducers } from 'redux';
|
||||
import shortid from 'shortid';
|
||||
import messageToasts from '../messageToasts/reducers';
|
||||
|
||||
import * as actions from './actions';
|
||||
import { now } from '../modules/dates';
|
||||
import { addToObject, alterInObject, alterInArr, removeFromArr, getFromArr, addToArr }
|
||||
from '../reduxUtils';
|
||||
import {
|
||||
addToObject,
|
||||
alterInObject,
|
||||
alterInArr,
|
||||
removeFromArr,
|
||||
getFromArr,
|
||||
addToArr,
|
||||
} from '../reduxUtils';
|
||||
import { t } from '../locales';
|
||||
|
||||
export function getInitialState(defaultDbId) {
|
||||
const defaultQueryEditor = {
|
||||
id: shortid.generate(),
|
||||
title: t('Untitled Query'),
|
||||
sql: 'SELECT *\nFROM\nWHERE',
|
||||
selectedText: null,
|
||||
latestQueryId: null,
|
||||
autorun: false,
|
||||
dbId: defaultDbId,
|
||||
};
|
||||
|
||||
return {
|
||||
alerts: [],
|
||||
queries: {},
|
||||
databases: {},
|
||||
queryEditors: [defaultQueryEditor],
|
||||
tabHistory: [defaultQueryEditor.id],
|
||||
tables: [],
|
||||
queriesLastUpdate: 0,
|
||||
activeSouthPaneTab: 'Results',
|
||||
};
|
||||
}
|
||||
|
||||
export const sqlLabReducer = function (state, action) {
|
||||
export const sqlLabReducer = function (state = {}, action) {
|
||||
const actionHandlers = {
|
||||
[actions.ADD_QUERY_EDITOR]() {
|
||||
const tabHistory = state.tabHistory.slice();
|
||||
|
@ -225,9 +211,6 @@ export const sqlLabReducer = function (state, action) {
|
|||
[actions.QUERY_EDITOR_PERSIST_HEIGHT]() {
|
||||
return alterInArr(state, 'queryEditors', action.queryEditor, { height: action.currentHeight });
|
||||
},
|
||||
[actions.ADD_ALERT]() {
|
||||
return addToArr(state, 'alerts', action.alert);
|
||||
},
|
||||
[actions.SET_DATABASES]() {
|
||||
const databases = {};
|
||||
action.databases.forEach((db) => {
|
||||
|
@ -235,9 +218,6 @@ export const sqlLabReducer = function (state, action) {
|
|||
});
|
||||
return Object.assign({}, state, { databases });
|
||||
},
|
||||
[actions.REMOVE_ALERT]() {
|
||||
return removeFromArr(state, 'alerts', action.alert);
|
||||
},
|
||||
[actions.REFRESH_QUERIES]() {
|
||||
let newQueries = Object.assign({}, state.queries);
|
||||
// Fetch the updates to the queries present in the store.
|
||||
|
@ -284,3 +264,8 @@ export const sqlLabReducer = function (state, action) {
|
|||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
export default combineReducers({
|
||||
sqlLab: sqlLabReducer,
|
||||
messageToasts,
|
||||
});
|
||||
|
|
|
@ -238,7 +238,9 @@ class Chart extends React.PureComponent {
|
|||
vizType={this.props.vizType}
|
||||
height={this.height}
|
||||
width={this.width}
|
||||
faded={this.props.refreshOverlayVisible && !this.props.errorMessage}
|
||||
faded={
|
||||
this.props.refreshOverlayVisible && !this.props.errorMessage
|
||||
}
|
||||
ref={(inner) => {
|
||||
this.container = inner;
|
||||
}}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/* global notify */
|
||||
import React from 'react';
|
||||
import AlertContainer from 'react-alert';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const propTypes = {
|
||||
initMessages: PropTypes.array,
|
||||
};
|
||||
const defaultProps = {
|
||||
initMessages: [],
|
||||
};
|
||||
|
||||
export default class AlertsWrapper extends React.PureComponent {
|
||||
componentDidMount() {
|
||||
this.props.initMessages.forEach((msg) => {
|
||||
if (['info', 'error', 'success'].indexOf(msg[0]) >= 0) {
|
||||
notify[msg[0]](msg[1]);
|
||||
} else {
|
||||
notify.show(msg[1]);
|
||||
}
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<AlertContainer
|
||||
ref={(ref) => {
|
||||
global.notify = ref;
|
||||
}}
|
||||
offset={14}
|
||||
position="top right"
|
||||
theme="dark"
|
||||
time={5000}
|
||||
transition="fade"
|
||||
/>);
|
||||
}
|
||||
}
|
||||
AlertsWrapper.propTypes = propTypes;
|
||||
AlertsWrapper.defaultProps = defaultProps;
|
|
@ -4,19 +4,22 @@ import { Popover, OverlayTrigger } from 'react-bootstrap';
|
|||
import CopyToClipboard from './CopyToClipboard';
|
||||
import { getShortUrl } from '../utils/common';
|
||||
import { t } from '../locales';
|
||||
import withToasts from '../messageToasts/enhancers/withToasts';
|
||||
|
||||
const propTypes = {
|
||||
url: PropTypes.string,
|
||||
emailSubject: PropTypes.string,
|
||||
emailContent: PropTypes.string,
|
||||
addDangerToast: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default class URLShortLinkButton extends React.Component {
|
||||
class URLShortLinkButton extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
shortUrl: '',
|
||||
};
|
||||
this.onShortUrlSuccess = this.onShortUrlSuccess.bind(this);
|
||||
}
|
||||
|
||||
onShortUrlSuccess(data) {
|
||||
|
@ -26,7 +29,7 @@ export default class URLShortLinkButton extends React.Component {
|
|||
}
|
||||
|
||||
getCopyUrl() {
|
||||
getShortUrl(this.props.url, this.onShortUrlSuccess.bind(this));
|
||||
getShortUrl(this.props.url, this.onShortUrlSuccess, this.props.addDangerToast);
|
||||
}
|
||||
|
||||
renderPopover() {
|
||||
|
@ -69,3 +72,5 @@ URLShortLinkButton.defaultProps = {
|
|||
};
|
||||
|
||||
URLShortLinkButton.propTypes = propTypes;
|
||||
|
||||
export default withToasts(URLShortLinkButton);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ActionCreators as UndoActionCreators } from 'redux-undo';
|
||||
|
||||
import { addInfoToast } from './messageToasts';
|
||||
import { addInfoToast } from '../../messageToasts/actions';
|
||||
import { setUnsavedChanges } from './dashboardState';
|
||||
import { TABS_TYPE, ROW_TYPE } from '../util/componentTypes';
|
||||
import {
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
addSuccessToast,
|
||||
addWarningToast,
|
||||
addDangerToast,
|
||||
} from './messageToasts';
|
||||
} from '../../messageToasts/actions';
|
||||
|
||||
export const SET_UNSAVED_CHANGES = 'SET_UNSAVED_CHANGES';
|
||||
export function setUnsavedChanges(hasUnsavedChanges) {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import AlertsWrapper from '../../components/AlertsWrapper';
|
||||
import getChartIdsFromLayout from '../util/getChartIdsFromLayout';
|
||||
import DashboardBuilder from '../containers/DashboardBuilder';
|
||||
import {
|
||||
|
@ -220,12 +219,7 @@ class Dashboard extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<AlertsWrapper initMessages={this.props.initMessages} />
|
||||
<DashboardBuilder />
|
||||
</div>
|
||||
);
|
||||
return <DashboardBuilder />;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import DashboardGrid from '../containers/DashboardGrid';
|
|||
import IconButton from './IconButton';
|
||||
import DragDroppable from './dnd/DragDroppable';
|
||||
import DashboardComponent from '../containers/DashboardComponent';
|
||||
import ToastPresenter from '../containers/ToastPresenter';
|
||||
import ToastPresenter from '../../messageToasts/containers/ToastPresenter';
|
||||
import WithPopoverMenu from './menu/WithPopoverMenu';
|
||||
|
||||
import getDragDropManager from '../util/getDragDropManager';
|
||||
|
|
|
@ -23,7 +23,7 @@ import {
|
|||
updateDashboardTitle,
|
||||
} from '../actions/dashboardLayout';
|
||||
|
||||
import { addSuccessToast, addDangerToast } from '../actions/messageToasts';
|
||||
import { addSuccessToast, addDangerToast } from '../../messageToasts/actions';
|
||||
|
||||
import { DASHBOARD_HEADER_ID } from '../util/constants';
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* global notify */
|
||||
/* global window */
|
||||
import $ from 'jquery';
|
||||
import { getExploreUrlAndPayload } from '../../../explore/exploreUtils';
|
||||
import { addSuccessToast, addDangerToast } from '../../../messageToasts/actions';
|
||||
|
||||
export const ADD_FILTER = 'ADD_FILTER';
|
||||
export function addFilter(sliceId, col, vals, merge = true, refresh = true) {
|
||||
|
@ -36,10 +37,10 @@ export function addSlicesToDashboard(dashboardId, sliceIds) {
|
|||
data: JSON.stringify({ slice_ids: sliceIds }),
|
||||
},
|
||||
})
|
||||
.done(() => {
|
||||
// Refresh page to allow for slices to re-render
|
||||
window.location.reload();
|
||||
})
|
||||
.done(() => {
|
||||
// Refresh page to allow for slices to re-render
|
||||
window.location.reload();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -75,13 +76,13 @@ export function saveSlice(slice, sliceName) {
|
|||
},
|
||||
success: () => {
|
||||
dispatch(updateSliceName(slice, sliceName));
|
||||
notify.success('This slice name was saved successfully.');
|
||||
dispatch(addSuccessToast('This slice name was saved successfully.'));
|
||||
},
|
||||
error: () => {
|
||||
// if server-side reject the overwrite action,
|
||||
// revert to old state
|
||||
dispatch(updateSliceName(slice, oldName));
|
||||
notify.error("You don't have the rights to alter this slice");
|
||||
dispatch(addDangerToast("You don't have the rights to alter this slice"));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import AlertsWrapper from '../../../../components/AlertsWrapper';
|
||||
import ToastsPresenter from '../../../../messageToasts/containers/ToastPresenter';
|
||||
import GridLayout from './GridLayout';
|
||||
import Header from './Header';
|
||||
import { exportChart } from '../../../../explore/exploreUtils';
|
||||
|
@ -385,7 +385,7 @@ class Dashboard extends React.PureComponent {
|
|||
return (
|
||||
<div id="dashboard-container">
|
||||
<div id="dashboard-header">
|
||||
<AlertsWrapper initMessages={this.props.initMessages} />
|
||||
<ToastsPresenter />
|
||||
<Header
|
||||
dashboard={this.props.dashboard}
|
||||
unsavedChanges={this.state.unsavedChanges}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
/* global notify */
|
||||
/* global window */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, FormControl, FormGroup, Radio } from 'react-bootstrap';
|
||||
import $ from 'jquery';
|
||||
|
||||
import { getAjaxErrorMsg } from '../../../../modules/utils';
|
||||
import ModalTrigger from '../../../../components/ModalTrigger';
|
||||
import { t } from '../../../../locales';
|
||||
import Checkbox from '../../../../components/Checkbox';
|
||||
|
||||
const $ = window.$ = require('jquery');
|
||||
import withToasts from '../../../../messageToasts/enhancers/withToasts';
|
||||
|
||||
const propTypes = {
|
||||
css: PropTypes.string,
|
||||
|
@ -16,6 +17,8 @@ const propTypes = {
|
|||
filters: PropTypes.object.isRequired,
|
||||
serialize: PropTypes.func,
|
||||
onSave: PropTypes.func,
|
||||
addSuccessToast: PropTypes.func.isRequired,
|
||||
addDangerToast: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class SaveModal extends React.PureComponent {
|
||||
|
@ -57,19 +60,23 @@ class SaveModal extends React.PureComponent {
|
|||
data: {
|
||||
data: JSON.stringify(data),
|
||||
},
|
||||
success(resp) {
|
||||
success: (resp) => {
|
||||
saveModal.close();
|
||||
onSaveDashboard();
|
||||
if (saveType === 'newDashboard') {
|
||||
window.location = `/superset/dashboard/${resp.id}/`;
|
||||
} else {
|
||||
notify.success(t('This dashboard was saved successfully.'));
|
||||
this.props.addSuccessToast(
|
||||
t('This dashboard was saved successfully.'),
|
||||
);
|
||||
}
|
||||
},
|
||||
error(error) {
|
||||
error: (error) => {
|
||||
saveModal.close();
|
||||
const errorMsg = getAjaxErrorMsg(error);
|
||||
notify.error(t('Sorry, there was an error saving this dashboard: ') + errorMsg);
|
||||
this.props.addDangerToast(
|
||||
t('Sorry, there was an error saving this dashboard: ') + errorMsg,
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -91,10 +98,9 @@ class SaveModal extends React.PureComponent {
|
|||
} else if (saveType === 'newDashboard') {
|
||||
if (!newDashboardTitle) {
|
||||
this.modal.close();
|
||||
showModal({
|
||||
title: t('Error'),
|
||||
body: t('You must pick a name for the new dashboard'),
|
||||
});
|
||||
this.props.addDangerToast(
|
||||
t('You must pick a name for the new dashboard'),
|
||||
);
|
||||
} else {
|
||||
data.dashboard_title = newDashboardTitle;
|
||||
url = `/superset/copy_dash/${dashboard.id}/`;
|
||||
|
@ -156,6 +162,7 @@ class SaveModal extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
SaveModal.propTypes = propTypes;
|
||||
|
||||
export default SaveModal;
|
||||
export default withToasts(SaveModal);
|
||||
|
|
|
@ -15,10 +15,16 @@ initJQueryAjax();
|
|||
|
||||
const appContainer = document.getElementById('app');
|
||||
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
|
||||
const initState = Object.assign({}, getInitialState(bootstrapData));
|
||||
const initState = getInitialState(bootstrapData);
|
||||
|
||||
const store = createStore(
|
||||
rootReducer, initState, compose(applyMiddleware(thunk), initEnhancer(false)));
|
||||
rootReducer,
|
||||
initState,
|
||||
compose(
|
||||
applyMiddleware(thunk),
|
||||
initEnhancer(false),
|
||||
),
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
|
|
|
@ -9,6 +9,7 @@ import { getParam } from '../../../modules/utils';
|
|||
import { alterInArr, removeFromArr } from '../../../reduxUtils';
|
||||
import { applyDefaultFormData } from '../../../explore/store';
|
||||
import { getColorFromScheme } from '../../../modules/colors';
|
||||
import messageToasts from '../../../messageToasts/reducers';
|
||||
|
||||
export function getInitialState(bootstrapData) {
|
||||
const {
|
||||
|
@ -121,6 +122,7 @@ export function getInitialState(bootstrapData) {
|
|||
common,
|
||||
editMode,
|
||||
},
|
||||
messageToasts: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -269,4 +271,5 @@ export default combineReducers({
|
|||
charts,
|
||||
dashboard,
|
||||
impressionId: () => shortid.generate(),
|
||||
messageToasts,
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ import dashboardState from './dashboardState';
|
|||
import datasources from './datasources';
|
||||
import sliceEntities from './sliceEntities';
|
||||
import dashboardLayout from '../reducers/undoableDashboardLayout';
|
||||
import messageToasts from '../reducers/messageToasts';
|
||||
import messageToasts from '../../messageToasts/reducers';
|
||||
|
||||
const dashboardInfo = (state = {}) => state;
|
||||
const impressionId = (state = '') => state;
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
@import './popover-menu.less';
|
||||
@import './resizable.less';
|
||||
@import './components/index.less';
|
||||
@import './toast.less';
|
||||
|
|
|
@ -33,12 +33,6 @@ export const LARGE_HEADER = 'LARGE_HEADER';
|
|||
export const BACKGROUND_WHITE = 'BACKGROUND_WHITE';
|
||||
export const BACKGROUND_TRANSPARENT = 'BACKGROUND_TRANSPARENT';
|
||||
|
||||
// Toast types
|
||||
export const INFO_TOAST = 'INFO_TOAST';
|
||||
export const SUCCESS_TOAST = 'SUCCESS_TOAST';
|
||||
export const WARNING_TOAST = 'WARNING_TOAST';
|
||||
export const DANGER_TOAST = 'DANGER_TOAST';
|
||||
|
||||
// undo-redo
|
||||
export const UNDO_LIMIT = 50;
|
||||
|
||||
|
|
|
@ -2,12 +2,6 @@ import PropTypes from 'prop-types';
|
|||
import componentTypes from './componentTypes';
|
||||
import backgroundStyleOptions from './backgroundStyleOptions';
|
||||
import headerStyleOptions from './headerStyleOptions';
|
||||
import {
|
||||
INFO_TOAST,
|
||||
SUCCESS_TOAST,
|
||||
WARNING_TOAST,
|
||||
DANGER_TOAST,
|
||||
} from './constants';
|
||||
|
||||
export const componentShape = PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
|
@ -26,18 +20,6 @@ export const componentShape = PropTypes.shape({
|
|||
}),
|
||||
});
|
||||
|
||||
export const toastShape = PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
toastType: PropTypes.oneOf([
|
||||
INFO_TOAST,
|
||||
SUCCESS_TOAST,
|
||||
WARNING_TOAST,
|
||||
DANGER_TOAST,
|
||||
]).isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
duration: PropTypes.number,
|
||||
});
|
||||
|
||||
export const chartPropShape = PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
chartAlert: PropTypes.string,
|
||||
|
|
|
@ -7,6 +7,7 @@ import AggregateOption from './AggregateOption';
|
|||
import columnType from '../propTypes/columnType';
|
||||
import savedMetricType from '../propTypes/savedMetricType';
|
||||
import aggregateOptionType from '../propTypes/aggregateOptionType';
|
||||
import withToasts from '../../messageToasts/enhancers/withToasts';
|
||||
|
||||
const propTypes = {
|
||||
option: PropTypes.oneOfType([
|
||||
|
@ -14,9 +15,10 @@ const propTypes = {
|
|||
savedMetricType,
|
||||
aggregateOptionType,
|
||||
]).isRequired,
|
||||
addWarningToast: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default function MetricDefinitionOption({ option }) {
|
||||
function MetricDefinitionOption({ option, addWarningToast }) {
|
||||
if (option.metric_name) {
|
||||
return (
|
||||
<MetricOption metric={option} showType />
|
||||
|
@ -30,7 +32,10 @@ export default function MetricDefinitionOption({ option }) {
|
|||
<AggregateOption aggregate={option} showType />
|
||||
);
|
||||
}
|
||||
notify.error('You must supply either a saved metric, column or aggregate to MetricDefinitionOption');
|
||||
addWarningToast('You must supply either a saved metric, column or aggregate to MetricDefinitionOption');
|
||||
return null;
|
||||
}
|
||||
|
||||
MetricDefinitionOption.propTypes = propTypes;
|
||||
|
||||
export default withToasts(MetricDefinitionOption);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global notify */
|
||||
/* eslint no-undef: 2 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Table } from 'reactable';
|
||||
|
@ -13,12 +13,15 @@ import {
|
|||
Tooltip,
|
||||
Well,
|
||||
} from 'react-bootstrap';
|
||||
import $ from 'jquery';
|
||||
|
||||
import ControlHeader from '../ControlHeader';
|
||||
import Loading from '../../../components/Loading';
|
||||
import { t } from '../../../locales';
|
||||
import ColumnOption from '../../../components/ColumnOption';
|
||||
import MetricOption from '../../../components/MetricOption';
|
||||
import withToasts from '../../../messageToasts/enhancers/withToasts';
|
||||
|
||||
|
||||
const propTypes = {
|
||||
description: PropTypes.string,
|
||||
|
@ -27,13 +30,14 @@ const propTypes = {
|
|||
onChange: PropTypes.func,
|
||||
value: PropTypes.string.isRequired,
|
||||
datasource: PropTypes.object,
|
||||
addDangerToast: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
onChange: () => {},
|
||||
};
|
||||
|
||||
export default class DatasourceControl extends React.PureComponent {
|
||||
class DatasourceControl extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -85,7 +89,7 @@ export default class DatasourceControl extends React.PureComponent {
|
|||
},
|
||||
error() {
|
||||
that.setState({ loading: false });
|
||||
notify.error(t('Something went wrong while fetching the datasource list'));
|
||||
this.props.addDangerToast(t('Something went wrong while fetching the datasource list'));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -229,3 +233,5 @@ export default class DatasourceControl extends React.PureComponent {
|
|||
|
||||
DatasourceControl.propTypes = propTypes;
|
||||
DatasourceControl.defaultProps = defaultProps;
|
||||
|
||||
export default withToasts(DatasourceControl);
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
/* global notify */
|
||||
/* eslint no-undef: 2 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select from '../../../components/AsyncSelect';
|
||||
import ControlHeader from '../ControlHeader';
|
||||
import { t } from '../../../locales';
|
||||
|
||||
import withToasts from '../../../messageToasts/enhancers/withToasts';
|
||||
|
||||
const propTypes = {
|
||||
dataEndpoint: PropTypes.string.isRequired,
|
||||
multi: PropTypes.bool,
|
||||
|
@ -18,6 +20,7 @@ const propTypes = {
|
|||
PropTypes.arrayOf(PropTypes.string),
|
||||
PropTypes.arrayOf(PropTypes.number),
|
||||
]),
|
||||
addDangerToast: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
|
@ -40,7 +43,7 @@ const SelectAsyncControl = (props) => {
|
|||
<Select
|
||||
dataEndpoint={dataEndpoint}
|
||||
onChange={onSelectionChange}
|
||||
onAsyncError={errorMsg => notify.error(onAsyncErrorMessage + ': ' + errorMsg)}
|
||||
onAsyncError={errorMsg => this.props.addDangerToast(onAsyncErrorMessage + ': ' + errorMsg)}
|
||||
mutator={mutator}
|
||||
multi={multi}
|
||||
value={value}
|
||||
|
@ -54,4 +57,4 @@ const SelectAsyncControl = (props) => {
|
|||
SelectAsyncControl.propTypes = propTypes;
|
||||
SelectAsyncControl.defaultProps = defaultProps;
|
||||
|
||||
export default SelectAsyncControl;
|
||||
export default withToasts(SelectAsyncControl);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* eslint camelcase: 0 */
|
||||
/* eslint no-undef: 2 */
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createStore, applyMiddleware, compose } from 'redux';
|
||||
|
@ -9,11 +9,12 @@ import shortid from 'shortid';
|
|||
import { now } from '../modules/dates';
|
||||
import { initEnhancer } from '../reduxUtils';
|
||||
import { getChartKey } from './exploreUtils';
|
||||
import AlertsWrapper from '../components/AlertsWrapper';
|
||||
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';
|
||||
|
@ -26,25 +27,24 @@ 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 = Object.assign(
|
||||
bootstrapData, {
|
||||
rawFormData,
|
||||
controls,
|
||||
filterColumnOpts: [],
|
||||
isDatasourceMetaLoading: false,
|
||||
isStarred: false,
|
||||
},
|
||||
);
|
||||
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 sliceFormData = slice
|
||||
? getFormDataFromControls(getControlsState(bootstrapData, slice.form_data))
|
||||
: null;
|
||||
const chartKey = getChartKey(bootstrappedState);
|
||||
const initState = {
|
||||
charts: {
|
||||
|
@ -68,16 +68,23 @@ const initState = {
|
|||
},
|
||||
explore: bootstrappedState,
|
||||
impressionId: shortid.generate(),
|
||||
messageToasts: getToastsFromPyFlashMessages((bootstrapData.common || {}).flash_messages || []),
|
||||
};
|
||||
const store = createStore(rootReducer, initState,
|
||||
compose(applyMiddleware(thunk), initEnhancer(false)),
|
||||
|
||||
const store = createStore(
|
||||
rootReducer,
|
||||
initState,
|
||||
compose(
|
||||
applyMiddleware(thunk),
|
||||
initEnhancer(false),
|
||||
),
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<div>
|
||||
<ExploreViewContainer />
|
||||
<AlertsWrapper initMessages={bootstrappedState.common.flash_messages} />
|
||||
<ToastPresenter />
|
||||
</div>
|
||||
</Provider>,
|
||||
exploreViewContainer,
|
||||
|
|
|
@ -3,12 +3,14 @@ import { combineReducers } from 'redux';
|
|||
import charts from '../../chart/chartReducer';
|
||||
import saveModal from './saveModalReducer';
|
||||
import explore from './exploreReducer';
|
||||
import messageToasts from '../../messageToasts/reducers';
|
||||
|
||||
const impressionId = (state = '') => (state);
|
||||
const impressionId = (state = '') => state;
|
||||
|
||||
export default combineReducers({
|
||||
charts,
|
||||
saveModal,
|
||||
explore,
|
||||
impressionId,
|
||||
messageToasts,
|
||||
});
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"extends": "prettier",
|
||||
"plugins": ["prettier"],
|
||||
"rules": {
|
||||
"prefer-template": 2,
|
||||
"new-cap": 2,
|
||||
"no-restricted-syntax": 2,
|
||||
"guard-for-in": 2,
|
||||
"prefer-arrow-callback": 2,
|
||||
"func-names": 2,
|
||||
"react/jsx-no-bind": 2,
|
||||
"no-confusing-arrow": 2,
|
||||
"jsx-a11y/no-static-element-interactions": 2,
|
||||
"jsx-a11y/anchor-has-content": 2,
|
||||
"react/require-default-props": 2,
|
||||
"no-plusplus": 2,
|
||||
"no-mixed-operators": 0,
|
||||
"no-continue": 2,
|
||||
"no-bitwise": 2,
|
||||
"no-undef": 2,
|
||||
"no-multi-assign": 2,
|
||||
"no-restricted-properties": 2,
|
||||
"no-prototype-builtins": 2,
|
||||
"jsx-a11y/href-no-hash": 2,
|
||||
"class-methods-use-this": 2,
|
||||
"import/no-named-as-default": 2,
|
||||
"import/prefer-default-export": 2,
|
||||
"react/no-unescaped-entities": 2,
|
||||
"react/no-string-refs": 2,
|
||||
"react/jsx-indent": 0,
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
|
@ -5,14 +5,14 @@ import {
|
|||
SUCCESS_TOAST,
|
||||
WARNING_TOAST,
|
||||
DANGER_TOAST,
|
||||
} from '../util/constants';
|
||||
} from '../constants';
|
||||
|
||||
function getToastUuid(type) {
|
||||
export function getToastUuid(type) {
|
||||
return `${type}-${shortid.generate()}`;
|
||||
}
|
||||
|
||||
export const ADD_TOAST = 'ADD_TOAST';
|
||||
export function addToast({ toastType, text, duration }) {
|
||||
export function addToast({ toastType, text, duration = 8000 }) {
|
||||
return {
|
||||
type: ADD_TOAST,
|
||||
payload: {
|
||||
|
@ -50,10 +50,11 @@ export function addSuccessToast(text) {
|
|||
export const ADD_WARNING_TOAST = 'ADD_WARNING_TOAST';
|
||||
export function addWarningToast(text) {
|
||||
return dispatch =>
|
||||
dispatch(addToast({ text, toastType: WARNING_TOAST, duration: 4000 }));
|
||||
dispatch(addToast({ text, toastType: WARNING_TOAST, duration: 6000 }));
|
||||
}
|
||||
|
||||
export const ADD_DANGER_TOAST = 'ADD_DANGER_TOAST';
|
||||
export function addDangerToast(text) {
|
||||
return dispatch => dispatch(addToast({ text, toastType: DANGER_TOAST }));
|
||||
return dispatch =>
|
||||
dispatch(addToast({ text, toastType: DANGER_TOAST, duration: 8000 }));
|
||||
}
|
|
@ -3,13 +3,14 @@ import cx from 'classnames';
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
import { toastShape } from '../util/propShapes';
|
||||
import { toastShape } from '../propShapes';
|
||||
|
||||
import {
|
||||
INFO_TOAST,
|
||||
SUCCESS_TOAST,
|
||||
WARNING_TOAST,
|
||||
DANGER_TOAST,
|
||||
} from '../util/constants';
|
||||
} from '../constants';
|
||||
|
||||
const propTypes = {
|
||||
toast: toastShape.isRequired,
|
|
@ -2,7 +2,9 @@ import PropTypes from 'prop-types';
|
|||
import React from 'react';
|
||||
|
||||
import Toast from './Toast';
|
||||
import { toastShape } from '../util/propShapes';
|
||||
import { toastShape } from '../propShapes';
|
||||
|
||||
import '../stylesheets/toast.less';
|
||||
|
||||
const propTypes = {
|
||||
toasts: PropTypes.arrayOf(toastShape),
|
|
@ -0,0 +1,5 @@
|
|||
// Toast types
|
||||
export const INFO_TOAST = 'INFO_TOAST';
|
||||
export const SUCCESS_TOAST = 'SUCCESS_TOAST';
|
||||
export const WARNING_TOAST = 'WARNING_TOAST';
|
||||
export const DANGER_TOAST = 'DANGER_TOAST';
|
|
@ -2,7 +2,7 @@ import { bindActionCreators } from 'redux';
|
|||
import { connect } from 'react-redux';
|
||||
import ToastPresenter from '../components/ToastPresenter';
|
||||
|
||||
import { removeToast } from '../actions/messageToasts';
|
||||
import { removeToast } from '../actions';
|
||||
|
||||
export default connect(
|
||||
({ messageToasts: toasts }) => ({ toasts }),
|
|
@ -0,0 +1,26 @@
|
|||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import {
|
||||
addDangerToast,
|
||||
addInfoToast,
|
||||
addSuccessToast,
|
||||
addWarningToast,
|
||||
} from '../actions';
|
||||
|
||||
// To work properly the redux state must have a `messageToasts` subtree
|
||||
export default function withToasts(BaseComponent) {
|
||||
return connect(
|
||||
null,
|
||||
dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
addInfoToast,
|
||||
addSuccessToast,
|
||||
addWarningToast,
|
||||
addDangerToast,
|
||||
},
|
||||
dispatch,
|
||||
),
|
||||
)(BaseComponent);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
INFO_TOAST,
|
||||
SUCCESS_TOAST,
|
||||
WARNING_TOAST,
|
||||
DANGER_TOAST,
|
||||
} from './constants';
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const toastShape = PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
toastType: PropTypes.oneOf([
|
||||
INFO_TOAST,
|
||||
SUCCESS_TOAST,
|
||||
WARNING_TOAST,
|
||||
DANGER_TOAST,
|
||||
]).isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
duration: PropTypes.number,
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
import { ADD_TOAST, REMOVE_TOAST } from '../actions/messageToasts';
|
||||
import { ADD_TOAST, REMOVE_TOAST } from '../actions';
|
||||
|
||||
export default function messageToastsReducer(toasts = [], action) {
|
||||
switch (action.type) {
|
|
@ -1,3 +1,5 @@
|
|||
@import '../../dashboard/stylesheets/variables.less';
|
||||
|
||||
.toast-presenter {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
|
@ -16,7 +18,7 @@
|
|||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.35);
|
||||
will-change: transform, opacity;
|
||||
transform: translateY(-100%);
|
||||
transition: transform .3s, opacity .3s;
|
||||
transition: transform 0.3s, opacity 0.3s;
|
||||
}
|
||||
|
||||
.toast > button {
|
||||
|
@ -33,7 +35,7 @@
|
|||
}
|
||||
|
||||
.toast:after {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
|
@ -0,0 +1,22 @@
|
|||
import { addToast } from '../actions';
|
||||
import { INFO_TOAST, SUCCESS_TOAST, DANGER_TOAST } from '../constants';
|
||||
|
||||
export default function toastsFromPyFlashMessages(flashMessages = []) {
|
||||
const toasts = [];
|
||||
|
||||
flashMessages.forEach(([messageType, message]) => {
|
||||
const toastType =
|
||||
messageType === 'danger'
|
||||
? DANGER_TOAST
|
||||
: (messageType === 'success' && SUCCESS_TOAST) || INFO_TOAST;
|
||||
|
||||
const toast = addToast({
|
||||
text: message,
|
||||
toastType,
|
||||
}).payload;
|
||||
|
||||
toasts.push(toast);
|
||||
});
|
||||
|
||||
return toasts;
|
||||
}
|
|
@ -67,9 +67,8 @@ export function addToArr(state, arrKey, obj) {
|
|||
export function initEnhancer(persist = true) {
|
||||
let enhancer = persist ? compose(persistState()) : compose();
|
||||
if (process.env.NODE_ENV === 'dev') {
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
/* eslint-disable-next-line no-underscore-dangle */
|
||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||
/* eslint-enable */
|
||||
enhancer = persist ? composeEnhancers(persistState()) : composeEnhancers();
|
||||
}
|
||||
return enhancer;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
/* global notify */
|
||||
/* eslint global-require: 0 */
|
||||
import $ from 'jquery';
|
||||
|
||||
const d3 = window.d3 || require('d3');
|
||||
const d3 = require('d3');
|
||||
|
||||
export const EARTH_CIRCUMFERENCE_KM = 40075.16;
|
||||
export const LUMINANCE_RED_WEIGHT = 0.2126;
|
||||
|
@ -72,7 +71,7 @@ export function getParamsFromUrl() {
|
|||
return newParams;
|
||||
}
|
||||
|
||||
export function getShortUrl(longUrl, callback) {
|
||||
export function getShortUrl(longUrl, callback, onError) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/r/shortner/',
|
||||
|
@ -80,11 +79,11 @@ export function getShortUrl(longUrl, callback) {
|
|||
data: {
|
||||
data: '/' + longUrl,
|
||||
},
|
||||
success: (data) => {
|
||||
callback(data);
|
||||
},
|
||||
success: callback,
|
||||
error: () => {
|
||||
notify.error('Error getting the short URL');
|
||||
if (onError) {
|
||||
onError('Error getting the short URL');
|
||||
}
|
||||
callback(longUrl);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -391,8 +391,8 @@ acorn@^5.0.0, acorn@^5.5.0:
|
|||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8"
|
||||
|
||||
agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce"
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
|
||||
dependencies:
|
||||
es6-promisify "^5.0.0"
|
||||
|
||||
|
@ -427,8 +427,8 @@ ajv@^5.0.0, ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0:
|
|||
json-schema-traverse "^0.3.0"
|
||||
|
||||
ajv@^6.1.0:
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.1.tgz#88ebc1263c7133937d108b80c5572e64e1d9322d"
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360"
|
||||
dependencies:
|
||||
fast-deep-equal "^2.0.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
|
@ -938,8 +938,8 @@ babel-istanbul@^0.12.2:
|
|||
wordwrap "1.0.x"
|
||||
|
||||
babel-loader@^7.0.0:
|
||||
version "7.1.4"
|
||||
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.4.tgz#e3463938bd4e6d55d1c174c5485d406a188ed015"
|
||||
version "7.1.5"
|
||||
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68"
|
||||
dependencies:
|
||||
find-cache-dir "^1.0.0"
|
||||
loader-utils "^1.0.2"
|
||||
|
@ -1418,8 +1418,8 @@ base@^0.11.1:
|
|||
pascalcase "^0.1.1"
|
||||
|
||||
bcrypt-pbkdf@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
||||
dependencies:
|
||||
tweetnacl "^0.14.3"
|
||||
|
||||
|
@ -1507,8 +1507,8 @@ bops@0.0.6:
|
|||
to-utf8 "0.0.1"
|
||||
|
||||
bowser@^1.2.0, bowser@^1.7.3:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.3.tgz#6643ae4d783f31683f6d23156976b74183862162"
|
||||
version "1.9.4"
|
||||
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a"
|
||||
|
||||
boxen@^1.2.1:
|
||||
version "1.3.0"
|
||||
|
@ -1556,10 +1556,6 @@ braces@^2.3.0, braces@^2.3.1:
|
|||
split-string "^3.0.2"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
brcast@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/brcast/-/brcast-2.0.2.tgz#2db16de44140e418dc37fab10beec0369e78dcef"
|
||||
|
||||
brfs@^1.3.0, brfs@^1.4.3, brfs@^1.4.4:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3"
|
||||
|
@ -1778,12 +1774,12 @@ caniuse-api@^1.5.2:
|
|||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
version "1.0.30000856"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000856.tgz#fbebb99abe15a5654fc7747ebb5315bdfde3358f"
|
||||
version "1.0.30000864"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000864.tgz#35a4b2325a8d4553a46b516dbc233bf391d75555"
|
||||
|
||||
caniuse-lite@^1.0.30000844:
|
||||
version "1.0.30000856"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000856.tgz#ecc16978135a6f219b138991eb62009d25ee8daa"
|
||||
version "1.0.30000864"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000864.tgz#7a08c78da670f23c06f11aa918831b8f2dd60ddc"
|
||||
|
||||
capture-stack-trace@^1.0.0:
|
||||
version "1.0.0"
|
||||
|
@ -2181,8 +2177,8 @@ commander@2.9.0:
|
|||
graceful-readlink ">= 1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.9.0:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
version "2.16.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50"
|
||||
|
||||
commander@~2.13.0:
|
||||
version "2.13.0"
|
||||
|
@ -2505,8 +2501,8 @@ csso@~2.3.1:
|
|||
source-map "^0.5.3"
|
||||
|
||||
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b"
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797"
|
||||
|
||||
"cssstyle@>= 0.2.37 < 0.3.0":
|
||||
version "0.2.37"
|
||||
|
@ -2696,15 +2692,15 @@ datamaps@^0.5.8:
|
|||
topojson "^1.6.19"
|
||||
|
||||
datatables.net-bs@^1.10.15:
|
||||
version "1.10.18"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-bs/-/datatables.net-bs-1.10.18.tgz#72c9ebe926f9189f891d4c474a629defc99753e6"
|
||||
version "1.10.19"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net-bs/-/datatables.net-bs-1.10.19.tgz#08763b4e4d0cef1a427d019dc15e717c7ed67a4d"
|
||||
dependencies:
|
||||
datatables.net "1.10.18"
|
||||
datatables.net "1.10.19"
|
||||
jquery ">=1.7"
|
||||
|
||||
datatables.net@1.10.18:
|
||||
version "1.10.18"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.18.tgz#b6f045aa533101bcd33714e5338da8f905d3ef09"
|
||||
datatables.net@1.10.19:
|
||||
version "1.10.19"
|
||||
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.19.tgz#97a1ed41c85e62d61040603481b59790a172dd1f"
|
||||
dependencies:
|
||||
jquery ">=1.7"
|
||||
|
||||
|
@ -3023,8 +3019,8 @@ editor@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742"
|
||||
|
||||
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47:
|
||||
version "1.3.50"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.50.tgz#7438b76f92b41b919f3fbdd350fbd0757dacddf7"
|
||||
version "1.3.51"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.51.tgz#6a42b49daaf7f22a5b37b991daf949f34dbdb9b5"
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.4.0"
|
||||
|
@ -3270,8 +3266,8 @@ eslint-module-utils@^2.2.0:
|
|||
pkg-dir "^1.0.0"
|
||||
|
||||
eslint-plugin-import@^2.2.0:
|
||||
version "2.12.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz#dad31781292d6664b25317fd049d2e2b2f02205d"
|
||||
version "2.13.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz#df24f241175e312d91662dc91ca84064caec14ed"
|
||||
dependencies:
|
||||
contains-path "^0.1.0"
|
||||
debug "^2.6.8"
|
||||
|
@ -3297,20 +3293,20 @@ eslint-plugin-jsx-a11y@^5.1.1:
|
|||
jsx-ast-utils "^1.4.0"
|
||||
|
||||
eslint-plugin-prettier@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7"
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.1.tgz#de902b4a66b7bca24296429a59a1cc04020ccbbd"
|
||||
dependencies:
|
||||
fast-diff "^1.1.1"
|
||||
jest-docblock "^21.0.0"
|
||||
|
||||
eslint-plugin-react@^7.0.1:
|
||||
version "7.9.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.9.1.tgz#101aadd15e7c7b431ed025303ac7b421a8e3dc15"
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.10.0.tgz#af5c1fef31c4704db02098f9be18202993828b50"
|
||||
dependencies:
|
||||
doctrine "^2.1.0"
|
||||
has "^1.0.2"
|
||||
has "^1.0.3"
|
||||
jsx-ast-utils "^2.0.1"
|
||||
prop-types "^15.6.1"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
eslint-restricted-globals@^0.1.1:
|
||||
version "0.1.1"
|
||||
|
@ -3580,10 +3576,6 @@ fast-levenshtein@~2.0.4:
|
|||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||
|
||||
fast-memoize@^2.2.7:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.4.0.tgz#2f79eca41c41112b0b70cf53ac3940e206574648"
|
||||
|
||||
fastdom@^1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/fastdom/-/fastdom-1.0.8.tgz#10f9d36998fd6efae30e529597d788e750c9febb"
|
||||
|
@ -3600,7 +3592,7 @@ fault@^1.0.2:
|
|||
dependencies:
|
||||
format "^0.2.2"
|
||||
|
||||
fbjs@^0.8.1, fbjs@^0.8.12, fbjs@^0.8.4, fbjs@^0.8.9:
|
||||
fbjs@^0.8.1, fbjs@^0.8.4, fbjs@^0.8.9:
|
||||
version "0.8.17"
|
||||
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
|
||||
dependencies:
|
||||
|
@ -4087,26 +4079,6 @@ gl-vec4@^1.0.0, gl-vec4@^1.0.1:
|
|||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gl-vec4/-/gl-vec4-1.0.1.tgz#97d96878281b14b532cbce101785dfd1cb340964"
|
||||
|
||||
glamor@^2.20.24:
|
||||
version "2.20.40"
|
||||
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.40.tgz#f606660357b7cf18dface731ad1a2cfa93817f05"
|
||||
dependencies:
|
||||
fbjs "^0.8.12"
|
||||
inline-style-prefixer "^3.0.6"
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.5.10"
|
||||
through "^2.3.8"
|
||||
|
||||
glamorous@^3.13.1:
|
||||
version "3.25.0"
|
||||
resolved "https://registry.yarnpkg.com/glamorous/-/glamorous-3.25.0.tgz#d6d66c3dfffdc194761469adcbd996d4b70222e1"
|
||||
dependencies:
|
||||
brcast "^2.0.0"
|
||||
fast-memoize "^2.2.7"
|
||||
html-tag-names "^1.1.1"
|
||||
react-html-attributes "^1.3.0"
|
||||
svg-tag-names "^1.1.0"
|
||||
|
||||
glob-base@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
|
||||
|
@ -4344,7 +4316,7 @@ has-values@^1.0.0:
|
|||
is-number "^3.0.0"
|
||||
kind-of "^4.0.0"
|
||||
|
||||
has@^1.0.1, has@^1.0.2:
|
||||
has@^1.0.1, has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
dependencies:
|
||||
|
@ -4440,8 +4412,8 @@ home-or-tmp@^2.0.0:
|
|||
os-tmpdir "^1.0.1"
|
||||
|
||||
hosted-git-info@^2.1.4, hosted-git-info@^2.1.5, hosted-git-info@^2.4.2, hosted-git-info@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222"
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.1.tgz#6e4cee78b01bb849dcf93527708c69fdbee410df"
|
||||
|
||||
hosted-git-info@~2.1.5:
|
||||
version "2.1.5"
|
||||
|
@ -4451,20 +4423,12 @@ html-comment-regex@^1.1.0:
|
|||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e"
|
||||
|
||||
html-element-attributes@^1.0.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/html-element-attributes/-/html-element-attributes-1.3.1.tgz#9fa6a2e37e6b61790a303e87ddbbb9746e8c035f"
|
||||
|
||||
html-encoding-sniffer@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
|
||||
dependencies:
|
||||
whatwg-encoding "^1.0.1"
|
||||
|
||||
html-tag-names@^1.1.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/html-tag-names/-/html-tag-names-1.1.3.tgz#f81f75e59d626cb8a958a19e58f90c1d69707b82"
|
||||
|
||||
htmlparser2@^3.9.1:
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
|
||||
|
@ -4767,8 +4731,8 @@ is-builtin-module@^1.0.0:
|
|||
builtin-modules "^1.0.0"
|
||||
|
||||
is-callable@^1.1.1, is-callable@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
|
||||
|
||||
is-ci@^1.0.10:
|
||||
version "1.1.0"
|
||||
|
@ -4933,12 +4897,6 @@ is-object@~0.1.2:
|
|||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/is-object/-/is-object-0.1.2.tgz#00efbc08816c33cfc4ac8251d132e10dc65098d7"
|
||||
|
||||
is-odd@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24"
|
||||
dependencies:
|
||||
is-number "^4.0.0"
|
||||
|
||||
is-path-cwd@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
|
||||
|
@ -5812,7 +5770,7 @@ math-random@^1.0.1:
|
|||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac"
|
||||
|
||||
math.gl@^1.1.0, math.gl@^1.1.3, math.gl@^1.2.1:
|
||||
math.gl@^1.1.0, math.gl@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/math.gl/-/math.gl-1.2.1.tgz#3c7da0ae4f3383116c24bc183533cc4d7b8065a9"
|
||||
dependencies:
|
||||
|
@ -5823,6 +5781,17 @@ math.gl@^1.1.0, math.gl@^1.1.3, math.gl@^1.2.1:
|
|||
gl-vec3 "^1.0.3"
|
||||
gl-vec4 "^1.0.1"
|
||||
|
||||
math.gl@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/math.gl/-/math.gl-2.0.0.tgz#c41cf8f5cfce820161511c435d3f706eebd7deb0"
|
||||
dependencies:
|
||||
gl-mat3 "^1.0.0"
|
||||
gl-mat4 "^1.1.4"
|
||||
gl-quat "^1.0.0"
|
||||
gl-vec2 "^1.0.0"
|
||||
gl-vec3 "^1.0.3"
|
||||
gl-vec4 "^1.0.1"
|
||||
|
||||
mathfn@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mathfn/-/mathfn-1.0.1.tgz#650a0b183b0102debe94e42a807dc6b4d2cc57bd"
|
||||
|
@ -6105,20 +6074,15 @@ nan@^2.9.2:
|
|||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
|
||||
|
||||
nanoid@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-0.2.2.tgz#e2ebc6ad3db5e0454fd8124d30ca39b06555fe56"
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.9"
|
||||
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2"
|
||||
version "1.2.13"
|
||||
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
||||
dependencies:
|
||||
arr-diff "^4.0.0"
|
||||
array-unique "^0.3.2"
|
||||
define-property "^2.0.2"
|
||||
extend-shallow "^3.0.2"
|
||||
fragment-cache "^0.2.1"
|
||||
is-odd "^2.0.0"
|
||||
is-windows "^1.0.2"
|
||||
kind-of "^6.0.2"
|
||||
object.pick "^1.3.0"
|
||||
|
@ -6243,8 +6207,8 @@ node-libs-browser@^2.0.0:
|
|||
vm-browserify "0.0.4"
|
||||
|
||||
node-pre-gyp@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz#6e4ef5bb5c5203c6552448828c852c40111aac46"
|
||||
version "0.10.2"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.2.tgz#e8945c20ef6795a20aac2b44f036eb13cf5146e3"
|
||||
dependencies:
|
||||
detect-libc "^1.0.2"
|
||||
mkdirp "^0.5.1"
|
||||
|
@ -6252,7 +6216,7 @@ node-pre-gyp@^0.10.0:
|
|||
nopt "^4.0.1"
|
||||
npm-packlist "^1.1.6"
|
||||
npmlog "^4.0.2"
|
||||
rc "^1.1.7"
|
||||
rc "^1.2.7"
|
||||
rimraf "^2.6.1"
|
||||
semver "^5.3.0"
|
||||
tar "^4"
|
||||
|
@ -7444,8 +7408,8 @@ preserve@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
|
||||
|
||||
prettier@^1.12.1:
|
||||
version "1.13.5"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.5.tgz#7ae2076998c8edce79d63834e9b7b09fead6bfd0"
|
||||
version "1.13.7"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281"
|
||||
|
||||
prismjs@^1.8.4:
|
||||
version "1.15.0"
|
||||
|
@ -7522,7 +7486,7 @@ prop-types@15.5.10:
|
|||
fbjs "^0.8.9"
|
||||
loose-envify "^1.3.1"
|
||||
|
||||
prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1:
|
||||
prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
|
||||
version "15.6.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
|
||||
dependencies:
|
||||
|
@ -7704,7 +7668,7 @@ rc-config-loader@^2.0.1:
|
|||
path-exists "^2.1.0"
|
||||
require-from-string "^2.0.1"
|
||||
|
||||
rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
|
||||
rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||
dependencies:
|
||||
|
@ -7714,8 +7678,8 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
|
|||
strip-json-comments "~2.0.1"
|
||||
|
||||
re-resizable@^4.3.1:
|
||||
version "4.5.1"
|
||||
resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-4.5.1.tgz#4688e8311ea4b70d558f7aebb3168a25926e62d9"
|
||||
version "4.7.1"
|
||||
resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-4.7.1.tgz#3eca5bb94a6059d14311786cfd2d430bc9f7fba0"
|
||||
|
||||
react-ace@^5.10.0:
|
||||
version "5.10.0"
|
||||
|
@ -7743,15 +7707,6 @@ react-addons-test-utils@^15.6.2:
|
|||
version "15.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz#c12b6efdc2247c10da7b8770d185080a7b047156"
|
||||
|
||||
react-alert@^2.3.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/react-alert/-/react-alert-2.4.0.tgz#b4c9ce74919b46be330a7addbf46e7561c295bc7"
|
||||
dependencies:
|
||||
glamor "^2.20.24"
|
||||
glamorous "^3.13.1"
|
||||
nanoid "^0.2.2"
|
||||
react-transition-group "^1.1.2"
|
||||
|
||||
react-bootstrap-slider@2.1.5:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/react-bootstrap-slider/-/react-bootstrap-slider-2.1.5.tgz#2f79e57b69ddf2b5bd23310bddbd2de0c6bdfef3"
|
||||
|
@ -7853,12 +7808,6 @@ react-grid-layout@0.16.6:
|
|||
react-draggable "3.x"
|
||||
react-resizable "1.x"
|
||||
|
||||
react-html-attributes@^1.3.0:
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/react-html-attributes/-/react-html-attributes-1.4.2.tgz#0d2ccf134fc79b2d3543837dc1591d32b7b903f9"
|
||||
dependencies:
|
||||
html-element-attributes "^1.0.0"
|
||||
|
||||
react-input-autosize@^2.1.2:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8"
|
||||
|
@ -7874,14 +7823,14 @@ react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4:
|
|||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
|
||||
react-map-gl@^3.0.4:
|
||||
version "3.2.10"
|
||||
resolved "https://registry.yarnpkg.com/react-map-gl/-/react-map-gl-3.2.10.tgz#30ce9a26be4aea659c4fef981962ceb6feebe28a"
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-map-gl/-/react-map-gl-3.3.0.tgz#dad906ec4c56a51873884325c44025d49516a9ea"
|
||||
dependencies:
|
||||
babel-runtime "^6.23.0"
|
||||
bowser "^1.2.0"
|
||||
immutable "^3.8.2"
|
||||
mapbox-gl "0.45"
|
||||
math.gl "^1.1.3"
|
||||
math.gl "^1.1.0"
|
||||
mjolnir.js "^1.2.1"
|
||||
prop-types "^15.5.7"
|
||||
viewport-mercator-project "^5.1.0"
|
||||
|
@ -7897,8 +7846,8 @@ react-markdown@^3.3.0:
|
|||
xtend "^4.0.1"
|
||||
|
||||
react-modal@^3.1.7:
|
||||
version "3.4.5"
|
||||
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.4.5.tgz#75a7eefb8f4c8247278d5ce1c41249d7785d9f69"
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.5.1.tgz#33d38527def90ea324848f7d63e53acc4468a451"
|
||||
dependencies:
|
||||
exenv "^1.2.0"
|
||||
prop-types "^15.5.10"
|
||||
|
@ -7973,16 +7922,17 @@ react-sortable-hoc@^0.8.3:
|
|||
prop-types "^15.5.7"
|
||||
|
||||
react-split-pane@^0.1.63, react-split-pane@^0.1.66:
|
||||
version "0.1.77"
|
||||
resolved "https://registry.yarnpkg.com/react-split-pane/-/react-split-pane-0.1.77.tgz#f0c8cd18d076bbac900248dcf6dbcec02d5340db"
|
||||
version "0.1.81"
|
||||
resolved "https://registry.yarnpkg.com/react-split-pane/-/react-split-pane-0.1.81.tgz#b1e8b82e0a6edd10f18fd639a5f512db3cbbb4e6"
|
||||
dependencies:
|
||||
inline-style-prefixer "^3.0.6"
|
||||
prop-types "^15.5.10"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
react-style-proptype "^3.0.0"
|
||||
|
||||
react-sticky@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-sticky/-/react-sticky-6.0.2.tgz#d301c1b5307649220dbc045fcbacd077885c5ede"
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/react-sticky/-/react-sticky-6.0.3.tgz#7a18b643e1863da113d7f7036118d2a75d9ecde4"
|
||||
dependencies:
|
||||
prop-types "^15.5.8"
|
||||
raf "^3.3.0"
|
||||
|
@ -8010,7 +7960,7 @@ react-test-renderer@^15.6.2:
|
|||
fbjs "^0.8.9"
|
||||
object-assign "^4.1.0"
|
||||
|
||||
react-transition-group@^1.1.2, react-transition-group@^1.2.0:
|
||||
react-transition-group@^1.2.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-1.2.1.tgz#e11f72b257f921b213229a774df46612346c7ca6"
|
||||
dependencies:
|
||||
|
@ -8901,8 +8851,8 @@ socks@^1.1.10:
|
|||
smart-buffer "^1.0.13"
|
||||
|
||||
socks@~2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.0.tgz#144985b3331ced3ab5ccbee640ab7cb7d43fdd1f"
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9"
|
||||
dependencies:
|
||||
ip "^1.1.5"
|
||||
smart-buffer "^4.0.1"
|
||||
|
@ -9269,10 +9219,6 @@ supports-color@^5.1.0, supports-color@^5.3.0, supports-color@^5.4.0:
|
|||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
svg-tag-names@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/svg-tag-names/-/svg-tag-names-1.1.1.tgz#9641b29ef71025ee094c7043f7cdde7d99fbd50a"
|
||||
|
||||
svgo@^0.7.0:
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"
|
||||
|
@ -9360,7 +9306,7 @@ through2@~0.6.3:
|
|||
readable-stream ">=1.0.33-1 <1.1.0-0"
|
||||
xtend ">=4.0.0 <4.1.0-0"
|
||||
|
||||
through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8, through@~2.3.4:
|
||||
through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
|
||||
|
@ -9442,8 +9388,8 @@ topojson@^1.6.19:
|
|||
shapefile "0.3"
|
||||
|
||||
tough-cookie@^2.3.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.2.tgz#aa9133154518b494efab98a58247bfc38818c00c"
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
||||
dependencies:
|
||||
psl "^1.1.24"
|
||||
punycode "^1.4.1"
|
||||
|
@ -9557,8 +9503,8 @@ uglifyjs-webpack-plugin@^0.4.6:
|
|||
webpack-sources "^1.0.1"
|
||||
|
||||
uglifyjs-webpack-plugin@^1.1.0:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.6.tgz#f4bb44f02431e82b301d8d4624330a6a35729381"
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.7.tgz#57638dd99c853a1ebfe9d97b42160a8a507f9d00"
|
||||
dependencies:
|
||||
cacache "^10.0.4"
|
||||
find-cache-dir "^1.0.0"
|
||||
|
@ -9768,8 +9714,8 @@ util@^0.10.3:
|
|||
inherits "2.0.3"
|
||||
|
||||
uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0, uuid@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||
|
||||
v8flags@^2.1.1:
|
||||
version "2.1.1"
|
||||
|
@ -9828,10 +9774,10 @@ vfile@^2.0.0:
|
|||
vfile-message "^1.0.0"
|
||||
|
||||
viewport-mercator-project@^5.0.0, viewport-mercator-project@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/viewport-mercator-project/-/viewport-mercator-project-5.1.0.tgz#68bc5586988c2808d1456e1eff950d424eccec16"
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/viewport-mercator-project/-/viewport-mercator-project-5.2.0.tgz#2c50bc624a085d01a3a486f22ec329c0511fe4bd"
|
||||
dependencies:
|
||||
math.gl "^1.1.0"
|
||||
math.gl "^2.0.0"
|
||||
|
||||
vlq@^0.2.2:
|
||||
version "0.2.3"
|
||||
|
@ -10089,8 +10035,8 @@ yargs-parser@^9.0.2:
|
|||
camelcase "^4.1.0"
|
||||
|
||||
yargs@^11.0.0:
|
||||
version "11.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b"
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"
|
||||
dependencies:
|
||||
cliui "^4.0.0"
|
||||
decamelize "^1.1.1"
|
||||
|
|
Loading…
Reference in New Issue