diff --git a/presto-ui/bin/check_webui.sh b/presto-ui/bin/check_webui.sh index a669dc5cd4fa7..92e56ebcdfde8 100755 --- a/presto-ui/bin/check_webui.sh +++ b/presto-ui/bin/check_webui.sh @@ -29,10 +29,10 @@ fi popd -# Fail on flow warnings +# Fail on typescript warnings -if ! yarn --cwd ${WEBUI_ROOT}/ run flow; then - echo "ERROR: Flow found type errors while performing static analysis" +if ! yarn --cwd ${WEBUI_ROOT}/ run typecheck; then + echo "ERROR: Typescript type errors found" exit 1 fi diff --git a/presto-ui/src/components/LivePlan.jsx b/presto-ui/src/components/LivePlan.tsx similarity index 91% rename from presto-ui/src/components/LivePlan.jsx rename to presto-ui/src/components/LivePlan.tsx index 69b54e12bdd6e..86489abb68310 100644 --- a/presto-ui/src/components/LivePlan.jsx +++ b/presto-ui/src/components/LivePlan.tsx @@ -11,7 +11,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -//@flow import React, { useState, useEffect, useRef, useCallback } from "react"; import ReactDOMServer from "react-dom/server"; @@ -23,27 +22,27 @@ import { initializeGraph, initializeSvg } from "../d3utils"; import { QueryHeader } from "./QueryHeader"; type StageStatisticsProps = { - stage: any, + stage: any; }; export type StageNodeInfo = { - stageId: string, - id: string, - root: string, - distribution: any, - stageStats: any, - state: string, - nodes: Map, + stageId: string; + id: string; + root: string; + distribution: any; + stageStats: any; + state: string; + nodes: Map; }; type OutputStage = { - subStages: any, - stageId: string, - latestAttemptExecutionInfo: any, - plan: any, + subStages: any; + stageId: string; + latestAttemptExecutionInfo: any; + plan: any; }; type QueryInfo = { - outputStage: OutputStage, + outputStage: OutputStage; }; function getStages(queryInfo: QueryInfo): Map { @@ -86,7 +85,7 @@ function flattenNode(stages: any, rootNodeInfo: any, node: any, result: Map { +export const StageStatistics = (props: StageStatisticsProps): React.ReactElement => { const { stage } = props; const stats = stage.stageStats; return ( @@ -121,15 +120,15 @@ export const StageStatistics = (props: StageStatisticsProps): React.Node => { StageStatistics.getStages = getStages; type PlanNodeProps = { - id: string, - name: string, - identifier: string, - details: string, - sources: string[], - remoteSources: string[], + id: string; + name: string; + identifier: string; + details: string; + sources: string[]; + remoteSources: string[]; }; -export const PlanNode = (props: PlanNodeProps): React.Node => { +export const PlanNode = (props: PlanNodeProps): React.ReactElement => { return (
{ }; type LivePlanProps = { - queryId: string, - isEmbedded: boolean, + queryId: string; + isEmbedded: boolean; }; type LivePlanState = { - initialized: boolean, - ended: boolean, - query: ?any, + initialized: boolean; + ended: boolean; + query: any | null | undefined; }; -export const LivePlan = (props: LivePlanProps): React.Node => { +export const LivePlan = (props: LivePlanProps): React.ReactElement => { const [state, setState] = useState({ initialized: false, ended: false, query: null, }); - const timeoutId = useRef(null); + const timeoutId = useRef(null); const graphRef = useRef(initializeGraph()); - // $FlowFixMe: Flow is not recognizing the SVGSVGElement type const svgRef = useRef(null); - const renderRef = useRef(new dagreD3.render()); + const renderRef = useRef(dagreD3.render()); const refreshLoop: () => void = useCallback(() => { clearTimeout(timeoutId.current); // to stop multiple series of refreshLoop from going on simultaneously @@ -179,7 +177,7 @@ export const LivePlan = (props: LivePlanProps): React.Node => { if (ended) { clearTimeout(timeoutId.current); } else { - timeoutId.current = setTimeout(refreshLoop, 1000); + timeoutId.current = window.setTimeout(refreshLoop, 1000); } return { ...prevState, @@ -194,7 +192,7 @@ export const LivePlan = (props: LivePlanProps): React.Node => { ...prevState, initialized: true, })); - timeoutId.current = setTimeout(refreshLoop, 1000); + timeoutId.current = window.setTimeout(refreshLoop, 1000); }); }, [props.queryId]); @@ -322,7 +320,7 @@ export const LivePlan = (props: LivePlanProps): React.Node => { useEffect(() => { updateD3Graph(); - //$FlowFixMe + // @ts-expect-error - Bootstrap tooltip plugin not in jQuery types $('[data-bs-toggle="tooltip"]')?.tooltip?.(); }, [state.query, state.ended]); diff --git a/presto-ui/src/components/PageTitle.jsx b/presto-ui/src/components/PageTitle.tsx similarity index 92% rename from presto-ui/src/components/PageTitle.jsx rename to presto-ui/src/components/PageTitle.tsx index 8c5fa69f436e8..ea3f79fed52ce 100644 --- a/presto-ui/src/components/PageTitle.jsx +++ b/presto-ui/src/components/PageTitle.tsx @@ -11,23 +11,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -//@flow import React, { useState, useEffect, useRef } from "react"; type Props = { - titles: string[], - urls?: string[], - current?: number, - path?: string, + titles: string[]; + urls?: string[]; + current?: number; + path?: string; }; type State = { - noConnection: boolean, - lightShown: boolean, - info: ?any, - lastSuccess: number, - modalShown: boolean, - errorText: ?string, + noConnection: boolean; + lightShown: boolean; + info: any | null | undefined; + lastSuccess: number; + modalShown: boolean; + errorText: string | null | undefined; }; const ClusterResourceGroupNavBar = ({ titles, urls, current = 0 }: Props) => { @@ -50,7 +49,7 @@ const isOffline = () => { return window.location.protocol === "file:"; }; -export const PageTitle = (props: Props): React.Node => { +export const PageTitle = (props: Props): React.ReactElement => { const [state, setState] = useState({ noConnection: false, lightShown: false, @@ -60,7 +59,7 @@ export const PageTitle = (props: Props): React.Node => { errorText: null, }); - const timeoutId = useRef(null); + const timeoutId = useRef(null); const refreshLoop = () => { clearTimeout(timeoutId.current); @@ -74,9 +73,8 @@ export const PageTitle = (props: Props): React.Node => { lastSuccess: Date.now(), modalShown: false, })); - //$FlowFixMe$ Bootstrap 5 plugin $("#no-connection-modal").hide(); - timeoutId.current = setTimeout(refreshLoop, 1000); + timeoutId.current = window.setTimeout(refreshLoop, 1000); }) .catch((error) => { setState((prevState) => { @@ -87,11 +85,11 @@ export const PageTitle = (props: Props): React.Node => { !prevState.modalShown && (error || Date.now() - prevState.lastSuccess > 30 * 1000); if (shouldShowModal) { - //$FlowFixMe$ Bootstrap 5 plugin + // @ts-expect-error - Bootstrap modal plugin not in jQuery types $("#no-connection-modal").modal("show"); } - timeoutId.current = setTimeout(refreshLoop, 1000); + timeoutId.current = window.setTimeout(refreshLoop, 1000); return { ...prevState, @@ -207,7 +205,7 @@ export const PageTitle = (props: Props): React.Node => {
-