mirror of
https://github.com/apache/superset.git
synced 2024-09-12 00:29:39 -04:00
chore: clean up mountedTab (#11569)
This commit is contained in:
parent
24ba5301d1
commit
6ab03feed8
@ -67,7 +67,6 @@ describe('DashboardBuilder', () => {
|
|||||||
colorScheme: undefined,
|
colorScheme: undefined,
|
||||||
handleComponentDrop() {},
|
handleComponentDrop() {},
|
||||||
setDirectPathToChild: sinon.spy(),
|
setDirectPathToChild: sinon.spy(),
|
||||||
setMountedTab() {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function setup(overrideProps, useProvider = false, store = mockStore) {
|
function setup(overrideProps, useProvider = false, store = mockStore) {
|
||||||
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import { ChartUnconnected as Chart } from 'src/dashboard/components/gridComponents/Chart';
|
import Chart from 'src/dashboard/components/gridComponents/Chart';
|
||||||
import SliceHeader from 'src/dashboard/components/SliceHeader';
|
import SliceHeader from 'src/dashboard/components/SliceHeader';
|
||||||
import ChartContainer from 'src/chart/ChartContainer';
|
import ChartContainer from 'src/chart/ChartContainer';
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ describe('Tabs', () => {
|
|||||||
deleteComponent() {},
|
deleteComponent() {},
|
||||||
updateComponents() {},
|
updateComponents() {},
|
||||||
logEvent() {},
|
logEvent() {},
|
||||||
setMountedTab() {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function setup(overrideProps) {
|
function setup(overrideProps) {
|
||||||
|
@ -65,8 +65,6 @@ const propTypes = {
|
|||||||
onQuery: PropTypes.func,
|
onQuery: PropTypes.func,
|
||||||
onFilterMenuOpen: PropTypes.func,
|
onFilterMenuOpen: PropTypes.func,
|
||||||
onFilterMenuClose: PropTypes.func,
|
onFilterMenuClose: PropTypes.func,
|
||||||
// id of the last mounted parent tab
|
|
||||||
mountedParent: PropTypes.string,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const BLANK = {};
|
const BLANK = {};
|
||||||
|
@ -127,7 +127,7 @@ const StyledEditableTabs = styled(StyledTabs)`
|
|||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const EditableTabs = Object.assign(StyledEditableTabs, {
|
export const EditableTabs = Object.assign(StyledEditableTabs, {
|
||||||
TabPane: StyledTabPane,
|
TabPane: StyledTabPane,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ EditableTabs.TabPane.defaultProps = {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledLineEditableTabs = styled(EditableTabs)`
|
export const StyledLineEditableTabs = styled(EditableTabs)`
|
||||||
&.ant-tabs-card > .ant-tabs-nav .ant-tabs-tab {
|
&.ant-tabs-card > .ant-tabs-nav .ant-tabs-tab {
|
||||||
margin: 0 ${({ theme }) => theme.gridUnit * 4}px;
|
margin: 0 ${({ theme }) => theme.gridUnit * 4}px;
|
||||||
padding: ${({ theme }) => `${theme.gridUnit * 3}px ${theme.gridUnit}px`};
|
padding: ${({ theme }) => `${theme.gridUnit * 3}px ${theme.gridUnit}px`};
|
||||||
@ -170,9 +170,8 @@ const StyledLineEditableTabs = styled(EditableTabs)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const LineEditableTabs = Object.assign(StyledLineEditableTabs, {
|
export const LineEditableTabs = Object.assign(StyledLineEditableTabs, {
|
||||||
TabPane: StyledTabPane,
|
TabPane: StyledTabPane,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Tabs;
|
export default Tabs;
|
||||||
export { EditableTabs, LineEditableTabs };
|
|
||||||
|
@ -191,7 +191,7 @@ export function Menu({
|
|||||||
</DropdownMenu.ItemGroup>,
|
</DropdownMenu.ItemGroup>,
|
||||||
]}
|
]}
|
||||||
{(navbarRight.version_string || navbarRight.version_sha) && [
|
{(navbarRight.version_string || navbarRight.version_sha) && [
|
||||||
<DropdownMenu.Divider key="navbar-divider" />,
|
<DropdownMenu.Divider key="version-info-divider" />,
|
||||||
<DropdownMenu.ItemGroup
|
<DropdownMenu.ItemGroup
|
||||||
key="about-section"
|
key="about-section"
|
||||||
title={t('About')}
|
title={t('About')}
|
||||||
|
@ -320,14 +320,6 @@ export function setDirectPathToChild(path) {
|
|||||||
return { type: SET_DIRECT_PATH, path };
|
return { type: SET_DIRECT_PATH, path };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SET_MOUNTED_TAB = 'SET_MOUNTED_TAB';
|
|
||||||
/**
|
|
||||||
* Set if tab switch animation is in progress
|
|
||||||
*/
|
|
||||||
export function setMountedTab(mountedTab) {
|
|
||||||
return { type: SET_MOUNTED_TAB, mountedTab };
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SET_FOCUSED_FILTER_FIELD = 'SET_FOCUSED_FILTER_FIELD';
|
export const SET_FOCUSED_FILTER_FIELD = 'SET_FOCUSED_FILTER_FIELD';
|
||||||
export function setFocusedFilterField(chartId, column) {
|
export function setFocusedFilterField(chartId, column) {
|
||||||
return { type: SET_FOCUSED_FILTER_FIELD, chartId, column };
|
return { type: SET_FOCUSED_FILTER_FIELD, chartId, column };
|
||||||
|
@ -276,12 +276,6 @@ class DashboardBuilder extends React.Component {
|
|||||||
<TabPane
|
<TabPane
|
||||||
key={index === 0 ? DASHBOARD_GRID_ID : id}
|
key={index === 0 ? DASHBOARD_GRID_ID : id}
|
||||||
eventKey={index}
|
eventKey={index}
|
||||||
mountOnEnter
|
|
||||||
unmountOnExit={false}
|
|
||||||
onEntering={() => {
|
|
||||||
// Entering current tab, DOM is visible and has dimension
|
|
||||||
this.props.setMountedTab(id);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<DashboardGrid
|
<DashboardGrid
|
||||||
gridComponent={dashboardLayout[id]}
|
gridComponent={dashboardLayout[id]}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { exploreChart, exportChart } from '../../../explore/exploreUtils';
|
import { exploreChart, exportChart } from '../../../explore/exploreUtils';
|
||||||
import SliceHeader from '../SliceHeader';
|
import SliceHeader from '../SliceHeader';
|
||||||
@ -42,8 +41,6 @@ const propTypes = {
|
|||||||
height: PropTypes.number.isRequired,
|
height: PropTypes.number.isRequired,
|
||||||
updateSliceName: PropTypes.func.isRequired,
|
updateSliceName: PropTypes.func.isRequired,
|
||||||
isComponentVisible: PropTypes.bool,
|
isComponentVisible: PropTypes.bool,
|
||||||
// last switched tab
|
|
||||||
mountedParent: PropTypes.string,
|
|
||||||
handleToggleFullSize: PropTypes.func.isRequired,
|
handleToggleFullSize: PropTypes.func.isRequired,
|
||||||
|
|
||||||
// from redux
|
// from redux
|
||||||
@ -73,7 +70,6 @@ const propTypes = {
|
|||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
isCached: false,
|
isCached: false,
|
||||||
isComponentVisible: true,
|
isComponentVisible: true,
|
||||||
mountedParent: 'ROOT',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// we use state + shouldComponentUpdate() logic to prevent perf-wrecking
|
// we use state + shouldComponentUpdate() logic to prevent perf-wrecking
|
||||||
@ -85,7 +81,7 @@ const SHOULD_UPDATE_ON_PROP_CHANGES = Object.keys(propTypes).filter(
|
|||||||
const OVERFLOWABLE_VIZ_TYPES = new Set(['filter_box']);
|
const OVERFLOWABLE_VIZ_TYPES = new Set(['filter_box']);
|
||||||
const DEFAULT_HEADER_HEIGHT = 22;
|
const DEFAULT_HEADER_HEIGHT = 22;
|
||||||
|
|
||||||
class Chart extends React.Component {
|
export default class Chart extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -118,9 +114,6 @@ class Chart extends React.Component {
|
|||||||
// allow chart update/re-render only if visible:
|
// allow chart update/re-render only if visible:
|
||||||
// under selected tab or no tab layout
|
// under selected tab or no tab layout
|
||||||
if (nextProps.isComponentVisible) {
|
if (nextProps.isComponentVisible) {
|
||||||
if (nextProps.mountedParent === null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (nextProps.chart.triggerQuery) {
|
if (nextProps.chart.triggerQuery) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -354,21 +347,3 @@ class Chart extends React.Component {
|
|||||||
|
|
||||||
Chart.propTypes = propTypes;
|
Chart.propTypes = propTypes;
|
||||||
Chart.defaultProps = defaultProps;
|
Chart.defaultProps = defaultProps;
|
||||||
|
|
||||||
function mapStateToProps({ dashboardState }) {
|
|
||||||
return {
|
|
||||||
// needed to prevent chart from rendering while tab switch animation in progress
|
|
||||||
// when undefined, default to have mounted the root tab
|
|
||||||
mountedParent: dashboardState?.mountedTab,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The original Chart component not connected to state.
|
|
||||||
*/
|
|
||||||
export const ChartUnconnected = Chart;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redux connected Chart component.
|
|
||||||
*/
|
|
||||||
export default connect(mapStateToProps, null)(Chart);
|
|
||||||
|
@ -51,7 +51,6 @@ const propTypes = {
|
|||||||
|
|
||||||
// actions (from DashboardComponent.jsx)
|
// actions (from DashboardComponent.jsx)
|
||||||
logEvent: PropTypes.func.isRequired,
|
logEvent: PropTypes.func.isRequired,
|
||||||
setMountedTab: PropTypes.func.isRequired,
|
|
||||||
|
|
||||||
// grid related
|
// grid related
|
||||||
availableColumnCount: PropTypes.number,
|
availableColumnCount: PropTypes.number,
|
||||||
@ -202,7 +201,7 @@ class Tabs extends React.PureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleClickTab(tabIndex) {
|
handleClickTab(tabIndex) {
|
||||||
const { component, renderTabContent } = this.props;
|
const { component } = this.props;
|
||||||
|
|
||||||
if (tabIndex !== this.state.tabIndex) {
|
if (tabIndex !== this.state.tabIndex) {
|
||||||
const pathToTabIndex = getDirectPathToTabIndex(component, tabIndex);
|
const pathToTabIndex = getDirectPathToTabIndex(component, tabIndex);
|
||||||
@ -214,11 +213,6 @@ class Tabs extends React.PureComponent {
|
|||||||
|
|
||||||
this.props.onChangeTab({ pathToTabIndex });
|
this.props.onChangeTab({ pathToTabIndex });
|
||||||
}
|
}
|
||||||
if (renderTabContent) {
|
|
||||||
const tabIds = component.children;
|
|
||||||
const activeKey = tabIds[this.state.tabIndex];
|
|
||||||
this.props.setMountedTab(activeKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteComponent() {
|
handleDeleteComponent() {
|
||||||
|
@ -24,7 +24,6 @@ import {
|
|||||||
setColorSchemeAndUnsavedChanges,
|
setColorSchemeAndUnsavedChanges,
|
||||||
showBuilderPane,
|
showBuilderPane,
|
||||||
setDirectPathToChild,
|
setDirectPathToChild,
|
||||||
setMountedTab,
|
|
||||||
} from '../actions/dashboardState';
|
} from '../actions/dashboardState';
|
||||||
import {
|
import {
|
||||||
deleteTopLevelTabs,
|
deleteTopLevelTabs,
|
||||||
@ -50,7 +49,6 @@ function mapDispatchToProps(dispatch) {
|
|||||||
showBuilderPane,
|
showBuilderPane,
|
||||||
setColorSchemeAndUnsavedChanges,
|
setColorSchemeAndUnsavedChanges,
|
||||||
setDirectPathToChild,
|
setDirectPathToChild,
|
||||||
setMountedTab,
|
|
||||||
},
|
},
|
||||||
dispatch,
|
dispatch,
|
||||||
);
|
);
|
||||||
|
@ -35,7 +35,7 @@ import {
|
|||||||
updateComponents,
|
updateComponents,
|
||||||
handleComponentDrop,
|
handleComponentDrop,
|
||||||
} from '../actions/dashboardLayout';
|
} from '../actions/dashboardLayout';
|
||||||
import { setDirectPathToChild, setMountedTab } from '../actions/dashboardState';
|
import { setDirectPathToChild } from '../actions/dashboardState';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
component: componentShape.isRequired,
|
component: componentShape.isRequired,
|
||||||
@ -127,7 +127,6 @@ function mapDispatchToProps(dispatch) {
|
|||||||
updateComponents,
|
updateComponents,
|
||||||
handleComponentDrop,
|
handleComponentDrop,
|
||||||
setDirectPathToChild,
|
setDirectPathToChild,
|
||||||
setMountedTab,
|
|
||||||
logEvent,
|
logEvent,
|
||||||
},
|
},
|
||||||
dispatch,
|
dispatch,
|
||||||
|
@ -33,7 +33,6 @@ import {
|
|||||||
UPDATE_CSS,
|
UPDATE_CSS,
|
||||||
SET_REFRESH_FREQUENCY,
|
SET_REFRESH_FREQUENCY,
|
||||||
SET_DIRECT_PATH,
|
SET_DIRECT_PATH,
|
||||||
SET_MOUNTED_TAB,
|
|
||||||
SET_FOCUSED_FILTER_FIELD,
|
SET_FOCUSED_FILTER_FIELD,
|
||||||
UNSET_FOCUSED_FILTER_FIELD,
|
UNSET_FOCUSED_FILTER_FIELD,
|
||||||
} from '../actions/dashboardState';
|
} from '../actions/dashboardState';
|
||||||
@ -124,23 +123,11 @@ export default function dashboardStateReducer(state = {}, action) {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
[SET_DIRECT_PATH]() {
|
[SET_DIRECT_PATH]() {
|
||||||
const newState = {
|
return {
|
||||||
...state,
|
...state,
|
||||||
directPathToChild: action.path,
|
directPathToChild: action.path,
|
||||||
directPathLastUpdated: Date.now(),
|
directPathLastUpdated: Date.now(),
|
||||||
};
|
};
|
||||||
// change of direct path (tabs) will reset current mounted tab
|
|
||||||
// cannot just set mountedTab to null,
|
|
||||||
// as that is used when transitioning between tabs.
|
|
||||||
delete newState.mountedTab;
|
|
||||||
return newState;
|
|
||||||
},
|
|
||||||
[SET_MOUNTED_TAB]() {
|
|
||||||
// set current mounted tab after tab is really mounted to DOM
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
mountedTab: action.mountedTab,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
[SET_FOCUSED_FILTER_FIELD]() {
|
[SET_FOCUSED_FILTER_FIELD]() {
|
||||||
return {
|
return {
|
||||||
|
Loading…
Reference in New Issue
Block a user