1
Fork 0
mirror of https://github.com/Steffo99/sophon.git synced 2024-12-22 14:54:22 +00:00

Improve error handling

This commit is contained in:
Steffo 2021-10-15 18:07:45 +02:00 committed by Stefano Pigozzi
parent f748add494
commit 9af5ba714b
7 changed files with 180 additions and 113 deletions

View file

@ -37,6 +37,7 @@ import {ThemeProvider} from "./contexts/theme"
function App({..._}: RouteComponentProps) { function App({..._}: RouteComponentProps) {
return React.useMemo( return React.useMemo(
() => <> () => <>
<ErrorCatcherBox>
<Chapter> <Chapter>
<SophonDescriptionBox/> <SophonDescriptionBox/>
</Chapter> </Chapter>
@ -99,6 +100,7 @@ function App({..._}: RouteComponentProps) {
</>} </>}
/> />
</InstanceProvider> </InstanceProvider>
</ErrorCatcherBox>
</>, </>,
[], [],
) )
@ -112,11 +114,9 @@ export default function AppWrapper() {
<LayoutThreeCol> <LayoutThreeCol>
<LayoutThreeCol.Center> <LayoutThreeCol.Center>
<ThemedTitle level={1}/> <ThemedTitle level={1}/>
<ErrorCatcherBox>
<Reach.Router> <Reach.Router>
<App default/> <App default/>
</Reach.Router> </Reach.Router>
</ErrorCatcherBox>
<SophonFooter/> <SophonFooter/>
</LayoutThreeCol.Center> </LayoutThreeCol.Center>
</LayoutThreeCol> </LayoutThreeCol>

View file

@ -0,0 +1,34 @@
import {faLevelUpAlt} from "@fortawesome/free-solid-svg-icons"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import * as Reach from "@reach/router"
import {Button} from "@steffo/bluelib-react"
import {ButtonProps} from "@steffo/bluelib-react/dist/components/inputs/Button"
import * as React from "react"
import {useSophonPath} from "../../hooks/useSophonPath"
/**
* A button that takes the user back one sophon level (so two levels).
*
* @constructor
*/
export function GoBackButton({onClick, ...props}: Omit<ButtonProps, "children">): JSX.Element {
const location = useSophonPath()
const onClickWrapped = React.useCallback(
async event => {
event.preventDefault()
if(onClick) {
onClick(event)
}
await Reach.navigate("../..")
},
[onClick],
)
return (
<Button onClick={onClickWrapped} disabled={location.count === 0} {...props}>
<FontAwesomeIcon icon={faLevelUpAlt}/>&nbsp;Go up
</Button>
)
}

View file

@ -0,0 +1,40 @@
import * as Reach from "@reach/router"
import {Button} from "@steffo/bluelib-react"
import {ButtonProps} from "@steffo/bluelib-react/dist/components/inputs/Button"
import * as React from "react"
/**
* The props of {@link NavigateButton}.
*/
export interface NavigateButtonProps extends ButtonProps {
href: string,
}
/**
* A button functioning like a {@link Link}.
*
* @constructor
*/
export function NavigateButton({href, children, onClick, ...props}: NavigateButtonProps): JSX.Element {
const location = Reach.useLocation()
const onClickWrapped = React.useCallback(
event => {
event.preventDefault()
if(onClick) {
onClick(event)
}
if(href) {
// noinspection JSIgnoredPromiseFromCall
Reach.navigate(href)
}
},
[href, onClick],
)
return (
<Button children={children} onClick={onClickWrapped} disabled={location.pathname === href} {...props}/>
)
}

View file

@ -1,7 +1,9 @@
import {Box, Form} from "@steffo/bluelib-react" import {faAngleDoubleRight, faBug} from "@fortawesome/free-solid-svg-icons"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import {Box, Button, Form} from "@steffo/bluelib-react"
import * as React from "react" import * as React from "react"
import {IgnoreErrorButton} from "./IgnoreErrorButton" import {GoBackButton} from "../elements/GoBackButton"
import {ReportBugButton} from "./ReportBugButton" import {NavigateButton} from "../elements/NavigateButton"
interface ErrorCatcherBoxProps { interface ErrorCatcherBoxProps {
@ -44,8 +46,13 @@ export class ErrorCatcherBox extends React.Component<ErrorCatcherBoxProps, Error
{this.state.error.toString()} {this.state.error.toString()}
<Form> <Form>
<Form.Row> <Form.Row>
<IgnoreErrorButton onClick={this.clearError}/> <NavigateButton href={"https://github.com/Steffo99/sophon/issues/new?assignees=&labels=bug&template=1_bug_report.md&title="}>
<ReportBugButton/> <FontAwesomeIcon icon={faBug}/>&nbsp;Report bug
</NavigateButton>
<GoBackButton/>
<Button onClick={this.clearError}>
<FontAwesomeIcon icon={faAngleDoubleRight}/>&nbsp;Try ignoring the error
</Button>
</Form.Row> </Form.Row>
</Form> </Form>
</Box> </Box>

View file

@ -1,18 +0,0 @@
import {faAngleDoubleRight} from "@fortawesome/free-solid-svg-icons"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import {Button} from "@steffo/bluelib-react"
import * as React from "react"
export interface IgnoreErrorButtonProps {
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
}
export function IgnoreErrorButton({onClick}: IgnoreErrorButtonProps): JSX.Element {
return (
<Button onClick={onClick}>
<FontAwesomeIcon icon={faAngleDoubleRight}/>&nbsp;Try ignoring the error
</Button>
)
}

View file

@ -1,25 +0,0 @@
import {faBug} from "@fortawesome/free-solid-svg-icons"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import {navigate} from "@reach/router"
import {Button} from "@steffo/bluelib-react"
import * as React from "react"
export function ReportBugButton(): JSX.Element {
const onClick =
React.useCallback(
async () => {
await navigate("https://github.com/Steffo99/sophon/issues/new?assignees=&labels=bug&template=1_bug_report.md&title=")
},
[],
)
return React.useMemo(
() => (
<Button>
<FontAwesomeIcon onClick={onClick} icon={faBug}/>&nbsp;Report bug
</Button>
),
[onClick],
)
}

View file

@ -37,6 +37,11 @@ export interface ParsedPath {
* Passed the login page (either by browsing as guest or by logging in). * Passed the login page (either by browsing as guest or by logging in).
*/ */
loggedIn?: boolean, loggedIn?: boolean,
/**
* The number of pages that separate this to the website root.
*/
count: number,
} }
/** /**
@ -44,7 +49,9 @@ export interface ParsedPath {
* @param path - The path to split. * @param path - The path to split.
*/ */
export function parsePath(path: string): ParsedPath { export function parsePath(path: string): ParsedPath {
let result: ParsedPath = {} let result: ParsedPath = {
count: 0,
}
result.instance = path.match(/[/]i[/]([^/]+)/)?.[1] result.instance = path.match(/[/]i[/]([^/]+)/)?.[1]
result.userId = path.match(/[/]u[/]([0-9]+)/)?.[1] result.userId = path.match(/[/]u[/]([0-9]+)/)?.[1]
@ -54,5 +61,27 @@ export function parsePath(path: string): ParsedPath {
result.notebook = path.match(/[/]n[/]([A-Za-z0-9_-]+)/)?.[1] result.notebook = path.match(/[/]n[/]([A-Za-z0-9_-]+)/)?.[1]
result.loggedIn = Boolean(path.match(/[/]l[/]/)) result.loggedIn = Boolean(path.match(/[/]l[/]/))
if(result.instance) {
result.count += 1
}
if(result.userId) {
result.count += 1
}
if(result.userName) {
result.count += 1
}
if(result.researchGroup) {
result.count += 1
}
if(result.researchProject) {
result.count += 1
}
if(result.notebook) {
result.count += 1
}
if(result.loggedIn) {
result.count += 1
}
return result return result
} }