refactor: architecture modules indépendants — nettoyage CORE, registry enrichi, page modules dynamique

- 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>
This commit is contained in:
enzo 2026-03-22 03:34:17 +01:00
parent 91cf788221
commit ec7d120ef6
15 changed files with 460 additions and 997 deletions

View file

@ -55,9 +55,11 @@
<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 class="spinner-lg"></div><span>Chargement…</span>
</div>
<div class="modules-grid" x-show="!loading">
@ -65,29 +67,71 @@
<div class="neu-card module-card" :class="{ disabled: !mod.is_enabled }">
<div class="module-header">
<div class="module-icon">
<i :class="mod.icon || 'lnid-puzzle'"></i>
<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-desc" x-text="mod.description || ''"></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-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 trouvé</p>
<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>