diff --git a/package.json b/package.json
index 823f447..7e6edbe 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"react": "^18.2.0",
"react-cookie": "^5.0.0",
"react-dom": "^18.2.0",
+ "react-error-boundary": "^4.0.11",
"react-helmet": "^6.1.0",
"react-router-dom": "^6.14.1",
"react-simple-code-editor": "^0.13.1",
diff --git a/src/App.tsx b/src/App.tsx
index b22383a..af26dd9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -13,8 +13,10 @@ import Nodes from "./pages/Nodes";
import Node from "./pages/Node";
import StatsNodesLock from "./pages/StatsNodesLock";
import StatsNodesJobs from "./pages/StatsNodesJobs";
+import { ErrorBoundary } from "react-error-boundary";
import "./App.css";
+import ErrorFallback from "./components/ErrorFallback";
type AppProps = {
darkMode: boolean;
@@ -37,19 +39,21 @@ function App(props: AppProps) {
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
-
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
);
diff --git a/src/components/CodeBlock/index.jsx b/src/components/CodeBlock/index.jsx
new file mode 100644
index 0000000..9a3c0ba
--- /dev/null
+++ b/src/components/CodeBlock/index.jsx
@@ -0,0 +1,34 @@
+import Editor from "react-simple-code-editor";
+import { highlight, languages } from "prismjs/components/prism-core";
+import 'prismjs/components/prism-clike';
+import "prismjs/components/prism-yaml";
+import 'prismjs/components/prism-javascript';
+
+export default function CodeBlock(props) {
+ const language = languages[props.language];
+ if ( ! props.value ) return null;
+ return (
+ {
+ if (!! language ) return highlight(code, language);
+ return code;
+ }}
+ style={{
+ fontFamily: [
+ "ui-monospace",
+ "SFMono-Regular",
+ '"SF Mono"',
+ "Menlo",
+ "Consolas",
+ "Liberation Mono",
+ '"Lucida Console"',
+ "Courier",
+ "monospace",
+ ].join(","),
+ textAlign: "initial",
+ }}
+ />
+ )
+}
diff --git a/src/components/ErrorFallback/index.tsx b/src/components/ErrorFallback/index.tsx
new file mode 100644
index 0000000..f5f5815
--- /dev/null
+++ b/src/components/ErrorFallback/index.tsx
@@ -0,0 +1,24 @@
+import Typography from "@mui/material/Typography";
+import Link from "../Link";
+
+import CodeBlock from "../CodeBlock";
+
+export default function ErrorFallback(props: {error: Error}) {
+ return (
+
+
+ Apologies - the component encountered an error. Please
+
+ file an issue
+
+ including this error message:
+
+
+
+ );
+}
diff --git a/src/components/JobList/index.tsx b/src/components/JobList/index.tsx
index 8fba7d1..ce40d37 100644
--- a/src/components/JobList/index.tsx
+++ b/src/components/JobList/index.tsx
@@ -202,7 +202,7 @@ type JobListProps = {
export default function JobList({ query, sortMode }: JobListProps) {
const options = useDefaultTableOptions();
- const data = query.data?.jobs || [];
+ const data = (query.data?.jobs || []).filter(item => item.id);
const table = useMaterialReactTable({
...options,
columns,
diff --git a/src/pages/Job/index.jsx b/src/pages/Job/index.jsx
index 89997a0..cf06f74 100644
--- a/src/pages/Job/index.jsx
+++ b/src/pages/Job/index.jsx
@@ -13,14 +13,12 @@ import HighlightOffIcon from "@mui/icons-material/HighlightOff";
import FolderIcon from '@mui/icons-material/Folder';
import formatDuration from "date-fns/formatDuration";
import { isValid, parse } from "date-fns";
-import Editor from "react-simple-code-editor";
-import { highlight, languages } from "prismjs/components/prism-core";
-import "prismjs/components/prism-yaml";
import "prismjs/themes/prism-tomorrow.css";
import { Helmet } from "react-helmet";
import YAML from "json-to-pretty-yaml";
import Link from "../../components/Link";
+import CodeBlock from "../../components/CodeBlock";
import { useJob } from "../../lib/paddles";
import { getDuration, dirName } from "../../lib/utils";
@@ -150,25 +148,7 @@ function JobDetails({ query }) {
if (query.isError) return "!!!";
const code = YAML.stringify(query.data);
return (
- highlight(code, languages.yaml)}
- style={{
- fontFamily: [
- "ui-monospace",
- "SFMono-Regular",
- '"SF Mono"',
- "Menlo",
- "Consolas",
- "Liberation Mono",
- '"Lucida Console"',
- "Courier",
- "monospace",
- ].join(","),
- textAlign: "initial",
- }}
- />
+
);
}