/** * saveAll.js — Save All functionality using gridData */ (function() { 'use strict'; let saveAllRunning = false; function isBusy() { return saveAllRunning || window.batchRunning; } // ── Save single row ────────────────────────────────────────────────── $(document).on('click', '.save-btn', async function() { const btn = this; const rowIndex = parseInt(btn.dataset.row); const row = window.gridData?.[rowIndex]; if (!row) return; const origHtml = btn.innerHTML; btn.innerHTML = ''; btn.disabled = true; try { const formData = window.buildSavePayload(rowIndex); const resp = await fetch('save_edited_row.php', { method: 'POST', body: formData }); const result = await resp.json(); if (result.success) { row._dirty = false; if (window.gridRenderer?.clearDirty) window.gridRenderer.clearDirty(rowIndex); // Flash success on row without re-rendering (preserves Select2 state) const gridRow = document.querySelector(`.grid-row[data-id="${row.iddatadb}"]`); if (gridRow) { gridRow.classList.remove('row-dirty'); gridRow.querySelectorAll('.grid-cell').forEach(cell => { cell.classList.remove('cell-changed'); cell.classList.add('flash-success'); }); setTimeout(() => gridRow.querySelectorAll('.flash-success').forEach(c => c.classList.remove('flash-success')), 500); } const toastEl = document.getElementById('saveSuccessToast'); if (toastEl) bootstrap.Toast.getOrCreateInstance(toastEl).show(); } else { alert('Errore: ' + result.message); } } catch (e) { alert('Errore: ' + e.message); } finally { btn.innerHTML = origHtml; btn.disabled = false; } }); // ── Save All ───────────────────────────────────────────────────────── $(document).on('click', '.save-all-btn', function(e) { e.preventDefault(); if (isBusy()) return; const modalEl = document.getElementById('saveAllConfirmModal'); if (!modalEl) return; new bootstrap.Modal(modalEl, { keyboard: false }).show(); }); $(document).on('click', '#saveAllConfirmBtn', async function() { const confirmModal = bootstrap.Modal.getInstance(document.getElementById('saveAllConfirmModal')); if (confirmModal) confirmModal.hide(); saveAllRunning = true; const bar = document.getElementById('batchExportBar'); const statusEl = document.getElementById('batchExportStatus'); const cancelBtn = document.getElementById('exportBatchCancelBtn'); if (bar) bar.style.display = ''; if (cancelBtn) cancelBtn.style.display = 'none'; if (statusEl) statusEl.textContent = 'Saving...'; const data = window.gridData || []; const dirtyRows = data.map((r, i) => r._dirty ? i : -1).filter(i => i >= 0); if (dirtyRows.length === 0) { saveAllRunning = false; if (bar) bar.style.display = 'none'; const msgEl = document.getElementById('saveAllResultMessage'); if (msgEl) msgEl.textContent = 'No changes to save.'; new bootstrap.Modal(document.getElementById('saveAllResultModal')).show(); return; } let success = 0, fail = 0; for (const idx of dirtyRows) { if (statusEl) statusEl.textContent = `Saving ${success + fail + 1} / ${dirtyRows.length}...`; try { const formData = window.buildSavePayload(idx); const resp = await fetch('save_edited_row.php', { method: 'POST', body: formData }); const result = await resp.json(); if (result.success) { data[idx]._dirty = false; if (window.gridRenderer?.clearDirty) window.gridRenderer.clearDirty(idx); success++; } else { fail++; } } catch (e) { fail++; } } saveAllRunning = false; if (bar) bar.style.display = 'none'; const gr = window.gridRenderer; if (gr) gr.renderVisibleRows(); const msg = `Saved: ${success}` + (fail > 0 ? `, Errors: ${fail}` : ''); const msgEl = document.getElementById('saveAllResultMessage'); if (msgEl) msgEl.textContent = msg; new bootstrap.Modal(document.getElementById('saveAllResultModal')).show(); }); // ── beforeunload ───────────────────────────────────────────────────── window.addEventListener('beforeunload', function(e) { if (window.gridData && window.gridData.some(r => r._dirty)) { e.preventDefault(); e.returnValue = ''; } }); // Public window.saveAllRunning = () => saveAllRunning; })();