VisualLimsApiClientMock: fake data for all LIMS endpoints; getInstance() branches on SIMULATE_EXPORT_LIMS

get_clienti.php, get_fixed_field_data.php: simulate mode support
CustomField dropdown values mock added (get_customfield_values.php)

exportUnsavedModal: prompt save before export, MutationObserver waits for save, then proceeds to confirm
Removed old jQuery .export-lims-btn handler that bypassed confirm modal
Fix false "Unsaved changes" on page load: data-restoring guard in all programmatic trigger/dispatchEvent calls (populateSelect, populateClientDropdowns, populateDropdowns)

Fix ConsegnaRichiesta not shown on refresh: add to PHP $fixedAliasMap
Add step5_2_photos, step9_1_importa
This commit is contained in:
2026-02-28 00:44:21 +03:00
parent e3994d6f9f
commit 1fed113c5c
7 changed files with 584 additions and 269 deletions
+63 -32
View File
@@ -192,6 +192,16 @@ foreach ($tempMap as $f) {
$fixedFields[] = $f;
}
// Maps logical fixed_field_key → real datadb column name (mirrors JS fixedAliasMap)
$fixedAliasMap = [
'ClienteResponsabile' => 'cliente_responsabile_id',
'MoltiplicatorePrezzo' => 'moltiplicatore_prezzo_id',
'AnagraficaCertestObject' => 'anagrafica_certest_object_id',
'AnagraficaCertestService' => 'anagrafica_certest_service_id',
'ClienteFornitore' => 'cliente_fornitore_id',
'ConsegnaRichiesta' => 'consegna_richiesta',
];
// helper default (DATE can use 'today' if you already use it elsewhere)
function fixedDefaultValue(array $f): string
{
@@ -638,12 +648,14 @@ function fixedDefaultValue(array $f): string
}
#exportConfirmModal,
#exportResponseModal {
#exportResponseModal,
#exportUnsavedModal {
z-index: 1300 !important;
}
#exportConfirmModal .modal-backdrop,
#exportResponseModal .modal-backdrop {
#exportResponseModal .modal-backdrop,
#exportUnsavedModal .modal-backdrop {
z-index: 1299 !important;
}
@@ -1055,6 +1067,9 @@ function fixedDefaultValue(array $f): string
<span class="status-badge status-<?= htmlspecialchars($row['status'] ?? 'i') ?>">
<?= htmlspecialchars($row['status'] === 'i' ? 'Imported' : ($row['status'] === 'P' ? 'In Progress' : 'To LIMS')) ?>
</span>
<?php if (!empty($row['commessaweb'])): ?>
<span class="commessaweb-code" style="display:block; font-size:0.75em; color:#555; margin-top:2px;" title="CommessaWeb"><?= htmlspecialchars($row['commessaweb']) ?></span>
<?php endif; ?>
<input type="hidden" name="rows[<?= $index ?>][status]" value="<?= htmlspecialchars($row['status'] ?? 'i') ?>">
</div>
<?php
@@ -1159,7 +1174,8 @@ function fixedDefaultValue(array $f): string
if (!empty($fixedFields)) {
foreach ($fixedFields as $f) {
$key = $f['fixed_field_key'];
$val = $row[$key] ?? '';
$dbCol = $fixedAliasMap[$key] ?? $key;
$val = $row[$dbCol] ?? '';
if ($val === '' || $val === null) {
$val = fixedDefaultValue($f);
}
@@ -1290,32 +1306,6 @@ function fixedDefaultValue(array $f): string
});
});
$(document).on("click", ".export-lims-btn", function() {
let rowId = $(this).data("row");
let idDataDb = $(this).data("iddatadb");
$.ajax({
url: "export_to_lims.php",
method: "POST",
data: {
iddatadb: idDataDb
},
dataType: "json",
beforeSend: function() {
alert("Export started in background for row " + rowId);
},
success: function(response) {
if (response.success) {
alert(response.message);
} else {
alert("❌ Error: " + response.message);
}
},
error: function(xhr, status, error) {
alert("❌ AJAX error: " + error);
}
});
});
document.addEventListener("DOMContentLoaded", function() {
const inputs = document.querySelectorAll(".cell-input, .dropdown-select, .carrier-select, .awb-input, .date-picker");
@@ -1345,6 +1335,7 @@ function fixedDefaultValue(array $f): string
inputs.forEach(el => {
el.addEventListener("change", () => {
if (el.hasAttribute('data-restoring')) return;
hasChanges = true;
const gridCell = el.closest(".grid-cell");
@@ -1443,7 +1434,8 @@ function fixedDefaultValue(array $f): string
hasChanges = changedRows.size > 0;
alert('Salvataggio riga avvenuto con successo!');
const toastEl = document.getElementById('saveSuccessToast');
if (toastEl) bootstrap.Toast.getOrCreateInstance(toastEl).show();
} else {
alert('Errore durante il salvataggio: ' + data.message);
}
@@ -1561,7 +1553,7 @@ function fixedDefaultValue(array $f): string
});
// Gestisci la chiusura dei modali per rimuovere i backdrop
document.querySelectorAll('#exportConfirmModal, #exportResponseModal').forEach(modal => {
document.querySelectorAll('#exportConfirmModal, #exportResponseModal, #exportUnsavedModal').forEach(modal => {
modal.addEventListener('hidden.bs.modal', () => {
// Rimuovi tutti i backdrop residui
document.querySelectorAll('.modal-backdrop').forEach(backdrop => {
@@ -1657,10 +1649,12 @@ function fixedDefaultValue(array $f): string
// Ripristina il valore corrente
if (currentValue) {
dropdown.value = currentValue;
dropdown.setAttribute('data-restoring', '');
const event = new Event('change', {
bubbles: true
});
dropdown.dispatchEvent(event);
dropdown.removeAttribute('data-restoring');
}
});
}
@@ -1969,7 +1963,9 @@ function fixedDefaultValue(array $f): string
s2container.after(dropdown);
}
if (valToSelect) {
dropdown.setAttribute('data-restoring', '');
$(dropdown).val(valToSelect).trigger('change');
dropdown.removeAttribute('data-restoring');
}
} else {
// Select nativa
@@ -1988,9 +1984,11 @@ function fixedDefaultValue(array $f): string
});
if (valToSelect) {
dropdown.value = valToSelect;
dropdown.setAttribute('data-restoring', '');
dropdown.dispatchEvent(new Event('change', {
bubbles: true
}));
dropdown.removeAttribute('data-restoring');
}
}
});
@@ -2083,10 +2081,12 @@ function fixedDefaultValue(array $f): string
// Ripristina il valore corrente
if (currentValue) {
dropdown.value = currentValue;
dropdown.setAttribute('data-restoring', '');
const event = new Event('change', {
bubbles: true
});
dropdown.dispatchEvent(event);
dropdown.removeAttribute('data-restoring');
}
});
}
@@ -2528,7 +2528,9 @@ function fixedDefaultValue(array $f): string
if (currentVal) {
const found = results.find(r => String(r.id) === String(currentVal));
if (found) {
$select[0].setAttribute('data-restoring', '');
$select.val(currentVal).trigger('change');
$select[0].removeAttribute('data-restoring');
}
}
}
@@ -2715,6 +2717,35 @@ function fixedDefaultValue(array $f): string
</div>
</div>
<!-- Modal: unsaved changes before export -->
<div class="modal fade" id="exportUnsavedModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modifiche non salvate</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
La riga contiene modifiche non salvate. Salvare prima di procedere con l'esportazione?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Annulla</button>
<button type="button" class="btn btn-primary btn-sm" id="saveAndExportBtn">Salva ed Esporta</button>
</div>
</div>
</div>
</div>
<!-- Toast: row saved successfully -->
<div class="position-fixed bottom-0 end-0 p-3" style="z-index:9999">
<div id="saveSuccessToast" class="toast align-items-center text-bg-success border-0" role="alert" data-bs-delay="2500">
<div class="d-flex">
<div class="toast-body"><i class="fas fa-check-circle me-2"></i>Riga salvata con successo.</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
</div>
</div>
</div>
</body>
</html>
</html>