From 866a9e4c37473b4a35f039a7ead474705ef94bb4 Mon Sep 17 00:00:00 2001
From: Alicia Underhill <31083146+uhLeeshUh@users.noreply.github.com>
Date: Wed, 15 Jul 2020 16:01:59 -0600
Subject: [PATCH] feat(migration components): add migration components to
conditionally render on app-launch
create `IncompatibleBackend`, `MigratingBackend` and `MigrationFailed` components to run on app-launch. Create `ReportCrashAndReload` component to handle crash report, issue filing and reload functionality and refactor `ErrorHandler` to use this
---
app/components/ErrorHandler.tsx | 99 ++-----------------------
app/components/IncompatibleBackend.tsx | 20 +++++
app/components/MigratingBackend.tsx | 8 ++
app/components/MigrationFailed.tsx | 6 ++
app/components/ReportCrashAndReload.tsx | 90 ++++++++++++++++++++++
stories/AppLaunch.stories.tsx | 33 +++++++++
stories/Error.stories.tsx | 27 +++++++
7 files changed, 192 insertions(+), 91 deletions(-)
create mode 100644 app/components/IncompatibleBackend.tsx
create mode 100644 app/components/MigratingBackend.tsx
create mode 100644 app/components/MigrationFailed.tsx
create mode 100644 app/components/ReportCrashAndReload.tsx
create mode 100644 stories/AppLaunch.stories.tsx
create mode 100644 stories/Error.stories.tsx
diff --git a/app/components/ErrorHandler.tsx b/app/components/ErrorHandler.tsx
index ba31aaf4..60d830e9 100644
--- a/app/components/ErrorHandler.tsx
+++ b/app/components/ErrorHandler.tsx
@@ -1,28 +1,16 @@
import React from 'react'
-import versions from '../../version'
-import { CRASH_REPORTER_URL } from '../constants'
+import ReportCrashAndReload, { ErrorProps } from './ReportCrashAndReload'
import localStore from '../utils/localStore'
-import ExternalLink from './ExternalLink'
-import Button from './chrome/Button'
export default class ErrorHandler extends React.Component {
state = {
error: undefined,
- errorInfo: undefined,
- sendingReport: false,
- sentReport: false
+ errorInfo: undefined
}
- constructor (props) {
- super(props)
-
- this.handleSendCrashReport = this.handleSendCrashReport.bind(this)
- this.handleReload = this.handleReload.bind(this)
- }
-
- componentDidCatch (error, errorInfo) {
- this.setState({ error, errorInfo, sendingReport: false })
+ componentDidCatch (error: ErrorProps['error'], errorInfo: ErrorProps['errorInfo']) {
+ this.setState({ error, errorInfo })
// clear local storage, which may cause re-crashing if in an error put us
// into an un-recoverable state
@@ -33,87 +21,16 @@ export default class ErrorHandler extends React.Component {
localStore().setItem('commitComponent', '')
}
- handleSendCrashReport (e: React.MouseEvent) {
- const { error, errorInfo } = this.state
- this.setState({ error, errorInfo, sendingReport: true })
-
- console.log('sending report')
- postCrashReport(error, errorInfo)
- .then(() => {
- this.setState({
- sentReport: true,
- sendingReport: false
- })
- })
- .catch((e) => {
- console.log(e)
- this.setState({
- sendingReport: false
- })
- })
- }
-
- handleReload (e: React.MouseEvent) {
- window.location.hash = '/'
- window.location.reload()
- }
-
render () {
if (!this.state.error) {
return this.props.children
}
- const { sendingReport, sentReport } = this.state
-
return (
-
-
-
Dang. It broke.
-
Apologies, Qri desktop encountered an error. Send us a crash report!
-
- {sentReport
- ?
Thanks!
- : }
-
-
-
If you have additional info or questions, feel free to file an issue describing where things went wrong. The more detail, the better. Reload to get back to Qri.
-
-
-
-
+
)
}
}
-
-// TODO (b5) - bring this back in the near future for fetching home feed
-async function postCrashReport (err, errInfo): Promise {
- const options: FetchOptions = {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- app: 'desktop',
- version: versions.desktopVersion,
- platform: navigator.platform,
- error: err.toString(),
- info: errInfo.componentStack
- })
- }
-
- console.log(CRASH_REPORTER_URL)
- const r = await fetch(CRASH_REPORTER_URL, options)
- const res = await r.json()
- return res
-}
diff --git a/app/components/IncompatibleBackend.tsx b/app/components/IncompatibleBackend.tsx
new file mode 100644
index 00000000..9c7681ef
--- /dev/null
+++ b/app/components/IncompatibleBackend.tsx
@@ -0,0 +1,20 @@
+import React from 'react'
+import WelcomeTemplate from './onboard/WelcomeTemplate'
+import ExternalLink from './ExternalLink'
+
+interface IncompatibleBackendProps {
+ incompatibleVersion: string
+}
+
+// TODO: this variable needs to be replaced when the
+// lowestCompatibleBackend variable exists in backend.js
+const lowestCompatibleBackend = '0.9.8'
+
+const IncompatibleBackend: React.FC = ({ incompatibleVersion }) => (
+
+
{`The lowest supported backend version is v${lowestCompatibleBackend}, but you are running on v${incompatibleVersion}.`}
Apologies, Qri desktop encountered an error. Send us a crash report!
+ {sentReport
+ ?
Thanks!
+ : }
+
+
+
+
If you have additional info or questions, feel free to file an issue describing where things went wrong. The more detail, the better. Reload to get back to Qri.
+
+
+
+ )
+}
+
+// TODO (b5) - bring this back in the near future for fetching home feed
+const postCrashReport = async (error: ErrorProps['error'], errorInfo: ErrorProps['errorInfo']): Promise => {
+ const options: FetchOptions = {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ app: 'desktop',
+ version: versions.desktopVersion,
+ platform: navigator.platform,
+ error: error?.toString(),
+ info: errorInfo?.componentStack
+ })
+ }
+
+ console.log(CRASH_REPORTER_URL)
+ const r = await fetch(CRASH_REPORTER_URL, options)
+ const res = await r.json()
+ return res
+}
+
+export default ReportCrashAndReload
diff --git a/stories/AppLaunch.stories.tsx b/stories/AppLaunch.stories.tsx
new file mode 100644
index 00000000..12a0172d
--- /dev/null
+++ b/stories/AppLaunch.stories.tsx
@@ -0,0 +1,33 @@
+import React from 'react'
+
+import IncompatibleBackend from '../app/components/IncompatibleBackend'
+import MigratingBackend from '../app/components/MigratingBackend'
+import MigrationFailed from '../app/components/MigrationFailed'
+
+export default {
+ title: 'App Launch',
+ parameters: {
+ notes: 'List of migration components conditionally rendered on app launch'
+ }
+}
+
+export const incompatibleBackend = () => ()
+
+incompatibleBackend.story = {
+ name: 'Incompatible Backend',
+ parameters: { note: 'Screen when user is running an incompatible backend qri version' }
+}
+
+export const migratingBackend = () =>
+
+migratingBackend.story = {
+ name: 'Migrating Backend',
+ parameters: { note: 'Screen when backend is in the process of migrating' }
+}
+
+export const migrationFailed = () =>
+
+migrationFailed.story = {
+ name: 'Migration Failed',
+ parameters: { note: 'Screen when backend migration has failed' }
+}
\ No newline at end of file
diff --git a/stories/Error.stories.tsx b/stories/Error.stories.tsx
new file mode 100644
index 00000000..9d5c2d38
--- /dev/null
+++ b/stories/Error.stories.tsx
@@ -0,0 +1,27 @@
+import React from 'react'
+
+import ReportCrashAndReload from '../app/components/ReportCrashAndReload'
+
+export default {
+ title: 'Error',
+ parameters: {
+ notes: 'Application error handling'
+ }
+}
+
+const reportCrashAndReloadProps = {
+ title: 'Storybook test has crashed',
+ error: new Error('Test error for Storybook!'),
+ errorInfo: {
+ componentStack: `in ComponentThatThrows (created by App)
+ in ErrorBoundary (created by App)
+ in div (created by App)
+ in App` }
+}
+
+export const reportCrashAndReload = () => ()
+
+reportCrashAndReload.story = {
+ name: 'Report Crash and Reload',
+ parameters: { note: 'Screen when app throws an error and is caught. Prompts error report, issue and reload CTAs' }
+}
\ No newline at end of file