feat: réécriture frontend Alpine.js + HTMX + Swup (branche frontend/alpine)

Remplace Vue 3 / Vite / TypeScript par une stack légère statique :
- Alpine.js v3 : réactivité inline, stores auth/ui/i18n, composants par page
- HTMX v2 : interactions serveur via attributs HTML
- Swup v4 : transitions de page (bundlé via esbuild, IIFE browser-loadable)
- xterm.js v5 : terminal PTY (bundlé via esbuild)

Structure : HTML statiques + js/app.js + js/terminal.js + css/ + locales/
Build : esbuild (bundle Swup + xterm seulement) → dist/ → Nginx
Dockerfile simplifié : node:22-alpine build → nginx:1.27-alpine serve

Pages : index, install, login, dashboard, proxmox, updates, terminal, settings, modules
URLs propres via nginx try_files $uri.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
enzo 2026-03-21 16:19:24 +01:00
parent 7ba0ff143c
commit 2098c80ec1
48 changed files with 2446 additions and 5317 deletions

160
frontend/locales/en.json Normal file
View file

@ -0,0 +1,160 @@
{
"nav": {
"dashboard": "Dashboard",
"proxmox": "Proxmox",
"updates": "Updates",
"terminal": "Terminal",
"files": "Files",
"logs": "Logs",
"services": "Services",
"settings": "Settings",
"modules": "Modules"
},
"navbar": {
"darkMode": "Dark mode",
"lightMode": "Light mode",
"logout": "Logout"
},
"install": {
"subtitle": "Initial configuration of the management panel",
"step1": { "label": "General", "title": "General configuration", "desc": "Configure the instance name and public URL." },
"step2": { "label": "SSH", "title": "SSH Connection", "desc": "Configure SSH access to the Proxmox server. These credentials will be used for authentication and management." },
"step3": { "label": "Proxmox", "title": "Proxmox API", "desc": "Optional — Configure the API token to access Proxmox metrics." },
"step4": { "label": "Confirm", "title": "Confirm configuration" },
"instanceName": "Instance name",
"instanceNamePlaceholder": "My Proxmox server",
"publicUrl": "Public URL",
"publicUrlHint": "Auto-detected: {url}",
"defaultLang": "Default language",
"sshHost": "SSH host (host:port)",
"sshUsername": "SSH username",
"sshPassword": "SSH password",
"testSSH": "Test SSH connection",
"sshSuccess": "SSH connection successful!",
"sshFailed": "SSH connection failed",
"proxmoxUrl": "Proxmox URL",
"proxmoxTokenId": "Token ID",
"proxmoxTokenSecret": "Token secret",
"proxmoxTokenHint": "Token ID: enzo{'@'}pam!panel — Secret: UUID generated by Proxmox",
"back": "Back",
"next": "Next",
"finish": "Complete installation",
"error": "Installation error",
"networkError": "Network error"
},
"login": {
"subtitle": "Login with your Linux credentials",
"username": "Username",
"usernamePlaceholder": "Your Linux login",
"password": "Password",
"passwordPlaceholder": "Your password",
"submit": "Login",
"loading": "Logging in...",
"error": "Authentication error",
"hint": "Use your server's Linux credentials"
},
"dashboard": {
"welcome": "Hello, {name}",
"addWidget": "Add widget",
"lxcStatus": "LXC Status",
"metrics": "Metrics",
"noData": "No data available",
"lxcCount": "Total LXC",
"running": "Running",
"widgetShortcut": "Shortcut",
"widgetLXC": "LXC Status",
"widgetMetrics": "Metrics"
},
"proxmox": {
"all": "All",
"lxc": "LXC",
"vm": "VM",
"running": "Running",
"stopped": "Stopped",
"start": "Start",
"stop": "Stop",
"error": "Proxmox API error",
"liveUpdates": "Live updates",
"disconnected": "Disconnected"
},
"updates": {
"desc": "Check and run apt updates on the host or LXC containers.",
"selectTarget": "Select target",
"targetHost": "Proxmox Host",
"targetAll": "All LXC",
"start": "Start update",
"running": "Updating...",
"output": "Output",
"history": "History",
"noHistory": "No updates performed",
"checkUpdates": "Check",
"checkAll": "Check all",
"updateTarget": "Update",
"updateAll": "Update all",
"packagesToUpdate": "package(s) to update",
"upToDate": "Up to date",
"notChecked": "Not checked",
"checking": "Checking...",
"loadingTargets": "Loading targets...",
"stopped": "Stopped",
"status": {
"running": "Running",
"success": "Success",
"error": "Error",
"pending": "Pending"
}
},
"terminal": {
"connected": "Connected to {host}",
"disconnected": "Disconnected",
"connect": "Connect",
"reconnect": "Reconnect"
},
"files": {
"desc": "SFTP file browser",
"moduleNotEnabled": "Module not enabled. Go to Settings → Modules to enable it."
},
"settings": {
"general": "General",
"infrastructure": "Infrastructure",
"appearance": "Appearance",
"audit": "Audit log",
"instanceName": "Instance name",
"publicUrl": "Public URL",
"defaultLang": "Default language",
"sshHost": "SSH host",
"sshUsername": "SSH username",
"sshPassword": "SSH password",
"proxmoxUrl": "Proxmox URL",
"proxmoxTokenId": "Proxmox Token ID",
"proxmoxTokenIdPlaceholder": "enzo{'@'}pam!panel",
"proxmoxTokenSecret": "Token secret",
"secretPlaceholder": "Leave empty to keep current value",
"darkMode": "Dark mode",
"sidebarPosition": "Sidebar position",
"left": "Left",
"right": "Right",
"noAuditLog": "No audit log entries",
"logs": "Logs",
"logsRefresh": "Auto-refresh",
"logsNoRefresh": "Disabled",
"noLogs": "No logs available"
},
"modules": {
"desc": "Manage installed modules on ProxmoxPanel.",
"enabled": "Enabled",
"disabled": "Disabled",
"enable": "Enable",
"disable": "Disable",
"coreProtected": "CORE module (cannot be disabled)",
"restartNotice": "A server restart is required to apply changes."
},
"common": {
"refresh": "Refresh",
"save": "Save",
"saving": "Saving...",
"saved": "Saved!",
"cancel": "Cancel",
"networkError": "Network error"
}
}

