From e0edd29436c6743bbe04a66cfd5638a0f8ab3e9d Mon Sep 17 00:00:00 2001 From: Kevin Kandlbinder Date: Tue, 3 May 2022 14:39:26 +0200 Subject: [PATCH] Add error boundary for tools --- package.json | 4 ++- public/locales/de/translation.json | 8 ++++- public/locales/en/translation.json | 8 ++++- src/_common.scss | 28 ++++++++++++++- src/tools/ToolLoader.tsx | 55 +++++++++++++++++++++++++++--- yarn.lock | 5 +++ 6 files changed, 100 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 9a3afc9..bca6aff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kevins-data-toolbox", - "version": "2.0.0", + "version": "2.1.0", "private": true, "dependencies": { "@loadable/component": "^5.15.0", @@ -9,6 +9,7 @@ "@testing-library/user-event": "^14.1.1", "@types/jest": "^27.4.1", "@types/loadable__component": "^5.13.4", + "@types/lodash": "^4.14.182", "@types/node": "^17.0.31", "@types/react": "^18.0.8", "@types/react-dom": "^18.0.3", @@ -17,6 +18,7 @@ "i18next": "^21.6.16", "i18next-browser-languagedetector": "^6.1.0", "i18next-http-backend": "^1.2.1", + "lodash": "^4.17.21", "lucide-react": "^0.35.0", "react": "^18.1.0", "react-dom": "^18.1.0", diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index 2d31eac..9b2bfcc 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -47,6 +47,12 @@ "system": { "notfound": "Seite nicht gefunden", "language": "Sprache", - "imprint": "Impressum" + "imprint": "Impressum", + "errors": { + "toolException": { + "title": "Ein fatales Problem ist aufgetreten.", + "description": "Im Werkzeug ist ein fatales Problem aufgetreten und die Aufgabe konnte nicht abgeschlossen werden. Bitte erneut versuchen." + } + } } } \ No newline at end of file diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 2ae1331..5afbd4e 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -47,6 +47,12 @@ "system": { "notfound": "Page Not Found", "language": "Language", - "imprint": "Imprint" + "imprint": "Imprint", + "errors": { + "toolException": { + "title": "The tool encountered a fatal error.", + "description": "The tool encountered a fatal error and was unable to complete its task. Please retry." + } + } } } \ No newline at end of file diff --git a/src/_common.scss b/src/_common.scss index 2d3aaab..9d55c9d 100644 --- a/src/_common.scss +++ b/src/_common.scss @@ -11,7 +11,7 @@ $layoutNavigationHeight: 50px; max-width: $layoutWidth; padding: 0 $layoutPadding; margin: 0 auto; - + width: 100%; } @mixin boxStyle { @@ -30,7 +30,33 @@ $layoutNavigationHeight: 50px; } } +@mixin button { + @include boxStyle; + background: rgba(white, .75); + color: $colorAccent; + border: none; + border-radius: 10px; + padding: 10px; + margin: 0; + cursor: pointer; + font: inherit; + transition: all .2s ease-in-out; + + @media(prefers-color-scheme: dark) { + color: white; + } + + &:hover { + background: white; + color: $colorAccent; + } +} + @mixin formStyles() { + button { + @include button; + } + input[type=text], input[type=password], textarea, input[type=number] { @include boxStyle; diff --git a/src/tools/ToolLoader.tsx b/src/tools/ToolLoader.tsx index 4e64e4d..5fc6a8b 100644 --- a/src/tools/ToolLoader.tsx +++ b/src/tools/ToolLoader.tsx @@ -1,25 +1,72 @@ -import React from "react"; +import React, { useState } from "react"; import { useParams } from "react-router"; +import _ from "lodash"; import prerenderedLoadable from "../helpers/prerenderedLoadable"; import NotFoundPage from "../pages/NotFound"; +import * as styles from "../App.module.scss"; +import { Trans } from "react-i18next"; +import BoxMessage from "../components/BoxMessage"; +import { AlertOctagon } from "lucide-react"; + const HomePage = prerenderedLoadable(() => import('../pages/Home')); const RotTool = prerenderedLoadable(() => import('./cyphers_and_cryptography/rot/RotTool')); const Base64Tool = prerenderedLoadable(() => import('./cyphers_and_cryptography/base64/Base64Tool')); +type ErrorBoundaryProps = { + resetFunction: () => void +} +class ToolErrorBoundary extends React.Component, {hasError: boolean}> { + constructor(props: React.PropsWithChildren) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError(error: Error) { + return { hasError: true }; + } + componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { + console.log(error, errorInfo); + } + render() { + + if (this.state.hasError) { + // You can render any custom fallback UI + return <> +
+ }> + The tool encountered a fatal error. +

+ +

+ +
+
+ ; + } + return this.props.children; + } + } + const ToolLoader = () => { const {tool} = useParams(); + + const [key, setKey] = useState(_.uniqueId("toolLoader_")) + + const forceReset = () => { + setKey(_.uniqueId("toolLoader_")) + } switch(tool) { case "test": - return ; + return ; case "rot": - return ; + return ; case "base64": - return ; + return ; default: return ; diff --git a/yarn.lock b/yarn.lock index 9798fb8..df45e66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1762,6 +1762,11 @@ dependencies: "@types/react" "*" +"@types/lodash@^4.14.182": + version "4.14.182" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" + integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== + "@types/minimatch@*": version "3.0.5" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"