mirror of https://github.com/apache/superset.git
[Explore] applying refresh chart overlay when chart is stale (#4486)
* adding refresh chart overlay when chart is out of sync with control panel * fading the visualization when stale * addressing comments from team on layout of UI
This commit is contained in:
parent
849a2cecee
commit
764a92cd10
|
@ -9,6 +9,7 @@ import ChartBody from './ChartBody';
|
||||||
import Loading from '../components/Loading';
|
import Loading from '../components/Loading';
|
||||||
import { Logger, LOG_ACTIONS_RENDER_EVENT } from '../logger';
|
import { Logger, LOG_ACTIONS_RENDER_EVENT } from '../logger';
|
||||||
import StackTraceMessage from '../components/StackTraceMessage';
|
import StackTraceMessage from '../components/StackTraceMessage';
|
||||||
|
import RefreshChartOverlay from '../components/RefreshChartOverlay';
|
||||||
import visMap from '../../visualizations/main';
|
import visMap from '../../visualizations/main';
|
||||||
import sandboxedEval from '../modules/sandbox';
|
import sandboxedEval from '../modules/sandbox';
|
||||||
import './chart.css';
|
import './chart.css';
|
||||||
|
@ -36,11 +37,15 @@ const propTypes = {
|
||||||
queryResponse: PropTypes.object,
|
queryResponse: PropTypes.object,
|
||||||
lastRendered: PropTypes.number,
|
lastRendered: PropTypes.number,
|
||||||
triggerQuery: PropTypes.bool,
|
triggerQuery: PropTypes.bool,
|
||||||
|
refreshOverlayVisible: PropTypes.bool,
|
||||||
|
errorMessage: PropTypes.node,
|
||||||
// dashboard callbacks
|
// dashboard callbacks
|
||||||
addFilter: PropTypes.func,
|
addFilter: PropTypes.func,
|
||||||
getFilters: PropTypes.func,
|
getFilters: PropTypes.func,
|
||||||
clearFilter: PropTypes.func,
|
clearFilter: PropTypes.func,
|
||||||
removeFilter: PropTypes.func,
|
removeFilter: PropTypes.func,
|
||||||
|
onQuery: PropTypes.func,
|
||||||
|
onDismissRefreshOverlay: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
|
@ -214,12 +219,24 @@ class Chart extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{!isLoading &&
|
||||||
|
!this.props.chartAlert &&
|
||||||
|
this.props.refreshOverlayVisible &&
|
||||||
|
!this.props.errorMessage &&
|
||||||
|
<RefreshChartOverlay
|
||||||
|
height={this.height()}
|
||||||
|
width={this.width()}
|
||||||
|
onQuery={this.props.onQuery}
|
||||||
|
onDismiss={this.props.onDismissRefreshOverlay}
|
||||||
|
/>
|
||||||
|
}
|
||||||
{!isLoading && !this.props.chartAlert &&
|
{!isLoading && !this.props.chartAlert &&
|
||||||
<ChartBody
|
<ChartBody
|
||||||
containerId={this.containerId}
|
containerId={this.containerId}
|
||||||
vizType={this.props.vizType}
|
vizType={this.props.vizType}
|
||||||
height={this.height}
|
height={this.height}
|
||||||
width={this.width}
|
width={this.width}
|
||||||
|
faded={this.props.refreshOverlayVisible && !this.props.errorMessage}
|
||||||
ref={(inner) => {
|
ref={(inner) => {
|
||||||
this.container = inner;
|
this.container = inner;
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -7,6 +7,7 @@ const propTypes = {
|
||||||
vizType: PropTypes.string.isRequired,
|
vizType: PropTypes.string.isRequired,
|
||||||
height: PropTypes.func.isRequired,
|
height: PropTypes.func.isRequired,
|
||||||
width: PropTypes.func.isRequired,
|
width: PropTypes.func.isRequired,
|
||||||
|
faded: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChartBody extends React.PureComponent {
|
class ChartBody extends React.PureComponent {
|
||||||
|
@ -42,7 +43,7 @@ class ChartBody extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id={this.props.containerId}
|
id={this.props.containerId}
|
||||||
className={`slice_container ${this.props.vizType}`}
|
className={`slice_container ${this.props.vizType}${this.props.faded ? ' faded' : ''}`}
|
||||||
ref={(el) => { this.el = el; }}
|
ref={(el) => { this.el = el; }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 (
|
||||||
|
<div
|
||||||
|
style={{ height: this.props.height, width: this.props.width }}
|
||||||
|
className="explore-chart-overlay"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
className="refresh-overlay-btn"
|
||||||
|
onClick={this.props.onQuery}
|
||||||
|
bsStyle="primary"
|
||||||
|
>
|
||||||
|
{t('Run Query')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className="dismiss-overlay-btn"
|
||||||
|
onClick={this.props.onDismiss}
|
||||||
|
>
|
||||||
|
{t('Dismiss')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshChartOverlay.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default RefreshChartOverlay;
|
|
@ -10,6 +10,8 @@ import ExploreChartHeader from './ExploreChartHeader';
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
actions: PropTypes.object.isRequired,
|
actions: PropTypes.object.isRequired,
|
||||||
addHistory: PropTypes.func,
|
addHistory: PropTypes.func,
|
||||||
|
onQuery: PropTypes.func,
|
||||||
|
onDismissRefreshOverlay: PropTypes.func,
|
||||||
can_overwrite: PropTypes.bool.isRequired,
|
can_overwrite: PropTypes.bool.isRequired,
|
||||||
can_download: PropTypes.bool.isRequired,
|
can_download: PropTypes.bool.isRequired,
|
||||||
datasource: PropTypes.object,
|
datasource: PropTypes.object,
|
||||||
|
@ -24,7 +26,9 @@ const propTypes = {
|
||||||
form_data: PropTypes.object,
|
form_data: PropTypes.object,
|
||||||
standalone: PropTypes.bool,
|
standalone: PropTypes.bool,
|
||||||
timeout: PropTypes.number,
|
timeout: PropTypes.number,
|
||||||
|
refreshOverlayVisible: PropTypes.bool,
|
||||||
chart: PropTypes.shape(chartPropType),
|
chart: PropTypes.shape(chartPropType),
|
||||||
|
errorMessage: PropTypes.node,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExploreChartPanel extends React.PureComponent {
|
class ExploreChartPanel extends React.PureComponent {
|
||||||
|
@ -45,6 +49,10 @@ class ExploreChartPanel extends React.PureComponent {
|
||||||
setControlValue={this.props.actions.setControlValue}
|
setControlValue={this.props.actions.setControlValue}
|
||||||
timeout={this.props.timeout}
|
timeout={this.props.timeout}
|
||||||
vizType={this.props.vizType}
|
vizType={this.props.vizType}
|
||||||
|
refreshOverlayVisible={this.props.refreshOverlayVisible}
|
||||||
|
errorMessage={this.props.errorMessage}
|
||||||
|
onQuery={this.props.onQuery}
|
||||||
|
onDismissRefreshOverlay={this.props.onDismissRefreshOverlay}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ class ExploreViewContainer extends React.Component {
|
||||||
width: this.getWidth(),
|
width: this.getWidth(),
|
||||||
showModal: false,
|
showModal: false,
|
||||||
chartIsStale: false,
|
chartIsStale: false,
|
||||||
|
refreshOverlayVisible: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addHistory = this.addHistory.bind(this);
|
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);
|
this.props.actions.renderTriggered(new Date().getTime(), this.props.chart.chartKey);
|
||||||
}
|
}
|
||||||
if (this.hasQueryControlChanged(changedControlKeys, np.controls)) {
|
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.removeControlPanelAlert();
|
||||||
this.props.actions.triggerQuery(true, this.props.chart.chartKey);
|
this.props.actions.triggerQuery(true, this.props.chart.chartKey);
|
||||||
|
|
||||||
this.setState({ chartIsStale: false });
|
this.setState({ chartIsStale: false, refreshOverlayVisible: false });
|
||||||
this.addHistory({});
|
this.addHistory({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDismissRefreshOverlay() {
|
||||||
|
this.setState({ refreshOverlayVisible: false });
|
||||||
|
}
|
||||||
|
|
||||||
onStop() {
|
onStop() {
|
||||||
return this.props.chart.queryRequest.abort();
|
return this.props.chart.queryRequest.abort();
|
||||||
}
|
}
|
||||||
|
@ -227,7 +232,11 @@ class ExploreViewContainer extends React.Component {
|
||||||
width={this.state.width}
|
width={this.state.width}
|
||||||
height={this.state.height}
|
height={this.state.height}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
|
errorMessage={this.renderErrorMessage()}
|
||||||
|
refreshOverlayVisible={this.state.refreshOverlayVisible}
|
||||||
addHistory={this.addHistory}
|
addHistory={this.addHistory}
|
||||||
|
onQuery={this.onQuery.bind(this)}
|
||||||
|
onDismissRefreshOverlay={this.onDismissRefreshOverlay.bind(this)}
|
||||||
/>);
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,10 @@ div.widget .chart-header a {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slice_container.faded {
|
||||||
|
opacity: .2;
|
||||||
|
}
|
||||||
|
|
||||||
div.widget {
|
div.widget {
|
||||||
.slice_container {
|
.slice_container {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -424,3 +428,24 @@ g.annotation-container {
|
||||||
content: "\f0dd";
|
content: "\f0dd";
|
||||||
color: @brand-primary;
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue