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 { 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 &&
|
||||
<RefreshChartOverlay
|
||||
height={this.height()}
|
||||
width={this.width()}
|
||||
onQuery={this.props.onQuery}
|
||||
onDismiss={this.props.onDismissRefreshOverlay}
|
||||
/>
|
||||
}
|
||||
{!isLoading && !this.props.chartAlert &&
|
||||
<ChartBody
|
||||
containerId={this.containerId}
|
||||
vizType={this.props.vizType}
|
||||
height={this.height}
|
||||
width={this.width}
|
||||
faded={this.props.refreshOverlayVisible && !this.props.errorMessage}
|
||||
ref={(inner) => {
|
||||
this.container = inner;
|
||||
}}
|
||||
|
|
|
@ -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 (
|
||||
<div
|
||||
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; }}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -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 = {
|
||||
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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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)}
|
||||
/>);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue