feat: gestion réseau DHCP/statique depuis l'interface web
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -118,5 +118,169 @@ html_navbar('domain');
|
||||
<a href="/admin/index.php" class="btn btn-outline-secondary">Annuler</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- ── Réseau (hors formulaire principal) ── -->
|
||||
<div class="card shadow-sm mt-4">
|
||||
<div class="card-header fw-semibold d-flex justify-content-between align-items-center">
|
||||
<span><i class="bi bi-hdd-network me-2"></i>Réseau</span>
|
||||
<span id="net-current-ip" class="badge bg-secondary font-monospace">chargement…</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="net-loading" class="text-muted small mb-3">
|
||||
<div class="spinner-border spinner-border-sm me-2"></div>Lecture de la configuration…
|
||||
</div>
|
||||
<div id="net-form" style="display:none">
|
||||
<!-- Mode -->
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Mode</label>
|
||||
<div class="d-flex gap-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="net-mode" id="net-dhcp" value="dhcp">
|
||||
<label class="form-check-label" for="net-dhcp">DHCP <span class="text-muted small">(automatique)</span></label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="net-mode" id="net-static" value="static">
|
||||
<label class="form-check-label" for="net-static">IP Statique</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Champs IP statique -->
|
||||
<div id="net-static-fields" style="display:none">
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Adresse IP</label>
|
||||
<input type="text" id="net-ip" class="form-control font-monospace" placeholder="192.168.1.100">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">Masque</label>
|
||||
<select id="net-prefix" class="form-select font-monospace">
|
||||
<option value="24">/24 — 255.255.255.0</option>
|
||||
<option value="25">/25 — 255.255.255.128</option>
|
||||
<option value="16">/16 — 255.255.0.0</option>
|
||||
<option value="8">/8 — 255.0.0.0</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Passerelle</label>
|
||||
<input type="text" id="net-gw" class="form-control font-monospace" placeholder="192.168.1.1">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Serveurs DNS <span class="text-muted small">(séparés par virgule)</span></label>
|
||||
<input type="text" id="net-dns" class="form-control font-monospace" placeholder="8.8.8.8,1.1.1.1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="net-alert" class="alert py-2 mb-3" style="display:none"></div>
|
||||
|
||||
<div class="d-flex gap-2 align-items-center">
|
||||
<button class="btn btn-warning" onclick="applyNetwork()">
|
||||
<i class="bi bi-hdd-network me-1"></i>Appliquer la configuration réseau
|
||||
</button>
|
||||
<span id="net-spinner" class="spinner-border spinner-border-sm text-warning" style="display:none"></span>
|
||||
<span class="text-muted small" id="net-warn" style="display:none">
|
||||
<i class="bi bi-exclamation-triangle me-1 text-warning"></i>
|
||||
Si vous changez l'IP, reconnectez-vous sur la nouvelle adresse.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadNetworkConfig();
|
||||
|
||||
document.querySelectorAll('input[name="net-mode"]').forEach(function(r) {
|
||||
r.addEventListener('change', function() {
|
||||
document.getElementById('net-static-fields').style.display = r.value === 'static' ? '' : 'none';
|
||||
document.getElementById('net-warn').style.display = r.value === 'static' ? '' : 'none';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function loadNetworkConfig() {
|
||||
fetch('/api/network.php')
|
||||
.then(r => r.json())
|
||||
.then(function(d) {
|
||||
document.getElementById('net-loading').style.display = 'none';
|
||||
document.getElementById('net-form').style.display = '';
|
||||
|
||||
// IP actuelle
|
||||
const ip = d.current_ip || d.static_ip || '—';
|
||||
document.getElementById('net-current-ip').textContent = ip;
|
||||
|
||||
// Mode
|
||||
const mode = d.method || 'dhcp';
|
||||
document.querySelector('input[name="net-mode"][value="' + mode + '"]').checked = true;
|
||||
|
||||
// Champs statique
|
||||
if (mode === 'static') {
|
||||
document.getElementById('net-static-fields').style.display = '';
|
||||
document.getElementById('net-warn').style.display = '';
|
||||
}
|
||||
|
||||
// Pré-remplissage IP statique
|
||||
const sipRaw = d.static_ip || d.current_ip || '';
|
||||
const sipParts = sipRaw.split('/');
|
||||
document.getElementById('net-ip').value = sipParts[0] || '';
|
||||
document.getElementById('net-prefix').value = sipParts[1] || '24';
|
||||
document.getElementById('net-gw').value = d.static_gw || d.current_gw || '';
|
||||
document.getElementById('net-dns').value = (d.static_dns || d.current_dns || '8.8.8.8,1.1.1.1').replace(/\s/g,'');
|
||||
})
|
||||
.catch(function() {
|
||||
document.getElementById('net-loading').innerHTML = '<span class="text-danger"><i class="bi bi-exclamation-triangle me-1"></i>Impossible de lire la configuration réseau.</span>';
|
||||
});
|
||||
}
|
||||
|
||||
function applyNetwork() {
|
||||
const mode = document.querySelector('input[name="net-mode"]:checked')?.value || 'dhcp';
|
||||
const body = { mode };
|
||||
|
||||
if (mode === 'static') {
|
||||
body.ip = document.getElementById('net-ip').value.trim();
|
||||
body.prefix = document.getElementById('net-prefix').value;
|
||||
body.gateway = document.getElementById('net-gw').value.trim();
|
||||
body.dns = document.getElementById('net-dns').value.trim();
|
||||
if (!body.ip || !body.gateway) {
|
||||
showNetAlert('danger', 'Veuillez remplir l\'adresse IP et la passerelle.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('net-spinner').style.display = '';
|
||||
document.getElementById('net-alert').style.display = 'none';
|
||||
|
||||
fetch('/api/network.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(function(d) {
|
||||
document.getElementById('net-spinner').style.display = 'none';
|
||||
if (d.success) {
|
||||
let msg = d.msg || 'Configuration appliquée.';
|
||||
if (d.new_ip) msg += ' — Reconnectez-vous sur <strong>' + d.new_ip + '</strong>';
|
||||
showNetAlert('success', msg);
|
||||
setTimeout(loadNetworkConfig, 2000);
|
||||
} else {
|
||||
showNetAlert('danger', d.error || 'Erreur inconnue.');
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
document.getElementById('net-spinner').style.display = 'none';
|
||||
showNetAlert('warning', 'Pas de réponse — l\'IP a peut-être changé. Reconnectez-vous.');
|
||||
});
|
||||
}
|
||||
|
||||
function showNetAlert(type, msg) {
|
||||
const el = document.getElementById('net-alert');
|
||||
el.className = 'alert alert-' + type + ' py-2 mb-3';
|
||||
el.innerHTML = msg;
|
||||
el.style.display = '';
|
||||
}
|
||||
</script>
|
||||
<?php html_foot(); ?>
|
||||
|
||||
Reference in New Issue
Block a user