8000 add error handling to web app · phptuts/coderoad-vscode@9274d0b · GitHub
[go: up one dir, main page]

Skip to content

Commit 9274d0b

Browse files
committed
add error handling to web app
1 parent 34f8059 commit 9274d0b

File tree

8 files changed

+50
-15
lines changed
  • 8 files changed

    +50
    -15
    lines changed

    web-app/src/components/Error/index.tsx

    Lines changed: 7 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -2,6 +2,7 @@ import { ApolloError } from 'apollo-boost'
    22
    import { GraphQLError } from 'graphql'
    33
    import * as React from 'react'
    44
    import { css, jsx } from '@emotion/core'
    5+
    import onError from 'services/sentry/onError'
    56

    67
    const styles = {
    78
    container: {
    @@ -16,7 +17,12 @@ interface Props {
    1617
    }
    1718

    1819
    const ErrorView = ({ error }: Props) => {
    19-
    console.log(error)
    20+
    // log error
    21+
    React.useEffect(() => {
    22+
    console.log(error)
    23+
    onError(error)
    24+
    }, [])
    25+
    2026
    return (
    2127
    <div css={styles.container}>
    2228
    <h1>Error</h1>

    web-app/src/components/ErrorBoundary/index.tsx

    Lines changed: 6 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,20 +1,22 @@
    11
    import * as React from 'react'
    2+
    import onError from '../../services/sentry/onError'
    23

    34
    class ErrorBoundary extends React.Component {
    4-
    public state = { hasError: false }
    5+
    public state = { errorMessage: null }
    56

    67
    public componentDidCatch(error: Error, info: any) {
    8+
    onError(error)
    79
    // Display fallback UI
    8-
    this.setState({ hasError: true })
    10+
    this.setState({ errorMessage: error.message })
    911
    // You can also log the error to an error reporting service
    1012
    console.error(JSON.stringify(error))
    1113
    console.log(JSON.stringify(info))
    1214
    }
    1315

    1416
    public render() {
    15-
    if (this.state.hasError) {
    17+
    if (this.state.errorMessage) {
    1618
    // You can render any custom fallback UI
    17-
    return <h1>Something went wrong.</h1>
    19+
    return <h1>{this.state.errorMessage}</h1>
    1820
    }
    1921
    return this.props.children
    2022
    }

    web-app/src/components/Markdown/index.tsx

    Lines changed: 4 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -4,6 +4,7 @@ import markdownEmoji from 'markdown-it-emoji'
    44
    // @ts-ignore no types for package
    55
    import prism from 'markdown-it-prism'
    66
    import * as React from 'react'
    7+
    import onError from '../../services/sentry/onError'
    78
    // load prism styles & language support
    89
    import './prism'
    910

    @@ -56,7 +57,9 @@ const Markdown = (props: Props) => {
    5657
    try {
    5758
    html = md.render(props.children)
    5859
    } catch (error) {
    59-
    console.log(`failed to parse markdown for ${props.children}`)
    60+
    const message = `failed to parse markdown for ${props.children}`
    61+
    onError(new Error(message))
    62+
    console.log(message)
    6063
    html = `<div style='background-color: #FFB81A; padding: 0.5rem;'>
    6164
    <strong style='padding-bottom: 0.5rem;'>ERROR: Failed to parse markdown</strong>
    6265
    <p>${props.children}</p>

    web-app/src/components/Router/index.tsx

    Lines changed: 4 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -6,6 +6,7 @@ import machine from '../../services/state/machine'
    66
    import { useMachine } from '../../services/xstate-react'
    77
    import debuggerWrapper from '../Debugger/debuggerWrapper'
    88
    import Route from './Route'
    9+
    import onError from 'services/sentry/onError'
    910

    1011
    interface Props {
    1112
    children: any
    @@ -45,7 +46,9 @@ const Router = ({ children }: Props): React.ReactElement<CloneElementProps> | nu
    4546
    return debuggerWrapper(element, state)
    4647
    }
    4748
    }
    48-
    console.warn(`No Route matches for ${JSON.stringify(state)}`)
    49+
    const message = `No Route matches for ${JSON.stringify(state)}`
    50+
    onError(new Error(message))
    51+
    console.warn(message)
    4952
    return 10000 null
    5053
    }
    5154

    web-app/src/services/selectors/tutorial.ts

    Lines changed: 13 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,17 +1,22 @@
    11
    import { createSelector } from 'reselect'
    22
    import { MachineContext } from 'typings'
    33
    import * as G from 'typings/graphql'
    4+
    import onError from 'services/sentry/onError'
    45

    56
    export const currentTutorial = ({ tutorial }: MachineContext): G.Tutorial => {
    67
    if (!tutorial) {
    7-
    throw new Error('Tutorial not found')
    8+
    const error = new Error('Tutorial not found')
    9+
    onError(error)
    10+
    throw error
    811
    }
    912
    return tutorial
    1013
    }
    1114

    1215
    export const currentVersion = createSelector(currentTutorial, (tutorial: G.Tutorial) => {
    1316
    if (!tutorial.version) {
    14-
    throw new Error('Tutorial version not found')
    17+
    const error = new Error('Tutorial version not found')
    18+
    onError(error)
    19+
    throw error
    1520
    }
    1621
    return tutorial.version
    1722
    })
    @@ -26,7 +31,9 @@ export const currentLevel = (context: MachineContext): G.Level =>
    2631

    2732
    const levelIndex = levels.findIndex((l: G.Level) => l.id === context.position.levelId)
    2833
    if (levelIndex < 0) {
    29-
    throw new Error('Level not found when selecting level')
    34+
    const error = new Error(`Level not found when selecting level for ${version}`)
    35+
    onError(error)
    36+
    throw error
    3037
    }
    3138
    const level: G.Level = levels[levelIndex]
    3239

    @@ -41,7 +48,9 @@ export const currentStep = (context: MachineContext): G.Step =>
    4148
    const steps: G.Step[] = level.steps
    4249
    const step: G.Step | undefined = steps.find((s: G.Step) => s.id === context.position.stepId)
    4350
    if (!step) {
    44-
    throw new Error('No Step found')
    51+
    const error = new Error(`No Step found for Level ${level.id}. Expected step ${context.position.stepId}`)
    52+
    onError(error)
    53+
    throw error
    4554
    }
    4655
    return step
    4756
    },

    web-app/src/services/state/actions/api.ts

    Lines changed: 2 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -4,6 +4,7 @@ import client from '../../apollo'
    44
    import { setAuthToken } from '../../apollo/auth'
    55
    import authenticateMutation from '../../apollo/mutations/authenticate'
    66
    import channel from '../../channel'
    7+
    import onError from 'services/sentry/onError'
    78

    89
    interface AuthenticateData {
    910
    editorLogin: {
    @@ -30,6 +31,7 @@ export default {
    3031
    },
    3132
    })
    3233
    .catch(error => {
    34+
    onError(error)
    3335
    console.error('ERROR: Authentication failed')
    3436
    console.error(error)
    3537
    })

    web-app/src/services/state/actions/context.ts

    Lines changed: 4 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -2,6 +2,7 @@ import * as CR from 'typings'
    22
    import * as G from 'typings/graphql'
    33
    import { assign, send } from 'xstate'
    44
    import * as selectors from '../../selectors'
    5+
    import onError from 'services/sentry/onError'
    56

    67
    export default {
    78
    setEnv: assign({
    @@ -147,7 +148,9 @@ export default {
    147148
    // has next level?
    148149

    149150
    if (!context.tutorial) {
    150-
    throw new Error('Tutorial not found')
    151+
    const error = new Error('Tutorial not found')
    152+
    onError(error)
    153+
    throw error
    151154
    }
    152155

    153156
    const levels = context.tutorial.version.data.levels || []

    web-app/src/services/state/actions/editor.ts

    Lines changed: 10 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -4,6 +4,7 @@ import client from '../../apollo'
    44
    import tutorialQuery from '../../apollo/queries/tutorial'
    55
    import channel from '../../channel'
    66
    import * as selectors from '../../selectors'
    7+
    import onError from 'services/sentry/onError'
    78

    89
    interface TutorialData {
    910
    tutorial: G.Tutorial
    @@ -30,7 +31,9 @@ export default {
    3031
    initializeTutorial(context: CR.MachineContext, event: CR.MachineEvent) {
    3132
    // setup test runner and git
    3233
    if (!context.tutorial) {
    33-
    throw new Error('Tutorial not available to load')
    34+
    const error = new Error('Tutorial not available to load')
    35+
    onError(error)
    36+
    throw error
    3437
    }
    3538

    3639
    client
    @@ -43,7 +46,9 @@ export default {
    4346
    })
    4447
    .then(result => {
    4548
    if (!result || !result.data || !result.data.tutorial) {
    46-
    return Promise.reject('No tutorial returned from tutorial config query')
    49+
    const message = 'No tutorial returned from tutorial config query'
    50+
    onError(new Error(message))
    51+
    return Promise.reject(message)
    4752
    }
    4853

    4954
    channel.editorSend({
    @@ -52,7 +57,9 @@ export default {
    5257
    })
    5358
    })
    5459
    .catch((error: Error) => {
    55-
    return Promise.reject(`Failed to load tutorial config ${error.message}`)
    60+
    const message = `Failed to load tutorial config ${error.message}`
    61+
    onError(new Error(message))
    62+
    return Promise.reject(message)
    5663
    })
    5764
    },
    5865
    continueConfig(context: CR.MachineContext) {

    0 commit comments

    Comments
     (0)
    0