fix: CSS reset, settings API, modules champs, proxmox token
- CSS: ajout reset (box-sizing, margin, font-family, body background)
- Settings: save par PUT /api/settings/{key} (pas bulk), un appel par clé
- Settings: proxmox_token champ unique (format user@realm!id=secret)
- Modules: is_enabled/is_core (champs backend réels, pas enabled/core)
- Proxmox: supprime bouton reboot (route inexistante)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
65c8bf332f
commit
a4b5b06f04
5 changed files with 58 additions and 30 deletions
|
|
@ -4,6 +4,32 @@
|
||||||
Utilisé par tous les composants et les modules.
|
Utilisé par tous les composants et les modules.
|
||||||
============================================================================= */
|
============================================================================= */
|
||||||
|
|
||||||
|
/* ── Reset / Base ───────────────────────────────────────────────────────────── */
|
||||||
|
*, *::before, *::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Inter', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: var(--neu-bg);
|
||||||
|
color: var(--neu-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 { margin: 0; }
|
||||||
|
p { margin: 0; }
|
||||||
|
a { color: inherit; }
|
||||||
|
button { font-family: inherit; font-size: inherit; }
|
||||||
|
input, select, textarea { font-family: inherit; font-size: inherit; }
|
||||||
|
|
||||||
/* ── Variables CSS (surchargées par dark.css et light.css) ─────────────────── */
|
/* ── Variables CSS (surchargées par dark.css et light.css) ─────────────────── */
|
||||||
:root {
|
:root {
|
||||||
/* Couleurs de base */
|
/* Couleurs de base */
|
||||||
|
|
|
||||||
|
|
@ -544,10 +544,9 @@ document.addEventListener('alpine:init', () => {
|
||||||
default_lang: 'fr',
|
default_lang: 'fr',
|
||||||
ssh_host: '',
|
ssh_host: '',
|
||||||
ssh_username: '',
|
ssh_username: '',
|
||||||
ssh_password: '',
|
ssh_password: '', // chiffré, laisser vide = pas de changement
|
||||||
proxmox_url: '',
|
proxmox_url: '',
|
||||||
proxmox_token_id: '',
|
proxmox_token: '', // chiffré, format: user@realm!tokenid=secret
|
||||||
proxmox_token_secret: '',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
|
@ -572,13 +571,20 @@ document.addEventListener('alpine:init', () => {
|
||||||
this.saved = false
|
this.saved = false
|
||||||
this.error = ''
|
this.error = ''
|
||||||
try {
|
try {
|
||||||
const res = await apiFetch('/api/settings', {
|
// Backend: PUT /api/settings/{key} avec { value: "..." } — un appel par clé
|
||||||
|
const keys = Object.keys(this.settings)
|
||||||
|
for (const key of keys) {
|
||||||
|
const val = this.settings[key]
|
||||||
|
// Ignorer les champs vides pour les secrets (ne pas écraser l'existant)
|
||||||
|
if (val === '' && (key === 'ssh_password' || key === 'proxmox_token')) continue
|
||||||
|
const res = await apiFetch(`/api/settings/${key}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: JSON.stringify(this.settings),
|
body: JSON.stringify({ value: val }),
|
||||||
})
|
})
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const d = await res.json().catch(() => ({}))
|
const d = await res.json().catch(() => ({}))
|
||||||
throw new Error(d.error || 'Erreur sauvegarde')
|
throw new Error(d.error || `Erreur sauvegarde de ${key}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.saved = true
|
this.saved = true
|
||||||
setTimeout(() => { this.saved = false }, 3000)
|
setTimeout(() => { this.saved = false }, 3000)
|
||||||
|
|
@ -617,10 +623,11 @@ document.addEventListener('alpine:init', () => {
|
||||||
async toggle(mod) {
|
async toggle(mod) {
|
||||||
this.toggling[mod.id] = true
|
this.toggling[mod.id] = true
|
||||||
try {
|
try {
|
||||||
const action = mod.enabled ? 'disable' : 'enable'
|
// Backend: is_enabled (pas enabled)
|
||||||
|
const action = mod.is_enabled ? 'disable' : 'enable'
|
||||||
const res = await apiFetch(`/api/modules/${mod.id}/${action}`, { method: 'POST' })
|
const res = await apiFetch(`/api/modules/${mod.id}/${action}`, { method: 'POST' })
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
mod.enabled = !mod.enabled
|
mod.is_enabled = !mod.is_enabled
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
<div class="modules-grid" x-show="!loading">
|
<div class="modules-grid" x-show="!loading">
|
||||||
<template x-for="mod in modules" :key="mod.id">
|
<template x-for="mod in modules" :key="mod.id">
|
||||||
<div class="neu-card module-card" :class="{ disabled: !mod.enabled }">
|
<div class="neu-card module-card" :class="{ disabled: !mod.is_enabled }">
|
||||||
<div class="module-header">
|
<div class="module-header">
|
||||||
<div class="module-icon" x-text="mod.icon || '⬡'"></div>
|
<div class="module-icon" x-text="mod.icon || '⬡'"></div>
|
||||||
<div class="module-info">
|
<div class="module-info">
|
||||||
|
|
@ -63,14 +63,14 @@
|
||||||
<span class="module-desc" x-text="mod.description || ''"></span>
|
<span class="module-desc" x-text="mod.description || ''"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="module-toggle">
|
<div class="module-toggle">
|
||||||
<span class="core-badge" x-show="mod.core">CORE</span>
|
<span class="core-badge" x-show="mod.is_core">CORE</span>
|
||||||
<button class="toggle-btn" :class="{ on: mod.enabled }"
|
<button class="toggle-btn" :class="{ on: mod.is_enabled }"
|
||||||
@click="toggle(mod)" :disabled="mod.core || toggling[mod.id]"
|
@click="toggle(mod)" :disabled="mod.is_core || toggling[mod.id]"
|
||||||
x-show="!mod.core">
|
x-show="!mod.is_core">
|
||||||
<span class="toggle-track">
|
<span class="toggle-track">
|
||||||
<span class="toggle-thumb"></span>
|
<span class="toggle-thumb"></span>
|
||||||
</span>
|
</span>
|
||||||
<span class="toggle-label" x-text="mod.enabled ? 'Activé' : 'Désactivé'"></span>
|
<span class="toggle-label" x-text="mod.is_enabled ? 'Activé' : 'Désactivé'"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -86,10 +86,6 @@
|
||||||
@click="action(r.vmid,'lxc','stop')" :disabled="actionLoading[r.vmid+'-stop']">
|
@click="action(r.vmid,'lxc','stop')" :disabled="actionLoading[r.vmid+'-stop']">
|
||||||
⏹ Stop
|
⏹ Stop
|
||||||
</button>
|
</button>
|
||||||
<button class="neu-btn neu-btn--sm" x-show="r.status==='running'"
|
|
||||||
@click="action(r.vmid,'lxc','reboot')" :disabled="actionLoading[r.vmid+'-reboot']">
|
|
||||||
↺ Reboot
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -110,14 +110,13 @@
|
||||||
<label class="form-label" x-text="t('install.proxmoxUrl')"></label>
|
<label class="form-label" x-text="t('install.proxmoxUrl')"></label>
|
||||||
<input class="neu-input" type="url" x-model="settings.proxmox_url" />
|
<input class="neu-input" type="url" x-model="settings.proxmox_url" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group" style="grid-column: 1 / -1">
|
||||||
<label class="form-label" x-text="t('install.proxmoxTokenId')"></label>
|
<label class="form-label">Token API Proxmox</label>
|
||||||
<input class="neu-input" type="text" x-model="settings.proxmox_token_id" placeholder="user@realm!tokenid" />
|
<input class="neu-input" type="text" x-model="settings.proxmox_token"
|
||||||
</div>
|
placeholder="Laisser vide pour ne pas modifier — format: user@realm!tokenid=secret" />
|
||||||
<div class="form-group">
|
<span style="font-size:.75rem;color:var(--neu-text-muted)">
|
||||||
<label class="form-label" x-text="t('install.proxmoxTokenSecret')"></label>
|
Exemple : enzo@pam!panel=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
<input class="neu-input" type="text" x-model="settings.proxmox_token_secret"
|
</span>
|
||||||
placeholder="Laisser vide pour ne pas modifier" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue