mirror of
https://gitlab.w-hs.de/an14051/backerup-website.git
synced 2026-07-27 17:35:29 +00:00
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:
@@ -0,0 +1,34 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
export default function ProductTabs() {
|
||||
const pathname = usePathname();
|
||||
const isUpdaterup = pathname.startsWith("/updaterup");
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 rounded-xl border border-white/8 bg-white/3 p-1">
|
||||
<Link
|
||||
href="/"
|
||||
className={`px-4 py-1.5 rounded-lg text-sm font-semibold transition-all ${
|
||||
!isUpdaterup
|
||||
? "bg-cyan-500/20 text-cyan-300 border border-cyan-500/30 shadow-sm"
|
||||
: "text-slate-400 hover:text-slate-200 hover:bg-white/5"
|
||||
}`}
|
||||
>
|
||||
Backerup
|
||||
</Link>
|
||||
<Link
|
||||
href="/updaterup"
|
||||
className={`px-4 py-1.5 rounded-lg text-sm font-semibold transition-all ${
|
||||
isUpdaterup
|
||||
? "bg-violet-500/20 text-violet-300 border border-violet-500/30 shadow-sm"
|
||||
: "text-slate-400 hover:text-slate-200 hover:bg-white/5"
|
||||
}`}
|
||||
>
|
||||
Updaterup
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,39 +3,49 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { LINKS } from "@/lib/links";
|
||||
|
||||
export interface TerminalLinks {
|
||||
dockerImage?: string;
|
||||
uiPort?: string;
|
||||
updaterupDockerImage?: string;
|
||||
}
|
||||
|
||||
interface Line {
|
||||
type: "comment" | "cmd" | "cmd-cont" | "output" | "success" | "error";
|
||||
text: string;
|
||||
copyable?: boolean;
|
||||
}
|
||||
|
||||
function buildDockerRunLines(): Line[] {
|
||||
function buildDockerRunLines(links: TerminalLinks): Line[] {
|
||||
const dockerImage = links.dockerImage ?? LINKS.dockerImage;
|
||||
const uiPort = links.uiPort ?? LINKS.uiPort;
|
||||
return [
|
||||
{ type: "comment", text: "# Quick start: Run Backerup directly" },
|
||||
{ type: "cmd", text: "docker run -d --name backerup \\", copyable: true },
|
||||
{ type: "cmd-cont", text: ` -p ${LINKS.uiPort}:80 \\`, copyable: true },
|
||||
{ type: "cmd-cont", text: ` -p ${uiPort}:80 \\`, copyable: true },
|
||||
{ type: "cmd-cont", text: " -v /var/run/docker.sock:/var/run/docker.sock \\", copyable: true },
|
||||
{ type: "cmd-cont", text: " -v ${BACKUP_DIR:-/backups}:/backups \\", copyable: true },
|
||||
{ type: "cmd-cont", text: " -v backerup-config:/app/config \\", copyable: true },
|
||||
{ type: "cmd-cont", text: " -e BACKUP_DIR=/backups \\", copyable: true },
|
||||
{ type: "cmd-cont", text: " -e BACKUP_CONFIG_DIR=/app/config \\", copyable: true },
|
||||
{ type: "cmd-cont", text: ` -e HOST_BACKUP_DIR=/backups \\`, copyable: true },
|
||||
{ type: "cmd-cont", text: ` ${LINKS.dockerImage}`, copyable: true },
|
||||
{ type: "cmd-cont", text: ` ${dockerImage}`, copyable: true },
|
||||
{ type: "output", text: "a7f82c3d1b09" },
|
||||
{ type: "success", text: "✓ Container started" },
|
||||
{ type: "success", text: "✓ Ready at http://localhost:8080" },
|
||||
{ type: "success", text: `✓ Ready at http://localhost:${uiPort}` },
|
||||
];
|
||||
}
|
||||
|
||||
function buildDockerComposeLines(): Line[] {
|
||||
function buildDockerComposeLines(links: TerminalLinks): Line[] {
|
||||
const dockerImage = links.dockerImage ?? LINKS.dockerImage;
|
||||
const uiPort = links.uiPort ?? LINKS.uiPort;
|
||||
return [
|
||||
{ type: "comment", text: "# Using docker-compose for easier management" },
|
||||
{ type: "cmd", text: "cat > docker-compose.yml << 'EOF'", copyable: false },
|
||||
{ type: "output", text: "services:" },
|
||||
{ type: "output", text: " backerup:" },
|
||||
{ type: "output", text: ` image: ${LINKS.dockerImage}` },
|
||||
{ type: "output", text: ` image: ${dockerImage}` },
|
||||
{ type: "output", text: " ports:" },
|
||||
{ type: "output", text: ` - \"${LINKS.uiPort}:80\"` },
|
||||
{ type: "output", text: ` - \"${uiPort}:80\"` },
|
||||
{ type: "output", text: " volumes:" },
|
||||
{ type: "output", text: " - /var/run/docker.sock:/var/run/docker.sock" },
|
||||
{ type: "output", text: " - ${BACKUP_DIR:-/backups}:/backups" },
|
||||
@@ -51,12 +61,56 @@ function buildDockerComposeLines(): Line[] {
|
||||
{ type: "success", text: "✓ docker-compose.yml created" },
|
||||
{ type: "cmd", text: "docker compose up -d", copyable: false },
|
||||
{ type: "output", text: "[+] Building 2.3s (12/12) FINISHED" },
|
||||
{ type: "success", text: `✓ Ready at http://localhost:${uiPort}` },
|
||||
];
|
||||
}
|
||||
|
||||
function buildUpdaterupRunLines(links: TerminalLinks): Line[] {
|
||||
const updaterupDockerImage = links.updaterupDockerImage ?? LINKS.updaterupDockerImage;
|
||||
return [
|
||||
{ type: "comment", text: "# Quick start: Run Updaterup directly" },
|
||||
{ type: "cmd", text: "docker run -d --name updaterup \\", copyable: true },
|
||||
{ type: "cmd-cont", text: " -p 8080:80 \\", copyable: true },
|
||||
{ type: "cmd-cont", text: " -v /var/run/docker.sock:/var/run/docker.sock \\", copyable: true },
|
||||
{ type: "cmd-cont", text: " -v updaterup-config:/app/config \\", copyable: true },
|
||||
{ type: "cmd-cont", text: ` ${updaterupDockerImage}`, copyable: true },
|
||||
{ type: "output", text: "b3c91d2e4f07" },
|
||||
{ type: "success", text: "✓ Container started" },
|
||||
{ type: "success", text: "✓ Ready at http://localhost:8080" },
|
||||
];
|
||||
}
|
||||
|
||||
function buildLines(mode: "docker-run" | "docker-compose" = "docker-run"): Line[] {
|
||||
return mode === "docker-run" ? buildDockerRunLines() : buildDockerComposeLines();
|
||||
function buildUpdaterupComposeLines(links: TerminalLinks): Line[] {
|
||||
const updaterupDockerImage = links.updaterupDockerImage ?? LINKS.updaterupDockerImage;
|
||||
return [
|
||||
{ type: "comment", text: "# Using docker-compose for Updaterup" },
|
||||
{ type: "cmd", text: "cat > docker-compose.yml << 'EOF'", copyable: false },
|
||||
{ type: "output", text: "services:" },
|
||||
{ type: "output", text: " updaterup:" },
|
||||
{ type: "output", text: ` image: ${updaterupDockerImage}` },
|
||||
{ type: "output", text: " ports:" },
|
||||
{ type: "output", text: " - \"8080:80\"" },
|
||||
{ type: "output", text: " volumes:" },
|
||||
{ type: "output", text: " - /var/run/docker.sock:/var/run/docker.sock" },
|
||||
{ type: "output", text: " - updaterup-config:/app/config" },
|
||||
{ type: "output", text: " restart: unless-stopped" },
|
||||
{ type: "output", text: "volumes:" },
|
||||
{ type: "output", text: " updaterup-config:" },
|
||||
{ type: "output", text: "EOF" },
|
||||
{ type: "success", text: "✓ docker-compose.yml created" },
|
||||
{ type: "cmd", text: "docker compose up -d", copyable: false },
|
||||
{ type: "output", text: "[+] Building 1.8s (10/10) FINISHED" },
|
||||
{ type: "success", text: "✓ Ready at http://localhost:8080" },
|
||||
];
|
||||
}
|
||||
|
||||
function buildLines(mode: "docker-run" | "docker-compose" | "updaterup" | "updaterup-compose" = "docker-run", links: TerminalLinks = {}): Line[] {
|
||||
switch (mode) {
|
||||
case "docker-compose": return buildDockerComposeLines(links);
|
||||
case "updaterup": return buildUpdaterupRunLines(links);
|
||||
case "updaterup-compose": return buildUpdaterupComposeLines(links);
|
||||
default: return buildDockerRunLines(links);
|
||||
}
|
||||
}
|
||||
|
||||
function lineSpeed(line: Line) {
|
||||
@@ -88,8 +142,8 @@ function linePrompt(line: Line): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
export default function TerminalTyper({ mode = "docker-run" }: { mode?: "docker-run" | "docker-compose" } = {}) {
|
||||
const LINES = buildLines(mode);
|
||||
export default function TerminalTyper({ mode = "docker-run", links = {} }: { mode?: "docker-run" | "docker-compose" | "updaterup" | "updaterup-compose"; links?: TerminalLinks } = {}) {
|
||||
const LINES = buildLines(mode, links);
|
||||
const [doneLines, setDoneLines] = useState<number[]>([]);
|
||||
const [current, setCurrent] = useState<{ idx: number; chars: number } | null>({ idx: 0, chars: 0 });
|
||||
const [copied, setCopied] = useState(false);
|
||||
@@ -97,7 +151,7 @@ export default function TerminalTyper({ mode = "docker-run" }: { mode?: "docker-
|
||||
const copyToClipboard = () => {
|
||||
let textToCopy = "";
|
||||
|
||||
if (mode === "docker-compose") {
|
||||
if (mode === "docker-compose" || mode === "updaterup-compose") {
|
||||
// For docker-compose, copy the YAML content only
|
||||
const startIdx = LINES.findIndex(line => line.type === "output" && line.text === "services:");
|
||||
const endIdx = LINES.findIndex((line, i) => i > startIdx && line.type === "output" && line.text === "EOF");
|
||||
|
||||
Reference in New Issue
Block a user