Skip to content

Commit

Permalink
Merge pull request neo4j#791 from oskarhane/error-boundaries
Browse files Browse the repository at this point in the history
Add React error boundaries
  • Loading branch information
pe4cey authored Jul 9, 2018
2 parents cccf944 + 7be25ec commit b1dc40c
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 53 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
"isomorphic-fetch": "^2.2.1",
"jsonic": "^0.3.0",
"neo4j-driver": "^1.6.1",
"react": "^16.4.0",
"react": "^16.4.1",
"react-addons-pure-render-mixin": "^15.0.2",
"react-dnd": "^2.5.1",
"react-dnd-html5-backend": "^2.5.1",
Expand Down
57 changes: 57 additions & 0 deletions src/browser/components/ErrorBoundary.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2002-2018 "Neo4j, Inc"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { Component } from 'react'
import styled from 'styled-components'
import { StyledErrorBoundaryButton } from 'browser-components/buttons/index'

const ErrorWrapper = styled.div`
background-color: #fbf1f0;
padding: 10px;
text-align: center;
color: #da4433;
`

export default class ErrorBoundary extends Component {
state = {
errorInfo: null,
error: null
}
componentDidCatch (error, errorInfo) {
this.setState({ errorInfo, error })
}
render () {
if (this.state.error) {
return (
<ErrorWrapper>
<p>
Something went wrong: <em>"{this.state.error.toString()}"</em> and
the application can't recover.
</p>
<div style={{ marginTop: '5px' }}>
<StyledErrorBoundaryButton onClick={() => window.location.reload()}>
{this.props.caption || 'Reload application'}
</StyledErrorBoundaryButton>
</div>
</ErrorWrapper>
)
}
return this.props.children
}
}
11 changes: 11 additions & 0 deletions src/browser/components/buttons/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,17 @@ const StyledSecondaryFormButton = styled(StyledFormButton)`
background-color: ${props => props.theme.secondaryButtonBackground};
}
`

