This is an automated email from the ASF dual-hosted git repository. kgabryje pushed a commit to branch what-if in repository https://gitbox.apache.org/repos/asf/superset.git
commit 3df0521b2d5874d2e20e4b1706a945a7106d533c Author: Kamil Gabryjelski <[email protected]> AuthorDate: Tue Dec 16 21:29:37 2025 +0100 BETTER CHART LOADING --- superset-frontend/src/components/Chart/Chart.tsx | 60 ++++++++++++++++++++-- .../src/components/Chart/ChartRenderer.jsx | 10 +++- .../components/gridComponents/Chart/Chart.jsx | 9 +++- 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/superset-frontend/src/components/Chart/Chart.tsx b/superset-frontend/src/components/Chart/Chart.tsx index 12522b5314..0be79b6ef1 100644 --- a/superset-frontend/src/components/Chart/Chart.tsx +++ b/superset-frontend/src/components/Chart/Chart.tsx @@ -170,6 +170,20 @@ const MessageSpan = styled.span` color: ${({ theme }) => theme.colorText}; `; +const LoadingOverlay = styled.div` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: ${({ theme }) => theme.colorBgMask}; + z-index: 10; +`; + class Chart extends PureComponent<ChartProps, {}> { static defaultProps = defaultProps; @@ -314,6 +328,23 @@ class Chart extends PureComponent<ChartProps, {}> { ); } + renderLoadingOverlay(databaseName: string | undefined) { + const message = databaseName + ? t('Waiting on %s', databaseName) + : t('Waiting on database...'); + + return ( + <LoadingOverlay> + <Loading + position="inline-centered" + size={this.props.dashboardId ? 's' : 'm'} + muted={!!this.props.dashboardId} + /> + <MessageSpan>{message}</MessageSpan> + </LoadingOverlay> + ); + } + render() { const { height, @@ -373,6 +404,30 @@ class Chart extends PureComponent<ChartProps, {}> { ); } + const hasExistingData = + ensureIsArray(queriesResponse).length > 0 && + queriesResponse?.some(response => response?.data); + const isFirstLoad = isLoading && !hasExistingData; + + if (isFirstLoad) { + return ( + <ErrorBoundary + onError={this.handleRenderContainerFailure} + showMessage={false} + > + <Styles + data-ui-anchor="chart" + className="chart-container" + data-test="chart-container" + height={height} + width={width} + > + {this.renderSpinner(databaseName)} + </Styles> + </ErrorBoundary> + ); + } + return ( <ErrorBoundary onError={this.handleRenderContainerFailure} @@ -385,9 +440,8 @@ class Chart extends PureComponent<ChartProps, {}> { height={height} width={width} > - {isLoading - ? this.renderSpinner(databaseName) - : this.renderChartContainer()} + {this.renderChartContainer()} + {isLoading && this.renderLoadingOverlay(databaseName)} </Styles> </ErrorBoundary> ); diff --git a/superset-frontend/src/components/Chart/ChartRenderer.jsx b/superset-frontend/src/components/Chart/ChartRenderer.jsx index 61cf48fdb5..ce02be6f8a 100644 --- a/superset-frontend/src/components/Chart/ChartRenderer.jsx +++ b/superset-frontend/src/components/Chart/ChartRenderer.jsx @@ -279,8 +279,14 @@ class ChartRenderer extends Component { render() { const { chartAlert, chartStatus, chartId, emitCrossFilters } = this.props; - // Skip chart rendering - if (chartStatus === 'loading' || !!chartAlert || chartStatus === null) { + // Skip chart rendering for errors + if (chartAlert) { + return null; + } + + const hasData = + this.mutableQueriesResponse && this.mutableQueriesResponse.length > 0; + if (!hasData && (chartStatus === 'loading' || chartStatus === null)) { return null; } diff --git a/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.jsx b/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.jsx index 931ea28d40..9cb458718e 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.jsx @@ -21,6 +21,7 @@ import { useCallback, useEffect, useRef, useMemo, useState, memo } from 'react'; import PropTypes from 'prop-types'; import { t, logging } from '@superset-ui/core'; import { styled } from '@apache-superset/core/ui'; +import { Loading } from '@superset-ui/core/components'; import { debounce } from 'lodash'; import { useHistory } from 'react-router-dom'; import { bindActionCreators } from 'redux'; @@ -103,6 +104,10 @@ const ChartOverlay = styled.div` top: 0; left: 0; z-index: 5; + background-color: ${({ theme }) => theme.colorBgMask}; + display: flex; + align-items: center; + justify-content: center; `; const SliceContainer = styled.div` @@ -684,7 +689,9 @@ const Chart = props => { width, height: getChartHeight(), }} - /> + > + <Loading size="s" muted /> + </ChartOverlay> )} <ChartContainer
