add ErrorBoundary around layout outlet
Some checks failed
continuous-integration/drone/pr Build is failing

This commit is contained in:
Martti Malmi 2023-11-26 11:27:30 +02:00
parent 920f8ae20d
commit a592974b93
3 changed files with 85 additions and 40 deletions

View File

@ -0,0 +1,39 @@
import React from "react";
interface ErrorBoundaryState {
hasError: boolean;
errorMessage?: string;
}
interface ErrorBoundaryProps {
children: React.ReactNode;
}
export default class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return { hasError: true, errorMessage: error.message };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error("Caught an error:", error, errorInfo);
}
render() {
if (this.state.hasError) {
// Render any custom fallback UI with the error message
return (
<div className="p-2">
<h1>Something went wrong.</h1>
<p>Error: {this.state.errorMessage}</p>
</div>
);
}
return this.props.children;
}
}

View File

@ -22,6 +22,7 @@ import Toaster from "@/Toaster";
import useLogin from "@/Hooks/useLogin"; import useLogin from "@/Hooks/useLogin";
import { LongFormText } from "@/Element/Event/LongFormText"; import { LongFormText } from "@/Element/Event/LongFormText";
import NavSidebar from "@/Pages/Layout/NavSidebar"; import NavSidebar from "@/Pages/Layout/NavSidebar";
import ErrorBoundary from "@/Element/ErrorBoundary";
type Cols = "notes" | "articles" | "media" | "streams" | "notifications"; type Cols = "notes" | "articles" | "media" | "streams" | "notifications";
@ -68,46 +69,48 @@ export function SnortDeckLayout() {
reset: () => setDeckState({}), reset: () => setDeckState({}),
}}> }}>
<NavSidebar narrow={true} /> <NavSidebar narrow={true} />
<div className="deck-cols"> <ErrorBoundary>
{cols.map(c => { <div className="deck-cols">
switch (c) { {cols.map(c => {
case "notes": switch (c) {
return <NotesCol />; case "notes":
case "media": return <NotesCol />;
return <MediaCol setThread={t => setDeckState({ thread: t })} />; case "media":
case "articles": return <MediaCol setThread={t => setDeckState({ thread: t })} />;
return <ArticlesCol />; case "articles":
case "notifications": return <ArticlesCol />;
return <NotificationsCol setThread={t => setDeckState({ thread: t })} />; case "notifications":
} return <NotificationsCol setThread={t => setDeckState({ thread: t })} />;
})} }
</div> })}
{deckState.thread && ( </div>
<> {deckState.thread && (
<Modal id="thread-overlay" onClose={() => setDeckState({})} className="thread-overlay thread"> <>
<ThreadContextWrapper link={deckState.thread}> <Modal id="thread-overlay" onClose={() => setDeckState({})} className="thread-overlay thread">
<SpotlightFromThread onClose={() => setDeckState({})} /> <ThreadContextWrapper link={deckState.thread}>
<div> <SpotlightFromThread onClose={() => setDeckState({})} />
<Thread onBack={() => setDeckState({})} disableSpotlight={true} /> <div>
<Thread onBack={() => setDeckState({})} disableSpotlight={true} />
</div>
</ThreadContextWrapper>
</Modal>
</>
)}
{deckState.article && (
<>
<Modal
id="thread-overlay-article"
onClose={() => setDeckState({})}
className="thread-overlay long-form"
onClick={() => setDeckState({})}>
<div onClick={e => e.stopPropagation()}>
<LongFormText ev={deckState.article} isPreview={false} related={[]} />
</div> </div>
</ThreadContextWrapper> </Modal>
</Modal> </>
</> )}
)} <Toaster />
{deckState.article && ( </ErrorBoundary>
<>
<Modal
id="thread-overlay-article"
onClose={() => setDeckState({})}
className="thread-overlay long-form"
onClick={() => setDeckState({})}>
<div onClick={e => e.stopPropagation()}>
<LongFormText ev={deckState.article} isPreview={false} related={[]} />
</div>
</Modal>
</>
)}
<Toaster />
</DeckContext.Provider> </DeckContext.Provider>
</div> </div>
); );

View File

@ -17,6 +17,7 @@ import AccountHeader from "./AccountHeader";
import RightColumn from "./RightColumn"; import RightColumn from "./RightColumn";
import { LogoHeader } from "./LogoHeader"; import { LogoHeader } from "./LogoHeader";
import useLoginFeed from "@/Feed/LoginFeed"; import useLoginFeed from "@/Feed/LoginFeed";
import ErrorBoundary from "@/Element/ErrorBoundary";
export default function Index() { export default function Index() {
const location = useLocation(); const location = useLocation();
@ -62,7 +63,9 @@ export default function Index() {
<div className="flex flex-row w-full"> <div className="flex flex-row w-full">
<NavSidebar /> <NavSidebar />
<div className="flex flex-1 flex-col overflow-x-hidden"> <div className="flex flex-1 flex-col overflow-x-hidden">
<Outlet /> <ErrorBoundary>
<Outlet />
</ErrorBoundary>
</div> </div>
<RightColumn /> <RightColumn />
</div> </div>