diff --git a/superset/assets/javascripts/chart/Chart.jsx b/superset/assets/javascripts/chart/Chart.jsx index 0e064278f5..54736e53cb 100644 --- a/superset/assets/javascripts/chart/Chart.jsx +++ b/superset/assets/javascripts/chart/Chart.jsx @@ -9,6 +9,7 @@ import ChartBody from './ChartBody'; import Loading from '../components/Loading'; import { Logger, LOG_ACTIONS_RENDER_EVENT } from '../logger'; import StackTraceMessage from '../components/StackTraceMessage'; +import RefreshChartOverlay from '../components/RefreshChartOverlay'; import visMap from '../../visualizations/main'; import sandboxedEval from '../modules/sandbox'; import './chart.css'; @@ -36,11 +37,15 @@ const propTypes = { queryResponse: PropTypes.object, lastRendered: PropTypes.number, triggerQuery: PropTypes.bool, + refreshOverlayVisible: PropTypes.bool, + errorMessage: PropTypes.node, // dashboard callbacks addFilter: PropTypes.func, getFilters: PropTypes.func, clearFilter: PropTypes.func, removeFilter: PropTypes.func, + onQuery: PropTypes.func, + onDismissRefreshOverlay: PropTypes.func, }; const defaultProps = { @@ -214,12 +219,24 @@ class Chart extends React.PureComponent { /> } + {!isLoading && + !this.props.chartAlert && + this.props.refreshOverlayVisible && + !this.props.errorMessage && + + } {!isLoading && !this.props.chartAlert && { this.container = inner; }} diff --git a/superset/assets/javascripts/chart/ChartBody.jsx b/superset/assets/javascripts/chart/ChartBody.jsx index 89352f58b3..b459f44182 100644 --- a/superset/assets/javascripts/chart/ChartBody.jsx +++ b/superset/assets/javascripts/chart/ChartBody.jsx @@ -7,6 +7,7 @@ const propTypes = { vizType: PropTypes.string.isRequired, height: PropTypes.func.isRequired, width: PropTypes.func.isRequired, + faded: PropTypes.bool, }; class ChartBody extends React.PureComponent { @@ -42,7 +43,7 @@ class ChartBody extends React.PureComponent { return (
{ this.el = el; }} /> ); diff --git a/superset/assets/javascripts/components/RefreshChartOverlay.jsx b/superset/assets/javascripts/components/RefreshChartOverlay.jsx new file mode 100644 index 0000000000..9e3fced23a --- /dev/null +++ b/superset/assets/javascripts/components/RefreshChartOverlay.jsx @@ -0,0 +1,42 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Button from '../components/Button'; +import { t } from '../locales'; + +const propTypes = { + height: PropTypes.number.isRequired, + width: PropTypes.number.isRequired, + onQuery: PropTypes.func, + onDismiss: PropTypes.func, +}; + +class RefreshChartOverlay extends React.PureComponent { + render() { + return ( +
+
+ + +
+
+ ); + } +} + +RefreshChartOverlay.propTypes = propTypes; + +export default RefreshChartOverlay; diff --git a/superset/assets/javascripts/explore/components/ExploreChartPanel.jsx b/superset/assets/javascripts/explore/components/ExploreChartPanel.jsx index 5e4926ed26..bfb24fff7f 100644 --- a/superset/assets/javascripts/explore/components/ExploreChartPanel.jsx +++ b/superset/assets/javascripts/explore/components/ExploreChartPanel.jsx @@ -10,6 +10,8 @@ import ExploreChartHeader from './ExploreChartHeader'; const propTypes = { actions: PropTypes.object.isRequired, addHistory: PropTypes.func, + onQuery: PropTypes.func, + onDismissRefreshOverlay: PropTypes.func, can_overwrite: PropTypes.bool.isRequired, can_download: PropTypes.bool.isRequired, datasource: PropTypes.object, @@ -24,7 +26,9 @@ const propTypes = { form_data: PropTypes.object, standalone: PropTypes.bool, timeout: PropTypes.number, + refreshOverlayVisible: PropTypes.bool, chart: PropTypes.shape(chartPropType), + errorMessage: PropTypes.node, }; class ExploreChartPanel extends React.PureComponent { @@ -45,6 +49,10 @@ class ExploreChartPanel extends React.PureComponent { setControlValue={this.props.actions.setControlValue} timeout={this.props.timeout} vizType={this.props.vizType} + refreshOverlayVisible={this.props.refreshOverlayVisible} + errorMessage={this.props.errorMessage} + onQuery={this.props.onQuery} + onDismissRefreshOverlay={this.props.onDismissRefreshOverlay} /> ); } diff --git a/superset/assets/javascripts/explore/components/ExploreViewContainer.jsx b/superset/assets/javascripts/explore/components/ExploreViewContainer.jsx index c4b9fe525f..e1b7acbee0 100644 --- a/superset/assets/javascripts/explore/components/ExploreViewContainer.jsx +++ b/superset/assets/javascripts/explore/components/ExploreViewContainer.jsx @@ -50,6 +50,7 @@ class ExploreViewContainer extends React.Component { width: this.getWidth(), showModal: false, chartIsStale: false, + refreshOverlayVisible: false, }; this.addHistory = this.addHistory.bind(this); @@ -84,7 +85,7 @@ class ExploreViewContainer extends React.Component { this.props.actions.renderTriggered(new Date().getTime(), this.props.chart.chartKey); } if (this.hasQueryControlChanged(changedControlKeys, np.controls)) { - this.setState({ chartIsStale: true }); + this.setState({ chartIsStale: true, refreshOverlayVisible: true }); } } @@ -108,10 +109,14 @@ class ExploreViewContainer extends React.Component { this.props.actions.removeControlPanelAlert(); this.props.actions.triggerQuery(true, this.props.chart.chartKey); - this.setState({ chartIsStale: false }); + this.setState({ chartIsStale: false, refreshOverlayVisible: false }); this.addHistory({}); } + onDismissRefreshOverlay() { + this.setState({ refreshOverlayVisible: false }); + } + onStop() { return this.props.chart.queryRequest.abort(); } @@ -227,7 +232,11 @@ class ExploreViewContainer extends React.Component { width={this.state.width} height={this.state.height} {...this.props} + errorMessage={this.renderErrorMessage()} + refreshOverlayVisible={this.state.refreshOverlayVisible} addHistory={this.addHistory} + onQuery={this.onQuery.bind(this)} + onDismissRefreshOverlay={this.onDismissRefreshOverlay.bind(this)} />); } diff --git a/superset/assets/stylesheets/superset.less b/superset/assets/stylesheets/superset.less index 701375010a..4ac5ba8ae2 100644 --- a/superset/assets/stylesheets/superset.less +++ b/superset/assets/stylesheets/superset.less @@ -185,6 +185,10 @@ div.widget .chart-header a { display: none; } +.slice_container.faded { + opacity: .2; +} + div.widget { .slice_container { overflow: hidden; @@ -424,3 +428,24 @@ g.annotation-container { content: "\f0dd"; color: @brand-primary; } + +.explore-chart-overlay { + position: absolute; + z-index: 100; + display: flex; + align-items: center; + justify-content: center; + text-align: center; +} + +.refresh-overlay-btn { + font-weight: bold; + margin-right: 10px; +} + +.dismiss-overlay-btn { + font-weight: bold; + background: white; + color: @brand-primary; + border-color: @brand-primary; +}