Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: error boundary #109

Merged
merged 2 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"license": "AGPL-3.0-only",
"author": "Graasp",
"contributors": [
"Basile Spaenlehauer"
"Basile Spaenlehauer",
"Jérémy La Scala"
],
"homepage": ".",
"type": "module",
Expand All @@ -13,7 +14,7 @@
"@emotion/styled": "11.11.0",
"@graasp/apps-query-client": "3.4.8",
"@graasp/sdk": "4.1.0",
"@graasp/ui": "4.9.3",
"@graasp/ui": "4.10.0",
"@mui/icons-material": "5.15.12",
"@mui/lab": "5.0.0-alpha.167",
"@mui/material": "5.15.12",
Expand Down
17 changes: 16 additions & 1 deletion src/langs/en.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
{
"translations": {
"Welcome to the Graasp App Starter Kit": "Welcome to the Graasp App Starter Kit"
"Welcome to the Graasp App Starter Kit": "Welcome to the Graasp App Starter Kit",
"ERROR_BOUNDARY": {
"FALLBACK": {
"MESSAGE_TITLE": "Sorry, something went wrong with this application",
"MESSAGE_FEEDBACK": "Our team has been notified. If you would like to help, please, tell us what happened below.",
"ERROR_DETAILS": "Details of the error",
"NAME_LABEL": "Name",
"NAME_HELPER": "Provide your name (optional)",
"EMAIL_LABEL": "Email",
"EMAIL_HELPER": "Provide your email (optional)",
"COMMENT_LABEL": "Comment",
"COMMENT_HELPER": "Tell us what happened (optional)",
"THANKS_FOR_FEEDBACK": "Thank you for your feedback!",
"SEND": "Send your feedback"
}
}
}
}
40 changes: 40 additions & 0 deletions src/modules/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { FC, ReactNode } from 'react';
import { useTranslation } from 'react-i18next';

import { ErrorFallback } from '@graasp/ui/apps';

import * as Sentry from '@sentry/react';

const ErrorBoundary: FC<{ children?: ReactNode }> = ({ children }) => {
const { t: tFallback } = useTranslation('translations', {
keyPrefix: 'ERROR_BOUNDARY.FALLBACK',
});
return (
<Sentry.ErrorBoundary
// eslint-disable-next-line react/no-unstable-nested-components
fallback={({ error, componentStack, eventId }) => (
<ErrorFallback
error={error}
componentStack={componentStack}
eventId={eventId}
captureUserFeedback={Sentry.captureUserFeedback}
title={tFallback('MESSAGE_TITLE')}
formTitle={tFallback('MESSAGE_FEEDBACK')}
nameLabel={tFallback('NAME_LABEL')}
nameHelper={tFallback('NAME_HELPER')}
emailLabel={tFallback('EMAIL_LABEL')}
emailHelper={tFallback('EMAIL_HELPER')}
commentLabel={tFallback('COMMENT_LABEL')}
commentHelper={tFallback('COMMENT_HELPER')}
thanksMessage={tFallback('THANKS_FOR_FEEDBACK')}
sendButtonLabel={tFallback('SEND')}
errorDetailsLabel={tFallback('ERROR_DETAILS')}
/>
)}
>
{children}
</Sentry.ErrorBoundary>
);
};

export default ErrorBoundary;
65 changes: 35 additions & 30 deletions src/modules/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { defaultMockContext, mockMembers } from '@/mocks/db';
import Loader from '@/modules/common/Loader';
import { useObjectState } from '@/utils/hooks';

import ErrorBoundary from './ErrorBoundary';
import App from './main/App';

// declare the module to enable theme modification
Expand Down Expand Up @@ -80,42 +81,46 @@ const Root: FC = () => {
<ThemeProvider theme={theme}>
<CssBaseline enableColorScheme />
<I18nextProvider i18n={i18nConfig}>
<QueryClientProvider client={queryClient}>
<ToastContainer />
<WithLocalContext
defaultValue={window.Cypress ? window.appContext : mockContext}
LoadingComponent={<Loader />}
useGetLocalContext={hooks.useGetLocalContext}
useAutoResize={hooks.useAutoResize}
onError={() => {
console.error(
'An error occurred while fetching the context.',
);
}}
>
<WithTokenContext
<ErrorBoundary>
<QueryClientProvider client={queryClient}>
<ToastContainer />
<WithLocalContext
defaultValue={
window.Cypress ? window.appContext : mockContext
}
LoadingComponent={<Loader />}
useAuthToken={hooks.useAuthToken}
useGetLocalContext={hooks.useGetLocalContext}
useAutoResize={hooks.useAutoResize}
onError={() => {
console.error(
'An error occurred while requesting the token.',
'An error occurred while fetching the context.',
);
}}
>
<App />
{import.meta.env.DEV && (
<GraaspContextDevTool
members={mockMembers}
context={mockContext}
setContext={setMockContext}
/>
)}
</WithTokenContext>
</WithLocalContext>
{import.meta.env.DEV && (
<ReactQueryDevtools position="bottom-left" />
)}
</QueryClientProvider>
<WithTokenContext
LoadingComponent={<Loader />}
useAuthToken={hooks.useAuthToken}
onError={() => {
console.error(
'An error occurred while requesting the token.',
);
}}
>
<App />
{import.meta.env.DEV && (
<GraaspContextDevTool
members={mockMembers}
context={mockContext}
setContext={setMockContext}
/>
)}
</WithTokenContext>
</WithLocalContext>
{import.meta.env.DEV && (
<ReactQueryDevtools position="bottom-left" />
)}
</QueryClientProvider>
</ErrorBoundary>
</I18nextProvider>
</ThemeProvider>
</StyledEngineProvider>
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"moduleResolution": "Bundler",
swouf marked this conversation as resolved.
Show resolved Hide resolved
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
Expand Down
Loading
Loading