agregado de nuevos usuarios listo

This commit is contained in:
2025-09-24 17:51:05 -06:00
parent 85886f1fed
commit 11b95c97a7
11 changed files with 275 additions and 42 deletions

View File

@@ -29,6 +29,7 @@
<span class="chip" id="status">Conectando…</span>
<span class="chip" id="count">0 eventos</span>
<span class="chip" id="band">VLAN 2 • 10/10 Mbps</span>
<span class="chip" id="radiusState" style="background:#fee; color:#900; display:none;">RADIUS: Recargando…</span>
</div>
<div class="toolbar">
<button id="refresh">Recargar historial</button>
@@ -38,8 +39,23 @@
<button id="clear">Limpiar</button>
<button id="copy">Copiar</button>
<button id="exportCsv">Exportar CSV</button>
<button id="addUser">Añadir usuario</button>
</div>
<div id="list" class="list"></div>
<div id="modal" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.4); align-items:center; justify-content:center;">
<div style="background:#fff; color:#222; padding:16px; border-radius:8px; min-width:300px; max-width:90%;">
<h3 style="margin-top:0;">Nuevo usuario</h3>
<div style="display:flex; flex-direction:column; gap:8px;">
<label>Usuario <input id="u_username" /></label>
<label>Contraseña <input id="u_password" type="password" /></label>
<label>VLAN <input id="u_vlan" type="number" min="1" value="2" /></label>
</div>
<div style="display:flex; gap:8px; margin-top:12px;">
<button id="saveUser">Guardar</button>
<button id="cancelUser">Cancelar</button>
</div>
</div>
</div>
</main>
<script>
@@ -50,10 +66,18 @@ const btnRefresh = document.getElementById('refresh');
const btnSelfTest = document.getElementById('selfTest');
const selfTestStatus = document.getElementById('selfTestStatus');
const autoScroll = document.getElementById('autoScroll');
const radiusState = document.getElementById('radiusState');
let total = 0;
const btnClear = document.getElementById('clear');
const btnCopy = document.getElementById('copy');
const btnExportCsv = document.getElementById('exportCsv');
const btnAddUser = document.getElementById('addUser');
const modal = document.getElementById('modal');
const u_username = document.getElementById('u_username');
const u_password = document.getElementById('u_password');
const u_vlan = document.getElementById('u_vlan');
const saveUser = document.getElementById('saveUser');
const cancelUser = document.getElementById('cancelUser');
let history = [];
function renderItem(ev) {
@@ -142,6 +166,41 @@ btnExportCsv.addEventListener('click', () => {
a.remove();
});
btnAddUser.addEventListener('click', () => {
modal.style.display = 'flex';
u_username.value = '';
u_password.value = '';
u_vlan.value = '2';
u_username.focus();
});
cancelUser.addEventListener('click', () => {
modal.style.display = 'none';
});
saveUser.addEventListener('click', async () => {
const username = u_username.value.trim();
const password = u_password.value;
const vlan = u_vlan.value || '2';
if (!username || !password) {
alert('Usuario y contraseña son obligatorios');
return;
}
try {
const r = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password, vlan })
});
const data = await r.json();
if (!data.ok) throw new Error(data.error || 'Error desconocido');
modal.style.display = 'none';
alert('Usuario guardado');
} catch (e) {
alert('Error al guardar: ' + e.message);
}
});
// SSE live events
function connectSSE() {
const es = new EventSource('/events');
@@ -150,6 +209,12 @@ function connectSSE() {
es.addEventListener('message', (e) => {
try { const ev = JSON.parse(e.data); renderItem(ev); } catch {}
});
es.addEventListener('status', (e) => {
try {
const s = JSON.parse(e.data);
radiusState.style.display = s.radius_reloading ? 'inline-block' : 'none';
} catch {}
});
es.addEventListener('clear', () => { loadHistory(); });
}