fix: settings error layout (#7674)

Fixes: #7460 

![Screenshot from 2024-10-14
15-27-52](https://github.com/user-attachments/assets/bbae5c6f-0b36-4f98-92c5-de27b1eb06ad)

**Changes & Why**

Since all the settings pages lie in the Outlet of DefaultLayout, there
was no way to handle it apart from creating a separate errorFallback for
the settings route.
So, I created a settingsErrorFallback component that uses the same
styling of settings pages.
Created ErrorBoundaryWrapper that checks if its settings route then show
SettingsErrorFallback else show GenericErrorFallback.
Now, for the breadcrumb part. I found that all the settings pages use
hardcoded title. So, I created generateBreadcrumbLinks function that
will provide different title and links based on how it's respective
settings page has them.
If this approach looks fine, I will add the other remaining titles and
links to the generateBreadcrumbLinks function and move that whole
function to its separate file. And will fix linting errors.

If there is any different approach to handle it, lemme know. I'm happy
to implement it.
This commit is contained in:
Harsh Singh
2024-11-04 22:57:29 +05:30
committed by GitHub
parent 66c0aa5e52
commit 8e82b08acb
4 changed files with 37 additions and 34 deletions

View File

@ -1,6 +1,6 @@
import * as Sentry from '@sentry/react';
import { ErrorInfo, ReactNode } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import * as Sentry from '@sentry/react';
import { GenericErrorFallback } from '@/error-handler/components/GenericErrorFallback';

View File

@ -1,5 +1,6 @@
import { ThemeProvider, useTheme } from '@emotion/react';
import isEmpty from 'lodash.isempty';
import { PageBody } from '@/ui/layout/page/components/PageBody';
import { PageContainer } from '@/ui/layout/page/components/PageContainer';
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
import { useEffect, useState } from 'react';
import { FallbackProps } from 'react-error-boundary';
import { useLocation } from 'react-router-dom';
@ -11,7 +12,6 @@ import {
AnimatedPlaceholderEmptyTitle,
Button,
IconRefresh,
THEME_LIGHT,
} from 'twenty-ui';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
@ -31,27 +31,28 @@ export const GenericErrorFallback = ({
}
}, [previousLocation, location, resetErrorBoundary]);
const theme = useTheme();
return (
<ThemeProvider theme={isEmpty(theme) ? THEME_LIGHT : theme}>
<AnimatedPlaceholderEmptyContainer>
<AnimatedPlaceholder type="errorIndex" />
<AnimatedPlaceholderEmptyTextContainer>
<AnimatedPlaceholderEmptyTitle>
Servers on a coffee break
</AnimatedPlaceholderEmptyTitle>
<AnimatedPlaceholderEmptySubTitle>
{error.message}
</AnimatedPlaceholderEmptySubTitle>
</AnimatedPlaceholderEmptyTextContainer>
<Button
Icon={IconRefresh}
title="Reload"
variant={'secondary'}
onClick={() => resetErrorBoundary()}
/>
</AnimatedPlaceholderEmptyContainer>
</ThemeProvider>
<PageContainer>
<PageHeader />
<PageBody>
<AnimatedPlaceholderEmptyContainer>
<AnimatedPlaceholder type="errorIndex" />
<AnimatedPlaceholderEmptyTextContainer>
<AnimatedPlaceholderEmptyTitle>
Servers on a coffee break
</AnimatedPlaceholderEmptyTitle>
<AnimatedPlaceholderEmptySubTitle>
{error.message}
</AnimatedPlaceholderEmptySubTitle>
</AnimatedPlaceholderEmptyTextContainer>
<Button
Icon={IconRefresh}
title="Reload"
variant={'secondary'}
onClick={() => resetErrorBoundary()}
/>
</AnimatedPlaceholderEmptyContainer>
</PageBody>
</PageContainer>
);
};

View File

@ -10,11 +10,11 @@ import { SignInBackgroundMockPage } from '@/sign-in-background-mock/components/S
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
import { NAV_DRAWER_WIDTHS } from '@/ui/navigation/navigation-drawer/constants/NavDrawerWidths';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useScreenSize } from 'twenty-ui';
import { css, Global, useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { AnimatePresence, LayoutGroup, motion } from 'framer-motion';
import { Outlet } from 'react-router-dom';
import { useScreenSize } from 'twenty-ui';
const StyledLayout = styled.div`
background: ${({ theme }) => theme.background.noisy};

View File

@ -80,7 +80,7 @@ const StyledTopBarButtonContainer = styled.div`
`;
type PageHeaderProps = {
title: ReactNode;
title?: ReactNode;
hasClosePageButton?: boolean;
onClosePage?: () => void;
hasPaginationButtons?: boolean;
@ -147,13 +147,15 @@ export const PageHeader = ({
</>
)}
{Icon && <Icon size={theme.icon.size.md} />}
<StyledTitleContainer data-testid="top-bar-title">
{typeof title === 'string' ? (
<OverflowingTextWithTooltip text={title} />
) : (
title
)}
</StyledTitleContainer>
{title && (
<StyledTitleContainer data-testid="top-bar-title">
{typeof title === 'string' ? (
<OverflowingTextWithTooltip text={title} />
) : (
title
)}
</StyledTitleContainer>
)}
</StyledTopBarIconStyledTitleContainer>
</StyledLeftContainer>
<StyledPageActionContainer>{children}</StyledPageActionContainer>