Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(Dashboard): Remove unnecessary loading #29632

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4ca8e07
Unblock dashboard
geido Jul 18, 2024
605e435
Remove unnecessary loading
geido Jul 18, 2024
e8e944e
Fix loading logic - wip
geido Jul 23, 2024
bebee18
Fix loading logic - wip
geido Jul 23, 2024
469e289
Lazy load logo
geido Jul 23, 2024
6c8898e
Unblock native filters
geido Aug 1, 2024
10a5a66
Merge branch 'master' of https://github.com/apache/superset into geid…
geido Aug 5, 2024
10b8e24
Update tests
geido Aug 5, 2024
3955285
Merge branch 'master' of https://github.com/apache/superset into geid…
geido Aug 6, 2024
a9c2bb6
Add uuid
geido Aug 6, 2024
e100e5e
Avoid excessive updates
geido Aug 7, 2024
ccbfbac
Merge branch 'master' of https://github.com/apache/superset into geid…
geido Aug 7, 2024
1663b36
Control excessive requests
geido Aug 7, 2024
8490917
I want to be pretty
geido Aug 7, 2024
431c5a2
Fix type
geido Aug 8, 2024
df5e80a
Merge branch 'master' of https://github.com/apache/superset into geid…
geido Aug 19, 2024
a21b2be
Control triggerQuery
geido Aug 19, 2024
781aa9f
Move hydration flags to state
geido Aug 22, 2024
055868b
Update tests
geido Aug 22, 2024
07d7cd7
Lint
geido Aug 22, 2024
918ffc9
Fix EOF
geido Aug 22, 2024
1c177bc
Merge branch 'master' of https://github.com/apache/superset into geid…
geido Sep 2, 2024
da17840
Merge branch 'master' of https://github.com/apache/superset into geid…
geido Sep 24, 2024
c52360d
feat(DashboardInfo): Decouple dashboard info from full hydration
geido Sep 24, 2024
ec69380
chore(Skeleton): Unblock Header
geido Sep 26, 2024
198a7d7
fix(Skeleton): Fix missing slice
geido Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions superset-frontend/spec/fixtures/mockDashboardState.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export default {
css: '',
focusedFilterField: null,
refreshFrequency: 0,
dataMaskHydrated: true,
dashboardHydrated: true,
};

export const overwriteConfirmMetadata = {
Expand Down
3 changes: 2 additions & 1 deletion superset-frontend/src/components/Chart/chartReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const chart: ChartState = {
sliceFormData: null,
queryController: null,
queriesResponse: null,
triggerQuery: true,
triggerQuery: false,
lastRendered: 0,
};

Expand All @@ -55,6 +55,7 @@ export default function chartReducer(
return {
...chart,
...action.chart,
triggerQuery: true,
};
},
[actions.CHART_UPDATE_SUCCEEDED](state) {
Expand Down
5 changes: 5 additions & 0 deletions superset-frontend/src/dashboard/actions/dashboardState.js
Original file line number Diff line number Diff line change
Expand Up @@ -731,3 +731,8 @@ export const updateDashboardLabelsColor = () => async (dispatch, getState) => {
console.error('Failed to update dashboard color settings:', error);
}
};

export const ON_LEAVE_DASHBOARD = 'ON_LEAVE_DASHBOARD';
export function onLeaveDashboard() {
return { type: ON_LEAVE_DASHBOARD };
}
23 changes: 20 additions & 3 deletions superset-frontend/src/dashboard/actions/hydrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,26 @@ import updateComponentParentsList from '../util/updateComponentParentsList';
import { FilterBarOrientation } from '../types';

export const HYDRATE_DASHBOARD = 'HYDRATE_DASHBOARD';
export const HYDRATE_DASHBOARD_DATAMASK = 'HYDRATE_DASHBOARD_DATAMASK';
export const HYDRATE_DASHBOARD_ACTIVETABS = 'HYDRATE_DASHBOARD_ACTIVETABS';

export const hydrateDashboardDataMask = (dataMask, dashboardInfo) => dispatch =>
dispatch({
type: HYDRATE_DASHBOARD_DATAMASK,
data: {
dataMask,
dashboardInfo,
},
});

export const hydrateDashboardActiveTabs = activeTabs => dispatch =>
dispatch({
type: HYDRATE_DASHBOARD_ACTIVETABS,
data: activeTabs || [],
});

export const hydrateDashboard =
({ history, dashboard, charts, dataMask, activeTabs }) =>
({ history, dashboard, charts }) =>
(dispatch, getState) => {
const { user, common, dashboardState } = getState();
const { metadata, position_data: positionData } = dashboard;
Expand Down Expand Up @@ -286,7 +303,6 @@ export const hydrateDashboard =
FilterBarOrientation.Vertical,
crossFiltersEnabled,
},
dataMask,
dashboardFilters,
nativeFilters,
dashboardState: {
Expand All @@ -311,8 +327,9 @@ export const hydrateDashboard =
lastModifiedTime: dashboard.changed_on,
isRefreshing: false,
isFiltersRefreshing: false,
activeTabs: activeTabs || dashboardState?.activeTabs || [],
activeTabs: dashboardState?.activeTabs || [],
datasetsStatus: ResourceStatus.Loading,
dashboardHydrated: true,
},
dashboardLayout,
},
Expand Down
93 changes: 77 additions & 16 deletions superset-frontend/src/dashboard/components/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
import { PureComponent } from 'react';
import { Component } from 'react';
import PropTypes from 'prop-types';
import { isFeatureEnabled, t, FeatureFlag } from '@superset-ui/core';

