From da08e01f2813bc6b9e3de45500ee7e2fca351209 Mon Sep 17 00:00:00 2001 From: Soporte ZH Consultores Date: Mon, 11 May 2026 19:40:32 +0000 Subject: [PATCH] =?UTF-8?q?fix(escrituras):=20no=20interrumpir=20edici?= =?UTF-8?q?=C3=B3n=20con=20el=20auto-refresh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Antes el poll de 15s llamaba render() y reconstruía toda la tbody, borrando el modo edición en filas existentes (el guard isEditing solo cubría filas nuevas). Ahora: * loadAll() detecta si hay edición en curso (isEditing || editingRows.size) y guarda los datos en allRows sin rerenderizar. * Muestra "Edición en curso · refresco pausado" en el sync-status. * maybeFlushRefresh() aplica los cambios remotos pendientes al salir del modo edición (cancelar o guardar la última fila). * saveExistingRow ya llama a render() vía saveRow, así que limpia la bandera explícitamente. --- views/escrituras.html | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/views/escrituras.html b/views/escrituras.html index b6860f8..2af115f 100644 --- a/views/escrituras.html +++ b/views/escrituras.html @@ -561,9 +561,15 @@ async function loadAll(showOverlay=false) { const rows = await apiFetch('GET','list'); if (rows === null) return; allRows = rows || []; - setSyncState('ok','Sincronizado'); - // No re-renderizar si el usuario está escribiendo una fila nueva - if (!isEditing) render(); + // No re-renderizar si el usuario está editando (fila nueva o existente). + // Los datos quedan en memoria; se aplicarán al salir de edición. + if (isEditing || editingRows.size > 0) { + pendingRefresh = true; + setSyncState('ok','Edición en curso · refresco pausado'); + } else { + render(); + setSyncState('ok','Sincronizado'); + } } catch(e) { setSyncState('error','Sin conexión'); toast('Error al cargar datos: '+e.message,'error'); @@ -572,6 +578,15 @@ async function loadAll(showOverlay=false) { } } +// Si el poll trajo datos mientras se estaba editando, aplicarlos al terminar +function maybeFlushRefresh() { + if (pendingRefresh && !isEditing && editingRows.size === 0) { + pendingRefresh = false; + render(); + setSyncState('ok','Sincronizado'); + } +} + async function saveRow(row) { try { setSyncState('syncing','Guardando…'); @@ -805,7 +820,8 @@ function onKeydown(e) { }); // ── ROW ACTIONS ────────────────────────────────────────────────────────── -let editingRows = new Set(); // track which rows are in edit mode +let editingRows = new Set(); // track which rows are in edit mode +let pendingRefresh = false; // poll trajo datos mientras alguien editaba function toggleEditRow(id, btn) { const tr = document.querySelector(`tr[data-id="${id}"]`); @@ -830,6 +846,8 @@ function toggleEditRow(id, btn) { btn.title = 'Editar fila'; btn.style.background = ''; btn.style.borderColor = ''; + // Aplicar cambios remotos pendientes si los hubo + maybeFlushRefresh(); } else { // Enter edit mode editingRows.add(id); @@ -866,6 +884,8 @@ function saveExistingRow(id) { tr.classList.remove('editing-row'); const saveBtn = tr.querySelector('.ra-save'); if (saveBtn) saveBtn.classList.remove('pending'); + // saveRow llama a render() al terminar, lo que aplica también cambios remotos + pendingRefresh = false; saveRow(Object.assign({}, base, fields, { id })); }