fixed save parts with color button
This commit is contained in:
+134
-10
@@ -530,6 +530,7 @@ $(document).ready(function () {
|
|||||||
const finishLoading = function () {
|
const finishLoading = function () {
|
||||||
unsavedChanges = false;
|
unsavedChanges = false;
|
||||||
isLoadingPartsRecord = false;
|
isLoadingPartsRecord = false;
|
||||||
|
updateSaveBtnState();
|
||||||
|
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
};
|
};
|
||||||
@@ -809,7 +810,11 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#partsModal").on("hide.bs.modal", function (e) {
|
$(document).on("hide.bs.modal", "#partsModal", function (e) {
|
||||||
|
console.log(
|
||||||
|
"[partsModal] hide.bs.modal — unsavedChanges =",
|
||||||
|
unsavedChanges,
|
||||||
|
);
|
||||||
if (
|
if (
|
||||||
unsavedChanges &&
|
unsavedChanges &&
|
||||||
!confirm("Hai modifiche non salvate. Vuoi davvero uscire?")
|
!confirm("Hai modifiche non salvate. Vuoi davvero uscire?")
|
||||||
@@ -1843,11 +1848,17 @@ $(document).ready(function () {
|
|||||||
const item = (data.results || [])[0];
|
const item = (data.results || [])[0];
|
||||||
if (item) {
|
if (item) {
|
||||||
const option = new Option(item.text, item.id, true, true);
|
const option = new Option(item.text, item.id, true, true);
|
||||||
if (!fromFilter) $select.append(option).trigger("change");
|
if (!fromFilter)
|
||||||
|
$select
|
||||||
|
.append(option)
|
||||||
|
.trigger("change", [{ skipHandler: true }]);
|
||||||
else $select.append(option);
|
else $select.append(option);
|
||||||
partMatrice[partNumber] = item.id;
|
partMatrice[partNumber] = item.id;
|
||||||
} else {
|
} else {
|
||||||
if (!fromFilter) $select.val(null).trigger("change");
|
if (!fromFilter)
|
||||||
|
$select
|
||||||
|
.val(null)
|
||||||
|
.trigger("change", [{ skipHandler: true }]);
|
||||||
partMatrice[partNumber] = null;
|
partMatrice[partNumber] = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2025,6 +2036,7 @@ $(document).ready(function () {
|
|||||||
);
|
);
|
||||||
|
|
||||||
unsavedChanges = false;
|
unsavedChanges = false;
|
||||||
|
updateSaveBtnState();
|
||||||
|
|
||||||
if (!$("#quotationeBtn").hasClass("d-none"))
|
if (!$("#quotationeBtn").hasClass("d-none"))
|
||||||
$("#quotationeBtn").addClass("d-none");
|
$("#quotationeBtn").addClass("d-none");
|
||||||
@@ -2212,20 +2224,37 @@ $(document).ready(function () {
|
|||||||
function markUnsaved() {
|
function markUnsaved() {
|
||||||
if (isLoadingPartsRecord) return;
|
if (isLoadingPartsRecord) return;
|
||||||
|
|
||||||
if (!unsavedChanges) {
|
unsavedChanges = true;
|
||||||
unsavedChanges = true;
|
updateSaveBtnState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggiorna aspetto del tasto Salva in base a unsavedChanges
|
||||||
|
function updateSaveBtnState() {
|
||||||
|
const $btn = $("#savePartsBtn");
|
||||||
|
if (!$btn.length) return;
|
||||||
|
|
||||||
|
if (unsavedChanges) {
|
||||||
|
$btn.removeClass("btn-success").addClass("btn-danger");
|
||||||
|
} else {
|
||||||
|
$btn.removeClass("btn-danger").addClass("btn-success");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Catch-all: modifiche manuali negli input della tabella parti segnano "non salvato".
|
||||||
|
// I <select> (matrici Select2) sono esclusi: le loro modifiche reali sono già
|
||||||
|
// gestite in initializeSelect2, mentre l'inizializzazione async genererebbe falsi positivi.
|
||||||
|
$(document).on(
|
||||||
|
"input keyup",
|
||||||
|
"#partsTableBody input:not(.part-matrice), #partsTableBody textarea",
|
||||||
|
function () {
|
||||||
|
markUnsaved();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
$(window).on("beforeunload", function () {
|
$(window).on("beforeunload", function () {
|
||||||
if (unsavedChanges && $("#partsModal").hasClass("show")) {
|
if (unsavedChanges && $("#partsModal").hasClass("show")) {
|
||||||
return "Hai modifiche non salvate.";
|
return "Hai modifiche non salvate.";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$(document).on(
|
|
||||||
"input change",
|
|
||||||
"#partsTableBody input, #partsTableBody select",
|
|
||||||
markUnsaved,
|
|
||||||
);
|
|
||||||
$(document).on(
|
$(document).on(
|
||||||
"click",
|
"click",
|
||||||
".add-row-global, .add-mix-global, .add-mix-row, .remove-row, .propagate-matrice-btn, .propagate-all-btn, .note-btn",
|
".add-row-global, .add-mix-global, .add-mix-row, .remove-row, .propagate-matrice-btn, .propagate-all-btn, .note-btn",
|
||||||
@@ -2698,3 +2727,98 @@ $(document).on("click", "#showHideImageBtn", function () {
|
|||||||
window.initPartsResizableColumns = init;
|
window.initPartsResizableColumns = init;
|
||||||
window.applyPartsColumnWidths = syncColgroupToHeaders;
|
window.applyPartsColumnWidths = syncColgroupToHeaders;
|
||||||
})();
|
})();
|
||||||
|
// ===================
|
||||||
|
// NAVIGAZIONE TABELLA PARTI CON FRECCE TASTIERA
|
||||||
|
// ===================
|
||||||
|
(function () {
|
||||||
|
// Selettore dei campi navigabili in ogni riga, in ordine di colonna.
|
||||||
|
// I select Matrice (Select2) sono esclusi di proposito.
|
||||||
|
const NAV_SELECTOR =
|
||||||
|
".part-number, .part-description, .part-dateexpiry, .part-extra-field";
|
||||||
|
|
||||||
|
// Ritorna la lista ordinata dei campi navigabili della riga
|
||||||
|
function navFields($row) {
|
||||||
|
return $row.find(NAV_SELECTOR).filter(":visible");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Il cursore è all'inizio del testo dell'input?
|
||||||
|
function atStart(el) {
|
||||||
|
if (el.type === "date" || el.type === "number") return true;
|
||||||
|
return el.selectionStart === 0 && el.selectionEnd === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Il cursore è alla fine del testo dell'input?
|
||||||
|
function atEnd(el) {
|
||||||
|
if (el.type === "date" || el.type === "number") return true;
|
||||||
|
const len = (el.value || "").length;
|
||||||
|
return el.selectionStart === len && el.selectionEnd === len;
|
||||||
|
}
|
||||||
|
|
||||||
|
function focusField($field) {
|
||||||
|
if (!$field || !$field.length) return;
|
||||||
|
const el = $field.get(0);
|
||||||
|
el.focus();
|
||||||
|
// Seleziona il testo per comodità (non sui date input)
|
||||||
|
if (el.type !== "date" && typeof el.select === "function") {
|
||||||
|
try {
|
||||||
|
el.select();
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on("keydown", "#partsTableBody " + NAV_SELECTOR, function (e) {
|
||||||
|
// Ignora se un dropdown Select2 è aperto
|
||||||
|
if ($(".select2-container--open").length) return;
|
||||||
|
|
||||||
|
const key = e.key;
|
||||||
|
if (
|
||||||
|
key !== "ArrowUp" &&
|
||||||
|
key !== "ArrowDown" &&
|
||||||
|
key !== "ArrowLeft" &&
|
||||||
|
key !== "ArrowRight"
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const el = this;
|
||||||
|
const $cur = $(el);
|
||||||
|
const $row = $cur.closest("tr");
|
||||||
|
const fields = navFields($row);
|
||||||
|
const colIndex = fields.index(el);
|
||||||
|
if (colIndex === -1) return;
|
||||||
|
|
||||||
|
// --- SU / GIÙ: stessa colonna, riga adiacente ---
|
||||||
|
if (key === "ArrowUp" || key === "ArrowDown") {
|
||||||
|
const $targetRow =
|
||||||
|
key === "ArrowUp" ? $row.prev("tr") : $row.next("tr");
|
||||||
|
if (!$targetRow.length) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
const targetFields = navFields($targetRow);
|
||||||
|
// Stessa colonna se esiste, altrimenti l'ultima disponibile
|
||||||
|
const $target = targetFields.eq(colIndex).length
|
||||||
|
? targetFields.eq(colIndex)
|
||||||
|
: targetFields.last();
|
||||||
|
focusField($target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- SINISTRA: campo precedente, solo se cursore a inizio testo ---
|
||||||
|
if (key === "ArrowLeft") {
|
||||||
|
if (!atStart(el)) return; // lascia muovere il cursore nel testo
|
||||||
|
if (colIndex <= 0) return;
|
||||||
|
e.preventDefault();
|
||||||
|
focusField(fields.eq(colIndex - 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- DESTRA: campo successivo, solo se cursore a fine testo ---
|
||||||
|
if (key === "ArrowRight") {
|
||||||
|
if (!atEnd(el)) return;
|
||||||
|
if (colIndex >= fields.length - 1) return;
|
||||||
|
e.preventDefault();
|
||||||
|
focusField(fields.eq(colIndex + 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user