mix part and loader
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 514 B |
|
After Width: | Height: | Size: 506 B |
|
After Width: | Height: | Size: 519 B |
|
After Width: | Height: | Size: 510 B |
|
After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 516 B |
|
After Width: | Height: | Size: 511 B |
|
After Width: | Height: | Size: 514 B |
|
After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 521 B |
|
After Width: | Height: | Size: 511 B |
|
After Width: | Height: | Size: 508 B |
|
After Width: | Height: | Size: 518 B |
|
After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 515 B |
|
After Width: | Height: | Size: 515 B |
|
After Width: | Height: | Size: 511 B |
|
After Width: | Height: | Size: 515 B |
|
After Width: | Height: | Size: 513 B |
|
After Width: | Height: | Size: 507 B |
|
After Width: | Height: | Size: 521 B |
|
After Width: | Height: | Size: 518 B |
|
After Width: | Height: | Size: 515 B |
@@ -31,6 +31,6 @@ Content-Length: 51
|
|||||||
< strict-transport-security: max-age=2592000
|
< strict-transport-security: max-age=2592000
|
||||||
< x-powered-by: ASP.NET
|
< x-powered-by: ASP.NET
|
||||||
< x-content-type-options: nosniff
|
< x-content-type-options: nosniff
|
||||||
< date: Wed, 30 Jul 2025 08:42:50 GMT
|
< date: Wed, 30 Jul 2025 13:38:07 GMT
|
||||||
<
|
<
|
||||||
* Connection #0 to host 93.43.5.102 left intact
|
* Connection #0 to host 93.43.5.102 left intact
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
* [HTTP/2] [1] [:scheme: https]
|
* [HTTP/2] [1] [:scheme: https]
|
||||||
* [HTTP/2] [1] [:authority: 93.43.5.102]
|
* [HTTP/2] [1] [:authority: 93.43.5.102]
|
||||||
* [HTTP/2] [1] [:path: /limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues]
|
* [HTTP/2] [1] [:path: /limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues]
|
||||||
* [HTTP/2] [1] [authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1Mzg3MjE3MCwiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.EpboyTkahMCz-ctZyx0HlgjD2TcQKV9TnlYSo--3lp8]
|
* [HTTP/2] [1] [authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1Mzg4OTg4NywiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.fka4MClGYcSJycwopdVtHtp-59VPTCgT_waRi8qdLmE]
|
||||||
* [HTTP/2] [1] [accept: application/json]
|
* [HTTP/2] [1] [accept: application/json]
|
||||||
> GET /limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues HTTP/2
|
> GET /limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues HTTP/2
|
||||||
Host: 93.43.5.102
|
Host: 93.43.5.102
|
||||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1Mzg3MjE3MCwiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.EpboyTkahMCz-ctZyx0HlgjD2TcQKV9TnlYSo--3lp8
|
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1Mzg4OTg4NywiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.fka4MClGYcSJycwopdVtHtp-59VPTCgT_waRi8qdLmE
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
|
|
||||||
< HTTP/2 200
|
< HTTP/2 200
|
||||||
@@ -30,6 +30,6 @@ Accept: application/json
|
|||||||
< odata-version: 4.0
|
< odata-version: 4.0
|
||||||
< x-powered-by: ASP.NET
|
< x-powered-by: ASP.NET
|
||||||
< x-content-type-options: nosniff
|
< x-content-type-options: nosniff
|
||||||
< date: Wed, 30 Jul 2025 08:42:50 GMT
|
< date: Wed, 30 Jul 2025 13:38:08 GMT
|
||||||
<
|
<
|
||||||
* Connection #0 to host 93.43.5.102 left intact
|
* Connection #0 to host 93.43.5.102 left intact
|
||||||
|
|||||||
@@ -75,3 +75,6 @@ https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
|||||||
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
||||||
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
||||||
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
||||||
|
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
||||||
|
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
||||||
|
https://93.43.5.102/limsapi/api/odata/SchemaCustomField
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
<td><input type="text" class="form-control form-control-sm part-description" placeholder="Inserisci descrizione" style="width: 100%;"></td>
|
<td><input type="text" class="form-control form-control-sm part-description" placeholder="Inserisci descrizione" style="width: 100%;"></td>
|
||||||
<td>
|
<td>
|
||||||
<button type="button" class="btn btn-success btn-sm add-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-plus fa-xs"></i></button>
|
<button type="button" class="btn btn-success btn-sm add-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-plus fa-xs"></i></button>
|
||||||
|
<button type="button" class="btn btn-primary btn-sm add-mix-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;">M</button>
|
||||||
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; display: none;"><i class="fas fa-trash fa-xs"></i></button>
|
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; display: none;"><i class="fas fa-trash fa-xs"></i></button>
|
||||||
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check fa-xs"></i></span>
|
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check fa-xs"></i></span>
|
||||||
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin fa-xs"></i></span>
|
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin fa-xs"></i></span>
|
||||||
@@ -92,6 +93,9 @@
|
|||||||
#partsList .list-group-item {
|
#partsList .list-group-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#partsList .list-group-item:hover {
|
#partsList .list-group-item:hover {
|
||||||
@@ -113,18 +117,14 @@
|
|||||||
.draggable-marker {
|
.draggable-marker {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
/* Aumentato da 16px */
|
|
||||||
height: 24px;
|
height: 24px;
|
||||||
/* Aumentato da 16px */
|
|
||||||
background: rgba(255, 0, 0, 0.5);
|
background: rgba(255, 0, 0, 0.5);
|
||||||
border: 1px solid #ff0000;
|
border: 1px solid #ff0000;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
/* Aumentato per allineare il testo */
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
/* Aumentato da 8px */
|
|
||||||
cursor: move;
|
cursor: move;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
@@ -137,4 +137,9 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.add-to-mix-btn {
|
||||||
|
padding: 0.1rem 0.3rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -28,8 +28,8 @@ $(document).ready(function () {
|
|||||||
loadExistingParts(iddatadb);
|
loadExistingParts(iddatadb);
|
||||||
|
|
||||||
if (partsModal) {
|
if (partsModal) {
|
||||||
const modal = new bootstrap.Modal(partsModal); // Create a new instance
|
const modal = new bootstrap.Modal(partsModal);
|
||||||
modal.show(); // Show the modal
|
modal.show();
|
||||||
} else {
|
} else {
|
||||||
console.error("Modal Parts non trovato");
|
console.error("Modal Parts non trovato");
|
||||||
}
|
}
|
||||||
@@ -40,8 +40,8 @@ $(document).ready(function () {
|
|||||||
if (closeBtn) {
|
if (closeBtn) {
|
||||||
closeBtn.addEventListener("click", function () {
|
closeBtn.addEventListener("click", function () {
|
||||||
partsModal.style.display = "none";
|
partsModal.style.display = "none";
|
||||||
overlay.style.display = "none"; // Nascondi overlay
|
overlay.style.display = "none";
|
||||||
document.body.style.pointerEvents = "auto"; // Riattiva la pagina
|
document.body.style.pointerEvents = "auto";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +49,8 @@ $(document).ready(function () {
|
|||||||
window.addEventListener("click", function (event) {
|
window.addEventListener("click", function (event) {
|
||||||
if (event.target === partsModal) {
|
if (event.target === partsModal) {
|
||||||
partsModal.style.display = "none";
|
partsModal.style.display = "none";
|
||||||
overlay.style.display = "none"; // Nascondi overlay
|
overlay.style.display = "none";
|
||||||
document.body.style.pointerEvents = "auto"; // Riattiva la pagina
|
document.body.style.pointerEvents = "auto";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -98,13 +98,15 @@ $(document).ready(function () {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNewRow(nextPartNumber) {
|
function addNewRow(nextPartNumber, isMix = false) {
|
||||||
|
const description = isMix ? "Mix" : "";
|
||||||
const newRow = `
|
const newRow = `
|
||||||
<tr data-part-id="new">
|
<tr data-part-id="new">
|
||||||
<td><input type="number" class="form-control form-control-sm part-number" value="${nextPartNumber || 1}" style="width: 80px;"></td>
|
<td><input type="number" class="form-control form-control-sm part-number" value="${nextPartNumber || 1}" style="width: 80px;"></td>
|
||||||
<td><input type="text" class="form-control form-control-sm part-description" placeholder="Inserisci descrizione" style="width: 100%;"></td>
|
<td><input type="text" class="form-control form-control-sm part-description" value="${description}" placeholder="Inserisci descrizione" style="width: 100%;"></td>
|
||||||
<td>
|
<td>
|
||||||
<button type="button" class="btn btn-success btn-sm add-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-plus fa-xs"></i></button>
|
<button type="button" class="btn btn-success btn-sm add-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-plus fa-xs"></i></button>
|
||||||
|
<button type="button" class="btn btn-primary btn-sm add-mix-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;">M</button>
|
||||||
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; display: none;"><i class="fas fa-trash fa-xs"></i></button>
|
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; display: none;"><i class="fas fa-trash fa-xs"></i></button>
|
||||||
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check fa-xs"></i></span>
|
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check fa-xs"></i></span>
|
||||||
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin fa-xs"></i></span>
|
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin fa-xs"></i></span>
|
||||||
@@ -141,6 +143,20 @@ $(document).ready(function () {
|
|||||||
updatePartsList();
|
updatePartsList();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on("click", ".add-mix-row", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log("Pulsante Aggiungi Mix cliccato");
|
||||||
|
const maxPartNumber = Math.max(
|
||||||
|
...$("#partsTableBody tr")
|
||||||
|
.map(function () {
|
||||||
|
return parseInt($(this).find(".part-number").val()) || 0;
|
||||||
|
})
|
||||||
|
.get(),
|
||||||
|
);
|
||||||
|
addNewRow(maxPartNumber + 1, true);
|
||||||
|
updatePartsList();
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on("click", ".remove-row", function (e) {
|
$(document).on("click", ".remove-row", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log("Pulsante Rimuovi riga cliccato");
|
console.log("Pulsante Rimuovi riga cliccato");
|
||||||
@@ -202,8 +218,13 @@ $(document).ready(function () {
|
|||||||
const $saveStatus = $row.find(".save-status");
|
const $saveStatus = $row.find(".save-status");
|
||||||
const $saveLoading = $row.find(".save-loading");
|
const $saveLoading = $row.find(".save-loading");
|
||||||
const iddatadb = $("#partsModal").data("iddatadb");
|
const iddatadb = $("#partsModal").data("iddatadb");
|
||||||
|
const isMix = partDescription.startsWith("Mix") ? "Y" : "N";
|
||||||
|
|
||||||
console.log("Evento blur su input:", { partNumber, partDescription });
|
console.log("Evento blur su input:", {
|
||||||
|
partNumber,
|
||||||
|
partDescription,
|
||||||
|
isMix,
|
||||||
|
});
|
||||||
|
|
||||||
if (partDescription && iddatadb) {
|
if (partDescription && iddatadb) {
|
||||||
$saveLoading.show();
|
$saveLoading.show();
|
||||||
@@ -218,6 +239,7 @@ $(document).ready(function () {
|
|||||||
{
|
{
|
||||||
part_number: partNumber,
|
part_number: partNumber,
|
||||||
part_description: partDescription,
|
part_description: partDescription,
|
||||||
|
mix: isMix,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@@ -264,6 +286,7 @@ $(document).ready(function () {
|
|||||||
<td><input type="text" class="form-control form-control-sm part-description" value="${part.part_description}" style="width: 100%;"></td>
|
<td><input type="text" class="form-control form-control-sm part-description" value="${part.part_description}" style="width: 100%;"></td>
|
||||||
<td>
|
<td>
|
||||||
<button type="button" class="btn btn-success btn-sm add-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-plus fa-xs"></i></button>
|
<button type="button" class="btn btn-success btn-sm add-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-plus fa-xs"></i></button>
|
||||||
|
<button type="button" class="btn btn-primary btn-sm add-mix-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;">M</button>
|
||||||
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-trash fa-xs"></i></button>
|
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-trash fa-xs"></i></button>
|
||||||
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check fa-xs"></i></span>
|
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check fa-xs"></i></span>
|
||||||
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin fa-xs"></i></span>
|
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin fa-xs"></i></span>
|
||||||
@@ -297,19 +320,61 @@ $(document).ready(function () {
|
|||||||
$("#partsTableBody tr").each(function () {
|
$("#partsTableBody tr").each(function () {
|
||||||
const partNumber = $(this).find(".part-number").val();
|
const partNumber = $(this).find(".part-number").val();
|
||||||
const partDescription = $(this).find(".part-description").val();
|
const partDescription = $(this).find(".part-description").val();
|
||||||
if (partNumber && partDescription) {
|
if (
|
||||||
const listItem = `<li class="list-group-item" data-part-number="${partNumber}">${partNumber} - ${partDescription}</li>`;
|
partNumber &&
|
||||||
|
partDescription &&
|
||||||
|
!partDescription.startsWith("Mix")
|
||||||
|
) {
|
||||||
|
const listItem = `
|
||||||
|
<li class="list-group-item" data-part-number="${partNumber}">
|
||||||
|
${partNumber} - ${partDescription}
|
||||||
|
<button type="button" class="btn btn-success btn-sm add-to-mix-btn" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;"><i class="fas fa-plus fa-xs"></i></button>
|
||||||
|
</li>`;
|
||||||
$("#partsList").append(listItem);
|
$("#partsList").append(listItem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$(document).on("click", ".add-to-mix-btn", function () {
|
||||||
|
const $listItem = $(this).closest("li");
|
||||||
|
const partDescription = $listItem.text().split(" - ")[1].trim(); // Prende tutta la descrizione dopo il trattino
|
||||||
|
const $mixRow = $("#partsTableBody tr")
|
||||||
|
.filter(function () {
|
||||||
|
return $(this)
|
||||||
|
.find(".part-description")
|
||||||
|
.val()
|
||||||
|
.startsWith("Mix");
|
||||||
|
})
|
||||||
|
.last();
|
||||||
|
|
||||||
|
if ($mixRow.length === 0) {
|
||||||
|
alert("Crea prima una riga Mix usando il pulsante 'M'.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const $descriptionInput = $mixRow.find(".part-description");
|
||||||
|
let currentDescription = $descriptionInput.val().trim();
|
||||||
|
|
||||||
|
if (currentDescription === "Mix") {
|
||||||
|
currentDescription = `Mix ${partDescription}`;
|
||||||
|
} else if (!currentDescription.includes(partDescription)) {
|
||||||
|
currentDescription += ` + ${partDescription}`;
|
||||||
|
} else {
|
||||||
|
return; // Parte già presente, non aggiungerla
|
||||||
|
}
|
||||||
|
|
||||||
|
$descriptionInput.val(currentDescription);
|
||||||
|
$descriptionInput.trigger("blur"); // Attiva il salvataggio
|
||||||
|
updatePartsList();
|
||||||
|
});
|
||||||
|
|
||||||
let selectedPartNumber = null;
|
let selectedPartNumber = null;
|
||||||
let markers = [];
|
let markers = [];
|
||||||
let descriptionPosition = { x: 10, y: 10 };
|
let descriptionPosition = { x: 10, y: 10 };
|
||||||
let hasDescriptions = false;
|
let hasDescriptions = false;
|
||||||
|
|
||||||
$("#partsList").on("click", "li", function () {
|
$("#partsList").on("click", "li", function (e) {
|
||||||
|
if ($(e.target).hasClass("add-to-mix-btn")) return;
|
||||||
selectedPartNumber = $(this).data("part-number");
|
selectedPartNumber = $(this).data("part-number");
|
||||||
console.log("Part number selezionato:", selectedPartNumber);
|
console.log("Part number selezionato:", selectedPartNumber);
|
||||||
$(this).addClass("active").siblings().removeClass("active");
|
$(this).addClass("active").siblings().removeClass("active");
|
||||||
@@ -451,7 +516,11 @@ $(document).ready(function () {
|
|||||||
$("#partsTableBody tr").each(function () {
|
$("#partsTableBody tr").each(function () {
|
||||||
const partNumber = $(this).find(".part-number").val();
|
const partNumber = $(this).find(".part-number").val();
|
||||||
const partDescription = $(this).find(".part-description").val();
|
const partDescription = $(this).find(".part-description").val();
|
||||||
if (partNumber && partDescription) {
|
if (
|
||||||
|
partNumber &&
|
||||||
|
partDescription &&
|
||||||
|
!partDescription.startsWith("Mix")
|
||||||
|
) {
|
||||||
partsList.push(`${partNumber} ${partDescription}`);
|
partsList.push(`${partNumber} ${partDescription}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -525,7 +594,11 @@ $(document).ready(function () {
|
|||||||
$("#partsTableBody tr").each(function () {
|
$("#partsTableBody tr").each(function () {
|
||||||
const partNumber = $(this).find(".part-number").val();
|
const partNumber = $(this).find(".part-number").val();
|
||||||
const partDescription = $(this).find(".part-description").val();
|
const partDescription = $(this).find(".part-description").val();
|
||||||
if (partNumber && partDescription) {
|
if (
|
||||||
|
partNumber &&
|
||||||
|
partDescription &&
|
||||||
|
!partDescription.startsWith("Mix")
|
||||||
|
) {
|
||||||
partsList.push(`${partNumber} ${partDescription}`);
|
partsList.push(`${partNumber} ${partDescription}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,6 +21,89 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Funzione per gestire la webcam
|
||||||
|
function setupWebcam(iddatadb) {
|
||||||
|
const openWebcamBtn = document.getElementById("openWebcamBtn");
|
||||||
|
const webcamArea = document.getElementById("webcamArea");
|
||||||
|
const webcamVideo = document.getElementById("webcamVideo");
|
||||||
|
const captureBtn = document.getElementById("captureBtn");
|
||||||
|
const closeWebcamBtn = document.getElementById("closeWebcamBtn");
|
||||||
|
let stream = null;
|
||||||
|
|
||||||
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
||||||
|
console.warn("La webcam non è supportata dal browser.");
|
||||||
|
if (openWebcamBtn) openWebcamBtn.style.display = "none";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!openWebcamBtn ||
|
||||||
|
!webcamArea ||
|
||||||
|
!webcamVideo ||
|
||||||
|
!captureBtn ||
|
||||||
|
!closeWebcamBtn
|
||||||
|
) {
|
||||||
|
console.error("Elementi webcam mancanti");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apri la webcam
|
||||||
|
openWebcamBtn.addEventListener("click", async () => {
|
||||||
|
try {
|
||||||
|
stream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
video: true,
|
||||||
|
});
|
||||||
|
webcamVideo.srcObject = stream;
|
||||||
|
webcamArea.style.display = "block";
|
||||||
|
openWebcamBtn.style.display = "none";
|
||||||
|
dropArea.style.display = "none";
|
||||||
|
} catch (error) {
|
||||||
|
alert("Errore nell'accesso alla webcam: " + error.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cattura la foto
|
||||||
|
captureBtn.addEventListener("click", () => {
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.width = webcamVideo.videoWidth;
|
||||||
|
canvas.height = webcamVideo.videoHeight;
|
||||||
|
canvas
|
||||||
|
.getContext("2d")
|
||||||
|
.drawImage(webcamVideo, 0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// Converti l'immagine in un file
|
||||||
|
canvas.toBlob(async (blob) => {
|
||||||
|
const file = new File(
|
||||||
|
[blob],
|
||||||
|
`webcam_photo_${Date.now()}.jpg`,
|
||||||
|
{ type: "image/jpeg" },
|
||||||
|
);
|
||||||
|
const loader = document.getElementById("loader");
|
||||||
|
if (loader) {
|
||||||
|
console.log("Mostro loader per upload webcam");
|
||||||
|
loader.style.display = "flex";
|
||||||
|
}
|
||||||
|
await handleFiles([file], iddatadb);
|
||||||
|
closeWebcam();
|
||||||
|
}, "image/jpeg");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Chiudi la webcam
|
||||||
|
closeWebcamBtn.addEventListener("click", () => {
|
||||||
|
closeWebcam();
|
||||||
|
});
|
||||||
|
|
||||||
|
function closeWebcam() {
|
||||||
|
if (stream) {
|
||||||
|
stream.getTracks().forEach((track) => track.stop());
|
||||||
|
webcamVideo.srcObject = null;
|
||||||
|
webcamArea.style.display = "none";
|
||||||
|
openWebcamBtn.style.display = "block";
|
||||||
|
dropArea.style.display = "block";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Funzione per attaccare gli event listener al contenuto del popup
|
// Funzione per attaccare gli event listener al contenuto del popup
|
||||||
function attachPhotoEventListeners(iddatadb) {
|
function attachPhotoEventListeners(iddatadb) {
|
||||||
const dropArea = document.getElementById("dropArea");
|
const dropArea = document.getElementById("dropArea");
|
||||||
@@ -67,17 +150,35 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
dropArea.addEventListener(
|
dropArea.addEventListener(
|
||||||
"drop",
|
"drop",
|
||||||
(e) => {
|
(e) => {
|
||||||
|
console.log("Evento drop attivato");
|
||||||
const files = e.dataTransfer.files;
|
const files = e.dataTransfer.files;
|
||||||
handleFiles(files, iddatadb);
|
if (files.length > 0) {
|
||||||
|
handleFiles(files, iddatadb);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
dropArea.addEventListener("click", () => photoInput.click(), false);
|
dropArea.addEventListener(
|
||||||
|
"click",
|
||||||
|
() => {
|
||||||
|
console.log("Click su dropArea, apro input file");
|
||||||
|
photoInput.click();
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
photoInput.addEventListener(
|
photoInput.addEventListener(
|
||||||
"change",
|
"change",
|
||||||
() => handleFiles(photoInput.files, iddatadb),
|
(e) => {
|
||||||
|
console.log("Evento change su photoInput");
|
||||||
|
const files = e.target.files;
|
||||||
|
if (files.length > 0) {
|
||||||
|
handleFiles(files, iddatadb);
|
||||||
|
}
|
||||||
|
// Resetta l'input per consentire il caricamento dello stesso file
|
||||||
|
e.target.value = "";
|
||||||
|
},
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -116,6 +217,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Gestione ingrandimento immagini
|
// Gestione ingrandimento immagini
|
||||||
document.querySelectorAll(".thumbnail").forEach((img) => {
|
document.querySelectorAll(".thumbnail").forEach((img) => {
|
||||||
img.addEventListener("click", function () {
|
img.addEventListener("click", function () {
|
||||||
|
console.log("Click su thumbnail, apro modale immagine");
|
||||||
const enlargedImage = document.getElementById("enlargedImage");
|
const enlargedImage = document.getElementById("enlargedImage");
|
||||||
enlargedImage.src = this.src;
|
enlargedImage.src = this.src;
|
||||||
document.getElementById("imageModal").style.display = "block";
|
document.getElementById("imageModal").style.display = "block";
|
||||||
@@ -126,6 +228,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
const imageCloseBtn = document.querySelector(".image-modal-close");
|
const imageCloseBtn = document.querySelector(".image-modal-close");
|
||||||
if (imageCloseBtn) {
|
if (imageCloseBtn) {
|
||||||
imageCloseBtn.addEventListener("click", () => {
|
imageCloseBtn.addEventListener("click", () => {
|
||||||
|
console.log("Chiusura modale immagine");
|
||||||
document.getElementById("imageModal").style.display = "none";
|
document.getElementById("imageModal").style.display = "none";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -133,18 +236,46 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
.getElementById("imageModal")
|
.getElementById("imageModal")
|
||||||
.addEventListener("click", function (event) {
|
.addEventListener("click", function (event) {
|
||||||
if (event.target === this) {
|
if (event.target === this) {
|
||||||
|
console.log(
|
||||||
|
"Chiusura modale immagine cliccando sullo sfondo",
|
||||||
|
);
|
||||||
this.style.display = "none";
|
this.style.display = "none";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Inizializza la gestione della webcam
|
||||||
|
setupWebcam(iddatadb);
|
||||||
|
|
||||||
|
// Assicurati che il loader sia nascosto all'apertura del popup
|
||||||
|
const loader = document.getElementById("loader");
|
||||||
|
if (loader) {
|
||||||
|
console.log("Nascondo loader all'apertura del popup");
|
||||||
|
loader.style.display = "none";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Funzione per gestire il caricamento dei file
|
// Funzione per gestire il caricamento dei file
|
||||||
async function handleFiles(files, iddatadb) {
|
async function handleFiles(files, iddatadb) {
|
||||||
|
const loader = document.getElementById("loader");
|
||||||
|
if (!loader) {
|
||||||
|
console.error("Elemento loader non trovato");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!files || files.length === 0) {
|
||||||
|
console.warn("Nessun file da caricare");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
if (!file.type.startsWith("image/")) {
|
if (!file.type.startsWith("image/")) {
|
||||||
alert("Per favore, carica solo immagini!");
|
alert("Per favore, carica solo immagini!");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Inizio upload del file:", file.name);
|
||||||
|
loader.style.display = "flex";
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("photo", file);
|
formData.append("photo", file);
|
||||||
formData.append("iddatadb", iddatadb);
|
formData.append("iddatadb", iddatadb);
|
||||||
@@ -155,12 +286,18 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
});
|
});
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
console.log(
|
||||||
|
"Upload completato con successo, ricarico popup",
|
||||||
|
);
|
||||||
loadPopupContent(iddatadb);
|
loadPopupContent(iddatadb);
|
||||||
} else {
|
} else {
|
||||||
alert("Errore durante il caricamento: " + result.message);
|
alert("Errore durante il caricamento: " + result.message);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert("Errore durante il caricamento: " + error.message);
|
alert("Errore durante il caricamento: " + error.message);
|
||||||
|
} finally {
|
||||||
|
console.log("Nascondo loader dopo upload");
|
||||||
|
loader.style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,6 +322,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
closeBtn.addEventListener("click", function () {
|
closeBtn.addEventListener("click", function () {
|
||||||
|
console.log("Chiusura modale photos");
|
||||||
photosModal.style.display = "none";
|
photosModal.style.display = "none";
|
||||||
document.querySelector(".overlay").style.display = "none";
|
document.querySelector(".overlay").style.display = "none";
|
||||||
document.body.style.pointerEvents = "auto";
|
document.body.style.pointerEvents = "auto";
|
||||||
@@ -192,6 +330,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
|
|
||||||
window.addEventListener("click", function (event) {
|
window.addEventListener("click", function (event) {
|
||||||
if (event.target === photosModal) {
|
if (event.target === photosModal) {
|
||||||
|
console.log("Chiusura modale photos cliccando sullo sfondo");
|
||||||
photosModal.style.display = "none";
|
photosModal.style.display = "none";
|
||||||
document.querySelector(".overlay").style.display = "none";
|
document.querySelector(".overlay").style.display = "none";
|
||||||
document.body.style.pointerEvents = "auto";
|
document.body.style.pointerEvents = "auto";
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ $result->saveToFile($qrCodeFile);
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="popup-content">
|
<div class="popup-content">
|
||||||
|
<div id="loader" class="loader" style="display: none;">
|
||||||
|
<div style="text-align: center; color: white;">
|
||||||
|
<i class="fas fa-spinner fa-spin" style="font-size: 40px;"></i>
|
||||||
|
<p>Caricamento in corso...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<h3>Manage Photos</h3>
|
<h3>Manage Photos</h3>
|
||||||
<p><strong>ID Row:</strong> <?= htmlspecialchars($idriga) ?></p>
|
<p><strong>ID Row:</strong> <?= htmlspecialchars($idriga) ?></p>
|
||||||
<p><strong>Sample Code:</strong> <?= htmlspecialchars($sampleCode) ?></p>
|
<p><strong>Sample Code:</strong> <?= htmlspecialchars($sampleCode) ?></p>
|
||||||
@@ -91,7 +97,16 @@ $result->saveToFile($qrCodeFile);
|
|||||||
<p>Drag the photo here or click to select</p>
|
<p>Drag the photo here or click to select</p>
|
||||||
<input type="file" id="photoInput" multiple accept="image/*" style="display: none;">
|
<input type="file" id="photoInput" multiple accept="image/*" style="display: none;">
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Area per la webcam -->
|
||||||
|
<div id="webcamArea" style="display: none; text-align: center; margin-bottom: 20px;">
|
||||||
|
<p>Webcam Preview</p>
|
||||||
|
<video id="webcamVideo" autoplay playsinline style="max-width: 100%; max-height: 300px;"></video>
|
||||||
|
<div style="margin-top: 10px;">
|
||||||
|
<button id="captureBtn" style="padding: 10px 20px; background: #28a745; color: white; border: none; cursor: pointer;">Capture Photo</button>
|
||||||
|
<button id="closeWebcamBtn" style="padding: 10px 20px; background: #dc3545; color: white; border: none; cursor: pointer;">Close Webcam</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button id="openWebcamBtn" style="padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; margin-bottom: 20px;">Take Photo with Webcam</button>
|
||||||
<!-- Elenco delle foto -->
|
<!-- Elenco delle foto -->
|
||||||
<div id="photosList">
|
<div id="photosList">
|
||||||
<?php if (empty($photos)): ?>
|
<?php if (empty($photos)): ?>
|
||||||
@@ -149,7 +164,6 @@ $result->saveToFile($qrCodeFile);
|
|||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 1001;
|
z-index: 1001;
|
||||||
/* Sopra il popup principale */
|
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -184,31 +198,30 @@ $result->saveToFile($qrCodeFile);
|
|||||||
color: #bbb;
|
color: #bbb;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Stili per il loader */
|
||||||
|
.loader {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1002;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader .fa-spinner {
|
||||||
|
font-size: 40px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader p {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
|
||||||
// Gestione del click sulle immagini per ingrandirle
|
|
||||||
document.querySelectorAll('.thumbnail').forEach(img => {
|
|
||||||
img.addEventListener('click', function() {
|
|
||||||
const modal = document.getElementById('imageModal');
|
|
||||||
const enlargedImage = document.getElementById('enlargedImage');
|
|
||||||
enlargedImage.src = this.src;
|
|
||||||
modal.style.display = 'block';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Gestione della chiusura del modale
|
|
||||||
const modal = document.getElementById('imageModal');
|
|
||||||
const closeBtn = document.querySelector('.image-modal-close');
|
|
||||||
|
|
||||||
closeBtn.addEventListener('click', function() {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
});
|
|
||||||
|
|
||||||
// Chiudi il modale cliccando fuori dall'immagine
|
|
||||||
modal.addEventListener('click', function(event) {
|
|
||||||
if (event.target === modal) {
|
|
||||||
modal.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@@ -19,14 +19,16 @@ if (!$iddatadb || empty($parts)) {
|
|||||||
$part = $parts[0];
|
$part = $parts[0];
|
||||||
$partNumber = $part['part_number'] ?? null;
|
$partNumber = $part['part_number'] ?? null;
|
||||||
$partDescription = $part['part_description'] ?? '';
|
$partDescription = $part['part_description'] ?? '';
|
||||||
|
$mix = $part['mix'] ?? 'N'; // Aggiunto per gestire il campo mix
|
||||||
|
|
||||||
if ($partDescription) {
|
if ($partDescription) {
|
||||||
try {
|
try {
|
||||||
$stmt = $pdo->prepare("INSERT INTO identification_parts (iddatadb, part_number, part_description, created_at, updated_at) VALUES (:iddatadb, :part_number, :part_description, NOW(), NOW())");
|
$stmt = $pdo->prepare("INSERT INTO identification_parts (iddatadb, part_number, part_description, mix, created_at, updated_at) VALUES (:iddatadb, :part_number, :part_description, :mix, NOW(), NOW())");
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
':iddatadb' => $iddatadb,
|
':iddatadb' => $iddatadb,
|
||||||
':part_number' => $partNumber,
|
':part_number' => $partNumber,
|
||||||
':part_description' => $partDescription
|
':part_description' => $partDescription,
|
||||||
|
':mix' => $mix
|
||||||
]);
|
]);
|
||||||
echo json_encode(['success' => true, 'message' => 'Parte salvata con successo']);
|
echo json_encode(['success' => true, 'message' => 'Parte salvata con successo']);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
|
|||||||