From 2a0a0c9f38f5900290a1156374248a6259aee516 Mon Sep 17 00:00:00 2001 From: rattatwinko Date: Wed, 25 Jun 2025 21:04:42 +0200 Subject: [PATCH] german translations and some minor changes to the UI to make it prettier --- .gitignore | 3 + src/app/admin/manage/page.tsx | 40 ++-- src/app/admin/manage/rust-status.tsx | 74 ------ src/app/admin/manage/rust-status/page.tsx | 274 +++++++++------------- src/app/admin/page.tsx | 124 ++++++---- src/app/page.tsx | 2 +- 6 files changed, 209 insertions(+), 308 deletions(-) delete mode 100644 src/app/admin/manage/rust-status.tsx diff --git a/.gitignore b/.gitignore index 68ce977..7105967 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ target/ Cargo.lock **/*.rs.bk *.pdb + +# Cache +cache/ diff --git a/src/app/admin/manage/page.tsx b/src/app/admin/manage/page.tsx index fa39ae3..344d6ac 100644 --- a/src/app/admin/manage/page.tsx +++ b/src/app/admin/manage/page.tsx @@ -87,7 +87,7 @@ export default function ManagePage() { const handleLogout = () => { setIsAuthenticated(false); localStorage.removeItem('adminAuth'); - router.push('/admin'); + router.push('/'); }; // Get current directory contents @@ -110,7 +110,7 @@ export default function ManagePage() { // Breadcrumbs const breadcrumbs = [ - { name: 'Root', path: [] }, + { name: '/', path: [] }, ...currentPath.map((name, idx) => ({ name, path: currentPath.slice(0, idx + 1), @@ -238,39 +238,29 @@ export default function ManagePage() { {/* Mobile-friendly header */}
-

Manage Content

+

Inhaltsverwaltung

