diff --git a/superset/assets/.eslintrc b/superset/assets/.eslintrc
index c4f14916768..34cbfe9611c 100644
--- a/superset/assets/.eslintrc
+++ b/superset/assets/.eslintrc
@@ -17,7 +17,7 @@
* under the License.
*/
{
- "extends": "airbnb",
+ "extends": ["airbnb", "prettier"],
"parser": "babel-eslint",
"parserOptions": {
"ecmaFeatures": {
@@ -27,7 +27,7 @@
"env": {
"browser": true
},
- "plugins": ["react"],
+ "plugins": ["prettier", "react"],
"rules": {
"camelcase": [
"error",
@@ -77,7 +77,8 @@
"react/no-unused-prop-types": 0,
"react/require-default-props": 0,
"react/jsx-fragments": 1,
- "react/prop-types": 0
+ "react/prop-types": 0,
+ "prettier/prettier": "error"
},
"settings": {
"import/resolver": "webpack",
diff --git a/superset/assets/spec/javascripts/dashboard/.prettierrc b/superset/assets/.prettierrc
similarity index 100%
rename from superset/assets/spec/javascripts/dashboard/.prettierrc
rename to superset/assets/.prettierrc
diff --git a/superset/assets/cypress/integration/dashboard/controls.js b/superset/assets/cypress/integration/dashboard/controls.js
index 08402bcbbe3..aa04410173a 100644
--- a/superset/assets/cypress/integration/dashboard/controls.js
+++ b/superset/assets/cypress/integration/dashboard/controls.js
@@ -19,85 +19,105 @@
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
import readResponseBlob from '../../utils/readResponseBlob';
-export default () => describe('top-level controls', () => {
- const sliceRequests = [];
- const forceRefreshRequests = [];
- let mapId;
+export default () =>
+ describe('top-level controls', () => {
+ const sliceRequests = [];
+ const forceRefreshRequests = [];
+ let mapId;
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.visit(WORLD_HEALTH_DASHBOARD);
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.visit(WORLD_HEALTH_DASHBOARD);
- cy.get('#app').then((data) => {
- const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
- const dashboard = bootstrapData.dashboard_data;
- mapId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'world_map')).slice_id;
+ cy.get('#app').then(data => {
+ const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
+ const dashboard = bootstrapData.dashboard_data;
+ mapId = dashboard.slices.find(
+ slice => slice.form_data.viz_type === 'world_map',
+ ).slice_id;
- dashboard.slices
- .forEach((slice) => {
+ dashboard.slices.forEach(slice => {
const sliceRequest = `getJson_${slice.slice_id}`;
sliceRequests.push(`@${sliceRequest}`);
const formData = `{"slice_id":${slice.slice_id}}`;
- cy.route('POST', `/superset/explore_json/?form_data=${formData}`).as(sliceRequest);
+ cy.route('POST', `/superset/explore_json/?form_data=${formData}`).as(
+ sliceRequest,
+ );
const forceRefresh = `postJson_${slice.slice_id}_force`;
forceRefreshRequests.push(`@${forceRefresh}`);
- cy.route('POST', `/superset/explore_json/?form_data={"slice_id":${slice.slice_id}}&force=true`).as(forceRefresh);
- });
- });
- });
- afterEach(() => {
- sliceRequests.length = 0;
- forceRefreshRequests.length = 0;
- });
-
- it.skip('should allow chart level refresh', () => {
- cy.wait(sliceRequests);
- cy.get('.grid-container .world_map').should('be.exist');
- cy.get(`#slice_${mapId}-controls`).click();
- cy.get(`#slice_${mapId}-controls`).next()
- .find('.refresh-tooltip').trigger('click', { force: true });
-
- // not allow dashboard level force refresh when any chart is loading
- cy.get('#save-dash-split-button').trigger('click', { force: true });
- cy.contains('Force refresh dashboard').parent().should('have.class', 'disabled');
- // not allow chart level force refresh when it is loading
- cy.get(`#slice_${mapId}-controls`).next()
- .find('.refresh-tooltip')
- .parent()
- .parent()
- .should('have.class', 'disabled');
-
- cy.wait(`@postJson_${mapId}_force`);
- cy.get('#save-dash-split-button').trigger('click');
- cy.contains('Force refresh dashboard').parent().not('have.class', 'disabled');
- });
-
- it.skip('should allow dashboard level force refresh', () => {
- // when charts are not start loading, for example, under a secondary tab,
- // should allow force refresh
- cy.get('#save-dash-split-button').trigger('click');
- cy.contains('Force refresh dashboard').parent().not('have.class', 'disabled');
-
- // wait the all dash finish loading.
- cy.wait(sliceRequests);
- cy.get('#save-dash-split-button').trigger('click');
- cy.contains('Force refresh dashboard').trigger('click', { force: true });
- cy.get('#save-dash-split-button').trigger('click');
- cy.contains('Force refresh dashboard').parent().should('have.class', 'disabled');
-
- // wait all charts force refreshed
- cy.wait(forceRefreshRequests).then((xhrs) => {
- // is_cached in response should be false
- xhrs.forEach((xhr) => {
- readResponseBlob(xhr.response.body).then((responseBody) => {
- expect(responseBody.is_cached).to.equal(false);
+ cy.route(
+ 'POST',
+ `/superset/explore_json/?form_data={"slice_id":${slice.slice_id}}&force=true`,
+ ).as(forceRefresh);
});
});
});
+ afterEach(() => {
+ sliceRequests.length = 0;
+ forceRefreshRequests.length = 0;
+ });
- cy.get('#save-dash-split-button').trigger('click');
- cy.contains('Force refresh dashboard').parent().not('have.class', 'disabled');
+ it.skip('should allow chart level refresh', () => {
+ cy.wait(sliceRequests);
+ cy.get('.grid-container .world_map').should('be.exist');
+ cy.get(`#slice_${mapId}-controls`).click();
+ cy.get(`#slice_${mapId}-controls`)
+ .next()
+ .find('.refresh-tooltip')
+ .trigger('click', { force: true });
+
+ // not allow dashboard level force refresh when any chart is loading
+ cy.get('#save-dash-split-button').trigger('click', { force: true });
+ cy.contains('Force refresh dashboard')
+ .parent()
+ .should('have.class', 'disabled');
+ // not allow chart level force refresh when it is loading
+ cy.get(`#slice_${mapId}-controls`)
+ .next()
+ .find('.refresh-tooltip')
+ .parent()
+ .parent()
+ .should('have.class', 'disabled');
+
+ cy.wait(`@postJson_${mapId}_force`);
+ cy.get('#save-dash-split-button').trigger('click');
+ cy.contains('Force refresh dashboard')
+ .parent()
+ .not('have.class', 'disabled');
+ });
+
+ it.skip('should allow dashboard level force refresh', () => {
+ // when charts are not start loading, for example, under a secondary tab,
+ // should allow force refresh
+ cy.get('#save-dash-split-button').trigger('click');
+ cy.contains('Force refresh dashboard')
+ .parent()
+ .not('have.class', 'disabled');
+
+ // wait the all dash finish loading.
+ cy.wait(sliceRequests);
+ cy.get('#save-dash-split-button').trigger('click');
+ cy.contains('Force refresh dashboard').trigger('click', { force: true });
+ cy.get('#save-dash-split-button').trigger('click');
+ cy.contains('Force refresh dashboard')
+ .parent()
+ .should('have.class', 'disabled');
+
+ // wait all charts force refreshed
+ cy.wait(forceRefreshRequests).then(xhrs => {
+ // is_cached in response should be false
+ xhrs.forEach(xhr => {
+ readResponseBlob(xhr.response.body).then(responseBody => {
+ expect(responseBody.is_cached).to.equal(false);
+ });
+ });
+ });
+
+ cy.get('#save-dash-split-button').trigger('click');
+ cy.contains('Force refresh dashboard')
+ .parent()
+ .not('have.class', 'disabled');
+ });
});
-});
diff --git a/superset/assets/cypress/integration/dashboard/dashboard.helper.js b/superset/assets/cypress/integration/dashboard/dashboard.helper.js
index 1c16a829012..250eb5e15c0 100644
--- a/superset/assets/cypress/integration/dashboard/dashboard.helper.js
+++ b/superset/assets/cypress/integration/dashboard/dashboard.helper.js
@@ -19,5 +19,5 @@
export const WORLD_HEALTH_DASHBOARD = '/superset/dashboard/world_health/';
export const TABBED_DASHBOARD = '/superset/dashboard/tabbed_dash/';
-export const CHECK_DASHBOARD_FAVORITE_ENDPOINT = '/superset/favstar/Dashboard/*/count';
-
+export const CHECK_DASHBOARD_FAVORITE_ENDPOINT =
+ '/superset/favstar/Dashboard/*/count';
diff --git a/superset/assets/cypress/integration/dashboard/edit_mode.js b/superset/assets/cypress/integration/dashboard/edit_mode.js
index 79198e60af3..c279cc5f093 100644
--- a/superset/assets/cypress/integration/dashboard/edit_mode.js
+++ b/superset/assets/cypress/integration/dashboard/edit_mode.js
@@ -18,64 +18,83 @@
*/
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
-export default () => describe('edit mode', () => {
- beforeEach(() => {
- cy.server();
- cy.login();
+export default () =>
+ describe('edit mode', () => {
+ beforeEach(() => {
+ cy.server();
+ cy.login();
- cy.visit(WORLD_HEALTH_DASHBOARD);
- cy.get('#app').then((data) => {
- const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
- const dashboard = bootstrapData.dashboard_data;
- const boxplotChartId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'box_plot')).slice_id;
- const formData = `{"slice_id":${boxplotChartId}}`;
- const boxplotRequest = `/superset/explore_json/?form_data=${formData}`;
- cy.route('POST', boxplotRequest).as('boxplotRequest');
+ cy.visit(WORLD_HEALTH_DASHBOARD);
+ cy.get('#app').then(data => {
+ const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
+ const dashboard = bootstrapData.dashboard_data;
+ const boxplotChartId = dashboard.slices.find(
+ slice => slice.form_data.viz_type === 'box_plot',
+ ).slice_id;
+ const formData = `{"slice_id":${boxplotChartId}}`;
+ const boxplotRequest = `/superset/explore_json/?form_data=${formData}`;
+ cy.route('POST', boxplotRequest).as('boxplotRequest');
+ });
+
+ cy.get('.dashboard-header')
+ .contains('Edit dashboard')
+ .click();
});
- cy.get('.dashboard-header').contains('Edit dashboard').click();
- });
+ it('remove, and add chart flow', () => {
+ // wait box_plot data and find box plot
+ cy.wait('@boxplotRequest');
+ cy.get('.grid-container .box_plot').should('be.exist');
- it('remove, and add chart flow', () => {
- // wait box_plot data and find box plot
- cy.wait('@boxplotRequest');
- cy.get('.grid-container .box_plot').should('be.exist');
+ cy.get('.fa.fa-trash')
+ .last()
+ .then($el => {
+ cy.wrap($el)
+ .invoke('show')
+ .click();
- cy.get('.fa.fa-trash').last().then(($el) => {
- cy.wrap($el).invoke('show').click();
+ // box plot should be gone
+ cy.get('.grid-container .box_plot').should('not.exist');
+ });
- // box plot should be gone
- cy.get('.grid-container .box_plot').should('not.exist');
+ // open charts list
+ cy.get('.component-layer')
+ .contains('Your charts & filters')
+ .click();
+
+ // find box plot is available from list
+ cy.get('.slices-layer')
+ .find('.chart-card-container')
+ .contains('Box plot');
+
+ // drag-n-drop
+ const dataTransfer = { data: {} };
+ cy.get('.dragdroppable')
+ .contains('Box plot')
+ .trigger('mousedown', { which: 1 })
+ .trigger('dragstart', { dataTransfer })
+ .trigger('drag', {});
+ cy.get('.grid-content .dragdroppable')
+ .last()
+ .trigger('dragover', { dataTransfer })
+ .trigger('drop', { dataTransfer })
+ .trigger('dragend', { dataTransfer })
+ .trigger('mouseup', { which: 1 });
+
+ // add back to dashboard
+ cy.get('.grid-container .box_plot').should('be.exist');
+
+ // should show Save changes button
+ cy.get('.dashboard-header .button-container').contains('Save changes');
+
+ // undo 2 steps
+ cy.get('.dashboard-header .undo-action')
+ .click()
+ .click();
+
+ // no changes, can switch to view mode
+ cy.get('.dashboard-header .button-container')
+ .contains('Switch to view mode')
+ .click();
});
-
- // open charts list
- cy.get('.component-layer').contains('Your charts & filters').click();
-
- // find box plot is available from list
- cy.get('.slices-layer').find('.chart-card-container').contains('Box plot');
-
- // drag-n-drop
- const dataTransfer = { data: {} };
- cy.get('.dragdroppable').contains('Box plot')
- .trigger('mousedown', { which: 1 })
- .trigger('dragstart', { dataTransfer })
- .trigger('drag', {});
- cy.get('.grid-content .dragdroppable').last()
- .trigger('dragover', { dataTransfer })
- .trigger('drop', { dataTransfer })
- .trigger('dragend', { dataTransfer })
- .trigger('mouseup', { which: 1 });
-
- // add back to dashboard
- cy.get('.grid-container .box_plot').should('be.exist');
-
- // should show Save changes button
- cy.get('.dashboard-header .button-container').contains('Save changes');
-
- // undo 2 steps
- cy.get('.dashboard-header .undo-action').click().click();
-
- // no changes, can switch to view mode
- cy.get('.dashboard-header .button-container').contains('Switch to view mode').click();
});
-});
diff --git a/superset/assets/cypress/integration/dashboard/fav_star.js b/superset/assets/cypress/integration/dashboard/fav_star.js
index 27d88fb5d59..2a007f49b14 100644
--- a/superset/assets/cypress/integration/dashboard/fav_star.js
+++ b/superset/assets/cypress/integration/dashboard/fav_star.js
@@ -16,38 +16,50 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { WORLD_HEALTH_DASHBOARD, CHECK_DASHBOARD_FAVORITE_ENDPOINT } from './dashboard.helper';
+import {
+ WORLD_HEALTH_DASHBOARD,
+ CHECK_DASHBOARD_FAVORITE_ENDPOINT,
+} from './dashboard.helper';
-export default () => describe('favorite dashboard', () => {
- let isFavoriteDashboard = false;
+export default () =>
+ describe('favorite dashboard', () => {
+ let isFavoriteDashboard = false;
- beforeEach(() => {
- cy.server();
- cy.login();
+ beforeEach(() => {
+ cy.server();
+ cy.login();
- cy.route(CHECK_DASHBOARD_FAVORITE_ENDPOINT).as('countFavStar');
- cy.visit(WORLD_HEALTH_DASHBOARD);
+ cy.route(CHECK_DASHBOARD_FAVORITE_ENDPOINT).as('countFavStar');
+ cy.visit(WORLD_HEALTH_DASHBOARD);
- cy.wait('@countFavStar').then((xhr) => {
- isFavoriteDashboard = xhr.response.body.count === 1;
+ cy.wait('@countFavStar').then(xhr => {
+ isFavoriteDashboard = xhr.response.body.count === 1;
+ });
+ });
+
+ it('should allow favor/unfavor', () => {
+ if (!isFavoriteDashboard) {
+ cy.get('.favstar')
+ .find('i')
+ .should('have.class', 'fa-star-o');
+ cy.get('.favstar').trigger('click');
+ cy.get('.favstar')
+ .find('i')
+ .should('have.class', 'fa-star')
+ .and('not.have.class', 'fa-star-o');
+ } else {
+ cy.get('.favstar')
+ .find('i')
+ .should('have.class', 'fa-star')
+ .and('not.have.class', 'fa-star-o');
+ cy.get('.favstar').trigger('click');
+ cy.get('.fave-unfave-icon')
+ .find('i')
+ .should('have.class', 'fa-star-o')
+ .and('not.have.class', 'fa-star');
+ }
+
+ // reset to original fav state
+ cy.get('.favstar').trigger('click');
});
});
-
- it('should allow favor/unfavor', () => {
- if (!isFavoriteDashboard) {
- cy.get('.favstar').find('i').should('have.class', 'fa-star-o');
- cy.get('.favstar').trigger('click');
- cy.get('.favstar').find('i').should('have.class', 'fa-star')
- .and('not.have.class', 'fa-star-o');
- } else {
- cy.get('.favstar').find('i').should('have.class', 'fa-star')
- .and('not.have.class', 'fa-star-o');
- cy.get('.favstar').trigger('click');
- cy.get('.fave-unfave-icon').find('i').should('have.class', 'fa-star-o')
- .and('not.have.class', 'fa-star');
- }
-
- // reset to original fav state
- cy.get('.favstar').trigger('click');
- });
-});
diff --git a/superset/assets/cypress/integration/dashboard/filter.js b/superset/assets/cypress/integration/dashboard/filter.js
index 97b40a4150c..6da7de22d3e 100644
--- a/superset/assets/cypress/integration/dashboard/filter.js
+++ b/superset/assets/cypress/integration/dashboard/filter.js
@@ -18,53 +18,63 @@
*/
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
-export default () => describe('dashboard filter', () => {
- let sliceIds = [];
- let filterId;
+export default () =>
+ describe('dashboard filter', () => {
+ let sliceIds = [];
+ let filterId;
- beforeEach(() => {
- cy.server();
- cy.login();
+ beforeEach(() => {
+ cy.server();
+ cy.login();
- cy.visit(WORLD_HEALTH_DASHBOARD);
+ cy.visit(WORLD_HEALTH_DASHBOARD);
- cy.get('#app').then((data) => {
- const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
- const dashboard = bootstrapData.dashboard_data;
- sliceIds = dashboard.slices.map(slice => (slice.slice_id));
- filterId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'filter_box')).slice_id;
- });
- });
-
- it('should apply filter', () => {
- const aliases = [];
-
- const formData = `{"slice_id":${filterId}}`;
- const filterRoute = `/superset/explore_json/?form_data=${formData}`;
- cy.route('POST', filterRoute).as('fetchFilter');
- cy.wait('@fetchFilter');
- sliceIds
- .filter(id => (parseInt(id, 10) !== filterId))
- .forEach((id) => {
- const alias = `getJson_${id}`;
- aliases.push(`@${alias}`);
-
- cy.route('POST', `/superset/explore_json/?form_data={"slice_id":${id}}`).as(alias);
+ cy.get('#app').then(data => {
+ const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
+ const dashboard = bootstrapData.dashboard_data;
+ sliceIds = dashboard.slices.map(slice => slice.slice_id);
+ filterId = dashboard.slices.find(
+ slice => slice.form_data.viz_type === 'filter_box',
+ ).slice_id;
});
+ });
- // select filter_box and apply
- cy.get('.Select-control')
- .first().find('input')
- .first()
- .type('South Asia{enter}', { force: true });
+ it('should apply filter', () => {
+ const aliases = [];
- cy.wait(aliases).then((requests) => {
- requests.forEach((xhr) => {
- const requestFormData = xhr.request.body;
- const requestParams = JSON.parse(requestFormData.get('form_data'));
- expect(requestParams.extra_filters[0])
- .deep.eq({ col: 'region', op: 'in', val: ['South Asia'] });
+ const formData = `{"slice_id":${filterId}}`;
+ const filterRoute = `/superset/explore_json/?form_data=${formData}`;
+ cy.route('POST', filterRoute).as('fetchFilter');
+ cy.wait('@fetchFilter');
+ sliceIds
+ .filter(id => parseInt(id, 10) !== filterId)
+ .forEach(id => {
+ const alias = `getJson_${id}`;
+ aliases.push(`@${alias}`);
+
+ cy.route(
+ 'POST',
+ `/superset/explore_json/?form_data={"slice_id":${id}}`,
+ ).as(alias);
+ });
+
+ // select filter_box and apply
+ cy.get('.Select-control')
+ .first()
+ .find('input')
+ .first()
+ .type('South Asia{enter}', { force: true });
+
+ cy.wait(aliases).then(requests => {
+ requests.forEach(xhr => {
+ const requestFormData = xhr.request.body;
+ const requestParams = JSON.parse(requestFormData.get('form_data'));
+ expect(requestParams.extra_filters[0]).deep.eq({
+ col: 'region',
+ op: 'in',
+ val: ['South Asia'],
+ });
+ });
});
});
});
-});
diff --git a/superset/assets/cypress/integration/dashboard/load.js b/superset/assets/cypress/integration/dashboard/load.js
index c6427c7320a..6050cbf55c2 100644
--- a/superset/assets/cypress/integration/dashboard/load.js
+++ b/superset/assets/cypress/integration/dashboard/load.js
@@ -19,37 +19,40 @@
import readResponseBlob from '../../utils/readResponseBlob';
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
-export default () => describe('load', () => {
- const aliases = [];
+export default () =>
+ describe('load', () => {
+ const aliases = [];
- beforeEach(() => {
- cy.server();
- cy.login();
+ beforeEach(() => {
+ cy.server();
+ cy.login();
- cy.visit(WORLD_HEALTH_DASHBOARD);
+ cy.visit(WORLD_HEALTH_DASHBOARD);
- cy.get('#app').then((data) => {
- const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
- const slices = bootstrapData.dashboard_data.slices;
- // then define routes and create alias for each requests
- slices.forEach((slice) => {
- const alias = `getJson_${slice.slice_id}`;
- const formData = `{"slice_id":${slice.slice_id}}`;
- cy.route('POST', `/superset/explore_json/?form_data=${formData}`).as(alias);
- aliases.push(`@${alias}`);
+ cy.get('#app').then(data => {
+ const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
+ const slices = bootstrapData.dashboard_data.slices;
+ // then define routes and create alias for each requests
+ slices.forEach(slice => {
+ const alias = `getJson_${slice.slice_id}`;
+ const formData = `{"slice_id":${slice.slice_id}}`;
+ cy.route('POST', `/superset/explore_json/?form_data=${formData}`).as(
+ alias,
+ );
+ aliases.push(`@${alias}`);
+ });
+ });
+ });
+
+ it('should load dashboard', () => {
+ // wait and verify one-by-one
+ cy.wait(aliases).then(requests => {
+ requests.forEach(async xhr => {
+ expect(xhr.status).to.eq(200);
+ const responseBody = await readResponseBlob(xhr.response.body);
+ expect(responseBody).to.have.property('error', null);
+ cy.get(`#slice-container-${xhr.response.body.form_data.slice_id}`);
+ });
});
});
});
-
- it('should load dashboard', () => {
- // wait and verify one-by-one
- cy.wait(aliases).then((requests) => {
- requests.forEach(async (xhr) => {
- expect(xhr.status).to.eq(200);
- const responseBody = await readResponseBlob(xhr.response.body);
- expect(responseBody).to.have.property('error', null);
- cy.get(`#slice-container-${xhr.response.body.form_data.slice_id}`);
- });
- });
- });
-});
diff --git a/superset/assets/cypress/integration/dashboard/save.js b/superset/assets/cypress/integration/dashboard/save.js
index 772862d5b87..263fd8addfd 100644
--- a/superset/assets/cypress/integration/dashboard/save.js
+++ b/superset/assets/cypress/integration/dashboard/save.js
@@ -19,60 +19,73 @@
import readResponseBlob from '../../utils/readResponseBlob';
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
-export default () => describe('save', () => {
- let dashboardId;
- let boxplotChartId;
+export default () =>
+ describe('save', () => {
+ let dashboardId;
+ let boxplotChartId;
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.visit(WORLD_HEALTH_DASHBOARD);
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.visit(WORLD_HEALTH_DASHBOARD);
- cy.get('#app').then((data) => {
- const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
- const dashboard = bootstrapData.dashboard_data;
- dashboardId = dashboard.id;
- boxplotChartId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'box_plot')).slice_id;
+ cy.get('#app').then(data => {
+ const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
+ const dashboard = bootstrapData.dashboard_data;
+ dashboardId = dashboard.id;
+ boxplotChartId = dashboard.slices.find(
+ slice => slice.form_data.viz_type === 'box_plot',
+ ).slice_id;
- cy.route('POST', `/superset/copy_dash/${dashboardId}/`).as('copyRequest');
+ cy.route('POST', `/superset/copy_dash/${dashboardId}/`).as(
+ 'copyRequest',
+ );
+ });
+
+ cy.get('#save-dash-split-button').trigger('click', { force: true });
+ cy.contains('Save as').trigger('click', { force: true });
+ cy.get('.modal-footer')
+ .contains('Save')
+ .trigger('click', { force: true });
});
- cy.get('#save-dash-split-button').trigger('click', { force: true });
- cy.contains('Save as').trigger('click', { force: true });
- cy.get('.modal-footer').contains('Save').trigger('click', { force: true });
- });
+ it('should save as new dashboard', () => {
+ cy.wait('@copyRequest').then(xhr => {
+ expect(xhr.status).to.eq(200);
- it('should save as new dashboard', () => {
- cy.wait('@copyRequest').then((xhr) => {
- expect(xhr.status).to.eq(200);
-
- readResponseBlob(xhr.response.body).then((json) => {
- expect(json.id).to.be.gt(dashboardId);
+ readResponseBlob(xhr.response.body).then(json => {
+ expect(json.id).to.be.gt(dashboardId);
+ });
});
});
+
+ it('should save/overwrite dashboard', () => {
+ cy.wait('@copyRequest');
+
+ // should have box_plot chart
+ const formData = `{"slice_id":${boxplotChartId}}`;
+ const boxplotRequest = `/superset/explore_json/?form_data=${formData}`;
+ cy.route('POST', boxplotRequest).as('boxplotRequest');
+ cy.wait('@boxplotRequest');
+ cy.get('.grid-container .box_plot').should('be.exist');
+
+ // remove box_plot chart from dashboard
+ cy.get('.dashboard-header')
+ .contains('Edit dashboard')
+ .trigger('click', { force: true });
+ cy.get('.fa.fa-trash')
+ .last()
+ .trigger('click', { force: true });
+ cy.get('.grid-container .box_plot').should('not.exist');
+
+ cy.route('POST', '/superset/save_dash/**/').as('saveRequest');
+ cy.get('.dashboard-header')
+ .contains('Save changes')
+ .trigger('click', { force: true });
+
+ // go back to view mode
+ cy.wait('@saveRequest');
+ cy.get('.dashboard-header').contains('Edit dashboard');
+ cy.get('.grid-container .box_plot').should('not.exist');
+ });
});
-
- it('should save/overwrite dashboard', () => {
- cy.wait('@copyRequest');
-
- // should have box_plot chart
- const formData = `{"slice_id":${boxplotChartId}}`;
- const boxplotRequest = `/superset/explore_json/?form_data=${formData}`;
- cy.route('POST', boxplotRequest).as('boxplotRequest');
- cy.wait('@boxplotRequest');
- cy.get('.grid-container .box_plot').should('be.exist');
-
- // remove box_plot chart from dashboard
- cy.get('.dashboard-header').contains('Edit dashboard').trigger('click', { force: true });
- cy.get('.fa.fa-trash').last().trigger('click', { force: true });
- cy.get('.grid-container .box_plot').should('not.exist');
-
- cy.route('POST', '/superset/save_dash/**/').as('saveRequest');
- cy.get('.dashboard-header').contains('Save changes').trigger('click', { force: true });
-
- // go back to view mode
- cy.wait('@saveRequest');
- cy.get('.dashboard-header').contains('Edit dashboard');
- cy.get('.grid-container .box_plot').should('not.exist');
- });
-});
diff --git a/superset/assets/cypress/integration/dashboard/tabs.js b/superset/assets/cypress/integration/dashboard/tabs.js
index 273d2ecc584..4a86d3c703f 100644
--- a/superset/assets/cypress/integration/dashboard/tabs.js
+++ b/superset/assets/cypress/integration/dashboard/tabs.js
@@ -18,161 +18,183 @@
*/
import { TABBED_DASHBOARD } from './dashboard.helper';
-export default () => describe('tabs', () => {
- let filterId;
- let treemapId;
- let linechartId;
- let boxplotId;
+export default () =>
+ describe('tabs', () => {
+ let filterId;
+ let treemapId;
+ let linechartId;
+ let boxplotId;
- // cypress can not handle window.scrollTo
- // https://github.com/cypress-io/cypress/issues/2761
- // add this exception handler to pass test
- const handleException = () => {
- // return false to prevent the error from
- // failing this test
- cy.on('uncaught:exception', () => false);
- };
+ // cypress can not handle window.scrollTo
+ // https://github.com/cypress-io/cypress/issues/2761
+ // add this exception handler to pass test
+ const handleException = () => {
+ // return false to prevent the error from
+ // failing this test
+ cy.on('uncaught:exception', () => false);
+ };
- beforeEach(() => {
- cy.server();
- cy.login();
+ beforeEach(() => {
+ cy.server();
+ cy.login();
- cy.visit(TABBED_DASHBOARD);
+ cy.visit(TABBED_DASHBOARD);
- cy.get('#app').then((data) => {
- const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
- const dashboard = bootstrapData.dashboard_data;
- filterId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'filter_box')).slice_id;
- boxplotId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'box_plot')).slice_id;
- treemapId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'treemap')).slice_id;
- linechartId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'line')).slice_id;
+ cy.get('#app').then(data => {
+ const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
+ const dashboard = bootstrapData.dashboard_data;
+ filterId = dashboard.slices.find(
+ slice => slice.form_data.viz_type === 'filter_box',
+ ).slice_id;
+ boxplotId = dashboard.slices.find(
+ slice => slice.form_data.viz_type === 'box_plot',
+ ).slice_id;
+ treemapId = dashboard.slices.find(
+ slice => slice.form_data.viz_type === 'treemap',
+ ).slice_id;
+ linechartId = dashboard.slices.find(
+ slice => slice.form_data.viz_type === 'line',
+ ).slice_id;
- const filterFormdata = {
- slice_id: filterId,
- };
- const filterRequest = `/superset/explore_json/?form_data=${JSON.stringify(filterFormdata)}`;
- cy.route('POST', filterRequest).as('filterRequest');
+ const filterFormdata = {
+ slice_id: filterId,
+ };
+ const filterRequest = `/superset/explore_json/?form_data=${JSON.stringify(
+ filterFormdata,
+ )}`;
+ cy.route('POST', filterRequest).as('filterRequest');
- const treemapFormdata = {
- slice_id: treemapId,
- };
- const treemapRequest = `/superset/explore_json/?form_data=${JSON.stringify(treemapFormdata)}`;
- cy.route('POST', treemapRequest).as('treemapRequest');
+ const treemapFormdata = {
+ slice_id: treemapId,
+ };
+ const treemapRequest = `/superset/explore_json/?form_data=${JSON.stringify(
+ treemapFormdata,
+ )}`;
+ cy.route('POST', treemapRequest).as('treemapRequest');
- const linechartFormdata = {
- slice_id: linechartId,
- };
- const linechartRequest = `/superset/explore_json/?form_data=${JSON.stringify(linechartFormdata)}`;
- cy.route('POST', linechartRequest).as('linechartRequest');
+ const linechartFormdata = {
+ slice_id: linechartId,
+ };
+ const linechartRequest = `/superset/explore_json/?form_data=${JSON.stringify(
+ linechartFormdata,
+ )}`;
+ cy.route('POST', linechartRequest).as('linechartRequest');
- const boxplotFormdata = {
- slice_id: boxplotId,
- };
- const boxplotRequest = `/superset/explore_json/?form_data=${JSON.stringify(boxplotFormdata)}`;
- cy.route('POST', boxplotRequest).as('boxplotRequest');
+ const boxplotFormdata = {
+ slice_id: boxplotId,
+ };
+ const boxplotRequest = `/superset/explore_json/?form_data=${JSON.stringify(
+ boxplotFormdata,
+ )}`;
+ cy.route('POST', boxplotRequest).as('boxplotRequest');
+ });
});
- });
- it('should load charts when tab is visible', () => {
- // landing in first tab, should see 2 charts
- cy.wait('@filterRequest');
- cy.get('.grid-container .filter_box').should('be.exist');
- cy.wait('@treemapRequest');
- cy.get('.grid-container .treemap').should('be.exist');
- cy.get('.grid-container .box_plot').should('not.be.exist');
- cy.get('.grid-container .line').should('not.be.exist');
+ it('should load charts when tab is visible', () => {
+ // landing in first tab, should see 2 charts
+ cy.wait('@filterRequest');
+ cy.get('.grid-container .filter_box').should('be.exist');
+ cy.wait('@treemapRequest');
+ cy.get('.grid-container .treemap').should('be.exist');
+ cy.get('.grid-container .box_plot').should('not.be.exist');
+ cy.get('.grid-container .line').should('not.be.exist');
- // click row level tab, see 1 more chart
- cy.get('.tab-content ul.nav.nav-tabs li')
- .last()
- .find('.editable-title input')
- .click();
- cy.wait('@linechartRequest');
- cy.get('.grid-container .line').should('be.exist');
+ // click row level tab, see 1 more chart
+ cy.get('.tab-content ul.nav.nav-tabs li')
+ .last()
+ .find('.editable-title input')
+ .click();
+ cy.wait('@linechartRequest');
+ cy.get('.grid-container .line').should('be.exist');
- // click top level tab, see 1 more chart
- handleException();
- cy.get('.dashboard-component-tabs')
- .first()
- .find('ul.nav.nav-tabs li')
- .last()
- .find('.editable-title input')
- .click();
- cy.wait('@boxplotRequest');
- cy.get('.grid-container .box_plot').should('be.exist');
- });
+ // click top level tab, see 1 more chart
+ handleException();
+ cy.get('.dashboard-component-tabs')
+ .first()
+ .find('ul.nav.nav-tabs li')
+ .last()
+ .find('.editable-title input')
+ .click();
+ cy.wait('@boxplotRequest');
+ cy.get('.grid-container .box_plot').should('be.exist');
+ });
- it('should send new queries when tab becomes visible', () => {
- // landing in first tab
- cy.wait('@filterRequest');
- cy.wait('@treemapRequest');
+ it('should send new queries when tab becomes visible', () => {
+ // landing in first tab
+ cy.wait('@filterRequest');
+ cy.wait('@treemapRequest');
- // apply filter
- cy.get('.Select-control')
- .first()
- .find('input')
- .first()
- .type('South Asia{enter}', { force: true });
+ // apply filter
+ cy.get('.Select-control')
+ .first()
+ .find('input')
+ .first()
+ .type('South Asia{enter}', { force: true });
- // send new query from same tab
- cy.wait('@treemapRequest')
- .then((xhr) => {
+ // send new query from same tab
+ cy.wait('@treemapRequest').then(xhr => {
const requestFormData = xhr.request.body;
const requestParams = JSON.parse(requestFormData.get('form_data'));
- expect(requestParams.extra_filters[0])
- .deep.eq({ col: 'region', op: 'in', val: ['South Asia'] });
+ expect(requestParams.extra_filters[0]).deep.eq({
+ col: 'region',
+ op: 'in',
+ val: ['South Asia'],
+ });
});
- // click row level tab, send 1 more query
- cy.get('.tab-content ul.nav.nav-tabs li')
- .last()
- .click();
- cy.wait('@linechartRequest')
- .then((xhr) => {
+ // click row level tab, send 1 more query
+ cy.get('.tab-content ul.nav.nav-tabs li')
+ .last()
+ .click();
+ cy.wait('@linechartRequest').then(xhr => {
const requestFormData = xhr.request.body;
const requestParams = JSON.parse(requestFormData.get('form_data'));
- expect(requestParams.extra_filters[0])
- .deep.eq({ col: 'region', op: 'in', val: ['South Asia'] });
+ expect(requestParams.extra_filters[0]).deep.eq({
+ col: 'region',
+ op: 'in',
+ val: ['South Asia'],
+ });
});
- // click top level tab, send 1 more query
- handleException();
- cy.get('.dashboard-component-tabs')
- .first()
- .find('ul.nav.nav-tabs li')
- .last()
- .find('.editable-title input')
- .click();
- cy.wait('@boxplotRequest')
- .then((xhr) => {
+ // click top level tab, send 1 more query
+ handleException();
+ cy.get('.dashboard-component-tabs')
+ .first()
+ .find('ul.nav.nav-tabs li')
+ .last()
+ .find('.editable-title input')
+ .click();
+ cy.wait('@boxplotRequest').then(xhr => {
const requestFormData = xhr.request.body;
const requestParams = JSON.parse(requestFormData.get('form_data'));
- expect(requestParams.extra_filters[0])
- .deep.eq({ col: 'region', op: 'in', val: ['South Asia'] });
+ expect(requestParams.extra_filters[0]).deep.eq({
+ col: 'region',
+ op: 'in',
+ val: ['South Asia'],
+ });
});
- // navigate to filter and clear filter
- cy.get('.dashboard-component-tabs')
- .first()
- .find('ul.nav.nav-tabs li')
- .first()
- .click();
- cy.get('.tab-content ul.nav.nav-tabs li')
- .first()
- .click();
- cy.get('span.Select-clear')
- .click();
+ // navigate to filter and clear filter
+ cy.get('.dashboard-component-tabs')
+ .first()
+ .find('ul.nav.nav-tabs li')
+ .first()
+ .click();
+ cy.get('.tab-content ul.nav.nav-tabs li')
+ .first()
+ .click();
+ cy.get('span.Select-clear').click();
- // trigger 1 new query
- cy.wait('@treemapRequest');
+ // trigger 1 new query
+ cy.wait('@treemapRequest');
- // no other requests occurred
- cy.on('fail', (err) => {
- expect(err.message).to.include('Timed out retrying');
- return false;
- });
- cy.wait('@boxplotRequest', { timeout: 1000 }).then(() => {
- throw new Error('Unexpected API call.');
+ // no other requests occurred
+ cy.on('fail', err => {
+ expect(err.message).to.include('Timed out retrying');
+ return false;
+ });
+ cy.wait('@boxplotRequest', { timeout: 1000 }).then(() => {
+ throw new Error('Unexpected API call.');
+ });
});
});
-});
diff --git a/superset/assets/cypress/integration/dashboard/url_params.js b/superset/assets/cypress/integration/dashboard/url_params.js
index b82aea10ed8..d7f983e7c11 100644
--- a/superset/assets/cypress/integration/dashboard/url_params.js
+++ b/superset/assets/cypress/integration/dashboard/url_params.js
@@ -18,39 +18,41 @@
*/
import { WORLD_HEALTH_DASHBOARD } from './dashboard.helper';
-export default () => describe('dashboard url params', () => {
- const urlParams = { param1: '123', param2: 'abc' };
- let sliceIds = [];
+export default () =>
+ describe('dashboard url params', () => {
+ const urlParams = { param1: '123', param2: 'abc' };
+ let sliceIds = [];
- beforeEach(() => {
- cy.server();
- cy.login();
+ beforeEach(() => {
+ cy.server();
+ cy.login();
- cy.visit(WORLD_HEALTH_DASHBOARD, { qs: urlParams });
+ cy.visit(WORLD_HEALTH_DASHBOARD, { qs: urlParams });
- cy.get('#app').then((data) => {
- const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
- const dashboard = bootstrapData.dashboard_data;
- sliceIds = dashboard.slices.map(slice => (slice.slice_id));
+ cy.get('#app').then(data => {
+ const bootstrapData = JSON.parse(data[0].dataset.bootstrap);
+ const dashboard = bootstrapData.dashboard_data;
+ sliceIds = dashboard.slices.map(slice => slice.slice_id);
+ });
});
- });
- it('should apply url params to slice requests', () => {
- const aliases = [];
- sliceIds
- .forEach((id) => {
+ it('should apply url params to slice requests', () => {
+ const aliases = [];
+ sliceIds.forEach(id => {
const alias = `getJson_${id}`;
aliases.push(`@${alias}`);
- cy.route('POST', `/superset/explore_json/?form_data={"slice_id":${id}}`).as(alias);
+ cy.route(
+ 'POST',
+ `/superset/explore_json/?form_data={"slice_id":${id}}`,
+ ).as(alias);
});
- cy.wait(aliases).then((requests) => {
- requests.forEach((xhr) => {
- const requestFormData = xhr.request.body;
- const requestParams = JSON.parse(requestFormData.get('form_data'));
- expect(requestParams.url_params)
- .deep.eq(urlParams);
+ cy.wait(aliases).then(requests => {
+ requests.forEach(xhr => {
+ const requestFormData = xhr.request.body;
+ const requestParams = JSON.parse(requestFormData.get('form_data'));
+ expect(requestParams.url_params).deep.eq(urlParams);
+ });
});
});
});
-});
diff --git a/superset/assets/cypress/integration/explore/chart.test.js b/superset/assets/cypress/integration/explore/chart.test.js
index 9032de9d666..75874617efb 100644
--- a/superset/assets/cypress/integration/explore/chart.test.js
+++ b/superset/assets/cypress/integration/explore/chart.test.js
@@ -31,19 +31,21 @@ describe('Error', () => {
...FORM_DATA_DEFAULTS,
metrics: [NUM_METRIC],
viz_type: 'line',
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'state',
- operator: 'in',
- comparator: ['Fake State'],
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- }],
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'state',
+ operator: 'in',
+ comparator: ['Fake State'],
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ },
+ ],
};
cy.visitChartByParams(JSON.stringify(formData));
- cy.wait('@getJson').then(async (xhr) => {
+ cy.wait('@getJson').then(async xhr => {
expect(xhr.status).to.eq(400);
const responseBody = await readResponseBlob(xhr.response.body);
diff --git a/superset/assets/cypress/integration/explore/control.test.js b/superset/assets/cypress/integration/explore/control.test.js
index d20cb46e21f..7d0da009ec6 100644
--- a/superset/assets/cypress/integration/explore/control.test.js
+++ b/superset/assets/cypress/integration/explore/control.test.js
@@ -100,9 +100,10 @@ describe('AdhocMetrics', () => {
cy.get('#metrics-edit-popover').within(() => {
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
cy.get('.ace_content').click();
- cy.get('.ace_text-input')
- .type('/COUNT(DISTINCT name)', { force: true });
- cy.get('button').contains('Save').click();
+ cy.get('.ace_text-input').type('/COUNT(DISTINCT name)', { force: true });
+ cy.get('button')
+ .contains('Save')
+ .click();
});
cy.get('button.query').click();
@@ -130,11 +131,14 @@ describe('AdhocMetrics', () => {
cy.get('#adhoc-metric-edit-tabs-tab-SQL').click();
cy.get('.ace_identifier').contains('sum_girls');
cy.get('.ace_content').click();
- cy.get('.ace_text-input')
- .type('{selectall}{backspace}SUM(num)', { force: true });
+ cy.get('.ace_text-input').type('{selectall}{backspace}SUM(num)', {
+ force: true,
+ });
cy.get('#adhoc-metric-edit-tabs-tab-SIMPLE').click();
cy.get('.select-value-label').contains('num');
- cy.get('button').contains('Save').click();
+ cy.get('button')
+ .contains('Save')
+ .click();
});
cy.get('button.query').click();
@@ -200,8 +204,7 @@ describe('AdhocFilters', () => {
cy.get('#filter-edit-popover').within(() => {
cy.get('#adhoc-filter-edit-tabs-tab-SQL').click();
cy.get('.ace_content').click();
- cy.get('.ace_text-input')
- .type("'Amy' OR name = 'Bob'", { force: true });
+ cy.get('.ace_text-input').type("'Amy' OR name = 'Bob'", { force: true });
cy.get('button')
.contains('Save')
.click();
@@ -215,7 +218,6 @@ describe('AdhocFilters', () => {
});
});
-
describe('Advanced analytics', () => {
beforeEach(() => {
cy.login();
@@ -274,13 +276,21 @@ describe('Annotations', () => {
});
cy.get('.popover-content').within(() => {
- cy.get('[data-test=annotation-layer-name-header]').siblings().first().within(() => {
- cy.get('input').type('Goal line');
- });
- cy.get('[data-test=annotation-layer-value-header]').siblings().first().within(() => {
- cy.get('input').type('y=1400000');
- });
- cy.get('button').contains('OK').click();
+ cy.get('[data-test=annotation-layer-name-header]')
+ .siblings()
+ .first()
+ .within(() => {
+ cy.get('input').type('Goal line');
+ });
+ cy.get('[data-test=annotation-layer-value-header]')
+ .siblings()
+ .first()
+ .within(() => {
+ cy.get('input').type('y=1400000');
+ });
+ cy.get('button')
+ .contains('OK')
+ .click();
});
cy.get('button.query').click();
diff --git a/superset/assets/cypress/integration/explore/link.test.js b/superset/assets/cypress/integration/explore/link.test.js
index 9f5f82d59fa..22067498632 100644
--- a/superset/assets/cypress/integration/explore/link.test.js
+++ b/superset/assets/cypress/integration/explore/link.test.js
@@ -35,12 +35,17 @@ describe('Test explore links', () => {
cy.verifySliceSuccess({ waitAlias: '@postJson' });
cy.get('button#query').click();
- cy.get('span').contains('View query').parent().click();
+ cy.get('span')
+ .contains('View query')
+ .parent()
+ .click();
cy.wait('@postJson').then(() => {
cy.get('code');
});
cy.get('.modal-header').within(() => {
- cy.get('button.close').first().click({ force: true });
+ cy.get('button.close')
+ .first()
+ .click({ force: true });
});
});
@@ -57,8 +62,9 @@ describe('Test explore links', () => {
cy.wait(100);
- cy.get('#shorturl-popover [data-test="short-url"]').invoke('text')
- .then((text) => {
+ cy.get('#shorturl-popover [data-test="short-url"]')
+ .invoke('text')
+ .then(text => {
cy.visit(text);
});
cy.verifySliceSuccess({ waitAlias: '@postJson' });
@@ -85,7 +91,7 @@ describe('Test explore links', () => {
cy.visitChartByParams(JSON.stringify(formData));
cy.verifySliceSuccess({ waitAlias: '@postJson' });
- cy.url().then((url) => {
+ cy.url().then(url => {
cy.get('button[data-target="#save_modal"]').click();
cy.get('.modal-content').within(() => {
cy.get('input[name=new_slice_name]').type(newChartName);
@@ -111,9 +117,11 @@ describe('Test explore links', () => {
cy.get('button#btn_modal_save').click();
});
cy.verifySliceSuccess({ waitAlias: '@postJson' });
- cy.request(`/chart/api/read?_flt_3_slice_name=${chartName}`).then((response) => {
- cy.request('DELETE', `/chart/api/delete/${response.body.pks[0]}`);
- });
+ cy.request(`/chart/api/read?_flt_3_slice_name=${chartName}`).then(
+ response => {
+ cy.request('DELETE', `/chart/api/delete/${response.body.pks[0]}`);
+ },
+ );
});
it('Test chart save as and add to new dashboard', () => {
@@ -129,7 +137,9 @@ describe('Test explore links', () => {
cy.get('button#btn_modal_save').click();
});
cy.verifySliceSuccess({ waitAlias: '@postJson' });
- cy.request(`/dashboard/api/read?_flt_3_dashboard_title=${dashboardTitle}`).then((response) => {
+ cy.request(
+ `/dashboard/api/read?_flt_3_dashboard_title=${dashboardTitle}`,
+ ).then(response => {
expect(response.body.pks[0]).not.equals(null);
});
});
@@ -144,18 +154,23 @@ describe('Test explore links', () => {
cy.get('.modal-content').within(() => {
cy.get('input[name=new_slice_name]').type(chartName);
cy.get('input[data-test=add-to-existing-dashboard]').check();
- cy.get('.select.save-modal-selector').click().within(() => {
- cy.get('input').type(dashboardTitle, { force: true });
- cy.get('.select-option.is-focused')
- .trigger('mousedown');
- });
+ cy.get('.select.save-modal-selector')
+ .click()
+ .within(() => {
+ cy.get('input').type(dashboardTitle, { force: true });
+ cy.get('.select-option.is-focused').trigger('mousedown');
+ });
cy.get('button#btn_modal_save').click();
});
cy.verifySliceSuccess({ waitAlias: '@postJson' });
- cy.request(`/chart/api/read?_flt_3_slice_name=${chartName}`).then((response) => {
- cy.request('DELETE', `/chart/api/delete/${response.body.pks[0]}`);
- });
- cy.request(`/dashboard/api/read?_flt_3_dashboard_title=${dashboardTitle}`).then((response) => {
+ cy.request(`/chart/api/read?_flt_3_slice_name=${chartName}`).then(
+ response => {
+ cy.request('DELETE', `/chart/api/delete/${response.body.pks[0]}`);
+ },
+ );
+ cy.request(
+ `/dashboard/api/read?_flt_3_dashboard_title=${dashboardTitle}`,
+ ).then(response => {
cy.request('DELETE', `/dashboard/api/delete/${response.body.pks[0]}`);
});
});
diff --git a/superset/assets/cypress/integration/explore/visualizations/area.js b/superset/assets/cypress/integration/explore/visualizations/area.js
index 0e1906c5259..a3c5a33ce51 100644
--- a/superset/assets/cypress/integration/explore/visualizations/area.js
+++ b/superset/assets/cypress/integration/explore/visualizations/area.js
@@ -18,92 +18,99 @@
*/
import readResponseBlob from '../../../utils/readResponseBlob';
-export default () => describe('Area', () => {
- const AREA_FORM_DATA = {
- datasource: '2__table',
- viz_type: 'area',
- slice_id: 48,
- granularity_sqla: 'year',
- time_grain_sqla: 'P1D',
- time_range: '1960-01-01 : now',
- metrics: ['sum__SP_POP_TOTL'],
- adhoc_filters: [],
- groupby: [],
- limit: '25',
- order_desc: true,
- contribution: false,
- row_limit: 50000,
- show_brush: 'auto',
- show_legend: true,
- line_interpolation: 'linear',
- stacked_style: 'stack',
- color_scheme: 'bnbColors',
- rich_tooltip: true,
- show_controls: false,
- x_axis_label: '',
- bottom_margin: 'auto',
- x_ticks_layout: 'auto',
- x_axis_format: 'smart_date',
- x_axis_showminmax: false,
- y_axis_format: '.3s',
- y_log_scale: false,
- rolling_type: 'None',
- comparison_type: 'values',
- annotation_layers: [],
- };
+export default () =>
+ describe('Area', () => {
+ const AREA_FORM_DATA = {
+ datasource: '2__table',
+ viz_type: 'area',
+ slice_id: 48,
+ granularity_sqla: 'year',
+ time_grain_sqla: 'P1D',
+ time_range: '1960-01-01 : now',
+ metrics: ['sum__SP_POP_TOTL'],
+ adhoc_filters: [],
+ groupby: [],
+ limit: '25',
+ order_desc: true,
+ contribution: false,
+ row_limit: 50000,
+ show_brush: 'auto',
+ show_legend: true,
+ line_interpolation: 'linear',
+ stacked_style: 'stack',
+ color_scheme: 'bnbColors',
+ rich_tooltip: true,
+ show_controls: false,
+ x_axis_label: '',
+ bottom_margin: 'auto',
+ x_ticks_layout: 'auto',
+ x_axis_format: 'smart_date',
+ x_axis_showminmax: false,
+ y_axis_format: '.3s',
+ y_log_scale: false,
+ rolling_type: 'None',
+ comparison_type: 'values',
+ annotation_layers: [],
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work without groupby', () => {
- verify(AREA_FORM_DATA);
- cy.get('.nv-area').should('have.length', 1);
- });
-
- it('should work with group by', () => {
- verify({
- ...AREA_FORM_DATA,
- groupby: ['region'],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.nv-area').should('have.length', 7);
- });
-
- it('should work with groupby and filter', () => {
- cy.visitChartByParams(JSON.stringify({
- ...AREA_FORM_DATA,
- groupby: ['region'],
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'region',
- operator: 'in',
- comparator: ['South Asia', 'North America'],
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_txje2ikiv6_wxmn0qwd1xo',
- }],
- }));
-
- cy.wait('@getJson').then(async (xhr) => {
- cy.verifyResponseCodes(xhr);
-
- const responseBody = await readResponseBlob(xhr.response.body);
-
- // Make sure data is sorted correctly
- const firstRow = responseBody.data[0].values;
- const secondRow = responseBody.data[1].values;
- expect(firstRow[firstRow.length - 1].y).to.be.greaterThan(secondRow[secondRow.length - 1].y);
- cy.verifySliceContainer('svg');
+ it('should work without groupby', () => {
+ verify(AREA_FORM_DATA);
+ cy.get('.nv-area').should('have.length', 1);
+ });
+
+ it('should work with group by', () => {
+ verify({
+ ...AREA_FORM_DATA,
+ groupby: ['region'],
+ });
+
+ cy.get('.nv-area').should('have.length', 7);
+ });
+
+ it('should work with groupby and filter', () => {
+ cy.visitChartByParams(
+ JSON.stringify({
+ ...AREA_FORM_DATA,
+ groupby: ['region'],
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'region',
+ operator: 'in',
+ comparator: ['South Asia', 'North America'],
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_txje2ikiv6_wxmn0qwd1xo',
+ },
+ ],
+ }),
+ );
+
+ cy.wait('@getJson').then(async xhr => {
+ cy.verifyResponseCodes(xhr);
+
+ const responseBody = await readResponseBlob(xhr.response.body);
+
+ // Make sure data is sorted correctly
+ const firstRow = responseBody.data[0].values;
+ const secondRow = responseBody.data[1].values;
+ expect(firstRow[firstRow.length - 1].y).to.be.greaterThan(
+ secondRow[secondRow.length - 1].y,
+ );
+ cy.verifySliceContainer('svg');
+ });
+ cy.get('.nv-area').should('have.length', 2);
});
- cy.get('.nv-area').should('have.length', 2);
});
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/big_number.js b/superset/assets/cypress/integration/explore/visualizations/big_number.js
index a2d84283c7e..61c8fc65426 100644
--- a/superset/assets/cypress/integration/explore/visualizations/big_number.js
+++ b/superset/assets/cypress/integration/explore/visualizations/big_number.js
@@ -16,66 +16,70 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Big Number', () => {
- const BIG_NUMBER_FORM_DATA = {
- datasource: '2__table',
- viz_type: 'big_number',
- slice_id: 42,
- granularity_sqla: 'year',
- time_grain_sqla: 'P1D',
- time_range: '2000+:+2014-01-02',
- metric: 'sum__SP_POP_TOTL',
- adhoc_filters: [],
- compare_lag: '10',
- compare_suffix: 'over+10Y',
- y_axis_format: '.3s',
- show_trend_line: true,
- start_y_axis_at_zero: true,
- color_picker: {
- r: 0,
- g: 122,
- b: 135,
- a: 1,
- },
- };
+export default () =>
+ describe('Big Number', () => {
+ const BIG_NUMBER_FORM_DATA = {
+ datasource: '2__table',
+ viz_type: 'big_number',
+ slice_id: 42,
+ granularity_sqla: 'year',
+ time_grain_sqla: 'P1D',
+ time_range: '2000+:+2014-01-02',
+ metric: 'sum__SP_POP_TOTL',
+ adhoc_filters: [],
+ compare_lag: '10',
+ compare_suffix: 'over+10Y',
+ y_axis_format: '.3s',
+ show_trend_line: true,
+ start_y_axis_at_zero: true,
+ color_picker: {
+ r: 0,
+ g: 122,
+ b: 135,
+ a: 1,
+ },
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: '.big_number' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ chartSelector: '.big_number',
+ });
+ }
- beforeEach(() => {
- cy.login();
- cy.server();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work', () => {
- verify(BIG_NUMBER_FORM_DATA);
- cy.get('.chart-container .header_line');
- cy.get('.chart-container .subheader_line');
- cy.get('.chart-container svg path.vx-linepath');
- });
-
- it('should work without subheader', () => {
- verify({
- ...BIG_NUMBER_FORM_DATA,
- compare_lag: null,
+ beforeEach(() => {
+ cy.login();
+ cy.server();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.chart-container .header_line');
- cy.get('.chart-container .subheader_line');
- cy.get('.chart-container svg path.vx-linepath');
- });
- it('should not render trendline when hidden', () => {
- verify({
- ...BIG_NUMBER_FORM_DATA,
- show_trend_line: false,
+ it('should work', () => {
+ verify(BIG_NUMBER_FORM_DATA);
+ cy.get('.chart-container .header_line');
+ cy.get('.chart-container .subheader_line');
+ cy.get('.chart-container svg path.vx-linepath');
});
- cy.get('.chart-container .header_line');
- cy.get('.chart-container .subheader_line');
- cy.get('.chart-container').then((containers) => {
- expect(containers[0].querySelector('svg')).to.equal(null);
+
+ it('should work without subheader', () => {
+ verify({
+ ...BIG_NUMBER_FORM_DATA,
+ compare_lag: null,
+ });
+ cy.get('.chart-container .header_line');
+ cy.get('.chart-container .subheader_line');
+ cy.get('.chart-container svg path.vx-linepath');
+ });
+
+ it('should not render trendline when hidden', () => {
+ verify({
+ ...BIG_NUMBER_FORM_DATA,
+ show_trend_line: false,
+ });
+ cy.get('.chart-container .header_line');
+ cy.get('.chart-container .subheader_line');
+ cy.get('.chart-container').then(containers => {
+ expect(containers[0].querySelector('svg')).to.equal(null);
+ });
});
});
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/big_number_total.js b/superset/assets/cypress/integration/explore/visualizations/big_number_total.js
index e395c77d779..3fa45cf7992 100644
--- a/superset/assets/cypress/integration/explore/visualizations/big_number_total.js
+++ b/superset/assets/cypress/integration/explore/visualizations/big_number_total.js
@@ -21,52 +21,67 @@ import readResponseBlob from '../../../utils/readResponseBlob';
// Big Number Total
-export default () => describe('Big Number Total', () => {
- const BIG_NUMBER_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'big_number_total' };
+export default () =>
+ describe('Big Number Total', () => {
+ const BIG_NUMBER_DEFAULTS = {
+ ...FORM_DATA_DEFAULTS,
+ viz_type: 'big_number_total',
+ };
- beforeEach(() => {
- cy.login();
- cy.server();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
+ beforeEach(() => {
+ cy.login();
+ cy.server();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
+ });
- it('Test big number chart with adhoc metric', () => {
- const formData = { ...BIG_NUMBER_DEFAULTS, metric: NUM_METRIC };
+ it('Test big number chart with adhoc metric', () => {
+ const formData = { ...BIG_NUMBER_DEFAULTS, metric: NUM_METRIC };
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', querySubstring: NUM_METRIC.label });
- });
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ querySubstring: NUM_METRIC.label,
+ });
+ });
- it('Test big number chart with simple filter', () => {
- const filters = [
- {
- expressionType: 'SIMPLE',
- subject: 'name',
- operator: 'in',
- comparator: ['Aaron', 'Amy', 'Andrea'],
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_4y6teao56zs_ebjsvwy48c',
- },
- ];
+ it('Test big number chart with simple filter', () => {
+ const filters = [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'name',
+ operator: 'in',
+ comparator: ['Aaron', 'Amy', 'Andrea'],
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_4y6teao56zs_ebjsvwy48c',
+ },
+ ];
- const formData = { ...BIG_NUMBER_DEFAULTS, metric: 'count', adhoc_filters: filters };
+ const formData = {
+ ...BIG_NUMBER_DEFAULTS,
+ metric: 'count',
+ adhoc_filters: filters,
+ };
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson' });
- });
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson' });
+ });
- it('Test big number chart ignores groupby', () => {
- const formData = { ...BIG_NUMBER_DEFAULTS, metric: NUM_METRIC, groupby: ['state'] };
+ it('Test big number chart ignores groupby', () => {
+ const formData = {
+ ...BIG_NUMBER_DEFAULTS,
+ metric: NUM_METRIC,
+ groupby: ['state'],
+ };
- cy.visitChartByParams(JSON.stringify(formData));
- cy.wait(['@getJson']).then(async (xhr) => {
- cy.verifyResponseCodes(xhr);
- cy.verifySliceContainer();
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.wait(['@getJson']).then(async xhr => {
+ cy.verifyResponseCodes(xhr);
+ cy.verifySliceContainer();
- const responseBody = await readResponseBlob(xhr.response.body);
- expect(responseBody.query).not.contains(formData.groupby[0]);
+ const responseBody = await readResponseBlob(xhr.response.body);
+ expect(responseBody.query).not.contains(formData.groupby[0]);
+ });
});
});
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/box_plot.js b/superset/assets/cypress/integration/explore/visualizations/box_plot.js
index 582cb162482..86a0ca22ffe 100644
--- a/superset/assets/cypress/integration/explore/visualizations/box_plot.js
+++ b/superset/assets/cypress/integration/explore/visualizations/box_plot.js
@@ -16,53 +16,61 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Box Plot', () => {
- const BOX_PLOT_FORM_DATA = {
- datasource: '2__table',
- viz_type: 'box_plot',
- slice_id: 49,
- granularity_sqla: 'year',
- time_grain_sqla: 'P1D',
- time_range: '1960-01-01+:+now',
- metrics: ['sum__SP_POP_TOTL'],
- adhoc_filters: [],
- groupby: ['region'],
- limit: '25',
- color_scheme: 'bnbColors',
- whisker_options: 'Min/max+(no+outliers)',
- };
+export default () =>
+ describe('Box Plot', () => {
+ const BOX_PLOT_FORM_DATA = {
+ datasource: '2__table',
+ viz_type: 'box_plot',
+ slice_id: 49,
+ granularity_sqla: 'year',
+ time_grain_sqla: 'P1D',
+ time_range: '1960-01-01+:+now',
+ metrics: ['sum__SP_POP_TOTL'],
+ adhoc_filters: [],
+ groupby: ['region'],
+ limit: '25',
+ color_scheme: 'bnbColors',
+ whisker_options: 'Min/max+(no+outliers)',
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work', () => {
- verify(BOX_PLOT_FORM_DATA);
- cy.get('.chart-container svg rect.nv-boxplot-box').should('have.length', 7);
- });
-
- it('should work with filter', () => {
- verify({
- ...BOX_PLOT_FORM_DATA,
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'region',
- operator: '==',
- comparator: 'South Asia',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_8aqxcf5co1a_x7lm2d1fq0l',
- }],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.chart-container svg rect.nv-boxplot-box').should('have.length', 1);
- });
-});
+ it('should work', () => {
+ verify(BOX_PLOT_FORM_DATA);
+ cy.get('.chart-container svg rect.nv-boxplot-box').should(
+ 'have.length',
+ 7,
+ );
+ });
+
+ it('should work with filter', () => {
+ verify({
+ ...BOX_PLOT_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'region',
+ operator: '==',
+ comparator: 'South Asia',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_8aqxcf5co1a_x7lm2d1fq0l',
+ },
+ ],
+ });
+ cy.get('.chart-container svg rect.nv-boxplot-box').should(
+ 'have.length',
+ 1,
+ );
+ });
+ });
diff --git a/superset/assets/cypress/integration/explore/visualizations/bubble.js b/superset/assets/cypress/integration/explore/visualizations/bubble.js
index 915e97d5a56..563b453300b 100644
--- a/superset/assets/cypress/integration/explore/visualizations/bubble.js
+++ b/superset/assets/cypress/integration/explore/visualizations/bubble.js
@@ -16,74 +16,78 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Bubble', () => {
- const BUBBLE_FORM_DATA = {
- datasource: '2__table',
- viz_type: 'bubble',
- slice_id: 46,
- granularity_sqla: 'year',
- time_grain_sqla: 'P1D',
- time_range: '2011-01-01+:+2011-01-02',
- series: 'region',
- entity: 'country_name',
- x: 'sum__SP_RUR_TOTL_ZS',
- y: 'sum__SP_DYN_LE00_IN',
- size: 'sum__SP_POP_TOTL',
- max_bubble_size: '50',
- limit: 0,
- color_scheme: 'bnbColors',
- show_legend: true,
- x_axis_label: '',
- left_margin: 'auto',
- x_axis_format: '.3s',
- x_ticks_layout: 'auto',
- x_log_scale: false,
- x_axis_showminmax: false,
- y_axis_label: '',
- bottom_margin: 'auto',
- y_axis_format: '.3s',
- y_log_scale: false,
- y_axis_showminmax: false,
- };
+export default () =>
+ describe('Bubble', () => {
+ const BUBBLE_FORM_DATA = {
+ datasource: '2__table',
+ viz_type: 'bubble',
+ slice_id: 46,
+ granularity_sqla: 'year',
+ time_grain_sqla: 'P1D',
+ time_range: '2011-01-01+:+2011-01-02',
+ series: 'region',
+ entity: 'country_name',
+ x: 'sum__SP_RUR_TOTL_ZS',
+ y: 'sum__SP_DYN_LE00_IN',
+ size: 'sum__SP_POP_TOTL',
+ max_bubble_size: '50',
+ limit: 0,
+ color_scheme: 'bnbColors',
+ show_legend: true,
+ x_axis_label: '',
+ left_margin: 'auto',
+ x_axis_format: '.3s',
+ x_ticks_layout: 'auto',
+ x_log_scale: false,
+ x_axis_showminmax: false,
+ y_axis_label: '',
+ bottom_margin: 'auto',
+ y_axis_format: '.3s',
+ y_log_scale: false,
+ y_axis_showminmax: false,
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work', () => {
- verify(BUBBLE_FORM_DATA);
- cy.get('.chart-container svg circle').should('have.length', 208);
- });
-
- it('should work with filter', () => {
- verify({
- ...BUBBLE_FORM_DATA,
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'region',
- operator: '==',
- comparator: 'South+Asia',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_b2tfg1rs8y_8kmrcyxvsqd',
- }],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.chart-container svg circle')
- .should('have.length', 9)
- .then((nodeList) => {
- // Check that all circles have same color.
- const color = nodeList[0].getAttribute('fill');
- const circles = Array.prototype.slice.call(nodeList);
- expect(circles.every(c => c.getAttribute('fill') === color)).to.equal(true);
- });
- });
-});
+ it('should work', () => {
+ verify(BUBBLE_FORM_DATA);
+ cy.get('.chart-container svg circle').should('have.length', 208);
+ });
+
+ it('should work with filter', () => {
+ verify({
+ ...BUBBLE_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'region',
+ operator: '==',
+ comparator: 'South+Asia',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_b2tfg1rs8y_8kmrcyxvsqd',
+ },
+ ],
+ });
+ cy.get('.chart-container svg circle')
+ .should('have.length', 9)
+ .then(nodeList => {
+ // Check that all circles have same color.
+ const color = nodeList[0].getAttribute('fill');
+ const circles = Array.prototype.slice.call(nodeList);
+ expect(circles.every(c => c.getAttribute('fill') === color)).to.equal(
+ true,
+ );
+ });
+ });
+ });
diff --git a/superset/assets/cypress/integration/explore/visualizations/compare.js b/superset/assets/cypress/integration/explore/visualizations/compare.js
index 04f072e5ebf..2693eb26779 100644
--- a/superset/assets/cypress/integration/explore/visualizations/compare.js
+++ b/superset/assets/cypress/integration/explore/visualizations/compare.js
@@ -16,75 +16,77 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Compare', () => {
- const COMPARE_FORM_DATA = {
- datasource: '3__table',
- viz_type: 'compare',
- slice_id: 60,
- granularity_sqla: 'ds',
- time_grain_sqla: 'P1D',
- time_range: '100 years ago : now',
- metrics: ['count'],
- adhoc_filters: [],
- groupby: [],
- order_desc: true,
- contribution: false,
- row_limit: 50000,
- color_scheme: 'bnbColors',
- x_axis_label: 'Frequency',
- bottom_margin: 'auto',
- x_ticks_layout: 'auto',
- x_axis_format: 'smart_date',
- x_axis_showminmax: false,
- y_axis_label: 'Num',
- left_margin: 'auto',
- y_axis_showminmax: false,
- y_log_scale: false,
- y_axis_format: '.3s',
- rolling_type: 'None',
- comparison_type: 'values',
- annotation_layers: [],
- };
+export default () =>
+ describe('Compare', () => {
+ const COMPARE_FORM_DATA = {
+ datasource: '3__table',
+ viz_type: 'compare',
+ slice_id: 60,
+ granularity_sqla: 'ds',
+ time_grain_sqla: 'P1D',
+ time_range: '100 years ago : now',
+ metrics: ['count'],
+ adhoc_filters: [],
+ groupby: [],
+ order_desc: true,
+ contribution: false,
+ row_limit: 50000,
+ color_scheme: 'bnbColors',
+ x_axis_label: 'Frequency',
+ bottom_margin: 'auto',
+ x_ticks_layout: 'auto',
+ x_axis_format: 'smart_date',
+ x_axis_showminmax: false,
+ y_axis_label: 'Num',
+ left_margin: 'auto',
+ y_axis_showminmax: false,
+ y_log_scale: false,
+ y_axis_format: '.3s',
+ rolling_type: 'None',
+ comparison_type: 'values',
+ annotation_layers: [],
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work without groupby', () => {
- verify(COMPARE_FORM_DATA);
- cy.get('.chart-container .nvd3 path.nv-line').should('have.length', 1);
- });
-
- it('should with group by', () => {
- verify({
- ...COMPARE_FORM_DATA,
- groupby: ['gender'],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.chart-container .nvd3 path.nv-line').should('have.length', 2);
- });
- it('should work with filter', () => {
- verify({
- ...COMPARE_FORM_DATA,
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'gender',
- operator: '==',
- comparator: 'boy',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_tqx1en70hh_7nksse7nqic',
- }],
+ it('should work without groupby', () => {
+ verify(COMPARE_FORM_DATA);
+ cy.get('.chart-container .nvd3 path.nv-line').should('have.length', 1);
});
- cy.get('.chart-container .nvd3 path.nv-line').should('have.length', 1);
- });
-});
+ it('should with group by', () => {
+ verify({
+ ...COMPARE_FORM_DATA,
+ groupby: ['gender'],
+ });
+ cy.get('.chart-container .nvd3 path.nv-line').should('have.length', 2);
+ });
+
+ it('should work with filter', () => {
+ verify({
+ ...COMPARE_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'gender',
+ operator: '==',
+ comparator: 'boy',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_tqx1en70hh_7nksse7nqic',
+ },
+ ],
+ });
+ cy.get('.chart-container .nvd3 path.nv-line').should('have.length', 1);
+ });
+ });
diff --git a/superset/assets/cypress/integration/explore/visualizations/dist_bar.js b/superset/assets/cypress/integration/explore/visualizations/dist_bar.js
index 9f8046f0880..7b3a8f0440a 100644
--- a/superset/assets/cypress/integration/explore/visualizations/dist_bar.js
+++ b/superset/assets/cypress/integration/explore/visualizations/dist_bar.js
@@ -20,60 +20,65 @@ import { FORM_DATA_DEFAULTS, NUM_METRIC } from './shared.helper';
// Dist bar
-export default () => describe('Distribution bar chart', () => {
- const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'dist_bar' };
+export default () =>
+ describe('Distribution bar chart', () => {
+ const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'dist_bar' };
- beforeEach(() => {
- cy.login();
- cy.server();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
+ beforeEach(() => {
+ cy.login();
+ cy.server();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
+ });
- it('Test dist bar with adhoc metric', () => {
- const formData = { ...VIZ_DEFAULTS, metrics: NUM_METRIC, groupby: ['state'] };
+ it('Test dist bar with adhoc metric', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: NUM_METRIC,
+ groupby: ['state'],
+ };
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({
- waitAlias: '@getJson',
- querySubstring: NUM_METRIC.label,
- chartSelector: 'svg',
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ querySubstring: NUM_METRIC.label,
+ chartSelector: 'svg',
+ });
+ });
+
+ it('Test dist bar with series', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: NUM_METRIC,
+ groupby: ['state'],
+ columns: ['gender'],
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test dist bar with row limit', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: NUM_METRIC,
+ groupby: ['state'],
+ row_limit: 10,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test dist bar with contribution', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: NUM_METRIC,
+ groupby: ['state'],
+ columns: ['gender'],
+ contribution: true,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
});
});
-
- it('Test dist bar with series', () => {
- const formData = {
- ...VIZ_DEFAULTS,
- metrics: NUM_METRIC,
- groupby: ['state'],
- columns: ['gender'],
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test dist bar with row limit', () => {
- const formData = {
- ...VIZ_DEFAULTS,
- metrics: NUM_METRIC,
- groupby: ['state'],
- row_limit: 10,
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test dist bar with contribution', () => {
- const formData = {
- ...VIZ_DEFAULTS,
- metrics: NUM_METRIC,
- groupby: ['state'],
- columns: ['gender'],
- contribution: true,
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/dual_line.js b/superset/assets/cypress/integration/explore/visualizations/dual_line.js
index 069c96edf04..b86b0b4d5b5 100644
--- a/superset/assets/cypress/integration/explore/visualizations/dual_line.js
+++ b/superset/assets/cypress/integration/explore/visualizations/dual_line.js
@@ -16,56 +16,57 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Dual Line', () => {
- const DUAL_LINE_FORM_DATA = {
- datasource: '3__table',
- viz_type: 'dual_line',
- slice_id: 58,
- granularity_sqla: 'ds',
- time_grain_sqla: 'P1D',
- time_range: '100+years+ago+:+now',
- color_scheme: 'bnbColors',
- x_axis_format: 'smart_date',
- metric: 'avg__num',
- y_axis_format: '.3s',
- metric_2: 'sum__num',
- y_axis_2_format: '.3s',
- adhoc_filters: [],
- annotation_layers: [],
- };
+export default () =>
+ describe('Dual Line', () => {
+ const DUAL_LINE_FORM_DATA = {
+ datasource: '3__table',
+ viz_type: 'dual_line',
+ slice_id: 58,
+ granularity_sqla: 'ds',
+ time_grain_sqla: 'P1D',
+ time_range: '100+years+ago+:+now',
+ color_scheme: 'bnbColors',
+ x_axis_format: 'smart_date',
+ metric: 'avg__num',
+ y_axis_format: '.3s',
+ metric_2: 'sum__num',
+ y_axis_2_format: '.3s',
+ adhoc_filters: [],
+ annotation_layers: [],
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work', () => {
- verify(DUAL_LINE_FORM_DATA);
- cy.get('.chart-container svg path.nv-line').should('have.length', 2);
- });
-
- it('should work with filter', () => {
- verify({
- ...DUAL_LINE_FORM_DATA,
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'gender',
- operator: '==',
- comparator: 'girl',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_1ep6q50g8vk_48jj6qxdems',
- }],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
+ });
+
+ it('should work', () => {
+ verify(DUAL_LINE_FORM_DATA);
+ cy.get('.chart-container svg path.nv-line').should('have.length', 2);
+ });
+
+ it('should work with filter', () => {
+ verify({
+ ...DUAL_LINE_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'gender',
+ operator: '==',
+ comparator: 'girl',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_1ep6q50g8vk_48jj6qxdems',
+ },
+ ],
+ });
+ cy.get('.chart-container svg path.nv-line').should('have.length', 2);
});
- cy.get('.chart-container svg path.nv-line').should('have.length', 2);
});
-
-});
-
diff --git a/superset/assets/cypress/integration/explore/visualizations/filter_box.js b/superset/assets/cypress/integration/explore/visualizations/filter_box.js
index 69654a728f4..f62937de8c5 100644
--- a/superset/assets/cypress/integration/explore/visualizations/filter_box.js
+++ b/superset/assets/cypress/integration/explore/visualizations/filter_box.js
@@ -18,26 +18,26 @@
*/
import { FORM_DATA_DEFAULTS } from './shared.helper';
-export default () => describe('FilterBox', () => {
- const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'filter_box' };
+export default () =>
+ describe('FilterBox', () => {
+ const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'filter_box' };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
+ });
- it('should work with default date filter', () => {
- verify(VIZ_DEFAULTS);
- // Filter box should default to having a date filter with no filter selected
- cy.get('div.filter_box').within(() => {
- cy.get('span').contains('No filter');
+ it('should work with default date filter', () => {
+ verify(VIZ_DEFAULTS);
+ // Filter box should default to having a date filter with no filter selected
+ cy.get('div.filter_box').within(() => {
+ cy.get('span').contains('No filter');
+ });
});
});
-
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/histogram.js b/superset/assets/cypress/integration/explore/visualizations/histogram.js
index 1898a6d27ed..ec1957f0eb9 100644
--- a/superset/assets/cypress/integration/explore/visualizations/histogram.js
+++ b/superset/assets/cypress/integration/explore/visualizations/histogram.js
@@ -16,65 +16,67 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Histogram', () => {
- const HISTOGRAM_FORM_DATA = {
- datasource: '3__table',
- viz_type: 'histogram',
- slice_id: 60,
- granularity_sqla: 'ds',
- time_grain_sqla: 'P1D',
- time_range: '100 years ago : now',
- all_columns_x: ['num'],
- adhoc_filters: [],
- row_limit: 50000,
- groupby: [],
- color_scheme: 'bnbColors',
- link_length: 5,
- x_axis_label: 'Frequency',
- y_axis_label: 'Num',
- global_opacity: 1,
- normalized: false,
- };
+export default () =>
+ describe('Histogram', () => {
+ const HISTOGRAM_FORM_DATA = {
+ datasource: '3__table',
+ viz_type: 'histogram',
+ slice_id: 60,
+ granularity_sqla: 'ds',
+ time_grain_sqla: 'P1D',
+ time_range: '100 years ago : now',
+ all_columns_x: ['num'],
+ adhoc_filters: [],
+ row_limit: 50000,
+ groupby: [],
+ color_scheme: 'bnbColors',
+ link_length: 5,
+ x_axis_label: 'Frequency',
+ y_axis_label: 'Num',
+ global_opacity: 1,
+ normalized: false,
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work without groupby', () => {
- verify(HISTOGRAM_FORM_DATA);
- cy.get('.chart-container svg .vx-bar').should('have.length', 6);
- });
-
- it('should with group by', () => {
- verify({
- ...HISTOGRAM_FORM_DATA,
- groupby: ['gender'],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.chart-container svg .vx-bar').should('have.length', 12);
- });
- it('should work with filter', () => {
- verify({
- ...HISTOGRAM_FORM_DATA,
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'gender',
- operator: '==',
- comparator: 'boy',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_tqx1en70hh_7nksse7nqic',
- }],
+ it('should work without groupby', () => {
+ verify(HISTOGRAM_FORM_DATA);
+ cy.get('.chart-container svg .vx-bar').should('have.length', 6);
});
- cy.get('.chart-container svg .vx-bar').should('have.length', 5);
- });
-});
+ it('should with group by', () => {
+ verify({
+ ...HISTOGRAM_FORM_DATA,
+ groupby: ['gender'],
+ });
+ cy.get('.chart-container svg .vx-bar').should('have.length', 12);
+ });
+
+ it('should work with filter', () => {
+ verify({
+ ...HISTOGRAM_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'gender',
+ operator: '==',
+ comparator: 'boy',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_tqx1en70hh_7nksse7nqic',
+ },
+ ],
+ });
+ cy.get('.chart-container svg .vx-bar').should('have.length', 5);
+ });
+ });
diff --git a/superset/assets/cypress/integration/explore/visualizations/line.js b/superset/assets/cypress/integration/explore/visualizations/line.js
index 94bc393c493..1292072d395 100644
--- a/superset/assets/cypress/integration/explore/visualizations/line.js
+++ b/superset/assets/cypress/integration/explore/visualizations/line.js
@@ -18,223 +18,241 @@
*/
import { FORM_DATA_DEFAULTS, NUM_METRIC, SIMPLE_FILTER } from './shared.helper';
-export default () => describe('Line', () => {
- const LINE_CHART_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'line' };
+export default () =>
+ describe('Line', () => {
+ const LINE_CHART_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'line' };
- beforeEach(() => {
- cy.login();
- cy.server();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('Test line chart with adhoc metric', () => {
- const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test line chart with groupby', () => {
- const metrics = ['count'];
- const groupby = ['gender'];
-
- const formData = { ...LINE_CHART_DEFAULTS, metrics, groupby };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test line chart with simple filter', () => {
- const metrics = ['count'];
- const filters = [SIMPLE_FILTER];
-
- const formData = { ...LINE_CHART_DEFAULTS, metrics, adhoc_filters: filters };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test line chart with series limit sort asc', () => {
- const formData = {
- ...LINE_CHART_DEFAULTS,
- metrics: [NUM_METRIC],
- limit: 10,
- groupby: ['name'],
- timeseries_limit_metric: NUM_METRIC,
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test line chart with series limit sort desc', () => {
- const formData = {
- ...LINE_CHART_DEFAULTS,
- metrics: [NUM_METRIC],
- limit: 10,
- groupby: ['name'],
- timeseries_limit_metric: NUM_METRIC,
- order_desc: true,
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test line chart with rolling avg', () => {
- const metrics = [NUM_METRIC];
-
- const formData = { ...LINE_CHART_DEFAULTS, metrics, rolling_type: 'mean', rolling_periods: 10 };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test line chart with time shift 1 year', () => {
- const metrics = [NUM_METRIC];
-
- const formData = {
- ...LINE_CHART_DEFAULTS,
- metrics,
- time_compare: ['1+year'],
- comparison_type: 'values',
- groupby: ['gender'],
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
-
- // Offset color should match original line color
- cy.get('.nv-legend-text')
- .contains('boy')
- .siblings()
- .first()
- .should('have.attr', 'style')
- .then((style) => {
- cy.get('.nv-legend-text')
- .contains('boy, 1 year offset')
- .siblings()
- .first()
- .should('have.attr', 'style')
- .and('eq', style);
- });
-
- cy.get('.nv-legend-text')
- .contains('girl')
- .siblings()
- .first()
- .should('have.attr', 'style')
- .then((style) => {
- cy.get('.nv-legend-text')
- .contains('girl, 1 year offset')
- .siblings()
- .first()
- .should('have.attr', 'style')
- .and('eq', style);
- });
- });
-
- it('Test line chart with time shift yoy', () => {
- const metrics = [NUM_METRIC];
-
- const formData = {
- ...LINE_CHART_DEFAULTS,
- metrics,
- time_compare: ['1+year'],
- comparison_type: 'ratio',
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test line chart with time shift percentage change', () => {
- const metrics = [NUM_METRIC];
-
- const formData = {
- ...LINE_CHART_DEFAULTS,
- metrics,
- time_compare: ['1+year'],
- comparison_type: 'percentage',
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- });
-
- it('Test verbose name shows up in legend', () => {
- const formData = {
- ...LINE_CHART_DEFAULTS,
- metrics: ['count'],
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- cy.get('text.nv-legend-text').contains('COUNT(*)');
- });
-
- it('Test hidden annotation', () => {
- const formData = {
- ...LINE_CHART_DEFAULTS,
- metrics: ['count'],
- annotation_layers: [{
- name: 'Goal+line',
- annotationType: 'FORMULA',
- sourceType: '',
- value: 'y=140000',
- overrides: { time_range: null },
- show: false,
- titleColumn: '',
- descriptionColumns: [],
- timeColumn: '',
- intervalEndColumn: '',
- color: null,
- opacity: '',
- style: 'solid',
- width: 1,
- showMarkers: false,
- hideLine: false,
- }],
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- cy.get('.slice_container').within(() => {
- // Goal line annotation doesn't show up in legend
- cy.get('.nv-legend-text').should('have.length', 1);
+ beforeEach(() => {
+ cy.login();
+ cy.server();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- });
- it('Test event annotation time override', () => {
- cy.request('/chart/api/read?_flt_3_slice_name=Daily+Totals').then((response) => {
- const value = response.body.pks[0];
+ it('Test line chart with adhoc metric', () => {
+ const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test line chart with groupby', () => {
+ const metrics = ['count'];
+ const groupby = ['gender'];
+
+ const formData = { ...LINE_CHART_DEFAULTS, metrics, groupby };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test line chart with simple filter', () => {
+ const metrics = ['count'];
+ const filters = [SIMPLE_FILTER];
+
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics,
+ adhoc_filters: filters,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test line chart with series limit sort asc', () => {
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics: [NUM_METRIC],
+ limit: 10,
+ groupby: ['name'],
+ timeseries_limit_metric: NUM_METRIC,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test line chart with series limit sort desc', () => {
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics: [NUM_METRIC],
+ limit: 10,
+ groupby: ['name'],
+ timeseries_limit_metric: NUM_METRIC,
+ order_desc: true,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test line chart with rolling avg', () => {
+ const metrics = [NUM_METRIC];
+
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics,
+ rolling_type: 'mean',
+ rolling_periods: 10,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test line chart with time shift 1 year', () => {
+ const metrics = [NUM_METRIC];
+
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics,
+ time_compare: ['1+year'],
+ comparison_type: 'values',
+ groupby: ['gender'],
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+
+ // Offset color should match original line color
+ cy.get('.nv-legend-text')
+ .contains('boy')
+ .siblings()
+ .first()
+ .should('have.attr', 'style')
+ .then(style => {
+ cy.get('.nv-legend-text')
+ .contains('boy, 1 year offset')
+ .siblings()
+ .first()
+ .should('have.attr', 'style')
+ .and('eq', style);
+ });
+
+ cy.get('.nv-legend-text')
+ .contains('girl')
+ .siblings()
+ .first()
+ .should('have.attr', 'style')
+ .then(style => {
+ cy.get('.nv-legend-text')
+ .contains('girl, 1 year offset')
+ .siblings()
+ .first()
+ .should('have.attr', 'style')
+ .and('eq', style);
+ });
+ });
+
+ it('Test line chart with time shift yoy', () => {
+ const metrics = [NUM_METRIC];
+
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics,
+ time_compare: ['1+year'],
+ comparison_type: 'ratio',
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test line chart with time shift percentage change', () => {
+ const metrics = [NUM_METRIC];
+
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics,
+ time_compare: ['1+year'],
+ comparison_type: 'percentage',
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ });
+
+ it('Test verbose name shows up in legend', () => {
const formData = {
...LINE_CHART_DEFAULTS,
metrics: ['count'],
- annotation_layers: [{
- name: 'Yearly date',
- annotationType: 'EVENT',
- sourceType: 'table',
- value,
- overrides: { time_range: null },
- show: true,
- titleColumn: 'ds',
- descriptionColumns: ['ds'],
- timeColumn: 'ds',
- color: null,
- opacity: '',
- style: 'solid',
- width: 1,
- showMarkers: false,
- hideLine: false,
- }],
};
+
cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ cy.get('text.nv-legend-text').contains('COUNT(*)');
});
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- cy.get('.slice_container').within(() => {
- cy.get('.nv-event-annotation-layer-0').children().should('have.length', 44);
+ it('Test hidden annotation', () => {
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics: ['count'],
+ annotation_layers: [
+ {
+ name: 'Goal+line',
+ annotationType: 'FORMULA',
+ sourceType: '',
+ value: 'y=140000',
+ overrides: { time_range: null },
+ show: false,
+ titleColumn: '',
+ descriptionColumns: [],
+ timeColumn: '',
+ intervalEndColumn: '',
+ color: null,
+ opacity: '',
+ style: 'solid',
+ width: 1,
+ showMarkers: false,
+ hideLine: false,
+ },
+ ],
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ cy.get('.slice_container').within(() => {
+ // Goal line annotation doesn't show up in legend
+ cy.get('.nv-legend-text').should('have.length', 1);
+ });
+ });
+
+ it('Test event annotation time override', () => {
+ cy.request('/chart/api/read?_flt_3_slice_name=Daily+Totals').then(
+ response => {
+ const value = response.body.pks[0];
+ const formData = {
+ ...LINE_CHART_DEFAULTS,
+ metrics: ['count'],
+ annotation_layers: [
+ {
+ name: 'Yearly date',
+ annotationType: 'EVENT',
+ sourceType: 'table',
+ value,
+ overrides: { time_range: null },
+ show: true,
+ titleColumn: 'ds',
+ descriptionColumns: ['ds'],
+ timeColumn: 'ds',
+ color: null,
+ opacity: '',
+ style: 'solid',
+ width: 1,
+ showMarkers: false,
+ hideLine: false,
+ },
+ ],
+ };
+ cy.visitChartByParams(JSON.stringify(formData));
+ },
+ );
+
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ cy.get('.slice_container').within(() => {
+ cy.get('.nv-event-annotation-layer-0')
+ .children()
+ .should('have.length', 44);
+ });
});
});
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/pie.js b/superset/assets/cypress/integration/explore/visualizations/pie.js
index 6b404d4e6a8..832b6743f24 100644
--- a/superset/assets/cypress/integration/explore/visualizations/pie.js
+++ b/superset/assets/cypress/integration/explore/visualizations/pie.js
@@ -16,56 +16,65 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Pie', () => {
- const PIE_FORM_DATA = {
- datasource: '3__table',
- viz_type: 'pie',
- slice_id: 55,
- granularity_sqla: 'ds',
- time_grain_sqla: 'P1D',
- time_range: '100 years ago : now',
- metric: 'sum__num',
- adhoc_filters: [],
- groupby: ['gender'],
- row_limit: 50000,
- pie_label_type: 'key',
- donut: false,
- show_legend: true,
- show_labels: true,
- labels_outside: true,
- color_scheme: 'bnbColors',
- };
+export default () =>
+ describe('Pie', () => {
+ const PIE_FORM_DATA = {
+ datasource: '3__table',
+ viz_type: 'pie',
+ slice_id: 55,
+ granularity_sqla: 'ds',
+ time_grain_sqla: 'P1D',
+ time_range: '100 years ago : now',
+ metric: 'sum__num',
+ adhoc_filters: [],
+ groupby: ['gender'],
+ row_limit: 50000,
+ pie_label_type: 'key',
+ donut: false,
+ show_legend: true,
+ show_labels: true,
+ labels_outside: true,
+ color_scheme: 'bnbColors',
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work with ad-hoc metric', () => {
- verify(PIE_FORM_DATA);
- cy.get('.chart-container .nv-pie .nv-slice path').should('have.length', 2);
- });
-
- it('should work with simple filter', () => {
- verify({
- ...PIE_FORM_DATA,
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'gender',
- operator: '==',
- comparator: 'boy',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_tqx1en70hh_7nksse7nqic',
- }],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
+ });
+
+ it('should work with ad-hoc metric', () => {
+ verify(PIE_FORM_DATA);
+ cy.get('.chart-container .nv-pie .nv-slice path').should(
+ 'have.length',
+ 2,
+ );
+ });
+
+ it('should work with simple filter', () => {
+ verify({
+ ...PIE_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'gender',
+ operator: '==',
+ comparator: 'boy',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_tqx1en70hh_7nksse7nqic',
+ },
+ ],
+ });
+ cy.get('.chart-container .nv-pie .nv-slice path').should(
+ 'have.length',
+ 1,
+ );
});
- cy.get('.chart-container .nv-pie .nv-slice path').should('have.length', 1);
});
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/pivot_table.js b/superset/assets/cypress/integration/explore/visualizations/pivot_table.js
index 4422d04359d..88746086e96 100644
--- a/superset/assets/cypress/integration/explore/visualizations/pivot_table.js
+++ b/superset/assets/cypress/integration/explore/visualizations/pivot_table.js
@@ -16,95 +16,114 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Pivot Table', () => {
- const PIVOT_TABLE_FORM_DATA = {
- datasource: '3__table',
- viz_type: 'pivot_table',
- slice_id: 61,
- granularity_sqla: 'ds',
- time_grain_sqla: 'P1D',
- time_range: '100+years+ago+:+now',
- metrics: ['sum__num'],
- adhoc_filters: [],
- groupby: ['name'],
- columns: ['state'],
- row_limit: 50000,
- pandas_aggfunc: 'sum',
- pivot_margins: true,
- number_format: '.3s',
- combine_metric: false,
- };
+export default () =>
+ describe('Pivot Table', () => {
+ const PIVOT_TABLE_FORM_DATA = {
+ datasource: '3__table',
+ viz_type: 'pivot_table',
+ slice_id: 61,
+ granularity_sqla: 'ds',
+ time_grain_sqla: 'P1D',
+ time_range: '100+years+ago+:+now',
+ metrics: ['sum__num'],
+ adhoc_filters: [],
+ groupby: ['name'],
+ columns: ['state'],
+ row_limit: 50000,
+ pandas_aggfunc: 'sum',
+ pivot_margins: true,
+ number_format: '.3s',
+ combine_metric: false,
+ };
- const TEST_METRIC = {
- expressionType: 'SIMPLE',
- column: {
- id: 338,
- column_name: 'sum_boys',
- expression: '',
- filterable: false,
- groupby: false,
- is_dttm: false,
- type: 'BIGINT',
- optionName: '_col_sum_boys',
- },
- aggregate: 'SUM',
- hasCustomLabel: false,
- fromFormData: false,
- label: 'SUM(sum_boys)',
- optionName: 'metric_gvpdjt0v2qf_6hkf56o012',
- };
+ const TEST_METRIC = {
+ expressionType: 'SIMPLE',
+ column: {
+ id: 338,
+ column_name: 'sum_boys',
+ expression: '',
+ filterable: false,
+ groupby: false,
+ is_dttm: false,
+ type: 'BIGINT',
+ optionName: '_col_sum_boys',
+ },
+ aggregate: 'SUM',
+ hasCustomLabel: false,
+ fromFormData: false,
+ label: 'SUM(sum_boys)',
+ optionName: 'metric_gvpdjt0v2qf_6hkf56o012',
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
+ });
- it('should work with single groupby', () => {
- verify(PIVOT_TABLE_FORM_DATA);
- cy.get('.chart-container tr th').then((ths) => {
- expect(ths.find(th => th.innerText.trim() === 'name')).to.not.equal(undefined);
+ it('should work with single groupby', () => {
+ verify(PIVOT_TABLE_FORM_DATA);
+ cy.get('.chart-container tr th').then(ths => {
+ expect(ths.find(th => th.innerText.trim() === 'name')).to.not.equal(
+ undefined,
+ );
+ });
+ });
+
+ it('should work with more than one groupby', () => {
+ verify({
+ ...PIVOT_TABLE_FORM_DATA,
+ groupby: ['name', 'gender'],
+ });
+ cy.get('.chart-container tr th').then(ths => {
+ expect(ths.find(th => th.innerText.trim() === 'name')).to.not.equal(
+ undefined,
+ );
+ expect(ths.find(th => th.innerText.trim() === 'gender')).to.not.equal(
+ undefined,
+ );
+ });
+ });
+
+ it('should work with multiple metrics', () => {
+ verify({
+ ...PIVOT_TABLE_FORM_DATA,
+ metrics: ['sum__num', TEST_METRIC],
+ });
+ cy.get('.chart-container tr th').then(ths => {
+ expect(ths.find(th => th.innerText.trim() === 'sum__num')).to.not.equal(
+ undefined,
+ );
+ expect(
+ ths.find(th => th.innerText.trim() === 'SUM(sum_boys)'),
+ ).to.not.equal(undefined);
+ });
+ });
+
+ it('should work with multiple groupby and multiple metrics', () => {
+ verify({
+ ...PIVOT_TABLE_FORM_DATA,
+ groupby: ['name', 'gender'],
+ metrics: ['sum__num', TEST_METRIC],
+ });
+ cy.get('.chart-container tr th').then(ths => {
+ expect(ths.find(th => th.innerText.trim() === 'name')).to.not.equal(
+ undefined,
+ );
+ expect(ths.find(th => th.innerText.trim() === 'gender')).to.not.equal(
+ undefined,
+ );
+ expect(ths.find(th => th.innerText.trim() === 'sum__num')).to.not.equal(
+ undefined,
+ );
+ expect(
+ ths.find(th => th.innerText.trim() === 'SUM(sum_boys)'),
+ ).to.not.equal(undefined);
+ });
});
});
-
- it('should work with more than one groupby', () => {
- verify({
- ...PIVOT_TABLE_FORM_DATA,
- groupby: ['name', 'gender'],
- });
- cy.get('.chart-container tr th').then((ths) => {
- expect(ths.find(th => th.innerText.trim() === 'name')).to.not.equal(undefined);
- expect(ths.find(th => th.innerText.trim() === 'gender')).to.not.equal(undefined);
- });
- });
-
- it('should work with multiple metrics', () => {
- verify({
- ...PIVOT_TABLE_FORM_DATA,
- metrics: ['sum__num', TEST_METRIC],
- });
- cy.get('.chart-container tr th').then((ths) => {
- expect(ths.find(th => th.innerText.trim() === 'sum__num')).to.not.equal(undefined);
- expect(ths.find(th => th.innerText.trim() === 'SUM(sum_boys)')).to.not.equal(undefined);
- });
- });
-
- it('should work with multiple groupby and multiple metrics', () => {
- verify({
- ...PIVOT_TABLE_FORM_DATA,
- groupby: ['name', 'gender'],
- metrics: ['sum__num', TEST_METRIC],
- });
- cy.get('.chart-container tr th').then((ths) => {
- expect(ths.find(th => th.innerText.trim() === 'name')).to.not.equal(undefined);
- expect(ths.find(th => th.innerText.trim() === 'gender')).to.not.equal(undefined);
- expect(ths.find(th => th.innerText.trim() === 'sum__num')).to.not.equal(undefined);
- expect(ths.find(th => th.innerText.trim() === 'SUM(sum_boys)')).to.not.equal(undefined);
- });
- });
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/sankey.js b/superset/assets/cypress/integration/explore/visualizations/sankey.js
index 4e346364b5e..45b81bc840b 100644
--- a/superset/assets/cypress/integration/explore/visualizations/sankey.js
+++ b/superset/assets/cypress/integration/explore/visualizations/sankey.js
@@ -16,63 +16,65 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Sankey', () => {
- const SANKEY_FORM_DATA = {
- datasource: '1__table',
- viz_type: 'sankey',
- slice_id: 1,
- url_params: {},
- granularity_sqla: null,
- time_grain_sqla: 'P1D',
- time_range: 'Last+week',
- groupby: ['source', 'target'],
- metric: 'sum__value',
- adhoc_filters: [],
- row_limit: '5000',
- color_scheme: 'bnbColors',
- };
+export default () =>
+ describe('Sankey', () => {
+ const SANKEY_FORM_DATA = {
+ datasource: '1__table',
+ viz_type: 'sankey',
+ slice_id: 1,
+ url_params: {},
+ granularity_sqla: null,
+ time_grain_sqla: 'P1D',
+ time_range: 'Last+week',
+ groupby: ['source', 'target'],
+ metric: 'sum__value',
+ adhoc_filters: [],
+ row_limit: '5000',
+ color_scheme: 'bnbColors',
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work', () => {
- verify(SANKEY_FORM_DATA);
- cy.get('.chart-container svg g.node rect').should('have.length', 41);
- });
-
- it('should work with filter', () => {
- verify({
- ...SANKEY_FORM_DATA,
- adhoc_filters: [
- {
- expressionType: 'SQL',
- sqlExpression: 'SUM(value)+>+0',
- clause: 'HAVING',
- subject: null,
- operator: null,
- comparator: null,
- fromFormData: false,
- filterOptionName: 'filter_jbdwe0hayaj_h9jfer8fy58',
- }, {
- expressionType: 'SIMPLE',
- subject: 'source',
- operator: '==',
- comparator: 'Energy',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_8e0otka9uif_vmqri4gmbqc',
- },
- ],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
+ });
+
+ it('should work', () => {
+ verify(SANKEY_FORM_DATA);
+ cy.get('.chart-container svg g.node rect').should('have.length', 41);
+ });
+
+ it('should work with filter', () => {
+ verify({
+ ...SANKEY_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SQL',
+ sqlExpression: 'SUM(value)+>+0',
+ clause: 'HAVING',
+ subject: null,
+ operator: null,
+ comparator: null,
+ fromFormData: false,
+ filterOptionName: 'filter_jbdwe0hayaj_h9jfer8fy58',
+ },
+ {
+ expressionType: 'SIMPLE',
+ subject: 'source',
+ operator: '==',
+ comparator: 'Energy',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_8e0otka9uif_vmqri4gmbqc',
+ },
+ ],
+ });
+ cy.get('.chart-container svg g.node rect').should('have.length', 6);
});
- cy.get('.chart-container svg g.node rect').should('have.length', 6);
});
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/sunburst.js b/superset/assets/cypress/integration/explore/visualizations/sunburst.js
index e57c2e19c8e..fca07731b7a 100644
--- a/superset/assets/cypress/integration/explore/visualizations/sunburst.js
+++ b/superset/assets/cypress/integration/explore/visualizations/sunburst.js
@@ -16,69 +16,71 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Sunburst', () => {
- const SUNBURST_FORM_DATA = {
- datasource: '2__table',
- viz_type: 'sunburst',
- slice_id: 47,
- granularity_sqla: 'year',
- time_grain_sqla: 'P1D',
- time_range: '2011-01-01+:+2011-01-01',
- groupby: ['region'],
- metric: 'sum__SP_POP_TOTL',
- adhoc_filters: [],
- row_limit: 50000,
- color_scheme: 'bnbColors',
- };
+export default () =>
+ describe('Sunburst', () => {
+ const SUNBURST_FORM_DATA = {
+ datasource: '2__table',
+ viz_type: 'sunburst',
+ slice_id: 47,
+ granularity_sqla: 'year',
+ time_grain_sqla: 'P1D',
+ time_range: '2011-01-01+:+2011-01-01',
+ groupby: ['region'],
+ metric: 'sum__SP_POP_TOTL',
+ adhoc_filters: [],
+ row_limit: 50000,
+ color_scheme: 'bnbColors',
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work without secondary metric', () => {
- verify(SUNBURST_FORM_DATA);
- // There should be 7 visible arcs + 1 hidden
- cy.get('.chart-container svg g#arcs path').should('have.length', 8);
- });
-
- it('should work with secondary metric', () => {
- verify({
- ...SUNBURST_FORM_DATA,
- secondary_metric: 'sum__SP_RUR_TOTL',
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.chart-container svg g#arcs path').should('have.length', 8);
- });
- it('should work with multiple groupbys', () => {
- verify({
- ...SUNBURST_FORM_DATA,
- groupby: ['region', 'country_name'],
+ it('should work without secondary metric', () => {
+ verify(SUNBURST_FORM_DATA);
+ // There should be 7 visible arcs + 1 hidden
+ cy.get('.chart-container svg g#arcs path').should('have.length', 8);
});
- cy.get('.chart-container svg g#arcs path').should('have.length', 118);
- });
- it('should work with filter', () => {
- verify({
- ...SUNBURST_FORM_DATA,
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'region',
- operator: 'in',
- comparator: ['South Asia', 'North America'],
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_txje2ikiv6_wxmn0qwd1xo',
- }],
+ it('should work with secondary metric', () => {
+ verify({
+ ...SUNBURST_FORM_DATA,
+ secondary_metric: 'sum__SP_RUR_TOTL',
+ });
+ cy.get('.chart-container svg g#arcs path').should('have.length', 8);
});
- cy.get('.chart-container svg g#arcs path').should('have.length', 3);
- });
-});
+ it('should work with multiple groupbys', () => {
+ verify({
+ ...SUNBURST_FORM_DATA,
+ groupby: ['region', 'country_name'],
+ });
+ cy.get('.chart-container svg g#arcs path').should('have.length', 118);
+ });
+
+ it('should work with filter', () => {
+ verify({
+ ...SUNBURST_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'region',
+ operator: 'in',
+ comparator: ['South Asia', 'North America'],
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_txje2ikiv6_wxmn0qwd1xo',
+ },
+ ],
+ });
+ cy.get('.chart-container svg g#arcs path').should('have.length', 3);
+ });
+ });
diff --git a/superset/assets/cypress/integration/explore/visualizations/table.js b/superset/assets/cypress/integration/explore/visualizations/table.js
index d2088b3a302..b9294ceaeba 100644
--- a/superset/assets/cypress/integration/explore/visualizations/table.js
+++ b/superset/assets/cypress/integration/explore/visualizations/table.js
@@ -21,129 +21,153 @@ import readResponseBlob from '../../../utils/readResponseBlob';
// Table
-export default () => describe('Table chart', () => {
- const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'table' };
+export default () =>
+ describe('Table chart', () => {
+ const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'table' };
- beforeEach(() => {
- cy.login();
- cy.server();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
+ beforeEach(() => {
+ cy.login();
+ cy.server();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
+ });
- it('Test table with adhoc metric', () => {
- const formData = { ...VIZ_DEFAULTS, metrics: NUM_METRIC };
+ it('Test table with adhoc metric', () => {
+ const formData = { ...VIZ_DEFAULTS, metrics: NUM_METRIC };
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({
- waitAlias: '@getJson',
- querySubstring: NUM_METRIC.label,
- chartSelector: 'table',
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ querySubstring: NUM_METRIC.label,
+ chartSelector: 'table',
+ });
+ });
+
+ it('Test table with groupby', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: NUM_METRIC,
+ groupby: ['name'],
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ querySubstring: formData.groupby[0],
+ chartSelector: 'table',
+ });
+ });
+
+ it('Test table with percent metrics and groupby', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ percent_metrics: NUM_METRIC,
+ metrics: [],
+ groupby: ['name'],
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
+ });
+
+ it('Test table with groupby order desc', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: NUM_METRIC,
+ groupby: ['name'],
+ order_desc: true,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
+ });
+
+ it('Test table with groupby and limit', () => {
+ const limit = 10;
+
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: NUM_METRIC,
+ groupby: ['name'],
+ row_limit: limit,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+
+ cy.wait('@getJson').then(async xhr => {
+ cy.verifyResponseCodes(xhr);
+ cy.verifySliceContainer('table');
+ const responseBody = await readResponseBlob(xhr.response.body);
+ expect(responseBody.data.records.length).to.eq(limit);
+ });
+ cy.get('span.label-danger').contains('10 rows');
+ });
+
+ it('Test table with columns and row limit', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ all_columns: ['name'],
+ metrics: [],
+ row_limit: 10,
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
+ });
+
+ it('Test table with columns, ordering, and row limit', () => {
+ const limit = 10;
+
+ const formData = {
+ ...VIZ_DEFAULTS,
+ all_columns: ['name', 'state', 'ds', 'num'],
+ metrics: [],
+ row_limit: limit,
+ order_by_cols: ['["num",+false]'],
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.wait('@getJson').then(async xhr => {
+ cy.verifyResponseCodes(xhr);
+ cy.verifySliceContainer('table');
+ const responseBody = await readResponseBlob(xhr.response.body);
+ const { records } = responseBody.data;
+ expect(records[0].num).greaterThan(records[records.length - 1].num);
+ });
+ });
+
+ it('Test table with simple filter', () => {
+ const metrics = ['count'];
+ const filters = [SIMPLE_FILTER];
+
+ const formData = { ...VIZ_DEFAULTS, metrics, adhoc_filters: filters };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
+ });
+
+ it('Tests table number formatting with % in metric name', () => {
+ const PERCENT_METRIC = {
+ expressionType: 'SQL',
+ sqlExpression: 'CAST(SUM(sum_girls)+AS+FLOAT)/SUM(num)',
+ column: null,
+ aggregate: null,
+ hasCustomLabel: true,
+ fromFormData: true,
+ label: '%+Girls',
+ optionName: 'metric_6qwzgc8bh2v_zox7hil1mzs',
+ };
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: PERCENT_METRIC,
+ groupby: ['state'],
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ querySubstring: formData.groupby[0],
+ chartSelector: 'table',
+ });
+ cy.get('td').contains(/\d*%/);
});
});
-
- it('Test table with groupby', () => {
- const formData = { ...VIZ_DEFAULTS, metrics: NUM_METRIC, groupby: ['name'] };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({
- waitAlias: '@getJson',
- querySubstring: formData.groupby[0],
- chartSelector: 'table',
- });
- });
-
- it('Test table with percent metrics and groupby', () => {
- const formData = {
- ...VIZ_DEFAULTS,
- percent_metrics: NUM_METRIC,
- metrics: [],
- groupby: ['name'],
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
- });
-
- it('Test table with groupby order desc', () => {
- const formData = { ...VIZ_DEFAULTS, metrics: NUM_METRIC, groupby: ['name'], order_desc: true };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
- });
-
- it('Test table with groupby and limit', () => {
- const limit = 10;
-
- const formData = { ...VIZ_DEFAULTS, metrics: NUM_METRIC, groupby: ['name'], row_limit: limit };
-
- cy.visitChartByParams(JSON.stringify(formData));
-
- cy.wait('@getJson').then(async (xhr) => {
- cy.verifyResponseCodes(xhr);
- cy.verifySliceContainer('table');
- const responseBody = await readResponseBlob(xhr.response.body);
- expect(responseBody.data.records.length).to.eq(limit);
- });
- cy.get('span.label-danger').contains('10 rows');
- });
-
- it('Test table with columns and row limit', () => {
- const formData = { ...VIZ_DEFAULTS, all_columns: ['name'], metrics: [], row_limit: 10 };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
- });
-
- it('Test table with columns, ordering, and row limit', () => {
- const limit = 10;
-
- const formData = {
- ...VIZ_DEFAULTS,
- all_columns: ['name', 'state', 'ds', 'num'],
- metrics: [],
- row_limit: limit,
- order_by_cols: ['["num",+false]'],
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.wait('@getJson').then(async (xhr) => {
- cy.verifyResponseCodes(xhr);
- cy.verifySliceContainer('table');
- const responseBody = await readResponseBlob(xhr.response.body);
- const { records } = responseBody.data;
- expect(records[0].num).greaterThan(records[records.length - 1].num);
- });
- });
-
- it('Test table with simple filter', () => {
- const metrics = ['count'];
- const filters = [SIMPLE_FILTER];
-
- const formData = { ...VIZ_DEFAULTS, metrics, adhoc_filters: filters };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'table' });
- });
-
- it('Tests table number formatting with % in metric name', () => {
- const PERCENT_METRIC = {
- expressionType: 'SQL',
- sqlExpression: 'CAST(SUM(sum_girls)+AS+FLOAT)/SUM(num)',
- column: null,
- aggregate: null,
- hasCustomLabel: true,
- fromFormData: true,
- label: '%+Girls',
- optionName: 'metric_6qwzgc8bh2v_zox7hil1mzs',
- };
- const formData = { ...VIZ_DEFAULTS, metrics: PERCENT_METRIC, groupby: ['state'] };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({
- waitAlias: '@getJson',
- querySubstring: formData.groupby[0],
- chartSelector: 'table',
- });
- cy.get('td').contains(/\d*%/);
- });
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/time_table.js b/superset/assets/cypress/integration/explore/visualizations/time_table.js
index 84cfe05cb75..6cd4b87f08c 100644
--- a/superset/assets/cypress/integration/explore/visualizations/time_table.js
+++ b/superset/assets/cypress/integration/explore/visualizations/time_table.js
@@ -20,87 +20,116 @@ import { FORM_DATA_DEFAULTS, NUM_METRIC } from './shared.helper';
// time table viz
-export default () => describe('Time Table Viz', () => {
- const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'time_table' };
+export default () =>
+ describe('Time Table Viz', () => {
+ const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'time_table' };
- beforeEach(() => {
- cy.login();
- cy.server();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('Test time series table multiple metrics last year total', () => {
- const formData = {
- ...VIZ_DEFAULTS,
- metrics: [NUM_METRIC, 'count'],
- column_collection: [{
- key: '9g4K-B-YL',
- label: 'Last+Year',
- colType: 'time',
- timeLag: '1',
- comparisonType: 'value',
- }],
- url: '',
- };
-
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', querySubstring: NUM_METRIC.label });
- cy.get('.time-table').within(() => {
- cy.get('span').contains('Sum(num)');
- cy.get('span').contains('COUNT(*)');
+ beforeEach(() => {
+ cy.login();
+ cy.server();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- });
- it('Test time series table metric and group by last year total', () => {
- const formData = {
- ...VIZ_DEFAULTS,
- metrics: [NUM_METRIC],
- groupby: ['gender'],
- column_collection: [{
- key: '9g4K-B-YL',
- label: 'Last+Year',
- colType: 'time',
- timeLag: '1',
- comparisonType: 'value',
- }],
- url: '',
- };
+ it('Test time series table multiple metrics last year total', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: [NUM_METRIC, 'count'],
+ column_collection: [
+ {
+ key: '9g4K-B-YL',
+ label: 'Last+Year',
+ colType: 'time',
+ timeLag: '1',
+ comparisonType: 'value',
+ },
+ ],
+ url: '',
+ };
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', querySubstring: NUM_METRIC.label });
- cy.get('.time-table').within(() => {
- cy.get('td').contains('boy');
- cy.get('td').contains('girl');
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ querySubstring: NUM_METRIC.label,
+ });
+ cy.get('.time-table').within(() => {
+ cy.get('span').contains('Sum(num)');
+ cy.get('span').contains('COUNT(*)');
+ });
});
- });
- it('Test time series various time columns', () => {
- const formData = {
- ...VIZ_DEFAULTS,
- metrics: [NUM_METRIC, 'count'],
- column_collection: [
- { key: 'LHHNPhamU', label: 'Current', colType: 'time', timeLag: 0 },
- { key: '9g4K-B-YL', label: 'Last Year', colType: 'time', timeLag: '1', comparisonType: 'value' },
- { key: 'JVZXtNu7_', label: 'YoY', colType: 'time', timeLag: 1, comparisonType: 'perc', d3format: '%' },
- { key: 'tN5Gba36u', label: 'Trend', colType: 'spark' },
- ],
- url: '',
- };
+ it('Test time series table metric and group by last year total', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: [NUM_METRIC],
+ groupby: ['gender'],
+ column_collection: [
+ {
+ key: '9g4K-B-YL',
+ label: 'Last+Year',
+ colType: 'time',
+ timeLag: '1',
+ comparisonType: 'value',
+ },
+ ],
+ url: '',
+ };
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', querySubstring: NUM_METRIC.label });
- cy.get('.time-table').within(() => {
- cy.get('th').contains('Current');
- cy.get('th').contains('Last Year');
- cy.get('th').contains('YoY');
- cy.get('th').contains('Trend');
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ querySubstring: NUM_METRIC.label,
+ });
+ cy.get('.time-table').within(() => {
+ cy.get('td').contains('boy');
+ cy.get('td').contains('girl');
+ });
+ });
- cy.get('span').contains('%');
- cy.get('svg').first().then((charts) => {
- const firstChart = charts[0];
- expect(firstChart.clientWidth).greaterThan(0);
- expect(firstChart.clientHeight).greaterThan(0);
+ it('Test time series various time columns', () => {
+ const formData = {
+ ...VIZ_DEFAULTS,
+ metrics: [NUM_METRIC, 'count'],
+ column_collection: [
+ { key: 'LHHNPhamU', label: 'Current', colType: 'time', timeLag: 0 },
+ {
+ key: '9g4K-B-YL',
+ label: 'Last Year',
+ colType: 'time',
+ timeLag: '1',
+ comparisonType: 'value',
+ },
+ {
+ key: 'JVZXtNu7_',
+ label: 'YoY',
+ colType: 'time',
+ timeLag: 1,
+ comparisonType: 'perc',
+ d3format: '%',
+ },
+ { key: 'tN5Gba36u', label: 'Trend', colType: 'spark' },
+ ],
+ url: '',
+ };
+
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({
+ waitAlias: '@getJson',
+ querySubstring: NUM_METRIC.label,
+ });
+ cy.get('.time-table').within(() => {
+ cy.get('th').contains('Current');
+ cy.get('th').contains('Last Year');
+ cy.get('th').contains('YoY');
+ cy.get('th').contains('Trend');
+
+ cy.get('span').contains('%');
+ cy.get('svg')
+ .first()
+ .then(charts => {
+ const firstChart = charts[0];
+ expect(firstChart.clientWidth).greaterThan(0);
+ expect(firstChart.clientHeight).greaterThan(0);
+ });
});
});
});
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/treemap.js b/superset/assets/cypress/integration/explore/visualizations/treemap.js
index 83c1a99c46a..16560aa0ef3 100644
--- a/superset/assets/cypress/integration/explore/visualizations/treemap.js
+++ b/superset/assets/cypress/integration/explore/visualizations/treemap.js
@@ -16,62 +16,65 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('Treemap', () => {
- const TREEMAP_FORM_DATA = {
- datasource: '2__table',
- viz_type: 'treemap',
- slice_id: 50,
- granularity_sqla: 'year',
- time_grain_sqla: 'P1D',
- time_range: '1960-01-01+:+now',
- metrics: ['sum__SP_POP_TOTL'],
- adhoc_filters: [],
- groupby: ['country_code'],
- row_limit: 50000,
- color_scheme: 'bnbColors',
- treemap_ratio: 1.618033988749895,
- number_format: '.3s',
- };
+export default () =>
+ describe('Treemap', () => {
+ const TREEMAP_FORM_DATA = {
+ datasource: '2__table',
+ viz_type: 'treemap',
+ slice_id: 50,
+ granularity_sqla: 'year',
+ time_grain_sqla: 'P1D',
+ time_range: '1960-01-01+:+now',
+ metrics: ['sum__SP_POP_TOTL'],
+ adhoc_filters: [],
+ groupby: ['country_code'],
+ row_limit: 50000,
+ color_scheme: 'bnbColors',
+ treemap_ratio: 1.618033988749895,
+ number_format: '.3s',
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work', () => {
- verify(TREEMAP_FORM_DATA);
- cy.get('.chart-container svg rect.child').should('have.length', 214);
- });
-
- it('should work with multiple groupby', () => {
- verify({
- ...TREEMAP_FORM_DATA,
- groupby: ['region', 'country_code'],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.chart-container svg rect.parent').should('have.length', 7);
- cy.get('.chart-container svg rect.child').should('have.length', 214);
- });
- it('should work with filter', () => {
- verify({
- ...TREEMAP_FORM_DATA,
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'region',
- operator: '==',
- comparator: 'South Asia',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_8aqxcf5co1a_x7lm2d1fq0l',
- }],
+ it('should work', () => {
+ verify(TREEMAP_FORM_DATA);
+ cy.get('.chart-container svg rect.child').should('have.length', 214);
+ });
+
+ it('should work with multiple groupby', () => {
+ verify({
+ ...TREEMAP_FORM_DATA,
+ groupby: ['region', 'country_code'],
+ });
+ cy.get('.chart-container svg rect.parent').should('have.length', 7);
+ cy.get('.chart-container svg rect.child').should('have.length', 214);
+ });
+
+ it('should work with filter', () => {
+ verify({
+ ...TREEMAP_FORM_DATA,
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'region',
+ operator: '==',
+ comparator: 'South Asia',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_8aqxcf5co1a_x7lm2d1fq0l',
+ },
+ ],
+ });
+ cy.get('.chart-container svg rect.child').should('have.length', 8);
});
- cy.get('.chart-container svg rect.child').should('have.length', 8);
});
-});
diff --git a/superset/assets/cypress/integration/explore/visualizations/world_map.js b/superset/assets/cypress/integration/explore/visualizations/world_map.js
index 6eac41fb23d..6db348b2d61 100644
--- a/superset/assets/cypress/integration/explore/visualizations/world_map.js
+++ b/superset/assets/cypress/integration/explore/visualizations/world_map.js
@@ -16,65 +16,71 @@
* specific language governing permissions and limitations
* under the License.
*/
-export default () => describe('World Map', () => {
- const WORLD_MAP_FORM_DATA = {
- datasource: '2__table',
- viz_type: 'world_map',
- slice_id: 45,
- granularity_sqla: 'year',
- time_grain_sqla: 'P1D',
- time_range: '2014-01-01 : 2014-01-02',
- entity: 'country_code',
- country_fieldtype: 'cca3',
- metric: 'sum__SP_RUR_TOTL_ZS',
- adhoc_filters: [],
- row_limit: 50000,
- show_bubbles: true,
- secondary_metric: 'sum__SP_POP_TOTL',
- max_bubble_size: '25',
- };
+export default () =>
+ describe('World Map', () => {
+ const WORLD_MAP_FORM_DATA = {
+ datasource: '2__table',
+ viz_type: 'world_map',
+ slice_id: 45,
+ granularity_sqla: 'year',
+ time_grain_sqla: 'P1D',
+ time_range: '2014-01-01 : 2014-01-02',
+ entity: 'country_code',
+ country_fieldtype: 'cca3',
+ metric: 'sum__SP_RUR_TOTL_ZS',
+ adhoc_filters: [],
+ row_limit: 50000,
+ show_bubbles: true,
+ secondary_metric: 'sum__SP_POP_TOTL',
+ max_bubble_size: '25',
+ };
- function verify(formData) {
- cy.visitChartByParams(JSON.stringify(formData));
- cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
- }
+ function verify(formData) {
+ cy.visitChartByParams(JSON.stringify(formData));
+ cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
+ }
- beforeEach(() => {
- cy.server();
- cy.login();
- cy.route('POST', '/superset/explore_json/**').as('getJson');
- });
-
- it('should work with ad-hoc metric', () => {
- verify(WORLD_MAP_FORM_DATA);
- cy.get('.bubbles circle.datamaps-bubble').should('have.length', 206);
- });
-
- it('should work with simple filter', () => {
- verify({
- ...WORLD_MAP_FORM_DATA,
- metric: 'count',
- adhoc_filters: [{
- expressionType: 'SIMPLE',
- subject: 'region',
- operator: '==',
- comparator: 'South Asia',
- clause: 'WHERE',
- sqlExpression: null,
- fromFormData: true,
- filterOptionName: 'filter_8aqxcf5co1a_x7lm2d1fq0l',
- }],
+ beforeEach(() => {
+ cy.server();
+ cy.login();
+ cy.route('POST', '/superset/explore_json/**').as('getJson');
});
- cy.get('.bubbles circle.datamaps-bubble').should('have.length', 8);
- });
- it('should hide bubbles when told so', () => {
- verify({
- ...WORLD_MAP_FORM_DATA,
- show_bubbles: false,
+ it('should work with ad-hoc metric', () => {
+ verify(WORLD_MAP_FORM_DATA);
+ cy.get('.bubbles circle.datamaps-bubble').should('have.length', 206);
});
- cy.get('.slice_container').then((containers) => {
- expect(containers[0].querySelectorAll('.bubbles circle.datamaps-bubble').length).to.equal(0);
+
+ it('should work with simple filter', () => {
+ verify({
+ ...WORLD_MAP_FORM_DATA,
+ metric: 'count',
+ adhoc_filters: [
+ {
+ expressionType: 'SIMPLE',
+ subject: 'region',
+ operator: '==',
+ comparator: 'South Asia',
+ clause: 'WHERE',
+ sqlExpression: null,
+ fromFormData: true,
+ filterOptionName: 'filter_8aqxcf5co1a_x7lm2d1fq0l',
+ },
+ ],
+ });
+ cy.get('.bubbles circle.datamaps-bubble').should('have.length', 8);
+ });
+
+ it('should hide bubbles when told so', () => {
+ verify({
+ ...WORLD_MAP_FORM_DATA,
+ show_bubbles: false,
+ });
+ cy.get('.slice_container').then(containers => {
+ expect(
+ containers[0].querySelectorAll('.bubbles circle.datamaps-bubble')
+ .length,
+ ).to.equal(0);
+ });
});
});
-});
diff --git a/superset/assets/cypress/integration/sqllab/query.js b/superset/assets/cypress/integration/sqllab/query.js
index cf698f46f6a..df34631c4f0 100644
--- a/superset/assets/cypress/integration/sqllab/query.js
+++ b/superset/assets/cypress/integration/sqllab/query.js
@@ -37,9 +37,9 @@ export default () => {
cy.get('#brace-editor textarea')
.clear({ force: true })
.type(
- `{selectall}{backspace}SELECT ds, gender, name, num FROM main.birth_names LIMIT ${rowLimit}`,
- { force: true },
- );
+ `{selectall}{backspace}SELECT ds, gender, name, num FROM main.birth_names LIMIT ${rowLimit}`,
+ { force: true },
+ );
cy.get('#js-sql-toolbar button')
.eq(0)
.click();
@@ -48,7 +48,7 @@ export default () => {
selectResultsTab()
.eq(0) // ensures results tab in case preview tab exists
- .then((tableNodes) => {
+ .then(tableNodes => {
const [header, bodyWrapper] = tableNodes[0].childNodes;
const body = bodyWrapper.childNodes[0];
const expectedColCount = header.childNodes.length;
@@ -62,7 +62,8 @@ export default () => {
cy.route('savedqueryviewapi/**').as('getSavedQuery');
cy.route('superset/tables/**').as('getTables');
- const query = 'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
+ const query =
+ 'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
const savedQueryTitle = `CYPRESS TEST QUERY ${shortid.generate()}`;
// we will assert that the results of the query we save, and the saved query are the same
@@ -81,7 +82,7 @@ export default () => {
cy.wait('@sqlLabQuery');
// Save results to check agains below
- selectResultsTab().then((resultsA) => {
+ selectResultsTab().then(resultsA => {
initialResultsTable = resultsA[0];
});
@@ -93,8 +94,8 @@ export default () => {
cy.get('.modal-sm input')
.clear({ force: true })
.type(`{selectall}{backspace}${savedQueryTitle}`, {
- force: true,
- });
+ force: true,
+ });
cy.get('.modal-sm .modal-body button')
.eq(0) // save
@@ -117,10 +118,13 @@ export default () => {
cy.wait('@sqlLabQuery');
// assert the results of the saved query match the initial results
- selectResultsTab().then((resultsB) => {
+ selectResultsTab().then(resultsB => {
savedQueryResultsTable = resultsB[0];
- assertSQLLabResultsAreEqual(initialResultsTable, savedQueryResultsTable);
+ assertSQLLabResultsAreEqual(
+ initialResultsTable,
+ savedQueryResultsTable,
+ );
});
});
});
diff --git a/superset/assets/cypress/integration/sqllab/sourcePanel.js b/superset/assets/cypress/integration/sqllab/sourcePanel.js
index df15334c2f9..ef977b2f7f5 100644
--- a/superset/assets/cypress/integration/sqllab/sourcePanel.js
+++ b/superset/assets/cypress/integration/sqllab/sourcePanel.js
@@ -35,7 +35,9 @@ export default () => {
cy.get('.sql-toolbar .Select').should('have.length', 3);
cy.get('.sql-toolbar .table-schema').should('not.exist');
- cy.get('.SouthPane .tab-content .filterable-table-container').should('not.exist');
+ cy.get('.SouthPane .tab-content .filterable-table-container').should(
+ 'not.exist',
+ );
cy.get('.sql-toolbar .Select')
.eq(0) // database select
diff --git a/superset/assets/cypress/integration/sqllab/tabs.js b/superset/assets/cypress/integration/sqllab/tabs.js
index 0d9731ef982..2fc102e241d 100644
--- a/superset/assets/cypress/integration/sqllab/tabs.js
+++ b/superset/assets/cypress/integration/sqllab/tabs.js
@@ -25,7 +25,7 @@ export default () => {
});
it('allows you to create a tab', () => {
- cy.get('#a11y-query-editor-tabs > ul > li').then((tabList) => {
+ cy.get('#a11y-query-editor-tabs > ul > li').then(tabList => {
const initialTabCount = tabList.length;
// add tab
@@ -33,23 +33,31 @@ export default () => {
.last()
.click();
- cy.get('#a11y-query-editor-tabs > ul > li').should('have.length', initialTabCount + 1);
+ cy.get('#a11y-query-editor-tabs > ul > li').should(
+ 'have.length',
+ initialTabCount + 1,
+ );
});
});
it('allows you to close a tab', () => {
- cy.get('#a11y-query-editor-tabs > ul > li').then((tabListA) => {
+ cy.get('#a11y-query-editor-tabs > ul > li').then(tabListA => {
const initialTabCount = tabListA.length;
// open the tab dropdown to remove
- cy.get('#a11y-query-editor-tabs > ul > li:first button:nth-child(2)').click();
+ cy.get(
+ '#a11y-query-editor-tabs > ul > li:first button:nth-child(2)',
+ ).click();
// first item is close
cy.get('#a11y-query-editor-tabs > ul > li:first ul li a')
.eq(0)
.click();
- cy.get('#a11y-query-editor-tabs > ul > li').should('have.length', initialTabCount - 1);
+ cy.get('#a11y-query-editor-tabs > ul > li').should(
+ 'have.length',
+ initialTabCount - 1,
+ );
});
});
});
diff --git a/superset/assets/cypress/support/commands.js b/superset/assets/cypress/support/commands.js
index dd3be98216f..1c12e4fb20d 100644
--- a/superset/assets/cypress/support/commands.js
+++ b/superset/assets/cypress/support/commands.js
@@ -51,26 +51,26 @@ Cypress.Commands.add('login', () => {
method: 'POST',
url: '/login/',
body: { username: 'admin', password: 'general' },
- }).then((response) => {
+ }).then(response => {
expect(response.status).to.eq(200);
});
});
-Cypress.Commands.add('visitChartByName', (name) => {
- cy.request(`/chart/api/read?_flt_3_slice_name=${name}`).then((response) => {
+Cypress.Commands.add('visitChartByName', name => {
+ cy.request(`/chart/api/read?_flt_3_slice_name=${name}`).then(response => {
cy.visit(`${BASE_EXPLORE_URL}{"slice_id": ${response.body.pks[0]}}`);
});
});
-Cypress.Commands.add('visitChartById', (chartId) => {
+Cypress.Commands.add('visitChartById', chartId => {
cy.visit(`${BASE_EXPLORE_URL}{"slice_id": ${chartId}}`);
});
-Cypress.Commands.add('visitChartByParams', (params) => {
+Cypress.Commands.add('visitChartByParams', params => {
cy.visit(`${BASE_EXPLORE_URL}${params}`);
});
-Cypress.Commands.add('verifyResponseCodes', async (xhr) => {
+Cypress.Commands.add('verifyResponseCodes', async xhr => {
// After a wait response check for valid response
expect(xhr.status).to.eq(200);
@@ -81,11 +81,11 @@ Cypress.Commands.add('verifyResponseCodes', async (xhr) => {
}
});
-Cypress.Commands.add('verifySliceContainer', (chartSelector) => {
+Cypress.Commands.add('verifySliceContainer', chartSelector => {
// After a wait response check for valid slice container
cy.get('.slice_container').within(() => {
if (chartSelector) {
- cy.get(chartSelector).then((charts) => {
+ cy.get(chartSelector).then(charts => {
const firstChart = charts[0];
expect(firstChart.clientWidth).greaterThan(0);
expect(firstChart.clientHeight).greaterThan(0);
@@ -94,15 +94,18 @@ Cypress.Commands.add('verifySliceContainer', (chartSelector) => {
});
});
-Cypress.Commands.add('verifySliceSuccess', ({ waitAlias, querySubstring, chartSelector }) => {
- cy.wait(waitAlias).then(async (xhr) => {
- cy.verifyResponseCodes(xhr);
+Cypress.Commands.add(
+ 'verifySliceSuccess',
+ ({ waitAlias, querySubstring, chartSelector }) => {
+ cy.wait(waitAlias).then(async xhr => {
+ cy.verifyResponseCodes(xhr);
- const responseBody = await readResponseBlob(xhr.response.body);
- if (querySubstring) {
- expect(responseBody.query).contains(querySubstring);
- }
+ const responseBody = await readResponseBlob(xhr.response.body);
+ if (querySubstring) {
+ expect(responseBody.query).contains(querySubstring);
+ }
- cy.verifySliceContainer(chartSelector);
- });
-});
+ cy.verifySliceContainer(chartSelector);
+ });
+ },
+);
diff --git a/superset/assets/cypress/support/index.js b/superset/assets/cypress/support/index.js
index 68b580a2564..9ff4b7b1a48 100644
--- a/superset/assets/cypress/support/index.js
+++ b/superset/assets/cypress/support/index.js
@@ -36,6 +36,6 @@ import './commands';
// The following is a workaround for Cypress not supporting fetch.
// By setting window.fetch = null, we force the fetch polyfill to fall back
// to xhr as described here https://github.com/cypress-io/cypress/issues/95
-Cypress.on('window:before:load', (win) => {
+Cypress.on('window:before:load', win => {
win.fetch = null; // eslint-disable-line no-param-reassign
});
diff --git a/superset/assets/cypress/utils/readResponseBlob.js b/superset/assets/cypress/utils/readResponseBlob.js
index 429485a8a64..6cf077b37ab 100644
--- a/superset/assets/cypress/utils/readResponseBlob.js
+++ b/superset/assets/cypress/utils/readResponseBlob.js
@@ -21,7 +21,7 @@
// and that the response can be parsed as JSON. This is needed to read
// the value of any fetch-based response.
export default function readResponseBlob(blob) {
- return new Promise((resolve) => {
+ return new Promise(resolve => {
const reader = new FileReader();
reader.onload = () => resolve(JSON.parse(reader.result));
reader.readAsText(blob);
diff --git a/superset/assets/package-lock.json b/superset/assets/package-lock.json
index d53f9b7e212..4ab9b1583cd 100644
--- a/superset/assets/package-lock.json
+++ b/superset/assets/package-lock.json
@@ -19894,9 +19894,9 @@
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
},
"prettier": {
- "version": "1.15.3",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.15.3.tgz",
- "integrity": "sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg==",
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
+ "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
"dev": true
},
"pretty-format": {
diff --git a/superset/assets/package.json b/superset/assets/package.json
index 59c29c58630..b82d2d3c44f 100644
--- a/superset/assets/package.json
+++ b/superset/assets/package.json
@@ -200,7 +200,7 @@
"minimist": "^1.2.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"po2json": "^0.4.5",
- "prettier": "^1.12.1",
+ "prettier": "^1.19.1",
"react-test-renderer": "^16.9.0",
"redux-mock-store": "^1.2.3",
"sinon": "^4.5.0",
diff --git a/superset/assets/spec/helpers/shim.js b/superset/assets/spec/helpers/shim.js
index 06ecc790b6f..b6ca1b92d9f 100644
--- a/superset/assets/spec/helpers/shim.js
+++ b/superset/assets/spec/helpers/shim.js
@@ -36,7 +36,7 @@ global.document = global.jsdom('
');
global.window = document.defaultView;
global.HTMLElement = window.HTMLElement;
-Object.keys(document.defaultView).forEach((property) => {
+Object.keys(document.defaultView).forEach(property => {
if (typeof global[property] === 'undefined') {
exposedProperties.push(property);
global[property] = document.defaultView[property];
diff --git a/superset/assets/spec/javascripts/CRUD/CollectionTable_spec.jsx b/superset/assets/spec/javascripts/CRUD/CollectionTable_spec.jsx
index 0feb2cd120c..119947a46d2 100644
--- a/superset/assets/spec/javascripts/CRUD/CollectionTable_spec.jsx
+++ b/superset/assets/spec/javascripts/CRUD/CollectionTable_spec.jsx
@@ -28,7 +28,6 @@ const props = {
};
describe('CollectionTable', () => {
-
let wrapper;
let el;
@@ -46,5 +45,4 @@ describe('CollectionTable', () => {
expect(wrapper.find('table')).toHaveLength(1);
expect(wrapper.find('tbody tr.row')).toHaveLength(length);
});
-
});
diff --git a/superset/assets/spec/javascripts/addSlice/AddSliceContainer_spec.jsx b/superset/assets/spec/javascripts/addSlice/AddSliceContainer_spec.jsx
index e16b9889378..a399d22e782 100644
--- a/superset/assets/spec/javascripts/addSlice/AddSliceContainer_spec.jsx
+++ b/superset/assets/spec/javascripts/addSlice/AddSliceContainer_spec.jsx
@@ -52,7 +52,12 @@ describe('AddSliceContainer', () => {
});
it('renders a disabled button if no datasource is selected', () => {
- expect(wrapper.find(Button).dive().find('.btn[disabled=true]')).toHaveLength(1);
+ expect(
+ wrapper
+ .find(Button)
+ .dive()
+ .find('.btn[disabled=true]'),
+ ).toHaveLength(1);
});
it('renders an enabled button if datasource is selected', () => {
@@ -62,7 +67,12 @@ describe('AddSliceContainer', () => {
datasourceId: datasourceValue.split('__')[0],
datasourceType: datasourceValue.split('__')[1],
});
- expect(wrapper.find(Button).dive().find('.btn[disabled=false]')).toHaveLength(1);
+ expect(
+ wrapper
+ .find(Button)
+ .dive()
+ .find('.btn[disabled=false]'),
+ ).toHaveLength(1);
});
it('formats explore url', () => {
@@ -72,7 +82,8 @@ describe('AddSliceContainer', () => {
datasourceId: datasourceValue.split('__')[0],
datasourceType: datasourceValue.split('__')[1],
});
- const formattedUrl = '/superset/explore/?form_data=%7B%22viz_type%22%3A%22table%22%2C%22datasource%22%3A%221__table%22%7D';
+ const formattedUrl =
+ '/superset/explore/?form_data=%7B%22viz_type%22%3A%22table%22%2C%22datasource%22%3A%221__table%22%7D';
expect(wrapper.instance().exploreUrl()).toBe(formattedUrl);
});
});
diff --git a/superset/assets/spec/javascripts/chart/chartActions_spec.js b/superset/assets/spec/javascripts/chart/chartActions_spec.js
index a4a832632e3..56e8cfb6386 100644
--- a/superset/assets/spec/javascripts/chart/chartActions_spec.js
+++ b/superset/assets/spec/javascripts/chart/chartActions_spec.js
@@ -117,7 +117,9 @@ describe('chart actions', () => {
it('should CHART_UPDATE_TIMEOUT action upon query timeout', () => {
const unresolvingPromise = new Promise(() => {});
- fetchMock.post(MOCK_URL, () => unresolvingPromise, { overwriteRoutes: true });
+ fetchMock.post(MOCK_URL, () => unresolvingPromise, {
+ overwriteRoutes: true,
+ });
const timeoutInSec = 1 / 1000;
const actionThunk = actions.postChartFormData({}, false, timeoutInSec);
@@ -133,7 +135,11 @@ describe('chart actions', () => {
});
it('should dispatch CHART_UPDATE_FAILED action upon non-timeout non-abort failure', () => {
- fetchMock.post(MOCK_URL, { throws: { statusText: 'misc error' } }, { overwriteRoutes: true });
+ fetchMock.post(
+ MOCK_URL,
+ { throws: { statusText: 'misc error' } },
+ { overwriteRoutes: true },
+ );
const timeoutInSec = 1 / 1000;
const actionThunk = actions.postChartFormData({}, false, timeoutInSec);
diff --git a/superset/assets/spec/javascripts/chart/chartReducers_spec.js b/superset/assets/spec/javascripts/chart/chartReducers_spec.js
index fdf2ed768b1..f2f83c8962d 100644
--- a/superset/assets/spec/javascripts/chart/chartReducers_spec.js
+++ b/superset/assets/spec/javascripts/chart/chartReducers_spec.js
@@ -19,7 +19,6 @@
import chartReducer, { chart } from '../../../src/chart/chartReducer';
import * as actions from '../../../src/chart/chartAction';
-
describe('chart reducers', () => {
const chartKey = 1;
let testChart;
@@ -39,7 +38,10 @@ describe('chart reducers', () => {
});
it('should update endtime on timeout', () => {
- const newState = chartReducer(charts, actions.chartUpdateTimeout('timeout', 60, chartKey));
+ const newState = chartReducer(
+ charts,
+ actions.chartUpdateTimeout('timeout', 60, chartKey),
+ );
expect(newState[chartKey].chartUpdateEndTime).toBeGreaterThan(0);
expect(newState[chartKey].chartStatus).toEqual('failed');
});
diff --git a/superset/assets/spec/javascripts/components/AlteredSliceTag_spec.jsx b/superset/assets/spec/javascripts/components/AlteredSliceTag_spec.jsx
index 51f0002497d..63902ab574c 100644
--- a/superset/assets/spec/javascripts/components/AlteredSliceTag_spec.jsx
+++ b/superset/assets/spec/javascripts/components/AlteredSliceTag_spec.jsx
@@ -164,24 +164,32 @@ describe('AlteredSliceTag', () => {
describe('renderTriggerNode', () => {
it('renders a TooltipWrapper', () => {
- const triggerNode = shallow({wrapper.instance().renderTriggerNode()}
);
+ const triggerNode = shallow(
+ {wrapper.instance().renderTriggerNode()}
,
+ );
expect(triggerNode.find(TooltipWrapper)).toHaveLength(1);
});
});
describe('renderModalBody', () => {
it('renders a Table', () => {
- const modalBody = shallow({wrapper.instance().renderModalBody()}
);
+ const modalBody = shallow(
+ {wrapper.instance().renderModalBody()}
,
+ );
expect(modalBody.find(Table)).toHaveLength(1);
});
it('renders a Thead', () => {
- const modalBody = shallow({wrapper.instance().renderModalBody()}
);
+ const modalBody = shallow(
+ {wrapper.instance().renderModalBody()}
,
+ );
expect(modalBody.find(Thead)).toHaveLength(1);
});
it('renders Th', () => {
- const modalBody = shallow({wrapper.instance().renderModalBody()}
);
+ const modalBody = shallow(
+ {wrapper.instance().renderModalBody()}
,
+ );
const th = modalBody.find(Th);
expect(th).toHaveLength(3);
['control', 'before', 'after'].forEach((v, i) => {
@@ -190,13 +198,17 @@ describe('AlteredSliceTag', () => {
});
it('renders the correct number of Tr', () => {
- const modalBody = shallow({wrapper.instance().renderModalBody()}
);
+ const modalBody = shallow(
+ {wrapper.instance().renderModalBody()}
,
+ );
const tr = modalBody.find(Tr);
expect(tr).toHaveLength(7);
});
it('renders the correct number of Td', () => {
- const modalBody = shallow({wrapper.instance().renderModalBody()}
);
+ const modalBody = shallow(
+ {wrapper.instance().renderModalBody()}
,
+ );
const td = modalBody.find(Td);
expect(td).toHaveLength(21);
['control', 'before', 'after'].forEach((v, i) => {
@@ -225,13 +237,20 @@ describe('AlteredSliceTag', () => {
});
it('returns "Max" and "Min" for BoundsControl', () => {
- expect(wrapper.instance().formatValue([5, 6], 'y_axis_bounds')).toBe('Min: 5, Max: 6');
+ expect(wrapper.instance().formatValue([5, 6], 'y_axis_bounds')).toBe(
+ 'Min: 5, Max: 6',
+ );
});
it('returns stringified objects for CollectionControl', () => {
- const value = [{ 1: 2, alpha: 'bravo' }, { sent: 'imental', w0ke: 5 }];
+ const value = [
+ { 1: 2, alpha: 'bravo' },
+ { sent: 'imental', w0ke: 5 },
+ ];
const expected = '{"1":2,"alpha":"bravo"}, {"sent":"imental","w0ke":5}';
- expect(wrapper.instance().formatValue(value, 'column_collection')).toBe(expected);
+ expect(wrapper.instance().formatValue(value, 'column_collection')).toBe(
+ expected,
+ );
});
it('returns boolean values as string', () => {
@@ -278,7 +297,9 @@ describe('AlteredSliceTag', () => {
},
];
const expected = 'a in [1, g, 7, ho], b not in [hu, ho, ha]';
- expect(wrapper.instance().formatValue(filters, 'adhoc_filters')).toBe(expected);
+ expect(wrapper.instance().formatValue(filters, 'adhoc_filters')).toBe(
+ expected,
+ );
});
it('correctly formats filters with string values', () => {
@@ -299,7 +320,9 @@ describe('AlteredSliceTag', () => {
},
];
const expected = 'a == gucci, b LIKE moshi moshi';
- expect(wrapper.instance().formatValue(filters, 'adhoc_filters')).toBe(expected);
+ expect(wrapper.instance().formatValue(filters, 'adhoc_filters')).toBe(
+ expected,
+ );
});
});
describe('isEqualish', () => {
@@ -318,12 +341,18 @@ describe('AlteredSliceTag', () => {
it('considers deeply equal objects as equal', () => {
const inst = wrapper.instance();
expect(inst.isEqualish('', '')).toBe(true);
- expect(inst.isEqualish({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).toBe(true);
+ expect(inst.isEqualish({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).toBe(
+ true,
+ );
// Out of order
- expect(inst.isEqualish({ a: 1, b: 2, c: 3 }, { b: 2, a: 1, c: 3 })).toBe(true);
+ expect(inst.isEqualish({ a: 1, b: 2, c: 3 }, { b: 2, a: 1, c: 3 })).toBe(
+ true,
+ );
// Actually not equal
- expect(inst.isEqualish({ a: 1, b: 2, z: 9 }, { a: 1, b: 2, c: 3 })).toBe(false);
+ expect(inst.isEqualish({ a: 1, b: 2, z: 9 }, { a: 1, b: 2, c: 3 })).toBe(
+ false,
+ );
});
});
});
diff --git a/superset/assets/spec/javascripts/components/AsyncSelect_spec.jsx b/superset/assets/spec/javascripts/components/AsyncSelect_spec.jsx
index 6918e1b94cc..cb0281526c0 100644
--- a/superset/assets/spec/javascripts/components/AsyncSelect_spec.jsx
+++ b/superset/assets/spec/javascripts/components/AsyncSelect_spec.jsx
@@ -44,15 +44,11 @@ describe('AsyncSelect', () => {
};
it('is valid element', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('has one select', () => {
- const wrapper = shallow(
- ,
- );
+ const wrapper = shallow( );
expect(wrapper.find(Select)).toHaveLength(1);
});
@@ -67,13 +63,11 @@ describe('AsyncSelect', () => {
});
describe('auto select', () => {
- it('should not call onChange if autoSelect=false', (done) => {
+ it('should not call onChange if autoSelect=false', done => {
expect.assertions(2);
const onChangeSpy = jest.fn();
- shallow(
- ,
- );
+ shallow( );
setTimeout(() => {
expect(fetchMock.calls(dataGlob)).toHaveLength(1);
@@ -82,7 +76,7 @@ describe('AsyncSelect', () => {
});
});
- it('should auto select the first option if autoSelect=true', (done) => {
+ it('should auto select the first option if autoSelect=true', done => {
expect.assertions(3);
const onChangeSpy = jest.fn();
@@ -98,12 +92,17 @@ describe('AsyncSelect', () => {
});
});
- it('should not auto select when value prop is set and autoSelect=true', (done) => {
+ it('should not auto select when value prop is set and autoSelect=true', done => {
expect.assertions(3);
const onChangeSpy = jest.fn();
const wrapper = shallow(
- ,
+ ,
);
setTimeout(() => {
@@ -114,7 +113,7 @@ describe('AsyncSelect', () => {
});
});
- it('should call onAsyncError if there is an error fetching options', (done) => {
+ it('should call onAsyncError if there is an error fetching options', done => {
expect.assertions(3);
const errorEndpoint = 'async/error/';
@@ -123,7 +122,11 @@ describe('AsyncSelect', () => {
const onAsyncError = jest.fn();
shallow(
- ,
+ ,
);
setTimeout(() => {
diff --git a/superset/assets/spec/javascripts/components/CachedLabel_spec.jsx b/superset/assets/spec/javascripts/components/CachedLabel_spec.jsx
index 235d55e8336..1e9cbb0caaa 100644
--- a/superset/assets/spec/javascripts/components/CachedLabel_spec.jsx
+++ b/superset/assets/spec/javascripts/components/CachedLabel_spec.jsx
@@ -29,14 +29,10 @@ describe('CachedLabel', () => {
};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders', () => {
- const wrapper = shallow(
- ,
- );
+ const wrapper = shallow( );
expect(wrapper.find(Label)).toHaveLength(1);
});
});
diff --git a/superset/assets/spec/javascripts/components/Checkbox_spec.jsx b/superset/assets/spec/javascripts/components/Checkbox_spec.jsx
index 72edb7c5f54..6a8573eca6c 100644
--- a/superset/assets/spec/javascripts/components/Checkbox_spec.jsx
+++ b/superset/assets/spec/javascripts/components/Checkbox_spec.jsx
@@ -29,7 +29,7 @@ describe('Checkbox', () => {
};
let wrapper;
- const factory = (o) => {
+ const factory = o => {
const props = Object.assign({}, defaultProps, o);
return shallow( );
};
@@ -49,7 +49,10 @@ describe('Checkbox', () => {
});
it('unchecks when clicked', () => {
expect(wrapper.find('i.fa-check.text-transparent')).toHaveLength(0);
- wrapper.find('i').first().simulate('click');
+ wrapper
+ .find('i')
+ .first()
+ .simulate('click');
expect(defaultProps.onChange.calledOnce).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/components/ColumnOption_spec.jsx b/superset/assets/spec/javascripts/components/ColumnOption_spec.jsx
index 584304921b8..26650da62cb 100644
--- a/superset/assets/spec/javascripts/components/ColumnOption_spec.jsx
+++ b/superset/assets/spec/javascripts/components/ColumnOption_spec.jsx
@@ -60,17 +60,24 @@ describe('ColumnOption', () => {
it('shows a label with column_name when no verbose_name', () => {
props.column.verbose_name = null;
wrapper = shallow(factory(props));
- expect(wrapper.find('.option-label').first().text()).toBe('foo');
+ expect(
+ wrapper
+ .find('.option-label')
+ .first()
+ .text(),
+ ).toBe('foo');
});
it('shows a column type label when showType is true', () => {
- wrapper = shallow(factory({
- ...props,
- showType: true,
- column: {
- expression: null,
- type: 'str',
- },
- }));
+ wrapper = shallow(
+ factory({
+ ...props,
+ showType: true,
+ column: {
+ expression: null,
+ type: 'str',
+ },
+ }),
+ );
expect(wrapper.find(ColumnTypeLabel)).toHaveLength(1);
});
it('column with expression has correct column label if showType is true', () => {
@@ -80,14 +87,16 @@ describe('ColumnOption', () => {
expect(wrapper.find(ColumnTypeLabel).props().type).toBe('expression');
});
it('shows no column type label when type is null', () => {
- wrapper = shallow(factory({
- ...props,
- showType: true,
- column: {
- expression: null,
- type: null,
- },
- }));
+ wrapper = shallow(
+ factory({
+ ...props,
+ showType: true,
+ column: {
+ expression: null,
+ type: null,
+ },
+ }),
+ );
expect(wrapper.find(ColumnTypeLabel)).toHaveLength(0);
});
it('dttm column has correct column label if showType is true', () => {
diff --git a/superset/assets/spec/javascripts/components/ColumnTypeLabel_spec.jsx b/superset/assets/spec/javascripts/components/ColumnTypeLabel_spec.jsx
index ea199e3bed7..8c5f9ea4933 100644
--- a/superset/assets/spec/javascripts/components/ColumnTypeLabel_spec.jsx
+++ b/superset/assets/spec/javascripts/components/ColumnTypeLabel_spec.jsx
@@ -34,7 +34,9 @@ describe('ColumnOption', () => {
}
it('is a valid element', () => {
- expect(React.isValidElement( )).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('string type shows ABC icon', () => {
const lbl = getWrapper({}).find('.type-label');
diff --git a/superset/assets/spec/javascripts/components/CopyToClipboard_spec.jsx b/superset/assets/spec/javascripts/components/CopyToClipboard_spec.jsx
index 90f48ce9e6d..4b81ac9f754 100644
--- a/superset/assets/spec/javascripts/components/CopyToClipboard_spec.jsx
+++ b/superset/assets/spec/javascripts/components/CopyToClipboard_spec.jsx
@@ -26,8 +26,8 @@ describe('CopyToClipboard', () => {
};
it('renders', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
});
diff --git a/superset/assets/spec/javascripts/components/FilterableTable/FilterableTable_spec.jsx b/superset/assets/spec/javascripts/components/FilterableTable/FilterableTable_spec.jsx
index d792f479734..32bd4314307 100644
--- a/superset/assets/spec/javascripts/components/FilterableTable/FilterableTable_spec.jsx
+++ b/superset/assets/spec/javascripts/components/FilterableTable/FilterableTable_spec.jsx
@@ -18,7 +18,9 @@
*/
import React from 'react';
import { mount } from 'enzyme';
-import FilterableTable, { MAX_COLUMNS_FOR_TABLE } from '../../../../src/components/FilterableTable/FilterableTable';
+import FilterableTable, {
+ MAX_COLUMNS_FOR_TABLE,
+} from '../../../../src/components/FilterableTable/FilterableTable';
describe('FilterableTable', () => {
const mockedProps = {
@@ -35,7 +37,9 @@ describe('FilterableTable', () => {
wrapper = mount( );
});
it('is valid element', () => {
- expect(React.isValidElement( )).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('renders a grid with 2 Table rows', () => {
expect(wrapper.find('.ReactVirtualized__Grid')).toHaveLength(1);
@@ -44,13 +48,22 @@ describe('FilterableTable', () => {
it('renders a grid with 2 Grid rows for wide tables', () => {
const wideTableColumns = MAX_COLUMNS_FOR_TABLE + 1;
const wideTableMockedProps = {
- orderedColumnKeys: Array.from(Array(wideTableColumns), (_, x) => `col_${x}`),
+ orderedColumnKeys: Array.from(
+ Array(wideTableColumns),
+ (_, x) => `col_${x}`,
+ ),
data: [
- Object.assign(...Array.from(Array(wideTableColumns)).map((val, x) => ({ [`col_${x}`]: x }))),
+ Object.assign(
+ ...Array.from(Array(wideTableColumns)).map((val, x) => ({
+ [`col_${x}`]: x,
+ })),
+ ),
],
height: 500,
};
- const wideTableWrapper = mount( );
+ const wideTableWrapper = mount(
+ ,
+ );
expect(wideTableWrapper.find('.ReactVirtualized__Grid')).toHaveLength(2);
});
it('filters on a string', () => {
diff --git a/superset/assets/spec/javascripts/components/FormRow_spec.jsx b/superset/assets/spec/javascripts/components/FormRow_spec.jsx
index 7c54a47b46c..9b2db4ef1d7 100644
--- a/superset/assets/spec/javascripts/components/FormRow_spec.jsx
+++ b/superset/assets/spec/javascripts/components/FormRow_spec.jsx
@@ -55,5 +55,4 @@ describe('FormRow', () => {
expect(wrapper.find(Row)).toHaveLength(1);
expect(wrapper.find(Col)).toHaveLength(2);
});
-
});
diff --git a/superset/assets/spec/javascripts/components/MetricOption_spec.jsx b/superset/assets/spec/javascripts/components/MetricOption_spec.jsx
index 8da21d6466f..cd9c0e8de60 100644
--- a/superset/assets/spec/javascripts/components/MetricOption_spec.jsx
+++ b/superset/assets/spec/javascripts/components/MetricOption_spec.jsx
@@ -61,7 +61,12 @@ describe('MetricOption', () => {
it('shows a label with metric_name when no verbose_name', () => {
props.metric.verbose_name = null;
wrapper = shallow(factory(props));
- expect(wrapper.find('.option-label').first().text()).toBe('foo');
+ expect(
+ wrapper
+ .find('.option-label')
+ .first()
+ .text(),
+ ).toBe('foo');
});
it('shows only 1 InfoTooltipWithTrigger when no descr and no warning', () => {
props.metric.warning_text = null;
diff --git a/superset/assets/spec/javascripts/components/ModalTrigger_spec.jsx b/superset/assets/spec/javascripts/components/ModalTrigger_spec.jsx
index 77af49b7a62..1b3066bf8be 100644
--- a/superset/assets/spec/javascripts/components/ModalTrigger_spec.jsx
+++ b/superset/assets/spec/javascripts/components/ModalTrigger_spec.jsx
@@ -28,8 +28,6 @@ describe('ModalTrigger', () => {
};
it('is a valid element', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/components/OnPasteSelect_spec.jsx b/superset/assets/spec/javascripts/components/OnPasteSelect_spec.jsx
index d7e2635bf5e..c5f5742799c 100644
--- a/superset/assets/spec/javascripts/components/OnPasteSelect_spec.jsx
+++ b/superset/assets/spec/javascripts/components/OnPasteSelect_spec.jsx
@@ -83,8 +83,8 @@ describe('OnPasteSelect', () => {
});
it('calls onChange with pasted new line separated values', () => {
- evt.clipboardData.getData = sinon.spy(() =>
- 'United States\nChina\nRussian Federation\nIndia',
+ evt.clipboardData.getData = sinon.spy(
+ () => 'United States\nChina\nRussian Federation\nIndia',
);
wrapper.instance().onPaste(evt);
expected = [
@@ -99,8 +99,8 @@ describe('OnPasteSelect', () => {
});
it('calls onChange with pasted tab separated values', () => {
- evt.clipboardData.getData = sinon.spy(() =>
- 'Russian Federation\tMexico\tIndia\tCanada',
+ evt.clipboardData.getData = sinon.spy(
+ () => 'Russian Federation\tMexico\tIndia\tCanada',
);
wrapper.instance().onPaste(evt);
expected = [
@@ -115,8 +115,8 @@ describe('OnPasteSelect', () => {
});
it('calls onChange without duplicate values and adds new comma separated values', () => {
- evt.clipboardData.getData = sinon.spy(() =>
- 'China, China, China, China, Mexico, Mexico, Chi na, Mexico, ',
+ evt.clipboardData.getData = sinon.spy(
+ () => 'China, China, China, China, Mexico, Mexico, Chi na, Mexico, ',
);
expected = [
props.options[1],
@@ -132,14 +132,10 @@ describe('OnPasteSelect', () => {
});
it('calls onChange without duplicate values and parses new line separated values', () => {
- evt.clipboardData.getData = sinon.spy(() =>
- 'United States\nCanada\nMexico\nUnited States\nCanada',
+ evt.clipboardData.getData = sinon.spy(
+ () => 'United States\nCanada\nMexico\nUnited States\nCanada',
);
- expected = [
- props.options[0],
- props.options[3],
- props.options[6],
- ];
+ expected = [props.options[0], props.options[3], props.options[6]];
wrapper.instance().onPaste(evt);
expect(props.onChange.calledWith(expected)).toBe(true);
expect(evt.preventDefault.called).toBe(true);
@@ -147,25 +143,25 @@ describe('OnPasteSelect', () => {
});
it('calls onChange without duplicate values and parses tab separated values', () => {
- evt.clipboardData.getData = sinon.spy(() =>
- 'China\tIndia\tChina\tRussian Federation\tJapan\tJapan',
- );
- expected = [
- props.options[1],
- props.options[2],
- props.options[4],
- props.options[5],
- ];
- wrapper.instance().onPaste(evt);
- expect(props.onChange.calledWith(expected)).toBe(true);
- expect(evt.preventDefault.called).toBe(true);
- expect(props.isValidNewOption.callCount).toBe(24);
- });
+ evt.clipboardData.getData = sinon.spy(
+ () => 'China\tIndia\tChina\tRussian Federation\tJapan\tJapan',
+ );
+ expected = [
+ props.options[1],
+ props.options[2],
+ props.options[4],
+ props.options[5],
+ ];
+ wrapper.instance().onPaste(evt);
+ expect(props.onChange.calledWith(expected)).toBe(true);
+ expect(evt.preventDefault.called).toBe(true);
+ expect(props.isValidNewOption.callCount).toBe(24);
+ });
it('calls onChange with currently selected values and new comma separated values', () => {
props.value = ['United States', 'Canada', 'Mexico'];
- evt.clipboardData.getData = sinon.spy(() =>
- 'United States, Canada, Japan, India',
+ evt.clipboardData.getData = sinon.spy(
+ () => 'United States, Canada, Japan, India',
);
wrapper = shallow( );
expected = [
@@ -183,9 +179,7 @@ describe('OnPasteSelect', () => {
it('calls onChange with currently selected values and new "new line" separated values', () => {
props.value = ['China', 'India', 'Japan'];
- evt.clipboardData.getData = sinon.spy(() =>
- 'Mexico\nJapan\nIndia',
- );
+ evt.clipboardData.getData = sinon.spy(() => 'Mexico\nJapan\nIndia');
wrapper = shallow( );
expected = [
props.options[1],
@@ -200,23 +194,23 @@ describe('OnPasteSelect', () => {
});
it('calls onChange with currently selected values and new tab separated values', () => {
- props.value = ['United States', 'Canada', 'Mexico', 'Russian Federation'];
- evt.clipboardData.getData = sinon.spy(() =>
- 'United States\tCanada\tJapan\tIndia',
- );
- wrapper = shallow( );
- expected = [
- props.options[0],
- props.options[3],
- props.options[6],
- props.options[4],
- props.options[5],
- props.options[2],
- ];
- wrapper.instance().onPaste(evt);
- expect(props.onChange.calledWith(expected)).toBe(true);
- expect(evt.preventDefault.called).toBe(true);
- expect(props.isValidNewOption.callCount).toBe(29);
- });
+ props.value = ['United States', 'Canada', 'Mexico', 'Russian Federation'];
+ evt.clipboardData.getData = sinon.spy(
+ () => 'United States\tCanada\tJapan\tIndia',
+ );
+ wrapper = shallow( );
+ expected = [
+ props.options[0],
+ props.options[3],
+ props.options[6],
+ props.options[4],
+ props.options[5],
+ props.options[2],
+ ];
+ wrapper.instance().onPaste(evt);
+ expect(props.onChange.calledWith(expected)).toBe(true);
+ expect(evt.preventDefault.called).toBe(true);
+ expect(props.isValidNewOption.callCount).toBe(29);
+ });
});
});
diff --git a/superset/assets/spec/javascripts/components/PopoverSection_spec.jsx b/superset/assets/spec/javascripts/components/PopoverSection_spec.jsx
index 4c731e0af62..28fda4ded79 100644
--- a/superset/assets/spec/javascripts/components/PopoverSection_spec.jsx
+++ b/superset/assets/spec/javascripts/components/PopoverSection_spec.jsx
@@ -31,7 +31,7 @@ describe('PopoverSection', () => {
};
let wrapper;
- const factory = (overrideProps) => {
+ const factory = overrideProps => {
const props = Object.assign({}, defaultProps, overrideProps || {});
return shallow( );
};
@@ -39,7 +39,9 @@ describe('PopoverSection', () => {
wrapper = factory();
});
it('renders', () => {
- expect(React.isValidElement( )).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('is show an icon when selected', () => {
expect(wrapper.find('.fa-check')).toHaveLength(1);
diff --git a/superset/assets/spec/javascripts/components/TableSelector_spec.jsx b/superset/assets/spec/javascripts/components/TableSelector_spec.jsx
index d1febbf8f88..638afc71e1d 100644
--- a/superset/assets/spec/javascripts/components/TableSelector_spec.jsx
+++ b/superset/assets/spec/javascripts/components/TableSelector_spec.jsx
@@ -81,12 +81,10 @@ describe('TableSelector', () => {
afterAll(fetchMock.reset);
it('should handle empty', () =>
- inst
- .getTableNamesBySubStr('')
- .then((data) => {
- expect(data).toEqual({ options: [] });
- return Promise.resolve();
- }));
+ inst.getTableNamesBySubStr('').then(data => {
+ expect(data).toEqual({ options: [] });
+ return Promise.resolve();
+ }));
it('should handle table name', () => {
fetchMock.get(GET_TABLE_NAMES_GLOB, tables, { overwriteRoutes: true });
@@ -94,28 +92,29 @@ describe('TableSelector', () => {
return wrapper
.instance()
.getTableNamesBySubStr('my table')
- .then((data) => {
+ .then(data => {
expect(fetchMock.calls(GET_TABLE_NAMES_GLOB)).toHaveLength(1);
expect(data).toEqual({
options: [
- {
- value: 'birth_names',
- schema: 'main',
- label: 'birth_names',
- title: 'birth_names',
- },
- {
- value: 'energy_usage',
- schema: 'main',
- label: 'energy_usage',
- title: 'energy_usage',
- },
- {
- value: 'wb_health_population',
- schema: 'main',
- label: 'wb_health_population',
- title: 'wb_health_population',
- }],
+ {
+ value: 'birth_names',
+ schema: 'main',
+ label: 'birth_names',
+ title: 'birth_names',
+ },
+ {
+ value: 'energy_usage',
+ schema: 'main',
+ label: 'energy_usage',
+ title: 'energy_usage',
+ },
+ {
+ value: 'wb_health_population',
+ schema: 'main',
+ label: 'wb_health_population',
+ title: 'wb_health_population',
+ },
+ ],
});
return Promise.resolve();
});
@@ -130,8 +129,9 @@ describe('TableSelector', () => {
.instance()
.getTableNamesBySubStr('slashed/table')
.then(() => {
- expect(fetchMock.lastUrl(GET_TABLE_GLOB))
- .toContain('/slashed%252Fschema/slashed%252Ftable');
+ expect(fetchMock.lastUrl(GET_TABLE_GLOB)).toContain(
+ '/slashed%252Fschema/slashed%252Ftable',
+ );
return Promise.resolve();
});
});
@@ -149,37 +149,39 @@ describe('TableSelector', () => {
it('should fetch table options', () => {
fetchMock.get(FETCH_TABLES_GLOB, tables, { overwriteRoutes: true });
- return inst
- .fetchTables(true, 'birth_names')
- .then(() => {
- expect(wrapper.state().tableOptions).toHaveLength(3);
- expect(wrapper.state().tableOptions).toEqual([
- {
- value: 'birth_names',
- schema: 'main',
- label: 'birth_names',
- title: 'birth_names',
- },
- {
- value: 'energy_usage',
- schema: 'main',
- label: 'energy_usage',
- title: 'energy_usage',
- },
- {
- value: 'wb_health_population',
- schema: 'main',
- label: 'wb_health_population',
- title: 'wb_health_population',
- },
- ]);
- return Promise.resolve();
- });
+ return inst.fetchTables(true, 'birth_names').then(() => {
+ expect(wrapper.state().tableOptions).toHaveLength(3);
+ expect(wrapper.state().tableOptions).toEqual([
+ {
+ value: 'birth_names',
+ schema: 'main',
+ label: 'birth_names',
+ title: 'birth_names',
+ },
+ {
+ value: 'energy_usage',
+ schema: 'main',
+ label: 'energy_usage',
+ title: 'energy_usage',
+ },
+ {
+ value: 'wb_health_population',
+ schema: 'main',
+ label: 'wb_health_population',
+ title: 'wb_health_population',
+ },
+ ]);
+ return Promise.resolve();
+ });
});
// Test needs to be fixed: Github issue #7768
xit('should dispatch a danger toast on error', () => {
- fetchMock.get(FETCH_TABLES_GLOB, { throws: 'error' }, { overwriteRoutes: true });
+ fetchMock.get(
+ FETCH_TABLES_GLOB,
+ { throws: 'error' },
+ { overwriteRoutes: true },
+ );
wrapper
.instance()
@@ -202,7 +204,9 @@ describe('TableSelector', () => {
const schemaOptions = {
schemas: ['main', 'erf', 'superset'],
};
- fetchMock.get(FETCH_SCHEMAS_GLOB, schemaOptions, { overwriteRoutes: true });
+ fetchMock.get(FETCH_SCHEMAS_GLOB, schemaOptions, {
+ overwriteRoutes: true,
+ });
return wrapper
.instance()
diff --git a/superset/assets/spec/javascripts/components/URLShortLinkButton_spec.jsx b/superset/assets/spec/javascripts/components/URLShortLinkButton_spec.jsx
index a8321357096..c61e91684a8 100644
--- a/superset/assets/spec/javascripts/components/URLShortLinkButton_spec.jsx
+++ b/superset/assets/spec/javascripts/components/URLShortLinkButton_spec.jsx
@@ -33,7 +33,9 @@ describe('URLShortLinkButton', () => {
function setup() {
const mockStore = configureStore([]);
const store = mockStore({});
- return shallow( , { context: { store } }).dive();
+ return shallow( , {
+ context: { store },
+ }).dive();
}
it('renders OverlayTrigger', () => {
diff --git a/superset/assets/spec/javascripts/components/URLShortLinkModal_spec.jsx b/superset/assets/spec/javascripts/components/URLShortLinkModal_spec.jsx
index 9ad52c2e5e5..a1bc94046f2 100644
--- a/superset/assets/spec/javascripts/components/URLShortLinkModal_spec.jsx
+++ b/superset/assets/spec/javascripts/components/URLShortLinkModal_spec.jsx
@@ -33,7 +33,9 @@ describe('URLShortLinkModal', () => {
function setup() {
const mockStore = configureStore([]);
const store = mockStore({});
- return shallow( , { context: { store } }).dive();
+ return shallow( , {
+ context: { store },
+ }).dive();
}
it('renders ModalTrigger', () => {
diff --git a/superset/assets/spec/javascripts/components/VirtualizedRendererWrap_spec.jsx b/superset/assets/spec/javascripts/components/VirtualizedRendererWrap_spec.jsx
index 351e26938b1..fdb7c4ca9cb 100644
--- a/superset/assets/spec/javascripts/components/VirtualizedRendererWrap_spec.jsx
+++ b/superset/assets/spec/javascripts/components/VirtualizedRendererWrap_spec.jsx
@@ -34,9 +34,7 @@ const defaultProps = {
};
function TestOption({ option }) {
- return (
- {option.label}
- );
+ return {option.label} ;
}
TestOption.propTypes = {
option: PropTypes.object.isRequired,
@@ -75,14 +73,18 @@ describe('VirtualizedRendererWrap', () => {
props.option = props.focusedOption;
wrapper = shallow( );
const optionDiv = wrapper.find('div');
- expect(optionDiv.props().className).toBe('VirtualizedSelectOption VirtualizedSelectFocusedOption');
+ expect(optionDiv.props().className).toBe(
+ 'VirtualizedSelectOption VirtualizedSelectFocusedOption',
+ );
});
it('renders disabled option with the correct class', () => {
props.option.disabled = true;
wrapper = shallow( );
const optionDiv = wrapper.find('div');
- expect(optionDiv.props().className).toBe('VirtualizedSelectOption VirtualizedSelectDisabledOption');
+ expect(optionDiv.props().className).toBe(
+ 'VirtualizedSelectOption VirtualizedSelectDisabledOption',
+ );
props.option.disabled = false;
});
@@ -90,14 +92,18 @@ describe('VirtualizedRendererWrap', () => {
props.valueArray = [props.option, props.focusedOption];
wrapper = shallow( );
const optionDiv = wrapper.find('div');
- expect(optionDiv.props().className).toBe('VirtualizedSelectOption VirtualizedSelectSelectedOption');
+ expect(optionDiv.props().className).toBe(
+ 'VirtualizedSelectOption VirtualizedSelectSelectedOption',
+ );
});
it('renders options with custom classes', () => {
props.option.className = 'CustomClass';
wrapper = shallow( );
const optionDiv = wrapper.find('div');
- expect(optionDiv.props().className).toBe('VirtualizedSelectOption CustomClass');
+ expect(optionDiv.props().className).toBe(
+ 'VirtualizedSelectOption CustomClass',
+ );
});
it('calls focusedOption on its own option onMouseEnter', () => {
diff --git a/superset/assets/spec/javascripts/datasource/ChangeDatasourceModal_spec.jsx b/superset/assets/spec/javascripts/datasource/ChangeDatasourceModal_spec.jsx
index f55ab71b1e7..c1da270b90f 100644
--- a/superset/assets/spec/javascripts/datasource/ChangeDatasourceModal_spec.jsx
+++ b/superset/assets/spec/javascripts/datasource/ChangeDatasourceModal_spec.jsx
@@ -70,7 +70,7 @@ describe('ChangeDatasourceModal', () => {
expect(wrapper.find(Modal)).toHaveLength(1);
});
- it('fetches datasources', (done) => {
+ it('fetches datasources', done => {
inst.onEnterModal();
setTimeout(() => {
expect(fetchMock.calls(DATASOURCES_ENDPOINT)).toHaveLength(1);
@@ -79,12 +79,14 @@ describe('ChangeDatasourceModal', () => {
}, 0);
});
- it('changes the datasource', (done) => {
+ it('changes the datasource', done => {
fetchMock.get(DATASOURCE_ENDPOINT, DATASOURCE_PAYLOAD);
inst.selectDatasource(datasourceData);
setTimeout(() => {
expect(fetchMock.calls(DATASOURCE_ENDPOINT)).toHaveLength(1);
- expect(props.onDatasourceSave.getCall(0).args[0]).toEqual(DATASOURCE_PAYLOAD);
+ expect(props.onDatasourceSave.getCall(0).args[0]).toEqual(
+ DATASOURCE_PAYLOAD,
+ );
fetchMock.reset();
done();
}, 0);
diff --git a/superset/assets/spec/javascripts/datasource/DatasourceEditor_spec.jsx b/superset/assets/spec/javascripts/datasource/DatasourceEditor_spec.jsx
index c23ff43dbe0..898d76872a0 100644
--- a/superset/assets/spec/javascripts/datasource/DatasourceEditor_spec.jsx
+++ b/superset/assets/spec/javascripts/datasource/DatasourceEditor_spec.jsx
@@ -70,7 +70,7 @@ describe('DatasourceEditor', () => {
expect(wrapper.find(Tabs)).toHaveLength(1);
});
- it('makes an async request', (done) => {
+ it('makes an async request', done => {
wrapper.setState({ activeTabKey: 2 });
const syncButton = wrapper.find('.sync-from-source');
expect(syncButton).toHaveLength(1);
@@ -93,6 +93,11 @@ describe('DatasourceEditor', () => {
it('renders isSqla fields', () => {
wrapper.setState({ activeTabKey: 4 });
expect(wrapper.state('isSqla')).toBe(true);
- expect(wrapper.find(Field).find({ fieldKey: 'fetch_values_predicate' }).exists()).toBe(true);
+ expect(
+ wrapper
+ .find(Field)
+ .find({ fieldKey: 'fetch_values_predicate' })
+ .exists(),
+ ).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/datasource/DatasourceModal_spec.jsx b/superset/assets/spec/javascripts/datasource/DatasourceModal_spec.jsx
index 090e82c06e4..720ef980317 100644
--- a/superset/assets/spec/javascripts/datasource/DatasourceModal_spec.jsx
+++ b/superset/assets/spec/javascripts/datasource/DatasourceModal_spec.jsx
@@ -68,7 +68,7 @@ describe('DatasourceModal', () => {
expect(wrapper.find(DatasourceEditor)).toHaveLength(1);
});
- it('saves on confirm', (done) => {
+ it('saves on confirm', done => {
inst.onConfirmSave();
setTimeout(() => {
expect(fetchMock.calls(SAVE_ENDPOINT)).toHaveLength(1);
diff --git a/superset/assets/spec/javascripts/explore/AdhocFilter_spec.js b/superset/assets/spec/javascripts/explore/AdhocFilter_spec.js
index 7f8701bd912..a559bd70990 100644
--- a/superset/assets/spec/javascripts/explore/AdhocFilter_spec.js
+++ b/superset/assets/spec/javascripts/explore/AdhocFilter_spec.js
@@ -16,7 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import AdhocFilter, { EXPRESSION_TYPES, CLAUSES } from '../../../src/explore/AdhocFilter';
+import AdhocFilter, {
+ EXPRESSION_TYPES,
+ CLAUSES,
+} from '../../../src/explore/AdhocFilter';
describe('AdhocFilter', () => {
it('sets filterOptionName in constructor', () => {
@@ -93,7 +96,9 @@ describe('AdhocFilter', () => {
sqlExpression: 'value > 10',
clause: CLAUSES.WHERE,
});
- const adhocFilter4 = adhocFilter3.duplicateWith({ sqlExpression: 'value = 5' });
+ const adhocFilter4 = adhocFilter3.duplicateWith({
+ sqlExpression: 'value = 5',
+ });
// eslint-disable-next-line no-unused-expressions
expect(adhocFilter3.equals(adhocFilter4)).toBe(false);
diff --git a/superset/assets/spec/javascripts/explore/AdhocMetric_spec.js b/superset/assets/spec/javascripts/explore/AdhocMetric_spec.js
index a03c42a7ac3..a564412e027 100644
--- a/superset/assets/spec/javascripts/explore/AdhocMetric_spec.js
+++ b/superset/assets/spec/javascripts/explore/AdhocMetric_spec.js
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-import AdhocMetric, { EXPRESSION_TYPES } from '../../../src/explore/AdhocMetric';
+import AdhocMetric, {
+ EXPRESSION_TYPES,
+} from '../../../src/explore/AdhocMetric';
import { AGGREGATES } from '../../../src/explore/constants';
const valueColumn = { type: 'DOUBLE', column_name: 'value' };
@@ -45,7 +47,9 @@ describe('AdhocMetric', () => {
column: valueColumn,
aggregate: AGGREGATES.SUM,
});
- const adhocMetric2 = adhocMetric1.duplicateWith({ aggregate: AGGREGATES.AVG });
+ const adhocMetric2 = adhocMetric1.duplicateWith({
+ aggregate: AGGREGATES.AVG,
+ });
expect(adhocMetric1.column).toBe(adhocMetric2.column);
expect(adhocMetric1.column).toBe(valueColumn);
@@ -83,7 +87,9 @@ describe('AdhocMetric', () => {
label: 'old label',
hasCustomLabel: true,
});
- const adhocMetric4 = adhocMetric3.duplicateWith({ sqlExpression: 'COUNT(1)' });
+ const adhocMetric4 = adhocMetric3.duplicateWith({
+ sqlExpression: 'COUNT(1)',
+ });
// eslint-disable-next-line no-unused-expressions
expect(adhocMetric3.equals(adhocMetric4)).toBe(false);
@@ -94,7 +100,9 @@ describe('AdhocMetric', () => {
column: valueColumn,
aggregate: AGGREGATES.SUM,
});
- const adhocMetric2 = adhocMetric1.duplicateWith({ aggregate: AGGREGATES.AVG });
+ const adhocMetric2 = adhocMetric1.duplicateWith({
+ aggregate: AGGREGATES.AVG,
+ });
expect(adhocMetric2.label).toBe('AVG(value)');
});
@@ -106,7 +114,9 @@ describe('AdhocMetric', () => {
hasCustomLabel: true,
label: 'label1',
});
- const adhocMetric2 = adhocMetric1.duplicateWith({ aggregate: AGGREGATES.AVG });
+ const adhocMetric2 = adhocMetric1.duplicateWith({
+ aggregate: AGGREGATES.AVG,
+ });
expect(adhocMetric2.label).toBe('label1');
});
@@ -160,51 +170,45 @@ describe('AdhocMetric', () => {
expect(adhocMetric5.isValid()).toBe(false);
});
- it(
- 'can translate back from sql expressions to simple expressions when possible',
- () => {
- const adhocMetric = new AdhocMetric({
- expressionType: EXPRESSION_TYPES.SQL,
- sqlExpression: 'AVG(my_column)',
- hasCustomLabel: true,
- label: 'label1',
- });
- expect(adhocMetric.inferSqlExpressionColumn()).toBe('my_column');
- expect(adhocMetric.inferSqlExpressionAggregate()).toBe('AVG');
+ it('can translate back from sql expressions to simple expressions when possible', () => {
+ const adhocMetric = new AdhocMetric({
+ expressionType: EXPRESSION_TYPES.SQL,
+ sqlExpression: 'AVG(my_column)',
+ hasCustomLabel: true,
+ label: 'label1',
+ });
+ expect(adhocMetric.inferSqlExpressionColumn()).toBe('my_column');
+ expect(adhocMetric.inferSqlExpressionAggregate()).toBe('AVG');
- const adhocMetric2 = new AdhocMetric({
- expressionType: EXPRESSION_TYPES.SQL,
- sqlExpression: 'AVG(SUM(my_column)) / MAX(other_column)',
- hasCustomLabel: true,
- label: 'label1',
- });
- expect(adhocMetric2.inferSqlExpressionColumn()).toBeNull();
- expect(adhocMetric2.inferSqlExpressionAggregate()).toBeNull();
- },
- );
+ const adhocMetric2 = new AdhocMetric({
+ expressionType: EXPRESSION_TYPES.SQL,
+ sqlExpression: 'AVG(SUM(my_column)) / MAX(other_column)',
+ hasCustomLabel: true,
+ label: 'label1',
+ });
+ expect(adhocMetric2.inferSqlExpressionColumn()).toBeNull();
+ expect(adhocMetric2.inferSqlExpressionAggregate()).toBeNull();
+ });
- it(
- 'will infer columns and aggregates when converting to a simple expression',
- () => {
- const adhocMetric = new AdhocMetric({
- expressionType: EXPRESSION_TYPES.SQL,
- sqlExpression: 'AVG(my_column)',
- hasCustomLabel: true,
- label: 'label1',
- });
- const adhocMetric2 = adhocMetric.duplicateWith({
- expressionType: EXPRESSION_TYPES.SIMPLE,
- aggregate: AGGREGATES.SUM,
- });
- expect(adhocMetric2.aggregate).toBe(AGGREGATES.SUM);
- expect(adhocMetric2.column.column_name).toBe('my_column');
+ it('will infer columns and aggregates when converting to a simple expression', () => {
+ const adhocMetric = new AdhocMetric({
+ expressionType: EXPRESSION_TYPES.SQL,
+ sqlExpression: 'AVG(my_column)',
+ hasCustomLabel: true,
+ label: 'label1',
+ });
+ const adhocMetric2 = adhocMetric.duplicateWith({
+ expressionType: EXPRESSION_TYPES.SIMPLE,
+ aggregate: AGGREGATES.SUM,
+ });
+ expect(adhocMetric2.aggregate).toBe(AGGREGATES.SUM);
+ expect(adhocMetric2.column.column_name).toBe('my_column');
- const adhocMetric3 = adhocMetric.duplicateWith({
- expressionType: EXPRESSION_TYPES.SIMPLE,
- column: valueColumn,
- });
- expect(adhocMetric3.aggregate).toBe(AGGREGATES.AVG);
- expect(adhocMetric3.column.column_name).toBe('value');
- },
- );
+ const adhocMetric3 = adhocMetric.duplicateWith({
+ expressionType: EXPRESSION_TYPES.SIMPLE,
+ column: valueColumn,
+ });
+ expect(adhocMetric3.aggregate).toBe(AGGREGATES.AVG);
+ expect(adhocMetric3.column.column_name).toBe('value');
+ });
});
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocFilterControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocFilterControl_spec.jsx
index b879c5b1ba2..25859c3673f 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocFilterControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocFilterControl_spec.jsx
@@ -21,7 +21,10 @@ import React from 'react';
import sinon from 'sinon';
import { shallow } from 'enzyme';
-import AdhocFilter, { EXPRESSION_TYPES, CLAUSES } from '../../../../src/explore/AdhocFilter';
+import AdhocFilter, {
+ EXPRESSION_TYPES,
+ CLAUSES,
+} from '../../../../src/explore/AdhocFilter';
import AdhocFilterControl from '../../../../src/explore/components/controls/AdhocFilterControl';
import AdhocMetric from '../../../../src/explore/AdhocMetric';
import { AGGREGATES, OPERATORS } from '../../../../src/explore/constants';
@@ -82,15 +85,17 @@ describe('AdhocFilterControl', () => {
const adhocFilter = onChange.lastCall.args[0][0];
expect(adhocFilter instanceof AdhocFilter).toBe(true);
- expect(adhocFilter.equals((
- new AdhocFilter({
- expressionType: EXPRESSION_TYPES.SQL,
- subject: savedMetric.expression,
- operator: OPERATORS['>'],
- comparator: 0,
- clause: CLAUSES.HAVING,
- })
- ))).toBe(true);
+ expect(
+ adhocFilter.equals(
+ new AdhocFilter({
+ expressionType: EXPRESSION_TYPES.SQL,
+ subject: savedMetric.expression,
+ operator: OPERATORS['>'],
+ comparator: 0,
+ clause: CLAUSES.HAVING,
+ }),
+ ),
+ ).toBe(true);
});
it('handles adhoc metrics being selected to filter on', () => {
@@ -100,15 +105,17 @@ describe('AdhocFilterControl', () => {
const adhocFilter = onChange.lastCall.args[0][0];
expect(adhocFilter instanceof AdhocFilter).toBe(true);
- expect(adhocFilter.equals((
- new AdhocFilter({
- expressionType: EXPRESSION_TYPES.SQL,
- subject: sumValueAdhocMetric.label,
- operator: OPERATORS['>'],
- comparator: 0,
- clause: CLAUSES.HAVING,
- })
- ))).toBe(true);
+ expect(
+ adhocFilter.equals(
+ new AdhocFilter({
+ expressionType: EXPRESSION_TYPES.SQL,
+ subject: sumValueAdhocMetric.label,
+ operator: OPERATORS['>'],
+ comparator: 0,
+ clause: CLAUSES.HAVING,
+ }),
+ ),
+ ).toBe(true);
});
it('handles columns being selected to filter on', () => {
@@ -118,15 +125,17 @@ describe('AdhocFilterControl', () => {
const adhocFilter = onChange.lastCall.args[0][0];
expect(adhocFilter instanceof AdhocFilter).toBe(true);
- expect(adhocFilter.equals((
- new AdhocFilter({
- expressionType: EXPRESSION_TYPES.SIMPLE,
- subject: columns[0].column_name,
- operator: OPERATORS['=='],
- comparator: '',
- clause: CLAUSES.WHERE,
- })
- ))).toBe(true);
+ expect(
+ adhocFilter.equals(
+ new AdhocFilter({
+ expressionType: EXPRESSION_TYPES.SIMPLE,
+ subject: columns[0].column_name,
+ operator: OPERATORS['=='],
+ comparator: '',
+ clause: CLAUSES.WHERE,
+ }),
+ ),
+ ).toBe(true);
});
it('persists existing filters even when new filters are added', () => {
@@ -140,14 +149,16 @@ describe('AdhocFilterControl', () => {
const newAdhocFilter = onChange.lastCall.args[0][1];
expect(newAdhocFilter instanceof AdhocFilter).toBe(true);
- expect(newAdhocFilter.equals((
- new AdhocFilter({
- expressionType: EXPRESSION_TYPES.SIMPLE,
- subject: columns[0].column_name,
- operator: OPERATORS['=='],
- comparator: '',
- clause: CLAUSES.WHERE,
- })
- ))).toBe(true);
+ expect(
+ newAdhocFilter.equals(
+ new AdhocFilter({
+ expressionType: EXPRESSION_TYPES.SIMPLE,
+ subject: columns[0].column_name,
+ operator: OPERATORS['=='],
+ comparator: '',
+ clause: CLAUSES.WHERE,
+ }),
+ ),
+ ).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopoverSimpleTabContent_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopoverSimpleTabContent_spec.jsx
index 67607c74bc2..d5079cead6f 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopoverSimpleTabContent_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopoverSimpleTabContent_spec.jsx
@@ -22,7 +22,10 @@ import sinon from 'sinon';
import { shallow } from 'enzyme';
import { FormGroup } from 'react-bootstrap';
-import AdhocFilter, { EXPRESSION_TYPES, CLAUSES } from '../../../../src/explore/AdhocFilter';
+import AdhocFilter, {
+ EXPRESSION_TYPES,
+ CLAUSES,
+} from '../../../../src/explore/AdhocFilter';
import AdhocMetric from '../../../../src/explore/AdhocMetric';
import AdhocFilterEditPopoverSimpleTabContent from '../../../../src/explore/components/AdhocFilterEditPopoverSimpleTabContent';
import { AGGREGATES } from '../../../../src/explore/constants';
@@ -68,7 +71,9 @@ function setup(overrides) {
datasource: {},
...overrides,
};
- const wrapper = shallow( );
+ const wrapper = shallow(
+ ,
+ );
return { wrapper, onChange, onHeightChange };
}
@@ -80,23 +85,29 @@ describe('AdhocFilterEditPopoverSimpleTabContent', () => {
it('passes the new adhocFilter to onChange after onSubjectChange', () => {
const { wrapper, onChange } = setup();
- wrapper.instance().onSubjectChange({ type: 'VARCHAR(255)', column_name: 'source' });
+ wrapper
+ .instance()
+ .onSubjectChange({ type: 'VARCHAR(255)', column_name: 'source' });
expect(onChange.calledOnce).toBe(true);
- expect(onChange.lastCall.args[0].equals((
- simpleAdhocFilter.duplicateWith({ subject: 'source' })
- ))).toBe(true);
+ expect(
+ onChange.lastCall.args[0].equals(
+ simpleAdhocFilter.duplicateWith({ subject: 'source' }),
+ ),
+ ).toBe(true);
});
it('may alter the clause in onSubjectChange if the old clause is not appropriate', () => {
const { wrapper, onChange } = setup();
wrapper.instance().onSubjectChange(sumValueAdhocMetric);
expect(onChange.calledOnce).toBe(true);
- expect(onChange.lastCall.args[0].equals((
- simpleAdhocFilter.duplicateWith({
- subject: sumValueAdhocMetric.label,
- clause: CLAUSES.HAVING,
- })
- ))).toBe(true);
+ expect(
+ onChange.lastCall.args[0].equals(
+ simpleAdhocFilter.duplicateWith({
+ subject: sumValueAdhocMetric.label,
+ clause: CLAUSES.HAVING,
+ }),
+ ),
+ ).toBe(true);
});
it('will convert from individual comparator to array if the operator changes to multi', () => {
@@ -109,21 +120,27 @@ describe('AdhocFilterEditPopoverSimpleTabContent', () => {
});
it('will convert from array to individual comparators if the operator changes from multi', () => {
- const { wrapper, onChange } = setup({ adhocFilter: simpleMultiAdhocFilter });
+ const { wrapper, onChange } = setup({
+ adhocFilter: simpleMultiAdhocFilter,
+ });
wrapper.instance().onOperatorChange({ operator: '<' });
expect(onChange.calledOnce).toBe(true);
- expect(onChange.lastCall.args[0].equals((
- simpleAdhocFilter.duplicateWith({ operator: '<', comparator: '10' })
- ))).toBe(true);
+ expect(
+ onChange.lastCall.args[0].equals(
+ simpleAdhocFilter.duplicateWith({ operator: '<', comparator: '10' }),
+ ),
+ ).toBe(true);
});
it('passes the new adhocFilter to onChange after onComparatorChange', () => {
const { wrapper, onChange } = setup();
wrapper.instance().onComparatorChange('20');
expect(onChange.calledOnce).toBe(true);
- expect(onChange.lastCall.args[0].equals((
- simpleAdhocFilter.duplicateWith({ comparator: '20' })
- ))).toBe(true);
+ expect(
+ onChange.lastCall.args[0].equals(
+ simpleAdhocFilter.duplicateWith({ comparator: '20' }),
+ ),
+ ).toBe(true);
});
it('will filter operators for table datasources', () => {
@@ -141,8 +158,9 @@ describe('AdhocFilterEditPopoverSimpleTabContent', () => {
it('expands when its multi comparator input field expands', () => {
const { wrapper, onHeightChange } = setup();
- wrapper.instance().multiComparatorComponent =
- { _selectRef: { select: { control: { clientHeight: 57 } } } };
+ wrapper.instance().multiComparatorComponent = {
+ _selectRef: { select: { control: { clientHeight: 57 } } },
+ };
wrapper.instance().handleMultiComparatorInputHeightChange();
expect(onHeightChange.calledOnce).toBe(true);
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopoverSqlTabContent_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopoverSqlTabContent_spec.jsx
index 4bc739e95ad..eef902778db 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopoverSqlTabContent_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopoverSqlTabContent_spec.jsx
@@ -22,7 +22,10 @@ import sinon from 'sinon';
import { shallow } from 'enzyme';
import { FormGroup } from 'react-bootstrap';
-import AdhocFilter, { EXPRESSION_TYPES, CLAUSES } from '../../../../src/explore/AdhocFilter';
+import AdhocFilter, {
+ EXPRESSION_TYPES,
+ CLAUSES,
+} from '../../../../src/explore/AdhocFilter';
import AdhocFilterEditPopoverSqlTabContent from '../../../../src/explore/components/AdhocFilterEditPopoverSqlTabContent';
const sqlAdhocFilter = new AdhocFilter({
@@ -54,17 +57,21 @@ describe('AdhocFilterEditPopoverSqlTabContent', () => {
const { wrapper, onChange } = setup();
wrapper.instance().onSqlExpressionClauseChange(CLAUSES.HAVING);
expect(onChange.calledOnce).toBe(true);
- expect(onChange.lastCall.args[0].equals((
- sqlAdhocFilter.duplicateWith({ clause: CLAUSES.HAVING })
- ))).toBe(true);
+ expect(
+ onChange.lastCall.args[0].equals(
+ sqlAdhocFilter.duplicateWith({ clause: CLAUSES.HAVING }),
+ ),
+ ).toBe(true);
});
it('passes the new query to onChange after onSqlExpressionChange', () => {
const { wrapper, onChange } = setup();
wrapper.instance().onSqlExpressionChange('value < 5');
expect(onChange.calledOnce).toBe(true);
- expect(onChange.lastCall.args[0].equals((
- sqlAdhocFilter.duplicateWith({ sqlExpression: 'value < 5' })
- ))).toBe(true);
+ expect(
+ onChange.lastCall.args[0].equals(
+ sqlAdhocFilter.duplicateWith({ sqlExpression: 'value < 5' }),
+ ),
+ ).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
index c38d0ed3657..0f917ab3fac 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocFilterEditPopover_spec.jsx
@@ -22,7 +22,10 @@ import sinon from 'sinon';
import { shallow } from 'enzyme';
import { Button, Popover, Tab, Tabs } from 'react-bootstrap';
-import AdhocFilter, { EXPRESSION_TYPES, CLAUSES } from '../../../../src/explore/AdhocFilter';
+import AdhocFilter, {
+ EXPRESSION_TYPES,
+ CLAUSES,
+} from '../../../../src/explore/AdhocFilter';
import AdhocMetric from '../../../../src/explore/AdhocMetric';
import AdhocFilterEditPopover from '../../../../src/explore/components/AdhocFilterEditPopover';
import AdhocFilterEditPopoverSimpleTabContent from '../../../../src/explore/components/AdhocFilterEditPopoverSimpleTabContent';
@@ -81,7 +84,9 @@ describe('AdhocFilterEditPopover', () => {
expect(wrapper.find(Tabs)).toHaveLength(1);
expect(wrapper.find(Tab)).toHaveLength(2);
expect(wrapper.find(Button)).toHaveLength(2);
- expect(wrapper.find(AdhocFilterEditPopoverSimpleTabContent)).toHaveLength(1);
+ expect(wrapper.find(AdhocFilterEditPopoverSimpleTabContent)).toHaveLength(
+ 1,
+ );
});
it('renders sql tab content when the adhoc filter expressionType is sql', () => {
@@ -102,7 +107,9 @@ describe('AdhocFilterEditPopover', () => {
it('prevents saving if the filter is invalid', () => {
const { wrapper } = setup();
expect(wrapper.find(Button).find({ disabled: true })).toHaveLength(0);
- wrapper.instance().onAdhocFilterChange(simpleAdhocFilter.duplicateWith({ operator: null }));
+ wrapper
+ .instance()
+ .onAdhocFilterChange(simpleAdhocFilter.duplicateWith({ operator: null }));
expect(wrapper.find(Button).find({ disabled: true })).toHaveLength(1);
wrapper.instance().onAdhocFilterChange(sqlAdhocFilter);
expect(wrapper.find(Button).find({ disabled: true })).toHaveLength(0);
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocFilterOption_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocFilterOption_spec.jsx
index 2a1830a2c4c..c24a3cf0ef9 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocFilterOption_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocFilterOption_spec.jsx
@@ -22,7 +22,10 @@ import sinon from 'sinon';
import { shallow } from 'enzyme';
import { Label, OverlayTrigger } from 'react-bootstrap';
-import AdhocFilter, { EXPRESSION_TYPES, CLAUSES } from '../../../../src/explore/AdhocFilter';
+import AdhocFilter, {
+ EXPRESSION_TYPES,
+ CLAUSES,
+} from '../../../../src/explore/AdhocFilter';
import AdhocFilterOption from '../../../../src/explore/components/AdhocFilterOption';
const simpleAdhocFilter = new AdhocFilter({
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocMetricEditPopoverTitle_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocMetricEditPopoverTitle_spec.jsx
index 0300f7fb1a8..15416a11430 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocMetricEditPopoverTitle_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocMetricEditPopoverTitle_spec.jsx
@@ -52,7 +52,12 @@ describe('AdhocMetricEditPopoverTitle', () => {
it('renders an OverlayTrigger wrapper with the title', () => {
const { wrapper } = setup();
expect(wrapper.find(OverlayTrigger)).toHaveLength(1);
- expect(wrapper.find(OverlayTrigger).find('span').text()).toBe('My Metric\xa0');
+ expect(
+ wrapper
+ .find(OverlayTrigger)
+ .find('span')
+ .text(),
+ ).toBe('My Metric\xa0');
});
it('transfers to edit mode when clicked', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocMetricEditPopover_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocMetricEditPopover_spec.jsx
index a6106dbb9bf..36733749539 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocMetricEditPopover_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocMetricEditPopover_spec.jsx
@@ -22,7 +22,9 @@ import sinon from 'sinon';
import { shallow } from 'enzyme';
import { Button, FormGroup, Popover } from 'react-bootstrap';
-import AdhocMetric, { EXPRESSION_TYPES } from '../../../../src/explore/AdhocMetric';
+import AdhocMetric, {
+ EXPRESSION_TYPES,
+} from '../../../../src/explore/AdhocMetric';
import AdhocMetricEditPopover from '../../../../src/explore/components/AdhocMetricEditPopover';
import { AGGREGATES } from '../../../../src/explore/constants';
@@ -68,19 +70,25 @@ describe('AdhocMetricEditPopover', () => {
it('overwrites the adhocMetric in state with onColumnChange', () => {
const { wrapper } = setup();
wrapper.instance().onColumnChange(columns[0]);
- expect(wrapper.state('adhocMetric')).toEqual(sumValueAdhocMetric.duplicateWith({ column: columns[0] }));
+ expect(wrapper.state('adhocMetric')).toEqual(
+ sumValueAdhocMetric.duplicateWith({ column: columns[0] }),
+ );
});
it('overwrites the adhocMetric in state with onAggregateChange', () => {
const { wrapper } = setup();
wrapper.instance().onAggregateChange({ aggregate: AGGREGATES.AVG });
- expect(wrapper.state('adhocMetric')).toEqual(sumValueAdhocMetric.duplicateWith({ aggregate: AGGREGATES.AVG }));
+ expect(wrapper.state('adhocMetric')).toEqual(
+ sumValueAdhocMetric.duplicateWith({ aggregate: AGGREGATES.AVG }),
+ );
});
it('overwrites the adhocMetric in state with onSqlExpressionChange', () => {
const { wrapper } = setup({ adhocMetric: sqlExpressionAdhocMetric });
wrapper.instance().onSqlExpressionChange('COUNT(1)');
- expect(wrapper.state('adhocMetric')).toEqual(sqlExpressionAdhocMetric.duplicateWith({ sqlExpression: 'COUNT(1)' }));
+ expect(wrapper.state('adhocMetric')).toEqual(
+ sqlExpressionAdhocMetric.duplicateWith({ sqlExpression: 'COUNT(1)' }),
+ );
});
it('overwrites the adhocMetric in state with onLabelChange', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/AdhocMetricStaticOption_spec.jsx b/superset/assets/spec/javascripts/explore/components/AdhocMetricStaticOption_spec.jsx
index 96e6fabcff5..248468a6ba4 100644
--- a/superset/assets/spec/javascripts/explore/components/AdhocMetricStaticOption_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AdhocMetricStaticOption_spec.jsx
@@ -21,7 +21,9 @@ import React from 'react';
import { shallow } from 'enzyme';
import AdhocMetricStaticOption from '../../../../src/explore/components/AdhocMetricStaticOption';
-import AdhocMetric, { EXPRESSION_TYPES } from '../../../../src/explore/AdhocMetric';
+import AdhocMetric, {
+ EXPRESSION_TYPES,
+} from '../../../../src/explore/AdhocMetric';
import { AGGREGATES } from '../../../../src/explore/constants';
const sumValueAdhocMetric = new AdhocMetric({
@@ -32,7 +34,9 @@ const sumValueAdhocMetric = new AdhocMetric({
describe('AdhocMetricStaticOption', () => {
it('renders the adhoc metrics label', () => {
- const wrapper = shallow( );
+ const wrapper = shallow(
+ ,
+ );
expect(wrapper.text()).toBe('SUM(source)');
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/AggregateOption_spec.jsx b/superset/assets/spec/javascripts/explore/components/AggregateOption_spec.jsx
index 5300164370f..61a1912b716 100644
--- a/superset/assets/spec/javascripts/explore/components/AggregateOption_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/AggregateOption_spec.jsx
@@ -24,7 +24,9 @@ import AggregateOption from '../../../../src/explore/components/AggregateOption'
describe('AggregateOption', () => {
it('renders the aggregate', () => {
- const wrapper = shallow( );
+ const wrapper = shallow(
+ ,
+ );
expect(wrapper.text()).toBe('SUM');
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/BoundsControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/BoundsControl_spec.jsx
index 5497d80826d..cc05a7f3488 100644
--- a/superset/assets/spec/javascripts/explore/components/BoundsControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/BoundsControl_spec.jsx
@@ -42,13 +42,24 @@ describe('BoundsControl', () => {
});
it('errors on non-numeric', () => {
- wrapper.find(FormControl).first().simulate('change', { target: { value: 's' } });
+ wrapper
+ .find(FormControl)
+ .first()
+ .simulate('change', { target: { value: 's' } });
expect(defaultProps.onChange.calledWith([null, null])).toBe(true);
- expect(defaultProps.onChange.getCall(0).args[1][0]).toContain('value should be numeric');
+ expect(defaultProps.onChange.getCall(0).args[1][0]).toContain(
+ 'value should be numeric',
+ );
});
it('casts to numeric', () => {
- wrapper.find(FormControl).first().simulate('change', { target: { value: '1' } });
- wrapper.find(FormControl).last().simulate('change', { target: { value: '5' } });
+ wrapper
+ .find(FormControl)
+ .first()
+ .simulate('change', { target: { value: '1' } });
+ wrapper
+ .find(FormControl)
+ .last()
+ .simulate('change', { target: { value: '5' } });
expect(defaultProps.onChange.calledWith([1, 5])).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/CheckboxControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/CheckboxControl_spec.jsx
index 9e946194818..aafcc979231 100644
--- a/superset/assets/spec/javascripts/explore/components/CheckboxControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/CheckboxControl_spec.jsx
@@ -54,7 +54,10 @@ describe('CheckboxControl', () => {
fullComponent.instance().forceUpdate();
- fullComponent.find('label span').last().simulate('click');
+ fullComponent
+ .find('label span')
+ .last()
+ .simulate('click');
expect(spy.calledOnce).toBe(true);
});
diff --git a/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx
index c372e314a82..c01975eb804 100644
--- a/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ColorPickerControl_spec.jsx
@@ -21,14 +21,16 @@ import React from 'react';
import { shallow } from 'enzyme';
import { OverlayTrigger } from 'react-bootstrap';
import { SketchPicker } from 'react-color';
-import { CategoricalScheme, getCategoricalSchemeRegistry } from '@superset-ui/color';
+import {
+ CategoricalScheme,
+ getCategoricalSchemeRegistry,
+} from '@superset-ui/color';
-import ColorPickerControl from
- '../../../../src/explore/components/controls/ColorPickerControl';
+import ColorPickerControl from '../../../../src/explore/components/controls/ColorPickerControl';
import ControlHeader from '../../../../src/explore/components/ControlHeader';
const defaultProps = {
- value: { },
+ value: {},
};
describe('ColorPickerControl', () => {
@@ -36,10 +38,13 @@ describe('ColorPickerControl', () => {
let inst;
beforeEach(() => {
getCategoricalSchemeRegistry()
- .registerValue('test', new CategoricalScheme({
- id: 'test',
- colors: ['red', 'green', 'blue'],
- }))
+ .registerValue(
+ 'test',
+ new CategoricalScheme({
+ id: 'test',
+ colors: ['red', 'green', 'blue'],
+ }),
+ )
.setDefaultKey('test');
wrapper = shallow( );
inst = wrapper.instance();
diff --git a/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx b/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx
index c2b6a96604d..a1187a7e226 100644
--- a/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ColorScheme_spec.jsx
@@ -22,11 +22,12 @@ import { mount } from 'enzyme';
import { Creatable } from 'react-select';
import { getCategoricalSchemeRegistry } from '@superset-ui/color';
-import ColorSchemeControl from
- '../../../../src/explore/components/controls/ColorSchemeControl';
+import ColorSchemeControl from '../../../../src/explore/components/controls/ColorSchemeControl';
const defaultProps = {
- options: getCategoricalSchemeRegistry().keys().map(s => ([s, s])),
+ options: getCategoricalSchemeRegistry()
+ .keys()
+ .map(s => [s, s]),
};
describe('ColorSchemeControl', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/ControlPanelSection_spec.jsx b/superset/assets/spec/javascripts/explore/components/ControlPanelSection_spec.jsx
index c662d274cce..7e4f7478e9f 100644
--- a/superset/assets/spec/javascripts/explore/components/ControlPanelSection_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ControlPanelSection_spec.jsx
@@ -20,11 +20,9 @@ import React from 'react';
import { shallow } from 'enzyme';
import { Panel } from 'react-bootstrap';
-import InfoTooltipWithTrigger from
- '../../../../src/components/InfoTooltipWithTrigger';
+import InfoTooltipWithTrigger from '../../../../src/components/InfoTooltipWithTrigger';
-import ControlPanelSection from
- '../../../../src/explore/components/ControlPanelSection';
+import ControlPanelSection from '../../../../src/explore/components/ControlPanelSection';
const defaultProps = {
children: a child element
,
@@ -57,11 +55,21 @@ describe('ControlPanelSection', () => {
});
it('renders a label if present', () => {
- expect(wrapper.find(Panel).dive().text()).toContain('my label');
+ expect(
+ wrapper
+ .find(Panel)
+ .dive()
+ .text(),
+ ).toContain('my label');
});
it('renders a InfoTooltipWithTrigger if label and tooltip is present', () => {
- expect(wrapper.find(Panel).dive().find(InfoTooltipWithTrigger)).toHaveLength(1);
+ expect(
+ wrapper
+ .find(Panel)
+ .dive()
+ .find(InfoTooltipWithTrigger),
+ ).toHaveLength(1);
});
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx b/superset/assets/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
index 50dbe999dfb..4d9e383f880 100644
--- a/superset/assets/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ControlPanelsContainer_spec.jsx
@@ -29,15 +29,18 @@ import * as featureFlags from 'src/featureFlags';
describe('ControlPanelsContainer', () => {
let wrapper;
let scopedFilterOn = false;
- const isFeatureEnabledMock = jest.spyOn(featureFlags, 'isFeatureEnabled')
- .mockImplementation(() => scopedFilterOn);
+ const isFeatureEnabledMock = jest
+ .spyOn(featureFlags, 'isFeatureEnabled')
+ .mockImplementation(() => scopedFilterOn);
beforeAll(() => {
getChartControlPanelRegistry().registerValue('table', {
controlPanelSections: [
{
label: t('GROUP BY'),
- description: t('Use this section if you want a query that aggregates'),
+ description: t(
+ 'Use this section if you want a query that aggregates',
+ ),
expanded: true,
controlSetRows: [
['groupby'],
@@ -60,9 +63,7 @@ describe('ControlPanelsContainer', () => {
{
label: t('Query'),
expanded: true,
- controlSetRows: [
- ['adhoc_filters'],
- ],
+ controlSetRows: [['adhoc_filters']],
},
{
label: t('Options'),
diff --git a/superset/assets/spec/javascripts/explore/components/DatasourceControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/DatasourceControl_spec.jsx
index 47643a11af3..c40f4a150cd 100644
--- a/superset/assets/spec/javascripts/explore/components/DatasourceControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/DatasourceControl_spec.jsx
@@ -47,7 +47,9 @@ describe('DatasourceControl', () => {
function setup() {
const mockStore = configureStore([]);
const store = mockStore({});
- return shallow( , { context: { store } });
+ return shallow( , {
+ context: { store },
+ });
}
it('renders a Modal', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/DateFilterControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/DateFilterControl_spec.jsx
index 0eef849cc46..09c7d7f7958 100644
--- a/superset/assets/spec/javascripts/explore/components/DateFilterControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/DateFilterControl_spec.jsx
@@ -70,7 +70,9 @@ describe('DateFilterControl', () => {
label.simulate('click');
setTimeout(() => {
expect(wrapper.find('.popover')).toHaveLength(1);
- expect(wrapper.find('.ok')).first().simulate('click');
+ expect(wrapper.find('.ok'))
+ .first()
+ .simulate('click');
setTimeout(() => {
expect(wrapper.find('.popover')).toHaveLength(0);
}, 10);
diff --git a/superset/assets/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx b/superset/assets/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx
index a7aec9caf7f..f2403541fab 100644
--- a/superset/assets/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx
@@ -37,7 +37,9 @@ describe('DisplayQueryButton', () => {
};
it('is valid', () => {
- expect(React.isValidElement( )).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('renders a dropdown', () => {
const wrapper = mount( );
diff --git a/superset/assets/spec/javascripts/explore/components/EmbedCodeButton_spec.jsx b/superset/assets/spec/javascripts/explore/components/EmbedCodeButton_spec.jsx
index bf4f1998972..e2353638f78 100644
--- a/superset/assets/spec/javascripts/explore/components/EmbedCodeButton_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/EmbedCodeButton_spec.jsx
@@ -30,7 +30,9 @@ describe('EmbedCodeButton', () => {
};
it('renders', () => {
- expect(React.isValidElement( )).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('renders overlay trigger', () => {
@@ -39,13 +41,15 @@ describe('EmbedCodeButton', () => {
});
it('returns correct embed code', () => {
- const stub = sinon.stub(exploreUtils, 'getExploreLongUrl').callsFake(() => ('endpoint_url'));
+ const stub = sinon
+ .stub(exploreUtils, 'getExploreLongUrl')
+ .callsFake(() => 'endpoint_url');
const wrapper = mount( );
wrapper.setState({
height: '1000',
width: '2000',
});
- const embedHTML = (
+ const embedHTML =
''
- );
+ '';
expect(wrapper.instance().generateEmbedHTML()).toBe(embedHTML);
stub.restore();
});
diff --git a/superset/assets/spec/javascripts/explore/components/ExploreActionButtons_spec.jsx b/superset/assets/spec/javascripts/explore/components/ExploreActionButtons_spec.jsx
index 2f9297fef45..bc665058c11 100644
--- a/superset/assets/spec/javascripts/explore/components/ExploreActionButtons_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ExploreActionButtons_spec.jsx
@@ -18,8 +18,7 @@
*/
import React from 'react';
import { shallow } from 'enzyme';
-import ExploreActionButtons from
- '../../../../src/explore/components/ExploreActionButtons';
+import ExploreActionButtons from '../../../../src/explore/components/ExploreActionButtons';
describe('ExploreActionButtons', () => {
const defaultProps = {
diff --git a/superset/assets/spec/javascripts/explore/components/ExploreChartHeader_spec.jsx b/superset/assets/spec/javascripts/explore/components/ExploreChartHeader_spec.jsx
index 583d7b9b023..ddc107ab5ec 100644
--- a/superset/assets/spec/javascripts/explore/components/ExploreChartHeader_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ExploreChartHeader_spec.jsx
@@ -44,9 +44,9 @@ describe('ExploreChartHeader', () => {
});
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('renders', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/ExploreChartPanel_spec.jsx b/superset/assets/spec/javascripts/explore/components/ExploreChartPanel_spec.jsx
index fa1666895e4..2b1ad85f79d 100644
--- a/superset/assets/spec/javascripts/explore/components/ExploreChartPanel_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ExploreChartPanel_spec.jsx
@@ -28,8 +28,6 @@ describe('ChartContainer', () => {
};
it('renders when vizType is line', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/ExploreViewContainer_spec.jsx b/superset/assets/spec/javascripts/explore/components/ExploreViewContainer_spec.jsx
index bdaa6420f64..5af8aad0acd 100644
--- a/superset/assets/spec/javascripts/explore/components/ExploreViewContainer_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ExploreViewContainer_spec.jsx
@@ -37,8 +37,9 @@ describe('ExploreViewContainer', () => {
let isFeatureEnabledMock;
beforeAll(() => {
- isFeatureEnabledMock = jest.spyOn(featureFlags, 'isFeatureEnabled')
- .mockReturnValue(false);
+ isFeatureEnabledMock = jest
+ .spyOn(featureFlags, 'isFeatureEnabled')
+ .mockReturnValue(false);
const bootstrapData = {
common: {
@@ -63,9 +64,7 @@ describe('ExploreViewContainer', () => {
});
it('renders', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders QueryAndSaveButtons', () => {
@@ -83,8 +82,14 @@ describe('ExploreViewContainer', () => {
describe('componentWillReceiveProps()', () => {
it('when controls change, should call resetControls', () => {
expect(wrapper.instance().props.controls.viz_type.value).toBe('table');
- const resetControls = sinon.stub(wrapper.instance().props.actions, 'resetControls');
- const triggerQuery = sinon.stub(wrapper.instance().props.actions, 'triggerQuery');
+ const resetControls = sinon.stub(
+ wrapper.instance().props.actions,
+ 'resetControls',
+ );
+ const triggerQuery = sinon.stub(
+ wrapper.instance().props.actions,
+ 'triggerQuery',
+ );
// triggers componentWillReceiveProps
wrapper.setProps({
diff --git a/superset/assets/spec/javascripts/explore/components/FilterBoxItemControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/FilterBoxItemControl_spec.jsx
index 4a4e4f8a2ae..77a4e8307bb 100644
--- a/superset/assets/spec/javascripts/explore/components/FilterBoxItemControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/FilterBoxItemControl_spec.jsx
@@ -35,7 +35,7 @@ describe('FilterBoxItemControl', () => {
let wrapper;
let inst;
- const getWrapper = (propOverrides) => {
+ const getWrapper = propOverrides => {
const props = { ...defaultProps, ...propOverrides };
return shallow( );
};
diff --git a/superset/assets/spec/javascripts/explore/components/FilterDefinitionOption_spec.jsx b/superset/assets/spec/javascripts/explore/components/FilterDefinitionOption_spec.jsx
index dd3d13893d0..7ab7f5bf956 100644
--- a/superset/assets/spec/javascripts/explore/components/FilterDefinitionOption_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/FilterDefinitionOption_spec.jsx
@@ -23,7 +23,9 @@ import { shallow } from 'enzyme';
import FilterDefinitionOption from '../../../../src/explore/components/FilterDefinitionOption';
import ColumnOption from '../../../../src/components/ColumnOption';
import AdhocMetricStaticOption from '../../../../src/explore/components/AdhocMetricStaticOption';
-import AdhocMetric, { EXPRESSION_TYPES } from '../../../../src/explore/AdhocMetric';
+import AdhocMetric, {
+ EXPRESSION_TYPES,
+} from '../../../../src/explore/AdhocMetric';
import { AGGREGATES } from '../../../../src/explore/constants';
const sumValueAdhocMetric = new AdhocMetric({
@@ -34,19 +36,25 @@ const sumValueAdhocMetric = new AdhocMetric({
describe('FilterDefinitionOption', () => {
it('renders a ColumnOption given a column', () => {
- const wrapper = shallow( );
+ const wrapper = shallow(
+ ,
+ );
expect(wrapper.find(ColumnOption)).toHaveLength(1);
});
it('renders a AdhocMetricStaticOption given an adhoc metric', () => {
- const wrapper = shallow( );
+ const wrapper = shallow(
+ ,
+ );
expect(wrapper.find(AdhocMetricStaticOption)).toHaveLength(1);
});
it('renders the metric name given a saved metric', () => {
- const wrapper = shallow((
-
- ));
+ const wrapper = shallow(
+ ,
+ );
expect(wrapper.text()).toBe(' my_custom_metric');
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/FixedOrMetricControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/FixedOrMetricControl_spec.jsx
index 0a6fc135e91..1ab42435fdf 100644
--- a/superset/assets/spec/javascripts/explore/components/FixedOrMetricControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/FixedOrMetricControl_spec.jsx
@@ -20,16 +20,13 @@
import React from 'react';
import { shallow } from 'enzyme';
-import FixedOrMetricControl from
- '../../../../src/explore/components/controls/FixedOrMetricControl';
-import TextControl from
- '../../../../src/explore/components/controls/TextControl';
-import MetricsControl from
- '../../../../src/explore/components/controls/MetricsControl';
+import FixedOrMetricControl from '../../../../src/explore/components/controls/FixedOrMetricControl';
+import TextControl from '../../../../src/explore/components/controls/TextControl';
+import MetricsControl from '../../../../src/explore/components/controls/MetricsControl';
const defaultProps = {
- value: { },
- datasource: { },
+ value: {},
+ datasource: {},
};
describe('FixedOrMetricControl', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/MetricDefinitionOption_spec.jsx b/superset/assets/spec/javascripts/explore/components/MetricDefinitionOption_spec.jsx
index 470c969b453..f1b55c8f86a 100644
--- a/superset/assets/spec/javascripts/explore/components/MetricDefinitionOption_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/MetricDefinitionOption_spec.jsx
@@ -30,7 +30,9 @@ describe('MetricDefinitionOption', () => {
const store = mockStore({});
function setup(props) {
- return shallow( , { context: { store } }).dive();
+ return shallow( , {
+ context: { store },
+ }).dive();
}
it('renders a MetricOption given a saved metric', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/MetricDefinitionValue_spec.jsx b/superset/assets/spec/javascripts/explore/components/MetricDefinitionValue_spec.jsx
index f357991a530..2a326be509c 100644
--- a/superset/assets/spec/javascripts/explore/components/MetricDefinitionValue_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/MetricDefinitionValue_spec.jsx
@@ -33,14 +33,19 @@ const sumValueAdhocMetric = new AdhocMetric({
describe('MetricDefinitionValue', () => {
it('renders a MetricOption given a saved metric', () => {
- const wrapper = shallow( );
+ const wrapper = shallow(
+ ,
+ );
expect(wrapper.find(MetricOption)).toHaveLength(1);
});
it('renders an AdhocMetricOption given an adhoc metric', () => {
- const wrapper = shallow((
- {}} option={sumValueAdhocMetric} />
- ));
+ const wrapper = shallow(
+ {}}
+ option={sumValueAdhocMetric}
+ />,
+ );
expect(wrapper.find(AdhocMetricOption)).toHaveLength(1);
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/MetricsControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/MetricsControl_spec.jsx
index b6fbf1bacd3..a27b5240645 100644
--- a/superset/assets/spec/javascripts/explore/components/MetricsControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/MetricsControl_spec.jsx
@@ -24,7 +24,9 @@ import { shallow } from 'enzyme';
import MetricsControl from '../../../../src/explore/components/controls/MetricsControl';
import { AGGREGATES } from '../../../../src/explore/constants';
import OnPasteSelect from '../../../../src/components/OnPasteSelect';
-import AdhocMetric, { EXPRESSION_TYPES } from '../../../../src/explore/AdhocMetric';
+import AdhocMetric, {
+ EXPRESSION_TYPES,
+} from '../../../../src/explore/AdhocMetric';
const defaultProps = {
name: 'metrics',
@@ -63,33 +65,56 @@ const sumValueAdhocMetric = new AdhocMetric({
});
describe('MetricsControl', () => {
-
it('renders an OnPasteSelect', () => {
const { wrapper } = setup();
expect(wrapper.find(OnPasteSelect)).toHaveLength(1);
});
describe('constructor', () => {
-
it('unifies options for the dropdown select with aggregates', () => {
const { wrapper } = setup();
expect(wrapper.state('options')).toEqual([
- { optionName: '_col_source', type: 'VARCHAR(255)', column_name: 'source' },
- { optionName: '_col_target', type: 'VARCHAR(255)', column_name: 'target' },
+ {
+ optionName: '_col_source',
+ type: 'VARCHAR(255)',
+ column_name: 'source',
+ },
+ {
+ optionName: '_col_target',
+ type: 'VARCHAR(255)',
+ column_name: 'target',
+ },
{ optionName: '_col_value', type: 'DOUBLE', column_name: 'value' },
- ...Object.keys(AGGREGATES).map(
- aggregate => ({ aggregate_name: aggregate, optionName: '_aggregate_' + aggregate }),
- ),
- { optionName: 'sum__value', metric_name: 'sum__value', expression: 'SUM(energy_usage.value)' },
- { optionName: 'avg__value', metric_name: 'avg__value', expression: 'AVG(energy_usage.value)' },
+ ...Object.keys(AGGREGATES).map(aggregate => ({
+ aggregate_name: aggregate,
+ optionName: '_aggregate_' + aggregate,
+ })),
+ {
+ optionName: 'sum__value',
+ metric_name: 'sum__value',
+ expression: 'SUM(energy_usage.value)',
+ },
+ {
+ optionName: 'avg__value',
+ metric_name: 'avg__value',
+ expression: 'AVG(energy_usage.value)',
+ },
]);
});
it('does not show aggregates in options if no columns', () => {
const { wrapper } = setup({ columns: [] });
expect(wrapper.state('options')).toEqual([
- { optionName: 'sum__value', metric_name: 'sum__value', expression: 'SUM(energy_usage.value)' },
- { optionName: 'avg__value', metric_name: 'avg__value', expression: 'AVG(energy_usage.value)' },
+ {
+ optionName: 'sum__value',
+ metric_name: 'sum__value',
+ expression: 'SUM(energy_usage.value)',
+ },
+ {
+ optionName: 'avg__value',
+ metric_name: 'avg__value',
+ expression: 'AVG(energy_usage.value)',
+ },
]);
});
@@ -124,11 +149,9 @@ describe('MetricsControl', () => {
'avg__value',
]);
});
-
});
describe('onChange', () => {
-
it('handles saved metrics being selected', () => {
const { wrapper, onChange } = setup();
const select = wrapper.find(OnPasteSelect);
@@ -143,16 +166,20 @@ describe('MetricsControl', () => {
const adhocMetric = onChange.lastCall.args[0][0];
expect(adhocMetric instanceof AdhocMetric).toBe(true);
- expect(onChange.lastCall.args).toEqual([[{
- expressionType: EXPRESSION_TYPES.SIMPLE,
- column: valueColumn,
- aggregate: AGGREGATES.SUM,
- label: 'SUM(value)',
- fromFormData: false,
- hasCustomLabel: false,
- optionName: adhocMetric.optionName,
- sqlExpression: null,
- }]]);
+ expect(onChange.lastCall.args).toEqual([
+ [
+ {
+ expressionType: EXPRESSION_TYPES.SIMPLE,
+ column: valueColumn,
+ aggregate: AGGREGATES.SUM,
+ label: 'SUM(value)',
+ fromFormData: false,
+ hasCustomLabel: false,
+ optionName: adhocMetric.optionName,
+ sqlExpression: null,
+ },
+ ],
+ ]);
});
it('handles aggregates being selected', () => {
@@ -171,15 +198,22 @@ describe('MetricsControl', () => {
select.simulate('change', [{ aggregate_name: 'SUM', optionName: 'SUM' }]);
expect(setInputSpy.calledWith('SUM()')).toBe(true);
- expect(handleInputSpy.calledWith({ target: { value: 'SUM()' } })).toBe(true);
+ expect(handleInputSpy.calledWith({ target: { value: 'SUM()' } })).toBe(
+ true,
+ );
expect(onChange.lastCall.args).toEqual([[]]);
});
it('preserves existing selected AdhocMetrics', () => {
const { wrapper, onChange } = setup();
const select = wrapper.find(OnPasteSelect);
- select.simulate('change', [{ metric_name: 'sum__value' }, sumValueAdhocMetric]);
- expect(onChange.lastCall.args).toEqual([['sum__value', sumValueAdhocMetric]]);
+ select.simulate('change', [
+ { metric_name: 'sum__value' },
+ sumValueAdhocMetric,
+ ]);
+ expect(onChange.lastCall.args).toEqual([
+ ['sum__value', sumValueAdhocMetric],
+ ]);
});
});
@@ -189,12 +223,12 @@ describe('MetricsControl', () => {
value: [sumValueAdhocMetric],
});
- const editedMetric = sumValueAdhocMetric.duplicateWith({ aggregate: AGGREGATES.AVG });
+ const editedMetric = sumValueAdhocMetric.duplicateWith({
+ aggregate: AGGREGATES.AVG,
+ });
wrapper.instance().onMetricEdit(editedMetric);
- expect(onChange.lastCall.args).toEqual([[
- editedMetric,
- ]]);
+ expect(onChange.lastCall.args).toEqual([[editedMetric]]);
});
});
@@ -220,118 +254,151 @@ describe('MetricsControl', () => {
it('includes user defined metrics', () => {
const { wrapper } = setup({ datasourceType: 'druid' });
- expect(!!wrapper.instance().selectFilterOption(
- {
- metric_name: 'a_metric',
- optionName: 'a_metric',
- expression: 'SUM(FANCY(metric))',
- },
- 'a',
- )).toBe(true);
+ expect(
+ !!wrapper.instance().selectFilterOption(
+ {
+ metric_name: 'a_metric',
+ optionName: 'a_metric',
+ expression: 'SUM(FANCY(metric))',
+ },
+ 'a',
+ ),
+ ).toBe(true);
});
it('includes auto generated avg metrics for druid', () => {
const { wrapper } = setup({ datasourceType: 'druid' });
- expect(!!wrapper.instance().selectFilterOption(
- {
- metric_name: 'avg__metric',
- optionName: 'avg__metric',
- expression: 'AVG(metric)',
- },
- 'a',
- )).toBe(true);
+ expect(
+ !!wrapper.instance().selectFilterOption(
+ {
+ metric_name: 'avg__metric',
+ optionName: 'avg__metric',
+ expression: 'AVG(metric)',
+ },
+ 'a',
+ ),
+ ).toBe(true);
});
it('includes columns and aggregates', () => {
const { wrapper } = setup();
- expect(!!wrapper.instance().selectFilterOption(
- { type: 'VARCHAR(255)', column_name: 'source', optionName: '_col_source' },
- 'sou',
- )).toBe(true);
+ expect(
+ !!wrapper.instance().selectFilterOption(
+ {
+ type: 'VARCHAR(255)',
+ column_name: 'source',
+ optionName: '_col_source',
+ },
+ 'sou',
+ ),
+ ).toBe(true);
- expect(!!wrapper.instance().selectFilterOption(
- { aggregate_name: 'AVG', optionName: '_aggregate_AVG' },
- 'av',
- )).toBe(true);
+ expect(
+ !!wrapper
+ .instance()
+ .selectFilterOption(
+ { aggregate_name: 'AVG', optionName: '_aggregate_AVG' },
+ 'av',
+ ),
+ ).toBe(true);
});
it('includes columns based on verbose_name', () => {
const { wrapper } = setup();
- expect(!!wrapper.instance().selectFilterOption(
- { metric_name: 'sum__num', verbose_name: 'babies', optionName: '_col_sum_num' },
- 'bab',
- )).toBe(true);
+ expect(
+ !!wrapper.instance().selectFilterOption(
+ {
+ metric_name: 'sum__num',
+ verbose_name: 'babies',
+ optionName: '_col_sum_num',
+ },
+ 'bab',
+ ),
+ ).toBe(true);
});
it('excludes auto generated avg metrics for sqla', () => {
const { wrapper } = setup();
- expect(!!wrapper.instance().selectFilterOption(
- {
- metric_name: 'avg__metric',
- optionName: 'avg__metric',
- expression: 'AVG(metric)',
- },
- 'a',
- )).toBe(false);
+ expect(
+ !!wrapper.instance().selectFilterOption(
+ {
+ metric_name: 'avg__metric',
+ optionName: 'avg__metric',
+ expression: 'AVG(metric)',
+ },
+ 'a',
+ ),
+ ).toBe(false);
});
it('includes custom made simple saved metrics', () => {
const { wrapper } = setup();
- expect(!!wrapper.instance().selectFilterOption(
- {
- metric_name: 'my_fancy_sum_metric',
- optionName: 'my_fancy_sum_metric',
- expression: 'SUM(value)',
- },
- 'sum',
- )).toBe(true);
+ expect(
+ !!wrapper.instance().selectFilterOption(
+ {
+ metric_name: 'my_fancy_sum_metric',
+ optionName: 'my_fancy_sum_metric',
+ expression: 'SUM(value)',
+ },
+ 'sum',
+ ),
+ ).toBe(true);
});
it('excludes auto generated metrics', () => {
const { wrapper } = setup();
- expect(!!wrapper.instance().selectFilterOption(
- {
- metric_name: 'sum__value',
- optionName: 'sum__value',
- expression: 'SUM(value)',
- },
- 'sum',
- )).toBe(false);
+ expect(
+ !!wrapper.instance().selectFilterOption(
+ {
+ metric_name: 'sum__value',
+ optionName: 'sum__value',
+ expression: 'SUM(value)',
+ },
+ 'sum',
+ ),
+ ).toBe(false);
- expect(!!wrapper.instance().selectFilterOption(
- {
- metric_name: 'sum__value',
- optionName: 'sum__value',
- expression: 'SUM("table"."value")',
- },
- 'sum',
- )).toBe(false);
+ expect(
+ !!wrapper.instance().selectFilterOption(
+ {
+ metric_name: 'sum__value',
+ optionName: 'sum__value',
+ expression: 'SUM("table"."value")',
+ },
+ 'sum',
+ ),
+ ).toBe(false);
});
it('filters out metrics if the input begins with an aggregate', () => {
const { wrapper } = setup();
wrapper.setState({ aggregateInInput: true });
- expect(!!wrapper.instance().selectFilterOption(
- { metric_name: 'metric', expression: 'SUM(FANCY(metric))' },
- 'SUM(',
- )).toBe(false);
+ expect(
+ !!wrapper
+ .instance()
+ .selectFilterOption(
+ { metric_name: 'metric', expression: 'SUM(FANCY(metric))' },
+ 'SUM(',
+ ),
+ ).toBe(false);
});
it('includes columns if the input begins with an aggregate', () => {
const { wrapper } = setup();
wrapper.setState({ aggregateInInput: true });
- expect(!!wrapper.instance().selectFilterOption(
- { type: 'DOUBLE', column_name: 'value' },
- 'SUM(',
- )).toBe(true);
+ expect(
+ !!wrapper
+ .instance()
+ .selectFilterOption({ type: 'DOUBLE', column_name: 'value' }, 'SUM('),
+ ).toBe(true);
});
it('Removes metrics if savedMetrics changes', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/QueryAndSaveBtns_spec.jsx b/superset/assets/spec/javascripts/explore/components/QueryAndSaveBtns_spec.jsx
index 14d0c254fab..7ddfb99a801 100644
--- a/superset/assets/spec/javascripts/explore/components/QueryAndSaveBtns_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/QueryAndSaveBtns_spec.jsx
@@ -31,7 +31,9 @@ describe('QueryAndSaveButtons', () => {
// It must render
it('renders', () => {
- expect(React.isValidElement( )).toBe(true);
+ expect(
+ React.isValidElement( ),
+ ).toBe(true);
});
// Test the output
diff --git a/superset/assets/spec/javascripts/explore/components/RowCountLabel_spec.jsx b/superset/assets/spec/javascripts/explore/components/RowCountLabel_spec.jsx
index 5589a549a5c..3d4cff84f22 100644
--- a/superset/assets/spec/javascripts/explore/components/RowCountLabel_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/RowCountLabel_spec.jsx
@@ -31,7 +31,9 @@ describe('RowCountLabel', () => {
};
it('is valid', () => {
- expect(React.isValidElement( )).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('renders a Label and a TooltipWrapper', () => {
const wrapper = shallow( );
@@ -44,6 +46,11 @@ describe('RowCountLabel', () => {
limit: 100,
};
const wrapper = shallow( );
- expect(wrapper.find(Label).first().props().bsStyle).toBe('danger');
+ expect(
+ wrapper
+ .find(Label)
+ .first()
+ .props().bsStyle,
+ ).toBe('danger');
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/RunQueryActionButton_spec.jsx b/superset/assets/spec/javascripts/explore/components/RunQueryActionButton_spec.jsx
index ab2c93f6697..73221973c8f 100644
--- a/superset/assets/spec/javascripts/explore/components/RunQueryActionButton_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/RunQueryActionButton_spec.jsx
@@ -19,8 +19,7 @@
import React from 'react';
import { shallow } from 'enzyme';
-import RunQueryActionButton
- from '../../../../src/SqlLab/components/RunQueryActionButton';
+import RunQueryActionButton from '../../../../src/SqlLab/components/RunQueryActionButton';
import Button from '../../../../src/components/Button';
describe('RunQueryActionButton', () => {
diff --git a/superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx b/superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx
index d334688a4d0..1353e0e938e 100644
--- a/superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx
@@ -53,7 +53,7 @@ describe('SaveModal', () => {
const defaultProps = {
onHide: () => ({}),
- actions: bindActionCreators(saveModalActions, (arg) => {
+ actions: bindActionCreators(saveModalActions, arg => {
if (typeof arg === 'function') {
return arg(jest.fn);
}
@@ -144,11 +144,11 @@ describe('SaveModal', () => {
.stub(exploreUtils, 'getExploreUrlAndPayload')
.callsFake(() => ({ url: 'mockURL', payload: defaultProps.form_data }));
- sinon
- .stub(defaultProps.actions, 'saveSlice')
- .callsFake(() =>
- Promise.resolve({ data: { dashboard: '/mock/', slice: { slice_url: '/mock/' } } }),
- );
+ sinon.stub(defaultProps.actions, 'saveSlice').callsFake(() =>
+ Promise.resolve({
+ data: { dashboard: '/mock/', slice: { slice_url: '/mock/' } },
+ }),
+ );
});
afterEach(() => {
@@ -223,15 +223,14 @@ describe('SaveModal', () => {
return actionThunk(dispatch);
};
- it('makes the fetch request', () => (
+ it('makes the fetch request', () =>
makeRequest().then(() => {
expect(fetchMock.calls(saveEndpoint)).toHaveLength(1);
return Promise.resolve();
- })
- ));
+ }));
- it('calls correct actions on success', () => (
+ it('calls correct actions on success', () =>
makeRequest().then(() => {
expect(dispatch.callCount).toBe(1);
expect(dispatch.getCall(0).args[0].type).toBe(
@@ -239,17 +238,24 @@ describe('SaveModal', () => {
);
return Promise.resolve();
- })
- ));
+ }));
it('calls correct actions on error', () => {
- fetchMock.get(saveEndpoint, { throws: 'error' }, { overwriteRoutes: true });
+ fetchMock.get(
+ saveEndpoint,
+ { throws: 'error' },
+ { overwriteRoutes: true },
+ );
return makeRequest().then(() => {
expect(dispatch.callCount).toBe(1);
- expect(dispatch.getCall(0).args[0].type).toBe(saveModalActions.FETCH_DASHBOARDS_FAILED);
+ expect(dispatch.getCall(0).args[0].type).toBe(
+ saveModalActions.FETCH_DASHBOARDS_FAILED,
+ );
- fetchMock.get(saveEndpoint, mockDashboardData, { overwriteRoutes: true });
+ fetchMock.get(saveEndpoint, mockDashboardData, {
+ overwriteRoutes: true,
+ });
return Promise.resolve();
});
diff --git a/superset/assets/spec/javascripts/explore/components/SelectControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/SelectControl_spec.jsx
index ce20aab4627..05e47d56c0e 100644
--- a/superset/assets/spec/javascripts/explore/components/SelectControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/SelectControl_spec.jsx
@@ -27,7 +27,10 @@ import VirtualizedRendererWrap from '../../../../src/components/VirtualizedRende
import SelectControl from '../../../../src/explore/components/controls/SelectControl';
const defaultProps = {
- choices: [['1 year ago', '1 year ago'], ['today', 'today']],
+ choices: [
+ ['1 year ago', '1 year ago'],
+ ['today', 'today'],
+ ],
name: 'row_limit',
label: 'Row Limit',
valueKey: 'value', // shallow isn't passing SelectControl.defaultProps.valueKey through
@@ -115,8 +118,11 @@ describe('SelectControl', () => {
valueKey: 'value',
};
wrapper.setProps(selectAllProps);
- expect(wrapper.instance().getOptions(selectAllProps))
- .toContainEqual({ label: 'Select All', meta: true, value: 'Select All' });
+ expect(wrapper.instance().getOptions(selectAllProps)).toContainEqual({
+ label: 'Select All',
+ meta: true,
+ value: 'Select All',
+ });
});
it('returns the correct options when freeform is set to true', () => {
@@ -145,7 +151,10 @@ describe('SelectControl', () => {
{ value: 'four', label: 'four' },
];
const newProps = {
- choices: [['three', 'three'], ['four', 'four']],
+ choices: [
+ ['three', 'three'],
+ ['four', 'four'],
+ ],
name: 'name',
freeForm: false,
value: null,
diff --git a/superset/assets/spec/javascripts/explore/components/ViewportControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/ViewportControl_spec.jsx
index ada75ea9d6d..768a05eec34 100644
--- a/superset/assets/spec/javascripts/explore/components/ViewportControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/ViewportControl_spec.jsx
@@ -21,10 +21,8 @@ import React from 'react';
import { shallow } from 'enzyme';
import { OverlayTrigger, Label } from 'react-bootstrap';
-import ViewportControl from
- '../../../../src/explore/components/controls/ViewportControl';
-import TextControl from
- '../../../../src/explore/components/controls/TextControl';
+import ViewportControl from '../../../../src/explore/components/controls/ViewportControl';
+import TextControl from '../../../../src/explore/components/controls/TextControl';
import ControlHeader from '../../../../src/explore/components/ControlHeader';
const defaultProps = {
@@ -57,6 +55,12 @@ describe('ViewportControl', () => {
});
it('renders a summary in the label', () => {
- expect(wrapper.find(Label).first().render().text()).toBe('6° 51\' 8.50" | 31° 13\' 21.56"');
+ expect(
+ wrapper
+ .find(Label)
+ .first()
+ .render()
+ .text(),
+ ).toBe('6° 51\' 8.50" | 31° 13\' 21.56"');
});
});
diff --git a/superset/assets/spec/javascripts/explore/components/VizTypeControl_spec.jsx b/superset/assets/spec/javascripts/explore/components/VizTypeControl_spec.jsx
index 8941d1bbd12..e266e9f76c5 100644
--- a/superset/assets/spec/javascripts/explore/components/VizTypeControl_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/VizTypeControl_spec.jsx
@@ -35,14 +35,20 @@ describe('VizTypeControl', () => {
const registry = getChartMetadataRegistry();
registry
- .registerValue('vis1', new ChartMetadata({
- name: 'vis1',
- thumbnail: '',
- }))
- .registerValue('vis2', new ChartMetadata({
- name: 'vis2',
- thumbnail: '',
- }));
+ .registerValue(
+ 'vis1',
+ new ChartMetadata({
+ name: 'vis1',
+ thumbnail: '',
+ }),
+ )
+ .registerValue(
+ 'vis2',
+ new ChartMetadata({
+ name: 'vis2',
+ thumbnail: '',
+ }),
+ );
beforeEach(() => {
wrapper = shallow( );
diff --git a/superset/assets/spec/javascripts/explore/components/withVerification_spec.jsx b/superset/assets/spec/javascripts/explore/components/withVerification_spec.jsx
index bef21406954..f7cd15728dc 100644
--- a/superset/assets/spec/javascripts/explore/components/withVerification_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/components/withVerification_spec.jsx
@@ -42,7 +42,10 @@ const defaultProps = {
getEndpoint: controlValues => `valid_metrics?data=${controlValues}`,
};
-const VALID_METRIC = { metric_name: 'sum__value', expression: 'SUM(energy_usage.value)' };
+const VALID_METRIC = {
+ metric_name: 'sum__value',
+ expression: 'SUM(energy_usage.value)',
+};
function setup(overrides, validMetric) {
const onChange = sinon.spy();
@@ -51,16 +54,22 @@ function setup(overrides, validMetric) {
...defaultProps,
...overrides,
};
- const VerifiedControl = withVerification(MetricsControl, 'metric_name', 'savedMetrics');
+ const VerifiedControl = withVerification(
+ MetricsControl,
+ 'metric_name',
+ 'savedMetrics',
+ );
const wrapper = shallow( );
- fetchMock.mock('glob:*/valid_metrics*', validMetric || `["${VALID_METRIC.metric_name}"]`);
+ fetchMock.mock(
+ 'glob:*/valid_metrics*',
+ validMetric || `["${VALID_METRIC.metric_name}"]`,
+ );
return { props, wrapper, onChange };
}
afterEach(fetchMock.restore);
describe('VerifiedMetricsControl', () => {
-
it('Gets valid options', () => {
const { wrapper } = setup();
setTimeout(() => {
@@ -92,7 +101,9 @@ describe('VerifiedMetricsControl', () => {
});
it('Calls endpoint if control values change', () => {
- const { props, wrapper } = setup({ controlValues: { metrics: 'sum__value' } });
+ const { props, wrapper } = setup({
+ controlValues: { metrics: 'sum__value' },
+ });
setTimeout(() => {
expect(fetchMock.calls(defaultProps.getEndpoint())).toHaveLength(1);
fetchMock.reset();
diff --git a/superset/assets/spec/javascripts/explore/controlUtils_spec.jsx b/superset/assets/spec/javascripts/explore/controlUtils_spec.jsx
index 12117293ad5..2725a9a975e 100644
--- a/superset/assets/spec/javascripts/explore/controlUtils_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/controlUtils_spec.jsx
@@ -27,57 +27,55 @@ import {
describe('controlUtils', () => {
const state = {
datasource: {
- columns: [
- 'a', 'b', 'c',
- ],
- metrics: [
- { metric_name: 'first' },
- { metric_name: 'second' },
- ],
+ columns: ['a', 'b', 'c'],
+ metrics: [{ metric_name: 'first' }, { metric_name: 'second' }],
},
};
beforeAll(() => {
- getChartControlPanelRegistry().registerValue('test-chart', {
- requiresTime: true,
- controlPanelSections: [
- {
- label: t('Chart Options'),
- expanded: true,
- controlSetRows: [
- ['color_scheme', {
- name: 'rose_area_proportion',
- config: {
- type: 'CheckboxControl',
- label: t('Use Area Proportions'),
- description: t(
- 'Check if the Rose Chart should use segment area instead of ' +
- 'segment radius for proportioning',
- ),
- default: false,
- renderTrigger: true,
- },
- }],
- ],
+ getChartControlPanelRegistry()
+ .registerValue('test-chart', {
+ requiresTime: true,
+ controlPanelSections: [
+ {
+ label: t('Chart Options'),
+ expanded: true,
+ controlSetRows: [
+ [
+ 'color_scheme',
+ {
+ name: 'rose_area_proportion',
+ config: {
+ type: 'CheckboxControl',
+ label: t('Use Area Proportions'),
+ description: t(
+ 'Check if the Rose Chart should use segment area instead of ' +
+ 'segment radius for proportioning',
+ ),
+ default: false,
+ renderTrigger: true,
+ },
+ },
+ ],
+ ],
+ },
+ ],
+ })
+ .registerValue('test-chart-override', {
+ requiresTime: true,
+ controlPanelSections: [
+ {
+ label: t('Chart Options'),
+ expanded: true,
+ controlSetRows: [['color_scheme']],
+ },
+ ],
+ controlOverrides: {
+ color_scheme: {
+ label: t('My beautiful colors'),
+ },
},
- ],
- }).registerValue('test-chart-override', {
- requiresTime: true,
- controlPanelSections: [
- {
- label: t('Chart Options'),
- expanded: true,
- controlSetRows: [
- ['color_scheme'],
- ],
- },
- ],
- controlOverrides: {
- color_scheme: {
- label: t('My beautiful colors'),
- },
- },
- });
+ });
});
afterAll(() => {
@@ -101,20 +99,26 @@ describe('controlUtils', () => {
expect(control.label).toEqual('My beautiful colors');
});
- it('returns correct control config when control config is defined ' +
- 'in the control panel definition', () => {
- const roseAreaProportionControlConfig = getControlConfig('rose_area_proportion', 'test-chart');
+ it(
+ 'returns correct control config when control config is defined ' +
+ 'in the control panel definition',
+ () => {
+ const roseAreaProportionControlConfig = getControlConfig(
+ 'rose_area_proportion',
+ 'test-chart',
+ );
expect(roseAreaProportionControlConfig).toEqual({
type: 'CheckboxControl',
label: t('Use Area Proportions'),
description: t(
'Check if the Rose Chart should use segment area instead of ' +
- 'segment radius for proportioning',
+ 'segment radius for proportioning',
),
default: false,
renderTrigger: true,
- });
- });
+ });
+ },
+ );
});
describe('applyMapStateToPropsToControl,', () => {
@@ -129,7 +133,6 @@ describe('controlUtils', () => {
control = applyMapStateToPropsToControl(control, state);
expect(control.mapStateToProps).toBe(undefined);
});
-
});
describe('getControlState', () => {
diff --git a/superset/assets/spec/javascripts/explore/exploreActions_spec.js b/superset/assets/spec/javascripts/explore/exploreActions_spec.js
index 22e02495882..54c39b013e7 100644
--- a/superset/assets/spec/javascripts/explore/exploreActions_spec.js
+++ b/superset/assets/spec/javascripts/explore/exploreActions_spec.js
@@ -24,12 +24,16 @@ import * as actions from '../../../src/explore/actions/exploreActions';
describe('reducers', () => {
it('sets correct control value given a key and value', () => {
const newState = exploreReducer(
- defaultState, actions.setControlValue('x_axis_label', 'x', []));
+ defaultState,
+ actions.setControlValue('x_axis_label', 'x', []),
+ );
expect(newState.controls.x_axis_label.value).toBe('x');
});
it('setControlValue works as expected with a checkbox', () => {
- const newState = exploreReducer(defaultState,
- actions.setControlValue('show_legend', true, []));
+ const newState = exploreReducer(
+ defaultState,
+ actions.setControlValue('show_legend', true, []),
+ );
expect(newState.controls.show_legend.value).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/explore/store_spec.jsx b/superset/assets/spec/javascripts/explore/store_spec.jsx
index 470cb162605..80e3d1051b7 100644
--- a/superset/assets/spec/javascripts/explore/store_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/store_spec.jsx
@@ -37,7 +37,6 @@ describe('store', () => {
});
describe('applyDefaultFormData', () => {
-
window.featureFlags = {
SCOPED_FILTER: false,
};
@@ -77,6 +76,5 @@ describe('store', () => {
const outputFormData = applyDefaultFormData(inputFormData);
expect(outputFormData.this_should_no_be_here).toBe(undefined);
});
-
});
});
diff --git a/superset/assets/spec/javascripts/explore/utils_spec.jsx b/superset/assets/spec/javascripts/explore/utils_spec.jsx
index 3845233e2db..4efc21d3d5b 100644
--- a/superset/assets/spec/javascripts/explore/utils_spec.jsx
+++ b/superset/assets/spec/javascripts/explore/utils_spec.jsx
@@ -19,7 +19,10 @@
import sinon from 'sinon';
import URI from 'urijs';
-import { getExploreUrlAndPayload, getExploreLongUrl } from '../../../src/explore/exploreUtils';
+import {
+ getExploreUrlAndPayload,
+ getExploreLongUrl,
+} from '../../../src/explore/exploreUtils';
import * as hostNamesConfig from '../../../src/utils/hostNamesConfig';
describe('exploreUtils', () => {
@@ -44,10 +47,7 @@ describe('exploreUtils', () => {
force: false,
curUrl: 'http://superset.com',
});
- compareURI(
- URI(url),
- URI('/superset/explore/'),
- );
+ compareURI(URI(url), URI('/superset/explore/'));
expect(payload).toEqual(formData);
});
it('generates proper json url', () => {
@@ -57,10 +57,7 @@ describe('exploreUtils', () => {
force: false,
curUrl: 'http://superset.com',
});
- compareURI(
- URI(url),
- URI('/superset/explore_json/'),
- );
+ compareURI(URI(url), URI('/superset/explore_json/'));
expect(payload).toEqual(formData);
});
it('generates proper json forced url', () => {
@@ -72,8 +69,7 @@ describe('exploreUtils', () => {
});
compareURI(
URI(url),
- URI('/superset/explore_json/')
- .search({ force: 'true' }),
+ URI('/superset/explore_json/').search({ force: 'true' }),
);
expect(payload).toEqual(formData);
});
@@ -86,8 +82,7 @@ describe('exploreUtils', () => {
});
compareURI(
URI(url),
- URI('/superset/explore_json/')
- .search({ csv: 'true' }),
+ URI('/superset/explore_json/').search({ csv: 'true' }),
);
expect(payload).toEqual(formData);
});
@@ -100,8 +95,7 @@ describe('exploreUtils', () => {
});
compareURI(
URI(url),
- URI('/superset/explore/')
- .search({ standalone: 'true' }),
+ URI('/superset/explore/').search({ standalone: 'true' }),
);
expect(payload).toEqual(formData);
});
@@ -114,8 +108,7 @@ describe('exploreUtils', () => {
});
compareURI(
URI(url),
- URI('/superset/explore_json/')
- .search({ foo: 'bar' }),
+ URI('/superset/explore_json/').search({ foo: 'bar' }),
);
expect(payload).toEqual(formData);
});
@@ -128,8 +121,7 @@ describe('exploreUtils', () => {
});
compareURI(
URI(url),
- URI('/superset/explore_json/')
- .search({ foo: 'bar' }),
+ URI('/superset/explore_json/').search({ foo: 'bar' }),
);
expect(payload).toEqual(formData);
});
@@ -142,8 +134,7 @@ describe('exploreUtils', () => {
});
compareURI(
URI(url),
- URI('/superset/explore_json/')
- .search({ foo: 'bar' }),
+ URI('/superset/explore_json/').search({ foo: 'bar' }),
);
expect(payload).toEqual(formData);
});
@@ -153,10 +144,14 @@ describe('exploreUtils', () => {
let stub;
const availableDomains = [
'http://localhost/',
- 'domain1.com', 'domain2.com', 'domain3.com',
+ 'domain1.com',
+ 'domain2.com',
+ 'domain3.com',
];
beforeEach(() => {
- stub = sinon.stub(hostNamesConfig, 'availableDomains').value(availableDomains);
+ stub = sinon
+ .stub(hostNamesConfig, 'availableDomains')
+ .value(availableDomains);
});
afterEach(() => {
stub.restore();
diff --git a/superset/assets/spec/javascripts/messageToasts/.prettierrc b/superset/assets/spec/javascripts/messageToasts/.prettierrc
deleted file mode 100644
index a20502b7f06..00000000000
--- a/superset/assets/spec/javascripts/messageToasts/.prettierrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "singleQuote": true,
- "trailingComma": "all"
-}
diff --git a/superset/assets/spec/javascripts/middleware/logger_spec.js b/superset/assets/spec/javascripts/middleware/logger_spec.js
index c5f5a4a6c6a..e2b7b9a8a28 100644
--- a/superset/assets/spec/javascripts/middleware/logger_spec.js
+++ b/superset/assets/spec/javascripts/middleware/logger_spec.js
@@ -70,33 +70,32 @@ describe('logger middleware', () => {
clock.tick(2000);
expect(SupersetClient.post.callCount).toBe(1);
- expect(SupersetClient.post.getCall(0).args[0].endpoint).toMatch('/superset/log/');
+ expect(SupersetClient.post.getCall(0).args[0].endpoint).toMatch(
+ '/superset/log/',
+ );
});
- it(
- 'should include ts, start_offset, event_name, impression_id, source, and source_id in every event',
- () => {
- const clock = sinon.useFakeTimers();
- logger(mockStore)(next)(action);
- clock.tick(2000);
+ it('should include ts, start_offset, event_name, impression_id, source, and source_id in every event', () => {
+ const clock = sinon.useFakeTimers();
+ logger(mockStore)(next)(action);
+ clock.tick(2000);
- expect(SupersetClient.post.callCount).toBe(1);
- const events = SupersetClient.post.getCall(0).args[0].postPayload.events;
- const mockEventdata = action.payload.eventData;
- const mockEventname = action.payload.eventName;
- expect(events[0]).toMatchObject({
- key: mockEventdata.key,
- event_name: mockEventname,
- impression_id: mockStore.getState().impressionId,
- source: 'dashboard',
- source_id: mockStore.getState().dashboardInfo.id,
- event_type: 'timing',
- });
+ expect(SupersetClient.post.callCount).toBe(1);
+ const events = SupersetClient.post.getCall(0).args[0].postPayload.events;
+ const mockEventdata = action.payload.eventData;
+ const mockEventname = action.payload.eventName;
+ expect(events[0]).toMatchObject({
+ key: mockEventdata.key,
+ event_name: mockEventname,
+ impression_id: mockStore.getState().impressionId,
+ source: 'dashboard',
+ source_id: mockStore.getState().dashboardInfo.id,
+ event_type: 'timing',
+ });
- expect(typeof events[0].ts).toBe('number');
- expect(typeof events[0].start_offset).toBe('number');
- },
- );
+ expect(typeof events[0].ts).toBe('number');
+ expect(typeof events[0].start_offset).toBe('number');
+ });
it('should debounce a few log requests to one', () => {
const clock = sinon.useFakeTimers();
@@ -106,6 +105,8 @@ describe('logger middleware', () => {
clock.tick(2000);
expect(SupersetClient.post.callCount).toBe(1);
- expect(SupersetClient.post.getCall(0).args[0].postPayload.events).toHaveLength(3);
+ expect(
+ SupersetClient.post.getCall(0).args[0].postPayload.events,
+ ).toHaveLength(3);
});
});
diff --git a/superset/assets/spec/javascripts/modules/utils_spec.jsx b/superset/assets/spec/javascripts/modules/utils_spec.jsx
index 842f54b5045..4db2f0dfe56 100644
--- a/superset/assets/spec/javascripts/modules/utils_spec.jsx
+++ b/superset/assets/spec/javascripts/modules/utils_spec.jsx
@@ -44,24 +44,15 @@ describe('utils', () => {
expect(mainMetric(null)).toBeUndefined();
});
it('prefers the "count" metric when first', () => {
- const metrics = [
- { metric_name: 'count' },
- { metric_name: 'foo' },
- ];
+ const metrics = [{ metric_name: 'count' }, { metric_name: 'foo' }];
expect(mainMetric(metrics)).toBe('count');
});
it('prefers the "count" metric when not first', () => {
- const metrics = [
- { metric_name: 'foo' },
- { metric_name: 'count' },
- ];
+ const metrics = [{ metric_name: 'foo' }, { metric_name: 'count' }];
expect(mainMetric(metrics)).toBe('count');
});
it('selects the first metric when "count" is not an option', () => {
- const metrics = [
- { metric_name: 'foo' },
- { metric_name: 'not_count' },
- ];
+ const metrics = [{ metric_name: 'foo' }, { metric_name: 'not_count' }];
expect(mainMetric(metrics)).toBe('foo');
});
});
diff --git a/superset/assets/spec/javascripts/profile/App_spec.jsx b/superset/assets/spec/javascripts/profile/App_spec.jsx
index 7896a4caaf4..7a7224945b3 100644
--- a/superset/assets/spec/javascripts/profile/App_spec.jsx
+++ b/superset/assets/spec/javascripts/profile/App_spec.jsx
@@ -28,9 +28,7 @@ describe('App', () => {
user,
};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders 2 Col', () => {
diff --git a/superset/assets/spec/javascripts/profile/CreatedContent_spec.jsx b/superset/assets/spec/javascripts/profile/CreatedContent_spec.jsx
index af8130235b4..f2deca00223 100644
--- a/superset/assets/spec/javascripts/profile/CreatedContent_spec.jsx
+++ b/superset/assets/spec/javascripts/profile/CreatedContent_spec.jsx
@@ -35,12 +35,16 @@ describe('CreatedContent', () => {
};
it('renders 2 TableLoader', () => {
- const wrapper = shallow( , { context: { store } });
+ const wrapper = shallow( , {
+ context: { store },
+ });
expect(wrapper.find(TableLoader)).toHaveLength(2);
});
it('renders 2 titles', () => {
- const wrapper = shallow( , { context: { store } });
+ const wrapper = shallow( , {
+ context: { store },
+ });
expect(wrapper.find('h3')).toHaveLength(2);
});
});
diff --git a/superset/assets/spec/javascripts/profile/EditableTitle_spec.jsx b/superset/assets/spec/javascripts/profile/EditableTitle_spec.jsx
index 4013a636ac9..270dfa0a381 100644
--- a/superset/assets/spec/javascripts/profile/EditableTitle_spec.jsx
+++ b/superset/assets/spec/javascripts/profile/EditableTitle_spec.jsx
@@ -35,11 +35,11 @@ describe('EditableTitle', () => {
},
};
const editableWrapper = shallow( );
- const notEditableWrapper = shallow( );
+ const notEditableWrapper = shallow(
+ ,
+ );
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('should render title', () => {
const titleElement = editableWrapper.find('input');
diff --git a/superset/assets/spec/javascripts/profile/Favorites_spec.jsx b/superset/assets/spec/javascripts/profile/Favorites_spec.jsx
index 6248d18efc3..75482da046b 100644
--- a/superset/assets/spec/javascripts/profile/Favorites_spec.jsx
+++ b/superset/assets/spec/javascripts/profile/Favorites_spec.jsx
@@ -35,12 +35,16 @@ describe('Favorites', () => {
};
it('renders 2 TableLoader', () => {
- const wrapper = shallow( , { context: { store } });
+ const wrapper = shallow( , {
+ context: { store },
+ });
expect(wrapper.find(TableLoader)).toHaveLength(2);
});
it('renders 2 titles', () => {
- const wrapper = shallow( , { context: { store } });
+ const wrapper = shallow( , {
+ context: { store },
+ });
expect(wrapper.find('h3')).toHaveLength(2);
});
});
diff --git a/superset/assets/spec/javascripts/profile/RecentActivity_spec.jsx b/superset/assets/spec/javascripts/profile/RecentActivity_spec.jsx
index c99db2f58ac..08d6b6f19ba 100644
--- a/superset/assets/spec/javascripts/profile/RecentActivity_spec.jsx
+++ b/superset/assets/spec/javascripts/profile/RecentActivity_spec.jsx
@@ -28,9 +28,9 @@ describe('RecentActivity', () => {
user,
};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('renders a TableLoader', () => {
diff --git a/superset/assets/spec/javascripts/profile/Security_spec.jsx b/superset/assets/spec/javascripts/profile/Security_spec.jsx
index 79d6e878380..50dd541ac51 100644
--- a/superset/assets/spec/javascripts/profile/Security_spec.jsx
+++ b/superset/assets/spec/javascripts/profile/Security_spec.jsx
@@ -22,15 +22,12 @@ import { mount } from 'enzyme';
import { user, userNoPerms } from './fixtures';
import Security from '../../../src/profile/components/Security';
-
describe('Security', () => {
const mockedProps = {
user,
};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders 2 role labels', () => {
const wrapper = mount( );
diff --git a/superset/assets/spec/javascripts/profile/UserInfo_spec.jsx b/superset/assets/spec/javascripts/profile/UserInfo_spec.jsx
index d232ef6a320..0f9c1108d92 100644
--- a/superset/assets/spec/javascripts/profile/UserInfo_spec.jsx
+++ b/superset/assets/spec/javascripts/profile/UserInfo_spec.jsx
@@ -24,15 +24,12 @@ import { mount } from 'enzyme';
import { user } from './fixtures';
import UserInfo from '../../../src/profile/components/UserInfo';
-
describe('UserInfo', () => {
const mockedProps = {
user,
};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders a Gravatar', () => {
const wrapper = mount( );
diff --git a/superset/assets/spec/javascripts/profile/fixtures.jsx b/superset/assets/spec/javascripts/profile/fixtures.jsx
index da907a011e4..2b378c5adb7 100644
--- a/superset/assets/spec/javascripts/profile/fixtures.jsx
+++ b/superset/assets/spec/javascripts/profile/fixtures.jsx
@@ -20,40 +20,16 @@ export const user = {
username: 'alpha',
roles: {
Alpha: [
- [
- 'can_this_form_post',
- 'ResetMyPasswordView',
- ],
- [
- 'can_this_form_get',
- 'ResetMyPasswordView',
- ],
- [
- 'can_this_form_post',
- 'UserInfoEditView',
- ],
- [
- 'can_this_form_get',
- 'UserInfoEditView',
- ],
+ ['can_this_form_post', 'ResetMyPasswordView'],
+ ['can_this_form_get', 'ResetMyPasswordView'],
+ ['can_this_form_post', 'UserInfoEditView'],
+ ['can_this_form_get', 'UserInfoEditView'],
],
sql_lab: [
- [
- 'menu_access',
- 'SQL Lab',
- ],
- [
- 'can_sql_json',
- 'Superset',
- ],
- [
- 'can_search_queries',
- 'Superset',
- ],
- [
- 'can_csv',
- 'Superset',
- ],
+ ['menu_access', 'SQL Lab'],
+ ['can_sql_json', 'Superset'],
+ ['can_search_queries', 'Superset'],
+ ['can_csv', 'Superset'],
],
},
firstName: 'alpha',
diff --git a/superset/assets/spec/javascripts/showSavedQuery/utils_spec.jsx b/superset/assets/spec/javascripts/showSavedQuery/utils_spec.jsx
index d198a49180f..fd0e9135808 100644
--- a/superset/assets/spec/javascripts/showSavedQuery/utils_spec.jsx
+++ b/superset/assets/spec/javascripts/showSavedQuery/utils_spec.jsx
@@ -43,7 +43,6 @@ describe('getNestedValue', () => {
});
});
-
describe('interpolate', () => {
it('is a function', () => {
expect(typeof interpolate).toBe('function');
diff --git a/superset/assets/spec/javascripts/sqllab/ColumnElement_spec.jsx b/superset/assets/spec/javascripts/sqllab/ColumnElement_spec.jsx
index ff7c2671a5b..47d0ffdcb78 100644
--- a/superset/assets/spec/javascripts/sqllab/ColumnElement_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/ColumnElement_spec.jsx
@@ -22,31 +22,43 @@ import { mount } from 'enzyme';
import { mockedActions, table } from './fixtures';
import ColumnElement from '../../../src/SqlLab/components/ColumnElement';
-
describe('ColumnElement', () => {
const mockedProps = {
actions: mockedActions,
column: table.columns[0],
};
it('is valid with props', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders a proper primary key', () => {
const wrapper = mount( );
expect(wrapper.find('i.fa-key')).toHaveLength(1);
- expect(wrapper.find('.col-name').first().text()).toBe('id');
+ expect(
+ wrapper
+ .find('.col-name')
+ .first()
+ .text(),
+ ).toBe('id');
});
it('renders a multi-key column', () => {
const wrapper = mount( );
expect(wrapper.find('i.fa-link')).toHaveLength(1);
expect(wrapper.find('i.fa-bookmark')).toHaveLength(1);
- expect(wrapper.find('.col-name').first().text()).toBe('first_name');
+ expect(
+ wrapper
+ .find('.col-name')
+ .first()
+ .text(),
+ ).toBe('first_name');
});
it('renders a column with no keys', () => {
const wrapper = mount( );
expect(wrapper.find('i')).toHaveLength(0);
- expect(wrapper.find('.col-name').first().text()).toBe('last_name');
+ expect(
+ wrapper
+ .find('.col-name')
+ .first()
+ .text(),
+ ).toBe('last_name');
});
});
diff --git a/superset/assets/spec/javascripts/sqllab/ExploreResultsButton_spec.jsx b/superset/assets/spec/javascripts/sqllab/ExploreResultsButton_spec.jsx
index 70fca920d4f..8e4315f9aba 100644
--- a/superset/assets/spec/javascripts/sqllab/ExploreResultsButton_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/ExploreResultsButton_spec.jsx
@@ -99,7 +99,12 @@ describe('ExploreResultsButton', () => {
});
const badCols = wrapper.instance().getInvalidColumns();
- expect(badCols).toEqual(['COUNT(*)', '1', '123', 'CASE WHEN 1=1 THEN 1 ELSE 0 END']);
+ expect(badCols).toEqual([
+ 'COUNT(*)',
+ '1',
+ '123',
+ 'CASE WHEN 1=1 THEN 1 ELSE 0 END',
+ ]);
const msgWrapper = shallow(wrapper.instance().renderInvalidColumnMessage());
expect(msgWrapper.find('div')).toHaveLength(1);
@@ -175,11 +180,14 @@ describe('ExploreResultsButton', () => {
fetchMock.post(visualizeEndpoint, visualizationPayload);
beforeEach(() => {
- sinon
- .stub(exploreUtils, 'getExploreUrlAndPayload')
- .callsFake(() => ({ url: 'mockURL', payload: { datasource: '107__table' } }));
+ sinon.stub(exploreUtils, 'getExploreUrlAndPayload').callsFake(() => ({
+ url: 'mockURL',
+ payload: { datasource: '107__table' },
+ }));
sinon.spy(exploreUtils, 'exportChart');
- sinon.stub(wrapper.instance(), 'buildVizOptions').callsFake(() => mockOptions);
+ sinon
+ .stub(wrapper.instance(), 'buildVizOptions')
+ .callsFake(() => mockOptions);
});
afterEach(() => {
exploreUtils.getExploreUrlAndPayload.restore();
@@ -188,7 +196,7 @@ describe('ExploreResultsButton', () => {
fetchMock.reset();
});
- it('should build request with correct args', (done) => {
+ it('should build request with correct args', done => {
wrapper.instance().visualize();
setTimeout(() => {
@@ -196,7 +204,7 @@ describe('ExploreResultsButton', () => {
expect(calls).toHaveLength(1);
const formData = calls[0][1].body;
- Object.keys(mockOptions).forEach((key) => {
+ Object.keys(mockOptions).forEach(key => {
// eslint-disable-next-line no-unused-expressions
expect(formData.get(key)).toBeDefined();
});
@@ -205,7 +213,7 @@ describe('ExploreResultsButton', () => {
});
});
- it('should export chart and add an info toast', (done) => {
+ it('should export chart and add an info toast', done => {
const infoToastSpy = sinon.spy();
const datasourceSpy = sinon.stub();
@@ -223,13 +231,15 @@ describe('ExploreResultsButton', () => {
setTimeout(() => {
expect(datasourceSpy.callCount).toBe(1);
expect(exploreUtils.exportChart.callCount).toBe(1);
- expect(exploreUtils.exportChart.getCall(0).args[0].datasource).toBe('107__table');
+ expect(exploreUtils.exportChart.getCall(0).args[0].datasource).toBe(
+ '107__table',
+ );
expect(infoToastSpy.callCount).toBe(1);
done();
});
});
- it('should add error toast', (done) => {
+ it('should add error toast', done => {
const dangerToastSpy = sinon.stub(actions, 'addDangerToast');
const datasourceSpy = sinon.stub();
diff --git a/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx b/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx
index b75f7ee3376..db8794a09dd 100644
--- a/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/HighlightedSql_spec.jsx
@@ -23,9 +23,9 @@ import { mount, shallow } from 'enzyme';
import HighlightedSql from '../../../src/SqlLab/components/HighlightedSql';
import ModalTrigger from '../../../src/components/ModalTrigger';
-
describe('HighlightedSql', () => {
- const sql = "SELECT * FROM test WHERE something='fkldasjfklajdslfkjadlskfjkldasjfkladsjfkdjsa'";
+ const sql =
+ "SELECT * FROM test WHERE something='fkldasjfklajdslfkjadlskfjkldasjfkladsjfkdjsa'";
it('renders with props', () => {
expect(React.isValidElement( )).toBe(true);
});
@@ -39,7 +39,13 @@ describe('HighlightedSql', () => {
});
it('renders two SyntaxHighlighter in modal', () => {
const wrapper = mount(
- );
+ ,
+ );
const pre = wrapper.find('pre');
expect(pre).toHaveLength(1);
pre.simulate('click');
diff --git a/superset/assets/spec/javascripts/sqllab/LimitControl_spec.jsx b/superset/assets/spec/javascripts/sqllab/LimitControl_spec.jsx
index 5e8d743cfbc..c42126b163a 100644
--- a/superset/assets/spec/javascripts/sqllab/LimitControl_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/LimitControl_spec.jsx
@@ -36,7 +36,9 @@ describe('LimitControl', () => {
wrapper = shallow(factory(defaultProps));
});
it('is a valid element', () => {
- expect(React.isValidElement( )).toEqual(true);
+ expect(React.isValidElement( )).toEqual(
+ true,
+ );
});
it('renders a Label', () => {
expect(wrapper.find(Label)).toHaveLength(1);
@@ -45,37 +47,68 @@ describe('LimitControl', () => {
const value = 100;
wrapper = shallow(factory({ ...defaultProps, value }));
expect(wrapper.state().textValue).toEqual(value.toString());
- wrapper.find(Label).first().simulate('click');
+ wrapper
+ .find(Label)
+ .first()
+ .simulate('click');
expect(wrapper.state().showOverlay).toBe(true);
- expect(wrapper.find(ControlHeader).props().validationErrors).toHaveLength(0);
+ expect(wrapper.find(ControlHeader).props().validationErrors).toHaveLength(
+ 0,
+ );
});
it('handles invalid value', () => {
- wrapper.find(Label).first().simulate('click');
+ wrapper
+ .find(Label)
+ .first()
+ .simulate('click');
wrapper.setState({ textValue: 'invalid' });
- expect(wrapper.find(ControlHeader).props().validationErrors).toHaveLength(1);
+ expect(wrapper.find(ControlHeader).props().validationErrors).toHaveLength(
+ 1,
+ );
});
it('handles negative value', () => {
- wrapper.find(Label).first().simulate('click');
+ wrapper
+ .find(Label)
+ .first()
+ .simulate('click');
wrapper.setState({ textValue: '-1' });
- expect(wrapper.find(ControlHeader).props().validationErrors).toHaveLength(1);
+ expect(wrapper.find(ControlHeader).props().validationErrors).toHaveLength(
+ 1,
+ );
});
it('handles value above max row', () => {
- wrapper.find(Label).first().simulate('click');
+ wrapper
+ .find(Label)
+ .first()
+ .simulate('click');
wrapper.setState({ textValue: (defaultProps.maxRow + 1).toString() });
- expect(wrapper.find(ControlHeader).props().validationErrors).toHaveLength(1);
+ expect(wrapper.find(ControlHeader).props().validationErrors).toHaveLength(
+ 1,
+ );
});
it('opens and closes', () => {
- wrapper.find(Label).first().simulate('click');
+ wrapper
+ .find(Label)
+ .first()
+ .simulate('click');
expect(wrapper.state().showOverlay).toBe(true);
- wrapper.find('.ok').first().simulate('click');
+ wrapper
+ .find('.ok')
+ .first()
+ .simulate('click');
expect(wrapper.state().showOverlay).toBe(false);
});
it('resets and closes', () => {
const value = 100;
wrapper = shallow(factory({ ...defaultProps, value }));
- wrapper.find(Label).first().simulate('click');
+ wrapper
+ .find(Label)
+ .first()
+ .simulate('click');
expect(wrapper.state().textValue).toEqual(value.toString());
wrapper.find('.reset').simulate('click');
- expect(wrapper.state().textValue).toEqual(defaultProps.defaultQueryLimit.toString());
+ expect(wrapper.state().textValue).toEqual(
+ defaultProps.defaultQueryLimit.toString(),
+ );
});
});
diff --git a/superset/assets/spec/javascripts/sqllab/Link_spec.jsx b/superset/assets/spec/javascripts/sqllab/Link_spec.jsx
index 89116be1cf4..2df2eb39c6e 100644
--- a/superset/assets/spec/javascripts/sqllab/Link_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/Link_spec.jsx
@@ -30,12 +30,10 @@ describe('Link', () => {
expect(React.isValidElement( TEST)).toBe(true);
});
it('renders with props', () => {
- expect(
- React.isValidElement( TEST),
- ).toBe(true);
+ expect(React.isValidElement( TEST)).toBe(true);
});
it('renders an anchor tag', () => {
- const wrapper = shallow( TEST);
+ const wrapper = shallow( TEST);
expect(wrapper.find('a')).toHaveLength(1);
});
});
diff --git a/superset/assets/spec/javascripts/sqllab/QueryAutoRefresh_spec.jsx b/superset/assets/spec/javascripts/sqllab/QueryAutoRefresh_spec.jsx
index 527ecd68098..77ac0a29373 100644
--- a/superset/assets/spec/javascripts/sqllab/QueryAutoRefresh_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/QueryAutoRefresh_spec.jsx
@@ -37,14 +37,13 @@ describe('QueryAutoRefresh', () => {
const state = {
...initialState,
sqlLab,
-
};
const store = mockStore(state);
- const getWrapper = () => (
+ const getWrapper = () =>
shallow( , {
context: { store },
- }).dive());
+ }).dive();
let wrapper;
diff --git a/superset/assets/spec/javascripts/sqllab/QuerySearch_spec.jsx b/superset/assets/spec/javascripts/sqllab/QuerySearch_spec.jsx
index dca3d9972c5..b04a47e1712 100644
--- a/superset/assets/spec/javascripts/sqllab/QuerySearch_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/QuerySearch_spec.jsx
@@ -31,9 +31,7 @@ describe('QuerySearch', () => {
height: 0,
};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
let wrapper;
beforeEach(() => {
@@ -45,19 +43,18 @@ describe('QuerySearch', () => {
});
it('updates fromTime on user selects from time', () => {
- wrapper.find('[name="select-from"]')
- .simulate('change', { value: 0 });
+ wrapper.find('[name="select-from"]').simulate('change', { value: 0 });
expect(wrapper.state().from).toBe(0);
});
it('updates toTime on user selects to time', () => {
- wrapper.find('[name="select-to"]')
- .simulate('change', { value: 0 });
+ wrapper.find('[name="select-to"]').simulate('change', { value: 0 });
expect(wrapper.state().to).toBe(0);
});
it('updates status on user selects status', () => {
- wrapper.find('[name="select-status"]')
+ wrapper
+ .find('[name="select-status"]')
.simulate('change', { value: 'success' });
expect(wrapper.state().status).toBe('success');
});
diff --git a/superset/assets/spec/javascripts/sqllab/QueryStateLabel_spec.jsx b/superset/assets/spec/javascripts/sqllab/QueryStateLabel_spec.jsx
index 5ff8f975640..4c5e15766ca 100644
--- a/superset/assets/spec/javascripts/sqllab/QueryStateLabel_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/QueryStateLabel_spec.jsx
@@ -29,9 +29,9 @@ describe('SavedQuery', () => {
},
};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('has an Overlay and a Popover', () => {
const wrapper = shallow( );
diff --git a/superset/assets/spec/javascripts/sqllab/QueryTable_spec.jsx b/superset/assets/spec/javascripts/sqllab/QueryTable_spec.jsx
index c48612cd05f..7f38ceb7275 100644
--- a/superset/assets/spec/javascripts/sqllab/QueryTable_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/QueryTable_spec.jsx
@@ -31,14 +31,23 @@ describe('QueryTable', () => {
expect(React.isValidElement( )).toBe(true);
});
it('is valid with props', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders a proper table', () => {
const wrapper = shallow( );
expect(wrapper.find(Table)).toHaveLength(1);
- expect(wrapper.find(Table).shallow().find('table')).toHaveLength(1);
- expect(wrapper.find(Table).shallow().find('table').find('Tr')).toHaveLength(2);
+ expect(
+ wrapper
+ .find(Table)
+ .shallow()
+ .find('table'),
+ ).toHaveLength(1);
+ expect(
+ wrapper
+ .find(Table)
+ .shallow()
+ .find('table')
+ .find('Tr'),
+ ).toHaveLength(2);
});
});
diff --git a/superset/assets/spec/javascripts/sqllab/ResultSet_spec.jsx b/superset/assets/spec/javascripts/sqllab/ResultSet_spec.jsx
index 8aa00a9a989..803083ef209 100644
--- a/superset/assets/spec/javascripts/sqllab/ResultSet_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/ResultSet_spec.jsx
@@ -102,13 +102,16 @@ describe('ResultSet', () => {
wrapper.setProps({ query: emptyResults });
expect(wrapper.find(FilterableTable)).toHaveLength(0);
expect(wrapper.find(Alert)).toHaveLength(1);
- expect(wrapper.find(Alert).shallow().text()).toBe('The query returned no data');
+ expect(
+ wrapper
+ .find(Alert)
+ .shallow()
+ .text(),
+ ).toBe('The query returned no data');
});
it('should render cached query', () => {
const wrapper = shallow( );
- const cachedData = [
- { col1: 'a', col2: 'b' },
- ];
+ const cachedData = [{ col1: 'a', col2: 'b' }];
wrapper.setState({ data: cachedData });
const filterableTable = wrapper.find(FilterableTable);
expect(filterableTable.props().data).toBe(cachedData);
diff --git a/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx b/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx
index 46c215ceca1..508558f84af 100644
--- a/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/SaveQuery_spec.jsx
@@ -35,14 +35,10 @@ describe('SavedQuery', () => {
animation: false,
};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('is valid with props', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('has a ModalTrigger', () => {
const wrapper = shallow( );
@@ -63,7 +59,10 @@ describe('SavedQuery', () => {
const wrapper = shallow( );
const modal = shallow(wrapper.instance().renderModalBody());
expect(modal.find(Button)).toHaveLength(2);
- modal.find(Button).at(0).simulate('click');
+ modal
+ .find(Button)
+ .at(0)
+ .simulate('click');
expect(saveSpy.calledOnce).toBe(true);
});
it('has an update button if this is an existing query', () => {
@@ -78,7 +77,10 @@ describe('SavedQuery', () => {
const wrapper = shallow( );
const modal = shallow(wrapper.instance().renderModalBody());
expect(modal.find(Button)).toHaveLength(3);
- modal.find(Button).at(0).simulate('click');
+ modal
+ .find(Button)
+ .at(0)
+ .simulate('click');
expect(updateSpy.calledOnce).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/sqllab/ShareSqlLabQuery_spec.jsx b/superset/assets/spec/javascripts/sqllab/ShareSqlLabQuery_spec.jsx
index a6c7de9e293..c17295dfc1a 100644
--- a/superset/assets/spec/javascripts/sqllab/ShareSqlLabQuery_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/ShareSqlLabQuery_spec.jsx
@@ -54,9 +54,12 @@ describe('ShareSqlLabQuery', () => {
};
function setup(overrideProps) {
- const wrapper = shallow( , {
- context: { store },
- }).dive(); // wrapped in withToasts HOC
+ const wrapper = shallow(
+ ,
+ {
+ context: { store },
+ },
+ ).dive(); // wrapped in withToasts HOC
return wrapper;
}
@@ -80,7 +83,9 @@ describe('ShareSqlLabQuery', () => {
return instance.getCopyUrl().then(() => {
expect(storeQuerySpy.mock.calls).toHaveLength(1);
expect(fetchMock.calls(storeQueryUrl)).toHaveLength(1);
- expect(storeQuerySpy.mock.calls[0][0]).toMatchObject(defaultProps.queryEditor);
+ expect(storeQuerySpy.mock.calls[0][0]).toMatchObject(
+ defaultProps.queryEditor,
+ );
expect(instance.state.shortUrl).toContain(storeQueryMockId);
return Promise.resolve();
diff --git a/superset/assets/spec/javascripts/sqllab/SouthPane_spec.jsx b/superset/assets/spec/javascripts/sqllab/SouthPane_spec.jsx
index b67b2e6729e..914ce8f8ecd 100644
--- a/superset/assets/spec/javascripts/sqllab/SouthPane_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/SouthPane_spec.jsx
@@ -24,7 +24,9 @@ import { shallow } from 'enzyme';
import { STATUS_OPTIONS } from '../../../src/SqlLab/constants';
import { initialState } from './fixtures';
-import SouthPaneContainer, { SouthPane } from '../../../src/SqlLab/components/SouthPane';
+import SouthPaneContainer, {
+ SouthPane,
+} from '../../../src/SqlLab/components/SouthPane';
import ResultSet from '../../../src/SqlLab/components/ResultSet';
describe('SouthPane', () => {
@@ -34,10 +36,38 @@ describe('SouthPane', () => {
const mockedProps = {
editorQueries: [
- { cached: false, changedOn: Date.now(), db: 'main', dbId: 1, id: 'LCly_kkIN', startDttm: Date.now() },
- { cached: false, changedOn: 1559238500401, db: 'main', dbId: 1, id: 'lXJa7F9_r', startDttm: 1559238500401 },
- { cached: false, changedOn: 1559238506925, db: 'main', dbId: 1, id: '2g2_iRFMl', startDttm: 1559238506925 },
- { cached: false, changedOn: 1559238516395, db: 'main', dbId: 1, id: 'erWdqEWPm', startDttm: 1559238516395 },
+ {
+ cached: false,
+ changedOn: Date.now(),
+ db: 'main',
+ dbId: 1,
+ id: 'LCly_kkIN',
+ startDttm: Date.now(),
+ },
+ {
+ cached: false,
+ changedOn: 1559238500401,
+ db: 'main',
+ dbId: 1,
+ id: 'lXJa7F9_r',
+ startDttm: 1559238500401,
+ },
+ {
+ cached: false,
+ changedOn: 1559238506925,
+ db: 'main',
+ dbId: 1,
+ id: '2g2_iRFMl',
+ startDttm: 1559238506925,
+ },
+ {
+ cached: false,
+ changedOn: 1559238516395,
+ db: 'main',
+ dbId: 1,
+ id: 'erWdqEWPm',
+ startDttm: 1559238516395,
+ },
],
latestQueryId: 'LCly_kkIN',
dataPreviewQueries: [],
@@ -48,25 +78,34 @@ describe('SouthPane', () => {
offline: false,
};
- const getWrapper = () => (
+ const getWrapper = () =>
shallow( , {
context: { store },
- }).dive());
+ }).dive();
let wrapper;
beforeAll(() => {
- jest.spyOn(SouthPane.prototype, 'getSouthPaneHeight').mockImplementation(() => 500);
+ jest
+ .spyOn(SouthPane.prototype, 'getSouthPaneHeight')
+ .mockImplementation(() => 500);
});
it('should render offline when the state is offline', () => {
wrapper = getWrapper();
wrapper.setProps({ offline: true });
- expect(wrapper.find('.m-r-3').render().text()).toBe(STATUS_OPTIONS.offline);
+ expect(
+ wrapper
+ .find('.m-r-3')
+ .render()
+ .text(),
+ ).toBe(STATUS_OPTIONS.offline);
});
it('should pass latest query down to ResultSet component', () => {
wrapper = getWrapper();
expect(wrapper.find(ResultSet)).toHaveLength(1);
- expect(wrapper.find(ResultSet).props().query.id).toEqual(mockedProps.latestQueryId);
+ expect(wrapper.find(ResultSet).props().query.id).toEqual(
+ mockedProps.latestQueryId,
+ );
});
});
diff --git a/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx b/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx
index 379bf6616bb..4f420a016c9 100644
--- a/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/SqlEditorLeftBar_spec.jsx
@@ -53,11 +53,12 @@ describe('SqlEditorLeftBar', () => {
});
it('is valid', () => {
- expect(React.isValidElement( )).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
it('renders a TableElement', () => {
expect(wrapper.find(TableElement)).toHaveLength(1);
});
-
});
diff --git a/superset/assets/spec/javascripts/sqllab/SqlEditor_spec.jsx b/superset/assets/spec/javascripts/sqllab/SqlEditor_spec.jsx
index dcf2609e885..cb1002f5de9 100644
--- a/superset/assets/spec/javascripts/sqllab/SqlEditor_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/SqlEditor_spec.jsx
@@ -40,7 +40,7 @@ describe('SqlEditor', () => {
queryEditor: initialState.sqlLab.queryEditors[0],
latestQuery: queries[0],
tables: [table],
- getHeight: () => ('100px'),
+ getHeight: () => '100px',
editorQueries: [],
dataPreviewQueries: [],
defaultQueryLimit: 1000,
@@ -48,13 +48,13 @@ describe('SqlEditor', () => {
};
beforeAll(() => {
- jest.spyOn(SqlEditor.prototype, 'getSqlEditorHeight').mockImplementation(() => MOCKED_SQL_EDITOR_HEIGHT);
+ jest
+ .spyOn(SqlEditor.prototype, 'getSqlEditorHeight')
+ .mockImplementation(() => MOCKED_SQL_EDITOR_HEIGHT);
});
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('render a SqlEditorLeftBar', () => {
const wrapper = shallow( );
@@ -70,21 +70,23 @@ describe('SqlEditor', () => {
});
it('does not overflow the editor window', () => {
const wrapper = shallow( );
- const totalSize = parseFloat(wrapper.find(AceEditorWrapper).props().height)
- + wrapper.find(SouthPane).props().height
- + SQL_TOOLBAR_HEIGHT
- + (SQL_EDITOR_GUTTER_MARGIN * 2)
- + SQL_EDITOR_GUTTER_HEIGHT;
+ const totalSize =
+ parseFloat(wrapper.find(AceEditorWrapper).props().height) +
+ wrapper.find(SouthPane).props().height +
+ SQL_TOOLBAR_HEIGHT +
+ SQL_EDITOR_GUTTER_MARGIN * 2 +
+ SQL_EDITOR_GUTTER_HEIGHT;
expect(totalSize).toEqual(MOCKED_SQL_EDITOR_HEIGHT);
});
it('does not overflow the editor window after resizing', () => {
const wrapper = shallow( );
wrapper.setState({ height: 450 });
- const totalSize = parseFloat(wrapper.find(AceEditorWrapper).props().height)
- + wrapper.find(SouthPane).props().height
- + SQL_TOOLBAR_HEIGHT
- + (SQL_EDITOR_GUTTER_MARGIN * 2)
- + SQL_EDITOR_GUTTER_HEIGHT;
+ const totalSize =
+ parseFloat(wrapper.find(AceEditorWrapper).props().height) +
+ wrapper.find(SouthPane).props().height +
+ SQL_TOOLBAR_HEIGHT +
+ SQL_EDITOR_GUTTER_MARGIN * 2 +
+ SQL_EDITOR_GUTTER_HEIGHT;
expect(totalSize).toEqual(450);
});
it('render a LimitControl with default limit', () => {
@@ -99,6 +101,8 @@ describe('SqlEditor', () => {
const updatedProps = { ...mockedProps, queryEditor };
const wrapper = shallow( );
expect(wrapper.find(LimitControl)).toHaveLength(1);
- expect(wrapper.find(LimitControl).props().value).toEqual(queryEditor.queryLimit);
+ expect(wrapper.find(LimitControl).props().value).toEqual(
+ queryEditor.queryLimit,
+ );
});
});
diff --git a/superset/assets/spec/javascripts/sqllab/TabStatusIcon_spec.jsx b/superset/assets/spec/javascripts/sqllab/TabStatusIcon_spec.jsx
index 055aeb9b574..990143eeb6f 100644
--- a/superset/assets/spec/javascripts/sqllab/TabStatusIcon_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/TabStatusIcon_spec.jsx
@@ -24,7 +24,9 @@ import TabStatusIcon from '../../../src/SqlLab/components/TabStatusIcon';
function setup() {
const onClose = sinon.spy();
- const wrapper = shallow( );
+ const wrapper = shallow(
+ ,
+ );
return { wrapper, onClose };
}
diff --git a/superset/assets/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx b/superset/assets/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx
index 21e0ba331b1..eed1dd921c2 100644
--- a/superset/assets/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx
@@ -34,26 +34,27 @@ describe('TabbedSqlEditors', () => {
const mockStore = configureStore(middlewares);
const store = mockStore(initialState);
- const tabHistory = [
- 'dfsadfs',
- 'newEditorId',
+ const tabHistory = ['dfsadfs', 'newEditorId'];
+
+ const tables = [
+ Object.assign({}, table, {
+ dataPreviewQueryId: 'B1-VQU1zW',
+ queryEditorId: 'newEditorId',
+ }),
];
- const tables = [Object.assign({}, table, {
- dataPreviewQueryId: 'B1-VQU1zW',
- queryEditorId: 'newEditorId',
- })];
-
- const queryEditors = [{
- autorun: false,
- dbId: 1,
- id: 'newEditorId',
- latestQueryId: 'B1-VQU1zW',
- schema: null,
- selectedText: null,
- sql: 'SELECT ds...',
- title: 'Untitled Query',
- }];
+ const queryEditors = [
+ {
+ autorun: false,
+ dbId: 1,
+ id: 'newEditorId',
+ latestQueryId: 'B1-VQU1zW',
+ schema: null,
+ selectedText: null,
+ sql: 'SELECT ds...',
+ title: 'Untitled Query',
+ },
+ ];
const queries = {
'B1-VQU1zW': {
id: 'B1-VQU1zW',
@@ -69,21 +70,21 @@ describe('TabbedSqlEditors', () => {
queryEditors: initialState.sqlLab.queryEditors,
tabHistory: initialState.sqlLab.tabHistory,
editorHeight: '',
- getHeight: () => ('100px'),
+ getHeight: () => '100px',
database: {},
defaultQueryLimit: 1000,
maxRow: 100000,
};
- const getWrapper = () => (
+ const getWrapper = () =>
shallow( , {
context: { store },
- }).dive());
+ }).dive();
let wrapper;
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(
+ true,
+ );
});
describe('componentDidMount', () => {
let uriStub;
@@ -102,24 +103,36 @@ describe('TabbedSqlEditors', () => {
wrapper = mount( , {
context: { store },
});
- expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(true);
- expect(window.history.replaceState.getCall(0).args[2]).toBe('/superset/sqllab');
+ expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(
+ true,
+ );
+ expect(window.history.replaceState.getCall(0).args[2]).toBe(
+ '/superset/sqllab',
+ );
});
it('should handle savedQueryId', () => {
uriStub.returns({ savedQueryId: 1 });
wrapper = mount( , {
context: { store },
});
- expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(true);
- expect(window.history.replaceState.getCall(0).args[2]).toBe('/superset/sqllab');
+ expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(
+ true,
+ );
+ expect(window.history.replaceState.getCall(0).args[2]).toBe(
+ '/superset/sqllab',
+ );
});
it('should handle sql', () => {
uriStub.returns({ sql: 1, dbid: 1 });
wrapper = mount( , {
context: { store },
});
- expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(true);
- expect(window.history.replaceState.getCall(0).args[2]).toBe('/superset/sqllab');
+ expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(
+ true,
+ );
+ expect(window.history.replaceState.getCall(0).args[2]).toBe(
+ '/superset/sqllab',
+ );
});
});
describe('componentWillReceiveProps', () => {
@@ -133,17 +146,23 @@ describe('TabbedSqlEditors', () => {
spy.restore();
});
it('should update queriesArray and dataPreviewQueries', () => {
- expect(wrapper.state().queriesArray.slice(-1)[0]).toBe(queries['B1-VQU1zW']);
- expect(wrapper.state().dataPreviewQueries.slice(-1)[0]).toEqual(queries['B1-VQU1zW']);
+ expect(wrapper.state().queriesArray.slice(-1)[0]).toBe(
+ queries['B1-VQU1zW'],
+ );
+ expect(wrapper.state().dataPreviewQueries.slice(-1)[0]).toEqual(
+ queries['B1-VQU1zW'],
+ );
});
});
it('should rename Tab', () => {
- global.prompt = () => ('new title');
+ global.prompt = () => 'new title';
wrapper = getWrapper();
sinon.stub(wrapper.instance().props.actions, 'queryEditorSetTitle');
wrapper.instance().renameTab(queryEditors[0]);
- expect(wrapper.instance().props.actions.queryEditorSetTitle.getCall(0).args[1]).toBe('new title');
+ expect(
+ wrapper.instance().props.actions.queryEditorSetTitle.getCall(0).args[1],
+ ).toBe('new title');
delete global.prompt;
});
@@ -152,24 +171,27 @@ describe('TabbedSqlEditors', () => {
sinon.stub(wrapper.instance().props.actions, 'removeQueryEditor');
wrapper.instance().removeQueryEditor(queryEditors[0]);
- expect(wrapper.instance().props.actions.removeQueryEditor.getCall(0).args[0])
- .toBe(queryEditors[0]);
+ expect(
+ wrapper.instance().props.actions.removeQueryEditor.getCall(0).args[0],
+ ).toBe(queryEditors[0]);
});
it('should add new query editor', () => {
wrapper = getWrapper();
sinon.stub(wrapper.instance().props.actions, 'addQueryEditor');
wrapper.instance().newQueryEditor();
- expect(wrapper.instance().props.actions.addQueryEditor.getCall(0).args[0].title)
- .toContain('Untitled Query');
+ expect(
+ wrapper.instance().props.actions.addQueryEditor.getCall(0).args[0].title,
+ ).toContain('Untitled Query');
});
it('should duplicate query editor', () => {
wrapper = getWrapper();
sinon.stub(wrapper.instance().props.actions, 'cloneQueryToNewTab');
wrapper.instance().duplicateQueryEditor(queryEditors[0]);
- expect(wrapper.instance().props.actions.cloneQueryToNewTab.getCall(0).args[0])
- .toBe(queryEditors[0]);
+ expect(
+ wrapper.instance().props.actions.cloneQueryToNewTab.getCall(0).args[0],
+ ).toBe(queryEditors[0]);
});
it('should handle select', () => {
const mockEvent = {
@@ -186,7 +208,9 @@ describe('TabbedSqlEditors', () => {
// cannot switch to current tab, switchQueryEditor never gets called
wrapper.instance().handleSelect('dfsadfs', mockEvent);
- expect(wrapper.instance().props.actions.switchQueryEditor.callCount).toEqual(0);
+ expect(
+ wrapper.instance().props.actions.switchQueryEditor.callCount,
+ ).toEqual(0);
wrapper.instance().newQueryEditor.restore();
});
it('should render', () => {
@@ -194,7 +218,9 @@ describe('TabbedSqlEditors', () => {
wrapper.setState({ hideLeftBar: true });
const firstTab = wrapper.find(Tab).first();
- expect(firstTab.props().eventKey).toContain(initialState.sqlLab.queryEditors[0].id);
+ expect(firstTab.props().eventKey).toContain(
+ initialState.sqlLab.queryEditors[0].id,
+ );
expect(firstTab.find(SqlEditor)).toHaveLength(1);
const lastTab = wrapper.find(Tab).last();
@@ -202,8 +228,18 @@ describe('TabbedSqlEditors', () => {
});
it('should disable new tab when offline', () => {
wrapper = getWrapper();
- expect(wrapper.find(Tab).last().props().disabled).toBe(false);
+ expect(
+ wrapper
+ .find(Tab)
+ .last()
+ .props().disabled,
+ ).toBe(false);
wrapper.setProps({ offline: true });
- expect(wrapper.find(Tab).last().props().disabled).toBe(true);
+ expect(
+ wrapper
+ .find(Tab)
+ .last()
+ .props().disabled,
+ ).toBe(true);
});
});
diff --git a/superset/assets/spec/javascripts/sqllab/TableElement_spec.jsx b/superset/assets/spec/javascripts/sqllab/TableElement_spec.jsx
index c01d0660ef4..ae3bd627fd2 100644
--- a/superset/assets/spec/javascripts/sqllab/TableElement_spec.jsx
+++ b/superset/assets/spec/javascripts/sqllab/TableElement_spec.jsx
@@ -31,14 +31,10 @@ describe('TableElement', () => {
timeout: 0,
};
it('renders', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders with props', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('has 2 Link elements', () => {
const wrapper = shallow( );
@@ -54,10 +50,20 @@ describe('TableElement', () => {
it('sorts columns', () => {
const wrapper = shallow( );
expect(wrapper.state().sortColumns).toBe(false);
- expect(wrapper.find(ColumnElement).first().props().column.name).toBe('id');
+ expect(
+ wrapper
+ .find(ColumnElement)
+ .first()
+ .props().column.name,
+ ).toBe('id');
wrapper.find('.sort-cols').simulate('click');
expect(wrapper.state().sortColumns).toBe(true);
- expect(wrapper.find(ColumnElement).first().props().column.name).toBe('active');
+ expect(
+ wrapper
+ .find(ColumnElement)
+ .first()
+ .props().column.name,
+ ).toBe('active');
});
it('calls the collapseTable action', () => {
const wrapper = mount( );
diff --git a/superset/assets/spec/javascripts/sqllab/actions/sqlLab_spec.js b/superset/assets/spec/javascripts/sqllab/actions/sqlLab_spec.js
index 306a5f9777a..f8fab7579cf 100644
--- a/superset/assets/spec/javascripts/sqllab/actions/sqlLab_spec.js
+++ b/superset/assets/spec/javascripts/sqllab/actions/sqlLab_spec.js
@@ -78,7 +78,7 @@ describe('async actions', () => {
return store.dispatch(actions.saveQuery(query)).then(() => {
const call = fetchMock.calls(saveQueryEndpoint)[0];
const formData = call[1].body;
- Object.keys(query).forEach((key) => {
+ Object.keys(query).forEach(key => {
expect(formData.get(key)).toBeDefined();
});
});
@@ -111,7 +111,9 @@ describe('async actions', () => {
makeRequest().then(() => {
expect(fetchMock.calls(fetchQueryEndpoint)).toHaveLength(1);
expect(dispatch.callCount).toBe(2);
- expect(dispatch.getCall(1).lastArg.results.data.toString()).toBe(mockBigNumber);
+ expect(dispatch.getCall(1).lastArg.results.data.toString()).toBe(
+ mockBigNumber,
+ );
}));
it('calls querySuccess on fetch success', () => {
@@ -123,7 +125,9 @@ describe('async actions', () => {
actions.QUERY_SUCCESS,
];
return store.dispatch(actions.fetchQueryResults(query)).then(() => {
- expect(store.getActions().map(a => a.type)).toEqual(expectedActionTypes);
+ expect(store.getActions().map(a => a.type)).toEqual(
+ expectedActionTypes,
+ );
});
});
@@ -142,7 +146,9 @@ describe('async actions', () => {
actions.QUERY_FAILED,
];
return store.dispatch(actions.fetchQueryResults(query)).then(() => {
- expect(store.getActions().map(a => a.type)).toEqual(expectedActionTypes);
+ expect(store.getActions().map(a => a.type)).toEqual(
+ expectedActionTypes,
+ );
});
});
});
@@ -173,19 +179,20 @@ describe('async actions', () => {
makeRequest().then(() => {
expect(fetchMock.calls(runQueryEndpoint)).toHaveLength(1);
expect(dispatch.callCount).toBe(2);
- expect(dispatch.getCall(1).lastArg.results.data.toString()).toBe(mockBigNumber);
+ expect(dispatch.getCall(1).lastArg.results.data.toString()).toBe(
+ mockBigNumber,
+ );
}));
it('calls querySuccess on fetch success', () => {
expect.assertions(1);
const store = mockStore({});
- const expectedActionTypes = [
- actions.START_QUERY,
- actions.QUERY_SUCCESS,
- ];
+ const expectedActionTypes = [actions.START_QUERY, actions.QUERY_SUCCESS];
return store.dispatch(actions.runQuery(query)).then(() => {
- expect(store.getActions().map(a => a.type)).toEqual(expectedActionTypes);
+ expect(store.getActions().map(a => a.type)).toEqual(
+ expectedActionTypes,
+ );
});
});
@@ -199,12 +206,11 @@ describe('async actions', () => {
);
const store = mockStore({});
- const expectedActionTypes = [
- actions.START_QUERY,
- actions.QUERY_FAILED,
- ];
+ const expectedActionTypes = [actions.START_QUERY, actions.QUERY_FAILED];
return store.dispatch(actions.runQuery(query)).then(() => {
- expect(store.getActions().map(a => a.type)).toEqual(expectedActionTypes);
+ expect(store.getActions().map(a => a.type)).toEqual(
+ expectedActionTypes,
+ );
});
});
});
@@ -226,7 +232,6 @@ describe('async actions', () => {
});
});
-
it('calls stopQuery', () => {
expect.assertions(1);
@@ -265,22 +270,26 @@ describe('async actions', () => {
},
};
const store = mockStore(state);
- const expectedActions = [{
- type: actions.ADD_QUERY_EDITOR,
- queryEditor: {
- title: 'Copy of Dummy query editor',
- dbId: 1,
- schema: null,
- autorun: true,
- sql: 'SELECT * FROM something',
- queryLimit: undefined,
- maxRow: undefined,
- id: 'abcd',
+ const expectedActions = [
+ {
+ type: actions.ADD_QUERY_EDITOR,
+ queryEditor: {
+ title: 'Copy of Dummy query editor',
+ dbId: 1,
+ schema: null,
+ autorun: true,
+ sql: 'SELECT * FROM something',
+ queryLimit: undefined,
+ maxRow: undefined,
+ id: 'abcd',
+ },
},
- }];
- return store.dispatch(actions.cloneQueryToNewTab(query, true)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- });
+ ];
+ return store
+ .dispatch(actions.cloneQueryToNewTab(query, true))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
});
});
@@ -297,13 +306,17 @@ describe('async actions', () => {
expect.assertions(1);
const store = mockStore({});
- const expectedActions = [{
- type: actions.ADD_QUERY_EDITOR,
- queryEditor,
- }];
- return store.dispatch(actions.addQueryEditor(defaultQueryEditor)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- });
+ const expectedActions = [
+ {
+ type: actions.ADD_QUERY_EDITOR,
+ queryEditor,
+ },
+ ];
+ return store
+ .dispatch(actions.addQueryEditor(defaultQueryEditor))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ });
});
});
@@ -320,14 +333,18 @@ describe('async actions', () => {
const getTableMetadataEndpoint = 'glob:*/superset/table/*';
fetchMock.get(getTableMetadataEndpoint, {});
- const getExtraTableMetadataEndpoint = 'glob:*/superset/extra_table_metadata/*';
+ const getExtraTableMetadataEndpoint =
+ 'glob:*/superset/extra_table_metadata/*';
fetchMock.get(getExtraTableMetadataEndpoint, {});
let isFeatureEnabledMock;
beforeAll(() => {
- isFeatureEnabledMock = jest.spyOn(featureFlags, 'isFeatureEnabled')
- .mockImplementation(feature => feature === 'SQLLAB_BACKEND_PERSISTENCE');
+ isFeatureEnabledMock = jest
+ .spyOn(featureFlags, 'isFeatureEnabled')
+ .mockImplementation(
+ feature => feature === 'SQLLAB_BACKEND_PERSISTENCE',
+ );
});
afterAll(() => {
@@ -365,11 +382,9 @@ describe('async actions', () => {
query: { sqlEditorId: 'abcd' },
query_id: 'efgh',
};
- fetchMock.get(
- fetchQueryEndpoint,
- JSON.stringify(results),
- { overwriteRoutes: true },
- );
+ fetchMock.get(fetchQueryEndpoint, JSON.stringify(results), {
+ overwriteRoutes: true,
+ });
const store = mockStore({});
const expectedActions = [
{
@@ -419,10 +434,12 @@ describe('async actions', () => {
queryEditor,
},
];
- return store.dispatch(actions.setActiveQueryEditor(queryEditor)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
- });
+ return store
+ .dispatch(actions.setActiveQueryEditor(queryEditor))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
+ });
});
});
@@ -437,10 +454,12 @@ describe('async actions', () => {
queryEditor,
},
];
- return store.dispatch(actions.removeQueryEditor(queryEditor)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
- });
+ return store
+ .dispatch(actions.removeQueryEditor(queryEditor))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
+ });
});
});
@@ -457,10 +476,12 @@ describe('async actions', () => {
dbId,
},
];
- return store.dispatch(actions.queryEditorSetDb(queryEditor, dbId)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
- });
+ return store
+ .dispatch(actions.queryEditorSetDb(queryEditor, dbId))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
+ });
});
});
@@ -477,10 +498,12 @@ describe('async actions', () => {
schema,
},
];
- return store.dispatch(actions.queryEditorSetSchema(queryEditor, schema)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
- });
+ return store
+ .dispatch(actions.queryEditorSetSchema(queryEditor, schema))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
+ });
});
});
@@ -497,10 +520,12 @@ describe('async actions', () => {
autorun,
},
];
- return store.dispatch(actions.queryEditorSetAutorun(queryEditor, autorun)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
- });
+ return store
+ .dispatch(actions.queryEditorSetAutorun(queryEditor, autorun))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
+ });
});
});
@@ -517,10 +542,12 @@ describe('async actions', () => {
title,
},
];
- return store.dispatch(actions.queryEditorSetTitle(queryEditor, title)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
- });
+ return store
+ .dispatch(actions.queryEditorSetTitle(queryEditor, title))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
+ });
});
});
@@ -537,10 +564,12 @@ describe('async actions', () => {
sql,
},
];
- return store.dispatch(actions.queryEditorSetSql(queryEditor, sql)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
- });
+ return store
+ .dispatch(actions.queryEditorSetSql(queryEditor, sql))
+ .then(() => {
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
+ });
});
});
@@ -557,8 +586,8 @@ describe('async actions', () => {
queryLimit,
},
];
- return store.dispatch(
- actions.queryEditorSetQueryLimit(queryEditor, queryLimit))
+ return store
+ .dispatch(actions.queryEditorSetQueryLimit(queryEditor, queryLimit))
.then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
@@ -579,8 +608,10 @@ describe('async actions', () => {
templateParams,
},
];
- return store.dispatch(
- actions.queryEditorSetTemplateParams(queryEditor, templateParams))
+ return store
+ .dispatch(
+ actions.queryEditorSetTemplateParams(queryEditor, templateParams),
+ )
.then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(1);
@@ -597,30 +628,32 @@ describe('async actions', () => {
query: { sqlEditorId: 'null' },
query_id: 'efgh',
};
- fetchMock.post(
- runQueryEndpoint,
- JSON.stringify(results),
- { overwriteRoutes: true },
- );
+ fetchMock.post(runQueryEndpoint, JSON.stringify(results), {
+ overwriteRoutes: true,
+ });
const tableName = 'table';
const schemaName = 'schema';
const store = mockStore({});
const expectedActionTypes = [
- actions.MERGE_TABLE, // addTable
- actions.MERGE_TABLE, // getTableMetadata
- actions.START_QUERY, // runQuery (data preview)
- actions.MERGE_TABLE, // getTableExtendedMetadata
+ actions.MERGE_TABLE, // addTable
+ actions.MERGE_TABLE, // getTableMetadata
+ actions.START_QUERY, // runQuery (data preview)
+ actions.MERGE_TABLE, // getTableExtendedMetadata
actions.QUERY_SUCCESS, // querySuccess
- actions.MERGE_TABLE, // addTable
+ actions.MERGE_TABLE, // addTable
];
- return store.dispatch(
- actions.addTable(query, tableName, schemaName))
+ return store
+ .dispatch(actions.addTable(query, tableName, schemaName))
.then(() => {
- expect(store.getActions().map(a => a.type)).toEqual(expectedActionTypes);
+ expect(store.getActions().map(a => a.type)).toEqual(
+ expectedActionTypes,
+ );
expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
expect(fetchMock.calls(getTableMetadataEndpoint)).toHaveLength(1);
- expect(fetchMock.calls(getExtraTableMetadataEndpoint)).toHaveLength(1);
+ expect(fetchMock.calls(getExtraTableMetadataEndpoint)).toHaveLength(
+ 1,
+ );
// tab state is not updated, since the query is a data preview
expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(0);
@@ -641,9 +674,9 @@ describe('async actions', () => {
},
];
return store.dispatch(actions.expandTable(table)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
- });
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
+ });
});
});
@@ -660,9 +693,9 @@ describe('async actions', () => {
},
];
return store.dispatch(actions.collapseTable(table)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
- });
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
+ });
});
});
@@ -679,9 +712,9 @@ describe('async actions', () => {
},
];
return store.dispatch(actions.removeTable(table)).then(() => {
- expect(store.getActions()).toEqual(expectedActions);
- expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
- });
+ expect(store.getActions()).toEqual(expectedActions);
+ expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
+ });
});
});
@@ -694,11 +727,9 @@ describe('async actions', () => {
query: { sqlEditorId: 'null' },
query_id: 'efgh',
};
- fetchMock.post(
- runQueryEndpoint,
- JSON.stringify(results),
- { overwriteRoutes: true },
- );
+ fetchMock.post(runQueryEndpoint, JSON.stringify(results), {
+ overwriteRoutes: true,
+ });
const tables = [
{ id: 'one', dataPreviewQueryId: 'previewOne' },
@@ -744,8 +775,14 @@ describe('async actions', () => {
queryEditorId: '1',
},
];
- return store.dispatch(
- actions.migrateQueryEditorFromLocalStorage(queryEditor, tables, queries))
+ return store
+ .dispatch(
+ actions.migrateQueryEditorFromLocalStorage(
+ queryEditor,
+ tables,
+ queries,
+ ),
+ )
.then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(fetchMock.calls(updateTabStateEndpoint)).toHaveLength(3);
diff --git a/superset/assets/spec/javascripts/sqllab/fixtures.js b/superset/assets/spec/javascripts/sqllab/fixtures.js
index 30cff0b9dc4..cf9cba6677d 100644
--- a/superset/assets/spec/javascripts/sqllab/fixtures.js
+++ b/superset/assets/spec/javascripts/sqllab/fixtures.js
@@ -244,7 +244,10 @@ export const queries = [
type: 'STRING',
},
],
- data: [{ col1: 0, col2: 1 }, { col1: 2, col2: 3 }],
+ data: [
+ { col1: 0, col2: 1 },
+ { col1: 2, col2: 3 },
+ ],
},
},
{
diff --git a/superset/assets/spec/javascripts/sqllab/reducers/sqlLab_spec.js b/superset/assets/spec/javascripts/sqllab/reducers/sqlLab_spec.js
index d7aa1189573..87a0deb3213 100644
--- a/superset/assets/spec/javascripts/sqllab/reducers/sqlLab_spec.js
+++ b/superset/assets/spec/javascripts/sqllab/reducers/sqlLab_spec.js
@@ -61,7 +61,9 @@ describe('sqlLabReducer', () => {
queryEditor: defaultQueryEditor,
};
newState = sqlLabReducer(newState, setActiveQueryEditorAction);
- expect(newState.tabHistory[newState.tabHistory.length - 1]).toBe(defaultQueryEditor.id);
+ expect(newState.tabHistory[newState.tabHistory.length - 1]).toBe(
+ defaultQueryEditor.id,
+ );
});
it('should not fail while setting DB', () => {
const dbId = 9;
diff --git a/superset/assets/spec/javascripts/sqllab/utils/emptyQueryResults_spec.js b/superset/assets/spec/javascripts/sqllab/utils/emptyQueryResults_spec.js
index 44806272f33..b380607fa81 100644
--- a/superset/assets/spec/javascripts/sqllab/utils/emptyQueryResults_spec.js
+++ b/superset/assets/spec/javascripts/sqllab/utils/emptyQueryResults_spec.js
@@ -16,14 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { emptyQueryResults, clearQueryEditors } from '../../../../src/SqlLab/utils/reduxStateToLocalStorageHelper';
+import {
+ emptyQueryResults,
+ clearQueryEditors,
+} from '../../../../src/SqlLab/utils/reduxStateToLocalStorageHelper';
import { LOCALSTORAGE_MAX_QUERY_AGE_MS } from '../../../../src/SqlLab/constants';
import { queries, defaultQueryEditor } from '../fixtures';
describe('reduxStateToLocalStorageHelper', () => {
const queriesObj = {};
beforeEach(() => {
- queries.forEach((q) => {
+ queries.forEach(q => {
queriesObj[q.id] = q;
});
});
@@ -32,7 +35,9 @@ describe('reduxStateToLocalStorageHelper', () => {
// make sure sample data contains old query
const oldQuery = queries[0];
const { id, startDttm } = oldQuery;
- expect(Date.now() - startDttm).toBeGreaterThan(LOCALSTORAGE_MAX_QUERY_AGE_MS);
+ expect(Date.now() - startDttm).toBeGreaterThan(
+ LOCALSTORAGE_MAX_QUERY_AGE_MS,
+ );
expect(Object.keys(oldQuery.results)).toContain('data');
const emptiedQuery = emptyQueryResults(queriesObj);
diff --git a/superset/assets/spec/javascripts/utils/common_spec.jsx b/superset/assets/spec/javascripts/utils/common_spec.jsx
index c9c34bbeac8..f1a1653fc4e 100644
--- a/superset/assets/spec/javascripts/utils/common_spec.jsx
+++ b/superset/assets/spec/javascripts/utils/common_spec.jsx
@@ -16,15 +16,27 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { optionFromValue, prepareCopyToClipboardTabularData } from '../../../src/utils/common';
+import {
+ optionFromValue,
+ prepareCopyToClipboardTabularData,
+} from '../../../src/utils/common';
describe('utils/common', () => {
describe('optionFromValue', () => {
it('converts values as expected', () => {
- expect(optionFromValue(false)).toEqual({ value: false, label: '' });
+ expect(optionFromValue(false)).toEqual({
+ value: false,
+ label: '',
+ });
expect(optionFromValue(true)).toEqual({ value: true, label: '' });
- expect(optionFromValue(null)).toEqual({ value: '', label: '' });
- expect(optionFromValue('')).toEqual({ value: '', label: '' });
+ expect(optionFromValue(null)).toEqual({
+ value: '',
+ label: '',
+ });
+ expect(optionFromValue('')).toEqual({
+ value: '',
+ label: '',
+ });
expect(optionFromValue('foo')).toEqual({ value: 'foo', label: 'foo' });
expect(optionFromValue(5)).toEqual({ value: 5, label: '5' });
});
@@ -36,10 +48,12 @@ describe('utils/common', () => {
});
it('converts non empty array', () => {
const array = [
- { column1: 'lorem', column2: 'ipsum' },
- { column1: 'dolor', column2: 'sit', column3: 'amet' },
+ { column1: 'lorem', column2: 'ipsum' },
+ { column1: 'dolor', column2: 'sit', column3: 'amet' },
];
- expect(prepareCopyToClipboardTabularData(array)).toEqual('lorem\tipsum\ndolor\tsit\tamet\n');
+ expect(prepareCopyToClipboardTabularData(array)).toEqual(
+ 'lorem\tipsum\ndolor\tsit\tamet\n',
+ );
});
});
});
diff --git a/superset/assets/spec/javascripts/utils/getClientErrorObject_spec.js b/superset/assets/spec/javascripts/utils/getClientErrorObject_spec.js
index 7bb739fc8de..647f4e8f8d7 100644
--- a/superset/assets/spec/javascripts/utils/getClientErrorObject_spec.js
+++ b/superset/assets/spec/javascripts/utils/getClientErrorObject_spec.js
@@ -27,7 +27,7 @@ describe('getClientErrorObject()', () => {
it('Returns a Promise that resolves to an object with an error key', () => {
const error = 'error';
- return getClientErrorObject(error).then((errorObj) => {
+ return getClientErrorObject(error).then(errorObj => {
expect(errorObj).toMatchObject({ error });
});
});
@@ -36,15 +36,17 @@ describe('getClientErrorObject()', () => {
const jsonError = { something: 'something', error: 'Error message' };
const jsonErrorString = JSON.stringify(jsonError);
- return getClientErrorObject(new Response(jsonErrorString)).then((errorObj) => {
- expect(errorObj).toMatchObject(jsonError);
- });
+ return getClientErrorObject(new Response(jsonErrorString)).then(
+ errorObj => {
+ expect(errorObj).toMatchObject(jsonError);
+ },
+ );
});
it('Handles Response that can be parsed as text', () => {
const textError = 'Hello I am a text error';
- return getClientErrorObject(new Response(textError)).then((errorObj) => {
+ return getClientErrorObject(new Response(textError)).then(errorObj => {
expect(errorObj).toMatchObject({ error: textError });
});
});
@@ -52,7 +54,7 @@ describe('getClientErrorObject()', () => {
it('Handles plain text as input', () => {
const error = 'error';
- return getClientErrorObject(error).then((errorObj) => {
+ return getClientErrorObject(error).then(errorObj => {
expect(errorObj).toMatchObject({ error });
});
});
diff --git a/superset/assets/spec/javascripts/welcome/DashboardTable_spec.jsx b/superset/assets/spec/javascripts/welcome/DashboardTable_spec.jsx
index e989f9a207a..42f2dd7d782 100644
--- a/superset/assets/spec/javascripts/welcome/DashboardTable_spec.jsx
+++ b/superset/assets/spec/javascripts/welcome/DashboardTable_spec.jsx
@@ -31,9 +31,7 @@ const mockStore = configureStore([thunk]);
const store = mockStore({});
const dashboardsEndpoint = 'glob:*/dashboardasync/api/read*';
-const mockDashboards = [
- { id: 1, url: 'url', dashboard_title: 'title' },
-];
+const mockDashboards = [{ id: 1, url: 'url', dashboard_title: 'title' }];
fetchMock.get(dashboardsEndpoint, { result: mockDashboards });
@@ -50,7 +48,7 @@ describe('DashboardTable', () => {
expect(wrapper.find(Loading)).toHaveLength(1);
});
- it('fetches dashboards and renders a Table', (done) => {
+ it('fetches dashboards and renders a Table', done => {
const wrapper = setup();
setTimeout(() => {
diff --git a/superset/assets/spec/javascripts/welcome/Welcome_spec.jsx b/superset/assets/spec/javascripts/welcome/Welcome_spec.jsx
index 8a18b299955..67eb413f755 100644
--- a/superset/assets/spec/javascripts/welcome/Welcome_spec.jsx
+++ b/superset/assets/spec/javascripts/welcome/Welcome_spec.jsx
@@ -25,9 +25,7 @@ import Welcome from '../../../src/welcome/Welcome';
describe('Welcome', () => {
const mockedProps = {};
it('is valid', () => {
- expect(
- React.isValidElement( ),
- ).toBe(true);
+ expect(React.isValidElement( )).toBe(true);
});
it('renders 4 Tab, Panel, and Row components', () => {
const wrapper = shallow( );
diff --git a/superset/assets/src/CRUD/CollectionTable.jsx b/superset/assets/src/CRUD/CollectionTable.jsx
index 00b3a0b2b91..2612646bacc 100644
--- a/superset/assets/src/CRUD/CollectionTable.jsx
+++ b/superset/assets/src/CRUD/CollectionTable.jsx
@@ -49,10 +49,7 @@ const defaultProps = {
expandFieldset: null,
extraButtons: null,
};
-const Frame = props => (
-
- {props.children}
-
);
+const Frame = props => {props.children}
;
Frame.propTypes = { children: PropTypes.node };
function createKeyedCollection(arr) {
@@ -61,7 +58,7 @@ function createKeyedCollection(arr) {
id: o.id || shortid.generate(),
}));
const map = {};
- newArr.forEach((o) => {
+ newArr.forEach(o => {
map[o.id] = o;
});
return map;
@@ -97,7 +94,6 @@ export default class CRUDCollection extends React.PureComponent {
[col]: val,
},
});
-
}
onAddItem() {
let newItem = this.props.itemGenerator();
@@ -135,7 +131,9 @@ export default class CRUDCollection extends React.PureComponent {
}
effectiveTableColumns() {
const { tableColumns, allowDeletes, expandFieldset } = this.props;
- const cols = allowDeletes ? tableColumns.concat(['__actions']) : tableColumns;
+ const cols = allowDeletes
+ ? tableColumns.concat(['__actions'])
+ : tableColumns;
return expandFieldset ? ['__expand'].concat(cols) : cols;
}
toggleExpand(id) {
@@ -153,7 +151,9 @@ export default class CRUDCollection extends React.PureComponent {
{this.props.expandFieldset && }
- {cols.map(col => {this.getLabel(col)} )}
+ {cols.map(col => (
+ {this.getLabel(col)}
+ ))}
{this.props.allowDeletes && }
@@ -161,7 +161,11 @@ export default class CRUDCollection extends React.PureComponent {
}
renderExpandableSection(item) {
const propsGenerator = () => ({ item, onChange: this.onFieldsetChange });
- return recurseReactClone(this.props.expandFieldset, Fieldset, propsGenerator);
+ return recurseReactClone(
+ this.props.expandFieldset,
+ Fieldset,
+ propsGenerator,
+ );
}
renderCell(record, col) {
const renderer = this.props.itemRenderers[col];
@@ -172,20 +176,26 @@ export default class CRUDCollection extends React.PureComponent {
renderItem(record) {
const { tableColumns, allowDeletes, expandFieldset } = this.props;
/* eslint-disable no-underscore-dangle */
- const isExpanded = !!this.state.expandedColumns[record.id] || record.__expanded;
+ const isExpanded =
+ !!this.state.expandedColumns[record.id] || record.__expanded;
let tds = [];
if (expandFieldset) {
tds.push(
- );
+ ,
+ );
}
- tds = tds.concat(tableColumns.map(col => (
- {this.renderCell(record, col)}
- )));
+ tds = tds.concat(
+ tableColumns.map(col => (
+ {this.renderCell(record, col)}
+ )),
+ );
if (allowDeletes) {
tds.push(
@@ -193,43 +203,57 @@ export default class CRUDCollection extends React.PureComponent {
className="fa fa-close text-primary pointer"
onClick={this.deleteItem.bind(this, record.id)}
/>
- );
+ ,
+ );
}
- const trs = [{tds} ];
+ const trs = [
+
+ {tds}
+ ,
+ ];
if (isExpanded) {
trs.push(
-
-
- {this.renderExpandableSection(record)}
-
+
+ {this.renderExpandableSection(record)}
- );
+ ,
+ );
}
return trs;
}
renderEmptyCell() {
- return {this.props.emptyMessage} ;
+ return (
+
+ {this.props.emptyMessage}
+
+ );
}
renderTableBody() {
- const data = Object.keys(this.state.collection).map(k => this.state.collection[k]);
- const content = data.length ? data.map(d => this.renderItem(d)) : this.renderEmptyCell();
+ const data = Object.keys(this.state.collection).map(
+ k => this.state.collection[k],
+ );
+ const content = data.length
+ ? data.map(d => this.renderItem(d))
+ : this.renderEmptyCell();
return {content} ;
}
render() {
return (
-
+
{this.renderHeaderRow()}
{this.renderTableBody()}
- {this.props.allowAddItem &&
+ {this.props.allowAddItem && (
{t('Add Item')}
- }
+
+ )}
{this.props.extraButtons}
diff --git a/superset/assets/src/CRUD/Field.jsx b/superset/assets/src/CRUD/Field.jsx
index 902b68199be..1425085ed80 100644
--- a/superset/assets/src/CRUD/Field.jsx
+++ b/superset/assets/src/CRUD/Field.jsx
@@ -19,7 +19,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
- FormGroup, ControlLabel, HelpBlock, FormControl, OverlayTrigger, Tooltip,
+ FormGroup,
+ ControlLabel,
+ HelpBlock,
+ FormControl,
+ OverlayTrigger,
+ Tooltip,
} from 'react-bootstrap';
import './crud.less';
@@ -50,29 +55,30 @@ export default class Field extends React.PureComponent {
}
render() {
const { compact, value, label, control, descr, fieldKey } = this.props;
- const hookedControl = React.cloneElement(control, { value, onChange: this.onChange });
+ const hookedControl = React.cloneElement(control, {
+ value,
+ onChange: this.onChange,
+ });
return (
-
+
{label || fieldKey}
- {compact && descr &&
+ {compact && descr && (
{descr}
- }
+
+ {descr}
+
+ }
>
- }
+ )}
{hookedControl}
- {!compact && descr &&
- {descr}
- }
+ {!compact && descr && {descr} }
);
}
diff --git a/superset/assets/src/CRUD/Fieldset.jsx b/superset/assets/src/CRUD/Fieldset.jsx
index 75a04c6b9c9..f73cd79289b 100644
--- a/superset/assets/src/CRUD/Fieldset.jsx
+++ b/superset/assets/src/CRUD/Fieldset.jsx
@@ -55,9 +55,7 @@ export default class Fieldset extends React.PureComponent {
});
return (
);
diff --git a/superset/assets/src/CRUD/crud.less b/superset/assets/src/CRUD/crud.less
index 478e08f8f4d..b0cb324bf54 100644
--- a/superset/assets/src/CRUD/crud.less
+++ b/superset/assets/src/CRUD/crud.less
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../stylesheets/less/variables.less";
+@import '../../stylesheets/less/variables.less';
.CRUD {
.text-right {
diff --git a/superset/assets/src/CRUD/utils.js b/superset/assets/src/CRUD/utils.js
index 70b0988d11b..2fdcb6ff2b6 100644
--- a/superset/assets/src/CRUD/utils.js
+++ b/superset/assets/src/CRUD/utils.js
@@ -23,14 +23,18 @@ export function recurseReactClone(children, type, propExtender) {
* Clones a React component's children, and injects new props
* where the type specified is matched.
*/
- return React.Children.map(children, (child) => {
+ return React.Children.map(children, child => {
let newChild = child;
if (child && child.type.name === type.name) {
newChild = React.cloneElement(child, propExtender(child));
}
if (newChild && newChild.props.children) {
newChild = React.cloneElement(newChild, {
- children: recurseReactClone(newChild.props.children, type, propExtender),
+ children: recurseReactClone(
+ newChild.props.children,
+ type,
+ propExtender,
+ ),
});
}
return newChild;
diff --git a/superset/assets/src/SqlLab/App.jsx b/superset/assets/src/SqlLab/App.jsx
index 058e17dd950..c13314b560a 100644
--- a/superset/assets/src/SqlLab/App.jsx
+++ b/superset/assets/src/SqlLab/App.jsx
@@ -22,12 +22,19 @@ import { Provider } from 'react-redux';
import thunkMiddleware from 'redux-thunk';
import { hot } from 'react-hot-loader';
-import { initFeatureFlags, isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
+import {
+ initFeatureFlags,
+ isFeatureEnabled,
+ FeatureFlag,
+} from 'src/featureFlags';
import getInitialState from './reducers/getInitialState';
import rootReducer from './reducers/index';
import { initEnhancer } from '../reduxUtils';
import App from './components/App';
-import { emptyQueryResults, clearQueryEditors } from './utils/reduxStateToLocalStorageHelper';
+import {
+ emptyQueryResults,
+ clearQueryEditors,
+} from './utils/reduxStateToLocalStorageHelper';
import { BYTES_PER_CHAR, KB_STORAGE } from './constants';
import setupApp from '../setup/setupApp';
@@ -44,9 +51,9 @@ const initialState = getInitialState(bootstrapData);
const sqlLabPersistStateConfig = {
paths: ['sqlLab'],
config: {
- slicer: paths => (state) => {
+ slicer: paths => state => {
const subset = {};
- paths.forEach((path) => {
+ paths.forEach(path => {
// this line is used to remove old data from browser localStorage.
// we used to persist all redux state into localStorage, but
// it caused configurations passed from server-side got override.
@@ -64,7 +71,8 @@ const sqlLabPersistStateConfig = {
const data = JSON.stringify(subset);
// 2 digit precision
- const currentSize = Math.round(data.length * BYTES_PER_CHAR / KB_STORAGE * 100) / 100;
+ const currentSize =
+ Math.round(((data.length * BYTES_PER_CHAR) / KB_STORAGE) * 100) / 100;
if (state.localStorageUsageInKilobytes !== currentSize) {
state.localStorageUsageInKilobytes = currentSize; // eslint-disable-line no-param-reassign
}
@@ -88,7 +96,8 @@ const store = createStore(
// Highlight the navbar menu
const menus = document.querySelectorAll('.nav.navbar-nav li.dropdown');
-const sqlLabMenu = Array.prototype.slice.apply(menus)
+const sqlLabMenu = Array.prototype.slice
+ .apply(menus)
.find(element => element.innerText.trim() === 'SQL Lab');
if (sqlLabMenu) {
const classes = sqlLabMenu.getAttribute('class');
diff --git a/superset/assets/src/SqlLab/actions/sqlLab.js b/superset/assets/src/SqlLab/actions/sqlLab.js
index 36df2f4fbc7..870ca91692b 100644
--- a/superset/assets/src/SqlLab/actions/sqlLab.js
+++ b/superset/assets/src/SqlLab/actions/sqlLab.js
@@ -48,13 +48,15 @@ export const EXPAND_TABLE = 'EXPAND_TABLE';
export const COLLAPSE_TABLE = 'COLLAPSE_TABLE';
export const QUERY_EDITOR_SETDB = 'QUERY_EDITOR_SETDB';
export const QUERY_EDITOR_SET_SCHEMA = 'QUERY_EDITOR_SET_SCHEMA';
-export const QUERY_EDITOR_SET_SCHEMA_OPTIONS = 'QUERY_EDITOR_SET_SCHEMA_OPTIONS';
+export const QUERY_EDITOR_SET_SCHEMA_OPTIONS =
+ 'QUERY_EDITOR_SET_SCHEMA_OPTIONS';
export const QUERY_EDITOR_SET_TABLE_OPTIONS = 'QUERY_EDITOR_SET_TABLE_OPTIONS';
export const QUERY_EDITOR_SET_TITLE = 'QUERY_EDITOR_SET_TITLE';
export const QUERY_EDITOR_SET_AUTORUN = 'QUERY_EDITOR_SET_AUTORUN';
export const QUERY_EDITOR_SET_SQL = 'QUERY_EDITOR_SET_SQL';
export const QUERY_EDITOR_SET_QUERY_LIMIT = 'QUERY_EDITOR_SET_QUERY_LIMIT';
-export const QUERY_EDITOR_SET_TEMPLATE_PARAMS = 'QUERY_EDITOR_SET_TEMPLATE_PARAMS';
+export const QUERY_EDITOR_SET_TEMPLATE_PARAMS =
+ 'QUERY_EDITOR_SET_TEMPLATE_PARAMS';
export const QUERY_EDITOR_SET_SELECTED_TEXT = 'QUERY_EDITOR_SET_SELECTED_TEXT';
export const QUERY_EDITOR_PERSIST_HEIGHT = 'QUERY_EDITOR_PERSIST_HEIGHT';
export const MIGRATE_QUERY_EDITOR = 'MIGRATE_QUERY_EDITOR';
@@ -108,7 +110,7 @@ const queryServerMapping = invert(queryClientMapping);
// uses a mapping like those above to convert object key names to another style
const fieldConverter = mapping => obj =>
- mapKeys(obj, (value, key) => key in mapping ? mapping[key] : key);
+ mapKeys(obj, (value, key) => (key in mapping ? mapping[key] : key));
const convertQueryToServer = fieldConverter(queryServerMapping);
const convertQueryToClient = fieldConverter(queryClientMapping);
@@ -139,7 +141,7 @@ export function saveQuery(query) {
postPayload: convertQueryToServer(query),
stringify: false,
})
- .then((result) => {
+ .then(result => {
dispatch({
type: QUERY_EDITOR_SAVED,
query,
@@ -147,7 +149,9 @@ export function saveQuery(query) {
});
dispatch(addSuccessToast(t('Your query was saved')));
})
- .catch(() => dispatch(addDangerToast(t('Your query could not be saved'))));
+ .catch(() =>
+ dispatch(addDangerToast(t('Your query could not be saved'))),
+ );
}
export function updateQueryEditor(alterations) {
@@ -162,7 +166,9 @@ export function updateSavedQuery(query) {
stringify: false,
})
.then(() => dispatch(addSuccessToast(t('Your query was updated'))))
- .catch(() => dispatch(addDangerToast(t('Your query could not be updated'))))
+ .catch(() =>
+ dispatch(addDangerToast(t('Your query could not be updated'))),
+ )
.then(() => dispatch(updateQueryEditor(query)));
}
@@ -173,29 +179,53 @@ export function scheduleQuery(query) {
postPayload: query,
stringify: false,
})
- .then(() => dispatch(addSuccessToast(t('Your query has been scheduled. To see details of your query, navigate to Saved Queries'))))
- .catch(() => dispatch(addDangerToast(t('Your query could not be scheduled'))));
+ .then(() =>
+ dispatch(
+ addSuccessToast(
+ t(
+ 'Your query has been scheduled. To see details of your query, navigate to Saved Queries',
+ ),
+ ),
+ ),
+ )
+ .catch(() =>
+ dispatch(addDangerToast(t('Your query could not be scheduled'))),
+ );
}
export function estimateQueryCost(query) {
const { dbId, schema, sql, templateParams } = query;
- const endpoint = schema === null
+ const endpoint =
+ schema === null
? `/superset/estimate_query_cost/${dbId}/`
: `/superset/estimate_query_cost/${dbId}/${schema}/`;
- return dispatch => Promise.all([
- dispatch({ type: COST_ESTIMATE_STARTED, query }),
- SupersetClient.post({
- endpoint,
- postPayload: { sql, templateParams: JSON.parse(templateParams || '{}') },
- })
- .then(({ json }) => dispatch({ type: COST_ESTIMATE_RETURNED, query, json }))
- .catch(response =>
- getClientErrorObject(response).then((error) => {
- const message = error.error || error.statusText || t('Failed at retrieving results');
- return dispatch({ type: COST_ESTIMATE_FAILED, query, error: message });
- }),
- ),
- ]);
+ return dispatch =>
+ Promise.all([
+ dispatch({ type: COST_ESTIMATE_STARTED, query }),
+ SupersetClient.post({
+ endpoint,
+ postPayload: {
+ sql,
+ templateParams: JSON.parse(templateParams || '{}'),
+ },
+ })
+ .then(({ json }) =>
+ dispatch({ type: COST_ESTIMATE_RETURNED, query, json }),
+ )
+ .catch(response =>
+ getClientErrorObject(response).then(error => {
+ const message =
+ error.error ||
+ error.statusText ||
+ t('Failed at retrieving results');
+ return dispatch({
+ type: COST_ESTIMATE_FAILED,
+ query,
+ error: message,
+ });
+ }),
+ ),
+ ]);
}
export function startQuery(query) {
@@ -210,38 +240,54 @@ export function startQuery(query) {
}
export function querySuccess(query, results) {
- return function (dispatch) {
- const sync = (!query.isDataPreview && isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE))
- ? SupersetClient.put({
- endpoint: encodeURI(`/tabstateview/${results.query.sqlEditorId}`),
- postPayload: { latest_query_id: query.id },
- })
- : Promise.resolve();
+ return function(dispatch) {
+ const sync =
+ !query.isDataPreview &&
+ isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
+ ? SupersetClient.put({
+ endpoint: encodeURI(`/tabstateview/${results.query.sqlEditorId}`),
+ postPayload: { latest_query_id: query.id },
+ })
+ : Promise.resolve();
return sync
.then(() => dispatch({ type: QUERY_SUCCESS, query, results }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while storing the latest query id in the backend. ' +
- 'Please contact your administrator if this problem persists.'))));
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while storing the latest query id in the backend. ' +
+ 'Please contact your administrator if this problem persists.',
+ ),
+ ),
+ ),
+ );
};
}
export function queryFailed(query, msg, link) {
- return function (dispatch) {
- const sync = (!query.isDataPreview && isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE))
- ? SupersetClient.put({
- endpoint: encodeURI(`/tabstateview/${query.sqlEditorId}`),
- postPayload: { latest_query_id: query.id },
- })
- : Promise.resolve();
+ return function(dispatch) {
+ const sync =
+ !query.isDataPreview &&
+ isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
+ ? SupersetClient.put({
+ endpoint: encodeURI(`/tabstateview/${query.sqlEditorId}`),
+ postPayload: { latest_query_id: query.id },
+ })
+ : Promise.resolve();
return sync
.then(() => dispatch({ type: QUERY_FAILED, query, msg, link }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while storing the latest query id in the backend. ' +
- 'Please contact your administrator if this problem persists.'))));
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while storing the latest query id in the backend. ' +
+ 'Please contact your administrator if this problem persists.',
+ ),
+ ),
+ ),
+ );
};
}
@@ -262,7 +308,7 @@ export function requestQueryResults(query) {
}
export function fetchQueryResults(query, displayLimit) {
- return function (dispatch) {
+ return function(dispatch) {
dispatch(requestQueryResults(query));
return SupersetClient.get({
@@ -274,17 +320,20 @@ export function fetchQueryResults(query, displayLimit) {
return dispatch(querySuccess(query, bigIntJson));
})
.catch(response =>
- getClientErrorObject(response).then((error) => {
- const message = error.error || error.statusText || t('Failed at retrieving results');
+ getClientErrorObject(response).then(error => {
+ const message =
+ error.error ||
+ error.statusText ||
+ t('Failed at retrieving results');
return dispatch(queryFailed(query, message, error.link));
}),
);
- };
+ };
}
export function runQuery(query) {
- return function (dispatch) {
+ return function(dispatch) {
dispatch(startQuery(query));
const postPayload = {
client_id: query.id,
@@ -315,7 +364,7 @@ export function runQuery(query) {
}
})
.catch(response =>
- getClientErrorObject(response).then((error) => {
+ getClientErrorObject(response).then(error => {
let message = error.error || error.statusText || t('Unknown error');
if (message.includes('CSRF token')) {
message = t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT);
@@ -327,7 +376,7 @@ export function runQuery(query) {
}
export function validateQuery(query) {
- return function (dispatch) {
+ return function(dispatch) {
dispatch(startQueryValidation(query));
const postPayload = {
@@ -348,7 +397,7 @@ export function validateQuery(query) {
})
.then(({ json }) => dispatch(queryValidationReturned(query, json)))
.catch(response =>
- getClientErrorObject(response).then((error) => {
+ getClientErrorObject(response).then(error => {
let message = error.error || error.statusText || t('Unknown error');
if (message.includes('CSRF token')) {
message = t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT);
@@ -360,7 +409,7 @@ export function validateQuery(query) {
}
export function postStopQuery(query) {
- return function (dispatch) {
+ return function(dispatch) {
return SupersetClient.post({
endpoint: '/superset/stop_query/',
postPayload: { client_id: query.id },
@@ -368,7 +417,11 @@ export function postStopQuery(query) {
})
.then(() => dispatch(stopQuery(query)))
.then(() => dispatch(addSuccessToast(t('Query was stopped.'))))
- .catch(() => dispatch(addDangerToast(t('Failed at stopping query. ') + `'${query.id}'`)));
+ .catch(() =>
+ dispatch(
+ addDangerToast(t('Failed at stopping query. ') + `'${query.id}'`),
+ ),
+ );
};
}
@@ -389,9 +442,16 @@ function migrateTable(table, queryEditorId, dispatch) {
};
return dispatch({ type: MIGRATE_TABLE, oldTable: table, newTable });
})
- .catch(() => dispatch(addWarningToast(t(
- 'Unable to migrate table schema state to backend. Superset will retry ' +
- 'later. Please contact your administrator if this problem persists.'))));
+ .catch(() =>
+ dispatch(
+ addWarningToast(
+ t(
+ 'Unable to migrate table schema state to backend. Superset will retry ' +
+ 'later. Please contact your administrator if this problem persists.',
+ ),
+ ),
+ ),
+ );
}
function migrateQuery(queryId, queryEditorId, dispatch) {
@@ -400,36 +460,72 @@ function migrateQuery(queryId, queryEditorId, dispatch) {
postPayload: { queryId },
})
.then(() => dispatch({ type: MIGRATE_QUERY, queryId, queryEditorId }))
- .catch(() => dispatch(addWarningToast(t(
- 'Unable to migrate query state to backend. Superset will retry later. ' +
- 'Please contact your administrator if this problem persists.'))));
+ .catch(() =>
+ dispatch(
+ addWarningToast(
+ t(
+ 'Unable to migrate query state to backend. Superset will retry later. ' +
+ 'Please contact your administrator if this problem persists.',
+ ),
+ ),
+ ),
+ );
}
-export function migrateQueryEditorFromLocalStorage(queryEditor, tables, queries) {
- return function (dispatch) {
- return SupersetClient.post({ endpoint: '/tabstateview/', postPayload: { queryEditor } })
+export function migrateQueryEditorFromLocalStorage(
+ queryEditor,
+ tables,
+ queries,
+) {
+ return function(dispatch) {
+ return SupersetClient.post({
+ endpoint: '/tabstateview/',
+ postPayload: { queryEditor },
+ })
.then(({ json }) => {
const newQueryEditor = {
...queryEditor,
id: json.id.toString(),
};
- dispatch({ type: MIGRATE_QUERY_EDITOR, oldQueryEditor: queryEditor, newQueryEditor });
- dispatch({ type: MIGRATE_TAB_HISTORY, oldId: queryEditor.id, newId: newQueryEditor.id });
+ dispatch({
+ type: MIGRATE_QUERY_EDITOR,
+ oldQueryEditor: queryEditor,
+ newQueryEditor,
+ });
+ dispatch({
+ type: MIGRATE_TAB_HISTORY,
+ oldId: queryEditor.id,
+ newId: newQueryEditor.id,
+ });
return Promise.all([
- ...tables.map(table => migrateTable(table, newQueryEditor.id, dispatch)),
- ...queries.map(query => migrateQuery(query.id, newQueryEditor.id, dispatch)),
+ ...tables.map(table =>
+ migrateTable(table, newQueryEditor.id, dispatch),
+ ),
+ ...queries.map(query =>
+ migrateQuery(query.id, newQueryEditor.id, dispatch),
+ ),
]);
})
- .catch(() => dispatch(addWarningToast(t(
- 'Unable to migrate query editor state to backend. Superset will retry ' +
- 'later. Please contact your administrator if this problem persists.'))));
+ .catch(() =>
+ dispatch(
+ addWarningToast(
+ t(
+ 'Unable to migrate query editor state to backend. Superset will retry ' +
+ 'later. Please contact your administrator if this problem persists.',
+ ),
+ ),
+ ),
+ );
};
}
export function addQueryEditor(queryEditor) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
- ? SupersetClient.post({ endpoint: '/tabstateview/', postPayload: { queryEditor } })
+ ? SupersetClient.post({
+ endpoint: '/tabstateview/',
+ postPayload: { queryEditor },
+ })
: Promise.resolve({ json: { id: shortid.generate() } });
return sync
@@ -438,18 +534,30 @@ export function addQueryEditor(queryEditor) {
...queryEditor,
id: json.id.toString(),
};
- return dispatch({ type: ADD_QUERY_EDITOR, queryEditor: newQueryEditor });
+ return dispatch({
+ type: ADD_QUERY_EDITOR,
+ queryEditor: newQueryEditor,
+ });
})
- .catch(() => dispatch(addDangerToast(t(
- 'Unable to add a new tab to the backend. Please contact your administrator.'))));
+ .catch(() =>
+ dispatch(
+ addDangerToast(
+ t(
+ 'Unable to add a new tab to the backend. Please contact your administrator.',
+ ),
+ ),
+ ),
+ );
};
}
export function cloneQueryToNewTab(query, autorun) {
- return function (dispatch, getState) {
+ return function(dispatch, getState) {
const state = getState();
const { queryEditors, tabHistory } = state.sqlLab;
- const sourceQueryEditor = queryEditors.find(qe => qe.id === tabHistory[tabHistory.length - 1]);
+ const sourceQueryEditor = queryEditors.find(
+ qe => qe.id === tabHistory[tabHistory.length - 1],
+ );
const queryEditor = {
title: t('Copy of %s', sourceQueryEditor.title),
dbId: query.dbId ? query.dbId : null,
@@ -465,18 +573,25 @@ export function cloneQueryToNewTab(query, autorun) {
}
export function setActiveQueryEditor(queryEditor) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
- ? SupersetClient.post({ endpoint: encodeURI(`/tabstateview/${queryEditor.id}/activate`) })
+ ? SupersetClient.post({
+ endpoint: encodeURI(`/tabstateview/${queryEditor.id}/activate`),
+ })
: Promise.resolve();
return sync
.then(() => dispatch({ type: SET_ACTIVE_QUERY_EDITOR, queryEditor }))
- .catch((response) => {
+ .catch(response => {
if (response.status !== 404) {
- return dispatch(addDangerToast(t(
- 'An error occurred while setting the active tab. Please contact ' +
- 'your administrator.')));
+ return dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while setting the active tab. Please contact ' +
+ 'your administrator.',
+ ),
+ ),
+ );
}
return dispatch({ type: REMOVE_QUERY_EDITOR, queryEditor });
});
@@ -488,7 +603,7 @@ export function loadQueryEditor(queryEditor) {
}
export function setTables(tableSchemas) {
- const tables = tableSchemas.map((tableSchema) => {
+ const tables = tableSchemas.map(tableSchema => {
const {
columns,
selectStar,
@@ -518,8 +633,11 @@ export function setTables(tableSchemas) {
}
export function switchQueryEditor(queryEditor, displayLimit) {
- return function (dispatch) {
- if (isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE) && !queryEditor.loaded) {
+ return function(dispatch) {
+ if (
+ isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE) &&
+ !queryEditor.loaded
+ ) {
SupersetClient.get({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
})
@@ -549,10 +667,11 @@ export function switchQueryEditor(queryEditor, displayLimit) {
dispatch(fetchQueryResults(json.latest_query, displayLimit));
}
})
- .catch((response) => {
+ .catch(response => {
if (response.status !== 404) {
- return dispatch(addDangerToast(t(
- 'An error occurred while fetching tab state')));
+ return dispatch(
+ addDangerToast(t('An error occurred while fetching tab state')),
+ );
}
return dispatch({ type: REMOVE_QUERY_EDITOR, queryEditor });
});
@@ -567,43 +686,53 @@ export function setActiveSouthPaneTab(tabId) {
}
export function removeQueryEditor(queryEditor) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
- ? SupersetClient.delete({ endpoint: encodeURI(`/tabstateview/${queryEditor.id}`) })
+ ? SupersetClient.delete({
+ endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
+ })
: Promise.resolve();
return sync
- .then(() =>
- dispatch({ type: REMOVE_QUERY_EDITOR, queryEditor }),
- )
+ .then(() => dispatch({ type: REMOVE_QUERY_EDITOR, queryEditor }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while removing tab. Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while removing tab. Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
export function removeQuery(query) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.delete({
- endpoint: encodeURI(`/tabstateview/${query.sqlEditorId}/query/${query.id}`),
- })
+ endpoint: encodeURI(
+ `/tabstateview/${query.sqlEditorId}/query/${query.id}`,
+ ),
+ })
: Promise.resolve();
return sync
- .then(() =>
- dispatch({ type: REMOVE_QUERY, query }),
- )
+ .then(() => dispatch({ type: REMOVE_QUERY, query }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while removing query. Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while removing query. Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
export function queryEditorSetDb(queryEditor, dbId) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
@@ -614,14 +743,19 @@ export function queryEditorSetDb(queryEditor, dbId) {
return sync
.then(() => dispatch({ type: QUERY_EDITOR_SETDB, queryEditor, dbId }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while setting the tab database ID. Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while setting the tab database ID. Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
export function queryEditorSetSchema(queryEditor, schema) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
@@ -630,10 +764,17 @@ export function queryEditorSetSchema(queryEditor, schema) {
: Promise.resolve();
return sync
- .then(() => dispatch({ type: QUERY_EDITOR_SET_SCHEMA, queryEditor, schema }))
+ .then(() =>
+ dispatch({ type: QUERY_EDITOR_SET_SCHEMA, queryEditor, schema }),
+ )
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while setting the tab schema. Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while setting the tab schema. Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
@@ -647,7 +788,7 @@ export function queryEditorSetTableOptions(queryEditor, options) {
}
export function queryEditorSetAutorun(queryEditor, autorun) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
@@ -656,16 +797,23 @@ export function queryEditorSetAutorun(queryEditor, autorun) {
: Promise.resolve();
return sync
- .then(() => dispatch({ type: QUERY_EDITOR_SET_AUTORUN, queryEditor, autorun }))
+ .then(() =>
+ dispatch({ type: QUERY_EDITOR_SET_AUTORUN, queryEditor, autorun }),
+ )
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while setting the tab autorun. Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while setting the tab autorun. Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
export function queryEditorSetTitle(queryEditor, title) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
@@ -674,16 +822,23 @@ export function queryEditorSetTitle(queryEditor, title) {
: Promise.resolve();
return sync
- .then(() => dispatch({ type: QUERY_EDITOR_SET_TITLE, queryEditor, title }))
+ .then(() =>
+ dispatch({ type: QUERY_EDITOR_SET_TITLE, queryEditor, title }),
+ )
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while setting the tab title. Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while setting the tab title. Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
export function queryEditorSetSql(queryEditor, sql) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
@@ -694,16 +849,21 @@ export function queryEditorSetSql(queryEditor, sql) {
return sync
.then(() => dispatch({ type: QUERY_EDITOR_SET_SQL, queryEditor, sql }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while storing your query in the backend. To ' +
- 'avoid losing your changes, please save your query using the ' +
- '"Save Query" button.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while storing your query in the backend. To ' +
+ 'avoid losing your changes, please save your query using the ' +
+ '"Save Query" button.',
+ ),
+ ),
+ ),
);
};
}
export function queryEditorSetQueryLimit(queryEditor, queryLimit) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
@@ -712,16 +872,27 @@ export function queryEditorSetQueryLimit(queryEditor, queryLimit) {
: Promise.resolve();
return sync
- .then(() => dispatch({ type: QUERY_EDITOR_SET_QUERY_LIMIT, queryEditor, queryLimit }))
+ .then(() =>
+ dispatch({
+ type: QUERY_EDITOR_SET_QUERY_LIMIT,
+ queryEditor,
+ queryLimit,
+ }),
+ )
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while setting the tab title. Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while setting the tab title. Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
export function queryEditorSetTemplateParams(queryEditor, templateParams) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.put({
endpoint: encodeURI(`/tabstateview/${queryEditor.id}`),
@@ -730,11 +901,22 @@ export function queryEditorSetTemplateParams(queryEditor, templateParams) {
: Promise.resolve();
return sync
- .then(() => dispatch({ type: QUERY_EDITOR_SET_TEMPLATE_PARAMS, queryEditor, templateParams }))
+ .then(() =>
+ dispatch({
+ type: QUERY_EDITOR_SET_TEMPLATE_PARAMS,
+ queryEditor,
+ templateParams,
+ }),
+ )
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while setting the tab template parameters. ' +
- 'Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while setting the tab template parameters. ' +
+ 'Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
@@ -748,8 +930,14 @@ export function mergeTable(table, query) {
}
function getTableMetadata(table, query, dispatch) {
- return SupersetClient.get({ endpoint: encodeURI(`/superset/table/${query.dbId}/` +
- `${encodeURIComponent(table.name)}/${encodeURIComponent(table.schema)}/`) })
+ return SupersetClient.get({
+ endpoint: encodeURI(
+ `/superset/table/${query.dbId}/` +
+ `${encodeURIComponent(table.name)}/${encodeURIComponent(
+ table.schema,
+ )}/`,
+ ),
+ })
.then(({ json }) => {
const dataPreviewQuery = {
id: shortid.generate(),
@@ -783,30 +971,40 @@ function getTableMetadata(table, query, dispatch) {
isMetadataLoading: false,
}),
),
- dispatch(addDangerToast(t('An error occurred while fetching table metadata'))),
+ dispatch(
+ addDangerToast(t('An error occurred while fetching table metadata')),
+ ),
]),
);
}
function getTableExtendedMetadata(table, query, dispatch) {
return SupersetClient.get({
- endpoint: encodeURI(`/superset/extra_table_metadata/${query.dbId}/` +
- `${encodeURIComponent(table.name)}/${encodeURIComponent(table.schema)}/`),
+ endpoint: encodeURI(
+ `/superset/extra_table_metadata/${query.dbId}/` +
+ `${encodeURIComponent(table.name)}/${encodeURIComponent(
+ table.schema,
+ )}/`,
+ ),
})
.then(({ json }) => {
- dispatch(mergeTable({ ...table, ...json, isExtraMetadataLoading: false }));
+ dispatch(
+ mergeTable({ ...table, ...json, isExtraMetadataLoading: false }),
+ );
return json;
})
.catch(() =>
Promise.all([
dispatch(mergeTable({ ...table, isExtraMetadataLoading: false })),
- dispatch(addDangerToast(t('An error occurred while fetching table metadata'))),
+ dispatch(
+ addDangerToast(t('An error occurred while fetching table metadata')),
+ ),
]),
);
}
export function addTable(query, tableName, schemaName) {
- return function (dispatch) {
+ return function(dispatch) {
const table = {
dbId: query.dbId,
queryEditorId: query.id,
@@ -825,25 +1023,29 @@ export function addTable(query, tableName, schemaName) {
return Promise.all([
getTableMetadata(table, query, dispatch),
getTableExtendedMetadata(table, query, dispatch),
- ])
- .then(([newTable, json]) => {
- const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
- ? SupersetClient.post({
- endpoint: encodeURI('/tableschemaview/'),
- postPayload: { table: { ...newTable, ...json } },
- })
- : Promise.resolve({ json: { id: shortid.generate() } });
+ ]).then(([newTable, json]) => {
+ const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
+ ? SupersetClient.post({
+ endpoint: encodeURI('/tableschemaview/'),
+ postPayload: { table: { ...newTable, ...json } },
+ })
+ : Promise.resolve({ json: { id: shortid.generate() } });
- return sync
- .then(({ json: resultJson }) =>
- dispatch(mergeTable({ ...table, id: resultJson.id })),
- )
- .catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while fetching table metadata. ' +
- 'Please contact your administrator.'))),
- );
- });
+ return sync
+ .then(({ json: resultJson }) =>
+ dispatch(mergeTable({ ...table, id: resultJson.id })),
+ )
+ .catch(() =>
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while fetching table metadata. ' +
+ 'Please contact your administrator.',
+ ),
+ ),
+ ),
+ );
+ });
};
}
@@ -852,7 +1054,7 @@ export function changeDataPreviewId(oldQueryId, newQuery) {
}
export function reFetchQueryResults(query) {
- return function (dispatch) {
+ return function(dispatch) {
const newQuery = {
id: shortid.generate(),
dbId: query.dbId,
@@ -871,7 +1073,7 @@ export function reFetchQueryResults(query) {
}
export function expandTable(table) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.post({
endpoint: encodeURI(`/tableschemaview/${table.id}/expanded`),
@@ -882,15 +1084,20 @@ export function expandTable(table) {
return sync
.then(() => dispatch({ type: EXPAND_TABLE, table }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while expanding the table schema. ' +
- 'Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while expanding the table schema. ' +
+ 'Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
export function collapseTable(table) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? SupersetClient.post({
endpoint: encodeURI(`/tableschemaview/${table.id}/expanded`),
@@ -901,25 +1108,37 @@ export function collapseTable(table) {
return sync
.then(() => dispatch({ type: COLLAPSE_TABLE, table }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while collapsing the table schema. ' +
- 'Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while collapsing the table schema. ' +
+ 'Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
export function removeTable(table) {
- return function (dispatch) {
+ return function(dispatch) {
const sync = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
- ? SupersetClient.delete({ endpoint: encodeURI(`/tableschemaview/${table.id}`) })
+ ? SupersetClient.delete({
+ endpoint: encodeURI(`/tableschemaview/${table.id}`),
+ })
: Promise.resolve();
return sync
.then(() => dispatch({ type: REMOVE_TABLE, table }))
.catch(() =>
- dispatch(addDangerToast(t(
- 'An error occurred while removing the table schema. ' +
- 'Please contact your administrator.'))),
+ dispatch(
+ addDangerToast(
+ t(
+ 'An error occurred while removing the table schema. ' +
+ 'Please contact your administrator.',
+ ),
+ ),
+ ),
);
};
}
@@ -933,11 +1152,16 @@ export function setUserOffline(offline) {
}
export function persistEditorHeight(queryEditor, northPercent, southPercent) {
- return { type: QUERY_EDITOR_PERSIST_HEIGHT, queryEditor, northPercent, southPercent };
+ return {
+ type: QUERY_EDITOR_PERSIST_HEIGHT,
+ queryEditor,
+ northPercent,
+ southPercent,
+ };
}
export function popStoredQuery(urlId) {
- return function (dispatch) {
+ return function(dispatch) {
return SupersetClient.get({ endpoint: `/kv/${urlId}` })
.then(({ json }) =>
dispatch(
@@ -954,8 +1178,10 @@ export function popStoredQuery(urlId) {
};
}
export function popSavedQuery(saveQueryId) {
- return function (dispatch) {
- return SupersetClient.get({ endpoint: `/savedqueryviewapi/api/get/${saveQueryId}` })
+ return function(dispatch) {
+ return SupersetClient.get({
+ endpoint: `/savedqueryviewapi/api/get/${saveQueryId}`,
+ })
.then(({ json }) => {
const queryEditorProps = {
...convertQueryToClient(json.result),
@@ -967,7 +1193,7 @@ export function popSavedQuery(saveQueryId) {
};
}
export function popDatasourceQuery(datasourceKey, sql) {
- return function (dispatch) {
+ return function(dispatch) {
return SupersetClient.get({
endpoint: `/superset/fetch_datasource_metadata?datasourceKey=${datasourceKey}`,
})
@@ -982,7 +1208,9 @@ export function popDatasourceQuery(datasourceKey, sql) {
}),
),
)
- .catch(() => dispatch(addDangerToast(t("The datasource couldn't be loaded"))));
+ .catch(() =>
+ dispatch(addDangerToast(t("The datasource couldn't be loaded"))),
+ );
};
}
export function createDatasourceStarted() {
@@ -997,7 +1225,7 @@ export function createDatasourceFailed(err) {
}
export function createDatasource(vizOptions) {
- return (dispatch) => {
+ return dispatch => {
dispatch(createDatasourceStarted());
return SupersetClient.post({
endpoint: '/superset/sqllab_viz/',
@@ -1009,7 +1237,11 @@ export function createDatasource(vizOptions) {
return Promise.resolve(json);
})
.catch(() => {
- dispatch(createDatasourceFailed(t('An error occurred while creating the data source')));
+ dispatch(
+ createDatasourceFailed(
+ t('An error occurred while creating the data source'),
+ ),
+ );
return Promise.reject();
});
diff --git a/superset/assets/src/SqlLab/components/AceEditorWrapper.jsx b/superset/assets/src/SqlLab/components/AceEditorWrapper.jsx
index 314cb3189d4..ca142f182de 100644
--- a/superset/assets/src/SqlLab/components/AceEditorWrapper.jsx
+++ b/superset/assets/src/SqlLab/components/AceEditorWrapper.jsx
@@ -32,21 +32,22 @@ const SCHEMA_AUTOCOMPLETE_SCORE = 60;
const TABLE_AUTOCOMPLETE_SCORE = 55;
const COLUMN_AUTOCOMPLETE_SCORE = 50;
-const keywords = (
+const keywords =
'SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|AND|OR|GROUP|BY|ORDER|LIMIT|OFFSET|HAVING|AS|CASE|' +
'WHEN|THEN|ELSE|END|TYPE|LEFT|RIGHT|JOIN|ON|OUTER|DESC|ASC|UNION|CREATE|TABLE|PRIMARY|KEY|IF|' +
'FOREIGN|NOT|REFERENCES|DEFAULT|NULL|INNER|CROSS|NATURAL|DATABASE|DROP|GRANT|SUM|MAX|MIN|COUNT|' +
- 'AVG|DISTINCT'
-);
+ 'AVG|DISTINCT';
-const dataTypes = (
+const dataTypes =
'INT|NUMERIC|DECIMAL|DATE|VARCHAR|CHAR|BIGINT|FLOAT|DOUBLE|BIT|BINARY|TEXT|SET|TIMESTAMP|' +
- 'MONEY|REAL|NUMBER|INTEGER'
-);
+ 'MONEY|REAL|NUMBER|INTEGER';
const sqlKeywords = [].concat(keywords.split('|'), dataTypes.split('|'));
export const sqlWords = sqlKeywords.map(s => ({
- name: s, value: s, score: SQL_KEYWORD_AUTOCOMPLETE_SCORE, meta: 'sql',
+ name: s,
+ value: s,
+ score: SQL_KEYWORD_AUTOCOMPLETE_SCORE,
+ meta: 'sql',
}));
const propTypes = {
@@ -58,17 +59,19 @@ const propTypes = {
extendedTables: PropTypes.array,
queryEditor: PropTypes.object.isRequired,
height: PropTypes.string,
- hotkeys: PropTypes.arrayOf(PropTypes.shape({
- key: PropTypes.string.isRequired,
- descr: PropTypes.string.isRequired,
- func: PropTypes.func.isRequired,
- })),
+ hotkeys: PropTypes.arrayOf(
+ PropTypes.shape({
+ key: PropTypes.string.isRequired,
+ descr: PropTypes.string.isRequired,
+ func: PropTypes.func.isRequired,
+ }),
+ ),
onChange: PropTypes.func,
};
const defaultProps = {
- onBlur: () => { },
- onChange: () => { },
+ onBlur: () => {},
+ onChange: () => {},
schemas: [],
tables: [],
extendedTables: [],
@@ -89,9 +92,14 @@ class AceEditorWrapper extends React.PureComponent {
this.setAutoCompleter(this.props);
}
UNSAFE_componentWillReceiveProps(nextProps) {
- if (!areArraysShallowEqual(this.props.tables, nextProps.tables) ||
+ if (
+ !areArraysShallowEqual(this.props.tables, nextProps.tables) ||
!areArraysShallowEqual(this.props.schemas, nextProps.schemas) ||
- !areArraysShallowEqual(this.props.extendedTables, nextProps.extendedTables)) {
+ !areArraysShallowEqual(
+ this.props.extendedTables,
+ nextProps.extendedTables,
+ )
+ ) {
this.setAutoCompleter(nextProps);
}
if (nextProps.sql !== this.props.sql) {
@@ -112,7 +120,7 @@ class AceEditorWrapper extends React.PureComponent {
this.onAltEnter();
},
});
- this.props.hotkeys.forEach((keyConfig) => {
+ this.props.hotkeys.forEach(keyConfig => {
editor.commands.addCommand({
name: keyConfig.name,
bindKey: { win: keyConfig.key, mac: keyConfig.key },
@@ -123,10 +131,15 @@ class AceEditorWrapper extends React.PureComponent {
editor.selection.on('changeSelection', () => {
const selectedText = editor.getSelectedText();
// Backspace trigger 1 character selection, ignoring
- if (selectedText !== this.state.selectedText && selectedText.length !== 1) {
+ if (
+ selectedText !== this.state.selectedText &&
+ selectedText.length !== 1
+ ) {
this.setState({ selectedText });
this.props.actions.queryEditorSetSelectedText(
- this.props.queryEditor, selectedText);
+ this.props.queryEditor,
+ selectedText,
+ );
}
});
}
@@ -162,12 +175,12 @@ class AceEditorWrapper extends React.PureComponent {
const columns = {};
const tables = props.tables || [];
const extendedTables = props.extendedTables || [];
- const tableWords = tables.map((t) => {
+ const tableWords = tables.map(t => {
const tableName = t.value;
const extendedTable = extendedTables.find(et => et.name === tableName);
- const cols = extendedTable && extendedTable.columns || [];
- cols.forEach((col) => {
- columns[col.name] = null; // using an object as a unique set
+ const cols = (extendedTable && extendedTable.columns) || [];
+ cols.forEach(col => {
+ columns[col.name] = null; // using an object as a unique set
});
return {
name: t.label,
@@ -177,11 +190,17 @@ class AceEditorWrapper extends React.PureComponent {
};
});
- const columnWords = Object.keys(columns).map(col => (
- { name: col, value: col, score: COLUMN_AUTOCOMPLETE_SCORE, meta: 'column' }
- ));
+ const columnWords = Object.keys(columns).map(col => ({
+ name: col,
+ value: col,
+ score: COLUMN_AUTOCOMPLETE_SCORE,
+ meta: 'column',
+ }));
- const words = schemaWords.concat(tableWords).concat(columnWords).concat(sqlWords);
+ const words = schemaWords
+ .concat(tableWords)
+ .concat(columnWords)
+ .concat(sqlWords);
this.setState({ words }, () => {
const completer = {
@@ -194,7 +213,7 @@ class AceEditorWrapper extends React.PureComponent {
}
getAceAnnotations() {
const validationResult = this.props.queryEditor.validationResult;
- const resultIsReady = (validationResult && validationResult.completed);
+ const resultIsReady = validationResult && validationResult.completed;
if (resultIsReady && validationResult.errors.length > 0) {
const errors = validationResult.errors.map(err => ({
type: 'error',
diff --git a/superset/assets/src/SqlLab/components/App.jsx b/superset/assets/src/SqlLab/components/App.jsx
index 016a19ecd7f..f1c21be3361 100644
--- a/superset/assets/src/SqlLab/components/App.jsx
+++ b/superset/assets/src/SqlLab/components/App.jsx
@@ -56,10 +56,13 @@ class App extends React.PureComponent {
window.addEventListener('resize', this.handleResize.bind(this));
}
componentDidUpdate() {
- if (this.props.localStorageUsageInKilobytes >=
+ if (
+ this.props.localStorageUsageInKilobytes >=
LOCALSTORAGE_WARNING_THRESHOLD * LOCALSTORAGE_MAX_USAGE_KB
) {
- this.showLocalStorageUsageWarning(this.props.localStorageUsageInKilobytes);
+ this.showLocalStorageUsageWarning(
+ this.props.localStorageUsageInKilobytes,
+ );
}
}
componentWillUnmount() {
@@ -75,23 +78,34 @@ class App extends React.PureComponent {
const searchHeaderEl = $('#search-header');
const alertEl = $('#sqllab-alerts');
const headerEl = $('header .navbar');
- const headerHeight = headerEl.outerHeight() + parseInt(headerEl.css('marginBottom'), 10);
+ const headerHeight =
+ headerEl.outerHeight() + parseInt(headerEl.css('marginBottom'), 10);
const searchHeaderHeight =
searchHeaderEl.length > 0
- ? searchHeaderEl.outerHeight() + parseInt(searchHeaderEl.css('marginBottom'), 10)
+ ? searchHeaderEl.outerHeight() +
+ parseInt(searchHeaderEl.css('marginBottom'), 10)
: 0;
- const tabsHeight = tabsEl.length > 0 ? tabsEl.outerHeight() : searchHeaderHeight;
+ const tabsHeight =
+ tabsEl.length > 0 ? tabsEl.outerHeight() : searchHeaderHeight;
const warningHeight = warningEl.length > 0 ? warningEl.outerHeight() : 0;
const alertHeight = alertEl.length > 0 ? alertEl.outerHeight() : 0;
- return `${window.innerHeight - headerHeight - tabsHeight - warningHeight - alertHeight}px`;
+ return `${window.innerHeight -
+ headerHeight -
+ tabsHeight -
+ warningHeight -
+ alertHeight}px`;
}
showLocalStorageUsageWarning(currentUsage) {
this.props.actions.addDangerToast(
- t('SQL Lab uses your browser\'s local storage to store queries and results.' +
- `\n Currently, you are using ${currentUsage.toFixed(2)} KB out of ${LOCALSTORAGE_MAX_USAGE_KB} KB. storage space.` +
- '\n To keep SQL Lab from crashing, please delete some query tabs.' +
- '\n You can re-access these queries by using the Save feature before you delete the tab. ' +
- 'Note that you will need to close other SQL Lab windows before you do this.'),
+ t(
+ "SQL Lab uses your browser's local storage to store queries and results." +
+ `\n Currently, you are using ${currentUsage.toFixed(
+ 2,
+ )} KB out of ${LOCALSTORAGE_MAX_USAGE_KB} KB. storage space.` +
+ '\n To keep SQL Lab from crashing, please delete some query tabs.' +
+ '\n You can re-access these queries by using the Save feature before you delete the tab. ' +
+ 'Note that you will need to close other SQL Lab windows before you do this.',
+ ),
);
}
handleResize() {
@@ -145,7 +159,4 @@ function mapDispatchToProps(dispatch) {
}
export { App };
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(App);
+export default connect(mapStateToProps, mapDispatchToProps)(App);
diff --git a/superset/assets/src/SqlLab/components/ColumnElement.jsx b/superset/assets/src/SqlLab/components/ColumnElement.jsx
index c2c0aa9e091..1ee8579e8a1 100644
--- a/superset/assets/src/SqlLab/components/ColumnElement.jsx
+++ b/superset/assets/src/SqlLab/components/ColumnElement.jsx
@@ -54,7 +54,7 @@ export default function ColumnElement(props) {
{JSON.stringify(key, null, ' ')}
- }
+ }
>
@@ -64,11 +64,13 @@ export default function ColumnElement(props) {
return (
- {name}{icons}
+ {name}
+ {icons}
{col.type}
-
);
+
+ );
}
ColumnElement.propTypes = propTypes;
diff --git a/superset/assets/src/SqlLab/components/ExploreResultsButton.jsx b/superset/assets/src/SqlLab/components/ExploreResultsButton.jsx
index 4d8de5726e5..260c93366a8 100644
--- a/superset/assets/src/SqlLab/components/ExploreResultsButton.jsx
+++ b/superset/assets/src/SqlLab/components/ExploreResultsButton.jsx
@@ -48,7 +48,9 @@ class ExploreResultsButton extends React.PureComponent {
this.visualize = this.visualize.bind(this);
this.onClick = this.onClick.bind(this);
this.getInvalidColumns = this.getInvalidColumns.bind(this);
- this.renderInvalidColumnMessage = this.renderInvalidColumnMessage.bind(this);
+ this.renderInvalidColumnMessage = this.renderInvalidColumnMessage.bind(
+ this,
+ );
}
onClick() {
const timeout = this.props.timeout;
@@ -64,7 +66,7 @@ class ExploreResultsButton extends React.PureComponent {
}),
],
bsSize: 'large',
- onHide: (dialog) => {
+ onHide: dialog => {
dialog.hide();
},
});
@@ -75,7 +77,7 @@ class ExploreResultsButton extends React.PureComponent {
actions: [Dialog.DefaultAction('Ok', () => {}, 'btn-primary')],
bsSize: 'large',
bsStyle: 'warning',
- onHide: (dialog) => {
+ onHide: dialog => {
dialog.hide();
},
});
@@ -85,19 +87,26 @@ class ExploreResultsButton extends React.PureComponent {
}
getColumns() {
const props = this.props;
- if (props.query && props.query.results && props.query.results.selected_columns) {
+ if (
+ props.query &&
+ props.query.results &&
+ props.query.results.selected_columns
+ ) {
return props.query.results.selected_columns;
}
return [];
}
getQueryDuration() {
- return moment.duration(this.props.query.endDttm - this.props.query.startDttm).asSeconds();
+ return moment
+ .duration(this.props.query.endDttm - this.props.query.startDttm)
+ .asSeconds();
}
getInvalidColumns() {
- const re1 = /^[A-Za-z_]\w*$/; // starts with char or _, then only alphanum
- const re2 = /__\d+$/; // does not finish with __ and then a number which screams dup col name
+ const re1 = /^[A-Za-z_]\w*$/; // starts with char or _, then only alphanum
+ const re2 = /__\d+$/; // does not finish with __ and then a number which screams dup col name
- return this.props.query.results.selected_columns.map(col => col.name)
+ return this.props.query.results.selected_columns
+ .map(col => col.name)
.filter(col => !re1.test(col) || re2.test(col));
}
datasourceName() {
@@ -124,7 +133,7 @@ class ExploreResultsButton extends React.PureComponent {
visualize() {
this.props.actions
.createDatasource(this.buildVizOptions())
- .then((data) => {
+ .then(data => {
const columns = this.getColumns();
const formData = {
datasource: `${data.table_id}__table`,
@@ -136,22 +145,36 @@ class ExploreResultsButton extends React.PureComponent {
row_limit: 1000,
};
- this.props.actions.addInfoToast(t('Creating a data source and creating 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);
})
.catch(() => {
- this.props.actions.addDangerToast(this.props.errorMessage || t('An error occurred'));
+ this.props.actions.addDangerToast(
+ this.props.errorMessage || t('An error occurred'),
+ );
});
}
renderTimeoutWarning() {
return (
- {t('This query took %s seconds to run, ', Math.round(this.getQueryDuration())) +
- t('and the explore view times out at %s seconds ', this.props.timeout) +
- t('following this flow will most likely lead to your query timing out. ') +
- t('We recommend your summarize your data further before following that flow. ') +
+ {t(
+ 'This query took %s seconds to run, ',
+ Math.round(this.getQueryDuration()),
+ ) +
+ t(
+ 'and the explore view times out at %s seconds ',
+ this.props.timeout,
+ ) +
+ t(
+ 'following this flow will most likely lead to your query timing out. ',
+ ) +
+ t(
+ 'We recommend your summarize your data further before following that flow. ',
+ ) +
t('If activated you can use the ')}
CREATE TABLE AS
{t('feature to store a summarized data set that you can then explore.')}
@@ -173,7 +196,8 @@ class ExploreResultsButton extends React.PureComponent {
SELECT count(*)
AS my_alias
- ){' '}
+
+ ){' '}
{t(`limited to alphanumeric characters and underscores. Column aliases ending with
double underscores followed by a numeric value are not allowed for reasons
discussed in Github issue #5739.
@@ -182,7 +206,8 @@ class ExploreResultsButton extends React.PureComponent {
);
}
render() {
- const allowsSubquery = this.props.database && this.props.database.allows_subquery;
+ const allowsSubquery =
+ this.props.database && this.props.database.allows_subquery;
return (
<>
- {t('Explore')}
+ {' '}
+ {t('Explore')}
{
+ ref={el => {
this.dialog = el;
}}
/>
diff --git a/superset/assets/src/SqlLab/components/HighlightedSql.jsx b/superset/assets/src/SqlLab/components/HighlightedSql.jsx
index 8769575b23a..8d75be72673 100644
--- a/superset/assets/src/SqlLab/components/HighlightedSql.jsx
+++ b/superset/assets/src/SqlLab/components/HighlightedSql.jsx
@@ -18,7 +18,9 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import SyntaxHighlighter, { registerLanguage } from 'react-syntax-highlighter/dist/light';
+import SyntaxHighlighter, {
+ registerLanguage,
+} from 'react-syntax-highlighter/dist/light';
import sql from 'react-syntax-highlighter/dist/languages/hljs/sql';
import github from 'react-syntax-highlighter/dist/styles/hljs/github';
import { t } from '@superset-ui/translation';
@@ -55,20 +57,24 @@ class HighlightedSql extends React.Component {
lines = lines.slice(0, this.props.maxLines);
lines.push('{...}');
}
- return lines.map((line) => {
- if (line.length > this.props.maxWidth) {
- return line.slice(0, this.props.maxWidth) + '{...}';
- }
- return line;
- })
- .join('\n');
+ return lines
+ .map(line => {
+ if (line.length > this.props.maxWidth) {
+ return line.slice(0, this.props.maxWidth) + '{...}';
+ }
+ return line;
+ })
+ .join('\n');
}
triggerNode() {
- const shownSql = this.props.shrink ? this.shrinkSql(this.props.sql) : this.props.sql;
+ const shownSql = this.props.shrink
+ ? this.shrinkSql(this.props.sql)
+ : this.props.sql;
return (
{shownSql}
- );
+
+ );
}
generateModal() {
let rawSql;
diff --git a/superset/assets/src/SqlLab/components/LimitControl.jsx b/superset/assets/src/SqlLab/components/LimitControl.jsx
index 185d76a6ad9..c5ec5ba9513 100644
--- a/superset/assets/src/SqlLab/components/LimitControl.jsx
+++ b/superset/assets/src/SqlLab/components/LimitControl.jsx
@@ -55,14 +55,19 @@ export default class LimitControl extends React.PureComponent {
}
submitAndClose() {
- const value = parseInt(this.state.textValue, 10) || this.props.defaultQueryLimit;
+ const value =
+ parseInt(this.state.textValue, 10) || this.props.defaultQueryLimit;
this.props.onChange(value);
this.setState({ showOverlay: false });
}
isValidLimit(limit) {
- const value = parseInt(limit, 10);
- return !(Number.isNaN(value) || value <= 0 || (this.props.maxRow && value > this.props.maxRow));
+ const value = parseInt(limit, 10);
+ return !(
+ Number.isNaN(value) ||
+ value <= 0 ||
+ (this.props.maxRow && value > this.props.maxRow)
+ );
}
handleToggle() {
@@ -76,8 +81,11 @@ export default class LimitControl extends React.PureComponent {
renderPopover() {
const textValue = this.state.textValue;
const isValid = this.isValidLimit(textValue);
- const errorMsg = t('Row limit must be positive integer') +
- (this.props.maxRow ? t(' and not greater than %s', this.props.maxRow) : '');
+ const errorMsg =
+ t('Row limit must be positive integer') +
+ (this.props.maxRow
+ ? t(' and not greater than %s', this.props.maxRow)
+ : '');
return (
@@ -107,7 +115,10 @@ export default class LimitControl extends React.PureComponent {
Reset
@@ -120,10 +131,7 @@ export default class LimitControl extends React.PureComponent {
render() {
return (
-
+
LIMIT {this.props.value || this.props.maxRow}
- {this.props.tooltip}
-
- );
+ const tooltip = {this.props.tooltip} ;
const link = (
(
- ['running', 'started', 'pending', 'fetching'].indexOf(q.state) >= 0
- );
+ const isQueryRunning = q =>
+ ['running', 'started', 'pending', 'fetching'].indexOf(q.state) >= 0;
- return (
- Object.values(queries).some(
- q => isQueryRunning(q) &&
- now - q.startDttm < MAX_QUERY_AGE_TO_POLL,
- )
+ return Object.values(queries).some(
+ q => isQueryRunning(q) && now - q.startDttm < MAX_QUERY_AGE_TO_POLL,
);
}
startTimer() {
@@ -75,16 +71,19 @@ class QueryAutoRefresh extends React.PureComponent {
// only poll /superset/queries/ if there are started or running queries
if (this.shouldCheckForQueries()) {
SupersetClient.get({
- endpoint: `/superset/queries/${this.props.queriesLastUpdate - QUERY_UPDATE_BUFFER_MS}`,
+ endpoint: `/superset/queries/${this.props.queriesLastUpdate -
+ QUERY_UPDATE_BUFFER_MS}`,
timeout: QUERY_TIMEOUT_LIMIT,
- }).then(({ json }) => {
- if (Object.keys(json).length > 0) {
- this.props.actions.refreshQueries(json);
- }
- this.setState({ offline: false });
- }).catch(() => {
- this.setState({ offline: true });
- });
+ })
+ .then(({ json }) => {
+ if (Object.keys(json).length > 0) {
+ this.props.actions.refreshQueries(json);
+ }
+ this.setState({ offline: false });
+ })
+ .catch(() => {
+ this.setState({ offline: true });
+ });
} else {
this.setState({ offline: false });
}
@@ -114,7 +113,4 @@ function mapDispatchToProps(dispatch) {
};
}
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(QueryAutoRefresh);
+export default connect(mapStateToProps, mapDispatchToProps)(QueryAutoRefresh);
diff --git a/superset/assets/src/SqlLab/components/QueryHistory.jsx b/superset/assets/src/SqlLab/components/QueryHistory.jsx
index 738ee901bcb..a40b813ff8b 100644
--- a/superset/assets/src/SqlLab/components/QueryHistory.jsx
+++ b/superset/assets/src/SqlLab/components/QueryHistory.jsx
@@ -29,13 +29,19 @@ const propTypes = {
displayLimit: PropTypes.number.isRequired,
};
-const QueryHistory = (props) => {
+const QueryHistory = props => {
if (props.queries.length > 0) {
return (
{
/>
);
}
- return (
-
- {t('No query history yet...')}
-
- );
+ return {t('No query history yet...')} ;
};
QueryHistory.propTypes = propTypes;
diff --git a/superset/assets/src/SqlLab/components/QuerySearch.jsx b/superset/assets/src/SqlLab/components/QuerySearch.jsx
index 97d2ae53fe8..c22622d64cc 100644
--- a/superset/assets/src/SqlLab/components/QuerySearch.jsx
+++ b/superset/assets/src/SqlLab/components/QuerySearch.jsx
@@ -133,7 +133,7 @@ class QuerySearch extends React.PureComponent {
}
insertParams(baseUrl, params) {
- const validParams = params.filter(function (p) {
+ const validParams = params.filter(function(p) {
return p !== '';
});
return baseUrl + '?' + validParams.join('&');
@@ -158,16 +158,24 @@ class QuerySearch extends React.PureComponent {
userMutator(data) {
const options = [];
for (let i = 0; i < data.pks.length; i++) {
- options.push({ value: data.pks[i], label: this.userLabel(data.result[i]) });
+ options.push({
+ value: data.pks[i],
+ label: this.userLabel(data.result[i]),
+ });
}
return options;
}
dbMutator(data) {
- const options = data.result.map(db => ({ value: db.id, label: db.database_name }));
+ 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.addDangerToast(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;
}
@@ -179,16 +187,22 @@ class QuerySearch extends React.PureComponent {
this.state.databaseId ? `database_id=${this.state.databaseId}` : '',
this.state.searchText ? `search_text=${this.state.searchText}` : '',
this.state.status ? `status=${this.state.status}` : '',
- this.state.from ? `from=${this.getTimeFromSelection(this.state.from)}` : '',
+ this.state.from
+ ? `from=${this.getTimeFromSelection(this.state.from)}`
+ : '',
this.state.to ? `to=${this.getTimeFromSelection(this.state.to)}` : '',
];
- SupersetClient.get({ endpoint: this.insertParams('/superset/search_queries', params) })
+ SupersetClient.get({
+ endpoint: this.insertParams('/superset/search_queries', params),
+ })
.then(({ json }) => {
this.setState({ queriesArray: json, queriesLoading: false });
})
.catch(() => {
- this.props.actions.addDangerToast(t('An error occurred when refreshing queries'));
+ this.props.actions.addDangerToast(
+ t('An error occurred when refreshing queries'),
+ );
});
}
@@ -248,14 +262,21 @@ class QuerySearch extends React.PureComponent {
({ value: s, label: s }))}
+ options={Object.keys(STATUS_OPTIONS).map(s => ({
+ value: s,
+ label: s,
+ }))}
value={this.state.status}
isLoading={false}
autosize={false}
onChange={this.changeStatus}
/>
-
+
{t('Search')}
@@ -264,9 +285,21 @@ class QuerySearch extends React.PureComponent {
{this.state.queriesLoading ? (
) : (
-
+
{ },
- onDbClicked: () => { },
+ onUserClicked: () => {},
+ onDbClicked: () => {},
};
class QueryTable extends React.PureComponent {
@@ -93,7 +93,7 @@ class QueryTable extends React.PureComponent {
}
render() {
const data = this.props.queries
- .map((query) => {
+ .map(query => {
const q = Object.assign({}, query);
if (q.endDttm) {
q.duration = fDuration(q.startDttm, q.endDttm);
@@ -138,7 +138,12 @@ class QueryTable extends React.PureComponent {
);
q.sql = (
-
+
);
if (q.resultsKey) {
@@ -152,7 +157,11 @@ class QueryTable extends React.PureComponent {
}
modalTitle={t('Data preview')}
- beforeOpen={this.openAsyncResults.bind(this, query, this.props.displayLimit)}
+ beforeOpen={this.openAsyncResults.bind(
+ this,
+ query,
+ this.props.displayLimit,
+ )}
onExit={this.clearQueryResults.bind(this, query)}
modalBody={
v).join('.');
}
q.progress = (
@@ -198,7 +208,9 @@ class QueryTable extends React.PureComponent {
0) {
+ if (
+ this.props.cache &&
+ !nextProps.query.cached &&
+ nextProps.query.results &&
+ nextProps.query.results.data &&
+ nextProps.query.results.data.length > 0
+ ) {
this.setState(
{ data: nextProps.query.results.data },
this.clearQueryResults(nextProps.query),
);
}
- if (nextProps.query.resultsKey
- && nextProps.query.resultsKey !== this.props.query.resultsKey) {
+ if (
+ nextProps.query.resultsKey &&
+ nextProps.query.resultsKey !== this.props.query.resultsKey
+ ) {
this.fetchResults(nextProps.query);
}
}
@@ -100,7 +107,9 @@ export default class ResultSet extends React.PureComponent {
this.props.actions.addQueryEditor(qe);
}
toggleExploreResultsButton() {
- this.setState({ showExploreResultsButton: !this.state.showExploreResultsButton });
+ this.setState({
+ showExploreResultsButton: !this.state.showExploreResultsButton,
+ });
}
changeSearch(event) {
this.setState({ searchText: event.target.value });
@@ -113,7 +122,10 @@ export default class ResultSet extends React.PureComponent {
}
reRunQueryIfSessionTimeoutErrorOnMount() {
const { query } = this.props;
- if (query.errorMessage && query.errorMessage.indexOf('session timed out') > 0) {
+ if (
+ query.errorMessage &&
+ query.errorMessage.indexOf('session timed out') > 0
+ ) {
this.props.actions.runQuery(query, true);
}
}
@@ -128,16 +140,21 @@ export default class ResultSet extends React.PureComponent {
@@ -169,8 +186,10 @@ export default class ResultSet extends React.PureComponent {
}
render() {
const query = this.props.query;
- const height = Math.max(0,
- (this.props.search ? this.props.height - SEARCH_HEIGHT : this.props.height));
+ const height = Math.max(
+ 0,
+ this.props.search ? this.props.height - SEARCH_HEIGHT : this.props.height,
+ );
let sql;
if (this.props.showSql) {
@@ -184,13 +203,14 @@ export default class ResultSet extends React.PureComponent {
{query.errorMessage}
{query.link && {t('(Request Access)')} }
- );
+
+ );
} else if (query.state === 'success' && query.ctas) {
return (
- {t('Table')} [{query.tempTable} ] {t('was ' +
- 'created')}
+ {t('Table')} [{query.tempTable} ] {t('was created')}{' '}
+
-
);
+
+ );
} else if (query.state === 'success' && query.results) {
const results = query.results;
let data;
@@ -226,7 +247,9 @@ export default class ResultSet extends React.PureComponent {
>
);
} else if (data && data.length === 0) {
- return
{t('The query returned no data')} ;
+ return (
+
{t('The query returned no data')}
+ );
}
}
if (query.cached || (query.state === 'success' && !query.results)) {
@@ -235,7 +258,10 @@ export default class ResultSet extends React.PureComponent {
bsSize="sm"
className="fetch"
bsStyle="primary"
- onClick={this.reFetchQueryResults.bind(this, { ...query, isDataPreview: true })}
+ onClick={this.reFetchQueryResults.bind(this, {
+ ...query,
+ isDataPreview: true,
+ })}
>
{t('Fetch data preview')}
@@ -249,34 +275,34 @@ export default class ResultSet extends React.PureComponent {
striped
now={query.progress}
label={`${query.progress.toFixed(0)}%`}
- />);
+ />
+ );
}
if (query.trackingUrl) {
trackingUrl = (
{ window.open(query.trackingUrl); }}
+ onClick={() => {
+ window.open(query.trackingUrl);
+ }}
>
{t('Track Job')}
);
}
- const progressMsg = query && query.extra && query.extra.progress ? query.extra.progress : null;
+ const progressMsg =
+ query && query.extra && query.extra.progress
+ ? query.extra.progress
+ : null;
return (
-
- {!progressBar && }
-
+
{!progressBar && }
{progressMsg &&
{progressMsg} }
-
- {progressBar}
-
-
- {trackingUrl}
-
+
{progressBar}
+
{trackingUrl}
);
}
diff --git a/superset/assets/src/SqlLab/components/RunQueryActionButton.jsx b/superset/assets/src/SqlLab/components/RunQueryActionButton.jsx
index 37337a86577..218d66a76a4 100644
--- a/superset/assets/src/SqlLab/components/RunQueryActionButton.jsx
+++ b/superset/assets/src/SqlLab/components/RunQueryActionButton.jsx
@@ -37,22 +37,22 @@ const defaultProps = {
};
export default function RunQueryActionButton(props) {
- const runBtnText = props.selectedText ? t('Run Selected Query') : t('Run Query');
+ const runBtnText = props.selectedText
+ ? t('Run Selected Query')
+ : t('Run Query');
const btnStyle = props.selectedText ? 'warning' : 'primary';
- const shouldShowStopBtn = ['running', 'pending'].indexOf(props.queryState) > -1;
+ const shouldShowStopBtn =
+ ['running', 'pending'].indexOf(props.queryState) > -1;
const commonBtnProps = {
bsSize: 'small',
bsStyle: btnStyle,
- disabled: !(props.dbId),
+ disabled: !props.dbId,
};
if (shouldShowStopBtn) {
return (
-
+
{t('Stop')}
);
@@ -66,7 +66,8 @@ export default function RunQueryActionButton(props) {
disabled={!props.sql.trim()}
>
{runBtnText}
- );
+
+ );
}
return (
- {t('Description')}
+
+ {t('Description')}
+
-
- {this.props.saveQueryWarning}
-
+ {this.props.saveQueryWarning}
@@ -160,12 +160,18 @@ class SaveQuery extends React.PureComponent {
return (
{ this.saveModal = ref; }}
+ ref={ref => {
+ this.saveModal = ref;
+ }}
modalTitle={t('Save Query')}
modalBody={this.renderModalBody()}
backdrop="static"
triggerNode={
-
+
{t('Save Query')}
}
diff --git a/superset/assets/src/SqlLab/components/ScheduleQueryButton.jsx b/superset/assets/src/SqlLab/components/ScheduleQueryButton.jsx
index 09a7ddb3b22..207b26e59a8 100644
--- a/superset/assets/src/SqlLab/components/ScheduleQueryButton.jsx
+++ b/superset/assets/src/SqlLab/components/ScheduleQueryButton.jsx
@@ -58,7 +58,7 @@ function getValidationRules() {
function getValidator() {
const rules = getValidationRules();
return (formData, errors) => {
- rules.forEach((rule) => {
+ rules.forEach(rule => {
const test = validators[rule.name];
const args = rule.arguments.map(name => formData[name]);
const container = rule.container || rule.arguments.slice(-1)[0];
@@ -181,7 +181,7 @@ class ScheduleQueryButton extends React.PureComponent {
return (
{
+ ref={ref => {
this.saveModal = ref;
}}
modalTitle={t('Schedule Query')}
diff --git a/superset/assets/src/SqlLab/components/ShareSqlLabQuery.jsx b/superset/assets/src/SqlLab/components/ShareSqlLabQuery.jsx
index 176a4fc77dd..29313dc2470 100644
--- a/superset/assets/src/SqlLab/components/ShareSqlLabQuery.jsx
+++ b/superset/assets/src/SqlLab/components/ShareSqlLabQuery.jsx
@@ -52,10 +52,10 @@ class ShareSqlLabQuery extends React.Component {
const sharedQuery = { dbId, title, schema, autorun, sql };
return storeQuery(sharedQuery)
- .then((shortUrl) => {
+ .then(shortUrl => {
this.setState({ shortUrl });
})
- .catch((response) => {
+ .catch(response => {
getClientErrorObject(response).then(({ error }) => {
this.props.addDangerToast(error);
this.setState({ shortUrl: t('Error') });
@@ -68,7 +68,9 @@ class ShareSqlLabQuery extends React.Component {
}
+ copyNode={
+
+ }
/>
);
diff --git a/superset/assets/src/SqlLab/components/ShowSQL.jsx b/superset/assets/src/SqlLab/components/ShowSQL.jsx
index 45da9aa3cd5..10180f76139 100644
--- a/superset/assets/src/SqlLab/components/ShowSQL.jsx
+++ b/superset/assets/src/SqlLab/components/ShowSQL.jsx
@@ -18,7 +18,9 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import SyntaxHighlighter, { registerLanguage } from 'react-syntax-highlighter/dist/light';
+import SyntaxHighlighter, {
+ registerLanguage,
+} from 'react-syntax-highlighter/dist/light';
import sql from 'react-syntax-highlighter/dist/languages/hljs/sql';
import github from 'react-syntax-highlighter/dist/styles/hljs/github';
diff --git a/superset/assets/src/SqlLab/components/SouthPane.jsx b/superset/assets/src/SqlLab/components/SouthPane.jsx
index 3f747a8af9d..54c0dc34995 100644
--- a/superset/assets/src/SqlLab/components/SouthPane.jsx
+++ b/superset/assets/src/SqlLab/components/SouthPane.jsx
@@ -28,7 +28,11 @@ import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
import * as Actions from '../actions/sqlLab';
import QueryHistory from './QueryHistory';
import ResultSet from './ResultSet';
-import { STATUS_OPTIONS, STATE_BSSTYLE_MAP, LOCALSTORAGE_MAX_QUERY_AGE_MS } from '../constants';
+import {
+ STATUS_OPTIONS,
+ STATE_BSSTYLE_MAP,
+ LOCALSTORAGE_MAX_QUERY_AGE_MS,
+} from '../constants';
const TAB_HEIGHT = 44;
@@ -69,7 +73,9 @@ export class SouthPane extends React.PureComponent {
}
// One layer of abstraction for easy spying in unit tests
getSouthPaneHeight() {
- return this.southPaneRef.current ? this.southPaneRef.current.clientHeight : 0;
+ return this.southPaneRef.current
+ ? this.southPaneRef.current.clientHeight
+ : 0;
}
switchTab(id) {
this.props.actions.setActiveSouthPaneTab(id);
@@ -77,26 +83,40 @@ export class SouthPane extends React.PureComponent {
render() {
if (this.props.offline) {
return (
-
- { STATUS_OPTIONS.offline }
- );
+
+ {STATUS_OPTIONS.offline}
+
+ );
}
const innerTabContentHeight = this.state.height - TAB_HEIGHT;
let latestQuery;
const props = this.props;
if (props.editorQueries.length > 0) {
// get the latest query
- latestQuery = props.editorQueries.find(q => q.id === this.props.latestQueryId);
+ latestQuery = props.editorQueries.find(
+ q => q.id === this.props.latestQueryId,
+ );
}
let results;
if (latestQuery) {
if (
isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE) &&
latestQuery.state === 'success' &&
- (!latestQuery.resultsKey && !latestQuery.results)
+ !latestQuery.resultsKey &&
+ !latestQuery.results
+ ) {
+ results = (
+
+ {t('No stored results found, you need to re-run your query')}
+
+ );
+ } else if (
+ Date.now() - latestQuery.startDttm <=
+ LOCALSTORAGE_MAX_QUERY_AGE_MS
) {
- results = {t('No stored results found, you need to re-run your query')} ;
- } else if ((Date.now() - latestQuery.startDttm) <= LOCALSTORAGE_MAX_QUERY_AGE_MS) {
results = (
{t('Run a query to display results here')};
+ results = (
+ {t('Run a query to display results here')}
+ );
}
const dataPreviewTabs = props.dataPreviewQueries.map(query => (
-
+
{results}
-
+
= 0) {
+ if (
+ this.props.latestQuery &&
+ ['running', 'pending'].indexOf(this.props.latestQuery.state) >= 0
+ ) {
this.props.actions.postStopQuery(this.props.latestQuery);
}
}
@@ -297,7 +314,10 @@ class SqlEditor extends React.PureComponent {
}
queryPane() {
const hotkeys = this.getHotkeyConfig();
- const { aceEditorHeight, southPaneHeight } = this.getAceEditorAndSouthPaneHeights(
+ const {
+ aceEditorHeight,
+ southPaneHeight,
+ } = this.getAceEditorAndSouthPaneHeights(
this.state.height,
this.state.northPercent,
this.state.southPercent,
@@ -370,15 +390,18 @@ class SqlEditor extends React.PureComponent {
const qe = this.props.queryEditor;
let limitWarning = null;
if (
- this.props.latestQuery
- && this.props.latestQuery.results
- && this.props.latestQuery.results.displayLimitReached
+ this.props.latestQuery &&
+ this.props.latestQuery.results &&
+ this.props.latestQuery.results.displayLimitReached
) {
const tooltip = (
- {t(`It appears that the number of rows in the query results displayed
+ {t(
+ `It appears that the number of rows in the query results displayed
was limited on the server side to
- the %s limit.`, this.props.latestQuery.rows)}
+ the %s limit.`,
+ this.props.latestQuery.rows,
+ )}
);
limitWarning = (
@@ -387,7 +410,8 @@ class SqlEditor extends React.PureComponent {
);
}
- const successful = this.props.latestQuery && this.props.latestQuery.state === 'success';
+ const successful =
+ this.props.latestQuery && this.props.latestQuery.state === 'success';
const scheduleToolTip = successful
? t('Schedule the query periodically')
: t('You must run the query successfully first');
@@ -397,49 +421,56 @@ class SqlEditor extends React.PureComponent {
{
+ onChange={params => {
this.props.actions.queryEditorSetTemplateParams(qe, params);
}}
code={qe.templateParams}
/>
{limitWarning}
- {this.props.latestQuery &&
+ {this.props.latestQuery && (
- }
+ )}
);
diff --git a/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx b/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
index bf7afff727b..0f2ac94b03e 100644
--- a/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
+++ b/superset/assets/src/SqlLab/components/SqlEditorLeftBar.jsx
@@ -54,10 +54,16 @@ export default class SqlEditorLeftBar extends React.PureComponent {
this.props.actions.queryEditorSetSchema(this.props.queryEditor, schema);
}
onSchemasLoad(schemas) {
- this.props.actions.queryEditorSetSchemaOptions(this.props.queryEditor, schemas);
+ this.props.actions.queryEditorSetSchemaOptions(
+ this.props.queryEditor,
+ schemas,
+ );
}
onTablesLoad(tables) {
- this.props.actions.queryEditorSetTableOptions(this.props.queryEditor, tables);
+ this.props.actions.queryEditorSetTableOptions(
+ this.props.queryEditor,
+ tables,
+ );
}
onDbChange(db) {
this.props.actions.queryEditorSetDb(this.props.queryEditor, db.id);
@@ -76,7 +82,9 @@ export default class SqlEditorLeftBar extends React.PureComponent {
}));
this.props.actions.setDatabases(data.result);
if (data.result.length === 0) {
- this.props.actions.addDangerToast(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;
}
@@ -118,9 +126,16 @@ export default class SqlEditorLeftBar extends React.PureComponent {
/>
-
+
{this.props.tables.map(table => (
-
+
))}
diff --git a/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx b/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
index 8ffd097f13f..b47d7921f05 100644
--- a/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
+++ b/superset/assets/src/SqlLab/components/TabbedSqlEditors.jsx
@@ -67,22 +67,36 @@ class TabbedSqlEditors extends React.PureComponent {
this.removeQueryEditor = this.removeQueryEditor.bind(this);
this.renameTab = this.renameTab.bind(this);
this.toggleLeftBar = this.toggleLeftBar.bind(this);
- this.removeAllOtherQueryEditors = this.removeAllOtherQueryEditors.bind(this);
+ this.removeAllOtherQueryEditors = this.removeAllOtherQueryEditors.bind(
+ this,
+ );
this.duplicateQueryEditor = this.duplicateQueryEditor.bind(this);
}
componentDidMount() {
// migrate query editor and associated tables state to server
if (isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)) {
- const localStorageTables = this.props.tables.filter(table => table.inLocalStorage);
- const localStorageQueries = Object.values(this.props.queries)
- .filter(query => query.inLocalStorage);
- this.props.queryEditors.filter(qe => qe.inLocalStorage).forEach((qe) => {
- // get all queries associated with the query editor
- const queries = localStorageQueries
- .filter(query => query.sqlEditorId === qe.id);
- const tables = localStorageTables.filter(table => table.queryEditorId === qe.id);
- this.props.actions.migrateQueryEditorFromLocalStorage(qe, tables, queries);
- });
+ const localStorageTables = this.props.tables.filter(
+ table => table.inLocalStorage,
+ );
+ const localStorageQueries = Object.values(this.props.queries).filter(
+ query => query.inLocalStorage,
+ );
+ this.props.queryEditors
+ .filter(qe => qe.inLocalStorage)
+ .forEach(qe => {
+ // get all queries associated with the query editor
+ const queries = localStorageQueries.filter(
+ query => query.sqlEditorId === qe.id,
+ );
+ const tables = localStorageTables.filter(
+ table => table.queryEditorId === qe.id,
+ );
+ this.props.actions.migrateQueryEditorFromLocalStorage(
+ qe,
+ tables,
+ queries,
+ );
+ });
}
const query = URI(window.location).search(true);
@@ -102,7 +116,7 @@ class TabbedSqlEditors extends React.PureComponent {
const databases = this.props.databases;
const dbName = query.dbname;
if (dbName) {
- Object.keys(databases).forEach((db) => {
+ Object.keys(databases).forEach(db => {
if (databases[db].database_name === dbName) {
dbId = databases[db].id;
}
@@ -126,16 +140,21 @@ class TabbedSqlEditors extends React.PureComponent {
const latestQuery = this.props.queries[qe.latestQueryId];
if (
isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE) &&
- latestQuery && latestQuery.resultsKey
+ latestQuery &&
+ latestQuery.resultsKey
) {
// when results are not stored in localStorage they need to be
// fetched from the results backend (if configured)
- this.props.actions.fetchQueryResults(latestQuery, this.props.displayLimit);
+ this.props.actions.fetchQueryResults(
+ latestQuery,
+ this.props.displayLimit,
+ );
}
}
}
UNSAFE_componentWillReceiveProps(nextProps) {
- const nextActiveQeId = nextProps.tabHistory[nextProps.tabHistory.length - 1];
+ const nextActiveQeId =
+ nextProps.tabHistory[nextProps.tabHistory.length - 1];
const queriesArray = [];
for (const id in nextProps.queries) {
if (nextProps.queries[id].sqlEditorId === nextActiveQeId) {
@@ -147,13 +166,22 @@ class TabbedSqlEditors extends React.PureComponent {
}
const dataPreviewQueries = [];
- nextProps.tables.forEach((table) => {
+ nextProps.tables.forEach(table => {
const queryId = table.dataPreviewQueryId;
- if (queryId && nextProps.queries[queryId] && table.queryEditorId === nextActiveQeId) {
- dataPreviewQueries.push({ ...nextProps.queries[queryId], tableName: table.name });
+ if (
+ queryId &&
+ nextProps.queries[queryId] &&
+ table.queryEditorId === nextActiveQeId
+ ) {
+ dataPreviewQueries.push({
+ ...nextProps.queries[queryId],
+ tableName: table.name,
+ });
}
});
- if (!areArraysShallowEqual(dataPreviewQueries, this.state.dataPreviewQueries)) {
+ if (
+ !areArraysShallowEqual(dataPreviewQueries, this.state.dataPreviewQueries)
+ ) {
this.setState({ dataPreviewQueries });
}
}
@@ -180,7 +208,8 @@ class TabbedSqlEditors extends React.PureComponent {
queryCount++;
const activeQueryEditor = this.activeQueryEditor();
const firstDbId = Math.min(
- ...Object.values(this.props.databases).map(database => database.id));
+ ...Object.values(this.props.databases).map(database => database.id),
+ );
const warning = isFeatureEnabled(FeatureFlag.SQLLAB_BACKEND_PERSISTENCE)
? ''
: `${t(
@@ -191,7 +220,7 @@ class TabbedSqlEditors extends React.PureComponent {
dbId:
activeQueryEditor && activeQueryEditor.dbId
? activeQueryEditor.dbId
- : (this.props.defaultDbId || firstDbId),
+ : this.props.defaultDbId || firstDbId,
schema: activeQueryEditor ? activeQueryEditor.schema : null,
autorun: false,
sql: `${warning}SELECT ...`,
@@ -206,7 +235,10 @@ class TabbedSqlEditors extends React.PureComponent {
const qeid = this.props.tabHistory[this.props.tabHistory.length - 1];
if (key !== qeid) {
const queryEditor = this.props.queryEditors.find(qe => qe.id === key);
- this.props.actions.switchQueryEditor(queryEditor, this.props.displayLimit);
+ this.props.actions.switchQueryEditor(
+ queryEditor,
+ this.props.displayLimit,
+ );
}
}
}
@@ -214,8 +246,9 @@ class TabbedSqlEditors extends React.PureComponent {
this.props.actions.removeQueryEditor(qe);
}
removeAllOtherQueryEditors(cqe) {
- this.props.queryEditors
- .forEach(qe => qe !== cqe && this.removeQueryEditor(qe));
+ this.props.queryEditors.forEach(
+ qe => qe !== cqe && this.removeQueryEditor(qe),
+ );
}
duplicateQueryEditor(qe) {
this.props.actions.cloneQueryToNewTab(qe, false);
@@ -225,7 +258,8 @@ class TabbedSqlEditors extends React.PureComponent {
}
render() {
const editors = this.props.queryEditors.map((qe, i) => {
- const isSelected = this.activeQueryEditor() && this.activeQueryEditor().id === qe.id;
+ const isSelected =
+ this.activeQueryEditor() && this.activeQueryEditor().id === qe.id;
let latestQuery;
if (qe.latestQueryId) {
@@ -239,7 +273,10 @@ class TabbedSqlEditors extends React.PureComponent {
const title = (
<>
-
this.removeQueryEditor(qe)} tabState={state} />{' '}
+ this.removeQueryEditor(qe)}
+ tabState={state}
+ />{' '}
{qe.title}{' '}
>
);
@@ -268,7 +305,10 @@ class TabbedSqlEditors extends React.PureComponent {
{this.state.hideLeftBar ? t('Expand tool bar') : t('Hide tool bar')}
- this.removeAllOtherQueryEditors(qe)}>
+ this.removeAllOtherQueryEditors(qe)}
+ >
@@ -286,7 +326,9 @@ class TabbedSqlEditors extends React.PureComponent {
{isSelected && (
xt.queryEditorId === qe.id)}
+ tables={this.props.tables.filter(
+ xt => xt.queryEditorId === qe.id,
+ )}
queryEditor={qe}
editorQueries={this.state.queriesArray}
dataPreviewQueries={this.state.dataPreviewQueries}
@@ -317,7 +359,8 @@ class TabbedSqlEditors extends React.PureComponent {
-
+
+
}
className="addEditorTab"
@@ -355,7 +398,4 @@ function mapDispatchToProps(dispatch) {
export { TabbedSqlEditors };
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(TabbedSqlEditors);
+export default connect(mapStateToProps, mapDispatchToProps)(TabbedSqlEditors);
diff --git a/superset/assets/src/SqlLab/components/TableElement.jsx b/superset/assets/src/SqlLab/components/TableElement.jsx
index a1ba5a567ab..c8e96a9960c 100644
--- a/superset/assets/src/SqlLab/components/TableElement.jsx
+++ b/superset/assets/src/SqlLab/components/TableElement.jsx
@@ -32,7 +32,7 @@ import Loading from '../../components/Loading';
const propTypes = {
table: PropTypes.object,
actions: PropTypes.object,
- timeout: PropTypes.number, // used for tests
+ timeout: PropTypes.number, // used for tests
};
const defaultProps = {
@@ -119,7 +119,8 @@ class TableElement extends React.PureComponent {
{t('latest partition:')} {latest}
- {partitionClipBoard}
+ {' '}
+ {partitionClipBoard}
);
@@ -155,31 +156,31 @@ class TableElement extends React.PureComponent {
- {table.selectStar &&
+ {table.selectStar && (
- }
+ copyNode={ }
text={table.selectStar}
shouldShowText={false}
tooltipText={t('Copy SELECT statement to the clipboard')}
/>
- }
- {table.view &&
+ )}
+ {table.view && (
- }
+ )}
{ this.toggleTable(e); }}
+ onClick={e => {
+ this.toggleTable(e);
+ }}
>
-
- {table.name}
-
+ {table.name}
- {table.isMetadataLoading || table.isExtraMetadataLoading ?
-
- :
-
- {this.renderControls()}
-
- }
+ {table.isMetadataLoading || table.isExtraMetadataLoading ? (
+
+ ) : (
+ {this.renderControls()}
+ )}
{ this.toggleTable(e); }}
- className={(
+ onClick={e => {
+ this.toggleTable(e);
+ }}
+ className={
'text-primary pointer m-l-10 ' +
'fa fa-lg ' +
`fa-angle-${table.expanded ? 'up' : 'down'}`
- )}
+ }
/>
@@ -247,16 +244,12 @@ class TableElement extends React.PureComponent {
}
}
const metadata = (
-
+
{this.renderWell()}
- {cols && cols.map(col => (
-
- ))}
+ {cols &&
+ cols.map(col => )}
@@ -277,9 +270,7 @@ class TableElement extends React.PureComponent {
onMouseLeave={() => this.setHover(false)}
>
{this.renderHeader()}
-
- {this.renderBody()}
-
+ {this.renderBody()}
);
diff --git a/superset/assets/src/SqlLab/components/TemplateParamsEditor.jsx b/superset/assets/src/SqlLab/components/TemplateParamsEditor.jsx
index 07746902f57..c907ce26a15 100644
--- a/superset/assets/src/SqlLab/components/TemplateParamsEditor.jsx
+++ b/superset/assets/src/SqlLab/components/TemplateParamsEditor.jsx
@@ -91,7 +91,8 @@ export default class TemplateParamsEditor extends React.Component {
rel="noopener noreferrer"
>
Jinja templating
- syntax.
+ {' '}
+ syntax.
);
}
@@ -115,26 +116,24 @@ export default class TemplateParamsEditor extends React.Component {
);
}
render() {
- const paramCount = this.state.parsedJSON ? Object.keys(this.state.parsedJSON).length : 0;
+ const paramCount = this.state.parsedJSON
+ ? Object.keys(this.state.parsedJSON).length
+ : 0;
return (
+
{`${t('parameters')} `}
- {paramCount > 0 &&
- {paramCount}
- }
- {!this.state.isValid &&
+ {paramCount > 0 && {paramCount} }
+ {!this.state.isValid && (
- }
+ )}
}
modalBody={this.renderModalBody(true)}
diff --git a/superset/assets/src/SqlLab/index.jsx b/superset/assets/src/SqlLab/index.jsx
index f2547e79a30..c257009e64f 100644
--- a/superset/assets/src/SqlLab/index.jsx
+++ b/superset/assets/src/SqlLab/index.jsx
@@ -20,7 +20,4 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
-ReactDOM.render(
- ,
- document.getElementById('app'),
-);
+ReactDOM.render( , document.getElementById('app'));
diff --git a/superset/assets/src/SqlLab/main.less b/superset/assets/src/SqlLab/main.less
index e06cb333bd5..6ebfcba8a61 100644
--- a/superset/assets/src/SqlLab/main.less
+++ b/superset/assets/src/SqlLab/main.less
@@ -16,8 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../stylesheets/less/cosmo/variables.less";
-@import "../../stylesheets/less/variables.less";
+@import '../../stylesheets/less/cosmo/variables.less';
+@import '../../stylesheets/less/variables.less';
body {
overflow: hidden;
diff --git a/superset/assets/src/SqlLab/reducers/getInitialState.js b/superset/assets/src/SqlLab/reducers/getInitialState.js
index 220d5981375..dbefed7db84 100644
--- a/superset/assets/src/SqlLab/reducers/getInitialState.js
+++ b/superset/assets/src/SqlLab/reducers/getInitialState.js
@@ -65,7 +65,9 @@ export default function getInitialState({ defaultDbId, ...restBootstrapData }) {
title: activeTab.label,
sql: activeTab.sql,
selectedText: null,
- latestQueryId: activeTab.latest_query ? activeTab.latest_query.id : null,
+ latestQueryId: activeTab.latest_query
+ ? activeTab.latest_query.id
+ : null,
autorun: activeTab.autorun,
templateParams: activeTab.template_params,
dbId: activeTab.database_id,
@@ -93,7 +95,7 @@ export default function getInitialState({ defaultDbId, ...restBootstrapData }) {
const tables = [];
if (activeTab) {
- activeTab.table_schemas.forEach((tableSchema) => {
+ activeTab.table_schemas.forEach(tableSchema => {
const {
columns,
selectStar,
@@ -128,7 +130,10 @@ export default function getInitialState({ defaultDbId, ...restBootstrapData }) {
* hasn't used SQL Lab after it has been turned on, the state will be stored
* in the browser's local storage.
*/
- if (localStorage.getItem('redux') && JSON.parse(localStorage.getItem('redux')).sqlLab) {
+ if (
+ localStorage.getItem('redux') &&
+ JSON.parse(localStorage.getItem('redux')).sqlLab
+ ) {
const sqlLab = JSON.parse(localStorage.getItem('redux')).sqlLab;
if (sqlLab.queryEditors.length === 0) {
@@ -137,13 +142,17 @@ export default function getInitialState({ defaultDbId, ...restBootstrapData }) {
} else {
// add query editors and tables to state with a special flag so they can
// be migrated if the `SQLLAB_BACKEND_PERSISTENCE` feature flag is on
- sqlLab.queryEditors.forEach(qe => queryEditors.push({
- ...qe,
- inLocalStorage: true,
- loaded: true,
- }));
- sqlLab.tables.forEach(table => tables.push({ ...table, inLocalStorage: true }));
- Object.values(sqlLab.queries).forEach((query) => {
+ sqlLab.queryEditors.forEach(qe =>
+ queryEditors.push({
+ ...qe,
+ inLocalStorage: true,
+ loaded: true,
+ }),
+ );
+ sqlLab.tables.forEach(table =>
+ tables.push({ ...table, inLocalStorage: true }),
+ );
+ Object.values(sqlLab.queries).forEach(query => {
queries[query.id] = { ...query, inLocalStorage: true };
});
tabHistory.push(...sqlLab.tabHistory);
diff --git a/superset/assets/src/SqlLab/reducers/sqlLab.js b/superset/assets/src/SqlLab/reducers/sqlLab.js
index 03547b36f6a..d751917e9f4 100644
--- a/superset/assets/src/SqlLab/reducers/sqlLab.js
+++ b/superset/assets/src/SqlLab/reducers/sqlLab.js
@@ -42,16 +42,28 @@ export default function sqlLabReducer(state = {}, action) {
[actions.QUERY_EDITOR_SAVED]() {
const { query, result } = action;
const existing = state.queryEditors.find(qe => qe.id === query.id);
- return alterInArr(state, 'queryEditors', existing, {
- remoteId: result.remoteId,
- title: query.title,
- }, 'id');
+ return alterInArr(
+ state,
+ 'queryEditors',
+ existing,
+ {
+ remoteId: result.remoteId,
+ title: query.title,
+ },
+ 'id',
+ );
},
[actions.UPDATE_QUERY_EDITOR]() {
const id = action.alterations.remoteId;
const existing = state.queryEditors.find(qe => qe.remoteId === id);
if (existing == null) return state;
- return alterInArr(state, 'queryEditors', existing, action.alterations, 'remoteId');
+ return alterInArr(
+ state,
+ 'queryEditors',
+ existing,
+ action.alterations,
+ 'remoteId',
+ );
},
[actions.CLONE_QUERY_TO_NEW_TAB]() {
const progenitor = state.queryEditors.find(
@@ -75,7 +87,7 @@ export default function sqlLabReducer(state = {}, action) {
const qeIds = newState.queryEditors.map(qe => qe.id);
const queries = {};
- Object.keys(state.queries).forEach((k) => {
+ Object.keys(state.queries).forEach(k => {
const query = state.queries[k];
if (qeIds.indexOf(query.sqlEditorId) > -1) {
queries[k] = query;
@@ -86,7 +98,9 @@ export default function sqlLabReducer(state = {}, action) {
tabHistory = tabHistory.filter(id => qeIds.indexOf(id) > -1);
// Remove associated table schemas
- const tables = state.tables.filter(table => table.queryEditorId !== action.queryEditor.id);
+ const tables = state.tables.filter(
+ table => table.queryEditorId !== action.queryEditor.id,
+ );
newState = Object.assign({}, newState, { tabHistory, tables, queries });
return newState;
@@ -102,7 +116,7 @@ export default function sqlLabReducer(state = {}, action) {
[actions.MERGE_TABLE]() {
const at = Object.assign({}, action.table);
let existingTable;
- state.tables.forEach((xt) => {
+ state.tables.forEach(xt => {
if (
xt.dbId === at.dbId &&
xt.queryEditorId === at.queryEditorId &&
@@ -122,7 +136,9 @@ export default function sqlLabReducer(state = {}, action) {
at.dataPreviewQueryId = null;
let newState = addToArr(state, 'tables', at);
if (action.query) {
- newState = alterInArr(newState, 'tables', at, { dataPreviewQueryId: action.query.id });
+ newState = alterInArr(newState, 'tables', at, {
+ dataPreviewQueryId: action.query.id,
+ });
}
return newState;
},
@@ -132,7 +148,9 @@ export default function sqlLabReducer(state = {}, action) {
[actions.REMOVE_DATA_PREVIEW]() {
const queries = Object.assign({}, state.queries);
delete queries[action.table.dataPreviewQueryId];
- const newState = alterInArr(state, 'tables', action.table, { dataPreviewQueryId: null });
+ const newState = alterInArr(state, 'tables', action.table, {
+ dataPreviewQueryId: null,
+ });
return Object.assign({}, newState, { queries });
},
[actions.CHANGE_DATA_PREVIEW_ID]() {
@@ -140,9 +158,11 @@ export default function sqlLabReducer(state = {}, action) {
delete queries[action.oldQueryId];
const newTables = [];
- state.tables.forEach((xt) => {
+ state.tables.forEach(xt => {
if (xt.dataPreviewQueryId === action.oldQueryId) {
- newTables.push(Object.assign({}, xt, { dataPreviewQueryId: action.newQuery.id }));
+ newTables.push(
+ Object.assign({}, xt, { dataPreviewQueryId: action.newQuery.id }),
+ );
} else {
newTables.push(xt);
}
@@ -213,12 +233,14 @@ export default function sqlLabReducer(state = {}, action) {
newState = alterInArr(newState, 'queryEditors', sqlEditor, {
validationResult: {
id: action.query.id,
- errors: [{
- line_number: 1,
- start_column: 1,
- end_column: 1,
- message: `The server failed to validate your query.\n${action.message}`,
- }],
+ errors: [
+ {
+ line_number: 1,
+ start_column: 1,
+ end_column: 1,
+ message: `The server failed to validate your query.\n${action.message}`,
+ },
+ ],
completed: true,
},
});
@@ -265,11 +287,17 @@ export default function sqlLabReducer(state = {}, action) {
if (action.query.sqlEditorId) {
const qe = getFromArr(state.queryEditors, action.query.sqlEditorId);
if (qe.latestQueryId && state.queries[qe.latestQueryId]) {
- const newResults = Object.assign({}, state.queries[qe.latestQueryId].results, {
- data: [],
- query: null,
+ const newResults = Object.assign(
+ {},
+ state.queries[qe.latestQueryId].results,
+ {
+ data: [],
+ query: null,
+ },
+ );
+ const q = Object.assign({}, state.queries[qe.latestQueryId], {
+ results: newResults,
});
- const q = Object.assign({}, state.queries[qe.latestQueryId], { results: newResults });
const queries = Object.assign({}, state.queries, { [q.id]: q });
newState = Object.assign({}, state, { queries });
}
@@ -278,18 +306,28 @@ export default function sqlLabReducer(state = {}, action) {
}
newState = addToObject(newState, 'queries', action.query);
const sqlEditor = { id: action.query.sqlEditorId };
- return alterInArr(newState, 'queryEditors', sqlEditor, { latestQueryId: action.query.id });
+ return alterInArr(newState, 'queryEditors', sqlEditor, {
+ latestQueryId: action.query.id,
+ });
},
[actions.STOP_QUERY]() {
- return alterInObject(state, 'queries', action.query, { state: 'stopped', results: [] });
+ return alterInObject(state, 'queries', action.query, {
+ state: 'stopped',
+ results: [],
+ });
},
[actions.CLEAR_QUERY_RESULTS]() {
const newResults = Object.assign({}, action.query.results);
newResults.data = [];
- return alterInObject(state, 'queries', action.query, { results: newResults, cached: true });
+ return alterInObject(state, 'queries', action.query, {
+ results: newResults,
+ cached: true,
+ });
},
[actions.REQUEST_QUERY_RESULTS]() {
- return alterInObject(state, 'queries', action.query, { state: 'fetching' });
+ return alterInObject(state, 'queries', action.query, {
+ state: 'fetching',
+ });
},
[actions.QUERY_SUCCESS]() {
let rows;
@@ -322,8 +360,8 @@ export default function sqlLabReducer(state = {}, action) {
[actions.SET_ACTIVE_QUERY_EDITOR]() {
const qeIds = state.queryEditors.map(qe => qe.id);
if (
- (qeIds.indexOf(action.queryEditor.id) > -1) &&
- (state.tabHistory[state.tabHistory.length - 1] !== action.queryEditor.id)
+ qeIds.indexOf(action.queryEditor.id) > -1 &&
+ state.tabHistory[state.tabHistory.length - 1] !== action.queryEditor.id
) {
const tabHistory = state.tabHistory.slice();
tabHistory.push(action.queryEditor.id);
@@ -332,7 +370,9 @@ export default function sqlLabReducer(state = {}, action) {
return state;
},
[actions.LOAD_QUERY_EDITOR]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { ...action.queryEditor });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ ...action.queryEditor,
+ });
},
[actions.SET_TABLES]() {
return extendArr(state, 'tables', action.tables);
@@ -343,16 +383,14 @@ export default function sqlLabReducer(state = {}, action) {
[actions.MIGRATE_QUERY_EDITOR]() {
// remove migrated query editor from localStorage
const sqlLab = JSON.parse(localStorage.getItem('redux')).sqlLab;
- sqlLab.queryEditors = sqlLab.queryEditors.filter(qe => qe.id !== action.oldQueryEditor.id);
+ sqlLab.queryEditors = sqlLab.queryEditors.filter(
+ qe => qe.id !== action.oldQueryEditor.id,
+ );
localStorage.setItem('redux', JSON.stringify({ sqlLab }));
// replace localStorage query editor with the server backed one
return addToArr(
- removeFromArr(
- state,
- 'queryEditors',
- action.oldQueryEditor,
- ),
+ removeFromArr(state, 'queryEditors', action.oldQueryEditor),
'queryEditors',
action.newQueryEditor,
);
@@ -360,16 +398,14 @@ export default function sqlLabReducer(state = {}, action) {
[actions.MIGRATE_TABLE]() {
// remove migrated table from localStorage
const sqlLab = JSON.parse(localStorage.getItem('redux')).sqlLab;
- sqlLab.tables = sqlLab.tables.filter(table => table.id !== action.oldTable.id);
+ sqlLab.tables = sqlLab.tables.filter(
+ table => table.id !== action.oldTable.id,
+ );
localStorage.setItem('redux', JSON.stringify({ sqlLab }));
// replace localStorage table with the server backed one
return addToArr(
- removeFromArr(
- state,
- 'tables',
- action.oldTable,
- ),
+ removeFromArr(state, 'tables', action.oldTable),
'tables',
action.newTable,
);
@@ -377,9 +413,13 @@ export default function sqlLabReducer(state = {}, action) {
[actions.MIGRATE_TAB_HISTORY]() {
// remove migrated tab from localStorage tabHistory
const sqlLab = JSON.parse(localStorage.getItem('redux')).sqlLab;
- sqlLab.tabHistory = sqlLab.tabHistory.filter(tabId => tabId !== action.oldId);
+ sqlLab.tabHistory = sqlLab.tabHistory.filter(
+ tabId => tabId !== action.oldId,
+ );
localStorage.setItem('redux', JSON.stringify({ sqlLab }));
- const tabHistory = state.tabHistory.filter(tabId => tabId !== action.oldId);
+ const tabHistory = state.tabHistory.filter(
+ tabId => tabId !== action.oldId,
+ );
tabHistory.push(action.newId);
return Object.assign({}, state, { tabHistory });
},
@@ -393,25 +433,39 @@ export default function sqlLabReducer(state = {}, action) {
return Object.assign({}, state, { queries });
},
[actions.QUERY_EDITOR_SETDB]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { dbId: action.dbId });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ dbId: action.dbId,
+ });
},
[actions.QUERY_EDITOR_SET_SCHEMA]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { schema: action.schema });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ schema: action.schema,
+ });
},
[actions.QUERY_EDITOR_SET_SCHEMA_OPTIONS]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { schemaOptions: action.options });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ schemaOptions: action.options,
+ });
},
[actions.QUERY_EDITOR_SET_TABLE_OPTIONS]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { tableOptions: action.options });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ tableOptions: action.options,
+ });
},
[actions.QUERY_EDITOR_SET_TITLE]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { title: action.title });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ title: action.title,
+ });
},
[actions.QUERY_EDITOR_SET_SQL]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { sql: action.sql });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ sql: action.sql,
+ });
},
[actions.QUERY_EDITOR_SET_QUERY_LIMIT]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { queryLimit: action.queryLimit });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ queryLimit: action.queryLimit,
+ });
},
[actions.QUERY_EDITOR_SET_TEMPLATE_PARAMS]() {
return alterInArr(state, 'queryEditors', action.queryEditor, {
@@ -419,10 +473,14 @@ export default function sqlLabReducer(state = {}, action) {
});
},
[actions.QUERY_EDITOR_SET_SELECTED_TEXT]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { selectedText: action.sql });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ selectedText: action.sql,
+ });
},
[actions.QUERY_EDITOR_SET_AUTORUN]() {
- return alterInArr(state, 'queryEditors', action.queryEditor, { autorun: action.autorun });
+ return alterInArr(state, 'queryEditors', action.queryEditor, {
+ autorun: action.autorun,
+ });
},
[actions.QUERY_EDITOR_PERSIST_HEIGHT]() {
return alterInArr(state, 'queryEditors', action.queryEditor, {
@@ -432,7 +490,7 @@ export default function sqlLabReducer(state = {}, action) {
},
[actions.SET_DATABASES]() {
const databases = {};
- action.databases.forEach((db) => {
+ action.databases.forEach(db => {
databases[db.id] = db;
});
return Object.assign({}, state, { databases });
@@ -445,8 +503,9 @@ export default function sqlLabReducer(state = {}, action) {
for (const id in action.alteredQueries) {
const changedQuery = action.alteredQueries[id];
if (
- !state.queries.hasOwnProperty(id)
- || (state.queries[id].state !== 'stopped' && state.queries[id].state !== 'failed')
+ !state.queries.hasOwnProperty(id) ||
+ (state.queries[id].state !== 'stopped' &&
+ state.queries[id].state !== 'failed')
) {
if (changedQuery.changedOn > queriesLastUpdate) {
queriesLastUpdate = changedQuery.changedOn;
@@ -458,7 +517,10 @@ export default function sqlLabReducer(state = {}, action) {
if (!change) {
newQueries = state.queries;
}
- return Object.assign({}, state, { queries: newQueries, queriesLastUpdate });
+ return Object.assign({}, state, {
+ queries: newQueries,
+ queriesLastUpdate,
+ });
},
[actions.SET_USER_OFFLINE]() {
return Object.assign({}, state, { offline: action.offline });
diff --git a/superset/assets/src/SqlLab/utils/reduxStateToLocalStorageHelper.js b/superset/assets/src/SqlLab/utils/reduxStateToLocalStorageHelper.js
index d0a8f5f2fff..18d03d2102f 100644
--- a/superset/assets/src/SqlLab/utils/reduxStateToLocalStorageHelper.js
+++ b/superset/assets/src/SqlLab/utils/reduxStateToLocalStorageHelper.js
@@ -36,32 +36,33 @@ const PERSISTENT_QUERY_EDITOR_KEYS = new Set([
]);
export function emptyQueryResults(queries) {
- return Object.keys(queries)
- .reduce((accu, key) => {
- const { startDttm, results } = queries[key];
- const query = {
- ...queries[key],
- results: Date.now() - startDttm > LOCALSTORAGE_MAX_QUERY_AGE_MS ?
- {} : results,
- };
+ return Object.keys(queries).reduce((accu, key) => {
+ const { startDttm, results } = queries[key];
+ const query = {
+ ...queries[key],
+ results:
+ Date.now() - startDttm > LOCALSTORAGE_MAX_QUERY_AGE_MS ? {} : results,
+ };
- const updatedQueries = {
- ...accu,
- [key]: query,
- };
- return updatedQueries;
- }, {});
+ const updatedQueries = {
+ ...accu,
+ [key]: query,
+ };
+ return updatedQueries;
+ }, {});
}
export function clearQueryEditors(queryEditors) {
- return queryEditors
- .map(editor =>
+ return queryEditors.map(editor =>
// only return selected keys
Object.keys(editor)
.filter(key => PERSISTENT_QUERY_EDITOR_KEYS.has(key))
- .reduce((accumulator, key) => ({
- ...accumulator,
- [key]: editor[key],
- }), {}),
- );
+ .reduce(
+ (accumulator, key) => ({
+ ...accumulator,
+ [key]: editor[key],
+ }),
+ {},
+ ),
+ );
}
diff --git a/superset/assets/src/addSlice/AddSliceContainer.jsx b/superset/assets/src/addSlice/AddSliceContainer.jsx
index 71dda49c28c..106d33af9ad 100644
--- a/superset/assets/src/addSlice/AddSliceContainer.jsx
+++ b/superset/assets/src/addSlice/AddSliceContainer.jsx
@@ -25,10 +25,12 @@ import { t } from '@superset-ui/translation';
import VizTypeControl from '../explore/components/controls/VizTypeControl';
const propTypes = {
- datasources: PropTypes.arrayOf(PropTypes.shape({
- label: PropTypes.string.isRequired,
- value: PropTypes.string.isRequired,
- })).isRequired,
+ datasources: PropTypes.arrayOf(
+ PropTypes.shape({
+ label: PropTypes.string.isRequired,
+ value: PropTypes.string.isRequired,
+ }),
+ ).isRequired,
};
const styleSelectWidth = { width: 600 };
@@ -50,7 +52,8 @@ export default class AddSliceContainer extends React.PureComponent {
JSON.stringify({
viz_type: this.state.visType,
datasource: this.state.datasourceValue,
- }));
+ }),
+ );
return `/superset/explore/?form_data=${formData}`;
}
@@ -96,9 +99,12 @@ export default class AddSliceContainer extends React.PureComponent {
{t(
'If the datasource you are looking for is not ' +
- 'available in the list, ' +
- 'follow the instructions on the how to add it on the ')}
- {t('Superset tutorial')}
+ 'available in the list, ' +
+ 'follow the instructions on the how to add it on the ',
+ )}
+
+ {t('Superset tutorial')}
+
@@ -119,7 +125,8 @@ export default class AddSliceContainer extends React.PureComponent {
>
{t('Create new chart')}
-
+
+
);
diff --git a/superset/assets/src/addSlice/App.jsx b/superset/assets/src/addSlice/App.jsx
index 195512ffdf5..ccdf719f385 100644
--- a/superset/assets/src/addSlice/App.jsx
+++ b/superset/assets/src/addSlice/App.jsx
@@ -26,10 +26,10 @@ setupApp();
setupPlugins();
const addSliceContainer = document.getElementById('js-add-slice-container');
-const bootstrapData = JSON.parse(addSliceContainer.getAttribute('data-bootstrap'));
-
-const App = () => (
-
+const bootstrapData = JSON.parse(
+ addSliceContainer.getAttribute('data-bootstrap'),
);
+const App = () => ;
+
export default hot(module)(App);
diff --git a/superset/assets/src/addSlice/index.jsx b/superset/assets/src/addSlice/index.jsx
index 4f18feedb43..09b6de2291b 100644
--- a/superset/assets/src/addSlice/index.jsx
+++ b/superset/assets/src/addSlice/index.jsx
@@ -20,7 +20,4 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
-ReactDOM.render(
- ,
- document.getElementById('js-add-slice-container'),
-);
+ReactDOM.render( , document.getElementById('js-add-slice-container'));
diff --git a/superset/assets/src/chart/Chart.jsx b/superset/assets/src/chart/Chart.jsx
index a29079a2ffc..7a4679c6383 100644
--- a/superset/assets/src/chart/Chart.jsx
+++ b/superset/assets/src/chart/Chart.jsx
@@ -76,7 +76,9 @@ const defaultProps = {
class Chart extends React.PureComponent {
constructor(props) {
super(props);
- this.handleRenderContainerFailure = this.handleRenderContainerFailure.bind(this);
+ this.handleRenderContainerFailure = this.handleRenderContainerFailure.bind(
+ this,
+ );
}
componentDidMount() {
@@ -114,7 +116,11 @@ class Chart extends React.PureComponent {
handleRenderContainerFailure(error, info) {
const { actions, chartId } = this.props;
console.warn(error); // eslint-disable-line
- actions.chartRenderingFailed(error.toString(), chartId, info ? info.componentStack : null);
+ actions.chartRenderingFailed(
+ error.toString(),
+ chartId,
+ info ? info.componentStack : null,
+ );
actions.logEvent(LOG_ACTIONS_RENDER_CHART_CONTAINER, {
slice_id: chartId,
@@ -133,7 +139,8 @@ class Chart extends React.PureComponent {
message={chartAlert}
link={queryResponse ? queryResponse.link : null}
stackTrace={chartStackTrace}
- />);
+ />
+ );
}
render() {
@@ -160,12 +167,14 @@ class Chart extends React.PureComponent {
return {errorMessage} ;
}
return (
-
+
-
{isLoading &&
}
{!isLoading && !chartAlert && isFaded && (
diff --git a/superset/assets/src/chart/ChartContainer.jsx b/superset/assets/src/chart/ChartContainer.jsx
index 03a4f1a74b7..f509281f3dc 100644
--- a/superset/assets/src/chart/ChartContainer.jsx
+++ b/superset/assets/src/chart/ChartContainer.jsx
@@ -25,10 +25,13 @@ import Chart from './Chart';
function mapDispatchToProps(dispatch) {
return {
- actions: bindActionCreators({
- ...actions,
- logEvent,
- }, dispatch),
+ actions: bindActionCreators(
+ {
+ ...actions,
+ logEvent,
+ },
+ dispatch,
+ ),
};
}
diff --git a/superset/assets/src/chart/ChartRenderer.jsx b/superset/assets/src/chart/ChartRenderer.jsx
index 03ab130df12..3ab00741a6d 100644
--- a/superset/assets/src/chart/ChartRenderer.jsx
+++ b/superset/assets/src/chart/ChartRenderer.jsx
@@ -93,13 +93,15 @@ class ChartRenderer extends React.Component {
this.hasQueryResponseChange =
nextProps.queryResponse !== this.props.queryResponse;
- if (this.hasQueryResponseChange ||
+ if (
+ this.hasQueryResponseChange ||
nextProps.annotationData !== this.props.annotationData ||
nextProps.height !== this.props.height ||
nextProps.width !== this.props.width ||
nextState.tooltip !== this.state.tooltip ||
nextProps.triggerRender ||
- nextProps.formData.color_scheme !== this.props.formData.color_scheme) {
+ nextProps.formData.color_scheme !== this.props.formData.color_scheme
+ ) {
return true;
}
}
@@ -136,7 +138,11 @@ class ChartRenderer extends React.Component {
handleRenderFailure(error, info) {
const { actions, chartId } = this.props;
console.warn(error); // eslint-disable-line
- actions.chartRenderingFailed(error.toString(), chartId, info ? info.componentStack : null);
+ actions.chartRenderingFailed(
+ error.toString(),
+ chartId,
+ info ? info.componentStack : null,
+ );
// only trigger render log when query is changed
if (this.hasQueryResponseChange) {
@@ -170,12 +176,15 @@ class ChartRenderer extends React.Component {
positionLeft={tooltip.x + 30}
arrowOffsetTop={10}
>
- {typeof (tooltip.content) === 'string' ?
+ {typeof tooltip.content === 'string' ? (
- : tooltip.content
- }
+ ) : (
+ tooltip.content
+ )}
);
}
@@ -183,12 +192,7 @@ class ChartRenderer extends React.Component {
}
render() {
- const {
- chartAlert,
- chartStatus,
- vizType,
- chartId,
- } = this.props;
+ const { chartAlert, chartStatus, vizType, chartId } = this.props;
// Skip chart rendering
if (chartStatus === 'loading' || !!chartAlert || chartStatus === null) {
diff --git a/superset/assets/src/chart/chart.less b/superset/assets/src/chart/chart.less
index 18e8a105098..ce9e7c7a358 100644
--- a/superset/assets/src/chart/chart.less
+++ b/superset/assets/src/chart/chart.less
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../stylesheets/less/variables.less";
+@import '../../stylesheets/less/variables.less';
.chart-tooltip {
opacity: 0.75;
diff --git a/superset/assets/src/chart/chartAction.js b/superset/assets/src/chart/chartAction.js
index 69a074d9c9b..9859ef4c407 100644
--- a/superset/assets/src/chart/chartAction.js
+++ b/superset/assets/src/chart/chartAction.js
@@ -21,8 +21,14 @@
import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/connection';
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
-import { getExploreUrlAndPayload, getAnnotationJsonUrl } from '../explore/exploreUtils';
-import { requiresQuery, ANNOTATION_SOURCE_TYPES } from '../modules/AnnotationTypes';
+import {
+ getExploreUrlAndPayload,
+ getAnnotationJsonUrl,
+} from '../explore/exploreUtils';
+import {
+ requiresQuery,
+ ANNOTATION_SOURCE_TYPES,
+} from '../modules/AnnotationTypes';
import { addDangerToast } from '../messageToasts/actions';
import { logEvent } from '../logger/actions';
import { Logger, LOG_ACTIONS_LOAD_CHART } from '../logger/LogUtils';
@@ -31,7 +37,12 @@ import { allowCrossDomain } from '../utils/hostNamesConfig';
export const CHART_UPDATE_STARTED = 'CHART_UPDATE_STARTED';
export function chartUpdateStarted(queryController, latestQueryFormData, key) {
- return { type: CHART_UPDATE_STARTED, queryController, latestQueryFormData, key };
+ return {
+ type: CHART_UPDATE_STARTED,
+ queryController,
+ latestQueryFormData,
+ key,
+ };
}
export const CHART_UPDATE_SUCCEEDED = 'CHART_UPDATE_SUCCEEDED';
@@ -84,11 +95,18 @@ export function annotationQueryFailed(annotation, queryResponse, key) {
return { type: ANNOTATION_QUERY_FAILED, annotation, queryResponse, key };
}
-export function runAnnotationQuery(annotation, timeout = 60, formData = null, key) {
- return function (dispatch, getState) {
+export function runAnnotationQuery(
+ annotation,
+ timeout = 60,
+ formData = null,
+ key,
+) {
+ return function(dispatch, getState) {
const sliceKey = key || Object.keys(getState().charts)[0];
// make a copy of formData, not modifying original formData
- const fd = { ...(formData || getState().charts[sliceKey].latestQueryFormData) };
+ const fd = {
+ ...(formData || getState().charts[sliceKey].latestQueryFormData),
+ };
if (!requiresQuery(annotation.sourceType)) {
return Promise.resolve();
@@ -114,7 +132,9 @@ export function runAnnotationQuery(annotation, timeout = 60, formData = null, ke
if (fd !== null) {
const hasExtraFilters = fd.extra_filters && fd.extra_filters.length > 0;
- sliceFormData.extra_filters = hasExtraFilters ? fd.extra_filters : undefined;
+ sliceFormData.extra_filters = hasExtraFilters
+ ? fd.extra_filters
+ : undefined;
}
const isNative = annotation.sourceType === ANNOTATION_SOURCE_TYPES.NATIVE;
@@ -129,16 +149,25 @@ export function runAnnotationQuery(annotation, timeout = 60, formData = null, ke
signal,
timeout: timeout * 1000,
})
- .then(({ json }) => dispatch(annotationQuerySuccess(annotation, json, sliceKey)))
- .catch(response => getClientErrorObject(response).then((err) => {
- if (err.statusText === 'timeout') {
- dispatch(annotationQueryFailed(annotation, { error: 'Query Timeout' }, sliceKey));
- } else if ((err.error || '').toLowerCase().includes('no data')) {
- dispatch(annotationQuerySuccess(annotation, err, sliceKey));
- } else if (err.statusText !== 'abort') {
- dispatch(annotationQueryFailed(annotation, err, sliceKey));
- }
- }),
+ .then(({ json }) =>
+ dispatch(annotationQuerySuccess(annotation, json, sliceKey)),
+ )
+ .catch(response =>
+ getClientErrorObject(response).then(err => {
+ if (err.statusText === 'timeout') {
+ dispatch(
+ annotationQueryFailed(
+ annotation,
+ { error: 'Query Timeout' },
+ sliceKey,
+ ),
+ );
+ } else if ((err.error || '').toLowerCase().includes('no data')) {
+ dispatch(annotationQuerySuccess(annotation, err, sliceKey));
+ } else if (err.statusText !== 'abort') {
+ dispatch(annotationQueryFailed(annotation, err, sliceKey));
+ }
+ }),
);
};
}
@@ -171,8 +200,14 @@ export function addChart(chart, key) {
return { type: ADD_CHART, chart, key };
}
-export function exploreJSON(formData, force = false, timeout = 60, key, method) {
- return (dispatch) => {
+export function exploreJSON(
+ formData,
+ force = false,
+ timeout = 60,
+ key,
+ method,
+) {
+ return dispatch => {
const { url, payload } = getExploreUrlAndPayload({
formData,
endpointType: 'json',
@@ -200,46 +235,54 @@ export function exploreJSON(formData, force = false, timeout = 60, key, method)
};
}
- const clientMethod = method === 'GET' && isFeatureEnabled(FeatureFlag.CLIENT_CACHE)
- ? SupersetClient.get
- : SupersetClient.post;
+ const clientMethod =
+ method === 'GET' && isFeatureEnabled(FeatureFlag.CLIENT_CACHE)
+ ? SupersetClient.get
+ : SupersetClient.post;
const queryPromise = clientMethod(querySettings)
.then(({ json }) => {
- dispatch(logEvent(LOG_ACTIONS_LOAD_CHART, {
- slice_id: key,
- is_cached: json.is_cached,
- force_refresh: force,
- row_count: json.rowcount,
- datasource: formData.datasource,
- start_offset: logStart,
- ts: new Date().getTime(),
- duration: Logger.getTimestamp() - logStart,
- has_extra_filters: formData.extra_filters && formData.extra_filters.length > 0,
- viz_type: formData.viz_type,
- }));
- return dispatch(chartUpdateSucceeded(json, key));
- })
- .catch((response) => {
- const appendErrorLog = (errorDetails) => {
- dispatch(logEvent(LOG_ACTIONS_LOAD_CHART, {
+ dispatch(
+ logEvent(LOG_ACTIONS_LOAD_CHART, {
slice_id: key,
- has_err: true,
- error_details: errorDetails,
+ is_cached: json.is_cached,
+ force_refresh: force,
+ row_count: json.rowcount,
datasource: formData.datasource,
start_offset: logStart,
ts: new Date().getTime(),
duration: Logger.getTimestamp() - logStart,
- }));
+ has_extra_filters:
+ formData.extra_filters && formData.extra_filters.length > 0,
+ viz_type: formData.viz_type,
+ }),
+ );
+ return dispatch(chartUpdateSucceeded(json, key));
+ })
+ .catch(response => {
+ const appendErrorLog = errorDetails => {
+ dispatch(
+ logEvent(LOG_ACTIONS_LOAD_CHART, {
+ slice_id: key,
+ has_err: true,
+ error_details: errorDetails,
+ datasource: formData.datasource,
+ start_offset: logStart,
+ ts: new Date().getTime(),
+ duration: Logger.getTimestamp() - logStart,
+ }),
+ );
};
if (response.statusText === 'timeout') {
appendErrorLog('timeout');
- return dispatch(chartUpdateTimeout(response.statusText, timeout, key));
+ return dispatch(
+ chartUpdateTimeout(response.statusText, timeout, key),
+ );
} else if (response.name === 'AbortError') {
appendErrorLog('abort');
return dispatch(chartUpdateStopped(key));
}
- return getClientErrorObject(response).then((parsedResponse) => {
+ return getClientErrorObject(response).then(parsedResponse => {
appendErrorLog(parsedResponse.error);
return dispatch(chartUpdateFailed(parsedResponse, key));
});
@@ -251,7 +294,9 @@ export function exploreJSON(formData, force = false, timeout = 60, key, method)
queryPromise,
dispatch(triggerQuery(false, key)),
dispatch(updateQueryFormData(payload, key)),
- ...annotationLayers.map(x => dispatch(runAnnotationQuery(x, timeout, formData, key))),
+ ...annotationLayers.map(x =>
+ dispatch(runAnnotationQuery(x, timeout, formData, key)),
+ ),
]);
};
}
@@ -283,8 +328,11 @@ export function postChartFormData(formData, force = false, timeout = 60, key) {
}
export function redirectSQLLab(formData) {
- return (dispatch) => {
- const { url } = getExploreUrlAndPayload({ formData, endpointType: 'query' });
+ return dispatch => {
+ const { url } = getExploreUrlAndPayload({
+ formData,
+ endpointType: 'query',
+ });
return SupersetClient.post({
url,
postPayload: { form_data: formData },
@@ -299,15 +347,22 @@ export function redirectSQLLab(formData) {
redirectUrl.searchParams.set('sql', json.query);
window.open(redirectUrl.href, '_blank');
})
- .catch(() => dispatch(addDangerToast(t('An error occurred while loading the SQL'))));
+ .catch(() =>
+ dispatch(addDangerToast(t('An error occurred while loading the SQL'))),
+ );
};
}
export function refreshChart(chart, force, timeout) {
- return (dispatch) => {
- if (!chart.latestQueryFormData || Object.keys(chart.latestQueryFormData).length === 0) {
+ return dispatch => {
+ if (
+ !chart.latestQueryFormData ||
+ Object.keys(chart.latestQueryFormData).length === 0
+ ) {
return;
}
- dispatch(postChartFormData(chart.latestQueryFormData, force, timeout, chart.id));
+ dispatch(
+ postChartFormData(chart.latestQueryFormData, force, timeout, chart.id),
+ );
};
}
diff --git a/superset/assets/src/chart/chartReducer.js b/superset/assets/src/chart/chartReducer.js
index 02df8cb28d1..8ac7f1aefdc 100644
--- a/superset/assets/src/chart/chartReducer.js
+++ b/superset/assets/src/chart/chartReducer.js
@@ -44,7 +44,8 @@ export default function chartReducer(charts = {}, action) {
};
},
[actions.CHART_UPDATE_SUCCEEDED](state) {
- return { ...state,
+ return {
+ ...state,
chartStatus: 'success',
queryResponse: action.queryResponse,
chartAlert: null,
@@ -62,45 +63,57 @@ export default function chartReducer(charts = {}, action) {
};
},
[actions.CHART_UPDATE_STOPPED](state) {
- return { ...state,
+ return {
+ ...state,
chartStatus: 'stopped',
chartAlert: t('Updating chart was stopped'),
chartUpdateEndTime: now(),
};
},
[actions.CHART_RENDERING_SUCCEEDED](state) {
- return { ...state,
- chartStatus: 'rendered',
- chartUpdateEndTime: now(),
- };
+ return { ...state, chartStatus: 'rendered', chartUpdateEndTime: now() };
},
[actions.CHART_RENDERING_FAILED](state) {
- return { ...state,
+ return {
+ ...state,
chartStatus: 'failed',
chartStackTrace: action.stackTrace,
- chartAlert: t('An error occurred while rendering the visualization: %s', action.error),
+ chartAlert: t(
+ 'An error occurred while rendering the visualization: %s',
+ action.error,
+ ),
};
},
[actions.CHART_UPDATE_TIMEOUT](state) {
- return { ...state,
+ return {
+ ...state,
chartStatus: 'failed',
- chartAlert: (
+ chartAlert:
`${t('Query timeout')} - ` +
- t(`visualization queries are set to timeout at ${action.timeout} seconds. `) +
- t('Perhaps your data has grown, your database is under unusual load, ' +
- 'or you are simply querying a data source that is too large ' +
- 'to be processed within the timeout range. ' +
- 'If that is the case, we recommend that you summarize your data further.')),
+ t(
+ `visualization queries are set to timeout at ${action.timeout} seconds. `,
+ ) +
+ t(
+ 'Perhaps your data has grown, your database is under unusual load, ' +
+ 'or you are simply querying a data source that is too large ' +
+ 'to be processed within the timeout range. ' +
+ 'If that is the case, we recommend that you summarize your data further.',
+ ),
chartUpdateEndTime: now(),
};
},
[actions.CHART_UPDATE_FAILED](state) {
- return { ...state,
+ return {
+ ...state,
chartStatus: 'failed',
- chartAlert: action.queryResponse ? action.queryResponse.error : t('Network error.'),
+ chartAlert: action.queryResponse
+ ? action.queryResponse.error
+ : t('Network error.'),
chartUpdateEndTime: now(),
queryResponse: action.queryResponse,
- chartStackTrace: action.queryResponse ? action.queryResponse.stacktrace : null,
+ chartStackTrace: action.queryResponse
+ ? action.queryResponse.stacktrace
+ : null,
};
},
[actions.TRIGGER_QUERY](state) {
@@ -117,8 +130,10 @@ export default function chartReducer(charts = {}, action) {
return { ...state, latestQueryFormData: action.value };
},
[actions.ANNOTATION_QUERY_STARTED](state) {
- if (state.annotationQuery &&
- state.annotationQuery[action.annotation.name]) {
+ if (
+ state.annotationQuery &&
+ state.annotationQuery[action.annotation.name]
+ ) {
state.annotationQuery[action.annotation.name].abort();
}
const annotationQuery = {
@@ -151,8 +166,9 @@ export default function chartReducer(charts = {}, action) {
delete annotationData[action.annotation.name];
const annotationError = {
...state.annotationError,
- [action.annotation.name]: action.queryResponse ?
- action.queryResponse.error : t('Network error.'),
+ [action.annotation.name]: action.queryResponse
+ ? action.queryResponse.error
+ : t('Network error.'),
};
const annotationQuery = { ...state.annotationQuery };
delete annotationQuery[action.annotation.name];
diff --git a/superset/assets/src/components/AlteredSliceTag.jsx b/superset/assets/src/components/AlteredSliceTag.jsx
index a2746aaacb6..5f274042f15 100644
--- a/superset/assets/src/components/AlteredSliceTag.jsx
+++ b/superset/assets/src/components/AlteredSliceTag.jsx
@@ -48,9 +48,7 @@ function alterForComparison(value) {
return value;
}
-
export default class AlteredSliceTag extends React.Component {
-
constructor(props) {
super(props);
const diffs = this.getDiffs(props);
@@ -104,12 +102,15 @@ export default class AlteredSliceTag extends React.Component {
if (!value.length) {
return '[]';
}
- return value.map((v) => {
- const filterVal = v.comparator && v.comparator.constructor === Array ?
- `[${v.comparator.join(', ')}]` :
- v.comparator;
- return `${v.subject} ${v.operator} ${filterVal}`;
- }).join(', ');
+ return value
+ .map(v => {
+ const filterVal =
+ v.comparator && v.comparator.constructor === Array
+ ? `[${v.comparator.join(', ')}]`
+ : v.comparator;
+ return `${v.subject} ${v.operator} ${filterVal}`;
+ })
+ .join(', ');
} else if (controls[key] && controls[key].type === 'BoundsControl') {
return `Min: ${value[0]}, Max: ${value[1]}`;
} else if (controls[key] && controls[key].type === 'CollectionControl') {
@@ -130,7 +131,10 @@ export default class AlteredSliceTag extends React.Component {
for (const key in diffs) {
rows.push(
-
+
{this.formatValue(diffs[key].before, key)}
{this.formatValue(diffs[key].after, key)}
,
@@ -154,10 +158,7 @@ export default class AlteredSliceTag extends React.Component {
renderTriggerNode() {
return (
-
+
- {showShortLinkButton &&
- }
+
+ {showShortLinkButton && (
+
+ )}
);
}
diff --git a/superset/assets/src/components/AsyncSelect.jsx b/superset/assets/src/components/AsyncSelect.jsx
index 581fe2ca112..d7de3984f38 100644
--- a/superset/assets/src/components/AsyncSelect.jsx
+++ b/superset/assets/src/components/AsyncSelect.jsx
@@ -75,11 +75,12 @@ class AsyncSelect extends React.PureComponent {
this.onChange(options[0]);
}
})
- .catch(response => getClientErrorObject(response).then((error) => {
- this.props.onAsyncError(error.error || error.statusText || error);
- this.setState({ isLoading: false });
- }),
- );
+ .catch(response =>
+ getClientErrorObject(response).then(error => {
+ this.props.onAsyncError(error.error || error.statusText || error);
+ this.setState({ isLoading: false });
+ }),
+ );
}
render() {
diff --git a/superset/assets/src/components/BootstrapSliderWrapper.less b/superset/assets/src/components/BootstrapSliderWrapper.less
index b103ff4da9d..e78a2dd6689 100644
--- a/superset/assets/src/components/BootstrapSliderWrapper.less
+++ b/superset/assets/src/components/BootstrapSliderWrapper.less
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../stylesheets/less/variables.less";
+@import '../../stylesheets/less/variables.less';
.BootstrapSliderWrapper .slider-selection {
background: @gray-bg;
diff --git a/superset/assets/src/components/Button.jsx b/superset/assets/src/components/Button.jsx
index 29d93b7f827..818040fe46f 100644
--- a/superset/assets/src/components/Button.jsx
+++ b/superset/assets/src/components/Button.jsx
@@ -19,7 +19,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import { kebabCase } from 'lodash';
-import { Button as BootstrapButton, Tooltip, OverlayTrigger } from 'react-bootstrap';
+import {
+ Button as BootstrapButton,
+ Tooltip,
+ OverlayTrigger,
+} from 'react-bootstrap';
const propTypes = {
tooltip: PropTypes.node,
@@ -40,9 +44,7 @@ export default function Button(props) {
delete buttonProps.placement;
let button = (
-
- {props.children}
-
+ {props.children}
);
if (tooltip) {
if (props.disabled) {
@@ -51,15 +53,16 @@ export default function Button(props) {
buttonProps.style = { pointerEvents: 'none' };
button = (
-
- {props.children}
-
-
);
+ {props.children}
+
+ );
}
return (
{tooltip}}
+ overlay={
+ {tooltip}
+ }
>
{button}
diff --git a/superset/assets/src/components/CachedLabel.jsx b/superset/assets/src/components/CachedLabel.jsx
index 8c95b8c4b41..2faf9af507e 100644
--- a/superset/assets/src/components/CachedLabel.jsx
+++ b/superset/assets/src/components/CachedLabel.jsx
@@ -43,8 +43,10 @@ class CacheLabel extends React.PureComponent {
{t('Loaded data cached')}
{moment.utc(this.props.cachedTimestamp).fromNow()}
- ) :
- t('Loaded from cache');
+
+ ) : (
+ t('Loaded from cache')
+ );
const tooltipContent = (
@@ -66,10 +68,7 @@ class CacheLabel extends React.PureComponent {
render() {
const labelStyle = this.state.hovered ? 'primary' : 'default';
return (
-
+
{t('cached')}
- );
+
+ );
}
}
CacheLabel.propTypes = propTypes;
diff --git a/superset/assets/src/components/ChartIcon.jsx b/superset/assets/src/components/ChartIcon.jsx
index d25e4536e39..5fdec9f6ed8 100644
--- a/superset/assets/src/components/ChartIcon.jsx
+++ b/superset/assets/src/components/ChartIcon.jsx
@@ -19,8 +19,22 @@
import React from 'react';
const ChartIcon = () => (
-
-
+
+
diff --git a/superset/assets/src/components/Checkbox.jsx b/superset/assets/src/components/Checkbox.jsx
index 0793c7ce91b..d068488f65e 100644
--- a/superset/assets/src/components/Checkbox.jsx
+++ b/superset/assets/src/components/Checkbox.jsx
@@ -29,7 +29,9 @@ export default function Checkbox({ checked, onChange, style }) {
return (
{
onChange(!checked);
}}
@@ -39,6 +41,7 @@ export default function Checkbox({ checked, onChange, style }) {
cursor: 'pointer',
}}
/>
- );
+
+ );
}
Checkbox.propTypes = propTypes;
diff --git a/superset/assets/src/components/CheckboxIcons.jsx b/superset/assets/src/components/CheckboxIcons.jsx
index f26e75255a8..2c94c863fb0 100644
--- a/superset/assets/src/components/CheckboxIcons.jsx
+++ b/superset/assets/src/components/CheckboxIcons.jsx
@@ -19,22 +19,49 @@
import React from 'react';
export const CheckboxChecked = () => (
-
-
+
+
);
export const CheckboxHalfChecked = () => (
-
-
+
+
);
export const CheckboxUnchecked = () => (
-
-
+
+
);
diff --git a/superset/assets/src/components/ColumnOption.jsx b/superset/assets/src/components/ColumnOption.jsx
index 47f731daf08..6196006747b 100644
--- a/superset/assets/src/components/ColumnOption.jsx
+++ b/superset/assets/src/components/ColumnOption.jsx
@@ -31,7 +31,8 @@ const defaultProps = {
};
export default function ColumnOption({ column, showType }) {
- const hasExpression = column.expression && column.expression !== column.column_name;
+ const hasExpression =
+ column.expression && column.expression !== column.column_name;
let columnType = column.type;
if (column.is_dttm) {
@@ -46,23 +47,24 @@ export default function ColumnOption({ column, showType }) {
{column.verbose_name || column.column_name}
- {column.description &&
+ {column.description && (
- }
- {hasExpression &&
+ )}
+ {hasExpression && (
- }
- );
+ )}
+
+ );
}
ColumnOption.propTypes = propTypes;
ColumnOption.defaultProps = defaultProps;
diff --git a/superset/assets/src/components/ColumnTypeLabel.jsx b/superset/assets/src/components/ColumnTypeLabel.jsx
index 090dbd89b50..f378fccff77 100644
--- a/superset/assets/src/components/ColumnTypeLabel.jsx
+++ b/superset/assets/src/components/ColumnTypeLabel.jsx
@@ -31,9 +31,18 @@ export default function ColumnTypeLabel({ type }) {
stringIcon = 'Æ’';
} else if (type === 'aggregate') {
stringIcon = 'AGG';
- } else if (type.match(/.*char.*/i) || type.match(/string.*/i) || type.match(/.*text.*/i)) {
+ } else if (
+ type.match(/.*char.*/i) ||
+ type.match(/string.*/i) ||
+ type.match(/.*text.*/i)
+ ) {
stringIcon = 'ABC';
- } else if (type.match(/.*int.*/i) || type === 'LONG' || type === 'DOUBLE' || type === 'FLOAT') {
+ } else if (
+ type.match(/.*int.*/i) ||
+ type === 'LONG' ||
+ type === 'DOUBLE' ||
+ type === 'FLOAT'
+ ) {
stringIcon = '#';
} else if (type.match(/.*bool.*/i)) {
stringIcon = 'T/F';
@@ -43,13 +52,13 @@ export default function ColumnTypeLabel({ type }) {
stringIcon = '?';
}
- const typeIcon = stringIcon === 'time' ?
- :
- {stringIcon}
;
+ const typeIcon =
+ stringIcon === 'time' ? (
+
+ ) : (
+ {stringIcon}
+ );
- return (
-
- {typeIcon}
- );
+ return {typeIcon} ;
}
ColumnTypeLabel.propTypes = propTypes;
diff --git a/superset/assets/src/components/CopyToClipboard.jsx b/superset/assets/src/components/CopyToClipboard.jsx
index bd9a07bfa0c..9061c2929f5 100644
--- a/superset/assets/src/components/CopyToClipboard.jsx
+++ b/superset/assets/src/components/CopyToClipboard.jsx
@@ -62,7 +62,9 @@ export default class CopyToClipboard extends React.Component {
onClick() {
if (this.props.getText) {
- this.props.getText((d) => { this.copyToClipboard(d); });
+ this.props.getText(d => {
+ this.copyToClipboard(d);
+ });
} else {
this.copyToClipboard(this.props.text);
}
@@ -135,7 +137,9 @@ export default class CopyToClipboard extends React.Component {
return (
{this.props.shouldShowText && this.props.text && (
- {this.props.text}
+
+ {this.props.text}
+
)}
+
-
+
{this.props.copyNode}
@@ -169,9 +174,7 @@ export default class CopyToClipboard extends React.Component {
renderTooltip() {
return (
-
- {this.tooltipText()}
-
+ {this.tooltipText()}
);
}
diff --git a/superset/assets/src/components/EditableTitle.jsx b/superset/assets/src/components/EditableTitle.jsx
index fc6d47615f8..63c05cdd306 100644
--- a/superset/assets/src/components/EditableTitle.jsx
+++ b/superset/assets/src/components/EditableTitle.jsx
@@ -31,7 +31,10 @@ const propTypes = {
showTooltip: PropTypes.bool,
emptyText: PropTypes.node,
style: PropTypes.object,
- extraClasses: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.string]),
+ extraClasses: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.string),
+ PropTypes.string,
+ ]),
};
const defaultProps = {
title: t('Title'),
@@ -77,8 +80,9 @@ export default class EditableTitle extends React.PureComponent {
// For multi-line values, save the actual rendered size of the displayed text.
// Later, if a textarea is constructed for editing the value, we'll need this.
- const contentBoundingRect = (this.contentRef.current) ?
- this.contentRef.current.getBoundingClientRect() : null;
+ const contentBoundingRect = this.contentRef.current
+ ? this.contentRef.current.getBoundingClientRect()
+ : null;
this.setState({ isEditing: true, contentBoundingRect });
}
@@ -144,8 +148,15 @@ export default class EditableTitle extends React.PureComponent {
render() {
const { isEditing, title, contentBoundingRect } = this.state;
- const { emptyText, multiLine, showTooltip, canEdit,
- noPermitTooltip, style, extraClasses } = this.props;
+ const {
+ emptyText,
+ multiLine,
+ showTooltip,
+ canEdit,
+ noPermitTooltip,
+ style,
+ extraClasses,
+ } = this.props;
let value;
if (title) {
@@ -156,43 +167,51 @@ export default class EditableTitle extends React.PureComponent {
// Construct an inline style based on previously-saved height of the rendered label. Only
// used in multi-line contexts.
- const editStyle = (isEditing && contentBoundingRect) ? { height: `${contentBoundingRect.height}px` } : null;
+ const editStyle =
+ isEditing && contentBoundingRect
+ ? { height: `${contentBoundingRect.height}px` }
+ : null;
// Create a textarea when we're editing a multi-line value, otherwise create an input (which may
// be text or a button).
- let input = multiLine && isEditing ? (
-
- ) : (
-
- );
+ let input =
+ multiLine && isEditing ? (
+
+ ) : (
+
+ );
if (showTooltip && !isEditing) {
input = (
{input}
diff --git a/superset/assets/src/components/ErrorBoundary.jsx b/superset/assets/src/components/ErrorBoundary.jsx
index 926109486e4..5c7ecf581e4 100644
--- a/superset/assets/src/components/ErrorBoundary.jsx
+++ b/superset/assets/src/components/ErrorBoundary.jsx
@@ -54,7 +54,10 @@ export default class ErrorBoundary extends React.Component {
);
if (this.props.showMessage) {
return (
-
+
);
}
return null;
diff --git a/superset/assets/src/components/FilterBadgeIcon.jsx b/superset/assets/src/components/FilterBadgeIcon.jsx
index 5ad60514b9c..f6ed7647b4c 100644
--- a/superset/assets/src/components/FilterBadgeIcon.jsx
+++ b/superset/assets/src/components/FilterBadgeIcon.jsx
@@ -27,7 +27,12 @@ const propTypes = {
export default function FilterBadgeIcon({ colorCode = '' }) {
return (
-
+
);
diff --git a/superset/assets/src/components/FilterBadgeIcon.less b/superset/assets/src/components/FilterBadgeIcon.less
index 8b6b7c65d47..4f8de44d8e7 100644
--- a/superset/assets/src/components/FilterBadgeIcon.less
+++ b/superset/assets/src/components/FilterBadgeIcon.less
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../stylesheets/less/variables.less";
+@import '../../stylesheets/less/variables.less';
.filter-badge {
width: 20px;
diff --git a/superset/assets/src/components/FilterableTable/FilterableTable.jsx b/superset/assets/src/components/FilterableTable/FilterableTable.jsx
index 3f4b4f45f9f..5b0e1111067 100644
--- a/superset/assets/src/components/FilterableTable/FilterableTable.jsx
+++ b/superset/assets/src/components/FilterableTable/FilterableTable.jsx
@@ -40,7 +40,10 @@ import TooltipWrapper from '../TooltipWrapper';
function safeJsonObjectParse(data) {
// First perform a cheap proxy to avoid calling JSON.parse on data that is clearly not a
// JSON object or array
- if (typeof data !== 'string' || ['{', '['].indexOf(data.substring(0, 1)) === -1) {
+ if (
+ typeof data !== 'string' ||
+ ['{', '['].indexOf(data.substring(0, 1)) === -1
+ ) {
return null;
}
@@ -79,7 +82,6 @@ const JSON_TREE_THEME = {
base0F: '#cc6633',
};
-
// when more than MAX_COLUMNS_FOR_TABLE are returned, switch from table to grid view
export const MAX_COLUMNS_FOR_TABLE = 50;
@@ -123,11 +125,13 @@ export default class FilterableTable extends PureComponent {
this.sort = this.sort.bind(this);
// columns that have complex type and were expanded into sub columns
- this.complexColumns = props.orderedColumnKeys
- .reduce((obj, key) => ({
+ this.complexColumns = props.orderedColumnKeys.reduce(
+ (obj, key) => ({
...obj,
[key]: props.expandedColumns.some(name => name.startsWith(key + '.')),
- }), {});
+ }),
+ {},
+ );
this.widthsForColumnsByKey = this.getWidthsForColumns();
this.totalTableWidth = props.orderedColumnKeys
@@ -155,28 +159,33 @@ export default class FilterableTable extends PureComponent {
getWidthsForColumns() {
const PADDING = 40; // accounts for cell padding and width of sorting icon
const widthsByColumnKey = {};
- const cellContent = [].concat(...this.props.orderedColumnKeys.map(key =>
- this.list
- .map(data => this.getCellContent({ cellData: data[key], columnKey: key }))
- .push(key)
- .toJS(),
- ));
+ const cellContent = [].concat(
+ ...this.props.orderedColumnKeys.map(key =>
+ this.list
+ .map(data =>
+ this.getCellContent({ cellData: data[key], columnKey: key }),
+ )
+ .push(key)
+ .toJS(),
+ ),
+ );
- const colWidths = getMultipleTextDimensions(
- {
- className: 'cell-text-for-measuring',
- texts: cellContent,
- },
- ).map(dimension => dimension.width);
+ const colWidths = getMultipleTextDimensions({
+ className: 'cell-text-for-measuring',
+ texts: cellContent,
+ }).map(dimension => dimension.width);
this.props.orderedColumnKeys.forEach((key, index) => {
// we can't use Math.max(...colWidths.slice(...)) here since the number
// of elements might be bigger than the number of allowed arguments in a
// Javascript function
- widthsByColumnKey[key] = colWidths.slice(
- index * (this.list.size + 1),
- (index + 1) * (this.list.size + 1),
- ).reduce((a, b) => Math.max(a, b)) + PADDING;
+ widthsByColumnKey[key] =
+ colWidths
+ .slice(
+ index * (this.list.size + 1),
+ (index + 1) * (this.list.size + 1),
+ )
+ .reduce((a, b) => Math.max(a, b)) + PADDING;
});
return widthsByColumnKey;
@@ -184,11 +193,7 @@ export default class FilterableTable extends PureComponent {
getCellContent({ cellData, columnKey }) {
if (cellData === null) {
- return (
-
- NULL
-
- );
+ return NULL ;
}
const content = String(cellData);
const firstCharacter = content.substring(0, 1);
@@ -204,11 +209,11 @@ export default class FilterableTable extends PureComponent {
}
formatTableData(data) {
- const formattedData = data.map((row) => {
+ const formattedData = data.map(row => {
const newRow = {};
for (const k in row) {
const val = row[k];
- if (['string', 'number'].indexOf(typeof (val)) >= 0) {
+ if (['string', 'number'].indexOf(typeof val) >= 0) {
newRow[k] = val;
} else {
newRow[k] = val === null ? null : JSONbig.stringify(val);
@@ -226,7 +231,10 @@ export default class FilterableTable extends PureComponent {
const cellValue = row[key];
if (typeof cellValue === 'string') {
values.push(cellValue.toLowerCase());
- } else if (cellValue !== null && typeof cellValue.toString === 'function') {
+ } else if (
+ cellValue !== null &&
+ typeof cellValue.toString === 'function'
+ ) {
values.push(cellValue.toString());
}
}
@@ -260,7 +268,11 @@ export default class FilterableTable extends PureComponent {
return (
}
- modalFooter={ }
+ modalFooter={
+
+
+
+ }
modalTitle={t('Cell Content')}
triggerNode={node}
/>
@@ -285,16 +297,17 @@ export default class FilterableTable extends PureComponent {
}
renderTableHeader({ dataKey, label, sortBy, sortDirection }) {
- const className = this.props.expandedColumns.indexOf(label) > -1
- ? 'header-style-disabled'
- : 'header-style';
+ const className =
+ this.props.expandedColumns.indexOf(label) > -1
+ ? 'header-style-disabled'
+ : 'header-style';
return (
{label}
- {sortBy === dataKey &&
+ {sortBy === dataKey && (
- }
+ )}
);
@@ -302,9 +315,10 @@ export default class FilterableTable extends PureComponent {
renderGridCellHeader({ columnIndex, key, style }) {
const label = this.props.orderedColumnKeys[columnIndex];
- const className = this.props.expandedColumns.indexOf(label) > -1
- ? 'header-style-disabled'
- : 'header-style';
+ const className =
+ this.props.expandedColumns.indexOf(label) > -1
+ ? 'header-style-disabled'
+ : 'header-style';
return (
this.widthsForColumnsByKey[orderedColumnKeys[index]];
+ const getColumnWidth = ({ index }) =>
+ this.widthsForColumnsByKey[orderedColumnKeys[index]];
// fix height of filterable table
return (
@@ -415,12 +435,15 @@ export default class FilterableTable extends PureComponent {
let sortedAndFilteredList = this.list;
// filter list
if (filterText) {
- sortedAndFilteredList = this.list.filter(row => this.hasMatch(filterText, row));
+ sortedAndFilteredList = this.list.filter(row =>
+ this.hasMatch(filterText, row),
+ );
}
// sort list
if (sortBy) {
- sortedAndFilteredList = sortedAndFilteredList
- .sort(this.sortResults(sortBy, sortDirection === SortDirection.DESC));
+ sortedAndFilteredList = sortedAndFilteredList.sort(
+ this.sortResults(sortBy, sortDirection === SortDirection.DESC),
+ );
}
let { height } = this.props;
@@ -432,14 +455,15 @@ export default class FilterableTable extends PureComponent {
totalTableHeight -= SCROLL_BAR_HEIGHT;
}
- const rowGetter = ({ index }) => this.getDatum(sortedAndFilteredList, index);
+ const rowGetter = ({ index }) =>
+ this.getDatum(sortedAndFilteredList, index);
return (
- {this.state.fitted &&
+ {this.state.fitted && (
{orderedColumnKeys.map(columnKey => (
this.renderTableCell({ cellData, columnKey })}
+ cellRenderer={({ cellData }) =>
+ this.renderTableCell({ cellData, columnKey })
+ }
dataKey={columnKey}
disableSort={false}
headerRenderer={this.renderTableHeader}
@@ -466,7 +492,7 @@ export default class FilterableTable extends PureComponent {
/>
))}
- }
+ )}
);
}
diff --git a/superset/assets/src/components/FilterableTable/FilterableTableStyles.less b/superset/assets/src/components/FilterableTable/FilterableTableStyles.less
index 510ac4b9ac8..c3339129291 100644
--- a/superset/assets/src/components/FilterableTable/FilterableTableStyles.less
+++ b/superset/assets/src/components/FilterableTable/FilterableTableStyles.less
@@ -17,7 +17,7 @@
* under the License.
*/
-@import "../../../stylesheets/less/variables.less";
+@import '../../../stylesheets/less/variables.less';
.ReactVirtualized__Grid__innerScrollContainer {
border: 1px solid;
diff --git a/superset/assets/src/components/FormRow.jsx b/superset/assets/src/components/FormRow.jsx
index 012dca4fb0b..1581271a0d3 100644
--- a/superset/assets/src/components/FormRow.jsx
+++ b/superset/assets/src/components/FormRow.jsx
@@ -41,25 +41,33 @@ export default function FormRow({ label, tooltip, control, isCheckbox }) {
const labelAndTooltip = (
{label}{' '}
- {tooltip &&
+ {tooltip && (
}
- );
+ />
+ )}
+
+ );
if (isCheckbox) {
return (
- {control}
+
+ {control}
+
{labelAndTooltip}
-
);
+
+ );
}
return (
- {labelAndTooltip}
+
+ {labelAndTooltip}
+
{control}
-
);
+
+ );
}
FormRow.propTypes = propTypes;
FormRow.defaultProps = defaultProps;
diff --git a/superset/assets/src/components/Hotkeys.jsx b/superset/assets/src/components/Hotkeys.jsx
index 0d455244cd7..52d5e4dc34c 100644
--- a/superset/assets/src/components/Hotkeys.jsx
+++ b/superset/assets/src/components/Hotkeys.jsx
@@ -22,11 +22,13 @@ import Mousetrap from 'mousetrap';
import { OverlayTrigger, Popover } from 'react-bootstrap';
const propTypes = {
- hotkeys: PropTypes.arrayOf(PropTypes.shape({
- key: PropTypes.string.isRequired,
- descr: PropTypes.string.isRequired,
- func: PropTypes.func,
- })).isRequired,
+ hotkeys: PropTypes.arrayOf(
+ PropTypes.shape({
+ key: PropTypes.string.isRequired,
+ descr: PropTypes.string.isRequired,
+ func: PropTypes.func,
+ }),
+ ).isRequired,
header: PropTypes.string,
placement: PropTypes.string,
};
@@ -37,7 +39,7 @@ const defaultProps = {
export default class Hotkeys extends React.PureComponent {
componentDidMount() {
- this.props.hotkeys.forEach((keyConfig) => {
+ this.props.hotkeys.forEach(keyConfig => {
if (keyConfig.func) {
Mousetrap.bind([keyConfig.key], keyConfig.func);
}
@@ -57,13 +59,16 @@ export default class Hotkeys extends React.PureComponent {
{hotkeys.map(({ key, descr }) => (
- {key}
+
+ {key}
+
{descr}
))}
- );
+
+ );
}
render() {
return (
diff --git a/superset/assets/src/components/InfoTooltipWithTrigger.jsx b/superset/assets/src/components/InfoTooltipWithTrigger.jsx
index f4901041772..518137c8796 100644
--- a/superset/assets/src/components/InfoTooltipWithTrigger.jsx
+++ b/superset/assets/src/components/InfoTooltipWithTrigger.jsx
@@ -38,8 +38,17 @@ const defaultProps = {
const tooltipStyle = { wordWrap: 'break-word' };
export default function InfoTooltipWithTrigger({
- label, tooltip, icon, className, onClick, placement, bsStyle }) {
- const iconClass = `fa fa-${icon} ${className} ${bsStyle ? `text-${bsStyle}` : ''}`;
+ label,
+ tooltip,
+ icon,
+ className,
+ onClick,
+ placement,
+ bsStyle,
+}) {
+ const iconClass = `fa fa-${icon} ${className} ${
+ bsStyle ? `text-${bsStyle}` : ''
+ }`;
const iconEl = (
{' '}
- - {languages[langKey].name}
+ -{' '}
+ {languages[langKey].name}
),
diff --git a/superset/assets/src/components/Menu/Menu.jsx b/superset/assets/src/components/Menu/Menu.jsx
index eb90d94d005..7375d22594d 100644
--- a/superset/assets/src/components/Menu/Menu.jsx
+++ b/superset/assets/src/components/Menu/Menu.jsx
@@ -48,7 +48,9 @@ const propTypes = {
}).isRequired,
};
-export default function Menu({ data: { menu, brand, navbar_right: navbarRight } }) {
+export default function Menu({
+ data: { menu, brand, navbar_right: navbarRight },
+}) {
return (
@@ -80,7 +82,10 @@ export default function Menu({ data: { menu, brand, navbar_right: navbarRight }
)}
{navbarRight.show_language_picker && (
-
+
)}
{!navbarRight.user_is_anonymous && (
);
return (
-
+ );
}
MetricOption.propTypes = propTypes;
MetricOption.defaultProps = defaultProps;
diff --git a/superset/assets/src/components/ModalTrigger.jsx b/superset/assets/src/components/ModalTrigger.jsx
index 70575a2c6ab..d5e493af487 100644
--- a/superset/assets/src/components/ModalTrigger.jsx
+++ b/superset/assets/src/components/ModalTrigger.jsx
@@ -28,7 +28,7 @@ const propTypes = {
animation: PropTypes.bool,
triggerNode: PropTypes.node.isRequired,
modalTitle: PropTypes.node,
- modalBody: PropTypes.node, // not required because it can be generated by beforeOpen
+ modalBody: PropTypes.node, // not required because it can be generated by beforeOpen
modalFooter: PropTypes.node,
beforeOpen: PropTypes.func,
onExit: PropTypes.func,
@@ -82,19 +82,15 @@ export default class ModalTrigger extends React.Component {
className={this.props.className}
backdrop={this.props.backdrop}
>
- {this.props.modalTitle &&
+ {this.props.modalTitle && (
{this.props.modalTitle}
- }
-
- {this.props.modalBody}
-
- {this.props.modalFooter &&
-
- {this.props.modalFooter}
-
- }
+ )}
+ {this.props.modalBody}
+ {this.props.modalFooter && (
+ {this.props.modalFooter}
+ )}
);
}
@@ -119,9 +115,7 @@ export default class ModalTrigger extends React.Component {
} else if (this.props.isMenuItem) {
return (
<>
-
- {this.props.triggerNode}
-
+ {this.props.triggerNode}
{this.renderModal()}
>
);
diff --git a/superset/assets/src/components/OmniContainer.jsx b/superset/assets/src/components/OmniContainer.jsx
index edf33b974ad..3c2bd7471a2 100644
--- a/superset/assets/src/components/OmniContainer.jsx
+++ b/superset/assets/src/components/OmniContainer.jsx
@@ -23,9 +23,7 @@ import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/connection';
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
import Omnibar from 'omnibar';
-import {
- LOG_ACTIONS_OMNIBAR_TRIGGERED,
-} from '../logger/LogUtils';
+import { LOG_ACTIONS_OMNIBAR_TRIGGERED } from '../logger/LogUtils';
const propTypes = {
logEvent: PropTypes.func.isRequired,
@@ -34,17 +32,18 @@ const propTypes = {
const getDashboards = query =>
// todo: Build a dedicated endpoint for dashboard searching
// i.e. superset/v1/api/dashboards?q=${query}
- SupersetClient.get({
- endpoint: `/dashboardasync/api/read?_oc_DashboardModelViewAsync=changed_on&_od_DashboardModelViewAsync=desc&_flt_2_dashboard_title=${query}`,
- })
- .then(({ json }) => json.result.map(item => ({
- title: item.dashboard_title,
- ...item,
- }),
- ))
- .catch(() => ({
- title: t('An error occurred while fethching Dashboards'),
- }));
+ SupersetClient.get({
+ endpoint: `/dashboardasync/api/read?_oc_DashboardModelViewAsync=changed_on&_od_DashboardModelViewAsync=desc&_flt_2_dashboard_title=${query}`,
+ })
+ .then(({ json }) =>
+ json.result.map(item => ({
+ title: item.dashboard_title,
+ ...item,
+ })),
+ )
+ .catch(() => ({
+ title: t('An error occurred while fethching Dashboards'),
+ }));
class OmniContainer extends React.Component {
constructor(props) {
@@ -74,19 +73,21 @@ class OmniContainer extends React.Component {
this.setState({ showOmni: !this.state.showOmni });
- document
- .getElementsByClassName('Omnibar')[0]
- .focus();
+ document.getElementsByClassName('Omnibar')[0].focus();
}
}
}
render() {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
}
diff --git a/superset/assets/src/components/OnPasteSelect.jsx b/superset/assets/src/components/OnPasteSelect.jsx
index 91eadc844ae..9e019ba4e77 100644
--- a/superset/assets/src/components/OnPasteSelect.jsx
+++ b/superset/assets/src/components/OnPasteSelect.jsx
@@ -36,27 +36,31 @@ export default class OnPasteSelect extends React.Component {
const selected = this.props.value || [];
const existingOptions = {};
const existing = {};
- this.props.options.forEach((v) => {
+ this.props.options.forEach(v => {
existingOptions[v[this.props.valueKey]] = 1;
});
let options = [];
- selected.forEach((v) => {
+ selected.forEach(v => {
options.push({ [this.props.labelKey]: v, [this.props.valueKey]: v });
existing[v] = 1;
});
- options = options.concat(values
- .filter((v) => {
- const notExists = !existing[v];
- existing[v] = 1;
- return notExists && (validator ? validator({ [this.props.labelKey]: v }) : !!v);
- })
- .map((v) => {
- const opt = { [this.props.labelKey]: v, [this.props.valueKey]: v };
- if (!existingOptions[v]) {
- this.props.options.unshift(opt);
- }
- return opt;
- }),
+ options = options.concat(
+ values
+ .filter(v => {
+ const notExists = !existing[v];
+ existing[v] = 1;
+ return (
+ notExists &&
+ (validator ? validator({ [this.props.labelKey]: v }) : !!v)
+ );
+ })
+ .map(v => {
+ const opt = { [this.props.labelKey]: v, [this.props.valueKey]: v };
+ if (!existingOptions[v]) {
+ this.props.options.unshift(opt);
+ }
+ return opt;
+ }),
);
if (options.length) {
if (this.props.onChange) {
@@ -66,7 +70,7 @@ export default class OnPasteSelect extends React.Component {
}
render() {
const SelectComponent = this.props.selectWrap;
- const refFunc = (ref) => {
+ const refFunc = ref => {
if (this.props.refFunc) {
this.props.refFunc(ref);
}
@@ -74,11 +78,7 @@ export default class OnPasteSelect extends React.Component {
};
const inputProps = { onPaste: this.onPaste.bind(this) };
return (
-
+
);
}
}
diff --git a/superset/assets/src/components/OptionDescription.jsx b/superset/assets/src/components/OptionDescription.jsx
index d89c9ffb47b..d9b384dab26 100644
--- a/superset/assets/src/components/OptionDescription.jsx
+++ b/superset/assets/src/components/OptionDescription.jsx
@@ -30,17 +30,16 @@ const propTypes = {
export default function OptionDescription({ option }) {
return (
-
- {option.label}
-
- {option.description &&
+ {option.label}
+ {option.description && (
- }
- );
+ )}
+
+ );
}
OptionDescription.propTypes = propTypes;
diff --git a/superset/assets/src/components/PopoverSection.jsx b/superset/assets/src/components/PopoverSection.jsx
index b2a71857475..955594e21d1 100644
--- a/superset/assets/src/components/PopoverSection.jsx
+++ b/superset/assets/src/components/PopoverSection.jsx
@@ -28,22 +28,25 @@ const propTypes = {
children: PropTypes.node.isRequired,
};
-export default function PopoverSection({ title, isSelected, children, onSelect, info }) {
+export default function PopoverSection({
+ title,
+ isSelected,
+ children,
+ onSelect,
+ info,
+}) {
return (
{title}
- {info &&
- }
+ {info && (
+
+ )}
-
- {children}
-
-
);
+ {children}
+
+ );
}
PopoverSection.propTypes = propTypes;
diff --git a/superset/assets/src/components/RefreshLabel.jsx b/superset/assets/src/components/RefreshLabel.jsx
index 855dc66962a..87c852d6506 100644
--- a/superset/assets/src/components/RefreshLabel.jsx
+++ b/superset/assets/src/components/RefreshLabel.jsx
@@ -30,15 +30,13 @@ const propTypes = {
class RefreshLabel extends React.PureComponent {
render() {
return (
-
+
- );
+
+ );
}
}
RefreshLabel.propTypes = propTypes;
diff --git a/superset/assets/src/components/RefreshLabel.less b/superset/assets/src/components/RefreshLabel.less
index a1b055f6fa3..4defab711bf 100644
--- a/superset/assets/src/components/RefreshLabel.less
+++ b/superset/assets/src/components/RefreshLabel.less
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../stylesheets/less/cosmo/variables.less";
+@import '../../stylesheets/less/cosmo/variables.less';
.RefreshLabel:hover {
color: @brand-primary;
diff --git a/superset/assets/src/components/StackTraceMessage.jsx b/superset/assets/src/components/StackTraceMessage.jsx
index 434dcca8ebf..43ccbea1165 100644
--- a/superset/assets/src/components/StackTraceMessage.jsx
+++ b/superset/assets/src/components/StackTraceMessage.jsx
@@ -44,29 +44,29 @@ class StackTraceMessage extends React.PureComponent {
render() {
return (
-
+
this.setState({ showStackTrace: !this.state.showStackTrace })}
+ onClick={() =>
+ this.setState({ showStackTrace: !this.state.showStackTrace })
+ }
>
{this.props.message}
- {this.props.link &&
-
- (Request Access)
-
- }
+ {this.props.link && (
+
+ (Request Access)
+
+ )}
- {this.props.stackTrace &&
+ {this.props.stackTrace && (
-
- {this.props.stackTrace}
-
+ {this.props.stackTrace}
- }
+ )}
);
}
diff --git a/superset/assets/src/components/TableLoader.jsx b/superset/assets/src/components/TableLoader.jsx
index d38be49d07e..0a83a72116e 100644
--- a/superset/assets/src/components/TableLoader.jsx
+++ b/superset/assets/src/components/TableLoader.jsx
@@ -89,7 +89,7 @@ class TableLoader extends React.PureComponent {
>
{this.state.data.map((row, i) => (
- {columns.map((col) => {
+ {columns.map(col => {
if (row.hasOwnProperty('_' + col)) {
return (
diff --git a/superset/assets/src/components/TableSelector.jsx b/superset/assets/src/components/TableSelector.jsx
index 58c9018b6e2..4d925637e23 100644
--- a/superset/assets/src/components/TableSelector.jsx
+++ b/superset/assets/src/components/TableSelector.jsx
@@ -102,8 +102,12 @@ export default class TableSelector extends React.PureComponent {
return Promise.resolve({ options });
}
return SupersetClient.get({
- endpoint: encodeURI(`/superset/tables/${this.props.dbId}/` +
- `${encodeURIComponent(this.props.schema)}/${encodeURIComponent(input)}`),
+ endpoint: encodeURI(
+ `/superset/tables/${this.props.dbId}/` +
+ `${encodeURIComponent(this.props.schema)}/${encodeURIComponent(
+ input,
+ )}`,
+ ),
}).then(({ json }) => {
const options = json.options.map(o => ({
value: o.value,
@@ -112,13 +116,15 @@ export default class TableSelector extends React.PureComponent {
title: o.title,
type: o.type,
}));
- return ({ options });
+ return { options };
});
}
dbMutator(data) {
this.props.getDbList(data.result);
if (data.result.length === 0) {
- this.props.handleError(t("It seems you don't have access to any database"));
+ this.props.handleError(
+ t("It seems you don't have access to any database"),
+ );
}
return data.result.map(row => ({
...row,
@@ -131,9 +137,13 @@ export default class TableSelector extends React.PureComponent {
const { dbId, schema } = this.state;
if (dbId && schema) {
this.setState(() => ({ tableLoading: true, tableOptions: [] }));
- const endpoint = encodeURI(`/superset/tables/${dbId}/` +
- `${encodeURIComponent(schema)}/${encodeURIComponent(substr)}/${forceRefresh}/`);
- return SupersetClient.get({ endpoint })
+ const endpoint = encodeURI(
+ `/superset/tables/${dbId}/` +
+ `${encodeURIComponent(schema)}/${encodeURIComponent(
+ substr,
+ )}/${forceRefresh}/`,
+ );
+ return SupersetClient.get({ endpoint })
.then(({ json }) => {
const options = json.options.map(o => ({
value: o.value,
@@ -153,7 +163,7 @@ export default class TableSelector extends React.PureComponent {
this.props.handleError(t('Error while fetching table list'));
});
}
- this.setState(() => ({ tableLoading: false, tableOptions: [] }));
+ this.setState(() => ({ tableLoading: false, tableOptions: [] }));
return Promise.resolve();
}
fetchSchemas(dbId, force) {
@@ -165,7 +175,11 @@ export default class TableSelector extends React.PureComponent {
return SupersetClient.get({ endpoint })
.then(({ json }) => {
- const schemaOptions = json.schemas.map(s => ({ value: s, label: s, title: s }));
+ const schemaOptions = json.schemas.map(s => ({
+ value: s,
+ label: s,
+ title: s,
+ }));
this.setState({ schemaOptions, schemaLoading: false });
this.props.onSchemasLoad(schemaOptions);
})
@@ -200,11 +214,22 @@ export default class TableSelector extends React.PureComponent {
renderDatabaseOption(db) {
return (
- {db.backend}
+
+ {db.backend}
+
{db.database_name}
- );
+
+ );
}
- renderTableOption({ focusOption, focusedOption, key, option, selectValue, style, valueArray }) {
+ renderTableOption({
+ focusOption,
+ focusedOption,
+ key,
+ option,
+ selectValue,
+ style,
+ valueArray,
+ }) {
const classNames = ['Select-option'];
if (option === focusedOption) {
classNames.push('is-focused');
@@ -223,7 +248,9 @@ export default class TableSelector extends React.PureComponent {
-
+
{option.label}
@@ -249,7 +276,9 @@ export default class TableSelector extends React.PureComponent {
'order_columns:database_name,order_direction:asc,page:0,page_size:-1)'
}
onChange={this.onDatabaseChange}
- onAsyncError={() => this.props.handleError(t('Error while fetching database list'))}
+ onAsyncError={() =>
+ this.props.handleError(t('Error while fetching database list'))
+ }
clearable={false}
value={this.state.dbId}
valueKey="id"
@@ -263,7 +292,8 @@ export default class TableSelector extends React.PureComponent {
mutator={this.dbMutator}
placeholder={t('Select a database')}
autoSelect
- />);
+ />,
+ );
}
renderSchema() {
return this.renderSelectRow(
@@ -290,7 +320,10 @@ export default class TableSelector extends React.PureComponent {
renderTable() {
let tableSelectPlaceholder;
let tableSelectDisabled = false;
- if (this.props.database && this.props.database.allow_multi_schema_metadata_fetch) {
+ if (
+ this.props.database &&
+ this.props.database.allow_multi_schema_metadata_fetch
+ ) {
tableSelectPlaceholder = t('Type to search ...');
} else {
tableSelectPlaceholder = t('Select table ');
@@ -309,25 +342,28 @@ export default class TableSelector extends React.PureComponent {
options={options}
value={this.state.tableName}
optionRenderer={this.renderTableOption}
- />) : (
- );
+ />
+ ) : (
+
+ );
return this.renderSelectRow(
select,
this.changeSchema({ value: this.props.schema }, true)}
tooltipContent={t('Force refresh table list')}
- />);
+ />,
+ );
}
renderSeeTableLabel() {
return (
@@ -335,14 +371,12 @@ export default class TableSelector extends React.PureComponent {
{t('See table schema')}{' '}
- ({this.state.tableOptions.length}
- {' '}{t('in')}{' '}
-
- {this.props.schema}
- )
+ ({this.state.tableOptions.length} {t('in')}{' '}
+ {this.props.schema} )
- );
+
+ );
}
render() {
return (
diff --git a/superset/assets/src/components/TableSelector.less b/superset/assets/src/components/TableSelector.less
index 6c508c1a625..53e2b97e5a4 100644
--- a/superset/assets/src/components/TableSelector.less
+++ b/superset/assets/src/components/TableSelector.less
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../stylesheets/less/variables.less";
+@import '../../stylesheets/less/variables.less';
.TableSelector .fa-refresh {
padding-left: 9px;
diff --git a/superset/assets/src/components/TooltipWrapper.jsx b/superset/assets/src/components/TooltipWrapper.jsx
index 95ab6fd4344..ed3b970975f 100644
--- a/superset/assets/src/components/TooltipWrapper.jsx
+++ b/superset/assets/src/components/TooltipWrapper.jsx
@@ -32,7 +32,12 @@ const defaultProps = {
placement: 'top',
};
-export default function TooltipWrapper({ label, tooltip, children, placement }) {
+export default function TooltipWrapper({
+ label,
+ tooltip,
+ children,
+ placement,
+}) {
return (
}
+ copyNode={
+
+ }
/>
-
+
@@ -78,8 +84,12 @@ class URLShortLinkButton extends React.Component {
onEnter={this.getCopyUrl}
overlay={this.renderPopover()}
>
-
-
+
+
+
);
diff --git a/superset/assets/src/components/URLShortLinkModal.jsx b/superset/assets/src/components/URLShortLinkModal.jsx
index d6bf3f67224..ec3982ea8ab 100644
--- a/superset/assets/src/components/URLShortLinkModal.jsx
+++ b/superset/assets/src/components/URLShortLinkModal.jsx
@@ -55,7 +55,9 @@ class URLShortLinkModal extends React.Component {
}
getCopyUrl() {
- getShortUrl(this.props.url).then(this.onShortUrlSuccess).catch(this.props.addDangerToast);
+ getShortUrl(this.props.url)
+ .then(this.onShortUrlSuccess)
+ .catch(this.props.addDangerToast);
}
render() {
@@ -71,10 +73,14 @@ class URLShortLinkModal extends React.Component {
}
+ copyNode={
+
+ }
/>
-
+
diff --git a/superset/assets/src/components/VictoryTheme.js b/superset/assets/src/components/VictoryTheme.js
index e0b35dfae3f..54031a96e53 100644
--- a/superset/assets/src/components/VictoryTheme.js
+++ b/superset/assets/src/components/VictoryTheme.js
@@ -65,95 +65,116 @@ const strokeLinejoin = 'round';
// Create the theme
const theme = {
- area: assign({
- style: {
- data: {
- fill: charcoal,
+ area: assign(
+ {
+ style: {
+ data: {
+ fill: charcoal,
+ },
+ labels: baseLabelStyles,
},
- labels: baseLabelStyles,
},
- }, baseProps),
- axis: assign({
- style: {
- axis: {
- fill: 'none',
- stroke: AXIS_LINE_GRAY,
- strokeWidth: 1,
- strokeLinecap,
- strokeLinejoin,
+ baseProps,
+ ),
+ axis: assign(
+ {
+ style: {
+ axis: {
+ fill: 'none',
+ stroke: AXIS_LINE_GRAY,
+ strokeWidth: 1,
+ strokeLinecap,
+ strokeLinejoin,
+ },
+ axisLabel: assign({}, baseLabelStyles, {
+ padding: 25,
+ }),
+ grid: {
+ fill: 'none',
+ stroke: 'transparent',
+ },
+ ticks: {
+ fill: 'none',
+ padding: 10,
+ size: 1,
+ stroke: 'transparent',
+ },
+ tickLabels: baseLabelStyles,
},
- axisLabel: assign({}, baseLabelStyles, {
- padding: 25,
- }),
- grid: {
- fill: 'none',
- stroke: 'transparent',
- },
- ticks: {
- fill: 'none',
- padding: 10,
- size: 1,
- stroke: 'transparent',
- },
- tickLabels: baseLabelStyles,
},
- }, baseProps),
- bar: assign({
- style: {
- data: {
- fill: A11Y_BABU,
- padding: 10,
- stroke: 'transparent',
- strokeWidth: 0,
- width: 8,
+ baseProps,
+ ),
+ bar: assign(
+ {
+ style: {
+ data: {
+ fill: A11Y_BABU,
+ padding: 10,
+ stroke: 'transparent',
+ strokeWidth: 0,
+ width: 8,
+ },
+ labels: baseLabelStyles,
},
- labels: baseLabelStyles,
},
- }, baseProps),
- candlestick: assign({
- style: {
- data: {
- stroke: A11Y_BABU,
- strokeWidth: 1,
+ baseProps,
+ ),
+ candlestick: assign(
+ {
+ style: {
+ data: {
+ stroke: A11Y_BABU,
+ strokeWidth: 1,
+ },
+ labels: assign({}, baseLabelStyles, {
+ padding: 25,
+ textAnchor: 'end',
+ }),
+ },
+ candleColors: {
+ positive: '#ffffff',
+ negative: charcoal,
},
- labels: assign({}, baseLabelStyles, {
- padding: 25,
- textAnchor: 'end',
- }),
},
- candleColors: {
- positive: '#ffffff',
- negative: charcoal,
- },
- }, baseProps),
+ baseProps,
+ ),
chart: baseProps,
- errorbar: assign({
- style: {
- data: {
- fill: 'none',
- stroke: charcoal,
- strokeWidth: 2,
+ errorbar: assign(
+ {
+ style: {
+ data: {
+ fill: 'none',
+ stroke: charcoal,
+ strokeWidth: 2,
+ },
+ labels: assign({}, baseLabelStyles, {
+ textAnchor: 'start',
+ }),
},
- labels: assign({}, baseLabelStyles, {
- textAnchor: 'start',
- }),
},
- }, baseProps),
- group: assign({
- colorScale: colors,
- }, baseProps),
- line: assign({
- style: {
- data: {
- fill: 'none',
- stroke: A11Y_BABU,
- strokeWidth: 2,
+ baseProps,
+ ),
+ group: assign(
+ {
+ colorScale: colors,
+ },
+ baseProps,
+ ),
+ line: assign(
+ {
+ style: {
+ data: {
+ fill: 'none',
+ stroke: A11Y_BABU,
+ strokeWidth: 2,
+ },
+ labels: assign({}, baseLabelStyles, {
+ textAnchor: 'start',
+ }),
},
- labels: assign({}, baseLabelStyles, {
- textAnchor: 'start',
- }),
},
- }, baseProps),
+ baseProps,
+ ),
pie: {
style: {
data: {
@@ -171,21 +192,27 @@ const theme = {
height: 400,
padding: 50,
},
- scatter: assign({
- style: {
- data: {
- fill: charcoal,
- stroke: 'transparent',
- strokeWidth: 0,
+ scatter: assign(
+ {
+ style: {
+ data: {
+ fill: charcoal,
+ stroke: 'transparent',
+ strokeWidth: 0,
+ },
+ labels: assign({}, baseLabelStyles, {
+ textAnchor: 'middle',
+ }),
},
- labels: assign({}, baseLabelStyles, {
- textAnchor: 'middle',
- }),
},
- }, baseProps),
- stack: assign({
- colorScale: colors,
- }, baseProps),
+ baseProps,
+ ),
+ stack: assign(
+ {
+ colorScale: colors,
+ },
+ baseProps,
+ ),
};
export default theme;
diff --git a/superset/assets/src/components/VirtualizedRendererWrap.jsx b/superset/assets/src/components/VirtualizedRendererWrap.jsx
index 1b15557e78c..3f441736423 100644
--- a/superset/assets/src/components/VirtualizedRendererWrap.jsx
+++ b/superset/assets/src/components/VirtualizedRendererWrap.jsx
@@ -45,10 +45,12 @@ export default function VirtualizedRendererWrap(renderer) {
if (option.className) {
className.push(option.className);
}
- const events = option.disabled ? {} : {
- onClick: () => selectValue(option),
- onMouseEnter: () => focusOption(option),
- };
+ const events = option.disabled
+ ? {}
+ : {
+ onClick: () => selectValue(option),
+ onMouseEnter: () => focusOption(option),
+ };
return (
(
diff --git a/superset/assets/src/dashboard/actions/dashboardLayout.js b/superset/assets/src/dashboard/actions/dashboardLayout.js
index 1122918d2f0..7389399af51 100644
--- a/superset/assets/src/dashboard/actions/dashboardLayout.js
+++ b/superset/assets/src/dashboard/actions/dashboardLayout.js
@@ -203,8 +203,10 @@ export function handleComponentDrop(dropResult) {
} else if (
destination &&
source &&
- !// ensure it has moved
- (destination.id === source.id && destination.index === source.index)
+ !(
+ // ensure it has moved
+ (destination.id === source.id && destination.index === source.index)
+ )
) {
dispatch(moveComponent(dropResult));
}
diff --git a/superset/assets/src/dashboard/containers/Chart.jsx b/superset/assets/src/dashboard/containers/Chart.jsx
index 361fe4731d0..634a201d2cf 100644
--- a/superset/assets/src/dashboard/containers/Chart.jsx
+++ b/superset/assets/src/dashboard/containers/Chart.jsx
@@ -92,7 +92,4 @@ function mapDispatchToProps(dispatch) {
);
}
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(Chart);
+export default connect(mapStateToProps, mapDispatchToProps)(Chart);
diff --git a/superset/assets/src/dashboard/containers/Dashboard.jsx b/superset/assets/src/dashboard/containers/Dashboard.jsx
index 7ed9bd88529..791b99aff99 100644
--- a/superset/assets/src/dashboard/containers/Dashboard.jsx
+++ b/superset/assets/src/dashboard/containers/Dashboard.jsx
@@ -74,7 +74,4 @@ function mapDispatchToProps(dispatch) {
};
}
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(Dashboard);
+export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
diff --git a/superset/assets/src/dashboard/containers/DashboardBuilder.jsx b/superset/assets/src/dashboard/containers/DashboardBuilder.jsx
index 6bc81381880..9887295345c 100644
--- a/superset/assets/src/dashboard/containers/DashboardBuilder.jsx
+++ b/superset/assets/src/dashboard/containers/DashboardBuilder.jsx
@@ -54,7 +54,4 @@ function mapDispatchToProps(dispatch) {
);
}
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(DashboardBuilder);
+export default connect(mapStateToProps, mapDispatchToProps)(DashboardBuilder);
diff --git a/superset/assets/src/dashboard/containers/DashboardComponent.jsx b/superset/assets/src/dashboard/containers/DashboardComponent.jsx
index 22855ffc5b3..d1e2b8d53c1 100644
--- a/superset/assets/src/dashboard/containers/DashboardComponent.jsx
+++ b/superset/assets/src/dashboard/containers/DashboardComponent.jsx
@@ -117,7 +117,4 @@ class DashboardComponent extends React.PureComponent {
DashboardComponent.propTypes = propTypes;
DashboardComponent.defaultProps = defaultProps;
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(DashboardComponent);
+export default connect(mapStateToProps, mapDispatchToProps)(DashboardComponent);
diff --git a/superset/assets/src/dashboard/containers/DashboardGrid.jsx b/superset/assets/src/dashboard/containers/DashboardGrid.jsx
index 95b1216352c..cbec708e54f 100644
--- a/superset/assets/src/dashboard/containers/DashboardGrid.jsx
+++ b/superset/assets/src/dashboard/containers/DashboardGrid.jsx
@@ -43,7 +43,4 @@ function mapDispatchToProps(dispatch) {
);
}
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(DashboardGrid);
+export default connect(mapStateToProps, mapDispatchToProps)(DashboardGrid);
diff --git a/superset/assets/src/dashboard/containers/DashboardHeader.jsx b/superset/assets/src/dashboard/containers/DashboardHeader.jsx
index 88e54ac7451..04d778d5890 100644
--- a/superset/assets/src/dashboard/containers/DashboardHeader.jsx
+++ b/superset/assets/src/dashboard/containers/DashboardHeader.jsx
@@ -112,7 +112,4 @@ function mapDispatchToProps(dispatch) {
);
}
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(DashboardHeader);
+export default connect(mapStateToProps, mapDispatchToProps)(DashboardHeader);
diff --git a/superset/assets/src/dashboard/containers/SliceAdder.jsx b/superset/assets/src/dashboard/containers/SliceAdder.jsx
index 445dbc9fcb1..b7933f69a90 100644
--- a/superset/assets/src/dashboard/containers/SliceAdder.jsx
+++ b/superset/assets/src/dashboard/containers/SliceAdder.jsx
@@ -43,7 +43,4 @@ function mapDispatchToProps(dispatch) {
);
}
-export default connect(
- mapStateToProps,
- mapDispatchToProps,
-)(SliceAdder);
+export default connect(mapStateToProps, mapDispatchToProps)(SliceAdder);
diff --git a/superset/assets/src/dashboard/util/activeDashboardFilters.js b/superset/assets/src/dashboard/util/activeDashboardFilters.js
index 01d66ac2c21..f6d192677bb 100644
--- a/superset/assets/src/dashboard/util/activeDashboardFilters.js
+++ b/superset/assets/src/dashboard/util/activeDashboardFilters.js
@@ -49,9 +49,9 @@ export function isFilterBox(chartId) {
export function getAppliedFilterValues(chartId) {
// use cached data if possible
if (!(chartId in appliedFilterValuesByChart)) {
- const applicableFilters = Object.entries(activeFilters).filter(
- ([, { scope: chartIds }]) => chartIds.includes(chartId),
- );
+ const applicableFilters = Object.entries(
+ activeFilters,
+ ).filter(([, { scope: chartIds }]) => chartIds.includes(chartId));
appliedFilterValuesByChart[chartId] = flow(
keyBy(
([filterKey]) => getChartIdAndColumnFromFilterKey(filterKey).column,
diff --git a/superset/assets/src/datasource/ChangeDatasourceModal.jsx b/superset/assets/src/datasource/ChangeDatasourceModal.jsx
index d7a22600736..0eef9506cae 100644
--- a/superset/assets/src/datasource/ChangeDatasourceModal.jsx
+++ b/superset/assets/src/datasource/ChangeDatasourceModal.jsx
@@ -19,10 +19,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Table } from 'reactable-arc';
-import {
- FormControl,
- Modal,
-} from 'react-bootstrap';
+import { FormControl, Modal } from 'react-bootstrap';
import { SupersetClient } from '@superset-ui/connection';
import { t } from '@superset-ui/translation';
@@ -87,7 +84,7 @@ class ChangeDatasourceModal extends React.PureComponent {
this.setState({ loading: false, datasources });
})
- .catch((response) => {
+ .catch(response => {
this.setState({ loading: false });
getClientErrorObject(response).then(({ error }) => {
this.props.addDangerToast(error.error || error.statusText || error);
@@ -112,9 +109,11 @@ class ChangeDatasourceModal extends React.PureComponent {
this.props.onDatasourceSave(json);
this.props.onChange(datasource.uid);
})
- .catch((response) => {
+ .catch(response => {
getClientErrorObject(response).then(({ error, message }) => {
- const errorMessage = error ? error.error || error.statusText || error : message;
+ const errorMessage = error
+ ? error.error || error.statusText || error
+ : message;
this.props.addDangerToast(errorMessage);
});
});
@@ -139,7 +138,7 @@ class ChangeDatasourceModal extends React.PureComponent {
{
+ inputRef={ref => {
this.setSearchRef(ref);
}}
type="text"
diff --git a/superset/assets/src/datasource/DatasourceEditor.jsx b/superset/assets/src/datasource/DatasourceEditor.jsx
index 7e480755179..94b25b2cbc6 100644
--- a/superset/assets/src/datasource/DatasourceEditor.jsx
+++ b/superset/assets/src/datasource/DatasourceEditor.jsx
@@ -42,7 +42,9 @@ import withToasts from '../messageToasts/enhancers/withToasts';
import './main.less';
-const checkboxGenerator = (d, onChange) => ;
+const checkboxGenerator = (d, onChange) => (
+
+);
const DATA_TYPES = ['STRING', 'NUMERIC', 'DATETIME'];
function CollectionTabTitle({ title, collection }) {
@@ -59,8 +61,13 @@ CollectionTabTitle.propTypes = {
};
function ColumnCollectionTable({
- columns, onChange, editableColumnName, showExpression, allowAddItem,
- allowEditDataType, itemGenerator,
+ columns,
+ onChange,
+ editableColumnName,
+ showExpression,
+ allowAddItem,
+ allowEditDataType,
+ itemGenerator,
}) {
return (
- {showExpression &&
+ {showExpression && (
}
- />}
+ />
+ )}
}
/>
- {allowEditDataType &&
+ {allowEditDataType && (
}
- />}
+ control={
+
+ }
+ />
+ )}
{t('The pattern of timestamp format. For strings use ')}
@@ -132,17 +144,19 @@ function ColumnCollectionTable({
}}
onChange={onChange}
itemRenderers={{
- column_name: (v, onItemChange) => (
- editableColumnName ?
- :
+ column_name: (v, onItemChange) =>
+ editableColumnName ? (
+
+ ) : (
v
- ),
+ ),
type: d => {d} ,
is_dttm: checkboxGenerator,
filterable: checkboxGenerator,
groupby: checkboxGenerator,
}}
- />);
+ />
+ );
}
ColumnCollectionTable.propTypes = {
columns: PropTypes.array.isRequired,
@@ -168,7 +182,9 @@ ColumnCollectionTable.defaultProps = {
function StackedField({ label, formElement }) {
return (
-
{label}
+
+ {label}
+
{formElement}
);
@@ -180,11 +196,7 @@ StackedField.propTypes = {
};
function FormContainer({ children }) {
- return (
-
- {children}
-
- );
+ return {children} ;
}
FormContainer.propTypes = {
@@ -211,7 +223,9 @@ export class DatasourceEditor extends React.PureComponent {
isDruid: props.datasource.type === 'druid',
isSqla: props.datasource.type === 'table',
databaseColumns: props.datasource.columns.filter(col => !col.expression),
- calculatedColumns: props.datasource.columns.filter(col => !!col.expression),
+ calculatedColumns: props.datasource.columns.filter(
+ col => !!col.expression,
+ ),
metadataLoading: false,
activeTabKey: 1,
};
@@ -253,16 +267,18 @@ export class DatasourceEditor extends React.PureComponent {
let { databaseColumns } = this.state;
let hasChanged;
const currentColNames = databaseColumns.map(col => col.column_name);
- cols.forEach((col) => {
+ cols.forEach(col => {
if (currentColNames.indexOf(col.name) < 0) {
// Adding columns
- databaseColumns = databaseColumns.concat([{
- id: shortid.generate(),
- column_name: col.name,
- type: col.type,
- groupby: true,
- filterable: true,
- }]);
+ databaseColumns = databaseColumns.concat([
+ {
+ id: shortid.generate(),
+ column_name: col.name,
+ type: col.type,
+ groupby: true,
+ filterable: true,
+ },
+ ]);
hasChanged = true;
}
});
@@ -273,29 +289,33 @@ export class DatasourceEditor extends React.PureComponent {
syncMetadata() {
const { datasource } = this.state;
// Handle carefully when the schema is empty
- const endpoint = (
+ const endpoint =
`/datasource/external_metadata/${datasource.type}/${datasource.id}/` +
`?db_id=${datasource.database.id}` +
`&schema=${datasource.schema || ''}` +
- `&table_name=${datasource.datasource_name}`
- );
+ `&table_name=${datasource.datasource_name}`;
this.setState({ metadataLoading: true });
- SupersetClient.get({ endpoint }).then(({ json }) => {
- this.mergeColumns(json);
- this.props.addSuccessToast(t('Metadata has been synced'));
- this.setState({ metadataLoading: false });
- }).catch(response => getClientErrorObject(response).then(({ error, statusText }) => {
- this.props.addDangerToast(error || statusText || t('An error has occurred'));
+ SupersetClient.get({ endpoint })
+ .then(({ json }) => {
+ this.mergeColumns(json);
+ this.props.addSuccessToast(t('Metadata has been synced'));
this.setState({ metadataLoading: false });
- }),
- );
+ })
+ .catch(response =>
+ getClientErrorObject(response).then(({ error, statusText }) => {
+ this.props.addDangerToast(
+ error || statusText || t('An error has occurred'),
+ );
+ this.setState({ metadataLoading: false });
+ }),
+ );
}
findDuplicates(arr, accessor) {
const seen = {};
const dups = [];
- arr.forEach((obj) => {
+ arr.forEach(obj => {
const item = accessor(obj);
if (item in seen) {
dups.push(item);
@@ -313,17 +333,25 @@ export class DatasourceEditor extends React.PureComponent {
// Looking for duplicate column_name
dups = this.findDuplicates(datasource.columns, obj => obj.column_name);
- errors = errors.concat(dups.map(name => t('Column name [%s] is duplicated', name)));
+ errors = errors.concat(
+ dups.map(name => t('Column name [%s] is duplicated', name)),
+ );
// Looking for duplicate metric_name
dups = this.findDuplicates(datasource.metrics, obj => obj.metric_name);
- errors = errors.concat(dups.map(name => t('Metric name [%s] is duplicated', name)));
+ errors = errors.concat(
+ dups.map(name => t('Metric name [%s] is duplicated', name)),
+ );
// Making sure calculatedColumns have an expression defined
const noFilterCalcCols = this.state.calculatedColumns.filter(
- col => !col.expression && !col.json);
- errors = errors.concat(noFilterCalcCols.map(
- col => t('Calculated column [%s] requires an expression', col.column_name)));
+ col => !col.expression && !col.json,
+ );
+ errors = errors.concat(
+ noFilterCalcCols.map(col =>
+ t('Calculated column [%s] requires an expression', col.column_name),
+ ),
+ );
this.setState({ errors }, callback);
}
@@ -335,8 +363,12 @@ export class DatasourceEditor extends React.PureComponent {
renderSettingsFieldset() {
const datasource = this.state.datasource;
return (
-
- {this.state.isSqla &&
+
+ {this.state.isSqla && (
this.onDatasourcePropChange('schema', schema)}
- onDbChange={database => this.onDatasourcePropChange('database', database)}
- onTableChange={table => this.onDatasourcePropChange('datasource_name', table)}
+ onSchemaChange={schema =>
+ this.onDatasourcePropChange('schema', schema)
+ }
+ onDbChange={database =>
+ this.onDatasourcePropChange('database', database)
+ }
+ onTableChange={table =>
+ this.onDatasourcePropChange('datasource_name', table)
+ }
sqlLabMode={false}
clearable={false}
handleError={this.props.addDangerToast}
- />}
+ />
+ }
descr={t(
'The pointer to a physical table. Keep in mind that the chart is ' +
- 'associated to this Superset logical table, and this logical table points ' +
- 'the physical table referenced here.')}
- />}
+ 'associated to this Superset logical table, and this logical table points ' +
+ 'the physical table referenced here.',
+ )}
+ />
+ )}
}
+ control={
+
+ }
/>
}
/>
}
/>
- {this.state.isSqla &&
+ {this.state.isSqla && (
}
- />}
+ />
+ )}
data.pks.map((pk, i) => ({
- value: pk,
- label: `${data.result[i].first_name} ${data.result[i].last_name}`,
- }))}
- />}
- controlProps={{
- }}
+ mutator={data =>
+ data.pks.map((pk, i) => ({
+ value: pk,
+ label: `${data.result[i].first_name} ${data.result[i].last_name}`,
+ }))
+ }
+ />
+ }
+ controlProps={{}}
/>
);
@@ -409,34 +458,43 @@ export class DatasourceEditor extends React.PureComponent {
renderAdvancedFieldset() {
const datasource = this.state.datasource;
return (
-
- { this.state.isSqla &&
+
+ {this.state.isSqla && (
}
+ 'Superset will use this statement as a subquery while grouping and filtering ' +
+ 'on the generated parent queries.',
+ )}
+ control={
+
+ }
/>
- }
- { this.state.isDruid &&
+ )}
+ {this.state.isDruid && (
- {t('The JSON metric or post aggregation definition.')}
-
+ {t('The JSON metric or post aggregation definition.')}
+ }
+ control={
+
}
- control={ }
/>
- }
+ )}
}
/>
}
/>
- { this.state.isSqla &&
+ {this.state.isSqla && (
}
/>
- }
- );
+ )}
+
+ );
}
renderSpatialTab() {
@@ -460,7 +521,9 @@ export class DatasourceEditor extends React.PureComponent {
const { spatials, all_cols: allCols } = datasource;
return (
}
+ title={
+
+ }
eventKey={4}
>
(
- ),
+
+ ),
config: (v, onChange) => (
),
}}
/>
- );
+
+ );
}
renderErrors() {
if (this.state.errors.length > 0) {
return (
- {this.state.errors.map(err => {err}
)}
- );
+ {this.state.errors.map(err => (
+ {err}
+ ))}
+
+ );
}
return null;
}
@@ -524,7 +592,9 @@ export class DatasourceEditor extends React.PureComponent {
}
/>
@@ -540,9 +610,11 @@ export class DatasourceEditor extends React.PureComponent {
})}
itemRenderers={{
metric_name: (v, onChange) => (
- ),
+
+ ),
verbose_name: (v, onChange) => (
- ),
+
+ ),
expression: (v, onChange) => (
),
+ />
+ ),
description: (v, onChange, label) => (
}
- />),
+ />
+ ),
d3format: (v, onChange, label) => (
}
- />),
+ />
+ ),
}}
allowDeletes
- />);
+ />
+ );
}
render() {
@@ -577,48 +653,65 @@ export class DatasourceEditor extends React.PureComponent {
defaultActiveKey={activeTabKey}
>
}
+ title={
+
+ }
eventKey={1}
>
{activeTabKey === 1 && this.renderMetricCollection()}
+
}
eventKey={2}
>
- {activeTabKey === 2 &&
+ {activeTabKey === 2 && (
this.setColumns({ databaseColumns })}
+ onChange={databaseColumns =>
+ this.setColumns({ databaseColumns })
+ }
/>
{t('Sync columns from source')}
{this.state.metadataLoading && }
- }
+ )}
}
+ />
+ }
eventKey={3}
>
- {activeTabKey === 3 &&
+ {activeTabKey === 3 && (
this.setColumns({ calculatedColumns })}
+ onChange={calculatedColumns =>
+ this.setColumns({ calculatedColumns })
+ }
editableColumnName
showExpression
allowAddItem
@@ -631,27 +724,25 @@ export class DatasourceEditor extends React.PureComponent {
__expanded: true,
})}
/>
- }
+ )}
- {activeTabKey === 4 &&
-
-
-
{t('Be careful.')}
- {t('Changing these settings will affect all charts using this datasource, including charts owned by other people.')}
+ {activeTabKey === 4 && (
+
+
+ {t('Be careful.')}
+ {t(
+ 'Changing these settings will affect all charts using this datasource, including charts owned by other people.',
+ )}
+
+
+
{this.renderSettingsFieldset()}
+
+
+
{this.renderAdvancedFieldset()}
+
-
-
- {this.renderSettingsFieldset()}
-
-
-
-
- {this.renderAdvancedFieldset()}
-
-
-
- }
+ )}
diff --git a/superset/assets/src/datasource/DatasourceModal.jsx b/superset/assets/src/datasource/DatasourceModal.jsx
index 92bbad17118..5959716aa32 100644
--- a/superset/assets/src/datasource/DatasourceModal.jsx
+++ b/superset/assets/src/datasource/DatasourceModal.jsx
@@ -27,7 +27,6 @@ import getClientErrorObject from '../utils/getClientErrorObject';
import DatasourceEditor from '../datasource/DatasourceEditor';
import withToasts from '../messageToasts/enhancers/withToasts';
-
const propTypes = {
onChange: PropTypes.func,
datasource: PropTypes.object.isRequired,
@@ -62,10 +61,7 @@ class DatasourceModal extends React.PureComponent {
this.dialog.show({
title: t('Confirm save'),
bsSize: 'medium',
- actions: [
- Dialog.CancelAction(),
- Dialog.OKAction(this.onConfirmSave),
- ],
+ actions: [Dialog.CancelAction(), Dialog.OKAction(this.onConfirmSave)],
body: this.renderSaveDialog(),
});
}
@@ -88,9 +84,7 @@ class DatasourceModal extends React.PureComponent {
title: 'Error',
bsSize: 'medium',
bsStyle: 'danger',
- actions: [
- Dialog.DefaultAction('Ok', () => {}, 'btn-danger'),
- ],
+ actions: [Dialog.DefaultAction('Ok', () => {}, 'btn-danger')],
body: error || statusText || t('An error has occurred'),
});
}),
@@ -129,11 +123,7 @@ class DatasourceModal extends React.PureComponent {
render() {
return (
-
+
@@ -145,11 +135,12 @@ class DatasourceModal extends React.PureComponent {
- {this.props.show &&
+ {this.props.show && (
}
+ />
+ )}
@@ -173,11 +164,14 @@ class DatasourceModal extends React.PureComponent {
>
{t('Save')}
- {t('Cancel')}
+
+ {t('Cancel')}
+
- );
+
+ );
}
}
diff --git a/superset/assets/src/datasource/main.less b/superset/assets/src/datasource/main.less
index e91f0ffb0ed..955ced4c736 100644
--- a/superset/assets/src/datasource/main.less
+++ b/superset/assets/src/datasource/main.less
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../stylesheets/less/variables.less";
+@import '../../stylesheets/less/variables.less';
.Datasource .tab-content {
height: 600px;
diff --git a/superset/assets/src/explore/AdhocFilter.js b/superset/assets/src/explore/AdhocFilter.js
index aa5d1b2110b..c11d4fdef1d 100644
--- a/superset/assets/src/explore/AdhocFilter.js
+++ b/superset/assets/src/explore/AdhocFilter.js
@@ -48,8 +48,12 @@ function translateToSql(adhocMetric, { useSimple } = {}) {
const isMulti = MULTI_OPERATORS.indexOf(adhocMetric.operator) >= 0;
const subject = adhocMetric.subject;
const operator = OPERATORS_TO_SQL[adhocMetric.operator];
- const comparator = Array.isArray(adhocMetric.comparator) ? adhocMetric.comparator.join("','") : adhocMetric.comparator;
- return `${subject} ${operator} ${isMulti ? '(\'' : ''}${comparator}${isMulti ? '\')' : ''}`;
+ const comparator = Array.isArray(adhocMetric.comparator)
+ ? adhocMetric.comparator.join("','")
+ : adhocMetric.comparator;
+ return `${subject} ${operator} ${isMulti ? "('" : ''}${comparator}${
+ isMulti ? "')" : ''
+ }`;
} else if (adhocMetric.expressionType === EXPRESSION_TYPES.SQL) {
return adhocMetric.sqlExpression;
}
@@ -66,9 +70,10 @@ export default class AdhocFilter {
this.clause = adhocFilter.clause;
this.sqlExpression = null;
} else if (this.expressionType === EXPRESSION_TYPES.SQL) {
- this.sqlExpression = typeof adhocFilter.sqlExpression === 'string' ?
- adhocFilter.sqlExpression :
- translateToSql(adhocFilter, { useSimple: true });
+ this.sqlExpression =
+ typeof adhocFilter.sqlExpression === 'string'
+ ? adhocFilter.sqlExpression
+ : translateToSql(adhocFilter, { useSimple: true });
this.clause = adhocFilter.clause;
this.subject = null;
this.operator = null;
@@ -76,8 +81,13 @@ export default class AdhocFilter {
}
this.fromFormData = !!adhocFilter.filterOptionName;
- this.filterOptionName = adhocFilter.filterOptionName ||
- `filter_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
+ this.filterOptionName =
+ adhocFilter.filterOptionName ||
+ `filter_${Math.random()
+ .toString(36)
+ .substring(2, 15)}_${Math.random()
+ .toString(36)
+ .substring(2, 15)}`;
}
duplicateWith(nextFields) {
@@ -95,20 +105,19 @@ export default class AdhocFilter {
}
equals(adhocFilter) {
- return adhocFilter.expressionType === this.expressionType &&
+ return (
+ adhocFilter.expressionType === this.expressionType &&
adhocFilter.sqlExpression === this.sqlExpression &&
adhocFilter.operator === this.operator &&
adhocFilter.comparator === this.comparator &&
- adhocFilter.subject === this.subject;
+ adhocFilter.subject === this.subject
+ );
}
isValid() {
if (this.expressionType === EXPRESSION_TYPES.SIMPLE) {
if (this.operator === 'IS NOT NULL' || this.operator === 'IS NULL') {
- return !!(
- this.operator &&
- this.subject
- );
+ return !!(this.operator && this.subject);
}
return !!(
@@ -126,9 +135,7 @@ export default class AdhocFilter {
getDefaultLabel() {
const label = this.translateToSql();
- return label.length < 43 ?
- label :
- label.substring(0, 40) + '...';
+ return label.length < 43 ? label : label.substring(0, 40) + '...';
}
translateToSql() {
diff --git a/superset/assets/src/explore/AdhocMetric.js b/superset/assets/src/explore/AdhocMetric.js
index 2147b4b94b7..87de4ecfa30 100644
--- a/superset/assets/src/explore/AdhocMetric.js
+++ b/superset/assets/src/explore/AdhocMetric.js
@@ -24,19 +24,29 @@ export const EXPRESSION_TYPES = {
};
function inferSqlExpressionColumn(adhocMetric) {
- if (adhocMetric.sqlExpression && sqlaAutoGeneratedMetricRegex.test(adhocMetric.sqlExpression)) {
+ if (
+ adhocMetric.sqlExpression &&
+ sqlaAutoGeneratedMetricRegex.test(adhocMetric.sqlExpression)
+ ) {
const indexFirstCloseParen = adhocMetric.sqlExpression.indexOf(')');
- const indexPairedOpenParen =
- adhocMetric.sqlExpression.substring(0, indexFirstCloseParen).lastIndexOf('(');
+ const indexPairedOpenParen = adhocMetric.sqlExpression
+ .substring(0, indexFirstCloseParen)
+ .lastIndexOf('(');
if (indexFirstCloseParen > 0 && indexPairedOpenParen > 0) {
- return adhocMetric.sqlExpression.substring(indexPairedOpenParen + 1, indexFirstCloseParen);
+ return adhocMetric.sqlExpression.substring(
+ indexPairedOpenParen + 1,
+ indexFirstCloseParen,
+ );
}
}
return null;
}
function inferSqlExpressionAggregate(adhocMetric) {
- if (adhocMetric.sqlExpression && sqlaAutoGeneratedMetricRegex.test(adhocMetric.sqlExpression)) {
+ if (
+ adhocMetric.sqlExpression &&
+ sqlaAutoGeneratedMetricRegex.test(adhocMetric.sqlExpression)
+ ) {
const indexFirstOpenParen = adhocMetric.sqlExpression.indexOf('(');
if (indexFirstOpenParen > 0) {
return adhocMetric.sqlExpression.substring(0, indexFirstOpenParen);
@@ -51,8 +61,11 @@ export default class AdhocMetric {
if (this.expressionType === EXPRESSION_TYPES.SIMPLE) {
// try to be clever in the case of transitioning from Sql expression back to simple expression
const inferredColumn = inferSqlExpressionColumn(adhocMetric);
- this.column = adhocMetric.column || (inferredColumn && { column_name: inferredColumn });
- this.aggregate = adhocMetric.aggregate || inferSqlExpressionAggregate(adhocMetric);
+ this.column =
+ adhocMetric.column ||
+ (inferredColumn && { column_name: inferredColumn });
+ this.aggregate =
+ adhocMetric.aggregate || inferSqlExpressionAggregate(adhocMetric);
this.sqlExpression = null;
} else if (this.expressionType === EXPRESSION_TYPES.SQL) {
this.sqlExpression = adhocMetric.sqlExpression;
@@ -61,22 +74,29 @@ export default class AdhocMetric {
}
this.hasCustomLabel = !!(adhocMetric.hasCustomLabel && adhocMetric.label);
this.fromFormData = !!adhocMetric.optionName;
- this.label = this.hasCustomLabel ? adhocMetric.label : this.getDefaultLabel();
+ this.label = this.hasCustomLabel
+ ? adhocMetric.label
+ : this.getDefaultLabel();
- this.optionName = adhocMetric.optionName ||
- `metric_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
+ this.optionName =
+ adhocMetric.optionName ||
+ `metric_${Math.random()
+ .toString(36)
+ .substring(2, 15)}_${Math.random()
+ .toString(36)
+ .substring(2, 15)}`;
}
getDefaultLabel() {
const label = this.translateToSql();
- return label.length < 43 ?
- label :
- label.substring(0, 40) + '...';
+ return label.length < 43 ? label : label.substring(0, 40) + '...';
}
translateToSql() {
if (this.expressionType === EXPRESSION_TYPES.SIMPLE) {
- return `${this.aggregate || ''}(${(this.column && this.column.column_name) || ''})`;
+ return `${this.aggregate || ''}(${(this.column &&
+ this.column.column_name) ||
+ ''})`;
} else if (this.expressionType === EXPRESSION_TYPES.SQL) {
return this.sqlExpression;
}
@@ -91,21 +111,21 @@ export default class AdhocMetric {
}
equals(adhocMetric) {
- return adhocMetric.label === this.label &&
+ return (
+ adhocMetric.label === this.label &&
adhocMetric.expressionType === this.expressionType &&
adhocMetric.sqlExpression === this.sqlExpression &&
adhocMetric.aggregate === this.aggregate &&
- (
- (adhocMetric.column && adhocMetric.column.column_name) ===
+ (adhocMetric.column && adhocMetric.column.column_name) ===
(this.column && this.column.column_name)
- );
+ );
}
isValid() {
if (this.expressionType === EXPRESSION_TYPES.SIMPLE) {
return !!(this.column && this.aggregate);
} else if (this.expressionType === EXPRESSION_TYPES.SQL) {
- return !!(this.sqlExpression);
+ return !!this.sqlExpression;
}
return false;
}
diff --git a/superset/assets/src/explore/App.jsx b/superset/assets/src/explore/App.jsx
index 23922c652ee..0046cff74f8 100644
--- a/superset/assets/src/explore/App.jsx
+++ b/superset/assets/src/explore/App.jsx
@@ -39,17 +39,16 @@ setupApp();
setupPlugins();
const exploreViewContainer = document.getElementById('app');
-const bootstrapData = JSON.parse(exploreViewContainer.getAttribute('data-bootstrap'));
+const bootstrapData = JSON.parse(
+ exploreViewContainer.getAttribute('data-bootstrap'),
+);
initFeatureFlags(bootstrapData.common.feature_flags);
const initState = getInitialState(bootstrapData);
const store = createStore(
rootReducer,
initState,
- compose(
- applyMiddleware(thunk, logger),
- initEnhancer(false),
- ),
+ compose(applyMiddleware(thunk, logger), initEnhancer(false)),
);
const App = () => (
diff --git a/superset/assets/src/explore/actions/exploreActions.js b/superset/assets/src/explore/actions/exploreActions.js
index c68e65ba68e..31eb507e342 100644
--- a/superset/assets/src/explore/actions/exploreActions.js
+++ b/superset/assets/src/explore/actions/exploreActions.js
@@ -59,7 +59,6 @@ export function fetchDatasourcesFailed(error) {
return { type: FETCH_DATASOURCES_FAILED, error };
}
-
export const POST_DATASOURCES_FAILED = 'POST_DATASOURCES_FAILED';
export function postDatasourcesFailed(error) {
return { type: POST_DATASOURCES_FAILED, error };
@@ -77,8 +76,10 @@ export function toggleFaveStar(isStarred) {
export const FETCH_FAVE_STAR = 'FETCH_FAVE_STAR';
export function fetchFaveStar(sliceId) {
- return function (dispatch) {
- SupersetClient.get({ endpoint: `${FAVESTAR_BASE_URL}/${sliceId}/count` }).then(({ json }) => {
+ return function(dispatch) {
+ SupersetClient.get({
+ endpoint: `${FAVESTAR_BASE_URL}/${sliceId}/count`,
+ }).then(({ json }) => {
if (json.count > 0) {
dispatch(toggleFaveStar(true));
}
@@ -88,11 +89,17 @@ export function fetchFaveStar(sliceId) {
export const SAVE_FAVE_STAR = 'SAVE_FAVE_STAR';
export function saveFaveStar(sliceId, isStarred) {
- return function (dispatch) {
+ return function(dispatch) {
const urlSuffix = isStarred ? 'unselect' : 'select';
- SupersetClient.get({ endpoint: `${FAVESTAR_BASE_URL}/${sliceId}/${urlSuffix}/` })
+ SupersetClient.get({
+ endpoint: `${FAVESTAR_BASE_URL}/${sliceId}/${urlSuffix}/`,
+ })
.then(() => dispatch(toggleFaveStar(!isStarred)))
- .catch(() => dispatch(addDangerToast(t('An error occurred while starring this chart'))));
+ .catch(() =>
+ dispatch(
+ addDangerToast(t('An error occurred while starring this chart')),
+ ),
+ );
};
}
@@ -122,6 +129,19 @@ export function updateChartTitle(slice_name) {
}
export const CREATE_NEW_SLICE = 'CREATE_NEW_SLICE';
-export function createNewSlice(can_add, can_download, can_overwrite, slice, form_data) {
- return { type: CREATE_NEW_SLICE, can_add, can_download, can_overwrite, slice, form_data };
+export function createNewSlice(
+ can_add,
+ can_download,
+ can_overwrite,
+ slice,
+ form_data,
+) {
+ return {
+ type: CREATE_NEW_SLICE,
+ can_add,
+ can_download,
+ can_overwrite,
+ slice,
+ form_data,
+ };
}
diff --git a/superset/assets/src/explore/actions/saveModalActions.js b/superset/assets/src/explore/actions/saveModalActions.js
index 6af8151e8b4..01797ee8ec0 100644
--- a/superset/assets/src/explore/actions/saveModalActions.js
+++ b/superset/assets/src/explore/actions/saveModalActions.js
@@ -61,7 +61,7 @@ export function removeSaveModalAlert() {
}
export function saveSlice(formData, requestParams) {
- return (dispatch) => {
+ return dispatch => {
const { url, payload } = getExploreUrlAndPayload({
formData,
endpointType: 'base',
diff --git a/superset/assets/src/explore/components/AdhocFilterEditPopover.jsx b/superset/assets/src/explore/components/AdhocFilterEditPopover.jsx
index 975df0baa91..7da098cc4cc 100644
--- a/superset/assets/src/explore/components/AdhocFilterEditPopover.jsx
+++ b/superset/assets/src/explore/components/AdhocFilterEditPopover.jsx
@@ -31,11 +31,13 @@ const propTypes = {
onChange: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
onResize: PropTypes.func.isRequired,
- options: PropTypes.arrayOf(PropTypes.oneOfType([
- columnType,
- PropTypes.shape({ saved_metric_name: PropTypes.string.isRequired }),
- adhocMetricType,
- ])).isRequired,
+ options: PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ columnType,
+ PropTypes.shape({ saved_metric_name: PropTypes.string.isRequired }),
+ adhocMetricType,
+ ]),
+ ).isRequired,
datasource: PropTypes.object,
};
@@ -88,8 +90,14 @@ export default class AdhocFilterEditPopover extends React.Component {
onMouseMove(e) {
this.props.onResize();
this.setState({
- width: Math.max(this.dragStartWidth + (e.clientX - this.dragStartX), startingWidth),
- height: Math.max(this.dragStartHeight + (e.clientY - this.dragStartY) * 2, startingHeight),
+ width: Math.max(
+ this.dragStartWidth + (e.clientX - this.dragStartX),
+ startingWidth,
+ ),
+ height: Math.max(
+ this.dragStartHeight + (e.clientY - this.dragStartY) * 2,
+ startingHeight,
+ ),
});
}
@@ -118,10 +126,7 @@ export default class AdhocFilterEditPopover extends React.Component {
const hasUnsavedChanges = !adhocFilter.equals(propsAdhocFilter);
return (
-
+
- {
- (!this.props.datasource || this.props.datasource.type !== 'druid') ?
- :
-
- Custom SQL Filters are not available on druid datasources
-
- }
+ {!this.props.datasource ||
+ this.props.datasource.type !== 'druid' ? (
+
+ ) : (
+
+ Custom SQL Filters are not available on druid datasources
+
+ )}
Save
- Close
-
+
+ Close
+
+
);
diff --git a/superset/assets/src/explore/components/AdhocFilterEditPopoverSimpleTabContent.jsx b/superset/assets/src/explore/components/AdhocFilterEditPopoverSimpleTabContent.jsx
index c84d6bf3bd4..3fb6be6b48f 100644
--- a/superset/assets/src/explore/components/AdhocFilterEditPopoverSimpleTabContent.jsx
+++ b/superset/assets/src/explore/components/AdhocFilterEditPopoverSimpleTabContent.jsx
@@ -77,7 +77,9 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
this.onComparatorChange = this.onComparatorChange.bind(this);
this.onInputComparatorChange = this.onInputComparatorChange.bind(this);
this.isOperatorRelevant = this.isOperatorRelevant.bind(this);
- this.refreshComparatorSuggestions = this.refreshComparatorSuggestions.bind(this);
+ this.refreshComparatorSuggestions = this.refreshComparatorSuggestions.bind(
+ this,
+ );
this.multiComparatorRef = this.multiComparatorRef.bind(this);
this.state = {
@@ -141,7 +143,9 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
? currentComparator
: [currentComparator].filter(element => element);
} else {
- newComparator = Array.isArray(currentComparator) ? currentComparator[0] : currentComparator;
+ newComparator = Array.isArray(currentComparator)
+ ? currentComparator[0]
+ : currentComparator;
}
this.props.onChange(
this.props.adhocFilter.duplicateWith({
@@ -173,11 +177,17 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
this.multiComparatorComponent._selectRef.select &&
this.multiComparatorComponent._selectRef.select.control;
if (multiComparatorDOMNode) {
- if (multiComparatorDOMNode.clientHeight !== this.state.multiComparatorHeight) {
+ if (
+ multiComparatorDOMNode.clientHeight !==
+ this.state.multiComparatorHeight
+ ) {
this.props.onHeightChange(
- multiComparatorDOMNode.clientHeight - this.state.multiComparatorHeight,
+ multiComparatorDOMNode.clientHeight -
+ this.state.multiComparatorHeight,
);
- this.setState({ multiComparatorHeight: multiComparatorDOMNode.clientHeight });
+ this.setState({
+ multiComparatorHeight: multiComparatorDOMNode.clientHeight,
+ });
}
}
}
@@ -201,15 +211,21 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
signal,
endpoint: `/superset/filter/${datasource.type}/${datasource.id}/${col}/`,
}).then(({ json }) => {
- this.setState(() => ({ suggestions: json, abortActiveRequest: null, loading: false }));
+ this.setState(() => ({
+ suggestions: json,
+ abortActiveRequest: null,
+ loading: false,
+ }));
});
}
}
isOperatorRelevant(operator) {
return !(
- (this.props.datasource.type === 'druid' && TABLE_ONLY_OPERATORS.indexOf(operator) >= 0) ||
- (this.props.datasource.type === 'table' && DRUID_ONLY_OPERATORS.indexOf(operator) >= 0) ||
+ (this.props.datasource.type === 'druid' &&
+ TABLE_ONLY_OPERATORS.indexOf(operator) >= 0) ||
+ (this.props.datasource.type === 'table' &&
+ DRUID_ONLY_OPERATORS.indexOf(operator) >= 0) ||
(this.props.adhocFilter.clause === CLAUSES.HAVING &&
HAVING_OPERATORS.indexOf(operator) === -1)
);
@@ -233,10 +249,14 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
let subjectSelectProps = {
value: adhocFilter.subject ? { value: adhocFilter.subject } : undefined,
onChange: this.onSubjectChange,
- optionRenderer: VirtualizedRendererWrap(option => ),
+ optionRenderer: VirtualizedRendererWrap(option => (
+
+ )),
valueRenderer: option => {option.value} ,
valueKey: 'filterOptionName',
- noResultsText: t('No such column found. To filter on a metric, try the Custom SQL tab.'),
+ noResultsText: t(
+ 'No such column found. To filter on a metric, try the Custom SQL tab.',
+ ),
};
if (datasource.type === 'druid') {
@@ -266,8 +286,12 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
.map(operator => ({ operator })),
value: adhocFilter.operator,
onChange: this.onOperatorChange,
- optionRenderer: VirtualizedRendererWrap(operator => translateOperator(operator.operator)),
- valueRenderer: operator => {translateOperator(operator.operator)} ,
+ optionRenderer: VirtualizedRendererWrap(operator =>
+ translateOperator(operator.operator),
+ ),
+ valueRenderer: operator => (
+ {translateOperator(operator.operator)}
+ ),
valueKey: 'operator',
};
@@ -280,34 +304,38 @@ export default class AdhocFilterEditPopoverSimpleTabContent extends React.Compon
- {
- (
- MULTI_OPERATORS.indexOf(adhocFilter.operator) >= 0 ||
- this.state.suggestions.length > 0
- ) ?
- = 0}
- freeForm
- name="filter-comparator-value"
- value={adhocFilter.comparator}
- isLoading={this.state.loading}
- choices={this.state.suggestions}
- onChange={this.onComparatorChange}
- showHeader={false}
- noResultsText={t('type a value here')}
- refFunc={this.multiComparatorRef}
- disabled={adhocFilter.operator === 'IS NOT NULL' || adhocFilter.operator === 'IS NULL'}
- /> :
-
- }
+ {MULTI_OPERATORS.indexOf(adhocFilter.operator) >= 0 ||
+ this.state.suggestions.length > 0 ? (
+ = 0}
+ freeForm
+ name="filter-comparator-value"
+ value={adhocFilter.comparator}
+ isLoading={this.state.loading}
+ choices={this.state.suggestions}
+ onChange={this.onComparatorChange}
+ showHeader={false}
+ noResultsText={t('type a value here')}
+ refFunc={this.multiComparatorRef}
+ disabled={
+ adhocFilter.operator === 'IS NOT NULL' ||
+ adhocFilter.operator === 'IS NULL'
+ }
+ />
+ ) : (
+
+ )}
);
diff --git a/superset/assets/src/explore/components/AdhocFilterEditPopoverSqlTabContent.jsx b/superset/assets/src/explore/components/AdhocFilterEditPopoverSqlTabContent.jsx
index 32b58cc5efa..33586fcbdaa 100644
--- a/superset/assets/src/explore/components/AdhocFilterEditPopoverSqlTabContent.jsx
+++ b/superset/assets/src/explore/components/AdhocFilterEditPopoverSqlTabContent.jsx
@@ -37,11 +37,13 @@ import VirtualizedRendererWrap from '../../components/VirtualizedRendererWrap';
const propTypes = {
adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
onChange: PropTypes.func.isRequired,
- options: PropTypes.arrayOf(PropTypes.oneOfType([
- columnType,
- PropTypes.shape({ saved_metric_name: PropTypes.string.isRequired }),
- adhocMetricType,
- ])).isRequired,
+ options: PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ columnType,
+ PropTypes.shape({ saved_metric_name: PropTypes.string.isRequired }),
+ adhocMetricType,
+ ]),
+ ).isRequired,
height: PropTypes.number.isRequired,
};
@@ -51,7 +53,9 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component
constructor(props) {
super(props);
this.onSqlExpressionChange = this.onSqlExpressionChange.bind(this);
- this.onSqlExpressionClauseChange = this.onSqlExpressionClauseChange.bind(this);
+ this.onSqlExpressionClauseChange = this.onSqlExpressionClauseChange.bind(
+ this,
+ );
this.handleAceEditorRef = this.handleAceEditorRef.bind(this);
this.selectProps = {
@@ -64,12 +68,19 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component
};
if (langTools) {
- const words = sqlWords.concat(this.props.options.map((option) => {
- if (option.column_name) {
- return { name: option.column_name, value: option.column_name, score: 50, meta: 'option' };
- }
- return null;
- }));
+ const words = sqlWords.concat(
+ this.props.options.map(option => {
+ if (option.column_name) {
+ return {
+ name: option.column_name,
+ value: option.column_name,
+ score: 50,
+ meta: 'option',
+ };
+ }
+ return null;
+ }),
+ );
const completer = {
getCompletions: (aceEditor, session, pos, prefix, callback) => {
callback(null, words);
@@ -84,17 +95,21 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component
}
onSqlExpressionClauseChange(clause) {
- this.props.onChange(this.props.adhocFilter.duplicateWith({
- clause: clause && clause.clause,
- expressionType: EXPRESSION_TYPES.SQL,
- }));
+ this.props.onChange(
+ this.props.adhocFilter.duplicateWith({
+ clause: clause && clause.clause,
+ expressionType: EXPRESSION_TYPES.SQL,
+ }),
+ );
}
onSqlExpressionChange(sqlExpression) {
- this.props.onChange(this.props.adhocFilter.duplicateWith({
- sqlExpression,
- expressionType: EXPRESSION_TYPES.SQL,
- }));
+ this.props.onChange(
+ this.props.adhocFilter.duplicateWith({
+ sqlExpression,
+ expressionType: EXPRESSION_TYPES.SQL,
+ }),
+ );
}
handleAceEditorRef(ref) {
@@ -125,7 +140,8 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component
className="filter-edit-clause-dropdown"
/>
- Where filters by columns.
+ Where filters by columns.
+
Having filters by metrics.
@@ -134,7 +150,7 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component
ref={this.handleAceEditorRef}
mode="sql"
theme="github"
- height={(height - 100) + 'px'}
+ height={height - 100 + 'px'}
onChange={this.onSqlExpressionChange}
width="100%"
showGutter={false}
diff --git a/superset/assets/src/explore/components/AdhocFilterOption.jsx b/superset/assets/src/explore/components/AdhocFilterOption.jsx
index 195bbe43bdd..8b6adf621d5 100644
--- a/superset/assets/src/explore/components/AdhocFilterOption.jsx
+++ b/superset/assets/src/explore/components/AdhocFilterOption.jsx
@@ -28,11 +28,13 @@ import adhocMetricType from '../propTypes/adhocMetricType';
const propTypes = {
adhocFilter: PropTypes.instanceOf(AdhocFilter).isRequired,
onFilterEdit: PropTypes.func.isRequired,
- options: PropTypes.arrayOf(PropTypes.oneOfType([
- columnType,
- PropTypes.shape({ saved_metric_name: PropTypes.string.isRequired }),
- adhocMetricType,
- ])).isRequired,
+ options: PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ columnType,
+ PropTypes.shape({ saved_metric_name: PropTypes.string.isRequired }),
+ adhocMetricType,
+ ]),
+ ).isRequired,
datasource: PropTypes.object,
};
@@ -47,7 +49,7 @@ export default class AdhocFilterOption extends React.PureComponent {
}
onPopoverResize() {
- this.forceUpdate();
+ this.forceUpdate();
}
onOverlayEntered() {
@@ -97,9 +99,9 @@ export default class AdhocFilterOption extends React.PureComponent {
{adhocFilter.getDefaultLabel()}
diff --git a/superset/assets/src/explore/components/AdhocMetricEditPopover.jsx b/superset/assets/src/explore/components/AdhocMetricEditPopover.jsx
index 66406891650..c0b2394848b 100644
--- a/superset/assets/src/explore/components/AdhocMetricEditPopover.jsx
+++ b/superset/assets/src/explore/components/AdhocMetricEditPopover.jsx
@@ -18,7 +18,14 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { Button, ControlLabel, FormGroup, Popover, Tab, Tabs } from 'react-bootstrap';
+import {
+ Button,
+ ControlLabel,
+ FormGroup,
+ Popover,
+ Tab,
+ Tabs,
+} from 'react-bootstrap';
import VirtualizedSelect from 'react-virtualized-select';
import ace from 'brace';
import AceEditor from 'react-ace';
@@ -81,9 +88,14 @@ export default class AdhocMetricEditPopover extends React.Component {
selectWrap: VirtualizedSelect,
};
if (langTools) {
- const words = sqlWords.concat(this.props.columns.map(column => (
- { name: column.column_name, value: column.column_name, score: 50, meta: 'column' }
- )));
+ const words = sqlWords.concat(
+ this.props.columns.map(column => ({
+ name: column.column_name,
+ value: column.column_name,
+ score: 50,
+ meta: 'column',
+ })),
+ );
const completer = {
getCompletions: (aceEditor, session, pos, prefix, callback) => {
callback(null, words);
@@ -135,7 +147,8 @@ export default class AdhocMetricEditPopover extends React.Component {
onLabelChange(e) {
this.setState({
adhocMetric: this.state.adhocMetric.duplicateWith({
- label: e.target.value, hasCustomLabel: true,
+ label: e.target.value,
+ hasCustomLabel: true,
}),
});
}
@@ -151,8 +164,14 @@ export default class AdhocMetricEditPopover extends React.Component {
onMouseMove(e) {
this.props.onResize();
this.setState({
- width: Math.max(this.dragStartWidth + (e.clientX - this.dragStartX), startingWidth),
- height: Math.max(this.dragStartHeight + (e.clientY - this.dragStartY) * 2, startingHeight),
+ width: Math.max(
+ this.dragStartWidth + (e.clientX - this.dragStartX),
+ startingWidth,
+ ),
+ height: Math.max(
+ this.dragStartHeight + (e.clientY - this.dragStartY) * 2,
+ startingHeight,
+ ),
});
}
@@ -186,7 +205,8 @@ export default class AdhocMetricEditPopover extends React.Component {
const columnSelectProps = {
placeholder: t('%s column(s)', columns.length),
options: columns,
- value: (adhocMetric.column && adhocMetric.column.column_name) ||
+ value:
+ (adhocMetric.column && adhocMetric.column.column_name) ||
adhocMetric.inferSqlExpressionColumn(),
onChange: this.onColumnChange,
optionRenderer: VirtualizedRendererWrap(option => (
@@ -207,9 +227,9 @@ export default class AdhocMetricEditPopover extends React.Component {
};
if (this.props.datasourceType === 'druid') {
- aggregateSelectProps.options = aggregateSelectProps.options.filter((
- option => option.aggregate !== 'AVG'
- ));
+ aggregateSelectProps.options = aggregateSelectProps.options.filter(
+ option => option.aggregate !== 'AVG',
+ );
}
const popoverTitle = (
@@ -222,11 +242,7 @@ export default class AdhocMetricEditPopover extends React.Component {
const stateIsValid = adhocMetric.isValid();
const hasUnsavedChanges = !adhocMetric.equals(propsAdhocMetric);
return (
-
+
-
+
- column
+
+ column
+
- aggregate
-
+
+ aggregate
+
+
-
- {
- this.props.datasourceType !== 'druid' ?
-
-
- :
-
- Custom SQL Metrics are not available on druid datasources
-
- }
+
+ {this.props.datasourceType !== 'druid' ? (
+
+
+
+ ) : (
+
+ Custom SQL Metrics are not available on druid datasources
+
+ )}
Save
- Close
-
+
+ Close
+
+
);
diff --git a/superset/assets/src/explore/components/AdhocMetricEditPopoverTitle.jsx b/superset/assets/src/explore/components/AdhocMetricEditPopoverTitle.jsx
index 22663e6aa1c..8d0c06294ee 100644
--- a/superset/assets/src/explore/components/AdhocMetricEditPopoverTitle.jsx
+++ b/superset/assets/src/explore/components/AdhocMetricEditPopoverTitle.jsx
@@ -64,7 +64,9 @@ export default class AdhocMetricEditPopoverTitle extends React.Component {
render() {
const { adhocMetric, onChange } = this.props;
- const editPrompt = Click to edit label ;
+ const editPrompt = (
+ Click to edit label
+ );
return (
- {this.state.isEditable ?
+ {this.state.isEditable ? (
:
+ />
+ ) : (
{adhocMetric.hasCustomLabel ? adhocMetric.label : 'My Metric'}
-
+
- }
+ )}
);
}
diff --git a/superset/assets/src/explore/components/AdhocMetricOption.jsx b/superset/assets/src/explore/components/AdhocMetricOption.jsx
index a1ca1ed892e..ae168ca416f 100644
--- a/superset/assets/src/explore/components/AdhocMetricOption.jsx
+++ b/superset/assets/src/explore/components/AdhocMetricOption.jsx
@@ -85,13 +85,17 @@ export default class AdhocMetricOption extends React.PureComponent {
onExited={this.onOverlayExited}
>
- { e.stopPropagation(); }}>
+
{
+ e.stopPropagation();
+ }}
+ >
{adhocMetric.label}
diff --git a/superset/assets/src/explore/components/AdhocMetricStaticOption.jsx b/superset/assets/src/explore/components/AdhocMetricStaticOption.jsx
index 3aa5c4cdcb1..cc35b7b9c20 100644
--- a/superset/assets/src/explore/components/AdhocMetricStaticOption.jsx
+++ b/superset/assets/src/explore/components/AdhocMetricStaticOption.jsx
@@ -31,9 +31,7 @@ export default function AdhocMetricStaticOption({ adhocMetric, showType }) {
return (
{showType && }
-
- {adhocMetric.label}
-
+ {adhocMetric.label}
);
}
diff --git a/superset/assets/src/explore/components/AggregateOption.jsx b/superset/assets/src/explore/components/AggregateOption.jsx
index 6aaa8456886..6170f6d1361 100644
--- a/superset/assets/src/explore/components/AggregateOption.jsx
+++ b/superset/assets/src/explore/components/AggregateOption.jsx
@@ -31,9 +31,7 @@ export default function AggregateOption({ aggregate, showType }) {
return (
{showType && }
-
- {aggregate.aggregate_name}
-
+ {aggregate.aggregate_name}
);
}
diff --git a/superset/assets/src/explore/components/ControlHeader.jsx b/superset/assets/src/explore/components/ControlHeader.jsx
index ed27d165cf7..d0d0050f8a1 100644
--- a/superset/assets/src/explore/components/ControlHeader.jsx
+++ b/superset/assets/src/explore/components/ControlHeader.jsx
@@ -49,29 +49,28 @@ export default class ControlHeader extends React.Component {
if (this.props.hovered) {
return (
- {this.props.description &&
+ {this.props.description && (
- {' '}
+ />{' '}
- }
- {this.props.renderTrigger &&
+ )}
+ {this.props.renderTrigger && (
- {' '}
+ />{' '}
- }
- );
+ )}
+
+ );
}
return null;
}
@@ -79,26 +78,21 @@ export default class ControlHeader extends React.Component {
if (!this.props.label) {
return null;
}
- const labelClass = (this.props.validationErrors.length > 0) ? 'text-danger' : '';
+ const labelClass =
+ this.props.validationErrors.length > 0 ? 'text-danger' : '';
return (
-
+
- {this.props.leftNode &&
- {this.props.leftNode}
- }
+ {this.props.leftNode && {this.props.leftNode} }
{this.props.label}
-
- {' '}
- {(this.props.warning) &&
+ {' '}
+ {this.props.warning && (
-
- {' '}
+ {' '}
- }
- {(this.props.danger) &&
+ )}
+ {this.props.danger && (
-
- {' '}
+ {' '}
- }
- {(this.props.validationErrors.length > 0) &&
+ )}
+ {this.props.validationErrors.length > 0 && (
-
- {' '}
+ {' '}
- }
+ )}
{this.renderOptionalIcons()}
- {this.props.rightNode &&
-
- {this.props.rightNode}
-
- }
+ {this.props.rightNode && (
+
{this.props.rightNode}
+ )}
);
diff --git a/superset/assets/src/explore/components/ControlPanelSection.jsx b/superset/assets/src/explore/components/ControlPanelSection.jsx
index 14652fe1dc2..47c7fc10654 100644
--- a/superset/assets/src/explore/components/ControlPanelSection.jsx
+++ b/superset/assets/src/explore/components/ControlPanelSection.jsx
@@ -47,24 +47,30 @@ export default class ControlPanelSection extends React.Component {
renderHeader() {
const { label, description, hasErrors } = this.props;
return (
- label &&
+ label && (
- {label}
- {' '}
- {description && }
- {hasErrors &&
+ {label} {' '}
+ {description && (
+
+ )}
+ {hasErrors && (
}
+ />
+ )}
-
);
+
+ )
+ );
}
render() {
diff --git a/superset/assets/src/explore/components/ControlPanelsContainer.jsx b/superset/assets/src/explore/components/ControlPanelsContainer.jsx
index 12057383091..e377ab00ddb 100644
--- a/superset/assets/src/explore/components/ControlPanelsContainer.jsx
+++ b/superset/assets/src/explore/components/ControlPanelsContainer.jsx
@@ -63,21 +63,32 @@ class ControlPanelsContainer extends React.Component {
let mapF = controlConfigs[controlName].mapStateToProps;
// Looking to find mapStateToProps override for this viz type
- const controlPanelConfig = getChartControlPanelRegistry()
- .get(this.props.controls.viz_type.value) || {};
+ const controlPanelConfig =
+ getChartControlPanelRegistry().get(this.props.controls.viz_type.value) ||
+ {};
const controlOverrides = controlPanelConfig.controlOverrides || {};
- if (controlOverrides[controlName] && controlOverrides[controlName].mapStateToProps) {
+ if (
+ controlOverrides[controlName] &&
+ controlOverrides[controlName].mapStateToProps
+ ) {
mapF = controlOverrides[controlName].mapStateToProps;
}
// Applying mapStateToProps if needed
if (mapF) {
- return Object.assign({}, control, mapF(this.props.exploreState, control, this.props.actions));
+ return Object.assign(
+ {},
+ control,
+ mapF(this.props.exploreState, control, this.props.actions),
+ );
}
return control;
}
sectionsToRender() {
- return sectionsToRender(this.props.form_data.viz_type, this.props.datasource_type);
+ return sectionsToRender(
+ this.props.form_data.viz_type,
+ this.props.datasource_type,
+ );
}
removeAlert() {
@@ -88,20 +99,21 @@ class ControlPanelsContainer extends React.Component {
const { actions, controls, exploreState, form_data: formData } = this.props;
// Looking to find mapStateToProps override for this viz type
- const controlPanelConfig = getChartControlPanelRegistry().get(controls.viz_type.value) || {};
+ const controlPanelConfig =
+ getChartControlPanelRegistry().get(controls.viz_type.value) || {};
const controlOverrides = controlPanelConfig.controlOverrides || {};
const overrides = controlOverrides[name];
// Identifying mapStateToProps function to apply (logic can't be in store)
- const mapFn = (overrides && overrides.mapStateToProps)
- ? overrides.mapStateToProps
- : config.mapStateToProps;
+ const mapFn =
+ overrides && overrides.mapStateToProps
+ ? overrides.mapStateToProps
+ : config.mapStateToProps;
// If the control item is not an object, we have to look up the control data from
// the centralized controls file.
// When it is an object we read control data straight from `config` instead
- const controlData = lookupControlData ?
- controls[name] : config;
+ const controlData = lookupControlData ? controls[name] : config;
// Applying mapStateToProps if needed
const additionalProps = mapFn
@@ -126,11 +138,14 @@ class ControlPanelsContainer extends React.Component {
renderControlPanelSection(section) {
const { controls } = this.props;
- const hasErrors = section.controlSetRows.some(rows => rows.some(s => (
- controls[s] &&
- controls[s].validationErrors &&
- (controls[s].validationErrors.length > 0)
- )));
+ const hasErrors = section.controlSetRows.some(rows =>
+ rows.some(
+ s =>
+ controls[s] &&
+ controls[s].validationErrors &&
+ controls[s].validationErrors.length > 0,
+ ),
+ );
return (
{
+ controls={controlSets.map(controlItem => {
if (!controlItem) {
// When the item is invalid
return null;
} else if (React.isValidElement(controlItem)) {
// When the item is a React element
return controlItem;
- } else if (isPlainObject(controlItem) && controlItem.name && controlItem.config) {
+ } else if (
+ isPlainObject(controlItem) &&
+ controlItem.name &&
+ controlItem.config
+ ) {
const { name, config } = controlItem;
return this.renderControl(name, config, false);
@@ -174,15 +193,17 @@ class ControlPanelsContainer extends React.Component {
const allSectionsToRender = this.sectionsToRender();
const querySectionsToRender = [];
const displaySectionsToRender = [];
- allSectionsToRender.forEach((section) => {
- if (section.controlSetRows.some(rows => rows.some(
- control => (
- controlConfigs[control] &&
- (
- !controlConfigs[control].renderTrigger ||
- controlConfigs[control].tabOverride === 'data'
- )
- )))) {
+ allSectionsToRender.forEach(section => {
+ if (
+ section.controlSetRows.some(rows =>
+ rows.some(
+ control =>
+ controlConfigs[control] &&
+ (!controlConfigs[control].renderTrigger ||
+ controlConfigs[control].tabOverride === 'data'),
+ ),
+ )
+ ) {
querySectionsToRender.push(section);
} else {
displaySectionsToRender.push(section);
@@ -192,7 +213,7 @@ class ControlPanelsContainer extends React.Component {
return (
- {this.props.alert &&
+ {this.props.alert && (
{this.props.alert}
- }
+ )}
{querySectionsToRender.map(this.renderControlPanelSection)}
- {displaySectionsToRender.length > 0 &&
+ {displaySectionsToRender.length > 0 && (
{displaySectionsToRender.map(this.renderControlPanelSection)}
- }
+ )}
@@ -237,4 +258,7 @@ function mapDispatchToProps(dispatch) {
export { ControlPanelsContainer };
-export default connect(mapStateToProps, mapDispatchToProps)(ControlPanelsContainer);
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(ControlPanelsContainer);
diff --git a/superset/assets/src/explore/components/ControlRow.jsx b/superset/assets/src/explore/components/ControlRow.jsx
index 1bfd599397a..47a0a70de4b 100644
--- a/superset/assets/src/explore/components/ControlRow.jsx
+++ b/superset/assets/src/explore/components/ControlRow.jsx
@@ -30,7 +30,7 @@ function ControlSetRow(props) {
return (
{props.controls.map((control, i) => (
-
+
{control}
))}
diff --git a/superset/assets/src/explore/components/DisplayQueryButton.jsx b/superset/assets/src/explore/components/DisplayQueryButton.jsx
index 3b23176a586..2ac322113f8 100644
--- a/superset/assets/src/explore/components/DisplayQueryButton.jsx
+++ b/superset/assets/src/explore/components/DisplayQueryButton.jsx
@@ -18,13 +18,21 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import SyntaxHighlighter, { registerLanguage } from 'react-syntax-highlighter/light';
+import SyntaxHighlighter, {
+ registerLanguage,
+} from 'react-syntax-highlighter/light';
import htmlSyntax from 'react-syntax-highlighter/languages/hljs/htmlbars';
import markdownSyntax from 'react-syntax-highlighter/languages/hljs/markdown';
import sqlSyntax from 'react-syntax-highlighter/languages/hljs/sql';
import jsonSyntax from 'react-syntax-highlighter/languages/hljs/json';
import github from 'react-syntax-highlighter/styles/hljs/github';
-import { DropdownButton, MenuItem, Row, Col, FormControl } from 'react-bootstrap';
+import {
+ DropdownButton,
+ MenuItem,
+ Row,
+ Col,
+ FormControl,
+} from 'react-bootstrap';
import { Table } from 'reactable-arc';
import { t } from '@superset-ui/translation';
import { SupersetClient } from '@superset-ui/connection';
@@ -148,7 +156,10 @@ export default class DisplayQueryButton extends React.PureComponent {
-
+
);
+ return (
+
+ );
} else if (this.state.error) {
return {this.state.error} ;
} else if (this.state.data) {
@@ -201,8 +214,10 @@ export default class DisplayQueryButton extends React.PureComponent {
noCaret
title={
-
- }
+
+
+
+ }
bsSize="sm"
pullRight
id="query"
@@ -238,10 +253,7 @@ export default class DisplayQueryButton extends React.PureComponent {
eventKey="2"
/>
{this.state.sqlSupported && (
-
+
{t('Run in SQL Lab')}
)}
diff --git a/superset/assets/src/explore/components/EmbedCodeButton.jsx b/superset/assets/src/explore/components/EmbedCodeButton.jsx
index a56bfe5a970..7f3217c086b 100644
--- a/superset/assets/src/explore/components/EmbedCodeButton.jsx
+++ b/superset/assets/src/explore/components/EmbedCodeButton.jsx
@@ -47,11 +47,10 @@ export default class EmbedCodeButton extends React.Component {
}
generateEmbedHTML() {
- const srcLink = (
+ const srcLink =
window.location.origin +
getExploreLongUrl(this.props.latestQueryFormData, 'standalone') +
- `&height=${this.state.height}`
- );
+ `&height=${this.state.height}`;
return (
'}
+ copyNode={
+
+ }
/>
@@ -93,7 +97,9 @@ export default class EmbedCodeButton extends React.Component {
- {t('Height')}
+
+ {t('Height')}
+
- {t('Width')}
+
+ {t('Width')}
+
-
+
+
);
diff --git a/superset/assets/src/explore/components/ExploreActionButtons.jsx b/superset/assets/src/explore/components/ExploreActionButtons.jsx
index 5734990bb95..c7a7f20c356 100644
--- a/superset/assets/src/explore/components/ExploreActionButtons.jsx
+++ b/superset/assets/src/explore/components/ExploreActionButtons.jsx
@@ -28,14 +28,20 @@ import { exportChart, getExploreLongUrl } from '../exploreUtils';
const propTypes = {
actions: PropTypes.object.isRequired,
- canDownload: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]).isRequired,
+ canDownload: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])
+ .isRequired,
chartStatus: PropTypes.string,
latestQueryFormData: PropTypes.object,
queryResponse: PropTypes.object,
};
export default function ExploreActionButtons({
- actions, canDownload, chartStatus, latestQueryFormData, queryResponse }) {
+ actions,
+ canDownload,
+ chartStatus,
+ latestQueryFormData,
+ queryResponse,
+}) {
const exportToCSVClasses = cx('btn btn-default btn-sm', {
'disabled disabledButton': !canDownload,
});
@@ -44,18 +50,19 @@ export default function ExploreActionButtons({
return (
- {latestQueryFormData &&
+ {latestQueryFormData && (
- }
+ )}
- {latestQueryFormData &&
-
}
+ {latestQueryFormData && (
+
+ )}
- {latestQueryFormData &&
+ {latestQueryFormData && (
.json
- }
- {latestQueryFormData &&
+
+ )}
+ {latestQueryFormData && (
.csv
- }
+
+ )}
{
- const { data } = json;
- if (isNewSlice) {
- this.props.actions.updateChartId(data.slice.slice_id, 0);
- this.props.actions.createNewSlice(
- data.can_add, data.can_download, data.can_overwrite,
- data.slice, data.form_data);
- this.props.addHistory({ isReplace: true, title: `[chart] ${data.slice.slice_name}` });
- } else {
- this.props.actions.updateChartTitle(newTitle);
- }
- });
+ this.props.actions.saveSlice(this.props.form_data, params).then(json => {
+ const { data } = json;
+ if (isNewSlice) {
+ this.props.actions.updateChartId(data.slice.slice_id, 0);
+ this.props.actions.createNewSlice(
+ data.can_add,
+ data.can_download,
+ data.can_overwrite,
+ data.slice,
+ data.form_data,
+ );
+ this.props.addHistory({
+ isReplace: true,
+ title: `[chart] ${data.slice.slice_name}`,
+ });
+ } else {
+ this.props.actions.updateChartTitle(newTitle);
+ }
+ });
}
renderChartTitle() {
@@ -93,58 +103,60 @@ class ExploreChartHeader extends React.PureComponent {
chartUpdateEndTime,
chartUpdateStartTime,
latestQueryFormData,
- queryResponse } = this.props.chart;
- const chartFinished = ['failed', 'rendered', 'success'].includes(this.props.chart.chartStatus);
+ queryResponse,
+ } = this.props.chart;
+ const chartFinished = ['failed', 'rendered', 'success'].includes(
+ this.props.chart.chartStatus,
+ );
return (
- ,
scheduleInfoContainer,
);
diff --git a/superset/assets/src/utils/DebouncedMessageQueue.js b/superset/assets/src/utils/DebouncedMessageQueue.js
index 70a46ffcd1a..2b6293c8b64 100644
--- a/superset/assets/src/utils/DebouncedMessageQueue.js
+++ b/superset/assets/src/utils/DebouncedMessageQueue.js
@@ -19,7 +19,11 @@
import { debounce } from 'lodash';
class DebouncedMessageQueue {
- constructor({ callback = () => {}, sizeThreshold = 1000, delayThreshold = 1000 }) {
+ constructor({
+ callback = () => {},
+ sizeThreshold = 1000,
+ delayThreshold = 1000,
+ }) {
this.queue = [];
this.sizeThreshold = sizeThreshold;
this.delayThrehold = delayThreshold;
diff --git a/superset/assets/src/utils/common.js b/superset/assets/src/utils/common.js
index c1a873a8efd..80ef3e3a76e 100644
--- a/superset/assets/src/utils/common.js
+++ b/superset/assets/src/utils/common.js
@@ -34,7 +34,7 @@ export function storeQuery(query) {
return SupersetClient.post({
endpoint: '/kv/store/',
postPayload: { data: query },
- }).then((response) => {
+ }).then(response => {
const baseUrl = window.location.origin + window.location.pathname;
const url = `${baseUrl}?id=${response.json.id}`;
return url;
@@ -45,7 +45,7 @@ export function getParamsFromUrl() {
const hash = window.location.search;
const params = hash.split('?')[1].split('&');
const newParams = {};
- params.forEach((p) => {
+ params.forEach(p => {
const value = p.split('=')[1].replace(/\+/g, ' ');
const key = p.split('=')[0];
newParams[key] = value;
@@ -62,8 +62,10 @@ export function getShortUrl(longUrl) {
})
.then(({ text }) => text)
.catch(response =>
- getClientErrorObject(response)
- .then(({ error, statusText }) => Promise.reject(error || statusText)));
+ getClientErrorObject(response).then(({ error, statusText }) =>
+ Promise.reject(error || statusText),
+ ),
+ );
}
export function supersetURL(rootUrl, getParams = {}) {
diff --git a/superset/assets/src/utils/errorMessages.js b/superset/assets/src/utils/errorMessages.js
index aa532e1042a..16a04105c4c 100644
--- a/superset/assets/src/utils/errorMessages.js
+++ b/superset/assets/src/utils/errorMessages.js
@@ -18,7 +18,8 @@
*/
// Error messages used in many places across applications
const COMMON_ERR_MESSAGES = {
- SESSION_TIMED_OUT: 'Your session timed out, please refresh your page and try again.',
+ SESSION_TIMED_OUT:
+ 'Your session timed out, please refresh your page and try again.',
};
export default COMMON_ERR_MESSAGES;
diff --git a/superset/assets/src/utils/getClientErrorObject.js b/superset/assets/src/utils/getClientErrorObject.js
index 8af1e54ce9b..fad31a0024d 100644
--- a/superset/assets/src/utils/getClientErrorObject.js
+++ b/superset/assets/src/utils/getClientErrorObject.js
@@ -22,37 +22,53 @@ import COMMON_ERR_MESSAGES from './errorMessages';
export default function getClientErrorObject(response) {
// takes a Response object as input, attempts to read response as Json if possible,
// and returns a Promise that resolves to a plain object with error key and text value.
- return new Promise((resolve) => {
+ return new Promise(resolve => {
if (typeof response === 'string') {
resolve({ error: response });
- } else if (response && response.constructor === Response && !response.bodyUsed) {
+ } else if (
+ response &&
+ response.constructor === Response &&
+ !response.bodyUsed
+ ) {
// attempt to read the body as json, and fallback to text. we must clone the
// response in order to fallback to .text() because Response is single-read
- response.clone().json().then((errorJson) => {
- let error = { ...response, ...errorJson };
- if (error.stack) {
- error = {
- ...error,
- error: t('Unexpected error: ') +
- (error.description || t('(no description, click to see stack trace)')),
- stacktrace: error.stack,
- };
- } else if (error.responseText && error.responseText.indexOf('CSRF') >= 0) {
- error = {
- ...error,
- error: t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT),
- };
- }
- resolve(error);
- }).catch(() => {
- // fall back to reading as text
- response.text().then((errorText) => {
- resolve({ ...response, error: errorText });
+ response
+ .clone()
+ .json()
+ .then(errorJson => {
+ let error = { ...response, ...errorJson };
+ if (error.stack) {
+ error = {
+ ...error,
+ error:
+ t('Unexpected error: ') +
+ (error.description ||
+ t('(no description, click to see stack trace)')),
+ stacktrace: error.stack,
+ };
+ } else if (
+ error.responseText &&
+ error.responseText.indexOf('CSRF') >= 0
+ ) {
+ error = {
+ ...error,
+ error: t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT),
+ };
+ }
+ resolve(error);
+ })
+ .catch(() => {
+ // fall back to reading as text
+ response.text().then(errorText => {
+ resolve({ ...response, error: errorText });
+ });
});
- });
} else {
// fall back to Response.statusText or generic error of we cannot read the response
- resolve({ ...response, error: response.statusText || t('An error occurred') });
+ resolve({
+ ...response,
+ error: response.statusText || t('An error occurred'),
+ });
}
});
}
diff --git a/superset/assets/src/utils/hostNamesConfig.js b/superset/assets/src/utils/hostNamesConfig.js
index 594345592d7..98ac055fc57 100644
--- a/superset/assets/src/utils/hostNamesConfig.js
+++ b/superset/assets/src/utils/hostNamesConfig.js
@@ -24,12 +24,13 @@ function getDomainsConfig() {
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
const availableDomains = new Set([location.hostname]);
- if (bootstrapData &&
+ if (
+ bootstrapData &&
bootstrapData.common &&
bootstrapData.common.conf &&
bootstrapData.common.conf.SUPERSET_WEBSERVER_DOMAINS
) {
- bootstrapData.common.conf.SUPERSET_WEBSERVER_DOMAINS.forEach((hostName) => {
+ bootstrapData.common.conf.SUPERSET_WEBSERVER_DOMAINS.forEach(hostName => {
availableDomains.add(hostName);
});
}
diff --git a/superset/assets/src/utils/reducerUtils.js b/superset/assets/src/utils/reducerUtils.js
index 91385e2e84c..1059fe958d9 100644
--- a/superset/assets/src/utils/reducerUtils.js
+++ b/superset/assets/src/utils/reducerUtils.js
@@ -31,7 +31,7 @@ export function addToObject(state, arrKey, obj) {
export function alterInObject(state, arrKey, obj, alterations) {
const newObject = Object.assign({}, state[arrKey]);
- newObject[obj.id] = (Object.assign({}, newObject[obj.id], alterations));
+ newObject[obj.id] = Object.assign({}, newObject[obj.id], alterations);
return Object.assign({}, state, { [arrKey]: newObject });
}
@@ -40,7 +40,7 @@ export function alterInArr(state, arrKey, obj, alterations) {
// new object with an altered property
const idKey = 'id';
const newArr = [];
- state[arrKey].forEach((arrItem) => {
+ state[arrKey].forEach(arrItem => {
if (obj[idKey] === arrItem[idKey]) {
newArr.push(Object.assign({}, arrItem, alterations));
} else {
@@ -52,7 +52,7 @@ export function alterInArr(state, arrKey, obj, alterations) {
export function removeFromArr(state, arrKey, obj, idKey = 'id') {
const newArr = [];
- state[arrKey].forEach((arrItem) => {
+ state[arrKey].forEach(arrItem => {
if (!(obj[idKey] === arrItem[idKey])) {
newArr.push(arrItem);
}
diff --git a/superset/assets/src/visualizations/FilterBox/FilterBox.jsx b/superset/assets/src/visualizations/FilterBox/FilterBox.jsx
index 40a954eb469..23896a18f6b 100644
--- a/superset/assets/src/visualizations/FilterBox/FilterBox.jsx
+++ b/superset/assets/src/visualizations/FilterBox/FilterBox.jsx
@@ -55,16 +55,22 @@ const propTypes = {
origSelectedValues: PropTypes.object,
datasource: PropTypes.object.isRequired,
instantFiltering: PropTypes.bool,
- filtersFields: PropTypes.arrayOf(PropTypes.shape({
- field: PropTypes.string,
- label: PropTypes.string,
- })),
- filtersChoices: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.shape({
- id: PropTypes.string,
- text: PropTypes.string,
- filter: PropTypes.string,
- metric: PropTypes.number,
- }))),
+ filtersFields: PropTypes.arrayOf(
+ PropTypes.shape({
+ field: PropTypes.string,
+ label: PropTypes.string,
+ }),
+ ),
+ filtersChoices: PropTypes.objectOf(
+ PropTypes.arrayOf(
+ PropTypes.shape({
+ id: PropTypes.string,
+ text: PropTypes.string,
+ filter: PropTypes.string,
+ metric: PropTypes.number,
+ }),
+ ),
+ ),
onChange: PropTypes.func,
onFilterMenuOpen: PropTypes.func,
onFilterMenuClose: PropTypes.func,
@@ -100,7 +106,10 @@ class FilterBox extends React.Component {
this.onFilterMenuClose = this.onFilterMenuClose.bind(this);
this.onFocus = this.onFilterMenuOpen;
this.onBlur = this.onFilterMenuClose;
- this.onOpenDateFilterControl = this.onFilterMenuOpen.bind(props.chartId, TIME_RANGE);
+ this.onOpenDateFilterControl = this.onFilterMenuOpen.bind(
+ props.chartId,
+ TIME_RANGE,
+ );
}
onFilterMenuOpen(chartId, column) {
@@ -120,9 +129,7 @@ class FilterBox extends React.Component {
actions: { setControlValue: this.changeFilter },
});
const mapFunc = control.mapStateToProps;
- return mapFunc
- ? Object.assign({}, control, mapFunc(this.props))
- : control;
+ return mapFunc ? Object.assign({}, control, mapFunc(this.props)) : control;
}
clickApply() {
@@ -168,7 +175,9 @@ class FilterBox extends React.Component {
name={TIME_RANGE}
label={label}
description={t('Select start and end date')}
- onChange={(...args) => { this.changeFilter(TIME_RANGE, ...args); }}
+ onChange={(...args) => {
+ this.changeFilter(TIME_RANGE, ...args);
+ }}
onOpenDateFilterControl={this.onOpenDateFilterControl}
onCloseDateFilterControl={this.onFilterMenuClose}
value={this.state.selectedValues[TIME_RANGE] || 'No filter'}
@@ -225,8 +234,10 @@ class FilterBox extends React.Component {
// Add created options to filtersChoices, even though it doesn't exist,
// or these options will exist in query sql but invisible to end user.
Object.keys(selectedValues)
- .filter(key => selectedValues.hasOwnProperty(key) && (key in filtersChoices))
- .forEach((key) => {
+ .filter(
+ key => selectedValues.hasOwnProperty(key) && key in filtersChoices,
+ )
+ .forEach(key => {
const choices = filtersChoices[key] || [];
const choiceIds = new Set(choices.map(f => f.id));
const selectedValuesForKey = Array.isArray(selectedValues[key])
@@ -234,7 +245,7 @@ class FilterBox extends React.Component {
: [selectedValues[key]];
selectedValuesForKey
.filter(value => !choiceIds.has(value))
- .forEach((value) => {
+ .forEach(value => {
choices.unshift({
filter: key,
id: value,
@@ -264,33 +275,37 @@ class FilterBox extends React.Component {
multi={filterConfig.multiple}
clearable={filterConfig.clearable}
value={value}
- options={data.map((opt) => {
+ options={data.map(opt => {
const perc = Math.round((opt.metric / max) * 100);
- const backgroundImage = (
+ const backgroundImage =
'linear-gradient(to right, lightgrey, ' +
- `lightgrey ${perc}%, rgba(0,0,0,0) ${perc}%`
- );
+ `lightgrey ${perc}%, rgba(0,0,0,0) ${perc}%`;
const style = {
backgroundImage,
padding: '2px 5px',
};
return { value: opt.id, label: opt.id, style };
})}
- onChange={(...args) => { this.changeFilter(key, ...args); }}
+ onChange={(...args) => {
+ this.changeFilter(key, ...args);
+ }}
onFocus={this.onFocus}
onBlur={this.onBlur}
- onOpen={(...args) => { this.onFilterMenuOpen(key, ...args); }}
+ onOpen={(...args) => {
+ this.onFilterMenuOpen(key, ...args);
+ }}
onClose={this.onFilterMenuClose}
selectComponent={Creatable}
selectWrap={VirtualizedSelect}
optionRenderer={VirtualizedRendererWrap(opt => opt.label)}
noResultsText={t('No results found')}
- />);
+ />
+ );
}
renderFilters() {
const { filtersFields, chartId } = this.props;
- return filtersFields.map((filterConfig) => {
+ return filtersFields.map(filterConfig => {
const { label, key } = filterConfig;
return (
@@ -311,9 +326,7 @@ class FilterBox extends React.Component {
return (
-
+
);
}
@@ -327,7 +340,7 @@ class FilterBox extends React.Component {
{this.renderDateFilter()}
{this.renderDatasourceFilters()}
{this.renderFilters()}
- {!instantFiltering &&
+ {!instantFiltering && (
{t('Apply')}
- }
+ )}
);
diff --git a/superset/assets/src/visualizations/FilterBox/FilterBox.less b/superset/assets/src/visualizations/FilterBox/FilterBox.less
index e37c3d6776f..b2b2f64a456 100644
--- a/superset/assets/src/visualizations/FilterBox/FilterBox.less
+++ b/superset/assets/src/visualizations/FilterBox/FilterBox.less
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-@import "../../../stylesheets/less/variables.less";
+@import '../../../stylesheets/less/variables.less';
.select2-highlighted > .filter_box {
background-color: transparent;
diff --git a/superset/assets/src/visualizations/FilterBox/FilterBoxChartPlugin.js b/superset/assets/src/visualizations/FilterBox/FilterBoxChartPlugin.js
index 2549effb193..def1a2c76f2 100644
--- a/superset/assets/src/visualizations/FilterBox/FilterBoxChartPlugin.js
+++ b/superset/assets/src/visualizations/FilterBox/FilterBoxChartPlugin.js
@@ -23,7 +23,8 @@ import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
name: t('Filter Box'),
- description: 'A multi filter, multi-choice filter box to make dashboards interactive',
+ description:
+ 'A multi filter, multi-choice filter box to make dashboards interactive',
thumbnail,
});
diff --git a/superset/assets/src/visualizations/FilterBox/transformProps.js b/superset/assets/src/visualizations/FilterBox/transformProps.js
index bd39404c47d..f00918a0bb8 100644
--- a/superset/assets/src/visualizations/FilterBox/transformProps.js
+++ b/superset/assets/src/visualizations/FilterBox/transformProps.js
@@ -29,7 +29,7 @@ export default function transformProps(chartProps) {
} = chartProps;
const {
onAddFilter = NOOP,
- onFilterMenuOpen = NOOP,
+ onFilterMenuOpen = NOOP,
onFilterMenuClose = NOOP,
} = hooks;
const {
diff --git a/superset/assets/src/visualizations/TimeTable/FormattedNumber.jsx b/superset/assets/src/visualizations/TimeTable/FormattedNumber.jsx
index 414d06b5245..57cc4037859 100644
--- a/superset/assets/src/visualizations/TimeTable/FormattedNumber.jsx
+++ b/superset/assets/src/visualizations/TimeTable/FormattedNumber.jsx
@@ -32,9 +32,7 @@ const defaultProps = {
function FormattedNumber({ num, format }) {
if (format) {
- return (
-
{formatNumber(format, num)}
- );
+ return
{formatNumber(format, num)} ;
}
return
{num} ;
}
diff --git a/superset/assets/src/visualizations/TimeTable/SparklineCell.jsx b/superset/assets/src/visualizations/TimeTable/SparklineCell.jsx
index 3b531baef6f..da73d02a829 100644
--- a/superset/assets/src/visualizations/TimeTable/SparklineCell.jsx
+++ b/superset/assets/src/visualizations/TimeTable/SparklineCell.jsx
@@ -18,7 +18,14 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
-import { Sparkline, LineSeries, PointSeries, HorizontalReferenceLine, VerticalReferenceLine, WithTooltip } from '@data-ui/sparkline';
+import {
+ Sparkline,
+ LineSeries,
+ PointSeries,
+ HorizontalReferenceLine,
+ VerticalReferenceLine,
+ WithTooltip,
+} from '@data-ui/sparkline';
import { formatNumber } from '@superset-ui/number-format';
import { getTextDimension } from '@superset-ui/dimension';
@@ -41,7 +48,9 @@ const defaultProps = {
numberFormat: undefined,
yAxisBounds: [null, null],
showYAxis: false,
- renderTooltip() { return
; },
+ renderTooltip() {
+ return
;
+ },
};
const MARGIN = {
@@ -58,18 +67,25 @@ const tooltipProps = {
};
function getSparklineTextWidth(text) {
- return getTextDimension({
- text,
- style: {
- fontSize: '12px',
- fontWeight: 200,
- letterSpacing: 0.4,
- },
- }).width + 5;
+ return (
+ getTextDimension({
+ text,
+ style: {
+ fontSize: '12px',
+ fontWeight: 200,
+ letterSpacing: 0.4,
+ },
+ }).width + 5
+ );
}
function isValidBoundValue(value) {
- return value !== null && value !== undefined && value !== '' && !Number.isNaN(value);
+ return (
+ value !== null &&
+ value !== undefined &&
+ value !== '' &&
+ !Number.isNaN(value)
+ );
}
class SparklineCell extends React.Component {
@@ -158,26 +174,23 @@ class SparklineCell extends React.Component {
onMouseMove={onMouseMove}
{...yScale}
>
- {showYAxis &&
- this.renderHorizontalReferenceLine(min, minLabel)}
- {showYAxis &&
- this.renderHorizontalReferenceLine(max, maxLabel)}
-
- {tooltipData &&
+ {showYAxis && this.renderHorizontalReferenceLine(min, minLabel)}
+ {showYAxis && this.renderHorizontalReferenceLine(max, maxLabel)}
+
+ {tooltipData && (
}
- {tooltipData &&
+ />
+ )}
+ {tooltipData && (
}
+ />
+ )}
)}
diff --git a/superset/assets/src/visualizations/TimeTable/TimeTable.jsx b/superset/assets/src/visualizations/TimeTable/TimeTable.jsx
index a0a241424a2..1b091b1e8fa 100644
--- a/superset/assets/src/visualizations/TimeTable/TimeTable.jsx
+++ b/superset/assets/src/visualizations/TimeTable/TimeTable.jsx
@@ -57,22 +57,26 @@ const propTypes = {
// Example
// {'2018-04-14 00:00:00': { 'SUM(metric_value)': 80031779.40047 }}
data: PropTypes.objectOf(PropTypes.objectOf(PropTypes.number)).isRequired,
- columnConfigs: PropTypes.arrayOf(PropTypes.shape({
- colType: PropTypes.string,
- comparisonType: PropTypes.string,
- d3format: PropTypes.string,
- key: PropTypes.string,
- label: PropTypes.string,
- timeLag: PropTypes.number,
- })).isRequired,
- rows: PropTypes.arrayOf(PropTypes.oneOfType([
+ columnConfigs: PropTypes.arrayOf(
PropTypes.shape({
+ colType: PropTypes.string,
+ comparisonType: PropTypes.string,
+ d3format: PropTypes.string,
+ key: PropTypes.string,
label: PropTypes.string,
+ timeLag: PropTypes.number,
}),
- PropTypes.shape({
- metric_name: PropTypes.string,
- }),
- ])).isRequired,
+ ).isRequired,
+ rows: PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ PropTypes.shape({
+ label: PropTypes.string,
+ }),
+ PropTypes.shape({
+ metric_name: PropTypes.string,
+ }),
+ ]),
+ ).isRequired,
rowType: PropTypes.oneOf(['column', 'metric']).isRequired,
url: PropTypes.string,
};
@@ -92,11 +96,7 @@ class TimeTable extends React.PureComponent {
const column = row;
if (fullUrl) {
return (
-
+
{column.label}
);
@@ -149,7 +149,12 @@ class TimeTable extends React.PureComponent {
renderTooltip={({ index }) => (
{formatNumber(column.d3format, sparkData[index])}
-
{formatTime(column.dateFormat, moment.utc(entries[index].time).toDate())}
+
+ {formatTime(
+ column.dateFormat,
+ moment.utc(entries[index].time).toDate(),
+ )}
+
)}
/>
@@ -175,19 +180,22 @@ class TimeTable extends React.PureComponent {
} else if (column.comparisonType === 'perc') {
v = recent / v;
} else if (column.comparisonType === 'perc_change') {
- v = (recent / v) - 1;
+ v = recent / v - 1;
}
v = v || 0;
} else if (column.colType === 'contrib') {
// contribution to column total
- v = recent / Object.keys(reversedEntries[0])
- .map(k => k !== 'time' ? reversedEntries[0][k] : null)
- .reduce((a, b) => a + b);
+ v =
+ recent /
+ Object.keys(reversedEntries[0])
+ .map(k => (k !== 'time' ? reversedEntries[0][k] : null))
+ .reduce((a, b) => a + b);
} else if (column.colType === 'avg') {
// Average over the last {timeLag}
- v = reversedEntries
- .map((k, i) => i < column.timeLag ? k[valueField] : 0)
- .reduce((a, b) => a + b) / column.timeLag;
+ v =
+ reversedEntries
+ .map((k, i) => (i < column.timeLag ? k[valueField] : 0))
+ .reduce((a, b) => a + b) / column.timeLag;
}
const color = colorFromBounds(v, column.bounds);
@@ -197,16 +205,20 @@ class TimeTable extends React.PureComponent {
column={column.key}
key={column.key}
value={v}
- style={color && {
- boxShadow: `inset 0px -2.5px 0px 0px ${color}`,
- borderRight: '2px solid #fff',
- }}
+ style={
+ color && {
+ boxShadow: `inset 0px -2.5px 0px 0px ${color}`,
+ borderRight: '2px solid #fff',
+ }
+ }
>
- {errorMsg
- ? (
{errorMsg}
)
- : (
+ {errorMsg ? (
+
{errorMsg}
+ ) : (
+
-
)}
+
+ )}
);
}
@@ -221,9 +233,11 @@ class TimeTable extends React.PureComponent {
{leftCell}
- {columnConfigs.map(c => c.colType === 'spark'
- ? this.renderSparklineCell(valueField, c, entries)
- : this.renderValueCell(valueField, c, reversedEntries))}
+ {columnConfigs.map(c =>
+ c.colType === 'spark'
+ ? this.renderSparklineCell(valueField, c, entries)
+ : this.renderValueCell(valueField, c, reversedEntries),
+ )}
);
}
@@ -243,16 +257,16 @@ class TimeTable extends React.PureComponent {
.map(time => ({ ...data[time], time }));
const reversedEntries = entries.concat().reverse();
- const defaultSort = rowType === 'column' && columnConfigs.length ? {
- column: columnConfigs[0].key,
- direction: 'desc',
- } : false;
+ const defaultSort =
+ rowType === 'column' && columnConfigs.length
+ ? {
+ column: columnConfigs[0].key,
+ direction: 'desc',
+ }
+ : false;
return (
-
+
- {c.label} {c.tooltip && (
+ {c.label}{' '}
+ {c.tooltip && (
)}
- ))}
+
+ ))}
{rows.map(row => this.renderRow(row, entries, reversedEntries))}
diff --git a/superset/assets/src/visualizations/TimeTable/transformProps.js b/superset/assets/src/visualizations/TimeTable/transformProps.js
index c2285fbebbb..fbcf998713b 100644
--- a/superset/assets/src/visualizations/TimeTable/transformProps.js
+++ b/superset/assets/src/visualizations/TimeTable/transformProps.js
@@ -18,12 +18,7 @@
*/
export default function transformProps(chartProps) {
const { height, datasource, formData, queryData } = chartProps;
- const {
- columnCollection = [],
- groupby,
- metrics,
- url,
- } = formData;
+ const { columnCollection = [], groupby, metrics, url } = formData;
const { records, columns } = queryData.data;
const isGroupBy = groupby.length > 0;
@@ -33,24 +28,23 @@ export default function transformProps(chartProps) {
// each row in the table is a metric
let rows;
if (isGroupBy) {
- rows = columns.map(column => (typeof column === 'object')
- ? column
- : { label: column });
+ rows = columns.map(column =>
+ typeof column === 'object' ? column : { label: column },
+ );
} else {
- const metricMap = datasource.metrics
- .reduce((acc, current) => {
- const map = acc;
- map[current.metric_name] = current;
- return map;
- }, {});
+ const metricMap = datasource.metrics.reduce((acc, current) => {
+ const map = acc;
+ map[current.metric_name] = current;
+ return map;
+ }, {});
- rows = metrics.map(metric => (typeof metric === 'object')
- ? metric
- : metricMap[metric]);
+ rows = metrics.map(metric =>
+ typeof metric === 'object' ? metric : metricMap[metric],
+ );
}
// TODO: Better parse this from controls instead of mutative value here.
- columnCollection.forEach((column) => {
+ columnCollection.forEach(column => {
const c = column;
if (c.timeLag !== undefined && c.timeLag !== null && c.timeLag !== '') {
c.timeLag = parseInt(c.timeLag, 10);
diff --git a/superset/assets/src/visualizations/constants.js b/superset/assets/src/visualizations/constants.js
index bfa8921407f..539e2678bb7 100644
--- a/superset/assets/src/visualizations/constants.js
+++ b/superset/assets/src/visualizations/constants.js
@@ -25,4 +25,3 @@ export const TIME_CHOICES = [
'90 days ago',
'1 year ago',
];
-
diff --git a/superset/assets/src/visualizations/presets/MainPreset.js b/superset/assets/src/visualizations/presets/MainPreset.js
index 3ea5592339c..f543fe34bc6 100644
--- a/superset/assets/src/visualizations/presets/MainPreset.js
+++ b/superset/assets/src/visualizations/presets/MainPreset.js
@@ -17,7 +17,10 @@
* under the License.
*/
import { Preset } from '@superset-ui/core';
-import { BigNumberChartPlugin, BigNumberTotalChartPlugin } from '@superset-ui/legacy-preset-chart-big-number';
+import {
+ BigNumberChartPlugin,
+ BigNumberTotalChartPlugin,
+} from '@superset-ui/legacy-preset-chart-big-number';
import CalendarChartPlugin from '@superset-ui/legacy-plugin-chart-calendar';
import ChordChartPlugin from '@superset-ui/legacy-plugin-chart-chord';
import CountryMapChartPlugin from '@superset-ui/legacy-plugin-chart-country-map';
@@ -45,9 +48,19 @@ import WorldMapChartPlugin from '@superset-ui/legacy-plugin-chart-world-map';
// Make sure to import '@superset-ui/legacy-preset-chart-nvd3/lib'
// Not '@superset-ui/legacy-preset-chart-nvd3',
// which will point to '@superset-ui/legacy-preset-chart-nvd3/esm' by default
-import { AreaChartPlugin, BarChartPlugin, BubbleChartPlugin, BulletChartPlugin,
- CompareChartPlugin, DistBarChartPlugin, DualLineChartPlugin, LineChartPlugin,
- LineMultiChartPlugin, PieChartPlugin, TimePivotChartPlugin } from '@superset-ui/legacy-preset-chart-nvd3/lib';
+import {
+ AreaChartPlugin,
+ BarChartPlugin,
+ BubbleChartPlugin,
+ BulletChartPlugin,
+ CompareChartPlugin,
+ DistBarChartPlugin,
+ DualLineChartPlugin,
+ LineChartPlugin,
+ LineMultiChartPlugin,
+ PieChartPlugin,
+ TimePivotChartPlugin,
+} from '@superset-ui/legacy-preset-chart-nvd3/lib';
import { BoxPlotChartPlugin } from '@superset-ui/preset-chart-xy/esm/legacy';
import { DeckGLChartPreset } from '@superset-ui/legacy-preset-chart-deckgl';
@@ -58,9 +71,7 @@ export default class MainPreset extends Preset {
constructor() {
super({
name: 'Legacy charts',
- presets: [
- new DeckGLChartPreset(),
- ],
+ presets: [new DeckGLChartPreset()],
plugins: [
new AreaChartPlugin().configure({ key: 'area' }),
new BarChartPlugin().configure({ key: 'bar' }),
diff --git a/superset/assets/src/welcome/App.jsx b/superset/assets/src/welcome/App.jsx
index 55febfae5db..d66a1371390 100644
--- a/superset/assets/src/welcome/App.jsx
+++ b/superset/assets/src/welcome/App.jsx
@@ -40,10 +40,7 @@ const store = createStore(
messageToasts: messageToastReducer,
}),
{},
- compose(
- applyMiddleware(thunk),
- initEnhancer(false),
- ),
+ compose(applyMiddleware(thunk), initEnhancer(false)),
);
const App = () => (
diff --git a/superset/assets/src/welcome/DashboardTable.jsx b/superset/assets/src/welcome/DashboardTable.jsx
index d510730eb39..1e898a845ad 100644
--- a/superset/assets/src/welcome/DashboardTable.jsx
+++ b/superset/assets/src/welcome/DashboardTable.jsx
@@ -41,13 +41,16 @@ class DashboardTable extends React.PureComponent {
componentDidMount() {
SupersetClient.get({
- endpoint: '/dashboardasync/api/read?_oc_DashboardModelViewAsync=changed_on&_od_DashboardModelViewAsync=desc',
+ endpoint:
+ '/dashboardasync/api/read?_oc_DashboardModelViewAsync=changed_on&_od_DashboardModelViewAsync=desc',
})
.then(({ json }) => {
- this.setState({ dashboards: json.result });
+ this.setState({ dashboards: json.result });
})
.catch(() => {
- this.props.addDangerToast(t('An error occurred while fethching Dashboards'));
+ this.props.addDangerToast(
+ t('An error occurred while fethching Dashboards'),
+ );
});
}
@@ -79,7 +82,8 @@ class DashboardTable extends React.PureComponent {
{unsafe(o.modified)}
- ))}
+
+ ))}
);
}
diff --git a/superset/assets/src/welcome/Welcome.jsx b/superset/assets/src/welcome/Welcome.jsx
index db1a632fd5f..54e986242bd 100644
--- a/superset/assets/src/welcome/Welcome.jsx
+++ b/superset/assets/src/welcome/Welcome.jsx
@@ -46,7 +46,9 @@ export default class Welcome extends React.PureComponent {
- {t('Dashboards')}
+
+ {t('Dashboards')}
+
- {t('Recently Viewed')}
+
+ {t('Recently Viewed')}
+
@@ -74,7 +78,9 @@ export default class Welcome extends React.PureComponent {
- {t('Favorites')}
+
+ {t('Favorites')}
+
diff --git a/superset/assets/src/welcome/index.jsx b/superset/assets/src/welcome/index.jsx
index f2547e79a30..c257009e64f 100644
--- a/superset/assets/src/welcome/index.jsx
+++ b/superset/assets/src/welcome/index.jsx
@@ -20,7 +20,4 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
-ReactDOM.render(
- ,
- document.getElementById('app'),
-);
+ReactDOM.render( , document.getElementById('app'));
diff --git a/superset/assets/webpack.config.js b/superset/assets/webpack.config.js
index da032dea16f..10760c0aa16 100644
--- a/superset/assets/webpack.config.js
+++ b/superset/assets/webpack.config.js
@@ -19,7 +19,8 @@
const os = require('os');
const path = require('path');
const webpack = require('webpack');
-const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
+const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
+ .BundleAnalyzerPlugin;
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
@@ -77,10 +78,12 @@ if (isDevMode) {
plugins.push(new webpack.HotModuleReplacementPlugin());
} else {
// text loading (webpack 4+)
- plugins.push(new MiniCssExtractPlugin({
- filename: '[name].[chunkhash].entry.css',
- chunkFilename: '[name].[chunkhash].chunk.css',
- }));
+ plugins.push(
+ new MiniCssExtractPlugin({
+ filename: '[name].[chunkhash].entry.css',
+ chunkFilename: '[name].[chunkhash].chunk.css',
+ }),
+ );
plugins.push(new OptimizeCSSAssetsPlugin());
}
@@ -97,10 +100,7 @@ if (isDevMode) {
output.chunkFilename = '[name].[chunkhash].chunk.js';
}
-const PREAMBLE = [
- 'babel-polyfill',
- path.join(APP_DIR, '/src/preamble.js'),
-];
+const PREAMBLE = ['babel-polyfill', path.join(APP_DIR, '/src/preamble.js')];
function addPreamble(entry) {
return PREAMBLE.concat([path.join(APP_DIR, entry)]);
@@ -160,7 +160,7 @@ const config = {
{
loader: 'thread-loader',
options: {
- // there should be 1 cpu for the fork-ts-checker-webpack-plugin
+ // there should be 1 cpu for the fork-ts-checker-webpack-plugin
workers: os.cpus().length - 1,
},
},
@@ -190,17 +190,18 @@ const config = {
loader: 'babel-loader',
options: {
presets: ['airbnb', '@babel/preset-react', '@babel/preset-env'],
- plugins: ['lodash', '@babel/plugin-syntax-dynamic-import', 'react-hot-loader/babel'],
+ plugins: [
+ 'lodash',
+ '@babel/plugin-syntax-dynamic-import',
+ 'react-hot-loader/babel',
+ ],
},
},
],
},
{
test: /\.css$/,
- include: [
- APP_DIR,
- /superset[-]ui.+\/src/,
- ],
+ include: [APP_DIR, /superset[-]ui.+\/src/],
use: [
isDevMode ? 'style-loader' : MiniCssExtractPlugin.loader,
{