From 715b42f7f27cae0181ac8d3dc1b5aa54a0a84376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Thu, 24 Oct 2019 21:00:50 +0100 Subject: [PATCH] chore(ui): migrate App component to typescript --- ui/src/{App.js => App.tsx} | 38 +++++------ ui/src/ErrorBoundary.test.js | 2 +- .../{ErrorBoundary.js => ErrorBoundary.tsx} | 63 +++++++++++-------- 3 files changed, 59 insertions(+), 44 deletions(-) rename ui/src/{App.js => App.tsx} (76%) rename ui/src/{ErrorBoundary.js => ErrorBoundary.tsx} (60%) diff --git a/ui/src/App.js b/ui/src/App.tsx similarity index 76% rename from ui/src/App.js rename to ui/src/App.tsx index c2adfeb6d..3a1906491 100644 --- a/ui/src/App.js +++ b/ui/src/App.tsx @@ -1,5 +1,4 @@ import React, { Component } from "react"; -import PropTypes from "prop-types"; import { Provider } from "mobx-react"; @@ -14,24 +13,27 @@ import { ErrorBoundary } from "./ErrorBoundary"; import "./App.scss"; -class App extends Component { - static propTypes = { - defaultFilters: PropTypes.arrayOf(PropTypes.string).isRequired, - uiDefaults: PropTypes.exact({ - Refresh: PropTypes.number.isRequired, - HideFiltersWhenIdle: PropTypes.bool.isRequired, - ColorTitlebar: PropTypes.bool.isRequired, - MinimalGroupWidth: PropTypes.number.isRequired, - AlertsPerGroup: PropTypes.number.isRequired, - CollapseGroups: PropTypes.oneOf([ - "expanded", - "collapsed", - "collapsedOnMobile" - ]).isRequired - }) - }; +interface UIDefaults { + Refresh: number; + HideFiltersWhenIdle: boolean; + ColorTitlebar: boolean; + MinimalGroupWidth: number; + AlertsPerGroup: number; + CollapseGroups: "expanded" | "collapsed" | "collapsedOnMobile"; +} - constructor(props) { +interface AppProps { + defaultFilters: Array; + uiDefaults: UIDefaults; +} + +class App extends Component { + alertStore: AlertStore; + silenceFormStore: SilenceFormStore; + settingsStore: Settings; + filters: Array = []; + + constructor(props: AppProps) { super(props); const { defaultFilters, uiDefaults } = this.props; diff --git a/ui/src/ErrorBoundary.test.js b/ui/src/ErrorBoundary.test.js index 5ef9ed1e7..c0e298435 100644 --- a/ui/src/ErrorBoundary.test.js +++ b/ui/src/ErrorBoundary.test.js @@ -52,7 +52,7 @@ describe("", () => { }); it("componentDidCatch passes scope to sentry", () => { - const sentrySpy = jest.spyOn(Sentry, "configureScope"); + const sentrySpy = jest.spyOn(Sentry, "captureException"); Sentry.init({ dsn: "https://foobar@localhost/123456" }); const tree = mount( diff --git a/ui/src/ErrorBoundary.js b/ui/src/ErrorBoundary.tsx similarity index 60% rename from ui/src/ErrorBoundary.js rename to ui/src/ErrorBoundary.tsx index 0b4e0d003..390ac0521 100644 --- a/ui/src/ErrorBoundary.js +++ b/ui/src/ErrorBoundary.tsx @@ -1,12 +1,22 @@ -import React, { Component } from "react"; -import PropTypes from "prop-types"; +import React, { + Component, + StatelessComponent, + ReactNode, + ErrorInfo +} from "react"; import * as Sentry from "@sentry/browser"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faBomb } from "@fortawesome/free-solid-svg-icons/faBomb"; -const InternalError = ({ message, secondsLeft, progressLeft }) => ( +interface InternalErrorProps { + message: ReactNode; + secondsLeft: number; + progressLeft: number; +} + +const InternalError: StatelessComponent = props => (

@@ -14,10 +24,10 @@ const InternalError = ({ message, secondsLeft, progressLeft }) => ( Internal error

- {message} + {props.message}

- This page will auto refresh in {secondsLeft}s + This page will auto refresh in {props.secondsLeft}s (

); -InternalError.propTypes = { - message: PropTypes.node.isRequired, - secondsLeft: PropTypes.number.isRequired, - progressLeft: PropTypes.number.isRequired -}; -class ErrorBoundary extends Component { - static propTypes = { - children: PropTypes.any +interface ErrorBoundaryProps { + children: React.ReactNode; +} + +interface ErrorBoundaryState { + cachedError: Error | null; + reloadSeconds: number; +} + +class ErrorBoundary extends Component { + timer: ReturnType | null; + state: Readonly = { + cachedError: null, + reloadSeconds: 60 }; - constructor(props) { + constructor(props: ErrorBoundaryProps) { super(props); this.timer = null; - this.state = { cachedError: null, reloadSeconds: 60 }; } reloadApp = () => { @@ -60,14 +75,12 @@ class ErrorBoundary extends Component { } }; - componentDidCatch(error, errorInfo) { + componentDidCatch(error: Error | null, errorInfo: ErrorInfo) { this.setState({ cachedError: error }); - Sentry.configureScope(scope => { - Object.keys(errorInfo).forEach(key => { - scope.setExtra(key, errorInfo[key]); - }); + Sentry.withScope(scope => { + scope.setExtras(errorInfo); + Sentry.captureException(error); }); - Sentry.captureException(error); // reload after 60s, this is to fix wall monitors automatically // but only if the timer isn't set yet if (this.timer === null) {