export const StyledErrorBoundaryButton = styled(StyledFormButton)`
color: #da4433;
border: 1px solid #da4433;
background-color: #fbf1f0;
&:hover {
color: #ff4433;
border: 1px solid #ff4433;
background-color: #fbf1f0;
}
`
const StyledDrawerFormButton = styled(StyledSecondaryFormButton)`
color: #bcc0c9;
border-color: #bcc0c9;
Expand Down
5 changes: 0 additions & 5 deletions src/browser/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import 'babel-polyfill'
import './styles/bootstrap.grid-only.min.css'
import './styles/streamline.css'
Expand All @@ -34,7 +33,3 @@ if (typeof btoa === 'undefined') {
return Buffer.from(str, 'binary').toString('base64')
}
}

// if (process.env.NODE_ENV !== 'production') {
// require('react/devtools')
// }
83 changes: 47 additions & 36 deletions src/browser/modules/App/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import {
getActiveGraph
} from 'browser-components/DesktopIntegration/helpers'
import { getMetadata, getUserAuthStatus } from 'shared/modules/sync/syncDuck'
import ErrorBoundary from 'browser-components/ErrorBoundary'

export class App extends Component {
componentDidMount () {
Expand All @@ -75,6 +76,7 @@ export class App extends Component {
document.removeEventListener('keyup', this.focusEditorOnSlash)
document.removeEventListener('keyup', this.expandEditorOnEsc)
}

focusEditorOnSlash = e => {
if (['INPUT', 'TEXTAREA'].indexOf(e.target.tagName) > -1) return
if (e.key !== '/') return
Expand All @@ -101,43 +103,48 @@ export class App extends Component {
browserSyncAuthStatus
} = this.props
const themeData = themes[theme] || themes['normal']

return (
<ThemeProvider theme={themeData}>
<StyledWrapper>
<DocTitle titleString={this.props.titleString} />
<UserInteraction />
<DesktopIntegration
integrationPoint={this.props.desktopIntegrationPoint}
onMount={this.props.setInitialConnectionData}
onGraphActive={this.props.switchConnection}
onGraphInactive={this.props.closeConnectionMaybe}
/>
<Render if={loadExternalScripts}>
<Intercom appID='lq70afwx' />
</Render>
<Render if={syncConsent && loadExternalScripts && loadSync}>
<BrowserSyncInit
authStatus={browserSyncAuthStatus}
authData={browserSyncMetadata}
config={browserSyncConfig}
<ErrorBoundary>
<ThemeProvider theme={themeData}>
<StyledWrapper>
<DocTitle titleString={this.props.titleString} />
<UserInteraction />
<DesktopIntegration
integrationPoint={this.props.desktopIntegrationPoint}
onMount={this.props.setInitialConnectionData}
onGraphActive={this.props.switchConnection}
onGraphInactive={this.props.closeConnectionMaybe}
/>
</Render>
<StyledApp>
<StyledBody>
<Sidebar openDrawer={drawer} onNavClick={handleNavClick} />
<StyledMainWrapper>
<Main
cmdchar={cmdchar}
activeConnection={activeConnection}
connectionState={connectionState}
errorMessage={errorMessage}
useBrowserSync={loadSync}
/>
</StyledMainWrapper>
</StyledBody>
</StyledApp>
</StyledWrapper>
</ThemeProvider>
<Render if={loadExternalScripts}>
<Intercom appID='lq70afwx' />
</Render>
<Render if={syncConsent && loadExternalScripts && loadSync}>
<BrowserSyncInit
authStatus={browserSyncAuthStatus}
authData={browserSyncMetadata}
config={browserSyncConfig}
/>
</Render>
<StyledApp>
<StyledBody>
<ErrorBoundary>
<Sidebar openDrawer={drawer} onNavClick={handleNavClick} />
</ErrorBoundary>
<StyledMainWrapper>
<Main
cmdchar={cmdchar}
activeConnection={activeConnection}
connectionState={connectionState}
errorMessage={errorMessage}
useBrowserSync={loadSync}
/>
</StyledMainWrapper>
</StyledBody>
</StyledApp>
</StyledWrapper>
</ThemeProvider>
</ErrorBoundary>
)
}
}
Expand Down Expand Up @@ -224,5 +231,9 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
}

export default withBus(
connect(mapStateToProps, mapDispatchToProps, mergeProps)(App)
connect(
mapStateToProps,
mapDispatchToProps,
mergeProps
)(App)
)
9 changes: 7 additions & 2 deletions src/browser/modules/Main/Main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ import {
} from './styled'
import SyncReminderBanner from './SyncReminderBanner'
import SyncConsentBanner from './SyncConsentBanner'
import ErrorBoundary from 'browser-components/ErrorBoundary'

const Main = props => {
return (
<StyledMain data-test-id='main'>
<Editor />
<ErrorBoundary>
<Editor />
</ErrorBoundary>
<Render if={props.showUnknownCommandBanner}>
<ErrorBanner>
Type&nbsp;
Expand Down Expand Up @@ -77,7 +80,9 @@ const Main = props => {
<Render if={props.useBrowserSync}>
<SyncConsentBanner />
</Render>
<Stream />
<ErrorBoundary>
<Stream />
</ErrorBoundary>
</StyledMain>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
exports[`PlanViews PlanStatusbar displays statusBarMessage 1`] = `
<div>
<div
class="sc-caSCKo gPyUVz sc-fAjcbJ gNJuEv"
class="sc-gisBJw gjAYNM sc-caSCKo hctWWH"
>
<div
class="sc-frDJqD boIXic"
class="sc-kvZOFW gfNjxO"
>
<div
class="sc-tilXH iYzIeW"
class="sc-hEsumM dpcDje"
>
Cypher version:
xx0
Expand All @@ -22,21 +22,21 @@ exports[`PlanViews PlanStatusbar displays statusBarMessage 1`] = `
</div>
</div>
<div
class="sc-hmzhuo fVRxUB"
class="sc-frDJqD jrNxwj"
>
<ul
class="sc-iAyFgw ivuHvH"
class="sc-hSdWYo dRKhSV"
>
<li
class="sc-iwsKbI eorUpA"
class="sc-gZMcBi xeFmB"
data-test-id="planCollapseButton"
>
<i
class=" sl-double-up"
/>
</li>
<li
class="sc-iwsKbI eorUpA"
class="sc-gZMcBi xeFmB"
data-test-id="planExpandButton"
>
<i
Expand Down
5 changes: 4 additions & 1 deletion src/browser/modules/Stream/StyleFrame.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ const mapDispatchToProps = dispatch => ({
}
})

const Statusbar = connect(mapStateToProps, mapDispatchToProps)(StyleStatusbar)
const Statusbar = connect(
mapStateToProps,
mapDispatchToProps
)(StyleStatusbar)

export default StyleFrame
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7745,7 +7745,7 @@ react-timeago@^3.4.3:
version "3.4.3"
resolved "https://neo.jfrog.io/neo/api/npm/npm/react-timeago/-/react-timeago-3.4.3.tgz#eb9061eefb044e4a2b09ce8c99d34645b2dbfa25"

react@^16.4.0:
react@^16.4.1:
version "16.4.1"
resolved "https://neo.jfrog.io/neo/api/npm/npm/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32"
dependencies:
Expand Down

0 comments on commit b1dc40c

Please sign in to comment.