feat: onglet Réparation dans paramètres — gestion modules fantômes

- GET /api/repair/modules : liste les modules non-core en DB
- DELETE /api/repair/modules/{id} : supprime un module de la DB
- settings.html : onglet Réparation avec liste + bouton Supprimer
- app.js : loadRepair() + resetModule() dans settingsPage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
enzo 2026-03-22 18:27:37 +01:00
parent ab834600ba
commit 3bc55a4c6f
4 changed files with 132 additions and 1 deletions

View file

@ -980,6 +980,9 @@ document.addEventListener('alpine:init', () => {
saved: false,
error: '',
shortcuts: [],
repairModules: [],
repairLoading: false,
resetting: {},
settings: {
instance_name: '',
public_url: '',
@ -1070,6 +1073,38 @@ document.addEventListener('alpine:init', () => {
}
},
async loadRepair() {
this.repairLoading = true
try {
const res = await apiFetch('/api/repair/modules')
if (res.ok) {
const data = await res.json()
this.repairModules = data.modules || []
}
} finally {
this.repairLoading = false
}
},
async resetModule(mod) {
if (!confirm(`Supprimer "${mod.name || mod.id}" de la base de données ?\nLe module pourra être réinstallé depuis le Store.`)) return
this.resetting[mod.id] = true
try {
const res = await apiFetch(`/api/repair/modules/${mod.id}`, { method: 'DELETE' })
if (res.ok) {
this.repairModules = this.repairModules.filter(m => m.id !== mod.id)
Alpine.store('toasts').success(`Module "${mod.name || mod.id}" supprimé de la DB`)
} else {
const d = await res.json().catch(() => ({}))
Alpine.store('toasts').error(d.error || 'Erreur suppression')
}
} catch(e) {
Alpine.store('toasts').error(e.message)
} finally {
this.resetting[mod.id] = false
}
},
t(key) { return Alpine.store('i18n').t(key) },
}))