From 8aecffd83ba994c73d10c6879f9ab274cef11153 Mon Sep 17 00:00:00 2001 From: Jesse Yang Date: Sat, 24 Oct 2020 21:40:36 -0700 Subject: [PATCH] refactor: typing for explore Control and messageToasts (#11416) --- .../dashboard/actions/dashboardLayout_spec.js | 29 +++--- .../messageToasts/mockMessageToasts.js | 6 +- .../getToastsFromPyFlashMessages_spec.js | 15 ++- superset-frontend/src/chart/Chart.jsx | 4 +- .../src/datasource/DatasourceEditor.jsx | 1 + .../{exploreActions.js => exploreActions.ts} | 91 +++++++++++-------- .../components/{Control.jsx => Control.tsx} | 76 +++++++--------- .../components/ControlPanelsContainer.jsx | 4 +- .../explore/components/PropertiesModal.tsx | 51 +++++------ .../src/explore/reducers/exploreReducer.js | 13 --- .../actions/{index.js => index.ts} | 38 ++++---- .../src/messageToasts/components/Toast.tsx | 39 ++++---- .../components/ToastPresenter.tsx | 37 ++++---- .../{constants.js => constants.ts} | 13 ++- .../src/messageToasts/propShapes.js | 39 -------- superset-frontend/src/messageToasts/types.ts | 17 +++- .../utils/getToastsFromPyFlashMessages.js | 6 +- superset-frontend/src/types/Chart.ts | 8 ++ .../src/views/CRUD/chart/ChartList.tsx | 4 +- 19 files changed, 226 insertions(+), 265 deletions(-) rename superset-frontend/src/explore/actions/{exploreActions.js => exploreActions.ts} (67%) rename superset-frontend/src/explore/components/{Control.jsx => Control.tsx} (60%) rename superset-frontend/src/messageToasts/actions/{index.js => index.ts} (64%) rename superset-frontend/src/messageToasts/{constants.js => constants.ts} (74%) delete mode 100644 superset-frontend/src/messageToasts/propShapes.js diff --git a/superset-frontend/spec/javascripts/dashboard/actions/dashboardLayout_spec.js b/superset-frontend/spec/javascripts/dashboard/actions/dashboardLayout_spec.js index 6f072feef1..4a98667e7d 100644 --- a/superset-frontend/spec/javascripts/dashboard/actions/dashboardLayout_spec.js +++ b/superset-frontend/spec/javascripts/dashboard/actions/dashboardLayout_spec.js @@ -40,7 +40,7 @@ import { import { setUnsavedChanges } from 'src/dashboard/actions/dashboardState'; import * as dashboardFilters from 'src/dashboard/actions/dashboardFilters'; -import { addWarningToast, ADD_TOAST } from 'src/messageToasts/actions'; +import { ADD_TOAST } from 'src/messageToasts/actions'; import { DASHBOARD_GRID_TYPE, @@ -349,24 +349,27 @@ describe('dashboardLayout actions', () => { const { getState, dispatch } = setup({ dashboardLayout: { present: { - source: { type: ROW_TYPE }, - destination: { type: ROW_TYPE, children: ['rowChild'] }, - dragging: { type: CHART_TYPE, meta: { width: 1 } }, - rowChild: { type: CHART_TYPE, meta: { width: 12 } }, + source: { id: 'source', type: ROW_TYPE, children: ['dragging'] }, + destination: { + id: 'destination', + type: ROW_TYPE, + children: ['rowChild'], + }, + dragging: { id: 'dragging', type: CHART_TYPE, meta: { width: 1 } }, + rowChild: { id: 'rowChild', type: CHART_TYPE, meta: { width: 12 } }, }, }, }); const dropResult = { source: { id: 'source', type: ROW_TYPE }, destination: { id: 'destination', type: ROW_TYPE }, - dragging: { id: 'dragging', type: CHART_TYPE }, + dragging: { id: 'dragging', type: CHART_TYPE, meta: { width: 1 } }, }; const thunk = handleComponentDrop(dropResult); thunk(dispatch, getState); - expect(dispatch.getCall(0).args[0].type).toEqual( - addWarningToast('').type, - ); + + expect(dispatch.getCall(0).args[0].type).toEqual(ADD_TOAST); expect(dispatch.callCount).toBe(1); }); @@ -479,13 +482,9 @@ describe('dashboardLayout actions', () => { }, }; - const thunk1 = handleComponentDrop(dropResult); - thunk1(dispatch, getState); + handleComponentDrop(dropResult)(dispatch, getState); - const thunk2 = dispatch.getCall(0).args[0]; - thunk2(dispatch, getState); - - expect(dispatch.getCall(1).args[0].type).toEqual(ADD_TOAST); + expect(dispatch.getCall(0).args[0].type).toEqual(ADD_TOAST); }); }); diff --git a/superset-frontend/spec/javascripts/messageToasts/mockMessageToasts.js b/superset-frontend/spec/javascripts/messageToasts/mockMessageToasts.js index e009ba56e3..311e626629 100644 --- a/superset-frontend/spec/javascripts/messageToasts/mockMessageToasts.js +++ b/superset-frontend/spec/javascripts/messageToasts/mockMessageToasts.js @@ -16,9 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -import { INFO_TOAST, DANGER_TOAST } from 'src/messageToasts/constants'; +import { ToastType } from 'src/messageToasts/constants'; export default [ - { id: 'info_id', toastType: INFO_TOAST, text: 'info toast' }, - { id: 'danger_id', toastType: DANGER_TOAST, text: 'danger toast' }, + { id: 'info_id', toastType: ToastType.INFO, text: 'info toast' }, + { id: 'danger_id', toastType: ToastType.DANGER, text: 'danger toast' }, ]; diff --git a/superset-frontend/spec/javascripts/messageToasts/utils/getToastsFromPyFlashMessages_spec.js b/superset-frontend/spec/javascripts/messageToasts/utils/getToastsFromPyFlashMessages_spec.js index edabc0a9eb..59f8a45d27 100644 --- a/superset-frontend/spec/javascripts/messageToasts/utils/getToastsFromPyFlashMessages_spec.js +++ b/superset-frontend/spec/javascripts/messageToasts/utils/getToastsFromPyFlashMessages_spec.js @@ -16,18 +16,17 @@ * specific language governing permissions and limitations * under the License. */ -import { - DANGER_TOAST, - INFO_TOAST, - SUCCESS_TOAST, -} from 'src/messageToasts/constants'; +import { ToastType } from 'src/messageToasts/constants'; import getToastsFromPyFlashMessages from 'src/messageToasts/utils/getToastsFromPyFlashMessages'; describe('getToastsFromPyFlashMessages', () => { it('should return an info toast', () => { const toast = getToastsFromPyFlashMessages([['info', 'info test']])[0]; - expect(toast).toMatchObject({ toastType: INFO_TOAST, text: 'info test' }); + expect(toast).toMatchObject({ + toastType: ToastType.INFO, + text: 'info test', + }); }); it('should return a success toast', () => { @@ -35,7 +34,7 @@ describe('getToastsFromPyFlashMessages', () => { ['success', 'success test'], ])[0]; expect(toast).toMatchObject({ - toastType: SUCCESS_TOAST, + toastType: ToastType.SUCCESS, text: 'success test', }); }); @@ -43,7 +42,7 @@ describe('getToastsFromPyFlashMessages', () => { it('should return a danger toast', () => { const toast = getToastsFromPyFlashMessages([['danger', 'danger test']])[0]; expect(toast).toMatchObject({ - toastType: DANGER_TOAST, + toastType: ToastType.DANGER, text: 'danger test', }); }); diff --git a/superset-frontend/src/chart/Chart.jsx b/superset-frontend/src/chart/Chart.jsx index 41f2785ecf..1d386ecf6e 100644 --- a/superset-frontend/src/chart/Chart.jsx +++ b/superset-frontend/src/chart/Chart.jsx @@ -49,7 +49,9 @@ const propTypes = { timeout: PropTypes.number, vizType: PropTypes.string.isRequired, triggerRender: PropTypes.bool, - owners: PropTypes.arrayOf(PropTypes.string), + owners: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + ), // state chartAlert: PropTypes.string, chartStatus: PropTypes.string, diff --git a/superset-frontend/src/datasource/DatasourceEditor.jsx b/superset-frontend/src/datasource/DatasourceEditor.jsx index 01684b1676..3cfba9411a 100644 --- a/superset-frontend/src/datasource/DatasourceEditor.jsx +++ b/superset-frontend/src/datasource/DatasourceEditor.jsx @@ -618,6 +618,7 @@ class DatasourceEditor extends React.PureComponent {
{DATASOURCE_TYPES_ARR.map(type => ( >) { SupersetClient.get({ endpoint: `${FAVESTAR_BASE_URL}/${sliceId}/count`, }).then(({ json }) => { @@ -87,33 +85,32 @@ export function fetchFaveStar(sliceId) { } export const SAVE_FAVE_STAR = 'SAVE_FAVE_STAR'; -export function saveFaveStar(sliceId, isStarred) { - return function (dispatch) { +export function saveFaveStar(sliceId: string, isStarred: boolean) { + return function (dispatch: Dispatch>) { const urlSuffix = isStarred ? 'unselect' : 'select'; SupersetClient.get({ endpoint: `${FAVESTAR_BASE_URL}/${sliceId}/${urlSuffix}/`, }) .then(() => dispatch(toggleFaveStar(!isStarred))) - .catch(() => + .catch(() => { dispatch( addDangerToast(t('An error occurred while starring this chart')), - ), - ); + ); + }); }; } export const SET_FIELD_VALUE = 'SET_FIELD_VALUE'; -export function setControlValue(controlName, value, validationErrors) { +export function setControlValue( + controlName: string, + value: any, + validationErrors: any[], +) { return { type: SET_FIELD_VALUE, controlName, value, validationErrors }; } -export const UPDATE_EXPLORE_ENDPOINTS = 'UPDATE_EXPLORE_ENDPOINTS'; -export function updateExploreEndpoints(jsonUrl, csvUrl, standaloneUrl) { - return { type: UPDATE_EXPLORE_ENDPOINTS, jsonUrl, csvUrl, standaloneUrl }; -} - export const SET_EXPLORE_CONTROLS = 'UPDATE_EXPLORE_CONTROLS'; -export function setExploreControls(formData) { +export function setExploreControls(formData: QueryFormData) { return { type: SET_EXPLORE_CONTROLS, formData }; } @@ -123,17 +120,17 @@ export function removeControlPanelAlert() { } export const UPDATE_CHART_TITLE = 'UPDATE_CHART_TITLE'; -export function updateChartTitle(sliceName) { +export function updateChartTitle(sliceName: string) { return { type: UPDATE_CHART_TITLE, sliceName }; } export const CREATE_NEW_SLICE = 'CREATE_NEW_SLICE'; export function createNewSlice( - can_add, - can_download, - can_overwrite, - slice, - form_data, + can_add: boolean, + can_download: boolean, + can_overwrite: boolean, + slice: Slice, + form_data: QueryFormData, ) { return { type: CREATE_NEW_SLICE, @@ -146,6 +143,26 @@ export function createNewSlice( } export const SLICE_UPDATED = 'SLICE_UPDATED'; -export function sliceUpdated(slice) { +export function sliceUpdated(slice: Slice) { return { type: SLICE_UPDATED, slice }; } + +export const exploreActions = { + setDatasourceType, + setDatasource, + setDatasources, + fetchDatasourcesStarted, + fetchDatasourcesSucceeded, + resetControls, + toggleFaveStar, + fetchFaveStar, + saveFaveStar, + setControlValue, + setExploreControls, + removeControlPanelAlert, + updateChartTitle, + createNewSlice, + sliceUpdated, +}; + +export type ExploreActions = typeof exploreActions; diff --git a/superset-frontend/src/explore/components/Control.jsx b/superset-frontend/src/explore/components/Control.tsx similarity index 60% rename from superset-frontend/src/explore/components/Control.jsx rename to superset-frontend/src/explore/components/Control.tsx index 68f0e656fa..8fc6583f23 100644 --- a/superset-frontend/src/explore/components/Control.jsx +++ b/superset-frontend/src/explore/components/Control.tsx @@ -16,52 +16,41 @@ * specific language governing permissions and limitations * under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; - -import './Control.less'; +import React, { ReactNode } from 'react'; +import { ControlType } from '@superset-ui/chart-controls'; +import { JsonValue, QueryFormData } from '@superset-ui/core'; +import { ExploreActions } from '../actions/exploreActions'; import controlMap from './controls'; -const controlTypes = Object.keys(controlMap); +import './Control.less'; -const propTypes = { - actions: PropTypes.object.isRequired, - name: PropTypes.string.isRequired, - type: PropTypes.oneOfType([ - PropTypes.oneOf(controlTypes).isRequired, - PropTypes.func.isRequired, - ]), - hidden: PropTypes.bool, - label: PropTypes.string.isRequired, - choices: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.array), - PropTypes.func, - ]), - description: PropTypes.string, - tooltipOnClick: PropTypes.func, - places: PropTypes.number, - validationErrors: PropTypes.array, - renderTrigger: PropTypes.bool, - rightNode: PropTypes.node, - formData: PropTypes.object, - value: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.object, - PropTypes.bool, - PropTypes.array, - PropTypes.func, - ]), +export type ControlProps = { + // the actual action dispatcher (via bindActionCreators) has identical + // signature to the original action factory. + actions: ExploreActions; + type: ControlType; + label: string; + name: string; + description?: string; + tooltipOnClick?: () => ReactNode; + places?: number; + rightNode?: ReactNode; + formData?: QueryFormData | null; + value?: JsonValue; + validationErrors?: any[]; + hidden?: boolean; + renderTrigger?: boolean; }; -const defaultProps = { - renderTrigger: false, - hidden: false, - validationErrors: [], -}; +export default class Control extends React.PureComponent< + ControlProps, + { hovered: boolean } +> { + onMouseEnter: () => void; -export default class Control extends React.PureComponent { - constructor(props) { + onMouseLeave: () => void; + + constructor(props: ControlProps) { super(props); this.state = { hovered: false }; this.onChange = this.onChange.bind(this); @@ -69,11 +58,11 @@ export default class Control extends React.PureComponent { this.onMouseLeave = this.setHover.bind(this, false); } - onChange(value, errors) { + onChange(value: any, errors: any[]) { this.props.actions.setControlValue(this.props.name, value, errors); } - setHover(hovered) { + setHover(hovered: boolean) { this.setState({ hovered }); } @@ -98,6 +87,3 @@ export default class Control extends React.PureComponent { ); } } - -Control.propTypes = propTypes; -Control.defaultProps = defaultProps; diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx b/superset-frontend/src/explore/components/ControlPanelsContainer.jsx index e79e71a2ef..e834c6dd40 100644 --- a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx +++ b/superset-frontend/src/explore/components/ControlPanelsContainer.jsx @@ -28,7 +28,7 @@ import ControlPanelSection from './ControlPanelSection'; import ControlRow from './ControlRow'; import Control from './Control'; import { sectionsToRender } from '../controlUtils'; -import * as exploreActions from '../actions/exploreActions'; +import { exploreActions } from '../actions/exploreActions'; const propTypes = { actions: PropTypes.object.isRequired, @@ -106,8 +106,8 @@ class ControlPanelsContainer extends React.Component { return ( void; @@ -81,28 +73,31 @@ function PropertiesModal({ slice, onHide, onSave }: InternalProps) { }); } - async function fetchChartData() { - try { - const response = await SupersetClient.get({ - endpoint: `/api/v1/chart/${slice.slice_id}`, - }); - const chart = response.json.result; - setOwners( - chart.owners.map((owner: any) => ({ - value: owner.id, - label: `${owner.first_name} ${owner.last_name}`, - })), - ); - } catch (response) { - const clientError = await getClientErrorObject(response); - showError(clientError); - } - } + const fetchChartData = useCallback( + async function fetchChartData() { + try { + const response = await SupersetClient.get({ + endpoint: `/api/v1/chart/${slice.slice_id}`, + }); + const chart = response.json.result; + setOwners( + chart.owners.map((owner: any) => ({ + value: owner.id, + label: `${owner.first_name} ${owner.last_name}`, + })), + ); + } catch (response) { + const clientError = await getClientErrorObject(response); + showError(clientError); + } + }, + [slice.slice_id], + ); // get the owners of this slice useEffect(() => { fetchChartData(); - }, []); + }, [fetchChartData]); const loadOptions = (input = '') => { const query = rison.encode({ diff --git a/superset-frontend/src/explore/reducers/exploreReducer.js b/superset-frontend/src/explore/reducers/exploreReducer.js index 83cd62e321..36d7908e61 100644 --- a/superset-frontend/src/explore/reducers/exploreReducer.js +++ b/superset-frontend/src/explore/reducers/exploreReducer.js @@ -72,19 +72,6 @@ export default function exploreReducer(state = {}, action) { isDatasourcesLoading: true, }; }, - [actions.FETCH_DATASOURCES_SUCCEEDED]() { - return { - ...state, - isDatasourcesLoading: false, - }; - }, - [actions.FETCH_DATASOURCES_FAILED]() { - return { - ...state, - isDatasourcesLoading: false, - controlPanelAlert: action.error, - }; - }, [actions.SET_DATASOURCES]() { return { ...state, diff --git a/superset-frontend/src/messageToasts/actions/index.js b/superset-frontend/src/messageToasts/actions/index.ts similarity index 64% rename from superset-frontend/src/messageToasts/actions/index.js rename to superset-frontend/src/messageToasts/actions/index.ts index bfed0472b6..4eeb2e12d5 100644 --- a/superset-frontend/src/messageToasts/actions/index.js +++ b/superset-frontend/src/messageToasts/actions/index.ts @@ -17,20 +17,18 @@ * under the License. */ import shortid from 'shortid'; +import { ToastType, ToastMeta } from '../types'; -import { - INFO_TOAST, - SUCCESS_TOAST, - WARNING_TOAST, - DANGER_TOAST, -} from '../constants'; - -export function getToastUuid(type) { +export function getToastUuid(type: ToastType) { return `${type}-${shortid.generate()}`; } export const ADD_TOAST = 'ADD_TOAST'; -export function addToast({ toastType, text, duration = 8000 }) { +export function addToast({ + toastType, + text, + duration = 8000, +}: Omit) { return { type: ADD_TOAST, payload: { @@ -43,7 +41,7 @@ export function addToast({ toastType, text, duration = 8000 }) { } export const REMOVE_TOAST = 'REMOVE_TOAST'; -export function removeToast(id) { +export function removeToast(id: string) { return { type: REMOVE_TOAST, payload: { @@ -54,25 +52,21 @@ export function removeToast(id) { // Different types of toasts export const ADD_INFO_TOAST = 'ADD_INFO_TOAST'; -export function addInfoToast(text) { - return dispatch => - dispatch(addToast({ text, toastType: INFO_TOAST, duration: 4000 })); +export function addInfoToast(text: string) { + return addToast({ text, toastType: ToastType.INFO, duration: 4000 }); } export const ADD_SUCCESS_TOAST = 'ADD_SUCCESS_TOAST'; -export function addSuccessToast(text) { - return dispatch => - dispatch(addToast({ text, toastType: SUCCESS_TOAST, duration: 4000 })); +export function addSuccessToast(text: string) { + return addToast({ text, toastType: ToastType.SUCCESS, duration: 4000 }); } export const ADD_WARNING_TOAST = 'ADD_WARNING_TOAST'; -export function addWarningToast(text) { - return dispatch => - dispatch(addToast({ text, toastType: WARNING_TOAST, duration: 6000 })); +export function addWarningToast(text: string) { + return addToast({ text, toastType: ToastType.WARNING, duration: 6000 }); } export const ADD_DANGER_TOAST = 'ADD_DANGER_TOAST'; -export function addDangerToast(text) { - return dispatch => - dispatch(addToast({ text, toastType: DANGER_TOAST, duration: 8000 })); +export function addDangerToast(text: string) { + return addToast({ text, toastType: ToastType.DANGER, duration: 8000 }); } diff --git a/superset-frontend/src/messageToasts/components/Toast.tsx b/superset-frontend/src/messageToasts/components/Toast.tsx index 5b06fa68b9..f9b9bf7f05 100644 --- a/superset-frontend/src/messageToasts/components/Toast.tsx +++ b/superset-frontend/src/messageToasts/components/Toast.tsx @@ -20,11 +20,10 @@ import { Alert } from 'react-bootstrap'; import { styled } from '@superset-ui/core'; import cx from 'classnames'; import Interweave from 'interweave'; -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import Icon from 'src/components/Icon'; -import { ToastType } from 'src/messageToasts/types'; - -import { SUCCESS_TOAST, WARNING_TOAST, DANGER_TOAST } from '../constants'; +import { ToastType } from 'src/messageToasts/constants'; +import { ToastMeta } from '../types'; const ToastContianer = styled.div` display: flex; @@ -37,19 +36,21 @@ const ToastContianer = styled.div` `; interface ToastPresenterProps { - toast: { id: string; toastType: ToastType; text: string; duration: number }; + toast: ToastMeta; onCloseToast: (id: string) => void; } export default function Toast({ toast, onCloseToast }: ToastPresenterProps) { - let hideTimer: ReturnType; + const hideTimer = useRef>(); const [visible, setVisible] = useState(false); const showToast = () => { setVisible(true); }; - const handleClosePress = () => { - clearTimeout(hideTimer); + const handleClosePress = useCallback(() => { + if (hideTimer.current) { + clearTimeout(hideTimer.current); + } // Wait for the transition setVisible(() => { setTimeout(() => { @@ -57,18 +58,20 @@ export default function Toast({ toast, onCloseToast }: ToastPresenterProps) { }, 150); return false; }); - }; + }, [onCloseToast, toast.id]); useEffect(() => { setTimeout(showToast); if (toast.duration > 0) { - hideTimer = setTimeout(handleClosePress, toast.duration); + hideTimer.current = setTimeout(handleClosePress, toast.duration); } return () => { - clearTimeout(hideTimer); + if (hideTimer.current) { + clearTimeout(hideTimer.current); + } }; - }, []); + }, [handleClosePress, toast.duration]); return ( - {toast.toastType === SUCCESS_TOAST && ( + {toast.toastType === ToastType.SUCCESS && ( )} - {toast.toastType === WARNING_TOAST || - (toast.toastType === DANGER_TOAST && )} + {toast.toastType === ToastType.WARNING || + (toast.toastType === ToastType.DANGER && )} diff --git a/superset-frontend/src/messageToasts/components/ToastPresenter.tsx b/superset-frontend/src/messageToasts/components/ToastPresenter.tsx index 4ce4898418..aba922c10c 100644 --- a/superset-frontend/src/messageToasts/components/ToastPresenter.tsx +++ b/superset-frontend/src/messageToasts/components/ToastPresenter.tsx @@ -18,7 +18,7 @@ */ import React from 'react'; import { styled } from '@superset-ui/core'; -import { ToastType } from 'src/messageToasts/types'; +import { ToastMeta } from 'src/messageToasts/types'; import Toast from './Toast'; const StyledToastPresenter = styled.div` @@ -67,25 +67,22 @@ const StyledToastPresenter = styled.div` } `; -type ToastShape = { - id: string; - toastType: ToastType; - text: string; - duration: number; +type ToastPresenterProps = { + toasts: Array; + removeToast: () => void; }; -interface ToastPresenterProps { - toasts: Array; - removeToast: () => void; -} - -const ToastPresenter = ({ toasts, removeToast }: ToastPresenterProps) => - toasts.length > 0 && ( - - {toasts.map(toast => ( - - ))} - +export default function ToastPresenter({ + toasts, + removeToast, +}: ToastPresenterProps) { + return ( + toasts.length > 0 && ( + + {toasts.map(toast => ( + + ))} + + ) ); - -export default ToastPresenter; +} diff --git a/superset-frontend/src/messageToasts/constants.js b/superset-frontend/src/messageToasts/constants.ts similarity index 74% rename from superset-frontend/src/messageToasts/constants.js rename to superset-frontend/src/messageToasts/constants.ts index 91f41c41b2..e22616c8a5 100644 --- a/superset-frontend/src/messageToasts/constants.js +++ b/superset-frontend/src/messageToasts/constants.ts @@ -17,7 +17,12 @@ * under the License. */ // Toast types -export const INFO_TOAST = 'INFO_TOAST'; -export const SUCCESS_TOAST = 'SUCCESS_TOAST'; -export const WARNING_TOAST = 'WARNING_TOAST'; -export const DANGER_TOAST = 'DANGER_TOAST'; +import { ToastType } from './types'; + +export { ToastType } from './types'; + +// for backward compatibility +export const INFO_TOAST = ToastType.INFO; +export const SUCCES_TOAST = ToastType.SUCCESS; +export const WARNING_TOAST = ToastType.WARNING; +export const DANGER_TOAST = ToastType.DANGER; diff --git a/superset-frontend/src/messageToasts/propShapes.js b/superset-frontend/src/messageToasts/propShapes.js deleted file mode 100644 index 0ce2aea41b..0000000000 --- a/superset-frontend/src/messageToasts/propShapes.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import PropTypes from 'prop-types'; - -import { - INFO_TOAST, - SUCCESS_TOAST, - WARNING_TOAST, - DANGER_TOAST, -} from './constants'; - -// eslint-disable-next-line import/prefer-default-export -export const toastShape = PropTypes.shape({ - id: PropTypes.string.isRequired, - toastType: PropTypes.oneOf([ - INFO_TOAST, - SUCCESS_TOAST, - WARNING_TOAST, - DANGER_TOAST, - ]).isRequired, - text: PropTypes.string.isRequired, - duration: PropTypes.number, -}); diff --git a/superset-frontend/src/messageToasts/types.ts b/superset-frontend/src/messageToasts/types.ts index 471a3a0ac6..0a72ec39b7 100644 --- a/superset-frontend/src/messageToasts/types.ts +++ b/superset-frontend/src/messageToasts/types.ts @@ -16,9 +16,16 @@ * specific language governing permissions and limitations * under the License. */ +export enum ToastType { + INFO = 'INFO_TOAST', + SUCCESS = 'SUCCESS_TOAST', + WARNING = 'WARNING_TOAST', + DANGER = 'DANGER_TOAST', +} -export type ToastType = - | 'INFO_TOAST' - | 'SUCCESS_TOAST' - | 'WARNING_TOAST' - | 'DANGER_TOAST'; +export interface ToastMeta { + id: string; + toastType: ToastType; + text: string; + duration: number; +} diff --git a/superset-frontend/src/messageToasts/utils/getToastsFromPyFlashMessages.js b/superset-frontend/src/messageToasts/utils/getToastsFromPyFlashMessages.js index 26fe7b713b..6f921c4953 100644 --- a/superset-frontend/src/messageToasts/utils/getToastsFromPyFlashMessages.js +++ b/superset-frontend/src/messageToasts/utils/getToastsFromPyFlashMessages.js @@ -17,7 +17,7 @@ * under the License. */ import { addToast } from '../actions'; -import { INFO_TOAST, SUCCESS_TOAST, DANGER_TOAST } from '../constants'; +import { ToastType } from '../constants'; export default function toastsFromPyFlashMessages(flashMessages = []) { const toasts = []; @@ -25,8 +25,8 @@ export default function toastsFromPyFlashMessages(flashMessages = []) { flashMessages.forEach(([messageType, message]) => { const toastType = messageType === 'danger' - ? DANGER_TOAST - : (messageType === 'success' && SUCCESS_TOAST) || INFO_TOAST; + ? ToastType.DANGER + : (messageType === 'success' && ToastType.SUCCESS) || ToastType.INFO; const toast = addToast({ text: message, diff --git a/superset-frontend/src/types/Chart.ts b/superset-frontend/src/types/Chart.ts index e78d81007b..5148d32d0b 100644 --- a/superset-frontend/src/types/Chart.ts +++ b/superset-frontend/src/types/Chart.ts @@ -37,3 +37,11 @@ export default interface Chart { owners?: Owner[]; datasource_name_text?: string; } + +export type Slice = { + id?: number; + slice_id: number; + slice_name: string; + description: string | null; + cache_timeout: number | null; +}; diff --git a/superset-frontend/src/views/CRUD/chart/ChartList.tsx b/superset-frontend/src/views/CRUD/chart/ChartList.tsx index 4323f4694c..a22c54d24d 100644 --- a/superset-frontend/src/views/CRUD/chart/ChartList.tsx +++ b/superset-frontend/src/views/CRUD/chart/ChartList.tsx @@ -34,8 +34,8 @@ import ListView, { SelectOption, } from 'src/components/ListView'; import withToasts from 'src/messageToasts/enhancers/withToasts'; -import PropertiesModal, { Slice } from 'src/explore/components/PropertiesModal'; -import Chart from 'src/types/Chart'; +import PropertiesModal from 'src/explore/components/PropertiesModal'; +import Chart, { Slice } from 'src/types/Chart'; import ListViewCard from 'src/components/ListViewCard'; import Label from 'src/components/Label'; import { Dropdown, Menu } from 'src/common/components';