diff --git a/apps/admin-x-settings/src/admin-x-ds/global/ErrorBoundary.stories.tsx b/apps/admin-x-settings/src/admin-x-ds/global/ErrorBoundary.stories.tsx new file mode 100644 index 0000000000..a353553cce --- /dev/null +++ b/apps/admin-x-settings/src/admin-x-ds/global/ErrorBoundary.stories.tsx @@ -0,0 +1,22 @@ +import ErrorBoundary from './ErrorBoundary'; +import type {Meta, StoryObj} from '@storybook/react'; + +const meta = { + title: 'Global / Error Boundary', + component: ErrorBoundary, + tags: ['autodocs'] +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const RaisesError = () => { + throw new Error('Something went wrong'); +}; + +export const WithError: Story = { + args: { + name: 'Test Section', + children: + } +}; diff --git a/apps/admin-x-settings/src/admin-x-ds/global/ErrorBoundary.tsx b/apps/admin-x-settings/src/admin-x-ds/global/ErrorBoundary.tsx new file mode 100644 index 0000000000..bcb13504be --- /dev/null +++ b/apps/admin-x-settings/src/admin-x-ds/global/ErrorBoundary.tsx @@ -0,0 +1,50 @@ +import Banner from './Banner'; +import React, {ComponentType, ErrorInfo, ReactNode} from 'react'; + +/** + * Catches errors in child components and displays a banner. Useful to prevent errors in one + * section from crashing the entire page + */ +class ErrorBoundary extends React.Component<{children: ReactNode, name: ReactNode}> { + state = {hasError: false}; + + constructor(props: {children: ReactNode, name: ReactNode}) { + super(props); + } + + static getDerivedStateFromError() { + return {hasError: true}; + } + + componentDidCatch(error: unknown, info: ErrorInfo) { + // TODO: Log to Sentry + // eslint-disable-next-line no-console + console.error(error); + // eslint-disable-next-line no-console + console.error('In component:', info.componentStack); + } + + render() { + if (this.state.hasError) { + return ( + + An error occurred loading {this.props.name}. Please refresh and try again. + + ); + } + + return this.props.children; + } +} + +export default ErrorBoundary; + +export const withErrorBoundary = >(Component: ComponentType, name: string) => { + return function WithErrorBoundary(props: Props) { + return ( + + + + ); + }; +}; diff --git a/apps/admin-x-settings/src/components/settings/advanced/CodeInjection.tsx b/apps/admin-x-settings/src/components/settings/advanced/CodeInjection.tsx index 3f6ce7b99c..d733029eab 100644 --- a/apps/admin-x-settings/src/components/settings/advanced/CodeInjection.tsx +++ b/apps/admin-x-settings/src/components/settings/advanced/CodeInjection.tsx @@ -8,6 +8,7 @@ import TabView from '../../../admin-x-ds/global/TabView'; import useSettingGroup from '../../../hooks/useSettingGroup'; import {ReactCodeMirrorRef} from '@uiw/react-codemirror'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const CodeInjection: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -93,4 +94,4 @@ const CodeInjection: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default CodeInjection; +export default withErrorBoundary(CodeInjection, 'Code injection'); diff --git a/apps/admin-x-settings/src/components/settings/advanced/History.tsx b/apps/admin-x-settings/src/components/settings/advanced/History.tsx index 5ff10839a3..7f1e11b50e 100644 --- a/apps/admin-x-settings/src/components/settings/advanced/History.tsx +++ b/apps/admin-x-settings/src/components/settings/advanced/History.tsx @@ -2,6 +2,7 @@ import Button from '../../../admin-x-ds/global/Button'; import React from 'react'; import SettingGroup from '../../../admin-x-ds/settings/SettingGroup'; import useRouting from '../../../hooks/useRouting'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const History: React.FC<{ keywords: string[] }> = ({keywords}) => { const {updateRoute} = useRouting(); @@ -21,4 +22,4 @@ const History: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default History; +export default withErrorBoundary(History, 'History'); diff --git a/apps/admin-x-settings/src/components/settings/advanced/Integrations.tsx b/apps/admin-x-settings/src/components/settings/advanced/Integrations.tsx index dde5e353fa..234612bd13 100644 --- a/apps/admin-x-settings/src/components/settings/advanced/Integrations.tsx +++ b/apps/admin-x-settings/src/components/settings/advanced/Integrations.tsx @@ -19,6 +19,7 @@ import {ReactComponent as ZapierIcon} from '../../../assets/icons/zapier.svg'; import {getSettingValues} from '../../../api/settings'; import {showToast} from '../../../admin-x-ds/global/Toast'; import {useGlobalData} from '../../providers/GlobalDataProvider'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; interface IntegrationItemProps { icon?: React.ReactNode, @@ -236,4 +237,4 @@ const Integrations: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Integrations; +export default withErrorBoundary(Integrations, 'Integrations'); diff --git a/apps/admin-x-settings/src/components/settings/advanced/Labs.tsx b/apps/admin-x-settings/src/components/settings/advanced/Labs.tsx index 41155c998e..4457847e91 100644 --- a/apps/admin-x-settings/src/components/settings/advanced/Labs.tsx +++ b/apps/admin-x-settings/src/components/settings/advanced/Labs.tsx @@ -8,6 +8,7 @@ import SettingGroup from '../../../admin-x-ds/settings/SettingGroup'; import SettingGroupHeader from '../../../admin-x-ds/settings/SettingGroupHeader'; import TabView, {Tab} from '../../../admin-x-ds/global/TabView'; import {useGlobalData} from '../../providers/GlobalDataProvider'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; type LabsTab = 'labs-migration-options' | 'labs-alpha-features' | 'labs-beta-features'; @@ -66,4 +67,4 @@ const Labs: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Labs; +export default withErrorBoundary(Labs, 'Labs'); diff --git a/apps/admin-x-settings/src/components/settings/email/DefaultRecipients.tsx b/apps/admin-x-settings/src/components/settings/email/DefaultRecipients.tsx index 23106006bc..c55169c1ac 100644 --- a/apps/admin-x-settings/src/components/settings/email/DefaultRecipients.tsx +++ b/apps/admin-x-settings/src/components/settings/email/DefaultRecipients.tsx @@ -10,6 +10,7 @@ import {getSettingValues} from '../../../api/settings'; import {useBrowseLabels} from '../../../api/labels'; import {useBrowseOffers} from '../../../api/offers'; import {useBrowseTiers} from '../../../api/tiers'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; type RefipientValueArgs = { defaultEmailRecipients: string; @@ -206,4 +207,4 @@ const DefaultRecipients: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default DefaultRecipients; +export default withErrorBoundary(DefaultRecipients, 'Default recipients'); diff --git a/apps/admin-x-settings/src/components/settings/email/EnableNewsletters.tsx b/apps/admin-x-settings/src/components/settings/email/EnableNewsletters.tsx index e40924ef6e..f9b8284c85 100644 --- a/apps/admin-x-settings/src/components/settings/email/EnableNewsletters.tsx +++ b/apps/admin-x-settings/src/components/settings/email/EnableNewsletters.tsx @@ -7,6 +7,7 @@ import Toggle from '../../../admin-x-ds/global/form/Toggle'; import useRouting from '../../../hooks/useRouting'; import {Setting, getSettingValues, useEditSettings} from '../../../api/settings'; import {useGlobalData} from '../../providers/GlobalDataProvider'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const EnableNewsletters: React.FC<{ keywords: string[] }> = ({keywords}) => { const {settings} = useGlobalData(); @@ -75,4 +76,4 @@ const EnableNewsletters: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default EnableNewsletters; +export default withErrorBoundary(EnableNewsletters, 'Newsletter sending'); diff --git a/apps/admin-x-settings/src/components/settings/email/Mailgun.tsx b/apps/admin-x-settings/src/components/settings/email/Mailgun.tsx index 7d2760b0cb..dd5f5ea341 100644 --- a/apps/admin-x-settings/src/components/settings/email/Mailgun.tsx +++ b/apps/admin-x-settings/src/components/settings/email/Mailgun.tsx @@ -7,6 +7,7 @@ import SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupConten import TextField from '../../../admin-x-ds/global/form/TextField'; import useSettingGroup from '../../../hooks/useSettingGroup'; import {getSettingValues, useEditSettings} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const MAILGUN_REGIONS = [ {label: '🇺🇸 US', value: 'https://api.mailgun.net/v3'}, @@ -122,4 +123,4 @@ const MailGun: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default MailGun; +export default withErrorBoundary(MailGun, 'Mailgun'); diff --git a/apps/admin-x-settings/src/components/settings/email/Newsletters.tsx b/apps/admin-x-settings/src/components/settings/email/Newsletters.tsx index 9d46df9756..0e4e8431b5 100644 --- a/apps/admin-x-settings/src/components/settings/email/Newsletters.tsx +++ b/apps/admin-x-settings/src/components/settings/email/Newsletters.tsx @@ -5,6 +5,7 @@ import SettingGroup from '../../../admin-x-ds/settings/SettingGroup'; import TabView from '../../../admin-x-ds/global/TabView'; import useRouting from '../../../hooks/useRouting'; import {useBrowseNewsletters} from '../../../api/newsletters'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const Newsletters: React.FC<{ keywords: string[] }> = ({keywords}) => { const {updateRoute} = useRouting(); @@ -46,4 +47,4 @@ const Newsletters: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Newsletters; +export default withErrorBoundary(Newsletters, 'Newsletters'); diff --git a/apps/admin-x-settings/src/components/settings/general/Facebook.tsx b/apps/admin-x-settings/src/components/settings/general/Facebook.tsx index 8272e68841..e2b99f6226 100644 --- a/apps/admin-x-settings/src/components/settings/general/Facebook.tsx +++ b/apps/admin-x-settings/src/components/settings/general/Facebook.tsx @@ -8,6 +8,7 @@ import useSettingGroup from '../../../hooks/useSettingGroup'; import {ReactComponent as FacebookLogo} from '../../../admin-x-ds/assets/images/facebook-logo.svg'; import {getImageUrl, useUploadImage} from '../../../api/images'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const Facebook: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -141,4 +142,4 @@ const Facebook: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Facebook; +export default withErrorBoundary(Facebook, 'Facebook card'); diff --git a/apps/admin-x-settings/src/components/settings/general/LockSite.tsx b/apps/admin-x-settings/src/components/settings/general/LockSite.tsx index c905ecaef3..481e69091c 100644 --- a/apps/admin-x-settings/src/components/settings/general/LockSite.tsx +++ b/apps/admin-x-settings/src/components/settings/general/LockSite.tsx @@ -7,6 +7,7 @@ import TextField from '../../../admin-x-ds/global/form/TextField'; import Toggle from '../../../admin-x-ds/global/form/Toggle'; import useSettingGroup from '../../../hooks/useSettingGroup'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const LockSite: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -108,4 +109,4 @@ const LockSite: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default LockSite; +export default withErrorBoundary(LockSite, 'Make site private'); diff --git a/apps/admin-x-settings/src/components/settings/general/Metadata.tsx b/apps/admin-x-settings/src/components/settings/general/Metadata.tsx index c796905b35..f78ce8dc8e 100644 --- a/apps/admin-x-settings/src/components/settings/general/Metadata.tsx +++ b/apps/admin-x-settings/src/components/settings/general/Metadata.tsx @@ -7,6 +7,7 @@ import useSettingGroup from '../../../hooks/useSettingGroup'; import {ReactComponent as GoogleLogo} from '../../../admin-x-ds/assets/images/google-logo.svg'; import {ReactComponent as MagnifyingGlass} from '../../../admin-x-ds/assets/icons/magnifying-glass.svg'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; interface SearchEnginePreviewProps { title: string; @@ -126,4 +127,4 @@ const Metadata: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Metadata; +export default withErrorBoundary(Metadata, 'Meta data'); diff --git a/apps/admin-x-settings/src/components/settings/general/PublicationLanguage.tsx b/apps/admin-x-settings/src/components/settings/general/PublicationLanguage.tsx index 17c1cdfb10..3faf98252e 100644 --- a/apps/admin-x-settings/src/components/settings/general/PublicationLanguage.tsx +++ b/apps/admin-x-settings/src/components/settings/general/PublicationLanguage.tsx @@ -4,6 +4,7 @@ import SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupConten import TextField from '../../../admin-x-ds/global/form/TextField'; import useSettingGroup from '../../../hooks/useSettingGroup'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const PublicationLanguage: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -71,4 +72,4 @@ const PublicationLanguage: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default PublicationLanguage; +export default withErrorBoundary(PublicationLanguage, 'Publication language'); diff --git a/apps/admin-x-settings/src/components/settings/general/SocialAccounts.tsx b/apps/admin-x-settings/src/components/settings/general/SocialAccounts.tsx index bac2145d3d..1c5442281a 100644 --- a/apps/admin-x-settings/src/components/settings/general/SocialAccounts.tsx +++ b/apps/admin-x-settings/src/components/settings/general/SocialAccounts.tsx @@ -5,6 +5,7 @@ import TextField from '../../../admin-x-ds/global/form/TextField'; import useSettingGroup from '../../../hooks/useSettingGroup'; import validator from 'validator'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; function validateFacebookUrl(newUrl: string) { const errMessage = 'The URL must be in a format like https://www.facebook.com/yourPage'; @@ -87,10 +88,10 @@ const SocialAccounts: React.FC<{ keywords: string[] }> = ({keywords}) => { const twitterInputRef = useRef(null); - const [facebookHandle, twitterHandle] = getSettingValues(localSettings, ['facebook', 'twitter']) as string[]; + const [facebookHandle, twitterHandle] = getSettingValues(localSettings, ['facebook', 'twitter']); - const [facebookUrl, setFacebookUrl] = useState(facebookHandleToUrl(facebookHandle)); - const [twitterUrl, setTwitterUrl] = useState(twitterHandleToUrl(twitterHandle)); + const [facebookUrl, setFacebookUrl] = useState(facebookHandle ? facebookHandleToUrl(facebookHandle) : ''); + const [twitterUrl, setTwitterUrl] = useState(twitterHandle ? twitterHandleToUrl(twitterHandle) : ''); const values = ( = ({keywords}) => { ); }; -export default SocialAccounts; +export default withErrorBoundary(SocialAccounts, 'Social accounts'); diff --git a/apps/admin-x-settings/src/components/settings/general/TimeZone.tsx b/apps/admin-x-settings/src/components/settings/general/TimeZone.tsx index 4d8e017702..607c0f743b 100644 --- a/apps/admin-x-settings/src/components/settings/general/TimeZone.tsx +++ b/apps/admin-x-settings/src/components/settings/general/TimeZone.tsx @@ -6,6 +6,7 @@ import timezoneData from '@tryghost/timezone-data'; import useSettingGroup from '../../../hooks/useSettingGroup'; import {getLocalTime} from '../../../utils/helpers'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; interface TimezoneDataDropdownOption { name: string; @@ -100,4 +101,4 @@ const TimeZone: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default TimeZone; +export default withErrorBoundary(TimeZone, 'Site timezone'); diff --git a/apps/admin-x-settings/src/components/settings/general/TitleAndDescription.tsx b/apps/admin-x-settings/src/components/settings/general/TitleAndDescription.tsx index a62e460c80..b66146be2c 100644 --- a/apps/admin-x-settings/src/components/settings/general/TitleAndDescription.tsx +++ b/apps/admin-x-settings/src/components/settings/general/TitleAndDescription.tsx @@ -4,6 +4,7 @@ import SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupConten import TextField from '../../../admin-x-ds/global/form/TextField'; import useSettingGroup from '../../../hooks/useSettingGroup'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const TitleAndDescription: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -82,4 +83,4 @@ const TitleAndDescription: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default TitleAndDescription; +export default withErrorBoundary(TitleAndDescription, 'Title & description'); diff --git a/apps/admin-x-settings/src/components/settings/general/Twitter.tsx b/apps/admin-x-settings/src/components/settings/general/Twitter.tsx index 24e0077a02..335d15bff2 100644 --- a/apps/admin-x-settings/src/components/settings/general/Twitter.tsx +++ b/apps/admin-x-settings/src/components/settings/general/Twitter.tsx @@ -8,6 +8,7 @@ import useSettingGroup from '../../../hooks/useSettingGroup'; import {ReactComponent as TwitterLogo} from '../../../admin-x-ds/assets/images/twitter-logo.svg'; import {getImageUrl, useUploadImage} from '../../../api/images'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const Twitter: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -141,4 +142,4 @@ const Twitter: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Twitter; +export default withErrorBoundary(Twitter, 'Twitter card'); diff --git a/apps/admin-x-settings/src/components/settings/general/Users.tsx b/apps/admin-x-settings/src/components/settings/general/Users.tsx index c45488aabb..bd24ce0306 100644 --- a/apps/admin-x-settings/src/components/settings/general/Users.tsx +++ b/apps/admin-x-settings/src/components/settings/general/Users.tsx @@ -14,6 +14,7 @@ import {UserInvite, useAddInvite, useDeleteInvite} from '../../../api/invites'; import {generateAvatarColor, getInitials} from '../../../utils/helpers'; import {showToast} from '../../../admin-x-ds/global/Toast'; import {useGlobalData} from '../../providers/GlobalDataProvider'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; interface OwnerProps { user: User; @@ -258,4 +259,4 @@ const Users: React.FC<{ keywords: string[], highlight?: boolean }> = ({keywords, ); }; -export default Users; +export default withErrorBoundary(Users, 'Staff'); diff --git a/apps/admin-x-settings/src/components/settings/membership/Access.tsx b/apps/admin-x-settings/src/components/settings/membership/Access.tsx index a2cf886ea5..147ac55624 100644 --- a/apps/admin-x-settings/src/components/settings/membership/Access.tsx +++ b/apps/admin-x-settings/src/components/settings/membership/Access.tsx @@ -8,6 +8,7 @@ import {GroupBase, MultiValue} from 'react-select'; import {getOptionLabel} from '../../../utils/helpers'; import {getSettingValues} from '../../../api/settings'; import {useBrowseTiers} from '../../../api/tiers'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const MEMBERS_SIGNUP_ACCESS_OPTIONS = [ { @@ -190,4 +191,4 @@ const Access: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Access; +export default withErrorBoundary(Access, 'Access'); diff --git a/apps/admin-x-settings/src/components/settings/membership/Analytics.tsx b/apps/admin-x-settings/src/components/settings/membership/Analytics.tsx index 67455f2b3a..9cf589dc10 100644 --- a/apps/admin-x-settings/src/components/settings/membership/Analytics.tsx +++ b/apps/admin-x-settings/src/components/settings/membership/Analytics.tsx @@ -6,6 +6,7 @@ import Toggle from '../../../admin-x-ds/global/form/Toggle'; import useSettingGroup from '../../../hooks/useSettingGroup'; import {getSettingValues} from '../../../api/settings'; import {usePostsExports} from '../../../api/posts'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const Analytics: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -105,4 +106,4 @@ const Analytics: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Analytics; +export default withErrorBoundary(Analytics, 'Analytics'); diff --git a/apps/admin-x-settings/src/components/settings/membership/Portal.tsx b/apps/admin-x-settings/src/components/settings/membership/Portal.tsx index 5006336086..03cd4619a5 100644 --- a/apps/admin-x-settings/src/components/settings/membership/Portal.tsx +++ b/apps/admin-x-settings/src/components/settings/membership/Portal.tsx @@ -2,6 +2,7 @@ import Button from '../../../admin-x-ds/global/Button'; import React from 'react'; import SettingGroup from '../../../admin-x-ds/settings/SettingGroup'; import useRouting from '../../../hooks/useRouting'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const Portal: React.FC<{ keywords: string[] }> = ({keywords}) => { const {updateRoute} = useRouting(); @@ -22,4 +23,4 @@ const Portal: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Portal; +export default withErrorBoundary(Portal, 'Portal settings'); diff --git a/apps/admin-x-settings/src/components/settings/membership/Tiers.tsx b/apps/admin-x-settings/src/components/settings/membership/Tiers.tsx index 4361d40634..7a5facc9a5 100644 --- a/apps/admin-x-settings/src/components/settings/membership/Tiers.tsx +++ b/apps/admin-x-settings/src/components/settings/membership/Tiers.tsx @@ -8,6 +8,7 @@ import useRouting from '../../../hooks/useRouting'; import {Tier, getActiveTiers, getArchivedTiers, useBrowseTiers} from '../../../api/tiers'; import {checkStripeEnabled} from '../../../api/settings'; import {useGlobalData} from '../../providers/GlobalDataProvider'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const StripeConnectedButton: React.FC<{className?: string; onClick: () => void;}> = ({className, onClick}) => { className = clsx( @@ -83,4 +84,4 @@ const Tiers: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Tiers; +export default withErrorBoundary(Tiers, 'Tiers'); diff --git a/apps/admin-x-settings/src/components/settings/membership/TipsOrDonations.tsx b/apps/admin-x-settings/src/components/settings/membership/TipsOrDonations.tsx index 9b7ef55321..ac4e4072bd 100644 --- a/apps/admin-x-settings/src/components/settings/membership/TipsOrDonations.tsx +++ b/apps/admin-x-settings/src/components/settings/membership/TipsOrDonations.tsx @@ -9,6 +9,7 @@ import useSettingGroup from '../../../hooks/useSettingGroup'; import {confirmIfDirty} from '../../../utils/modals'; import {currencySelectGroups, getSymbol, validateCurrencyAmount} from '../../../utils/currency'; import {getSettingValues} from '../../../api/settings'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const TipsOrDonations: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -132,4 +133,4 @@ const TipsOrDonations: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default TipsOrDonations; +export default withErrorBoundary(TipsOrDonations, 'Tips or donations'); diff --git a/apps/admin-x-settings/src/components/settings/site/AnnouncementBar.tsx b/apps/admin-x-settings/src/components/settings/site/AnnouncementBar.tsx index 4cee7c4ed1..51df5ebdf0 100644 --- a/apps/admin-x-settings/src/components/settings/site/AnnouncementBar.tsx +++ b/apps/admin-x-settings/src/components/settings/site/AnnouncementBar.tsx @@ -2,6 +2,7 @@ import Button from '../../../admin-x-ds/global/Button'; import React from 'react'; import SettingGroup from '../../../admin-x-ds/settings/SettingGroup'; import useRouting from '../../../hooks/useRouting'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const AnnouncementBar: React.FC<{ keywords: string[] }> = ({keywords}) => { const {updateRoute} = useRouting(); @@ -21,4 +22,4 @@ const AnnouncementBar: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default AnnouncementBar; +export default withErrorBoundary(AnnouncementBar, 'Announcement bar'); diff --git a/apps/admin-x-settings/src/components/settings/site/DesignSetting.tsx b/apps/admin-x-settings/src/components/settings/site/DesignSetting.tsx index 698b905c41..0eb13e88b6 100644 --- a/apps/admin-x-settings/src/components/settings/site/DesignSetting.tsx +++ b/apps/admin-x-settings/src/components/settings/site/DesignSetting.tsx @@ -2,6 +2,7 @@ import Button from '../../../admin-x-ds/global/Button'; import React from 'react'; import SettingGroup from '../../../admin-x-ds/settings/SettingGroup'; import useRouting from '../../../hooks/useRouting'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const DesignSetting: React.FC<{ keywords: string[] }> = ({keywords}) => { const {updateRoute} = useRouting(); @@ -21,4 +22,4 @@ const DesignSetting: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default DesignSetting; +export default withErrorBoundary(DesignSetting, 'Branding and design'); diff --git a/apps/admin-x-settings/src/components/settings/site/Navigation.tsx b/apps/admin-x-settings/src/components/settings/site/Navigation.tsx index edacbe809c..2ad07ed732 100644 --- a/apps/admin-x-settings/src/components/settings/site/Navigation.tsx +++ b/apps/admin-x-settings/src/components/settings/site/Navigation.tsx @@ -2,6 +2,7 @@ import Button from '../../../admin-x-ds/global/Button'; import React from 'react'; import SettingGroup from '../../../admin-x-ds/settings/SettingGroup'; import useRouting from '../../../hooks/useRouting'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const Navigation: React.FC<{ keywords: string[] }> = ({keywords}) => { const {updateRoute} = useRouting(); @@ -21,4 +22,4 @@ const Navigation: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Navigation; +export default withErrorBoundary(Navigation, 'Navigation'); diff --git a/apps/admin-x-settings/src/components/settings/site/Recommendations.tsx b/apps/admin-x-settings/src/components/settings/site/Recommendations.tsx index c6e2cd966f..5b01cf6853 100644 --- a/apps/admin-x-settings/src/components/settings/site/Recommendations.tsx +++ b/apps/admin-x-settings/src/components/settings/site/Recommendations.tsx @@ -8,6 +8,7 @@ import TabView from '../../../admin-x-ds/global/TabView'; import useRouting from '../../../hooks/useRouting'; import useSettingGroup from '../../../hooks/useSettingGroup'; import {useBrowseRecommendations} from '../../../api/recommendations'; +import {withErrorBoundary} from '../../../admin-x-ds/global/ErrorBoundary'; const Recommendations: React.FC<{ keywords: string[] }> = ({keywords}) => { const { @@ -74,4 +75,4 @@ const Recommendations: React.FC<{ keywords: string[] }> = ({keywords}) => { ); }; -export default Recommendations; +export default withErrorBoundary(Recommendations, 'Recommendations');