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

refactor: Migration of AnnotationLayerControl to TypeScript #28346

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
89b8366
chore: Migration of AnnotationLayerControl index.js to TypeScript
EnxDev May 5, 2024
b054a21
Reuses the ExplorePageState[explore] interface and removes the Explor…
EnxDev May 8, 2024
fc2005c
Update index.tsx
EnxDev May 9, 2024
92ec433
Update index.tsx
EnxDev May 9, 2024
cea4b2e
Update index.tsx
EnxDev May 9, 2024
0dbcd64
chore: Migration of AnnotationLayerControl index.js to TypeScript
EnxDev May 5, 2024
3948773
Reuses the ExplorePageState[explore] interface and removes the Explor…
EnxDev May 8, 2024
e8be58d
Update index.tsx
EnxDev May 9, 2024
bcfb86f
Update index.tsx
EnxDev May 9, 2024
fe2077d
Update index.tsx
EnxDev May 9, 2024
2f33b5c
Merge remote-tracking branch 'origin/chore/typescript-migration-Annot…
EnxDev Jun 4, 2024
ff3fb2e
Removes unused included types
EnxDev Jun 4, 2024
317567e
Removes any types from Annotation type
EnxDev Jun 6, 2024
2edf52e
Merge branch 'master' of https://github.com/apache/superset into chor…
EnxDev Jun 28, 2024
aa3049f
cleanup
EnxDev Jun 28, 2024
a9f9190
Linted
EnxDev Jun 28, 2024
a8758e9
Merge branch 'master' of https://github.com/apache/superset into chor…
geido Sep 25, 2024
da19896
Merge branch 'master' of https://github.com/apache/superset into chor…
EnxDev Sep 25, 2024
4c0c6f0
Merge branch 'master' of https://github.com/apache/superset into chor…
geido Sep 25, 2024
79e9c7a
fix(Ts): Fix types
geido Sep 25, 2024
b43d17c
Merge branch 'chore/typescript-migration-AnnotationLayerControl' of h…
geido Sep 25, 2024
9f5f56d
fix(Annotation): Fix duplicate annotation creation
geido Sep 25, 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: 1 addition & 1 deletion superset-frontend/src/components/Chart/chartAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export async function getChartDataRequest({
export function runAnnotationQuery({
annotation,
timeout,
formData = null,
formData,
key,
isDashboardRequest = false,
force = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -36,19 +46,37 @@ const AnnotationLayer = AsyncEsmComponent(
() => <div style={{ width: 450, height: 368 }} />,
);

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<string, string>;
annotationQuery: Record<string, AbortController>;
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<number | string, boolean>;
addedAnnotationIndex: number | null;
}

const defaultProps = {
vizType: '',
Expand All @@ -57,9 +85,10 @@ const defaultProps = {
annotationQuery: {},
onChange: () => {},
};
class AnnotationLayerControl extends PureComponent<Props, PopoverState> {
static defaultProps = defaultProps;

class AnnotationLayerControl extends PureComponent {
constructor(props) {
constructor(props: Props) {
super(props);
this.state = {
popoverVisible: {},
Expand All @@ -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(
Expand All @@ -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,
);
Expand All @@ -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();
Expand All @@ -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 (
<div id={`annotation-pop-${id}`} data-test="popover-content">
<AnnotationLayer
{...annotation}
{...(annotation || {})}
error={error}
colorScheme={this.props.colorScheme}
vizType={this.props.vizType}
addAnnotationLayer={newAnnotation =>
addAnnotationLayer={(newAnnotation: Annotation) =>
this.addAnnotationLayer(annotation, newAnnotation)
}
removeAnnotationLayer={() => this.removeAnnotationLayer(annotation)}
Expand All @@ -145,9 +181,9 @@ class AnnotationLayerControl extends PureComponent {
/>
</div>
);
}
};

renderInfo(anno) {
renderInfo(anno: Annotation) {
const { annotationError, annotationQuery, theme } = this.props;
if (annotationQuery[anno.name]) {
return (
Expand Down Expand Up @@ -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) => (
<ControlPopover
key={i}
Expand All @@ -202,15 +240,19 @@ class AnnotationLayerControl extends PureComponent {
</CustomListItem>
</ControlPopover>
));

const addLayerPopoverKey = 'add';

return (
<div>
<List bordered css={theme => ({ borderRadius: theme.gridUnit })}>
{annotations}
<ControlPopover
trigger="click"
content={this.renderPopover(addLayerPopoverKey, addedAnnotation)}
content={this.renderPopover(
addLayerPopoverKey,
addedAnnotation,
'',
)}
title={t('Add annotation layer')}
visible={this.state.popoverVisible[addLayerPopoverKey]}
destroyTooltipOnHide
Expand All @@ -232,27 +274,36 @@ class AnnotationLayerControl extends PureComponent {
}
}

AnnotationLayerControl.propTypes = propTypes;
AnnotationLayerControl.defaultProps = defaultProps;

// Tried to hook this up through stores/control.jsx instead of using redux
// directly, could not figure out how to get access to the color_scheme
function mapStateToProps({ charts, explore }) {
function mapStateToProps({
charts,
explore,
}: Pick<ExplorePageState, 'charts' | 'explore'>) {
const chartKey = getChartKey(explore);
const chart = charts[chartKey] || charts[0] || {};

const defaultChartState: Partial<ChartState> = {
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<any, undefined, AnyAction>,
) {
return {
refreshAnnotationData: annotationObj =>
refreshAnnotationData: (annotationObj: Annotation) =>
dispatch(runAnnotationQuery(annotationObj)),
};
}
Expand Down
Loading