From 50ac6b1a61df2b4924491d80205bb3be1ce1ce3c Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 5 Jun 2026 19:20:19 +0200 Subject: [PATCH] =?UTF-8?q?Remove:=20altes=20Next.js-Frontend=20gel=C3=B6s?= =?UTF-8?q?cht=20(durch=20HTMX+Jinja2=20ersetzt)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- deploy.sh | 45 + frontend/.env.example | 6 - frontend/.eslintrc.json | 3 - frontend/.gitignore | 37 - frontend/README.md | 206 - frontend/app/file-sharing/page.tsx | 270 - frontend/app/globals.css | 76 - frontend/app/identities/page.tsx | 877 --- frontend/app/layout.tsx | 21 - frontend/app/login/page.tsx | 117 - frontend/app/logs/page.tsx | 340 - frontend/app/navigator/page.tsx | 1456 ---- frontend/app/page.tsx | 646 -- frontend/app/services/page.tsx | 364 - frontend/app/shares/page.tsx | 516 -- frontend/app/zfs/page.tsx | 985 --- frontend/components/Header.tsx | 100 - frontend/components/PoolCard.tsx | 69 - frontend/components/VdevTree.tsx | 97 - .../components/navigator/DirectoryTree.tsx | 260 - .../components/shares/CreateNfsDialog.tsx | 166 - .../components/shares/CreateSambaDialog.tsx | 147 - .../components/shares/DeleteConfirmDialog.tsx | 66 - frontend/components/ui/badge.tsx | 27 - frontend/components/ui/button.tsx | 44 - frontend/components/ui/card.tsx | 68 - frontend/components/ui/dialog.tsx | 53 - frontend/components/ui/progress.tsx | 46 - frontend/lib/api.ts | 556 -- frontend/lib/useWebSocket.ts | 65 - frontend/lib/utils.ts | 68 - frontend/next-env.d.ts | 5 - frontend/next.config.js | 12 - frontend/next.config.ts | 13 - frontend/package-lock.json | 5834 ----------------- frontend/package.json | 30 - frontend/postcss.config.js | 6 - frontend/tailwind.config.js | 74 - frontend/tsconfig.json | 46 - frontend/tsconfig.tsbuildinfo | 1 - resume | 1 + 41 files changed, 46 insertions(+), 13773 deletions(-) create mode 100755 deploy.sh delete mode 100644 frontend/.env.example delete mode 100644 frontend/.eslintrc.json delete mode 100644 frontend/.gitignore delete mode 100644 frontend/README.md delete mode 100644 frontend/app/file-sharing/page.tsx delete mode 100644 frontend/app/globals.css delete mode 100644 frontend/app/identities/page.tsx delete mode 100644 frontend/app/layout.tsx delete mode 100644 frontend/app/login/page.tsx delete mode 100644 frontend/app/logs/page.tsx delete mode 100644 frontend/app/navigator/page.tsx delete mode 100644 frontend/app/page.tsx delete mode 100644 frontend/app/services/page.tsx delete mode 100644 frontend/app/shares/page.tsx delete mode 100644 frontend/app/zfs/page.tsx delete mode 100644 frontend/components/Header.tsx delete mode 100644 frontend/components/PoolCard.tsx delete mode 100644 frontend/components/VdevTree.tsx delete mode 100644 frontend/components/navigator/DirectoryTree.tsx delete mode 100644 frontend/components/shares/CreateNfsDialog.tsx delete mode 100644 frontend/components/shares/CreateSambaDialog.tsx delete mode 100644 frontend/components/shares/DeleteConfirmDialog.tsx delete mode 100644 frontend/components/ui/badge.tsx delete mode 100644 frontend/components/ui/button.tsx delete mode 100644 frontend/components/ui/card.tsx delete mode 100644 frontend/components/ui/dialog.tsx delete mode 100644 frontend/components/ui/progress.tsx delete mode 100644 frontend/lib/api.ts delete mode 100644 frontend/lib/useWebSocket.ts delete mode 100644 frontend/lib/utils.ts delete mode 100644 frontend/next-env.d.ts delete mode 100644 frontend/next.config.js delete mode 100644 frontend/next.config.ts delete mode 100644 frontend/package-lock.json delete mode 100644 frontend/package.json delete mode 100644 frontend/postcss.config.js delete mode 100644 frontend/tailwind.config.js delete mode 100644 frontend/tsconfig.json delete mode 100644 frontend/tsconfig.tsbuildinfo create mode 100644 resume diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..7b2b52b --- /dev/null +++ b/deploy.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Deploy ZMB Webui to target system +# Usage: ./deploy.sh [target] [--pull] +# Example: ./deploy.sh 192.168.1.179 +# Example: ./deploy.sh 192.168.1.179 --pull (pull from git first) + +TARGET="${1:-192.168.1.179}" +PULL="${2:-}" + +set -e + +if [ "$PULL" == "--pull" ]; then + echo "📦 Pulling from git..." + git pull origin master +fi + +echo "🔨 Building frontend..." +cd frontend +rm -rf .next out +npm run build > /dev/null 2>&1 +cd .. + +echo "📤 Deploying to $TARGET..." + +# Deploy backend +echo " → Backend..." +rsync -avz --delete backend/ root@$TARGET:/opt/zmb-webui/backend/ \ + --exclude venv --exclude __pycache__ --exclude "*.pyc" > /dev/null + +# Deploy frontend +echo " → Frontend..." +rsync -avz --delete frontend/out/ root@$TARGET:/opt/zmb-webui/frontend/ > /dev/null + +# Restart services +echo "🔄 Restarting services..." +ssh root@$TARGET bash << 'EOF' +systemctl restart zmb-webui-backend +sleep 1 +systemctl restart nginx +sleep 1 +echo "✓ Services restarted" +EOF + +echo "✅ Deployment complete!" +echo " Access: https://$TARGET:8090" diff --git a/frontend/.env.example b/frontend/.env.example deleted file mode 100644 index 434fd23..0000000 --- a/frontend/.env.example +++ /dev/null @@ -1,6 +0,0 @@ -# API Configuration -# Point to the FastAPI backend -NEXT_PUBLIC_API_URL=http://localhost:8000 - -# For production, use: -# NEXT_PUBLIC_API_URL=https://zfs-manager.example.com:9090 diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json deleted file mode 100644 index bffb357..0000000 --- a/frontend/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index 0ae0dfa..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# Dependencies -node_modules -/.pnp -.pnp.js - -# Testing -/coverage - -# Next.js -/.next/ -/out/ - -# Production -/build - -# Misc -.DS_Store -*.pem - -# Debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Local env files -.env -.env.local -.env.development.local -.env.test.local -.env.production.local - -# IDE -.vscode -.idea -*.swp -*.swo -*~ diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index ed3c9f8..0000000 --- a/frontend/README.md +++ /dev/null @@ -1,206 +0,0 @@ -# ZMB Webui Frontend - -Modern Next.js 15 web UI for ZFS storage management. Built with TypeScript, Tailwind CSS, and ISR optimization for performance on resource-constrained systems. - -## Features - -- **Dashboard**: Real-time pool status, capacity visualization, health monitoring -- **Snapshots**: Create, manage, and delete ZFS snapshots -- **File Manager**: Browse and manage files (coming soon) -- **Authentication**: JWT-based login with password hashing -- **Responsive Design**: Works on mobile, tablet, and desktop -- **Performance**: ISR (Incremental Static Regeneration) for fast page loads -- **Dark Mode Ready**: Full dark mode support with Tailwind CSS - -## Quick Start - -### Prerequisites - -- Node.js 18+ (for development) -- npm or yarn -- FastAPI backend running on http://localhost:8000 - -### Local Development - -```bash -# Install dependencies -npm install - -# Start development server -npm run dev - -# Open http://localhost:3000 in your browser -``` - -### Production Build - -```bash -# Build for production -npm run build - -# Start production server -npm start - -# Or export to static HTML -npm run export -``` - -## Configuration - -Copy `.env.example` to `.env.local` and update the API URL: - -```bash -cp .env.example .env.local -``` - -Edit `.env.local`: -``` -NEXT_PUBLIC_API_URL=http://your-backend-host:8000 -``` - -## Architecture - -### Pages - -- `/` - Dashboard (pool overview) -- `/login` - Authentication -- `/snapshots` - Snapshot management -- `/files` - File browser (coming soon) - -### Components - -- `PoolCard` - Individual pool display with health/capacity -- `Header` - Navigation and user menu -- UI components (Card, Button, Badge, Progress) - -### API Client - -`lib/api.ts` - TypeScript client for FastAPI backend with: -- Authentication (login/logout) -- Pool management -- Snapshot operations -- File browsing -- System information - -## Performance Optimizations - -### For 4GB RAM Systems - -- **ISR Strategy**: - - Dashboard revalidates every 30s - - Snapshots revalidate every 60s - - Static pages cached long-term - -- **Bundle Optimization**: - - Tree-shaking for unused imports - - Dynamic imports for heavy components - - Compression enabled by default - -- **Caching**: - - Browser caching for assets - - In-memory API response caching - - Service worker support ready - -## Development - -### Add a New Page - -```bash -# Create app/new-feature/page.tsx -mkdir app/new-feature -touch app/new-feature/page.tsx -``` - -### Add a New Component - -```bash -# Create components/MyComponent.tsx -touch components/MyComponent.tsx -``` - -### Use the API Client - -```typescript -import { api } from "@/lib/api" - -// Login -await api.login("admin", "password") - -// Get pools -const pools = await api.getPools() - -// Get snapshots -const snapshots = await api.getSnapshots() -``` - -## Deployment - -### On Raspberry Pi / ARM64 - -```bash -# Build on faster x86 machine -npm run build - -# Copy .next directory to Pi -scp -r .next pi@10.66.120.3:/opt/zmb-webui/frontend/ - -# Or build directly on Pi (slower) -npm run build -npm start -``` - -### With nginx - -```nginx -server { - listen 443 ssl http2; - server_name zmb-webui.example.com; - - ssl_certificate /path/to/cert.pem; - ssl_certificate_key /path/to/key.pem; - - location / { - proxy_pass http://localhost:3000; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host $host; - proxy_cache_bypass $http_upgrade; - } -} -``` - -### Systemd Service - -See `../deploy/zmb-webui-frontend.service` for service configuration. - -## Troubleshooting - -### Port 3000 already in use - -```bash -# Use different port -npm run dev -- -p 3001 -``` - -### API connection refused - -Check `.env.local` points to correct backend URL: -```bash -NEXT_PUBLIC_API_URL=http://localhost:8000 -``` - -### Build hangs on ARM64 - -The Node.js build process can be slow on Raspberry Pi. Either: -1. Build on faster x86 machine and copy artifacts -2. Increase available RAM/swap -3. Use pre-built Docker image - -## Contributing - -See main project README for contribution guidelines. - -## License - -Same as parent project diff --git a/frontend/app/file-sharing/page.tsx b/frontend/app/file-sharing/page.tsx deleted file mode 100644 index 11cbde7..0000000 --- a/frontend/app/file-sharing/page.tsx +++ /dev/null @@ -1,270 +0,0 @@ -"use client" - -import { useEffect, useState } from "react" -import { useRouter } from "next/navigation" -import { api } from "@/lib/api" -import { Header } from "@/components/Header" -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -import { Button } from "@/components/ui/button" -import { AlertCircle, RefreshCw } from "lucide-react" - -export default function FileSharingPage() { - const router = useRouter() - const [activeTab, setActiveTab] = useState<"samba" | "nfs">("samba") - const [loading, setLoading] = useState(true) - const [saving, setSaving] = useState(false) - const [error, setError] = useState(null) - const [success, setSuccess] = useState(null) - - // Samba state - const [sambaConfig, setSambaConfig] = useState("") - const [sambaConfigOriginal, setSambaConfigOriginal] = useState("") - const [sambaEditing, setSambaEditing] = useState(false) - - // NFS state - const [nfsConfig, setNfsConfig] = useState("") - const [nfsConfigOriginal, setNfsConfigOriginal] = useState("") - const [nfsEditing, setNfsEditing] = useState(false) - - useEffect(() => { - const token = localStorage.getItem("access_token") - if (!token) { - router.push("/login") - return - } - loadConfigs() - }, [router]) - - const loadConfigs = async () => { - try { - setLoading(true) - setError(null) - - const samba = await api.getSambaConfig().catch(() => ({ parameters: [] })) - - // Convert parameters array to key=value format - const sambaStr = (samba.parameters ?? []) - .map((p: any) => `${p.key} = ${p.value}`) - .join("\n") - - setSambaConfig(sambaStr) - setSambaConfigOriginal(sambaStr) - setNfsConfig("") - setNfsConfigOriginal("") - } catch (err) { - setError(err instanceof Error ? err.message : "Failed to load configurations") - } finally { - setLoading(false) - } - } - - const handleSambaSave = async () => { - try { - setSaving(true) - setError(null) - setSuccess(null) - - // Parse key=value format to object - const parameters: { [key: string]: string } = {} - sambaConfig.split("\n").forEach((line) => { - const trimmed = line.trim() - if (trimmed && !trimmed.startsWith("#") && !trimmed.startsWith(";")) { - const [key, ...valueParts] = trimmed.split("=") - if (key) { - parameters[key.trim()] = valueParts.join("=").trim() - } - } - }) - - await api.setSambaConfig(parameters) - setSambaConfigOriginal(sambaConfig) - setSambaEditing(false) - setSuccess("Samba configuration saved successfully. Changes applied to registry.") - setTimeout(() => setSuccess(null), 3000) - // Reload to show updated values - setTimeout(() => loadConfigs(), 500) - } catch (err) { - setError(err instanceof Error ? err.message : "Failed to save Samba configuration") - } finally { - setSaving(false) - } - } - - const handleNfsSave = async () => { - try { - setSaving(true) - setError(null) - setSuccess(null) - - setSuccess("NFS editing coming soon") - setTimeout(() => setSuccess(null), 3000) - } catch (err) { - setError(err instanceof Error ? err.message : "Failed to save NFS configuration") - } finally { - setSaving(false) - } - } - - return ( -
-
- -
-
-
-

File Sharing Configuration

-

Manage Samba (SMB) and NFS global settings

-
- -
- - {/* Error Alert */} - {error && ( -
- - {error} -
- )} - - {/* Success Alert */} - {success && ( -
- ✓ {success} -
- )} - - {/* Tabs */} -
- - -
- - {/* Samba Tab */} - {activeTab === "samba" && ( - - - Samba Global Configuration -
- {sambaEditing && ( - - )} - {sambaEditing ? ( - - ) : ( - - )} -
-
- - {sambaEditing ? ( -