refactor: Migrate HeaderActionsDropdown to typescript (#30568)

This commit is contained in:
Enzo Martellucci 2024-10-22 15:55:07 +02:00 committed by GitHub
parent 4d5f70c694
commit 4433ef47fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 55 additions and 87 deletions

View File

@ -66,9 +66,13 @@ const createProps = (): HeaderDropdownProps => ({
userCanCurate: false, userCanCurate: false,
lastModifiedTime: 0, lastModifiedTime: 0,
isDropdownVisible: true, isDropdownVisible: true,
setIsDropdownVisible: jest.fn(),
directPathToChild: [],
manageEmbedded: jest.fn(), manageEmbedded: jest.fn(),
dataMask: {}, dataMask: {},
logEvent: jest.fn(), logEvent: jest.fn(),
refreshLimit: 0,
refreshWarning: '',
}); });
const editModeOnProps = { const editModeOnProps = {

View File

@ -17,7 +17,6 @@
* under the License. * under the License.
*/ */
import { PureComponent } from 'react'; import { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { t } from '@superset-ui/core'; import { t } from '@superset-ui/core';
@ -35,73 +34,38 @@ import FilterScopeModal from 'src/dashboard/components/filterscope/FilterScopeMo
import getDashboardUrl from 'src/dashboard/util/getDashboardUrl'; import getDashboardUrl from 'src/dashboard/util/getDashboardUrl';
import { getActiveFilters } from 'src/dashboard/util/activeDashboardFilters'; import { getActiveFilters } from 'src/dashboard/util/activeDashboardFilters';
import { getUrlParam } from 'src/utils/urlUtils'; import { getUrlParam } from 'src/utils/urlUtils';
import { MenuKeys } from 'src/dashboard/types'; import { MenuKeys, RootState } from 'src/dashboard/types';
import { HeaderDropdownProps } from 'src/dashboard/components/Header/types';
const propTypes = { const mapStateToProps = (state: RootState) => ({
addSuccessToast: PropTypes.func.isRequired,
addDangerToast: PropTypes.func.isRequired,
dashboardInfo: PropTypes.object.isRequired,
dashboardId: PropTypes.number,
dashboardTitle: PropTypes.string,
dataMask: PropTypes.object.isRequired,
customCss: PropTypes.string,
colorNamespace: PropTypes.string,
colorScheme: PropTypes.string,
directPathToChild: PropTypes.array,
onChange: PropTypes.func.isRequired,
updateCss: PropTypes.func.isRequired,
forceRefreshAllCharts: PropTypes.func.isRequired,
refreshFrequency: PropTypes.number,
shouldPersistRefreshFrequency: PropTypes.bool.isRequired,
setRefreshFrequency: PropTypes.func.isRequired,
startPeriodicRender: PropTypes.func.isRequired,
editMode: PropTypes.bool.isRequired,
userCanEdit: PropTypes.bool,
userCanShare: PropTypes.bool,
userCanSave: PropTypes.bool,
userCanCurate: PropTypes.bool.isRequired,
isLoading: PropTypes.bool.isRequired,
layout: PropTypes.object.isRequired,
expandedSlices: PropTypes.object,
onSave: PropTypes.func.isRequired,
showPropertiesModal: PropTypes.func.isRequired,
manageEmbedded: PropTypes.func.isRequired,
logEvent: PropTypes.func,
refreshLimit: PropTypes.number,
refreshWarning: PropTypes.string,
lastModifiedTime: PropTypes.number.isRequired,
};
const defaultProps = {
colorNamespace: undefined,
colorScheme: undefined,
refreshLimit: 0,
refreshWarning: null,
};
const mapStateToProps = state => ({
directPathToChild: state.dashboardState.directPathToChild, directPathToChild: state.dashboardState.directPathToChild,
}); });
export class HeaderActionsDropdown extends PureComponent { interface HeaderActionsDropdownState {
static discardChanges() { css: string;
window.location.reload(); showReportSubMenu: boolean | null;
} }
constructor(props) { export class HeaderActionsDropdown extends PureComponent<
HeaderDropdownProps,
HeaderActionsDropdownState
> {
static defaultProps = {
colorNamespace: undefined,
colorScheme: undefined,
refreshLimit: 0,
refreshWarning: null,
};
constructor(props: HeaderDropdownProps) {
super(props); super(props);
this.state = { this.state = {
css: props.customCss, css: props.customCss || '',
showReportSubMenu: null, showReportSubMenu: null,
}; };
this.changeCss = this.changeCss.bind(this);
this.changeRefreshInterval = this.changeRefreshInterval.bind(this);
this.handleMenuClick = this.handleMenuClick.bind(this);
this.setShowReportSubMenu = this.setShowReportSubMenu.bind(this);
} }
UNSAFE_componentWillReceiveProps(nextProps) { UNSAFE_componentWillReceiveProps(nextProps: HeaderDropdownProps) {
if (this.props.customCss !== nextProps.customCss) { if (this.props.customCss !== nextProps.customCss) {
this.setState({ css: nextProps.customCss }, () => { this.setState({ css: nextProps.customCss }, () => {
injectCustomCss(nextProps.customCss); injectCustomCss(nextProps.customCss);
@ -109,23 +73,21 @@ export class HeaderActionsDropdown extends PureComponent {
} }
} }
setShowReportSubMenu(show) { setShowReportSubMenu = (show: boolean) => {
this.setState({ this.setState({ showReportSubMenu: show });
showReportSubMenu: show, };
});
}
changeCss(css) { changeCss = (css: string) => {
this.props.onChange(); this.props.onChange();
this.props.updateCss(css); this.props.updateCss(css);
} };
changeRefreshInterval(refreshInterval, isPersistent) { changeRefreshInterval = (refreshInterval: number, isPersistent: boolean) => {
this.props.setRefreshFrequency(refreshInterval, isPersistent); this.props.setRefreshFrequency(refreshInterval, isPersistent);
this.props.startPeriodicRender(refreshInterval * 1000); this.props.startPeriodicRender(refreshInterval * 1000);
} };
handleMenuClick({ key }) { handleMenuClick = ({ key }: Record<string, any>) => {
switch (key) { switch (key) {
case MenuKeys.RefreshDashboard: case MenuKeys.RefreshDashboard:
this.props.forceRefreshAllCharts(); this.props.forceRefreshAllCharts();
@ -139,7 +101,7 @@ export class HeaderActionsDropdown extends PureComponent {
pathname: window.location.pathname, pathname: window.location.pathname,
filters: getActiveFilters(), filters: getActiveFilters(),
hash: window.location.hash, hash: window.location.hash,
standalone: !getUrlParam(URL_PARAMS.standalone), standalone: getUrlParam(URL_PARAMS.standalone),
}); });
window.location.replace(url); window.location.replace(url);
break; break;
@ -151,7 +113,7 @@ export class HeaderActionsDropdown extends PureComponent {
default: default:
break; break;
} }
} };
render() { render() {
const { const {
@ -244,8 +206,8 @@ export class HeaderActionsDropdown extends PureComponent {
{userCanSave && ( {userCanSave && (
<Menu.Item key={MenuKeys.SaveModal}> <Menu.Item key={MenuKeys.SaveModal}>
<SaveModal <SaveModal
addSuccessToast={this.props.addSuccessToast} addSuccessToast={addSuccessToast}
addDangerToast={this.props.addDangerToast} addDangerToast={addDangerToast}
dashboardId={dashboardId} dashboardId={dashboardId}
dashboardTitle={dashboardTitle} dashboardTitle={dashboardTitle}
dashboardInfo={dashboardInfo} dashboardInfo={dashboardInfo}
@ -270,13 +232,13 @@ export class HeaderActionsDropdown extends PureComponent {
key={MenuKeys.Download} key={MenuKeys.Download}
disabled={isLoading} disabled={isLoading}
title={t('Download')} title={t('Download')}
logEvent={this.props.logEvent}
> >
<DownloadMenuItems <DownloadMenuItems
pdfMenuItemTitle={t('Export to PDF')} pdfMenuItemTitle={t('Export to PDF')}
imageMenuItemTitle={t('Download as Image')} imageMenuItemTitle={t('Download as Image')}
dashboardTitle={dashboardTitle} dashboardTitle={dashboardTitle}
dashboardId={dashboardId} dashboardId={dashboardId}
logEvent={this.props.logEvent}
/> />
</Menu.SubMenu> </Menu.SubMenu>
{userCanShare && ( {userCanShare && (
@ -338,15 +300,16 @@ export class HeaderActionsDropdown extends PureComponent {
{editMode && !isEmpty(dashboardInfo?.metadata?.filter_scopes) && ( {editMode && !isEmpty(dashboardInfo?.metadata?.filter_scopes) && (
<Menu.Item key={MenuKeys.SetFilterMapping}> <Menu.Item key={MenuKeys.SetFilterMapping}>
<FilterScopeModal <FilterScopeModal
className="m-r-5" triggerNode={
triggerNode={t('Set filter mapping')} <span className="m-r-5">{t('Set filter mapping')}</span>
}
/> />
</Menu.Item> </Menu.Item>
)} )}
<Menu.Item key={MenuKeys.AutorefreshModal}> <Menu.Item key={MenuKeys.AutorefreshModal}>
<RefreshIntervalModal <RefreshIntervalModal
addSuccessToast={this.props.addSuccessToast} addSuccessToast={addSuccessToast}
refreshFrequency={refreshFrequency} refreshFrequency={refreshFrequency}
refreshLimit={refreshLimit} refreshLimit={refreshLimit}
refreshWarning={refreshWarning} refreshWarning={refreshWarning}
@ -361,7 +324,4 @@ export class HeaderActionsDropdown extends PureComponent {
} }
} }
HeaderActionsDropdown.propTypes = propTypes;
HeaderActionsDropdown.defaultProps = defaultProps;
export default connect(mapStateToProps)(HeaderActionsDropdown); export default connect(mapStateToProps)(HeaderActionsDropdown);

View File

@ -30,7 +30,7 @@ interface DashboardInfo {
} }
export interface HeaderDropdownProps { export interface HeaderDropdownProps {
addSuccessToast: () => void; addSuccessToast: (msg: string) => void;
addDangerToast: () => void; addDangerToast: () => void;
customCss: string; customCss: string;
colorNamespace?: string; colorNamespace?: string;
@ -47,20 +47,24 @@ export interface HeaderDropdownProps {
onChange: () => void; onChange: () => void;
onSave: () => void; onSave: () => void;
refreshFrequency: number; refreshFrequency: number;
setRefreshFrequency: () => void; setRefreshFrequency: (refreshInterval: number, isPersistent: boolean) => void;
shouldPersistRefreshFrequency: boolean; shouldPersistRefreshFrequency: boolean;
showPropertiesModal: () => void; showPropertiesModal: () => void;
startPeriodicRender: () => void; startPeriodicRender: (interval: number) => void;
updateCss: () => void; updateCss: (css: string) => void;
userCanEdit: boolean; userCanEdit: boolean;
userCanSave: boolean; userCanSave: boolean;
userCanShare: boolean; userCanShare: boolean;
userCanCurate: boolean; userCanCurate: boolean;
isDropdownVisible: boolean;
manageEmbedded: () => void; manageEmbedded: () => void;
dataMask: any; dataMask: any;
lastModifiedTime: number; lastModifiedTime: number;
logEvent: () => void; logEvent: () => void;
setIsDropdownVisible: (visible: boolean) => void;
isDropdownVisible: boolean;
refreshLimit: number;
refreshWarning: string;
directPathToChild: string[];
} }
export interface HeaderProps { export interface HeaderProps {

View File

@ -24,7 +24,7 @@ const createProps = () => ({
imageMenuItemTitle: 'Download as Image', imageMenuItemTitle: 'Download as Image',
dashboardTitle: 'Test Dashboard', dashboardTitle: 'Test Dashboard',
logEvent: jest.fn(), logEvent: jest.fn(),
dashboardId: '123', dashboardId: 123,
}); });
const renderComponent = () => { const renderComponent = () => {

View File

@ -42,7 +42,7 @@ jest.mock('src/components/MessageToasts/withToasts', () => ({
const defaultProps = () => ({ const defaultProps = () => ({
text: 'Download', text: 'Download',
dashboardId: '123', dashboardId: 123,
format: DownloadScreenshotFormat.PDF, format: DownloadScreenshotFormat.PDF,
logEvent: mockLogEvent, logEvent: mockLogEvent,
}); });

View File

@ -45,7 +45,7 @@ export default function DownloadScreenshot({
...rest ...rest
}: { }: {
text: string; text: string;
dashboardId: string; dashboardId: number;
logEvent?: Function; logEvent?: Function;
format: string; format: string;
}) { }) {

View File

@ -25,7 +25,7 @@ export interface DownloadMenuItemProps {
imageMenuItemTitle: string; imageMenuItemTitle: string;
dashboardTitle: string; dashboardTitle: string;
logEvent?: Function; logEvent?: Function;
dashboardId: string; dashboardId: number;
} }
const DownloadMenuItems = (props: DownloadMenuItemProps) => { const DownloadMenuItems = (props: DownloadMenuItemProps) => {