mirror of
https://github.com/kremalicious/umami.git
synced 2024-12-24 02:06:19 +01:00
Added error boundary. Fixed #1976.
This commit is contained in:
parent
d73def80c7
commit
3f1ed750f0
33
components/common/ErrorBoundary.js
Normal file
33
components/common/ErrorBoundary.js
Normal file
@ -0,0 +1,33 @@
|
||||
/* eslint-disable no-console */
|
||||
import { ErrorBoundary as Boundary } from 'react-error-boundary';
|
||||
import { Button } from 'react-basics';
|
||||
import useMessages from 'hooks/useMessages';
|
||||
import styles from './ErrorBoundry.module.css';
|
||||
|
||||
const logError = (error, info) => {
|
||||
console.error(error, info.componentStack);
|
||||
};
|
||||
|
||||
export function ErrorBoundary({ children }) {
|
||||
const { formatMessage, messages } = useMessages();
|
||||
|
||||
const fallbackRender = ({ error, resetErrorBoundary }) => {
|
||||
console.log({ error });
|
||||
return (
|
||||
<div className={styles.error} role="alert">
|
||||
<h1>{formatMessage(messages.error)}</h1>
|
||||
<h3>{error.message}</h3>
|
||||
<pre>{error.stack}</pre>
|
||||
<Button onClick={resetErrorBoundary}>OK</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Boundary fallbackRender={fallbackRender} onError={logError}>
|
||||
{children}
|
||||
</Boundary>
|
||||
);
|
||||
}
|
||||
|
||||
export default ErrorBoundary;
|
19
components/common/ErrorBoundry.module.css
Normal file
19
components/common/ErrorBoundry.module.css
Normal file
@ -0,0 +1,19 @@
|
||||
.error {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
z-index: var(--z-index-overlay);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 600px;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.error button {
|
||||
align-self: center;
|
||||
}
|
@ -23,7 +23,7 @@ export function DateFilter({ websiteId, value, className }) {
|
||||
if (data) {
|
||||
setDateRange({ value, ...getDateRangeValues(new Date(data.createdAt), Date.now()) });
|
||||
}
|
||||
} else {
|
||||
} else if (value !== 'all') {
|
||||
setDateRange(value);
|
||||
}
|
||||
}
|
||||
@ -61,7 +61,7 @@ export function DateFilter({ websiteId, value, className }) {
|
||||
value: '90day',
|
||||
},
|
||||
{ label: formatMessage(labels.thisYear), value: '1year' },
|
||||
{
|
||||
websiteId && {
|
||||
label: formatMessage(labels.allTime),
|
||||
value: 'all',
|
||||
divider: true,
|
||||
@ -71,7 +71,7 @@ export function DateFilter({ websiteId, value, className }) {
|
||||
value: 'custom',
|
||||
divider: true,
|
||||
},
|
||||
];
|
||||
].filter(n => n);
|
||||
|
||||
const renderValue = value => {
|
||||
return value === 'custom' ? (
|
||||
|
@ -53,7 +53,7 @@ export function parseDateRange(value, locale = 'en-US') {
|
||||
|
||||
const match = value.match(/^(?<num>[0-9-]+)(?<unit>hour|day|week|month|year)$/);
|
||||
|
||||
if (!match) return;
|
||||
if (!match) return {};
|
||||
|
||||
const { num, unit } = match.groups;
|
||||
|
||||
|
@ -97,6 +97,7 @@
|
||||
"react-basics": "^0.77.0",
|
||||
"react-beautiful-dnd": "^13.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-error-boundary": "^4.0.4",
|
||||
"react-intl": "^5.24.7",
|
||||
"react-simple-maps": "^2.3.0",
|
||||
"react-spring": "^9.4.4",
|
||||
|
@ -3,6 +3,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import Head from 'next/head';
|
||||
import Script from 'next/script';
|
||||
import { useRouter } from 'next/router';
|
||||
import ErrorBoundary from 'components/common/ErrorBoundary';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
import '@fontsource/inter/400.css';
|
||||
@ -41,21 +42,37 @@ export default function App({ Component, pageProps }) {
|
||||
textComponent={Wrapper}
|
||||
onError={() => null}
|
||||
>
|
||||
<Head>
|
||||
<link rel="icon" href={`${basePath}/favicon.ico`} />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href={`${basePath}/apple-touch-icon.png`} />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href={`${basePath}/favicon-32x32.png`} />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href={`${basePath}/favicon-16x16.png`} />
|
||||
<link rel="manifest" href={`${basePath}/site.webmanifest`} />
|
||||
<link rel="mask-icon" href={`${basePath}/safari-pinned-tab.svg`} color="#5bbad5" />
|
||||
<meta name="msapplication-TileColor" content="#da532c" />
|
||||
<meta name="theme-color" content="#fafafa" media="(prefers-color-scheme: light)" />
|
||||
<meta name="theme-color" content="#2f2f2f" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
</Head>
|
||||
<Component {...pageProps} />
|
||||
{!pathname.includes('/share/') && <Script src={`${basePath}/telemetry.js`} />}
|
||||
<ErrorBoundary>
|
||||
<Head>
|
||||
<link rel="icon" href={`${basePath}/favicon.ico`} />
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href={`${basePath}/apple-touch-icon.png`}
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href={`${basePath}/favicon-32x32.png`}
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href={`${basePath}/favicon-16x16.png`}
|
||||
/>
|
||||
<link rel="manifest" href={`${basePath}/site.webmanifest`} />
|
||||
<link rel="mask-icon" href={`${basePath}/safari-pinned-tab.svg`} color="#5bbad5" />
|
||||
<meta name="msapplication-TileColor" content="#da532c" />
|
||||
<meta name="theme-color" content="#fafafa" media="(prefers-color-scheme: light)" />
|
||||
<meta name="theme-color" content="#2f2f2f" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
</Head>
|
||||
<Component {...pageProps} />
|
||||
{!pathname.includes('/share/') && <Script src={`${basePath}/telemetry.js`} />}
|
||||
</ErrorBoundary>
|
||||
</IntlProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
|
@ -1497,7 +1497,7 @@
|
||||
core-js-pure "^3.25.1"
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
"@babel/runtime@^7.0.0":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5":
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
|
||||
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
|
||||
@ -8258,6 +8258,13 @@ react-dom@^18.2.0:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react-error-boundary@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.4.tgz#d2e84505b0a67cec7a6bf33b0146faadfe31597d"
|
||||
integrity sha512-AbqMFx8bCsob8rCHZvJYQ42MQijK0/034RUvan9qrqyJCpazr8d9vKHrysbxcr6odoHLZvQEcYomFPoIqH9fow==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
|
||||
react-fast-compare@^2.0.1:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user