This is an automated email from the ASF dual-hosted git repository. graceguo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push: new 8bc30da [log] Add dashboard_id param to explore_json request (#9243) 8bc30da is described below commit 8bc30da6211df67ee8bec21e160ce587817ba85b Author: Grace Guo <grace....@airbnb.com> AuthorDate: Sun Mar 8 19:51:08 2020 -0700 [log] Add dashboard_id param to explore_json request (#9243) * [log] Add dashboard_id param to explore_json request * fix cypress test --- .../cypress/integration/dashboard/edit_mode.js | 3 +- .../cypress/integration/dashboard/filter.js | 6 ++-- .../cypress/integration/dashboard/load.js | 8 ++++-- .../cypress/integration/dashboard/save.js | 4 +-- .../cypress/integration/dashboard/tabs.js | 10 ++++--- .../cypress/integration/dashboard/url_params.js | 4 ++- superset-frontend/src/chart/Chart.jsx | 5 ++++ superset-frontend/src/chart/chartAction.js | 32 ++++++++++++++++++---- .../src/dashboard/actions/dashboardState.js | 16 +++++++++-- .../src/dashboard/components/Header.jsx | 15 ++++++++-- .../src/dashboard/components/SliceHeader.jsx | 3 ++ .../dashboard/components/SliceHeaderControls.jsx | 6 +++- .../dashboard/components/gridComponents/Chart.jsx | 10 ++++++- .../components/gridComponents/ChartHolder.jsx | 3 ++ .../dashboard/containers/DashboardComponent.jsx | 4 ++- 15 files changed, 101 insertions(+), 28 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.js b/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.js index c279cc5..913609c 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.js +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/edit_mode.js @@ -28,11 +28,12 @@ export default () => cy.get('#app').then(data => { const bootstrapData = JSON.parse(data[0].dataset.bootstrap); const dashboard = bootstrapData.dashboard_data; + const dashboardId = dashboard.id; 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}`; + const boxplotRequest = `/superset/explore_json/?form_data=${formData}&dashboard_id=${dashboardId}`; cy.route('POST', boxplotRequest).as('boxplotRequest'); }); diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/filter.js b/superset-frontend/cypress-base/cypress/integration/dashboard/filter.js index 6da7de2..c219796 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/filter.js +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/filter.js @@ -22,6 +22,7 @@ export default () => describe('dashboard filter', () => { let sliceIds = []; let filterId; + let dashboardId; beforeEach(() => { cy.server(); @@ -32,6 +33,7 @@ export default () => cy.get('#app').then(data => { const bootstrapData = JSON.parse(data[0].dataset.bootstrap); const dashboard = bootstrapData.dashboard_data; + dashboardId = dashboard.id; sliceIds = dashboard.slices.map(slice => slice.slice_id); filterId = dashboard.slices.find( slice => slice.form_data.viz_type === 'filter_box', @@ -43,7 +45,7 @@ export default () => const aliases = []; const formData = `{"slice_id":${filterId}}`; - const filterRoute = `/superset/explore_json/?form_data=${formData}`; + const filterRoute = `/superset/explore_json/?form_data=${formData}&dashboard_id=${dashboardId}`; cy.route('POST', filterRoute).as('fetchFilter'); cy.wait('@fetchFilter'); sliceIds @@ -54,7 +56,7 @@ export default () => cy.route( 'POST', - `/superset/explore_json/?form_data={"slice_id":${id}}`, + `/superset/explore_json/?form_data={"slice_id":${id}}&dashboard_id=${dashboardId}`, ).as(alias); }); diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/load.js b/superset-frontend/cypress-base/cypress/integration/dashboard/load.js index 6050cbf..5cb64fe 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/load.js +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/load.js @@ -31,14 +31,16 @@ export default () => cy.get('#app').then(data => { const bootstrapData = JSON.parse(data[0].dataset.bootstrap); + const dashboardId = bootstrapData.dashboard_data.id; 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, - ); + cy.route( + 'POST', + `/superset/explore_json/?form_data=${formData}&dashboard_id=${dashboardId}`, + ).as(alias); aliases.push(`@${alias}`); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/save.js b/superset-frontend/cypress-base/cypress/integration/dashboard/save.js index 263fd8a..03dec46 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/save.js +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/save.js @@ -60,11 +60,9 @@ export default () => }); 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}`; + const boxplotRequest = `/superset/explore_json/?form_data=${formData}&dashboard_id=${dashboardId}`; cy.route('POST', boxplotRequest).as('boxplotRequest'); cy.wait('@boxplotRequest'); cy.get('.grid-container .box_plot').should('be.exist'); diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/tabs.js b/superset-frontend/cypress-base/cypress/integration/dashboard/tabs.js index 4a86d3c..51dfa54 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/tabs.js +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/tabs.js @@ -24,6 +24,7 @@ export default () => let treemapId; let linechartId; let boxplotId; + let dashboardId; // cypress can not handle window.scrollTo // https://github.com/cypress-io/cypress/issues/2761 @@ -43,6 +44,7 @@ export default () => cy.get('#app').then(data => { const bootstrapData = JSON.parse(data[0].dataset.bootstrap); const dashboard = bootstrapData.dashboard_data; + dashboardId = dashboard.id; filterId = dashboard.slices.find( slice => slice.form_data.viz_type === 'filter_box', ).slice_id; @@ -61,7 +63,7 @@ export default () => }; const filterRequest = `/superset/explore_json/?form_data=${JSON.stringify( filterFormdata, - )}`; + )}&dashboard_id=${dashboardId}`; cy.route('POST', filterRequest).as('filterRequest'); const treemapFormdata = { @@ -69,7 +71,7 @@ export default () => }; const treemapRequest = `/superset/explore_json/?form_data=${JSON.stringify( treemapFormdata, - )}`; + )}&dashboard_id=${dashboardId}`; cy.route('POST', treemapRequest).as('treemapRequest'); const linechartFormdata = { @@ -77,7 +79,7 @@ export default () => }; const linechartRequest = `/superset/explore_json/?form_data=${JSON.stringify( linechartFormdata, - )}`; + )}&dashboard_id=${dashboardId}`; cy.route('POST', linechartRequest).as('linechartRequest'); const boxplotFormdata = { @@ -85,7 +87,7 @@ export default () => }; const boxplotRequest = `/superset/explore_json/?form_data=${JSON.stringify( boxplotFormdata, - )}`; + )}&dashboard_id=${dashboardId}`; cy.route('POST', boxplotRequest).as('boxplotRequest'); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/url_params.js b/superset-frontend/cypress-base/cypress/integration/dashboard/url_params.js index d7f983e..54b74a6 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/url_params.js +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/url_params.js @@ -22,6 +22,7 @@ export default () => describe('dashboard url params', () => { const urlParams = { param1: '123', param2: 'abc' }; let sliceIds = []; + let dashboardId; beforeEach(() => { cy.server(); @@ -32,6 +33,7 @@ export default () => cy.get('#app').then(data => { const bootstrapData = JSON.parse(data[0].dataset.bootstrap); const dashboard = bootstrapData.dashboard_data; + dashboardId = dashboard.id; sliceIds = dashboard.slices.map(slice => slice.slice_id); }); }); @@ -43,7 +45,7 @@ export default () => aliases.push(`@${alias}`); cy.route( 'POST', - `/superset/explore_json/?form_data={"slice_id":${id}}`, + `/superset/explore_json/?form_data={"slice_id":${id}}&dashboard_id=${dashboardId}`, ).as(alias); }); diff --git a/superset-frontend/src/chart/Chart.jsx b/superset-frontend/src/chart/Chart.jsx index 7a4679c..227b7af 100644 --- a/superset-frontend/src/chart/Chart.jsx +++ b/superset-frontend/src/chart/Chart.jsx @@ -34,6 +34,8 @@ const propTypes = { actions: PropTypes.object, chartId: PropTypes.number.isRequired, datasource: PropTypes.object.isRequired, + // current chart is included by dashboard + dashboardId: PropTypes.number, // original selected values for FilterBox viz // so that FilterBox can pre-populate selected values // only affect UI control @@ -71,6 +73,7 @@ const defaultProps = { initialValues: BLANK, setControlValue() {}, triggerRender: false, + dashboardId: null, }; class Chart extends React.PureComponent { @@ -101,6 +104,7 @@ class Chart extends React.PureComponent { false, this.props.timeout, this.props.chartId, + this.props.dashboardId, ); } else { // Create chart with POST request @@ -109,6 +113,7 @@ class Chart extends React.PureComponent { false, this.props.timeout, this.props.chartId, + this.props.dashboardId, ); } } diff --git a/superset-frontend/src/chart/chartAction.js b/superset-frontend/src/chart/chartAction.js index 657d0be..c7a125f 100644 --- a/superset-frontend/src/chart/chartAction.js +++ b/superset-frontend/src/chart/chartAction.js @@ -207,6 +207,7 @@ export function exploreJSON( timeout = 60, key, method, + dashboardId, ) { return dispatch => { const { url, payload } = getExploreUrlAndPayload({ @@ -215,6 +216,7 @@ export function exploreJSON( force, allowDomainSharding, method, + requestParams: dashboardId ? { dashboard_id: dashboardId } : {}, }); const logStart = Logger.getTimestamp(); const controller = new AbortController(); @@ -308,7 +310,13 @@ export function exploreJSON( } export const GET_SAVED_CHART = 'GET_SAVED_CHART'; -export function getSavedChart(formData, force = false, timeout = 60, key) { +export function getSavedChart( + formData, + force = false, + timeout = 60, + key, + dashboardId, +) { /* * Perform a GET request to `/explore_json`. * @@ -319,18 +327,24 @@ export function getSavedChart(formData, force = false, timeout = 60, key) { * GET /explore_json?{"chart_id":1,"extra_filters":"..."} * */ - return exploreJSON(formData, force, timeout, key, 'GET'); + return exploreJSON(formData, force, timeout, key, 'GET', dashboardId); } export const POST_CHART_FORM_DATA = 'POST_CHART_FORM_DATA'; -export function postChartFormData(formData, force = false, timeout = 60, key) { +export function postChartFormData( + formData, + force = false, + timeout = 60, + key, + dashboardId, +) { /* * Perform a POST request to `/explore_json`. * * This will post the form data to the endpoint, returning a new chart. * */ - return exploreJSON(formData, force, timeout, key, 'POST'); + return exploreJSON(formData, force, timeout, key, 'POST', dashboardId); } export function redirectSQLLab(formData) { @@ -359,7 +373,7 @@ export function redirectSQLLab(formData) { }; } -export function refreshChart(chartKey, force) { +export function refreshChart(chartKey, force, dashboardId) { return (dispatch, getState) => { const chart = (getState().charts || {})[chartKey]; const timeout = getState().dashboardInfo.common.conf @@ -372,7 +386,13 @@ export function refreshChart(chartKey, force) { return; } dispatch( - postChartFormData(chart.latestQueryFormData, force, timeout, chart.id), + postChartFormData( + chart.latestQueryFormData, + force, + timeout, + chart.id, + dashboardId, + ), ); }; } diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js b/superset-frontend/src/dashboard/actions/dashboardState.js index 20bb35d..33737f8 100644 --- a/superset-frontend/src/dashboard/actions/dashboardState.js +++ b/superset-frontend/src/dashboard/actions/dashboardState.js @@ -218,10 +218,17 @@ export function saveDashboardRequest(data, id, saveType) { }; } -export function fetchCharts(chartList = [], force = false, interval = 0) { +export function fetchCharts( + chartList = [], + force = false, + interval = 0, + dashboardId, +) { return (dispatch, getState) => { if (!interval) { - chartList.forEach(chartKey => dispatch(refreshChart(chartKey, force))); + chartList.forEach(chartKey => + dispatch(refreshChart(chartKey, force, dashboardId)), + ); return; } @@ -237,7 +244,10 @@ export function fetchCharts(chartList = [], force = false, interval = 0) { ? refreshTime / (chartList.length - 1) : 0; chartList.forEach((chartKey, i) => { - setTimeout(() => dispatch(refreshChart(chartKey, force)), delay * i); + setTimeout( + () => dispatch(refreshChart(chartKey, force, dashboardId)), + delay * i, + ); }); }; } diff --git a/superset-frontend/src/dashboard/components/Header.jsx b/superset-frontend/src/dashboard/components/Header.jsx index 4c8d014..c889d06 100644 --- a/superset-frontend/src/dashboard/components/Header.jsx +++ b/superset-frontend/src/dashboard/components/Header.jsx @@ -194,7 +194,13 @@ class Header extends React.PureComponent { interval: 0, chartCount: chartList.length, }); - return this.props.fetchCharts(chartList, true); + + return this.props.fetchCharts( + chartList, + true, + 0, + this.props.dashboardInfo.id, + ); } return false; } @@ -212,7 +218,12 @@ class Header extends React.PureComponent { interval, chartCount: affectedCharts.length, }); - return fetchCharts(affectedCharts, true, interval * 0.2); + return fetchCharts( + affectedCharts, + true, + interval * 0.2, + dashboardInfo.id, + ); }; this.refreshTimer = setPeriodicRunner({ diff --git a/superset-frontend/src/dashboard/components/SliceHeader.jsx b/superset-frontend/src/dashboard/components/SliceHeader.jsx index 3d36a51..a1fb9f3 100644 --- a/superset-frontend/src/dashboard/components/SliceHeader.jsx +++ b/superset-frontend/src/dashboard/components/SliceHeader.jsx @@ -44,6 +44,7 @@ const propTypes = { supersetCanCSV: PropTypes.bool, sliceCanEdit: PropTypes.bool, componentId: PropTypes.string.isRequired, + dashboardId: PropTypes.number.isRequired, filters: PropTypes.object.isRequired, addDangerToast: PropTypes.func.isRequired, }; @@ -94,6 +95,7 @@ class SliceHeader extends React.PureComponent { annotationQuery, annotationError, componentId, + dashboardId, addDangerToast, } = this.props; @@ -145,6 +147,7 @@ class SliceHeader extends React.PureComponent { supersetCanCSV={supersetCanCSV} sliceCanEdit={sliceCanEdit} componentId={componentId} + dashboardId={dashboardId} addDangerToast={addDangerToast} /> )} diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls.jsx b/superset-frontend/src/dashboard/components/SliceHeaderControls.jsx index 779609d..6bd5061 100644 --- a/superset-frontend/src/dashboard/components/SliceHeaderControls.jsx +++ b/superset-frontend/src/dashboard/components/SliceHeaderControls.jsx @@ -28,6 +28,7 @@ import { getActiveFilters } from '../util/activeDashboardFilters'; const propTypes = { slice: PropTypes.object.isRequired, componentId: PropTypes.string.isRequired, + dashboardId: PropTypes.number.isRequired, addDangerToast: PropTypes.func.isRequired, isCached: PropTypes.bool, isExpanded: PropTypes.bool, @@ -91,7 +92,10 @@ class SliceHeaderControls extends React.PureComponent { refreshChart() { if (this.props.updatedDttm) { - this.props.forceRefresh(this.props.slice.slice_id); + this.props.forceRefresh( + this.props.slice.slice_id, + this.props.dashboardId, + ); } } diff --git a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx index 02932ca..b399528 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx @@ -36,6 +36,7 @@ import getFilterValuesByFilterId from '../../util/getFilterValuesByFilterId'; const propTypes = { id: PropTypes.number.isRequired, componentId: PropTypes.string.isRequired, + dashboardId: PropTypes.number.isRequired, width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, updateSliceName: PropTypes.func.isRequired, @@ -205,13 +206,18 @@ class Chart extends React.Component { slice_id: this.props.slice.slice_id, is_cached: this.props.isCached, }); - return this.props.refreshChart(this.props.chart.id, true); + return this.props.refreshChart( + this.props.chart.id, + true, + this.props.dashboardId, + ); } render() { const { id, componentId, + dashboardId, chart, slice, datasource, @@ -269,6 +275,7 @@ class Chart extends React.Component { supersetCanCSV={supersetCanCSV} sliceCanEdit={sliceCanEdit} componentId={componentId} + dashboardId={dashboardId} filters={filters} addDangerToast={addDangerToast} /> @@ -306,6 +313,7 @@ class Chart extends React.Component { chartId={id} chartStatus={chart.chartStatus} datasource={datasource} + dashboardId={dashboardId} initialValues={initialValues} formData={formData} queryResponse={chart.queryResponse} diff --git a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx index a3cf5c1..85d5fdf 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx @@ -42,6 +42,7 @@ const CHART_MARGIN = 32; const propTypes = { id: PropTypes.string.isRequired, parentId: PropTypes.string.isRequired, + dashboardId: PropTypes.number.isRequired, component: componentShape.isRequired, parentComponent: componentShape.isRequired, index: PropTypes.number.isRequired, @@ -175,6 +176,7 @@ class ChartHolder extends React.Component { handleComponentDrop, editMode, isComponentVisible, + dashboardId, } = this.props; // inherit the size of parent columns @@ -228,6 +230,7 @@ class ChartHolder extends React.Component { <Chart componentId={component.id} id={component.meta.chartId} + dashboardId={dashboardId} width={Math.floor( widthMultiple * columnWidth + (widthMultiple - 1) * GRID_GUTTER_SIZE - diff --git a/superset-frontend/src/dashboard/containers/DashboardComponent.jsx b/superset-frontend/src/dashboard/containers/DashboardComponent.jsx index d1e2b8d..dd2c188 100644 --- a/superset-frontend/src/dashboard/containers/DashboardComponent.jsx +++ b/superset-frontend/src/dashboard/containers/DashboardComponent.jsx @@ -46,6 +46,7 @@ const propTypes = { logEvent: PropTypes.func.isRequired, directPathToChild: PropTypes.arrayOf(PropTypes.string), directPathLastUpdated: PropTypes.number, + dashboardId: PropTypes.number.isRequired, }; const defaultProps = { @@ -55,7 +56,7 @@ const defaultProps = { }; function mapStateToProps( - { dashboardLayout: undoableLayout, dashboardState }, + { dashboardLayout: undoableLayout, dashboardState, dashboardInfo }, ownProps, ) { const dashboardLayout = undoableLayout.present; @@ -68,6 +69,7 @@ function mapStateToProps( filters: getActiveFilters(), directPathToChild: dashboardState.directPathToChild, directPathLastUpdated: dashboardState.directPathLastUpdated, + dashboardId: dashboardInfo.id, filterFieldOnFocus: dashboardState.focusedFilterField.length === 0 ? {}