- Back to Admin + Zum Admin-Panel
- - - - - Rust Parser Status -
@@ -281,7 +271,7 @@ export default function ManagePage() { )}
@@ -430,20 +420,20 @@ export default function ManagePage() {

Confirm Delete

- Are you sure you want to delete {deleteConfirm.item?.type === 'folder' ? 'folder' : 'post'} "{deleteConfirm.item?.type === 'folder' ? deleteConfirm.item.name : deleteConfirm.item?.title}"? + Sind Sie sicher, dass Sie {deleteConfirm.item?.type === 'folder' ? 'Ordner' : 'Beitrag'} "{deleteConfirm.item?.type === 'folder' ? deleteConfirm.item.name : deleteConfirm.item?.title}" löschen möchten?

@@ -454,9 +444,9 @@ export default function ManagePage() { {deleteAllConfirm.show && (
-

Delete Full Folder

+

Lösche Ordner

- Are you sure you want to delete the entire folder and all its contents? + Sind Sie sicher, dass Sie den gesamten Ordner und alle Inhalte löschen möchten?
This cannot be undone!

@@ -465,7 +455,7 @@ export default function ManagePage() { onClick={() => setDeleteAllConfirm({ show: false, folder: null })} className="px-4 py-3 sm:py-2 bg-gray-200 rounded hover:bg-gray-300 text-base font-medium" > - Cancel + Abbrechen
diff --git a/src/app/admin/manage/rust-status.tsx b/src/app/admin/manage/rust-status.tsx deleted file mode 100644 index 39151bd..0000000 --- a/src/app/admin/manage/rust-status.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import React, { useEffect, useState } from 'react'; - -interface PostStats { - slug: string; - cache_hits: number; - cache_misses: number; - last_interpret_time_ms: number; - last_compile_time_ms: number; -} - -export default function RustStatusPage() { - const [stats, setStats] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - const fetchStats = async () => { - setLoading(true); - setError(null); - try { - const res = await fetch('/api/admin/posts?rsparseinfo=1'); - if (!res.ok) throw new Error('Failed to fetch stats'); - const data = await res.json(); - setStats(data); - } catch (e: any) { - setError(e.message || 'Unknown error'); - } finally { - setLoading(false); - } - }; - - useEffect(() => { - fetchStats(); - const interval = setInterval(fetchStats, 5000); - return () => clearInterval(interval); - }, []); - - return ( -
-

Rust Parser Status

- {loading &&
Loading...
} - {error &&
{error}
} - {!loading && !error && ( -
- - - - - - - - - - - - {stats.length === 0 ? ( - - ) : ( - stats.map(stat => ( - - - - - - - - )) - )} - -
SlugCache HitsCache MissesLast Interpret Time (ms)Last Compile Time (ms)
No stats available.
{stat.slug}{stat.cache_hits}{stat.cache_misses}{stat.last_interpret_time_ms}{stat.last_compile_time_ms}
-
- )} -
- ); -} \ No newline at end of file diff --git a/src/app/admin/manage/rust-status/page.tsx b/src/app/admin/manage/rust-status/page.tsx index 8a80514..315092e 100644 --- a/src/app/admin/manage/rust-status/page.tsx +++ b/src/app/admin/manage/rust-status/page.tsx @@ -1,18 +1,5 @@ 'use client'; import React, { useEffect, useState } from 'react'; -import { Bar } from 'react-chartjs-2'; -import { - Chart as ChartJS, - CategoryScale, - LinearScale, - BarElement, - Title, - Tooltip, - Legend, - ChartOptions, -} from 'chart.js'; - -ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend); interface PostStats { slug: string; @@ -26,176 +13,139 @@ export default function RustStatusPage() { const [stats, setStats] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [autoRefresh, setAutoRefresh] = useState(false); - const autoRefreshRef = React.useRef(null); + + // Summary calculations + const totalHits = stats.reduce((sum, s) => sum + s.cache_hits, 0); + const totalMisses = stats.reduce((sum, s) => sum + s.cache_misses, 0); + const avgInterpret = stats.length ? (stats.reduce((sum, s) => sum + s.last_interpret_time_ms, 0) / stats.length).toFixed(1) : 0; + const avgCompile = stats.length ? (stats.reduce((sum, s) => sum + s.last_compile_time_ms, 0) / stats.length).toFixed(1) : 0; const fetchStats = async () => { setLoading(true); setError(null); try { const res = await fetch('/api/admin/posts?rsparseinfo=1'); - if (!res.ok) throw new Error('Failed to fetch stats'); + if (!res.ok) throw new Error('Fehler beim Laden der Statistiken'); const data = await res.json(); setStats(data); } catch (e: any) { - setError(e.message || 'Unknown error'); + setError(e.message || 'Unbekannter Fehler'); } finally { setLoading(false); } }; - React.useEffect(() => { + useEffect(() => { fetchStats(); - // Listen for post changes via BroadcastChannel - let bc: BroadcastChannel | null = null; - if (typeof window !== 'undefined' && 'BroadcastChannel' in window) { - bc = new BroadcastChannel('posts-changed'); - bc.onmessage = (event) => { - if (event.data === 'changed') { - fetchStats(); - } - }; - } - return () => { - if (bc) bc.close(); - if (autoRefreshRef.current) clearInterval(autoRefreshRef.current); - }; }, []); - // Handle auto-refresh toggle - React.useEffect(() => { - if (autoRefresh) { - autoRefreshRef.current = setInterval(fetchStats, 2000); - } else if (autoRefreshRef.current) { - clearInterval(autoRefreshRef.current); - autoRefreshRef.current = null; - } - return () => { - if (autoRefreshRef.current) clearInterval(autoRefreshRef.current); - }; - }, [autoRefresh]); - - // Dashboard summary calculations - const totalHits = stats.reduce((sum, s) => sum + s.cache_hits, 0); - const totalMisses = stats.reduce((sum, s) => sum + s.cache_misses, 0); - const avgInterpret = stats.length ? (stats.reduce((sum, s) => sum + s.last_interpret_time_ms, 0) / stats.length).toFixed(1) : 0; - const avgCompile = stats.length ? (stats.reduce((sum, s) => sum + s.last_compile_time_ms, 0) / stats.length).toFixed(1) : 0; - - // Chart data - const chartData = { - labels: stats.map(s => s.slug), - datasets: [ - { - label: 'Cache Hits', - data: stats.map(s => s.cache_hits), - backgroundColor: 'rgba(34,197,94,0.7)', - }, - { - label: 'Cache Misses', - data: stats.map(s => s.cache_misses), - backgroundColor: 'rgba(239,68,68,0.7)', - }, - ], - }; - const chartOptions: ChartOptions<'bar'> = { - responsive: true, - plugins: { - legend: { position: 'top' }, - title: { display: true, text: 'Cache Hits & Misses per Post' }, - }, - scales: { - x: { stacked: true }, - y: { stacked: true, beginAtZero: true }, - }, - }; - return ( -
-

Rust Parser Dashboard

-
- - -
- {loading && ( -
-
-
Loading stats...
+
+
+ {/* Header with title and action buttons */} +
+
+
+ Rust Logo +
+

Rust-Parser Statistiken

+
+ +
+ {/* Back to Admin button */} + + + + + Zurück zur Admin-Panel + + + {/* Refresh button */} + +
- )} - {error && ( -
{error}
- )} - {!loading && !error && ( - <> - {/* Summary Cards */} -
-
- {totalHits} - Total Cache Hits -
-
- {totalMisses} - Total Cache Misses -
-
- {avgInterpret} ms - Avg Interpret Time -
-
- {avgCompile} ms - Avg Compile Time -
-
- {/* Bar Chart */} -
- + {/* Rest of your component remains the same */} + {/* Summary Cards */} +
+
+ {totalHits} + Cache-Treffer
+
+ {totalMisses} + Cache-Fehlschläge +
+
+ {avgInterpret} ms + Ø Interpretationszeit +
+
+ {avgCompile} ms + Ø Kompilierzeit +
+
- {/* Raw Data Table */} -
- - - - - - - - - - - - {stats.length === 0 ? ( - - ) : ( - stats.map(stat => ( - - - - - - - - )) - )} - -
SlugCache HitsCache MissesLast Interpret Time (ms)Last Compile Time (ms)
No stats available.
{stat.slug}{stat.cache_hits}{stat.cache_misses}{stat.last_interpret_time_ms}{stat.last_compile_time_ms}
-
- - )} + {/* Table */} +
+

Rohdaten

+ {loading &&
Lade Statistiken...
} + {error &&
{error}
} + {!loading && !error && ( +
+ + + + + + + + + + + + {stats.length === 0 ? ( + + ) : ( + stats.map(stat => ( + + + + + + + + )) + )} + +
SlugCache-TrefferCache-FehlschlägeInterpret (ms)Kompilier (ms)
Keine Statistiken verfügbar.
{stat.slug}{stat.cache_hits}{stat.cache_misses}{stat.last_interpret_time_ms}{stat.last_compile_time_ms}
+
+ )} +
+
); -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 940ac57..56fcfdf 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -812,31 +812,61 @@ export default function AdminPage() {
- {/* Docker warning above export button */} - {isDocker && ( -
- Warning: Docker is in use. Exporting will export the entire /app root directory (including all files and folders in the container's root). -
- )}
+ + + + + + + Rust-Parser + Statistiken + + {rememberExportChoice && lastExportChoice && (
💾 {lastExportChoice === 'docker' ? 'Docker' : 'Local'} @@ -960,26 +990,7 @@ export default function AdminPage() { Current folder: {currentPath.join('/') || 'root'}
- {/* Create Folder Form */} -
-

Create New Folder

-
- setNewFolderName(e.target.value)} - placeholder="Folder name" - className="flex-1 rounded-md border border-gray-300 px-3 py-2 text-base" - required - /> - -
-
+ {/* Drag and Drop Zone */}
-

Drag and drop Markdown files here

-

Files will be uploaded to: {currentPath.join('/') || 'root'}

+

Ziehe Markdown-Dateien hierher

+

Dateien werden hochgeladen zu: {currentPath.join('/') || 'root'}

+ {/* Create Folder Form */} +
+

Create New Folder

+
+ setNewFolderName(e.target.value)} + placeholder="Ordnername" + className="flex-1 rounded-md border border-gray-300 px-3 py-2 text-base" + required + /> + +
+
+ {/* Create Post Form */}
-

Create New Post

+

Erstelle neuen Beitrag

@@ -1011,7 +1043,7 @@ export default function AdminPage() { />
- +
- +
- +