feat: add admin links management and updaterup page

- Implemented AdminLinksPage for managing link entries with admin role check.
- Created API routes for fetching, updating, and deleting link entries.
- Added ProductTabs component for navigation between Backerup and Updaterup.
- Developed UpdaterupPage with detailed features, setup instructions, and statistics.
- Introduced links database functionality for runtime-editable link overrides.
This commit is contained in:
Anders Böttcher
2026-05-13 10:53:21 +02:00
parent 33e339bde6
commit 984b282a95
16 changed files with 1342 additions and 51 deletions
+20 -11
View File
@@ -2,8 +2,10 @@ import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import Link from "next/link";
import { LINKS } from "@/lib/links";
import { getLinks } from "@/lib/links-db";
import { getSession } from "@/lib/session";
import LogoutButton from "./components/LogoutButton";
import ProductTabs from "./components/ProductTabs";
import "./globals.css";
const geistSans = Geist({
@@ -44,6 +46,7 @@ export default async function RootLayout({
children: React.ReactNode;
}>) {
const session = await getSession();
const links = await getLinks();
return (
<html
lang="en"
@@ -70,7 +73,8 @@ export default async function RootLayout({
{/* ── Nav ── */}
<header className="sticky top-0 z-50 glass-heavy">
<div className="mx-auto flex max-w-6xl items-center justify-between px-6 py-4">
<Link href="/" className="flex items-center gap-2.5 group">
{/* Logo */}
<Link href="/" className="flex items-center gap-2.5 group shrink-0">
<div
className="w-8 h-8 rounded-lg flex items-center justify-center shrink-0"
style={{ background: "linear-gradient(135deg, #22d3ee, #0891b2)" }}
@@ -78,11 +82,16 @@ export default async function RootLayout({
<DockerIcon className="w-4 h-4 text-slate-900" />
</div>
<span className="text-base font-bold text-white group-hover:text-cyan-300 transition-colors tracking-tight">
Backerup
DoomLabs
</span>
</Link>
<nav className="flex items-center gap-1 text-sm font-medium">
{/* Product tab switcher */}
<div className="flex-1 flex justify-center px-4">
<ProductTabs />
</div>
<nav className="flex items-center gap-1 text-sm font-medium shrink-0">
<Link
href="/browse"
className="nav-link px-3 py-2 rounded-lg text-slate-400 hover:text-white hover:bg-white/5 transition-all"
@@ -96,7 +105,7 @@ export default async function RootLayout({
Share
</Link>
<a
href={LINKS.gitea}
href={links.gitea}
target="_blank"
rel="noopener noreferrer"
className="nav-link px-3 py-2 rounded-lg text-slate-400 hover:text-white hover:bg-white/5 transition-all flex items-center gap-1.5"
@@ -162,7 +171,7 @@ export default async function RootLayout({
</p>
<div className="mt-6 flex gap-3">
<a
href={LINKS.gitea}
href={links.gitea}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 px-4 py-2 rounded-lg border border-white/10 bg-white/3 text-xs text-slate-400 hover:text-white hover:border-white/20 transition-all"
@@ -179,8 +188,8 @@ export default async function RootLayout({
<ul className="space-y-3 text-sm text-slate-500">
<li><Link href="/browse" className="hover:text-cyan-400 transition-colors">Browse configs</Link></li>
<li><Link href="/share" className="hover:text-cyan-400 transition-colors">Share a backup</Link></li>
<li><a href={LINKS.docs} className="hover:text-cyan-400 transition-colors">Documentation</a></li>
<li><a href={LINKS.giteaReleases} className="hover:text-cyan-400 transition-colors">Changelog</a></li>
<li><a href={links.docs} className="hover:text-cyan-400 transition-colors">Documentation</a></li>
<li><a href={links.giteaReleases} className="hover:text-cyan-400 transition-colors">Changelog</a></li>
</ul>
</div>
@@ -188,10 +197,10 @@ export default async function RootLayout({
<div>
<h3 className="text-xs font-semibold uppercase tracking-widest text-slate-500 mb-4">Community</h3>
<ul className="space-y-3 text-sm text-slate-500">
<li><a href={LINKS.gitea} className="hover:text-cyan-400 transition-colors">Gitea</a></li>
<li><a href={LINKS.giteaIssues} className="hover:text-cyan-400 transition-colors">Issues</a></li>
<li><a href={LINKS.giteaDiscussions} className="hover:text-cyan-400 transition-colors">Discussions</a></li>
<li><a href={LINKS.giteaContributing} className="hover:text-cyan-400 transition-colors">Contributing</a></li>
<li><a href={links.gitea} className="hover:text-cyan-400 transition-colors">Gitea</a></li>
<li><a href={links.giteaIssues} className="hover:text-cyan-400 transition-colors">Issues</a></li>
<li><a href={links.giteaDiscussions} className="hover:text-cyan-400 transition-colors">Discussions</a></li>
<li><a href={links.giteaContributing} className="hover:text-cyan-400 transition-colors">Contributing</a></li>
</ul>
</div>
</div>