- Supprimer les modules services et logs du CORE (déplacés dans viewServices et viewLogs) - Enrichir modules/module.go : interface Registry avec NavItemDef, RunOnTarget, StreamOnTarget - Réécrire modules/loader.go : NewLoader accepte *db.DB, *sshpool.Pool, *crypto.Encryptor - Ajouter migration 005 : colonnes nav_* sur la table modules + suppression services/logs DB - Mettre à jour db.go (repairSchema) pour ajout idempotent des colonnes nav_* - Mettre à jour settings.go : GetModules retourne les champs nav, ajout GetRegistryModules et InstallRegistryModule - Mettre à jour main.go : NewLoader avec les bons arguments, ajout routes /api/registry/modules - Mettre à jour modules.html : section Store avec liste des modules Forgejo - Mettre à jour app.js : sidebar dynamique (nav_href depuis DB), modulesPage avec store - Mettre à jour pages.css : styles pour store de modules Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
140 lines
6.4 KiB
HTML
140 lines
6.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<script>(function(){document.documentElement.setAttribute("data-theme",localStorage.getItem("pxp_theme")||"dark");document.documentElement.setAttribute("data-sidebar",localStorage.getItem("pxp_sidebar_pos")||"left")})()</script>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>ProxmoxPanel — Modules</title>
|
|
<link rel="stylesheet" href="/css/neu.css" />
|
|
<link rel="stylesheet" href="/css/dark.css" />
|
|
<link rel="stylesheet" href="/css/light.css" />
|
|
<link rel="stylesheet" href="/css/pages.css" />
|
|
<link rel="stylesheet" href="/css/lineicons-duotone.css" />
|
|
<link rel="manifest" href="/manifest.json" />
|
|
<script src="/js/vendors/htmx.min.js"></script>
|
|
<script src="/js/vendors/swup.iife.js"></script>
|
|
<script src="/js/app.js"></script>
|
|
<script src="/js/vendors/alpine.min.js" defer></script>
|
|
</head>
|
|
<body x-data x-init="$store.ui.init()">
|
|
|
|
<aside class="sidebar" x-data="sidebar()" :class="{ collapsed: collapsed }" x-cloak>
|
|
<div class="sidebar-header" @click="toggle()">
|
|
<i class="sidebar-logo lnid-layout-1"></i>
|
|
<span class="sidebar-title" x-show="!collapsed">ProxmoxPanel</span>
|
|
</div>
|
|
<nav class="sidebar-nav">
|
|
<template x-for="item in navItems" :key="item.id">
|
|
<a class="sidebar-link" :class="{ active: isActive(item.id) }" :href="item.href" @click.prevent="navigate(item.href)">
|
|
<i class="sidebar-icon" :class="item.iconClass" :style="iconStyle(item)"></i>
|
|
<span class="sidebar-label" x-show="!collapsed" x-text="t(item.labelKey)"></span>
|
|
</a>
|
|
</template>
|
|
</nav>
|
|
<div class="sidebar-footer">
|
|
<a class="sidebar-link" href="/profile.html" @click.prevent="navigate('/profile.html')">
|
|
<i class="sidebar-icon lnid-user-circle-1"></i>
|
|
<span class="sidebar-label" x-show="!collapsed" x-text="$store.auth.user?.username || t('nav.profile')"></span>
|
|
</a>
|
|
</div>
|
|
</aside>
|
|
|
|
<div class="main-layout">
|
|
<nav class="navbar" x-data="navbar()" x-cloak>
|
|
<h2 class="navbar-title" x-text="t('nav.modules')"></h2>
|
|
<div class="navbar-actions">
|
|
<button class="neu-btn neu-btn--sm neu-btn--icon-sm" @click="toggleTheme()" :title="theme==='dark'?t('navbar.lightMode'):t('navbar.darkMode')">
|
|
<i :class="theme==='dark' ? 'lnid-sun-1' : 'lnid-moon-half-left-1'"></i>
|
|
</button>
|
|
<button class="neu-btn neu-btn--sm neu-btn--icon-sm" @click="logout()" :title="t('navbar.logout')">
|
|
<i class="lnid-power-button"></i>
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
|
|
<main id="swup" class="page-content transition-fade">
|
|
<div x-data="modulesPage()" x-cloak>
|
|
|
|
<!-- Modules installés -->
|
|
<h3 class="section-title"><i class="lnid-puzzle"></i> Modules installés</h3>
|
|
|
|
<div class="loading-state" x-show="loading">
|
|
<div class="spinner-lg"></div><span>Chargement…</span>
|
|
</div>
|
|
|
|
<div class="modules-grid" x-show="!loading">
|
|
<template x-for="mod in modules" :key="mod.id">
|
|
<div class="neu-card module-card" :class="{ disabled: !mod.is_enabled }">
|
|
<div class="module-header">
|
|
<div class="module-icon">
|
|
<i :class="mod.nav_icon || 'lnid-puzzle'"></i>
|
|
</div>
|
|
<div class="module-info">
|
|
<span class="module-name" x-text="mod.name || mod.id"></span>
|
|
<span class="module-version" x-text="mod.version"></span>
|
|
<span class="module-desc" x-text="mod.description"></span>
|
|
</div>
|
|
<div class="module-toggle">
|
|
<span class="core-badge" x-show="mod.is_core">CORE</span>
|
|
<button class="toggle-btn" :class="{ on: mod.is_enabled }"
|
|
@click="toggle(mod)" :disabled="mod.is_core || toggling[mod.id]"
|
|
x-show="!mod.is_core">
|
|
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
<span class="toggle-label" x-text="mod.is_enabled ? 'Activé' : 'Désactivé'"></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<p class="empty-state" x-show="modules.length === 0">Aucun module installé</p>
|
|
</div>
|
|
|
|
<!-- Store : modules disponibles -->
|
|
<h3 class="section-title" style="margin-top:2rem"><i class="lnid-download-2"></i> Store</h3>
|
|
<p class="section-desc">Modules disponibles depuis <a href="https://git.geronzi.fr/proxmoxPanel" target="_blank">git.geronzi.fr/proxmoxPanel</a></p>
|
|
|
|
<div class="loading-state" x-show="storeLoading">
|
|
<div class="spinner-lg"></div><span>Chargement du store…</span>
|
|
</div>
|
|
|
|
<div class="modules-grid" x-show="!storeLoading">
|
|
<template x-for="mod in storeModules" :key="mod.id">
|
|
<div class="neu-card module-card">
|
|
<div class="module-header">
|
|
<div class="module-icon"><i class="lnid-puzzle"></i></div>
|
|
<div class="module-info">
|
|
<span class="module-name" x-text="mod.id"></span>
|
|
<span class="module-desc" x-text="mod.description || '—'"></span>
|
|
<a class="module-repo-link" :href="mod.repo_url" target="_blank" x-text="mod.repo_url"></a>
|
|
</div>
|
|
<div class="module-toggle">
|
|
<span class="installed-badge" x-show="mod.installed">Installé</span>
|
|
<button class="neu-btn neu-btn--sm neu-btn--primary"
|
|
x-show="!mod.installed"
|
|
@click="install(mod)"
|
|
:disabled="installing[mod.id]">
|
|
<span x-show="installing[mod.id]" class="spinner-sm"></span>
|
|
<i x-show="!installing[mod.id]" class="lnid-download-2"></i>
|
|
Installer
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<p class="empty-state" x-show="!storeLoading && storeModules.length === 0">
|
|
Aucun module disponible dans le store
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Message rebuild -->
|
|
<div class="neu-card rebuild-notice" x-show="rebuildRequired" style="margin-top:1rem;border-left:3px solid var(--neu-warning)">
|
|
<i class="lnid-warning-circle-1" style="color:var(--neu-warning)"></i>
|
|
<span>Un ou plusieurs modules ont été installés. <strong>Un rebuild du container est nécessaire pour les activer.</strong></span>
|
|
</div>
|
|
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|