160
frontend/locales/fr.json Normal file
View file

@ -0,0 +1,160 @@
{
"nav": {
"dashboard": "Tableau de bord",
"proxmox": "Proxmox",
"updates": "Mises à jour",
"terminal": "Terminal",
"files": "Fichiers",
"logs": "Journaux",
"services": "Services",
"settings": "Paramètres",
"modules": "Modules"
},
"navbar": {
"darkMode": "Mode sombre",
"lightMode": "Mode clair",
"logout": "Se déconnecter"
},
"install": {
"subtitle": "Configuration initiale du panneau de gestion",
"step1": { "label": "Général", "title": "Configuration générale", "desc": "Configurez le nom de l'instance et l'URL publique." },
"step2": { "label": "SSH", "title": "Connexion SSH", "desc": "Configurez l'accès SSH au serveur Proxmox. Ces identifiants seront utilisés pour l'authentification et la gestion." },
"step3": { "label": "Proxmox", "title": "API Proxmox", "desc": "Optionnel — Configurez le token API pour accéder aux métriques Proxmox." },
"step4": { "label": "Confirmation", "title": "Confirmer la configuration" },
"instanceName": "Nom de l'instance",
"instanceNamePlaceholder": "Mon serveur Proxmox",
"publicUrl": "URL publique",
"publicUrlHint": "Détecté automatiquement : {url}",
"defaultLang": "Langue par défaut",
"sshHost": "Hôte SSH (host:port)",
"sshUsername": "Nom d'utilisateur SSH",
"sshPassword": "Mot de passe SSH",
"testSSH": "Tester la connexion SSH",
"sshSuccess": "Connexion SSH réussie !",
"sshFailed": "Connexion SSH échouée",
"proxmoxUrl": "URL Proxmox",
"proxmoxTokenId": "Token ID",
"proxmoxTokenSecret": "Secret du token",
"proxmoxTokenHint": "Token ID : enzo{'@'}pam!panel — Secret : uuid généré par Proxmox",
"back": "Retour",
"next": "Suivant",
"finish": "Terminer l'installation",
"error": "Erreur lors de l'installation",
"networkError": "Erreur réseau"
},
"login": {
"subtitle": "Connectez-vous avec vos identifiants Linux",
"username": "Nom d'utilisateur",
"usernamePlaceholder": "Votre login Linux",
"password": "Mot de passe",
"passwordPlaceholder": "Votre mot de passe",
"submit": "Se connecter",
"loading": "Connexion...",
"error": "Erreur d'authentification",
"hint": "Utilisez vos identifiants Linux du serveur"
},
"dashboard": {
"welcome": "Bonjour, {name}",
"addWidget": "Ajouter un widget",
"lxcStatus": "Statut LXC",
"metrics": "Métriques",
"noData": "Données non disponibles",
"lxcCount": "LXC Total",
"running": "En cours",
"widgetShortcut": "Raccourci",
"widgetLXC": "Statut LXC",
"widgetMetrics": "Métriques"
},
"proxmox": {
"all": "Tous",
"lxc": "LXC",
"vm": "VM",
"running": "En marche",
"stopped": "Arrêté",
"start": "Démarrer",
"stop": "Arrêter",
"error": "Erreur API Proxmox",
"liveUpdates": "Mises à jour en temps réel",
"disconnected": "Déconnecté"
},
"updates": {
"desc": "Vérifiez et lancez des mises à jour apt sur le host ou les LXC.",
"selectTarget": "Sélectionner la cible",
"targetHost": "Host Proxmox",
"targetAll": "Tous les LXC",
"start": "Lancer la mise à jour",
"running": "Mise à jour en cours...",
"output": "Sortie",
"history": "Historique",
"noHistory": "Aucune mise à jour effectuée",
"checkUpdates": "Vérifier",
"checkAll": "Tout vérifier",
"updateTarget": "Mettre à jour",
"updateAll": "Tout mettre à jour",
"packagesToUpdate": "paquet(s) à mettre à jour",
"upToDate": "À jour",
"notChecked": "Non vérifié",
"checking": "Vérification...",
"loadingTargets": "Chargement des cibles...",
"stopped": "Arrêté",
"status": {
"running": "En cours",
"success": "Succès",
"error": "Erreur",
"pending": "En attente"
}
},
"terminal": {
"connected": "Connecté à {host}",
"disconnected": "Déconnecté",
"connect": "Connecter",
"reconnect": "Reconnecter"
},
"files": {
"desc": "Navigateur de fichiers SFTP",
"moduleNotEnabled": "Module non activé. Rendez-vous dans Paramètres → Modules pour l'activer."
},
"settings": {
"general": "Général",
"infrastructure": "Infrastructure",
"appearance": "Apparence",
"audit": "Journal d'audit",
"instanceName": "Nom de l'instance",
"publicUrl": "URL publique",
"defaultLang": "Langue par défaut",
"sshHost": "Hôte SSH",
"sshUsername": "Utilisateur SSH",
"sshPassword": "Mot de passe SSH",
"proxmoxUrl": "URL Proxmox",
"proxmoxTokenId": "Token ID Proxmox",
"proxmoxTokenIdPlaceholder": "enzo{'@'}pam!panel",
"proxmoxTokenSecret": "Secret du token",
"secretPlaceholder": "Laisser vide pour ne pas modifier",
"darkMode": "Mode sombre",
"sidebarPosition": "Position de la sidebar",
"left": "Gauche",
"right": "Droite",
"noAuditLog": "Aucune entrée dans le journal",
"logs": "Logs",
"logsRefresh": "Rafraîchissement",
"logsNoRefresh": "Désactivé",
"noLogs": "Aucun log disponible"
},
"modules": {
"desc": "Gérez les modules installés sur ProxmoxPanel.",
"enabled": "Actif",
"disabled": "Inactif",
"enable": "Activer",
"disable": "Désactiver",
"coreProtected": "Module CORE (non désactivable)",
"restartNotice": "Un redémarrage du serveur est nécessaire pour appliquer les changements."
},
"common": {
"refresh": "Actualiser",
"save": "Sauvegarder",
"saving": "Sauvegarde...",
"saved": "Sauvegardé !",
"cancel": "Annuler",
"networkError": "Erreur réseau"
}
}