feat: add diagnostics page and broken link checker
All checks were successful
Deploy eolas-app / deploy (push) Successful in 1m7s

This commit is contained in:
Thomas Bishop 2025-12-22 17:08:40 +00:00
parent 7454a42f80
commit caef8ddf6b
3 changed files with 163 additions and 69 deletions

View file

@ -7,6 +7,7 @@ import TagTemplate from "./templates/TagTemplate"
import EntryTemplate from "./templates/EntryTemplate"
import Settings from "./pages/settings"
import About from "./pages/about"
import Diagnostics from "./pages/diagnostics"
const queryClient = new QueryClient({
defaultOptions: {
@ -27,6 +28,7 @@ export default function App() {
<Routes>
<Route index element={<Home />} />
<Route path="/settings" element={<Settings />} />
<Route path="/diagnostics" element={<Diagnostics />} />
<Route path="/about" element={<About />} />
<Route path="/entries/:entry" element={<EntryTemplate />} />
<Route path="/tags/:tag" element={<TagTemplate />} />

View file

@ -1,4 +1,14 @@
import { Info, FileText, Waypoints, SquareLibrary, Settings, ChevronRight } from "lucide-react"
import {
Info,
FileText,
Waypoints,
SquareLibrary,
Settings,
ChevronRight,
TestTubeDiagonal,
TestTube2,
FlaskConical,
} from "lucide-react"
import {
Sidebar,
@ -21,6 +31,11 @@ const footerMenu = [
url: "/about",
icon: Info,
},
{
title: "Diagnostics",
url: "/diagnostics",
icon: FlaskConical,
},
{
title: "Settings",

77
src/pages/diagnostics.tsx Normal file
View file

@ -0,0 +1,77 @@
import { Button } from "@/components/ui/button"
import PageTemplate from "@/templates/PageTemplate"
import api from "@/api/eolas-api"
import { useQuery } from "@tanstack/react-query"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { Link } from "react-router"
const PageBody = () => {
const { data, refetch, isLoading, error } = useQuery({
queryKey: ["diagnostics_broken-link"],
queryFn: () => api.get("/diagnostics/broken-links").then((res) => res.data),
enabled: false,
})
data?.data.sort((a, b) => a.source_entry_title.localeCompare(b.source_entry_title))
return (
<div className="max-w-2xl p-4 lg:p-6">
<div className="flex flex-row justify-between">
<h3 className="font-semibold mb-4">Broken links</h3>
<Button size="sm" variant="secondary" onClick={() => refetch()}>
Find broken links
</Button>
</div>
{isLoading ? (
<p>Generating list...</p>
) : error ? (
<div className="p-4 text-sm dark:text-red-300 text-red-700">
<div className="p-2 border-2 dark:border-red-800 border-red-500 dark:bg-red-900 bg-red-300">
Error fetching broken links
</div>{" "}
</div>
) : (
data && (
<>
<p className="leading-[1.5] mb-4 not-first:mt-4">
There are <b>{data?.count}</b> broken links.
</p>
<Table>
<TableHeader>
<TableRow>
<TableHead>Source entry</TableHead>
<TableHead>Broken link</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data?.data.map((link, i) => (
<TableRow key={i}>
<TableCell>
<Link
to={`/entries/${link?.source_entry_title}`} // Fixed: to={ instead of to=
className="text-foreground underline-offset-3 text-sm underline hover:text-gray-700 dark:hover:text-green-300"
>
{link?.source_entry_title.replace(/_/g, " ")}{" "}
</Link>{" "}
</TableCell>
<TableCell>{link?.broken_link_title}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</>
)
)}
</div>
)
}
export default function Diagnostics() {
return <PageTemplate pageTitle="Diagnostics" pageBody={<PageBody />} />
}