From 39f1b714a5a8a57a9eeeccd1d3c14039f79aa6f7 Mon Sep 17 00:00:00 2001 From: Enzo Martellucci <52219496+EnxDev@users.noreply.github.com> Date: Wed, 25 Sep 2024 17:45:11 +0200 Subject: [PATCH] refactor: Migration of AnnotationLayerControl to TypeScript (#28346) Co-authored-by: JUST.in DO IT Co-authored-by: Diego Pucci --- .../src/components/Chart/chartAction.js | 2 +- .../{index.jsx => index.tsx} | 137 ++++++++++++------ 2 files changed, 95 insertions(+), 44 deletions(-) rename superset-frontend/src/explore/components/controls/AnnotationLayerControl/{index.jsx => index.tsx} (72%) diff --git a/superset-frontend/src/components/Chart/chartAction.js b/superset-frontend/src/components/Chart/chartAction.js index 8a9124818424f..f7008c9de37ba 100644 --- a/superset-frontend/src/components/Chart/chartAction.js +++ b/superset-frontend/src/components/Chart/chartAction.js @@ -249,7 +249,7 @@ export async function getChartDataRequest({ export function runAnnotationQuery({ annotation, timeout, - formData = null, + formData, key, isDashboardRequest = false, force = false, diff --git a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/index.jsx b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/index.tsx similarity index 72% rename from superset-frontend/src/explore/components/controls/AnnotationLayerControl/index.jsx rename to superset-frontend/src/explore/components/controls/AnnotationLayerControl/index.tsx index 760717a3d9a11..7b77319c6d099 100644 --- a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/index.jsx +++ b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/index.tsx @@ -16,16 +16,26 @@ * specific language governing permissions and limitations * under the License. */ -import { PureComponent } from 'react'; -import PropTypes from 'prop-types'; import { List } from 'src/components'; import { connect } from 'react-redux'; -import { t, withTheme } from '@superset-ui/core'; +import { PureComponent } from 'react'; +import { + HandlerFunction, + JsonObject, + Payload, + QueryFormData, + SupersetTheme, + t, + withTheme, +} from '@superset-ui/core'; import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; import AsyncEsmComponent from 'src/components/AsyncEsmComponent'; import { getChartKey } from 'src/explore/exploreUtils'; import { runAnnotationQuery } from 'src/components/Chart/chartAction'; import CustomListItem from 'src/explore/components/controls/CustomListItem'; +import { ChartState, ExplorePageState } from 'src/explore/types'; +import { AnyAction } from 'redux'; +import { ThunkDispatch } from 'redux-thunk'; import ControlPopover, { getSectionContainerElement, } from '../ControlPopover/ControlPopover'; @@ -36,19 +46,37 @@ const AnnotationLayer = AsyncEsmComponent( () =>
, ); -const propTypes = { - colorScheme: PropTypes.string.isRequired, - annotationError: PropTypes.object, - annotationQuery: PropTypes.object, - vizType: PropTypes.string, +export interface Annotation { + name: string; + show?: boolean; + annotation: string; + timeout: Date; + key: string; + formData: QueryFormData | null; + isDashboardRequest?: boolean; + force?: boolean; +} - validationErrors: PropTypes.array, - name: PropTypes.string.isRequired, - actions: PropTypes.object, - value: PropTypes.arrayOf(PropTypes.object), - onChange: PropTypes.func, - refreshAnnotationData: PropTypes.func, -}; +export interface Props { + colorScheme: string; + annotationError: Record; + annotationQuery: Record; + vizType: string; + validationErrors: JsonObject[]; + name: string; + actions: { + setControlValue: HandlerFunction; + }; + value: Annotation[]; + onChange: (annotations: Annotation[]) => void; + refreshAnnotationData: (payload: Payload) => void; + theme: SupersetTheme; +} + +export interface PopoverState { + popoverVisible: Record; + addedAnnotationIndex: number | null; +} const defaultProps = { vizType: '', @@ -57,9 +85,10 @@ const defaultProps = { annotationQuery: {}, onChange: () => {}, }; +class AnnotationLayerControl extends PureComponent { + static defaultProps = defaultProps; -class AnnotationLayerControl extends PureComponent { - constructor(props) { + constructor(props: Props) { super(props); this.state = { popoverVisible: {}, @@ -75,7 +104,7 @@ class AnnotationLayerControl extends PureComponent { AnnotationLayer.preload(); } - UNSAFE_componentWillReceiveProps(nextProps) { + UNSAFE_componentWillReceiveProps(nextProps: Props) { const { name, annotationError, validationErrors, value } = nextProps; if (Object.keys(annotationError).length && !validationErrors.length) { this.props.actions.setControlValue( @@ -89,9 +118,12 @@ class AnnotationLayerControl extends PureComponent { } } - addAnnotationLayer(originalAnnotation, newAnnotation) { + addAnnotationLayer = ( + originalAnnotation: Annotation | null, + newAnnotation: Annotation, + ) => { let annotations = this.props.value; - if (annotations.includes(originalAnnotation)) { + if (originalAnnotation && annotations.includes(originalAnnotation)) { annotations = annotations.map(anno => anno === originalAnnotation ? newAnnotation : anno, ); @@ -106,15 +138,15 @@ class AnnotationLayerControl extends PureComponent { }); this.props.onChange(annotations); - } + }; - handleVisibleChange(visible, popoverKey) { + handleVisibleChange = (visible: boolean, popoverKey: number | string) => { this.setState(prevState => ({ popoverVisible: { ...prevState.popoverVisible, [popoverKey]: visible }, })); - } + }; - removeAnnotationLayer(annotation) { + removeAnnotationLayer(annotation: Annotation | null) { const annotations = this.props.value.filter(anno => anno !== annotation); // So scrollbar doesnt get stuck on hidden const element = getSectionContainerElement(); @@ -124,17 +156,21 @@ class AnnotationLayerControl extends PureComponent { this.props.onChange(annotations); } - renderPopover(popoverKey, annotation, error) { + renderPopover = ( + popoverKey: number | string, + annotation: Annotation | null, + error: string, + ) => { const id = annotation?.name || '_new'; return (
+ addAnnotationLayer={(newAnnotation: Annotation) => this.addAnnotationLayer(annotation, newAnnotation) } removeAnnotationLayer={() => this.removeAnnotationLayer(annotation)} @@ -145,9 +181,9 @@ class AnnotationLayerControl extends PureComponent { />
); - } + }; - renderInfo(anno) { + renderInfo(anno: Annotation) { const { annotationError, annotationQuery, theme } = this.props; if (annotationQuery[anno.name]) { return ( @@ -175,8 +211,10 @@ class AnnotationLayerControl extends PureComponent { render() { const { addedAnnotationIndex } = this.state; - const addedAnnotation = this.props.value[addedAnnotationIndex]; - + const addedAnnotation = + addedAnnotationIndex !== null + ? this.props.value[addedAnnotationIndex] + : null; const annotations = this.props.value.map((anno, i) => ( )); - const addLayerPopoverKey = 'add'; + return (
({ borderRadius: theme.gridUnit })}> {annotations} ) { const chartKey = getChartKey(explore); - const chart = charts[chartKey] || charts[0] || {}; + + const defaultChartState: Partial = { + annotationError: {}, + annotationQuery: {}, + }; + + const chart = + chartKey && charts[chartKey] ? charts[chartKey] : defaultChartState; return { // eslint-disable-next-line camelcase colorScheme: explore.controls?.color_scheme?.value, - annotationError: chart.annotationError, - annotationQuery: chart.annotationQuery, - vizType: explore.controls.viz_type.value, + annotationError: chart.annotationError ?? {}, + annotationQuery: chart.annotationQuery ?? {}, + vizType: explore.controls?.viz_type.value, }; } -function mapDispatchToProps(dispatch) { +function mapDispatchToProps( + dispatch: ThunkDispatch, +) { return { - refreshAnnotationData: annotationObj => + refreshAnnotationData: (annotationObj: Annotation) => dispatch(runAnnotationQuery(annotationObj)), }; }