Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9969cc9edc |
@@ -12,15 +12,12 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
let photoAnnotations = {};
|
let photoAnnotations = {};
|
||||||
let partColors = {};
|
let partColors = {};
|
||||||
let partSizes = {}; // memorizza la dimensione specifica per parte
|
|
||||||
let selectedPartNumber = null;
|
let selectedPartNumber = null;
|
||||||
let unsavedChanges = false;
|
let unsavedChanges = false;
|
||||||
let fabricCanvas = null;
|
let fabricCanvas = null;
|
||||||
let descriptionTextbox = null;
|
let descriptionTextbox = null;
|
||||||
let markerObjects = {};
|
let markerObjects = {};
|
||||||
let partsListData = [];
|
let partsListData = [];
|
||||||
// DIMENSIONE GLOBALE MARKER
|
|
||||||
let globalMarkerSize = 24;
|
|
||||||
|
|
||||||
// ===================
|
// ===================
|
||||||
// MODAL INITIALIZATION
|
// MODAL INITIALIZATION
|
||||||
@@ -32,8 +29,6 @@ $(document).ready(function () {
|
|||||||
trfHeader,
|
trfHeader,
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#annotationsModal").attr('data-iddatadb', iddatadb);
|
|
||||||
|
|
||||||
if (!iddatadb && !idquotations) {
|
if (!iddatadb && !idquotations) {
|
||||||
const errorMsg = $(
|
const errorMsg = $(
|
||||||
'<div class="alert alert-danger temp-alert" role="alert">Errore: ID TRF mancante. Impossibile inizializzare il modale delle annotazioni.</div>',
|
'<div class="alert alert-danger temp-alert" role="alert">Errore: ID TRF mancante. Impossibile inizializzare il modale delle annotazioni.</div>',
|
||||||
@@ -72,9 +67,6 @@ $(document).ready(function () {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
modal.show();
|
modal.show();
|
||||||
// Inizializza slider dimensione marker
|
|
||||||
$("#markerSizeSlider").val(globalMarkerSize);
|
|
||||||
$("#markerSizeValue").text(globalMarkerSize + "px");
|
|
||||||
|
|
||||||
// Debug: Verifica presenza elementi DOM
|
// Debug: Verifica presenza elementi DOM
|
||||||
console.log(
|
console.log(
|
||||||
@@ -136,7 +128,6 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
descriptionTextbox = null;
|
descriptionTextbox = null;
|
||||||
markerObjects = {};
|
markerObjects = {};
|
||||||
globalMarkerSize = 24;
|
|
||||||
$("#photoSelectorContainerAnnotations").empty().hide();
|
$("#photoSelectorContainerAnnotations").empty().hide();
|
||||||
$("#samplePhotoAnnotations").attr("src", "");
|
$("#samplePhotoAnnotations").attr("src", "");
|
||||||
$("#partsListAnnotations").empty();
|
$("#partsListAnnotations").empty();
|
||||||
@@ -153,16 +144,6 @@ $(document).ready(function () {
|
|||||||
$(":focus").blur();
|
$(":focus").blur();
|
||||||
});
|
});
|
||||||
|
|
||||||
// SLIDER DIMENSIONE MARKER
|
|
||||||
$(document)
|
|
||||||
.off("input", "#markerSizeSlider")
|
|
||||||
.on("input", "#markerSizeSlider", function () {
|
|
||||||
globalMarkerSize = parseInt($(this).val());
|
|
||||||
$("#markerSizeValue").text(globalMarkerSize + "px");
|
|
||||||
updateMarkers();
|
|
||||||
markUnsaved();
|
|
||||||
});
|
|
||||||
|
|
||||||
// ===================
|
// ===================
|
||||||
// PHOTO LOADERS
|
// PHOTO LOADERS
|
||||||
// ===================
|
// ===================
|
||||||
@@ -484,84 +465,113 @@ $(document).ready(function () {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// ===================
|
// ===================
|
||||||
// TORNA AL MODALE PARTI (modal_partsTable.php)
|
// BACK TO PARTS MODAL
|
||||||
// ===================
|
// ===================
|
||||||
$(document)
|
$(document)
|
||||||
.off("click.backToParts", "#backToPartsBtnAnnotations")
|
.off("click.backToParts", "#backToPartsBtnAnnotations")
|
||||||
.on("click.backToParts", "#backToPartsBtnAnnotations", function (e) {
|
.on("click.backToParts", "#backToPartsBtnAnnotations", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
console.log(
|
||||||
|
"Evento click su #backToPartsBtnAnnotations, ID elemento:",
|
||||||
|
$(this).attr("id"),
|
||||||
|
);
|
||||||
|
if (!$("#backToPartsBtnAnnotations").length) {
|
||||||
|
console.error(
|
||||||
|
"Pulsante #backToPartsBtnAnnotations non trovato nel DOM.",
|
||||||
|
);
|
||||||
|
const errorMsg = $(
|
||||||
|
'<div class="alert alert-danger temp-alert" role="alert">Errore: Pulsante #backToPartsBtnAnnotations non trovato nel DOM.</div>',
|
||||||
|
);
|
||||||
|
$("#annotationsModal .modal-body").prepend(errorMsg);
|
||||||
|
setTimeout(function () {
|
||||||
|
errorMsg.fadeOut(500, function () {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controlla modifiche non salvate
|
||||||
if (
|
if (
|
||||||
unsavedChanges &&
|
unsavedChanges &&
|
||||||
!confirm(
|
!confirm(
|
||||||
"Hai modifiche non salvate. Vuoi davvero tornare al modale delle parti?",
|
"Hai modifiche non salvate. Vuoi davvero tornare al modale delle parti?",
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
console.log(
|
||||||
|
"Tornare al modale delle parti annullato a causa di modifiche non salvate.",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Chiudi annotationsModal
|
||||||
|
const annotationsModalElement =
|
||||||
|
document.getElementById("annotationsModal");
|
||||||
|
const annotationsModal = bootstrap.Modal.getInstance(
|
||||||
|
annotationsModalElement,
|
||||||
|
);
|
||||||
|
if (annotationsModal) {
|
||||||
|
annotationsModal.hide();
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
"Impossibile trovare l'istanza del modale #annotationsModal.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apri partsModal
|
||||||
const iddatadb = $("#annotationsModal").data("iddatadb");
|
const iddatadb = $("#annotationsModal").data("iddatadb");
|
||||||
const idquotations = $("#annotationsModal").data("idquotations");
|
const idquotations = $("#annotationsModal").data("idquotations");
|
||||||
const trfHeader = $("#trfHeaderAnnotations").text();
|
const trfHeader = $("#trfHeaderAnnotations").text();
|
||||||
|
console.log("Apertura partsModal con:", {
|
||||||
// CHIUDI MODALE ANNOTAZIONI IN MODO SICURO
|
|
||||||
const annotationsModalElement =
|
|
||||||
document.getElementById("annotationsModal");
|
|
||||||
if (annotationsModalElement) {
|
|
||||||
const modalInstance = bootstrap.Modal.getInstance(
|
|
||||||
annotationsModalElement,
|
|
||||||
);
|
|
||||||
if (modalInstance) {
|
|
||||||
modalInstance.hide();
|
|
||||||
} else {
|
|
||||||
$(annotationsModalElement).modal("hide"); // fallback jQuery
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log("Torno a modal_partsTable.php con:", {
|
|
||||||
iddatadb,
|
iddatadb,
|
||||||
idquotations,
|
idquotations,
|
||||||
trfHeader,
|
trfHeader,
|
||||||
});
|
});
|
||||||
// CARICA E APRI MODALE PARTI
|
|
||||||
$.get(
|
|
||||||
"modal_partsTable.php",
|
|
||||||
{
|
|
||||||
iddatadb: iddatadb || "",
|
|
||||||
idquotations: idquotations || "",
|
|
||||||
trfHeader: trfHeader,
|
|
||||||
},
|
|
||||||
function (data) {
|
|
||||||
// Rimuovi vecchio modale (con ID corretto)
|
|
||||||
$("#partsTableModal").remove();
|
|
||||||
$(".modal-backdrop").remove();
|
|
||||||
|
|
||||||
// Aggiungi nuovo modale
|
const partsModalElement = document.getElementById("partsModal");
|
||||||
$("body").append(data);
|
if (!partsModalElement) {
|
||||||
|
console.error("Elemento #partsModal non trovato nel DOM.");
|
||||||
// Apri con Bootstrap 5
|
const errorMsg = $(
|
||||||
const partsModalElement =
|
'<div class="alert alert-danger temp-alert" role="alert">Errore: Il modale delle parti non è presente nel DOM.</div>',
|
||||||
document.getElementById("partsTableModal");
|
|
||||||
if (partsModalElement) {
|
|
||||||
const modal = new bootstrap.Modal(partsModalElement, {
|
|
||||||
backdrop: true,
|
|
||||||
keyboard: true,
|
|
||||||
focus: true,
|
|
||||||
});
|
|
||||||
modal.show();
|
|
||||||
} else {
|
|
||||||
let iddatadb = $("#annotationsModal").attr('data-iddatadb');
|
|
||||||
|
|
||||||
$("button.parts-btn[data-iddatadb='" + iddatadb + "']").trigger('click');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).fail(function (xhr) {
|
|
||||||
console.error("Errore caricamento modale parti:", xhr);
|
|
||||||
alert(
|
|
||||||
"Errore 404: modal_partsTable.php non trovato o errore server.",
|
|
||||||
);
|
);
|
||||||
});
|
$("#annotationsModal .modal-body").prepend(errorMsg);
|
||||||
|
setTimeout(function () {
|
||||||
|
errorMsg.fadeOut(500, function () {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let partsModal = bootstrap.Modal.getInstance(partsModalElement);
|
||||||
|
if (!partsModal) {
|
||||||
|
partsModal = new bootstrap.Modal(partsModalElement, {
|
||||||
|
backdrop: true,
|
||||||
|
keyboard: true,
|
||||||
|
focus: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inizializza il modale delle parti
|
||||||
|
if (typeof window.initPartsModal === "function") {
|
||||||
|
window.initPartsModal(iddatadb, idquotations, trfHeader);
|
||||||
|
partsModal.show();
|
||||||
|
console.log("partsModal aperto con successo.");
|
||||||
|
} else {
|
||||||
|
console.error("Funzione initPartsModal non definita.");
|
||||||
|
const errorMsg = $(
|
||||||
|
'<div class="alert alert-danger temp-alert" role="alert">Errore: Funzione initPartsModal non trovata.</div>',
|
||||||
|
);
|
||||||
|
$("#annotationsModal .modal-body").prepend(errorMsg);
|
||||||
|
setTimeout(function () {
|
||||||
|
errorMsg.fadeOut(500, function () {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===================
|
// ===================
|
||||||
// PARTS LIST
|
// PARTS LIST
|
||||||
// ===================
|
// ===================
|
||||||
@@ -623,19 +633,12 @@ $(document).ready(function () {
|
|||||||
)
|
)
|
||||||
.join("");
|
.join("");
|
||||||
const listItem = `
|
const listItem = `
|
||||||
<li class="list-group-item" data-part-number="${partNumber}">
|
<li class="list-group-item" data-part-number="${partNumber}">
|
||||||
<span class="part-info" style="cursor: pointer;">${partNumber} - ${partDescription}</span>
|
<span class="part-info" style="cursor: pointer;">${partNumber} - ${partDescription}</span>
|
||||||
<div class="color-picker-container" style="display:inline-block; position: relative; overflow: visible; z-index: 2000; margin-left:5px;">
|
<div class="color-picker-container" style="display: inline-block; position: relative; overflow: visible; z-index: 2000;">
|
||||||
<div class="color-option selected-color" style="background-color: ${partColor}; width: 20px; height: 20px; display: inline-block; cursor: pointer; pointer-events: auto;"></div>
|
<div class="color-option selected-color" style="background-color: ${partColor}; width: 20px; height: 20px; display: inline-block; margin-left: 5px; cursor: pointer; pointer-events: auto;"></div>
|
||||||
<div class="color-picker" style="display: none; position: absolute; right: 0; z-index: 2000; background: #fff; border: 1px solid #ccc; padding: 5px;">${colorOptions}</div>
|
<div class="color-picker" style="display: none; position: absolute; right: 0; z-index: 2000; background: #fff; border: 1px solid #ccc; padding: 5px;">${colorOptions}</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:inline-flex; align-items:center; gap:4px; margin-left:5px;">
|
|
||||||
<input type="range" class="marker-size-slider"
|
|
||||||
min="12" max="48" step="2"
|
|
||||||
value="${partSizes[partNumber] || globalMarkerSize}"
|
|
||||||
style="width:70px;">
|
|
||||||
<span class="marker-size-value" style="font-size:0.8rem;">${partSizes[partNumber] || globalMarkerSize}px</span>
|
|
||||||
</div>
|
|
||||||
</li>`;
|
</li>`;
|
||||||
partsListElement.append(listItem);
|
partsListElement.append(listItem);
|
||||||
}
|
}
|
||||||
@@ -684,77 +687,30 @@ $(document).ready(function () {
|
|||||||
$picker.toggle();
|
$picker.toggle();
|
||||||
});
|
});
|
||||||
|
|
||||||
// === Gestione cambio colore ===
|
|
||||||
partsListElement
|
partsListElement
|
||||||
.off("click.colorOption")
|
.off("click.colorOption")
|
||||||
.on("click.colorOption", ".color-option", function (e) {
|
.on("click.colorOption", ".color-option", function (e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
const color = $this.data("color");
|
const color = $this.data("color");
|
||||||
const $listItem = $this.closest("li");
|
const $listItem = $this.closest("li");
|
||||||
const partNumber = $listItem.data("part-number");
|
const partNumber = $listItem.data("part-number");
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"Cliccato .color-option, colore:",
|
"Cliccato .color-option, colore:",
|
||||||
color,
|
color,
|
||||||
"per parte:",
|
"per parte:",
|
||||||
partNumber,
|
partNumber,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Salva il nuovo colore
|
|
||||||
partColors[partNumber] = color;
|
partColors[partNumber] = color;
|
||||||
|
|
||||||
// Aggiorna il colore visivo nel selettore
|
|
||||||
$listItem
|
$listItem
|
||||||
.find(".selected-color")
|
.find(".selected-color")
|
||||||
.css("background-color", color);
|
.css("background-color", color);
|
||||||
|
|
||||||
// Se il marker è già presente, aggiorna anche sul canvas
|
|
||||||
if (markerObjects[partNumber]) {
|
|
||||||
const group = markerObjects[partNumber];
|
|
||||||
const circle = group.item(0); // il cerchio
|
|
||||||
circle.set("fill", color);
|
|
||||||
circle.set("stroke", color);
|
|
||||||
fabricCanvas.renderAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chiudi la palette e aggiorna canvas
|
|
||||||
$this.closest(".color-picker").hide();
|
$this.closest(".color-picker").hide();
|
||||||
updateMarkers();
|
updateMarkers();
|
||||||
markUnsaved();
|
markUnsaved();
|
||||||
});
|
});
|
||||||
|
|
||||||
// === Slider locale per dimensione marker ===
|
|
||||||
partsListElement
|
|
||||||
.off("input.localMarkerSize")
|
|
||||||
.on("input.localMarkerSize", ".marker-size-slider", function (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// Riferimenti alla parte e valore scelto
|
|
||||||
const $slider = $(this);
|
|
||||||
const partNumber = $slider.closest("li").data("part-number");
|
|
||||||
const newSize = parseInt($slider.val());
|
|
||||||
|
|
||||||
// Aggiorna il valore visivo accanto allo slider
|
|
||||||
$slider.siblings(".marker-size-value").text(newSize + "px");
|
|
||||||
|
|
||||||
// Memorizza la nuova dimensione per quella parte
|
|
||||||
partSizes[partNumber] = newSize;
|
|
||||||
|
|
||||||
// Aggiorna i marker sul canvas
|
|
||||||
updateMarkers();
|
|
||||||
|
|
||||||
// Segnala modifiche non salvate
|
|
||||||
markUnsaved();
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Dimensione marker aggiornata per parte ${partNumber}: ${newSize}px`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document)
|
$(document)
|
||||||
.off("click.colorPicker")
|
.off("click.colorPicker")
|
||||||
.on("click.colorPicker", function (e) {
|
.on("click.colorPicker", function (e) {
|
||||||
@@ -936,10 +892,8 @@ $(document).ready(function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size = partSizes[marker.partNumber] || globalMarkerSize;
|
const radius = 12;
|
||||||
const radius = size / 2;
|
const fontSize = 16;
|
||||||
const fontSize = Math.max(10, Math.round(size * 0.65));
|
|
||||||
|
|
||||||
const markerColor =
|
const markerColor =
|
||||||
marker.color || partColors[marker.partNumber] || "#ff0000";
|
marker.color || partColors[marker.partNumber] || "#ff0000";
|
||||||
|
|
||||||
@@ -1059,7 +1013,7 @@ $(document).ready(function () {
|
|||||||
scaleY: 1,
|
scaleY: 1,
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
fontFamily: "Arial",
|
fontFamily: "Arial",
|
||||||
fontSize: Math.max(16, Math.round(globalMarkerSize * 0.8)),
|
fontSize: 24,
|
||||||
fill: "#000000",
|
fill: "#000000",
|
||||||
padding: 10,
|
padding: 10,
|
||||||
editable: false,
|
editable: false,
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
include('include/headscript.php');
|
|
||||||
|
|
||||||
$dbHandler = DBHandlerSelect::getInstance();
|
|
||||||
$pdo = $dbHandler->getConnection();
|
|
||||||
|
|
||||||
// Recupera l'ID dell'utente loggato
|
|
||||||
$user_id = $iduserlogin ?? 1;
|
|
||||||
|
|
||||||
if (!$user_id) {
|
|
||||||
echo json_encode(['success' => false, 'message' => "ID dell'utente autenticato mancante"]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->prepare(
|
|
||||||
"SELECT DISTINCT q.*
|
|
||||||
FROM quotations q
|
|
||||||
INNER JOIN identification_parts ip
|
|
||||||
ON ip.idquotations = q.id
|
|
||||||
AND ip.iddatadb IS NULL
|
|
||||||
WHERE q.iduser = :iduser"
|
|
||||||
);
|
|
||||||
$stmt->execute([':iduser' => $user_id]);
|
|
||||||
$quotations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'quotations' => $quotations]);
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Errore nel caricamento delle quotations: ' . $e->getMessage()]);
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,13 @@
|
|||||||
<!-- Modal per la gestione delle annotazioni -->
|
<!-- Modal per la gestione delle annotazioni -->
|
||||||
<div class="modal fade" id="annotationsModal" tabindex="-1" aria-labelledby="annotationsModalLabel" aria-hidden="true">
|
<div class="modal fade" id="annotationsModal" tabindex="-1" aria-labelledby="annotationsModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-xl" style="max-width: 90% !important; width: 90% !important;">
|
<div class="modal-dialog modal-xl" style="max-width: 80% !important; width: 80% !important;">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="annotationsModalLabel">Annotazioni per TRF: <span id="trfHeaderAnnotations"></span></h5>
|
<h5 class="modal-title" id="annotationsModalLabel">Annotazioni per TRF: <span id="trfHeaderAnnotations"></span></h5>
|
||||||
|
|
||||||
<!-- SLIDER PER DIMENSIONE MARKER -->
|
|
||||||
<div style="display: flex; align-items: center; gap: 10px; margin-left: 20px;">
|
|
||||||
<label for="markerSizeSlider" style="margin: 0; font-size: 0.9rem; white-space: nowrap;">Dimensione marker:</label>
|
|
||||||
<input type="range" id="markerSizeSlider" min="16" max="48" value="24" step="2" style="width: 120px;">
|
|
||||||
<span id="markerSizeValue" style="font-weight: bold; min-width: 30px;">24px</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- COLONNA SINISTRA RIDOTTA -->
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
||||||
<h6 style="margin: 0;">Elenco Parti</h6>
|
<h6 style="margin: 0;">Elenco Parti</h6>
|
||||||
@@ -25,17 +16,15 @@
|
|||||||
<label for="showMixPartsAnnotations" style="font-size: 0.9rem;">Mix</label>
|
<label for="showMixPartsAnnotations" style="font-size: 0.9rem;">Mix</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul id="partsListAnnotations" class="list-group" style="max-height: 500px; overflow-y: auto;"></ul>
|
<ul id="partsListAnnotations" class="list-group"></ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- COLONNA DESTRA PIÙ GRANDE -->
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h6>Foto del Campione</h6>
|
<h6>Foto del Campione</h6>
|
||||||
<div style="display: flex; align-items: center; margin-bottom: 10px;">
|
<div style="display: flex; align-items: center; margin-bottom: 10px;">
|
||||||
<button type="button" class="btn btn-primary btn-sm" id="downloadPhotoBtnAnnotations" style="padding: 0.1rem 0.5rem; font-size: 0.8rem; margin-right: 10px;"><i class="fas fa-download"></i></button>
|
<button type="button" class="btn btn-primary btn-sm" id="downloadPhotoBtnAnnotations" style="padding: 0.1rem 0.5rem; font-size: 0.8rem; margin-right: 10px;"><i class="fas fa-download"></i></button>
|
||||||
<div id="photoSelectorContainerAnnotations" style="display: none;"></div>
|
<div id="photoSelectorContainerAnnotations" style="display: none;"></div>
|
||||||
</div>
|
</div>
|
||||||
<div style="position: relative; width: 100%; min-height: 500px; border: 1px solid #ddd; border-radius: 4px; overflow: hidden;">
|
<div style="position: relative; width: 100%; min-height: 400px;">
|
||||||
<img id="samplePhotoAnnotations" src="" alt="Foto del campione" style="max-width: 100%; max-height: 100%; object-fit: contain; position: absolute; top: 0; left: 0;">
|
<img id="samplePhotoAnnotations" src="" alt="Foto del campione" style="max-width: 100%; max-height: 100%; object-fit: contain; position: absolute; top: 0; left: 0;">
|
||||||
<canvas id="photoCanvasAnnotations" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></canvas>
|
<canvas id="photoCanvasAnnotations" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></canvas>
|
||||||
<canvas id="overlayCanvasAnnotations" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1000;"></canvas>
|
<canvas id="overlayCanvasAnnotations" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1000;"></canvas>
|
||||||
@@ -227,32 +216,4 @@
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
z-index: 3000;
|
z-index: 3000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stile per lo slider */
|
|
||||||
#markerSizeSlider {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
height: 6px;
|
|
||||||
border-radius: 3px;
|
|
||||||
background: #ddd;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#markerSizeSlider::-webkit-slider-thumb {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #007bff;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
#markerSizeSlider::-moz-range-thumb {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #007bff;
|
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="row parts-row">
|
<div class="row">
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<!-- Prima riga: Elenco Parti, Rinumera, Voce -->
|
<!-- Prima riga: Elenco Parti, Rinumera, Voce -->
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
||||||
@@ -14,11 +14,6 @@
|
|||||||
<div style="display: flex; align-items: center;">
|
<div style="display: flex; align-items: center;">
|
||||||
<button type="button" class="btn btn-info btn-sm" id="renumberPartsBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Rinumera Parti</button>
|
<button type="button" class="btn btn-info btn-sm" id="renumberPartsBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Rinumera Parti</button>
|
||||||
<button type="button" class="btn btn-secondary btn-sm ms-2" id="toggleVoiceBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;"><i class="fas fa-microphone"></i> Voce</button>
|
<button type="button" class="btn btn-secondary btn-sm ms-2" id="toggleVoiceBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;"><i class="fas fa-microphone"></i> Voce</button>
|
||||||
<button type="button" class="btn btn-info btn-sm ms-2 d-none" id="quotationeBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Add Quotation</button>
|
|
||||||
<button type="button" class="btn btn-primary btn-sm ms-2" id="showHideImageBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">
|
|
||||||
<i class="fas fa-eye-slash" style="font-size: 0.8rem;"></i>
|
|
||||||
<i class="fas fa-image ms-1" style="font-size: 0.8rem;"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Seconda riga: +, M, MacroMatrice, Matrice globale, Propaga -->
|
<!-- Seconda riga: +, M, MacroMatrice, Matrice globale, Propaga -->
|
||||||
@@ -146,24 +141,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Finestra modale "Aggiungi preventivo" -->
|
|
||||||
<div class="modal fade" id="addQuotationModal" tabindex="-1" aria-labelledby="addQuotationModalLabel" aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-md">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title" id="addQuotationModalLabel">Choose a quotation</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<select id="addQuotationSelect" class="form-control form-control-sm" style="width: 100% !important; min-width: 100% !important"></select>
|
|
||||||
</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="addQuotationBtn">Confirm</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* --- Base --- */
|
/* --- Base --- */
|
||||||
@@ -180,14 +157,6 @@
|
|||||||
max-width: 100% !important
|
max-width: 100% !important
|
||||||
}
|
}
|
||||||
|
|
||||||
#addQuotationModal {
|
|
||||||
z-index: 1060 !important
|
|
||||||
}
|
|
||||||
|
|
||||||
#addQuotationModal .modal-backdrop {
|
|
||||||
z-index: 1055 !important
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tabelle */
|
/* Tabelle */
|
||||||
#partsTable tr {
|
#partsTable tr {
|
||||||
display: table-row !important
|
display: table-row !important
|
||||||
|
|||||||
+16
-160
@@ -6,7 +6,6 @@ $(document).ready(function () {
|
|||||||
let unsavedChanges = false;
|
let unsavedChanges = false;
|
||||||
let matrici = [];
|
let matrici = [];
|
||||||
let macroMatrici = [];
|
let macroMatrici = [];
|
||||||
let quotations = [];
|
|
||||||
|
|
||||||
// --- ROW ID helpers: niente più cache impazzita di jQuery .data() ---
|
// --- ROW ID helpers: niente più cache impazzita di jQuery .data() ---
|
||||||
function getPartId($row) {
|
function getPartId($row) {
|
||||||
@@ -142,7 +141,7 @@ $(document).ready(function () {
|
|||||||
// ===================
|
// ===================
|
||||||
// MODAL HANDLING
|
// MODAL HANDLING
|
||||||
// ===================
|
// ===================
|
||||||
function loadParts(iddatadb, idquotations, callback = null) {
|
function loadParts(iddatadb, idquotations) {
|
||||||
if (iddatadb) {
|
if (iddatadb) {
|
||||||
if (matrici.length === 0) {
|
if (matrici.length === 0) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@@ -154,14 +153,14 @@ $(document).ready(function () {
|
|||||||
loadMacroMatrici();
|
loadMacroMatrici();
|
||||||
initializeGlobalSelect2();
|
initializeGlobalSelect2();
|
||||||
loadPhoto(iddatadb, idquotations);
|
loadPhoto(iddatadb, idquotations);
|
||||||
loadExistingParts(iddatadb, idquotations, callback);
|
loadExistingParts(iddatadb, idquotations);
|
||||||
},
|
},
|
||||||
error: function (xhr, status, error) {
|
error: function (xhr, status, error) {
|
||||||
matrici = [];
|
matrici = [];
|
||||||
loadMacroMatrici();
|
loadMacroMatrici();
|
||||||
initializeGlobalSelect2();
|
initializeGlobalSelect2();
|
||||||
loadPhoto(iddatadb, idquotations);
|
loadPhoto(iddatadb, idquotations);
|
||||||
loadExistingParts(iddatadb, idquotations, callback);
|
loadExistingParts(iddatadb, idquotations);
|
||||||
const errorMsg = $(
|
const errorMsg = $(
|
||||||
'<div class="alert alert-danger temp-alert" role="alert">Errore nel caricamento delle matrici: ' +
|
'<div class="alert alert-danger temp-alert" role="alert">Errore nel caricamento delle matrici: ' +
|
||||||
error +
|
error +
|
||||||
@@ -181,11 +180,11 @@ $(document).ready(function () {
|
|||||||
loadMacroMatrici();
|
loadMacroMatrici();
|
||||||
initializeGlobalSelect2();
|
initializeGlobalSelect2();
|
||||||
loadPhoto(iddatadb, idquotations);
|
loadPhoto(iddatadb, idquotations);
|
||||||
loadExistingParts(iddatadb, idquotations, callback);
|
loadExistingParts(iddatadb, idquotations);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loadPhoto(iddatadb, idquotations);
|
loadPhoto(iddatadb, idquotations);
|
||||||
loadExistingParts(iddatadb, idquotations, callback);
|
loadExistingParts(iddatadb, idquotations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,8 +589,6 @@ $(document).ready(function () {
|
|||||||
if (response.success) {
|
if (response.success) {
|
||||||
$saveStatus.show();
|
$saveStatus.show();
|
||||||
setTimeout(() => $saveStatus.hide(), 2000);
|
setTimeout(() => $saveStatus.hide(), 2000);
|
||||||
|
|
||||||
if (!$("#quotationeBtn").hasClass('d-none')) $("#quotationeBtn").addClass("d-none");
|
|
||||||
} else {
|
} else {
|
||||||
const errorMsg = $(
|
const errorMsg = $(
|
||||||
'<div class="alert alert-danger temp-alert" role="alert">Errore nel salvataggio: ' +
|
'<div class="alert alert-danger temp-alert" role="alert">Errore nel salvataggio: ' +
|
||||||
@@ -1158,7 +1155,7 @@ $(document).ready(function () {
|
|||||||
saveRow($(this).closest("tr"));
|
saveRow($(this).closest("tr"));
|
||||||
});
|
});
|
||||||
|
|
||||||
function loadExistingParts(iddatadb, idquotations, callback = null) {
|
function loadExistingParts(iddatadb, idquotations) {
|
||||||
const endpoint = idquotations
|
const endpoint = idquotations
|
||||||
? "load_parts_quotation.php"
|
? "load_parts_quotation.php"
|
||||||
: "load_parts.php";
|
: "load_parts.php";
|
||||||
@@ -1236,11 +1233,8 @@ $(document).ready(function () {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
addNewRow(1, false); // Riga iniziale normale
|
addNewRow(1, false); // Riga iniziale normale
|
||||||
$("#quotationeBtn").removeClass("d-none");
|
|
||||||
}
|
}
|
||||||
updateRowButtons();
|
updateRowButtons();
|
||||||
|
|
||||||
if (callback) callback();
|
|
||||||
},
|
},
|
||||||
error: function (xhr, status, error) {
|
error: function (xhr, status, error) {
|
||||||
const errorMsg = $(
|
const errorMsg = $(
|
||||||
@@ -1345,7 +1339,6 @@ $(document).ready(function () {
|
|||||||
partId,
|
partId,
|
||||||
currentValue,
|
currentValue,
|
||||||
selectedMacro,
|
selectedMacro,
|
||||||
true
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1422,7 +1415,6 @@ $(document).ready(function () {
|
|||||||
partId,
|
partId,
|
||||||
idmatrice,
|
idmatrice,
|
||||||
selectedMacro = null,
|
selectedMacro = null,
|
||||||
fromFilter = false
|
|
||||||
) {
|
) {
|
||||||
if (typeof $.fn.select2 === "undefined") {
|
if (typeof $.fn.select2 === "undefined") {
|
||||||
$select.replaceWith(
|
$select.replaceWith(
|
||||||
@@ -1482,8 +1474,8 @@ $(document).ready(function () {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ripristina il valore se valido
|
// === MODIFICA CHIRURGICA: solo qui ===
|
||||||
if (partId && partId !== "new" && currentValue) {
|
if (currentValue && currentValue !== "new") {
|
||||||
const matrice = matrici.find((m) => m.IdMatrice == currentValue);
|
const matrice = matrici.find((m) => m.IdMatrice == currentValue);
|
||||||
if (matrice) {
|
if (matrice) {
|
||||||
const option = new Option(
|
const option = new Option(
|
||||||
@@ -1492,24 +1484,20 @@ $(document).ready(function () {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
$select.append(option).trigger("change");
|
||||||
if (!fromFilter) $select.append(option).trigger("change");
|
|
||||||
else $select.append(option);
|
|
||||||
|
|
||||||
partMatrice[partNumber] = matrice.IdMatrice;
|
partMatrice[partNumber] = matrice.IdMatrice;
|
||||||
} else {
|
} else {
|
||||||
// Aggiusta valore non valido
|
$select.val(null).trigger("change");
|
||||||
if (!fromFilter) $select.val(null).trigger("change");
|
|
||||||
|
|
||||||
partMatrice[partNumber] = null;
|
partMatrice[partNumber] = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$select.val(null).trigger("change", [{ skipHandler: true }]);
|
// Nessun valore: assicurati che sia vuoto
|
||||||
}
|
$select.val(null).trigger("change");
|
||||||
|
partMatrice[partNumber] = null;
|
||||||
$select.on("change", function (event, data) {
|
}
|
||||||
if (data && data?.skipHandler) return;
|
// === FINE MODIFICA ===
|
||||||
|
|
||||||
|
$select.on("change", function () {
|
||||||
const idmatrice = $(this).val();
|
const idmatrice = $(this).val();
|
||||||
const $row = $(this).closest("tr");
|
const $row = $(this).closest("tr");
|
||||||
const partId = $row.data("part-id");
|
const partId = $row.data("part-id");
|
||||||
@@ -1793,122 +1781,6 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
// Esporta la funzione loadParts per essere usata da import_Edit2.php
|
// Esporta la funzione loadParts per essere usata da import_Edit2.php
|
||||||
window.loadParts = loadParts;
|
window.loadParts = loadParts;
|
||||||
|
|
||||||
$(document).on("click", "#quotationeBtn", function () {
|
|
||||||
$("#addQuotationModal").modal("show");
|
|
||||||
|
|
||||||
if (quotations.length > 0) {
|
|
||||||
reloadQuotations();
|
|
||||||
} else {
|
|
||||||
$.ajax({
|
|
||||||
url: "load_quotations.php",
|
|
||||||
method: "GET",
|
|
||||||
success: function (response) {
|
|
||||||
quotations = response?.quotations || [];
|
|
||||||
|
|
||||||
reloadQuotations();
|
|
||||||
},
|
|
||||||
error: function (xhr, status, error) {
|
|
||||||
console.error("Errore AJAX caricamento quotations:", error, xhr.responseText);
|
|
||||||
let message = `
|
|
||||||
<div class="alert alert-danger temp-alert" role="alert">
|
|
||||||
Errore nel caricamento delle quotations: ${error} (${xhr.status})
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
$("#partsModal .modal-body").prepend(errorMsg);
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
message.fadeOut(500, function () {
|
|
||||||
$(this).remove();
|
|
||||||
});
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("click", "#addQuotationBtn", function () {
|
|
||||||
const quotationId = $("#addQuotationSelect").val();
|
|
||||||
|
|
||||||
if (quotationId && confirm("Confermo di collegare la quotazione al campione?")) {
|
|
||||||
$("#addQuotationModal").modal("hide");
|
|
||||||
|
|
||||||
loadParts(null, quotationId, () => {
|
|
||||||
$("#quotationeBtn").addClass("d-none");
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
$("#partsTableBody tr").each(function () {
|
|
||||||
$(this).find(".save-loading").show();
|
|
||||||
});
|
|
||||||
|
|
||||||
let photoList = $('#photoSelector option').map(function () {
|
|
||||||
return this.value?.split('/')?.pop();
|
|
||||||
}).get();
|
|
||||||
|
|
||||||
if (!photoList.length) {
|
|
||||||
let path = $('#samplePhoto').attr("src")?.split('/')?.pop();
|
|
||||||
|
|
||||||
if (path) photoList = [path];
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "save_parts_photo_iddatadb.php",
|
|
||||||
method: "POST",
|
|
||||||
data: JSON.stringify({
|
|
||||||
iddatadb: $("#partsModal").data("iddatadb"),
|
|
||||||
photoList,
|
|
||||||
partIds: $('#partsTableBody tr').map(function () {
|
|
||||||
return $(this).data("part-id");
|
|
||||||
}).get(),
|
|
||||||
}),
|
|
||||||
success: function () {
|
|
||||||
$("#partsTableBody tr").each(function () {
|
|
||||||
let $row = $(this);
|
|
||||||
let $saveStatus = $row.find(".save-status");
|
|
||||||
let $saveLoading = $row.find(".save-loading");
|
|
||||||
|
|
||||||
$saveLoading.hide();
|
|
||||||
$saveStatus.show();
|
|
||||||
|
|
||||||
setTimeout(() => $saveStatus.hide(), 2000);
|
|
||||||
});
|
|
||||||
}, error: function (xhr, status, error) {
|
|
||||||
let message = `
|
|
||||||
<div class="alert alert-danger temp-alert" role="alert">
|
|
||||||
Errore di salvataggio: ${error} (${xhr.status})
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
$("#partsModal .modal-body").prepend(message);
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
message.fadeOut(500, function () {
|
|
||||||
$(this).remove();
|
|
||||||
});
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function reloadQuotations() {
|
|
||||||
if (quotations.length > 0) {
|
|
||||||
$("#addQuotationSelect").empty();
|
|
||||||
|
|
||||||
$("#addQuotationSelect").append("<option value=''>Seleziona Quotation</option>");
|
|
||||||
|
|
||||||
quotations.forEach(quotation => {
|
|
||||||
if (quotation?.description) {
|
|
||||||
$("#addQuotationSelect").append(`<option value='${quotation?.id}'>${quotation?.description}</option>`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#addQuotationSelect").select2();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on("change", ".propagate-date-input", function () {
|
$(document).on("change", ".propagate-date-input", function () {
|
||||||
@@ -2132,19 +2004,3 @@ $(document).on("click", ".save-common-note-btn", function () {
|
|||||||
markUnsaved();
|
markUnsaved();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on("click", "#showHideImageBtn", function () {
|
|
||||||
let mainRow = $(this).closest(".parts-row");
|
|
||||||
let photoContainer = mainRow.find(".col-md-3");
|
|
||||||
let tableContainer = mainRow.find("#partsTable").closest("div[class*='col-md']");
|
|
||||||
|
|
||||||
if (photoContainer.hasClass("d-none")) {
|
|
||||||
photoContainer.removeClass("d-none");
|
|
||||||
tableContainer.removeClass("col-md-12").addClass("col-md-9");
|
|
||||||
$(this).html("<i class='fas fa-eye-slash' style='font-size: 0.8rem;'></i><i class='fas fa-image ms-1' style='font-size: 0.8rem;'></i>");
|
|
||||||
} else {
|
|
||||||
photoContainer.addClass("d-none");
|
|
||||||
tableContainer.removeClass("col-md-9").addClass("col-md-12");
|
|
||||||
$(this).html("<i class='fas fa-eye' style='font-size: 0.8rem;'></i><i class='fas fa-image ms-1' style='font-size: 0.8rem;'></i>");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -399,18 +399,14 @@ if (isset($_GET['edit_id'])) {
|
|||||||
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
|
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
|
||||||
<?php include('include/footer.php'); ?>
|
<?php include('include/footer.php'); ?>
|
||||||
</div>
|
</div>
|
||||||
<div id="partsModalContainer"></div>
|
<?php include('modal_parts.php'); ?>
|
||||||
<div id="annotationsModalContainer"></div>
|
<?php include('photos_functions.php'); ?>
|
||||||
<?php include 'photos_functions.php'; ?>
|
|
||||||
|
|
||||||
<?php include('jsinclude.php'); ?>
|
<?php include('jsinclude.php'); ?>
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
|
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
|
||||||
<script src="photos.js"></script>
|
<script src="photos.js"></script>
|
||||||
<script src="annotationsModal.js"></script>
|
<script src="parts.js"></script>
|
||||||
<script src="partsTable.js"></script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
// Mostra messaggi di stato se presenti
|
// Mostra messaggi di stato se presenti
|
||||||
@@ -427,45 +423,6 @@ if (isset($_GET['edit_id'])) {
|
|||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).on('click', '.parts-btn', function() {
|
|
||||||
const idquotations = $(this).data('idquotations');
|
|
||||||
$.ajax({
|
|
||||||
url: 'modal_partsTable.php',
|
|
||||||
method: 'GET',
|
|
||||||
data: {
|
|
||||||
idquotations: idquotations
|
|
||||||
},
|
|
||||||
success: function(response) {
|
|
||||||
$('#partsModalContainer').html(response);
|
|
||||||
const modalElement = document.getElementById('partsModal');
|
|
||||||
if (!modalElement) return;
|
|
||||||
$("#trfHeader").text(`Quotation #${idquotations}`);
|
|
||||||
$("#partsModal").data("idquotations", idquotations);
|
|
||||||
let modal = bootstrap.Modal.getInstance(modalElement) || new bootstrap.Modal(modalElement, {
|
|
||||||
backdrop: true
|
|
||||||
});
|
|
||||||
modal.show();
|
|
||||||
if (typeof window.loadParts === 'function') window.loadParts(null, idquotations);
|
|
||||||
},
|
|
||||||
error: function(xhr, status, error) {
|
|
||||||
alert('Errore nel caricamento del modale: ' + error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('hidden.bs.modal', '#partsModal', function() {
|
|
||||||
$('#partsModalContainer').empty();
|
|
||||||
$('.modal-backdrop').remove();
|
|
||||||
$('body').removeClass('modal-open').css('padding-right', '');
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('hidden.bs.modal', '#annotationsModal', function() {
|
|
||||||
$('#annotationsModalContainer').empty();
|
|
||||||
$('.modal-backdrop').remove();
|
|
||||||
$('body').removeClass('modal-open').css('padding-right', '');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Inizializza DataTables se non siamo in modalità modifica
|
// Inizializza DataTables se non siamo in modalità modifica
|
||||||
if (!document.querySelector('#editForm')) {
|
if (!document.querySelector('#editForm')) {
|
||||||
$('#quotationsTable').DataTable({
|
$('#quotationsTable').DataTable({
|
||||||
@@ -567,7 +524,12 @@ if (isset($_GET['edit_id'])) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Modale per le foto in quotations.php -->
|
<!-- Modale per le foto in quotations.php -->
|
||||||
|
<div class="modal" id="photosModal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close-btn">×</span>
|
||||||
|
<div class="popup-content"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
<?php
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
include('include/headscript.php');
|
|
||||||
|
|
||||||
$dbHandler = DBHandlerSelect::getInstance();
|
|
||||||
$pdo = $dbHandler->getConnection();
|
|
||||||
|
|
||||||
$data = json_decode(file_get_contents('php://input'), true);
|
|
||||||
|
|
||||||
$iddatadb = $data['iddatadb'] ?? null;
|
|
||||||
$partIds = $data['partIds'] ?? [];
|
|
||||||
$photoList = $data['photoList'] ?? null;
|
|
||||||
|
|
||||||
if ($iddatadb) {
|
|
||||||
if (count($partIds) != 0) {
|
|
||||||
$idList = array_values(array_map('intval', $partIds));
|
|
||||||
$placeholders = [];
|
|
||||||
$parameters = [':iddatadb' => $iddatadb];
|
|
||||||
|
|
||||||
foreach ($idList as $index => $id) {
|
|
||||||
$paramName = ":id{$index}";
|
|
||||||
$placeholders[] = $paramName;
|
|
||||||
$parameters[$paramName] = $id;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sql = 'UPDATE identification_parts SET iddatadb = :iddatadb WHERE id IN (' . implode(',', $placeholders) . ')';
|
|
||||||
$stmt = $pdo->prepare($sql);
|
|
||||||
$stmt->execute($parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($photoList) != 0) {
|
|
||||||
$placeholders = [];
|
|
||||||
$parameters = [':iddatadb' => $iddatadb];
|
|
||||||
|
|
||||||
foreach ($photoList as $index => $photo) {
|
|
||||||
$paramName = ":photo{$index}";
|
|
||||||
$placeholders[] = $paramName;
|
|
||||||
$parameters[$paramName] = $photo;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $pdo->prepare('UPDATE datadb_photos SET iddatadb = :iddatadb WHERE file_path IN (' . implode(',', $placeholders) . ')');
|
|
||||||
$stmt->execute($parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => '']);
|
|
||||||
} else {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Dati mancanti']);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user