import { PluginContext } from 'src/components/DynamicPlugins';
import Loading from 'src/components/Loading';
import getBootstrapData from 'src/utils/getBootstrapData';
import getChartIdsFromLayout from '../util/getChartIdsFromLayout';
import getLayoutComponentFromChartId from '../util/getLayoutComponentFromChartId';
Expand Down Expand Up @@ -68,7 +67,7 @@ const defaultProps = {
userId: '',
};

class Dashboard extends PureComponent {
class Dashboard extends Component {
static contextType = PluginContext;

static onBeforeUnload(hasChanged) {
Expand All @@ -90,6 +89,13 @@ class Dashboard extends PureComponent {
this.appliedFilters = props.activeFilters ?? {};
this.appliedOwnDataCharts = props.ownDataCharts ?? {};
this.onVisibilityChange = this.onVisibilityChange.bind(this);
this.applyCharts = this.applyCharts.bind(this);

this.state = {
prevActiveFilters: {},
prevOwnDataCharts: {},
hasTriggered: false,
};
}

componentDidMount() {
Expand Down Expand Up @@ -117,13 +123,41 @@ class Dashboard extends PureComponent {
};
}
window.addEventListener('visibilitychange', this.onVisibilityChange);
this.applyCharts();
}

componentDidUpdate() {
this.applyCharts();
}

shouldComponentUpdate(nextProps) {
const { activeFilters, ownDataCharts, chartConfiguration, dashboardState } =
this.props;
const nextDataMaskHydrated = nextProps.dashboardState.dataMaskHydrated;
const nextActiveFilters = nextProps.activeFilters;
const nextOwnDataCharts = nextProps.ownDataCharts;
const nextChartConfiguration = nextProps.chartConfiguration;
const nextDashboardState = nextProps.dashboardState;

if (
nextDataMaskHydrated &&
(!areObjectsEqual(dashboardState, nextDashboardState, {
ignoreUndefined: true,
}) ||
!areObjectsEqual(activeFilters, nextActiveFilters, {
ignoreUndefined: true,
}) ||
!areObjectsEqual(ownDataCharts, nextOwnDataCharts, {
ignoreUndefined: true,
}) ||
!areObjectsEqual(chartConfiguration, nextChartConfiguration, {
ignoreUndefined: true,
}))
) {
return true;
}
return false;
}

UNSAFE_componentWillReceiveProps(nextProps) {
const currentChartIds = getChartIdsFromLayout(this.props.layout);
const nextChartIds = getChartIdsFromLayout(nextProps.layout);
Expand Down Expand Up @@ -158,7 +192,11 @@ class Dashboard extends PureComponent {
const { hasUnsavedChanges, editMode } = this.props.dashboardState;

const { appliedFilters, appliedOwnDataCharts } = this;
const { activeFilters, ownDataCharts, chartConfiguration } = this.props;
const { activeFilters, ownDataCharts, chartConfiguration, dashboardState } =
this.props;

const { dataMaskHydrated } = dashboardState;

if (
isFeatureEnabled(FeatureFlag.DashboardCrossFilters) &&
!chartConfiguration
Expand All @@ -168,16 +206,41 @@ class Dashboard extends PureComponent {
return;
}

if (
!editMode &&
(!areObjectsEqual(appliedOwnDataCharts, ownDataCharts, {
ignoreUndefined: true,
}) ||
if (dataMaskHydrated) {
const hasFilters =
Object.keys(activeFilters).length > 0 ||
Object.keys(ownDataCharts).length > 0;
const hadFilters =
Object.keys(this.state.prevActiveFilters).length > 0 ||
Object.keys(this.state.prevOwnDataCharts).length > 0;
const { hasTriggered } = this.state;

const filtersChanged =
!areObjectsEqual(appliedOwnDataCharts, ownDataCharts, {
ignoreUndefined: true,
}) ||
!areObjectsEqual(appliedFilters, activeFilters, {
ignoreUndefined: true,
}))
) {
this.applyFilters();
});

// triggers when filters are/were present and are changed/removed
if (!editMode && filtersChanged && (hasFilters || hadFilters)) {
this.setState({
prevActiveFilters: activeFilters,
prevOwnDataCharts: ownDataCharts,
hasTriggered: true,
});
this.applyFilters();
}
// triggers for dashboards with no filters
if (
(editMode || (!hasFilters && !hadFilters)) &&
dashboardState.sliceIds.length > 0 &&
!hasTriggered
) {
this.setState({ hasTriggered: true });
this.refreshCharts(dashboardState.sliceIds);
}
}

if (hasUnsavedChanges) {
Expand All @@ -190,6 +253,7 @@ class Dashboard extends PureComponent {
componentWillUnmount() {
window.removeEventListener('visibilitychange', this.onVisibilityChange);
this.props.actions.clearDataMaskState();
this.props.actions.onLeaveDashboard();
}

onVisibilityChange() {
Expand Down Expand Up @@ -276,9 +340,6 @@ class Dashboard extends PureComponent {
}

render() {
if (this.context.loading) {
return <Loading />;
}
return this.props.children;
}
}
Expand Down
6 changes: 6 additions & 0 deletions superset-frontend/src/dashboard/components/Dashboard.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ describe('Dashboard', () => {
});

it('should not call refresh when is editMode', () => {
wrapper.setState({ hasTriggered: true });
wrapper.setProps({
dashboardState: {
...dashboardState,
Expand All @@ -147,7 +148,9 @@ describe('Dashboard', () => {
wrapper.setProps({
activeFilters: OVERRIDE_FILTERS,
});

wrapper.instance().componentDidUpdate(prevProps);

expect(refreshSpy.callCount).toBe(0);
expect(wrapper.instance().appliedFilters).toBe(OVERRIDE_FILTERS);
});
Expand Down Expand Up @@ -186,6 +189,9 @@ describe('Dashboard', () => {
});

it('should call refresh if a filter is removed', () => {
wrapper.setState({
prevActiveFilters: OVERRIDE_FILTERS,
});
wrapper.setProps({
activeFilters: {},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
const dispatch = useDispatch();
const uiConfig = useUiConfig();
const theme = useTheme();
const isDashboardHydrated = useSelector<RootState, boolean>(
state => state.dashboardState.dashboardHydrated,
);

const dashboardId = useSelector<RootState, string>(
({ dashboardInfo }) => `${dashboardInfo.id}`,
Expand Down Expand Up @@ -463,12 +466,18 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {

const {
showDashboard,
requiredFirstFilter,
missingInitialFilters,
dashboardFiltersOpen,
toggleDashboardFiltersOpen,
nativeFiltersEnabled,
} = useNativeFilters();

// Unblocking the Dashboard rendering unless filters are required
const canShowDashboard = !requiredFirstFilter.length
? true
: showDashboard && isDashboardHydrated;

const [containerRef, isSticky] = useElementOnScreen<HTMLDivElement>({
threshold: [1],
});
Expand Down Expand Up @@ -675,8 +684,8 @@ const DashboardBuilder: FC<DashboardBuilderProps> = () => {
editMode={editMode}
marginLeft={dashboardContentMarginLeft}
>
{showDashboard ? (
missingInitialFilters.length > 0 ? (
{canShowDashboard ? (
!editMode && missingInitialFilters.length > 0 ? (
<div
css={css`
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export const useNativeFilters = () => {

return {
showDashboard,
requiredFirstFilter,
missingInitialFilters,
dashboardFiltersOpen,
toggleDashboardFiltersOpen,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const propTypes = {
datasetsStatus: PropTypes.oneOf(['loading', 'error', 'complete']),
isInView: PropTypes.bool,
emitCrossFilters: PropTypes.bool,
isDashboardHydrated: PropTypes.bool,
};

const defaultProps = {
Expand Down Expand Up @@ -418,7 +419,13 @@ class Chart extends Component {
}

const { queriesResponse, chartUpdateEndTime, chartStatus } = chart;
const isLoading = chartStatus === 'loading';

// Controlling the status of a Chart based on Dashboard hydration
const { isDashboardHydrated } = this.props;
const controlledChartStatus = isDashboardHydrated ? chartStatus : 'loading';
const { triggerQuery } = chart;
const isLoading = controlledChartStatus === 'loading';

// eslint-disable-next-line camelcase
const isCached = queriesResponse?.map(({ is_cached }) => is_cached) || [];
const cachedDttm =
Expand Down Expand Up @@ -465,7 +472,7 @@ class Chart extends Component {
addDangerToast={addDangerToast}
handleToggleFullSize={handleToggleFullSize}
isFullSize={isFullSize}
chartStatus={chart.chartStatus}
chartStatus={controlledChartStatus}
formData={formData}
width={width}
height={this.getHeaderHeight()}
Expand Down Expand Up @@ -510,7 +517,7 @@ class Chart extends Component {
annotationData={chart.annotationData}
chartAlert={chart.chartAlert}
chartId={id}
chartStatus={chartStatus}
chartStatus={controlledChartStatus}
datasource={datasource}
dashboardId={dashboardId}
initialValues={initialValues}
Expand All @@ -521,7 +528,7 @@ class Chart extends Component {
filterState={filterState}
queriesResponse={chart.queriesResponse}
timeout={timeout}
triggerQuery={chart.triggerQuery}
triggerQuery={triggerQuery}
vizType={slice.viz_type}
setControlValue={setControlValue}
postTransformProps={postTransformProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const props = {
supersetCanExplore: false,
supersetCanCSV: false,
supersetCanShare: false,
isDashboardHydrated: true,
};

function setup(overrideProps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const crossFiltersSelector = (props: {
verboseMaps: { [key: string]: Record<string, string> };
}): CrossFilterIndicator[] => {
const { dataMask, chartConfiguration, dashboardLayout, verboseMaps } = props;
const chartsIds = Object.keys(chartConfiguration);
const chartsIds = Object.keys(chartConfiguration || {});

return chartsIds
.map(chartId => {
Expand Down
1 change: 1 addition & 0 deletions superset-frontend/src/dashboard/containers/Chart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ function mapStateToProps(
setControlValue,
datasetsStatus,
emitCrossFilters: !!dashboardInfo.crossFiltersEnabled,
isDashboardHydrated: !!dashboardState.dashboardHydrated,
};
}

Expand Down
Loading
Loading