Compare commits

..

21 Commits

Author SHA1 Message Date
solocla bb34b775bd added matrice to identification parts 2025-09-16 19:09:07 +02:00
solocla 8b08969c69 get matrice 2025-09-16 11:39:44 +02:00
solocla 34d4dc8660 quotations page 2025-09-13 12:31:31 +02:00
solocla 1510ef03f1 added level to collahge 2025-09-12 18:09:01 +02:00
solocla ce8c95921f remove .env from repository 2025-09-12 10:17:22 +02:00
solocla 095a6ae879 remove debug/log/json files from tracking 2025-09-12 10:03:50 +02:00
solocla 296143016a template mapping addes is visible as checkbox and is required as badge 2025-09-12 10:01:19 +02:00
solocla 3aa2504f3c fixed cut 2025-09-08 14:01:17 +02:00
solocla c1a396f246 added canvas functionality 2025-09-08 11:40:43 +02:00
solocla a45ba1c8b3 added cut 2025-09-08 10:26:15 +02:00
solocla 7a944a73f7 get_commessaweb 2025-09-08 08:42:05 +02:00
solocla 71595cc8de added speech functions 2025-09-06 18:48:38 +02:00
solocla f89dbd0c23 added save all 2025-09-06 12:29:29 +02:00
solocla 9ba859e15b Merge remote-tracking branch 'origin/bugfix/warning-text-and-logic-change' 2025-09-05 21:44:38 +02:00
solocla 672e448e9a fixed renumerate parts 2025-09-04 15:16:19 +02:00
solocla 0749032fbc added collage, fixed parts marker color, added ri number 2025-09-04 15:01:03 +02:00
kapsona777 d692614f70 warning fix 2025-09-01 19:56:08 +04:00
solocla 1303cff9fd added export to lims button 2025-08-29 15:36:55 +02:00
solocla 6b2bd0964b fixed dropdown selection 2025-08-28 10:25:12 +02:00
solocla 0d2cf13524 update historical trf 2025-08-28 09:36:16 +02:00
solocla f6ef9c39d2 added multi webcam functionality 2025-08-27 20:21:38 +02:00
30 changed files with 52873 additions and 21517 deletions
-47
View File
@@ -1,47 +0,0 @@
APP_ENV=production
APP_DEBUG=true
APP_KEY=base64:C+sutHm6xP5sE4QXhoZFhYjArlVN11s2mDU1F8beUkM=
APP_URL=http://vanguard.test
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST="localhost"
DB_DATABASE="trfcertest"
DB_USERNAME="solocla"
DB_PASSWORD="!Massarosa2"
DB_PREFIX="auth_"
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_DRIVER=sync
SESSION_DRIVER=database
SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=mail
MAIL_FROM_NAME=Vanguard
MAIL_FROM_ADDRESS=vanguard@test.dev
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
# Credenziali API VisualLims
API_BASE_URL=https://93.43.5.102/limsapi
API_USERNAME=WebApiUser
API_PASSWORD=webapiuser01
BASE_URL=http://localhost:8000/userarea/
-36
View File
@@ -1,36 +0,0 @@
* Trying 93.43.5.102:443...
* Connected to 93.43.5.102 (93.43.5.102) port 443
* ALPN: curl offers h2,http/1.1
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN: server accepted h2
* Server certificate:
* subject: C=FR; ST=Île-de-France; O=Bureau Veritas; CN=bvcpsitaly-elims.it
* start date: Feb 17 00:00:00 2025 GMT
* expire date: Feb 17 23:59:59 2026 GMT
* issuer: C=US; O=Corporation Service Company; CN=Corporation Service Company RSA OV SSL CA
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://93.43.5.102/limsapi/api/authentication/authenticate
* [HTTP/2] [1] [:method: POST]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: 93.43.5.102]
* [HTTP/2] [1] [:path: /limsapi/api/authentication/authenticate]
* [HTTP/2] [1] [content-type: application/json]
* [HTTP/2] [1] [accept: application/json]
* [HTTP/2] [1] [content-length: 51]
> POST /limsapi/api/authentication/authenticate HTTP/2
Host: 93.43.5.102
Content-Type: application/json
Accept: application/json
Content-Length: 51
< HTTP/2 200
< cache-control: max-age=0
< content-type: application/json; charset=utf-8
< server: Microsoft-IIS/10.0
< strict-transport-security: max-age=2592000
< x-powered-by: ASP.NET
< x-content-type-options: nosniff
< date: Thu, 21 Aug 2025 10:23:44 GMT
<
* Connection #0 to host 93.43.5.102 left intact
@@ -1,35 +0,0 @@
* Trying 93.43.5.102:443...
* Connected to 93.43.5.102 (93.43.5.102) port 443
* ALPN: curl offers h2,http/1.1
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN: server accepted h2
* Server certificate:
* subject: C=FR; ST=Île-de-France; O=Bureau Veritas; CN=bvcpsitaly-elims.it
* start date: Feb 17 00:00:00 2025 GMT
* expire date: Feb 17 23:59:59 2026 GMT
* issuer: C=US; O=Corporation Service Company; CN=Corporation Service Company RSA OV SSL CA
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://93.43.5.102/limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: 93.43.5.102]
* [HTTP/2] [1] [:path: /limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues]
* [HTTP/2] [1] [authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1NTc3OTAyNSwiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.bBV1z1uaxZeUuw-2YS2gLGaxTCQJAHTieM82KVJb5nw]
* [HTTP/2] [1] [accept: application/json]
> GET /limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues HTTP/2
Host: 93.43.5.102
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1NTc3OTAyNSwiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.bBV1z1uaxZeUuw-2YS2gLGaxTCQJAHTieM82KVJb5nw
Accept: application/json
< HTTP/2 200
< cache-control: max-age=0
< content-type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8
< server: Microsoft-IIS/10.0
< strict-transport-security: max-age=2592000
< odata-version: 4.0
< x-powered-by: ASP.NET
< x-content-type-options: nosniff
< date: Thu, 21 Aug 2025 10:23:44 GMT
<
* Connection #0 to host 93.43.5.102 left intact
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,23 @@
# Swagger Codegen Ignore
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md
@@ -0,0 +1 @@
3.0.34
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+4
View File
@@ -11,3 +11,7 @@
2025-08-26 16:48:44 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper 2025-08-26 16:48:44 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-08-26 16:49:24 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper 2025-08-26 16:49:24 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-08-26 16:50:23 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper 2025-08-26 16:50:23 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-09-08 08:39:17 - Risposta non JSON valida: <?xml version="1.0" encoding="utf-8"?><edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="DevExpress.ExpressApp.SystemModule" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="DashboardViewItemDescriptor"><Key><PropertyRef Name="ViewId" /></Key><Property Name="ViewId" Type="Edm.String" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem" BaseType="DevExpress.ExpressApp.NonPersistentLiteObject" Abstract="true"><Property Name="Visibility" Type="DevExpress.ExpressApp.Editors.ViewItemVisibility" Nullable="false" /></EntityType><EntityType Name="DashboardOrganizationItem_1OfIModelDashboardViewItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem" Abstract="true" /><EntityType Name="ViewDashboardOrganizationItem" BaseType="DevExpress.ExpressApp.SystemModule.DashboardOrganizationItem_1OfIModelDashboardViewItem"><Property Name="ObjectType" Type="System.Type" /><Proper
2025-09-16 13:37:03 - Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
2025-09-16 13:37:51 - Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
2025-09-16 13:44:24 - Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
+39
View File
@@ -0,0 +1,39 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
// ID della CommessaWeb specifica (cambialo di volta in volta)
$id = 529435; // TODO: Cambia questo valore con l'ID desiderato
// Endpoint per recuperare la CommessaWeb specifica con espansione dello schema custom
$endpoint = "CommessaWeb({$id})";
// Opzioni per l'espansione: includi OrderCustomFields per ottenere i campi custom dello schema assegnato all'ordine
$options = ['$expand' => 'OrderCustomFields'];
// Debug: salva URL usato
$base_url = 'https://93.43.5.102/limsapi/api/odata/';
$query = http_build_query($options);
$full_url = $base_url . $endpoint . ($query ? '?' . $query : '');
file_put_contents(__DIR__ . '/last_url.txt', $full_url . PHP_EOL, FILE_APPEND);
// Chiamata API
$data = $api->get($endpoint, $options);
// Salva il JSON in locale
file_put_contents(__DIR__ . '/commessaweb_schema_response.json', json_encode($data, JSON_PRETTY_PRINT));
echo json_encode($data);
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
+36
View File
@@ -0,0 +1,36 @@
<?php
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
header('Content-Type: application/json');
ini_set('display_errors', '0');
error_reporting(E_ALL);
try {
$api = VisualLimsApiClient::getInstance();
// Endpoint per recuperare le Matrici
$endpoint = 'Matrice';
// (Opzionale) aggiungi parametri, ad esempio $top per limitare i risultati
$options = []; // oppure ad esempio: ['$top' => 100]
// Debug: salva URL usato
$base_url = 'https://93.43.5.102/limsapi/api/odata/';
$query = http_build_query($options);
$full_url = $base_url . $endpoint . ($query ? '?' . $query : '');
file_put_contents(__DIR__ . '/last_url.txt', $full_url . PHP_EOL, FILE_APPEND);
// Chiamata API
$data = $api->get($endpoint, $options);
// Salva il JSON in locale
file_put_contents(__DIR__ . '/matrici_response.json', json_encode($data, JSON_PRETTY_PRINT));
echo json_encode($data);
} catch (Exception $e) {
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
+263 -113
View File
@@ -128,6 +128,9 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" /> <link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<?php include('cssinclude.php'); ?> <?php include('cssinclude.php'); ?>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<style> <style>
input.auto-input, input.auto-input,
select.auto-input { select.auto-input {
@@ -499,6 +502,22 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
.proceed-btn { .proceed-btn {
margin-top: 20px; margin-top: 20px;
} }
.grid-cell.button-cell,
.grid-header.button-header {
min-width: 210px !important;
flex: 0 0 210px !important;
}
.action-btn {
padding: 6px 8px;
margin-right: 5px;
border: none;
border-radius: 5px;
cursor: pointer;
width: 50px;
box-sizing: border-box;
}
</style> </style>
<title>Dati Storici - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title> <title>Dati Storici - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
</head> </head>
@@ -610,40 +629,66 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
</div> </div>
<div id="noResults" class="text-danger" style="display:none;">Nessun risultato trovato</div> <div id="noResults" class="text-danger" style="display:none;">Nessun risultato trovato</div>
<div class="scrollbar-container"></div> <div class="scrollbar-container"></div>
<form id="editForm"> <form id="editForm">
<div class="grid-container"> <div class="grid-container">
<?php $fixedColumns = ['filename_import', 'status', 'importdate']; ?>
<?php if ($status === 'i'): ?>
<div class="grid-top"> <div class="grid-top">
<div class="grid-cell" style="flex: 0 0 100px;"></div> <div class="grid-cell actions-cell" style="flex: 0 0 200px;"></div>
<div class="grid-cell" style="flex: 0 0 100px;"></div>
<div class="grid-cell" style="flex: 0 0 100px;"></div>
<div class="grid-cell" style="flex: 0 0 150px;"></div>
<?php <?php
foreach ($fixedColumns as $col) { // Campo con main_field = 1
echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>"; if ($mainFieldMapping) {
} $inputClass = $mainFieldMapping['is_manual'] ? 'manual-input' : 'auto-input';
$autoIndex = 0; if ($mainFieldMapping['is_required']) $inputClass .= ' required-input';
foreach ($allMappings as $mapping) { $index = $mainFieldMapping['is_manual'] ? "manual_0" : "auto_0";
if (!$mapping['is_manual']) {
$inputClass = 'auto-input';
if ($mapping['is_required']) $inputClass .= ' required-input';
if ($mapping['data_type'] === 'SceltaMultipla') {
echo "<div class='grid-cell' style='flex: 0 0 150px;'>"; echo "<div class='grid-cell' style='flex: 0 0 150px;'>";
echo "<select class='custom-field dropdown-select $inputClass' data-column='auto_$autoIndex' data-field-id='{$mapping['field_id']}' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">"; if ($mainFieldMapping['data_type'] === 'SceltaMultipla') {
$fieldValue = $mainFieldMapping['manual_default'] ?? '';
echo "<select class='custom-field dropdown-select $inputClass' data-column='$index' data-field-id='{$mainFieldMapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
echo "<button type='button' class='propagate-btn' data-column='auto_$autoIndex' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>"; echo "<button type='button' class='propagate-btn' data-column='$index' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>";
} else {
$fieldValue = $mainFieldMapping['manual_default'] ?? '';
if ($mainFieldMapping['data_type'] === 'DATE' && $mainFieldMapping['manual_default'] === 'today') {
$fieldValue = date('Y-m-d');
}
if ($mainFieldMapping['data_type'] === 'DATE') {
echo "<input type='date' class='custom-field $inputClass' data-column='$index' value='" . htmlspecialchars($fieldValue) . "' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
} elseif ($mainFieldMapping['data_type'] === 'INT') {
echo "<input type='number' class='custom-field $inputClass' data-column='$index' value='" . htmlspecialchars($fieldValue) . "' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
} else {
echo "<input type='text' class='custom-field $inputClass' data-column='$index' value='" . htmlspecialchars($fieldValue) . "' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
}
echo "<button type='button' class='propagate-btn' data-column='$index' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>";
}
echo "</div>"; echo "</div>";
} else { } else {
echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>"; echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>";
} }
// Campi automatici (escluso main_field)
$autoIndex = ($mainFieldMapping && !$mainFieldMapping['is_manual']) ? 1 : 0;
foreach ($allMappings as $mapping) {
if (!$mapping['is_manual'] && $mapping['main_field'] != 1) {
$inputClass = 'auto-input';
if ($mapping['is_required']) $inputClass .= ' required-input';
echo "<div class='grid-cell' style='flex: 0 0 150px;'>";
if ($mapping['data_type'] === 'SceltaMultipla') {
$fieldValue = $mapping['manual_default'] ?? '';
echo "<select class='custom-field dropdown-select $inputClass' data-column='auto_$autoIndex' data-field-id='{$mapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
echo "<option value=''>Seleziona...</option>";
echo "</select>";
echo "<button type='button' class='propagate-btn' data-column='auto_$autoIndex' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>";
} else {
echo "<div style='height: 34px;'></div>";
}
echo "</div>";
$autoIndex++; $autoIndex++;
} }
} }
$manualIndex = 0; // Campi manuali (escluso main_field)
$manualIndex = ($mainFieldMapping && $mainFieldMapping['is_manual']) ? 1 : 0;
foreach ($allMappings as $mapping) { foreach ($allMappings as $mapping) {
if ($mapping['is_manual']) { if ($mapping['is_manual'] && $mapping['main_field'] != 1) {
$fieldValue = $mapping['manual_default'] ?? ''; $fieldValue = $mapping['manual_default'] ?? '';
if ($mapping['data_type'] === 'DATE' && $mapping['manual_default'] === 'today') { if ($mapping['data_type'] === 'DATE' && $mapping['manual_default'] === 'today') {
$fieldValue = date('Y-m-d'); $fieldValue = date('Y-m-d');
@@ -652,100 +697,122 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if ($mapping['is_required']) $inputClass .= ' required-input'; if ($mapping['is_required']) $inputClass .= ' required-input';
echo "<div class='grid-cell' style='flex: 0 0 150px;'>"; echo "<div class='grid-cell' style='flex: 0 0 150px;'>";
if ($mapping['data_type'] === 'SceltaMultipla') { if ($mapping['data_type'] === 'SceltaMultipla') {
echo "<select class='custom-field dropdown-select $inputClass' data-column='manual_$manualIndex' data-field-id='{$mapping['field_id']}' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">"; echo "<select class='custom-field dropdown-select $inputClass' data-column='manual_$manualIndex' data-field-id='{$mapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
echo "<button type='button' class='propagate-btn' data-column='manual_$manualIndex' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>"; echo "<button type='button' class='propagate-btn' data-column='manual_$manualIndex' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>";
} elseif ($mapping['data_type'] === 'DATE') { } elseif ($mapping['data_type'] === 'DATE') {
echo "<input type='date' class='custom-field $inputClass' data-column='manual_$manualIndex' value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">"; echo "<input type='date' class='custom-field $inputClass' data-column='manual_$manualIndex' value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
echo "<button type='button' class='propagate-btn' data-column='manual_$manualIndex' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>";
} elseif ($mapping['data_type'] === 'INT') { } elseif ($mapping['data_type'] === 'INT') {
echo "<input type='number' class='custom-field $inputClass' data-column='manual_$manualIndex' value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">"; echo "<input type='number' class='custom-field $inputClass' data-column='manual_$manualIndex' value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
echo "<button type='button' class='propagate-btn' data-column='manual_$manualIndex' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>";
} else { } else {
echo "<input type='text' class='custom-field $inputClass' data-column='manual_$manualIndex' value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">"; echo "<input type='text' class='custom-field $inputClass' data-column='manual_$manualIndex' value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
}
echo "<button type='button' class='propagate-btn' data-column='manual_$manualIndex' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>"; echo "<button type='button' class='propagate-btn' data-column='manual_$manualIndex' " . ($is_readonly ? 'disabled' : '') . "><i class='fas fa-arrow-down'></i></button>";
}
echo "</div>"; echo "</div>";
$manualIndex++; $manualIndex++;
} }
} }
// Colonne status, Import Reference Code, filename_import
$fixedColumnsReduced = ['status'];
foreach ($fixedColumnsReduced as $col) {
echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>";
}
echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>"; // Import Reference Code
echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>"; // filename_import
// AWB Number e Tracking Info
echo "<div class='grid-cell' style='flex: 0 0 200px;'></div>"; echo "<div class='grid-cell' style='flex: 0 0 200px;'></div>";
echo "<div class='grid-cell' style='flex: 0 0 250px;'></div>"; echo "<div class='grid-cell' style='flex: 0 0 250px;'></div>";
?> ?>
</div> </div>
<?php endif; ?>
<div class="grid-row"> <div class="grid-row">
<div class="grid-header" style="flex: 0 0 100px;">Save</div> <div class="grid-header actions-cell" style="flex: 0 0 200px; position: relative;">Azioni<div class="resizer"></div>
<div class="grid-header" style="flex: 0 0 100px;">Photos</div>
<div class="grid-header" style="flex: 0 0 100px;">Parts</div>
<div class="grid-header" data-index="3" style="flex: 0 0 150px; position: relative;">Import Reference Code<div class="resizer"></div>
</div> </div>
<?php <?php
$headerIndex = 4; // Header per il campo main_field = 1
foreach ($fixedColumns as $col) { $headerIndex = 1;
if ($mainFieldMapping) {
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>" . htmlspecialchars($mainFieldMapping['field_label']) . "<div class='resizer'></div></div>";
$headerIndex++;
}
// Header per campi automatici (escluso main_field)
foreach ($allMappings as $mapping) {
if (!$mapping['is_manual'] && $mapping['main_field'] != 1) {
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>" . htmlspecialchars($mapping['field_label']) . "<div class='resizer'></div></div>";
$headerIndex++;
}
}
// Header per campi manuali (escluso main_field)
foreach ($allMappings as $mapping) {
if ($mapping['is_manual'] && $mapping['main_field'] != 1) {
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>" . htmlspecialchars($mapping['field_label']) . "<div class='resizer'></div></div>";
$headerIndex++;
}
}
// Header per status, Import Reference Code, filename_import
foreach ($fixedColumnsReduced as $col) {
$displayName = $slugMapping[$col] ?? $col; $displayName = $slugMapping[$col] ?? $col;
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>$displayName<div class='resizer'></div></div>"; echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>$displayName<div class='resizer'></div></div>";
$headerIndex++; $headerIndex++;
} }
foreach ($allMappings as $mapping) { echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>Import Reference Code<div class='resizer'></div></div>";
if (!$mapping['is_manual']) {
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>" . htmlspecialchars($mapping['field_label']) . "<div class='resizer'></div></div>";
$headerIndex++; $headerIndex++;
} echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>File<div class='resizer'></div></div>";
}
foreach ($allMappings as $mapping) {
if ($mapping['is_manual']) {
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 150px; position: relative;'>" . htmlspecialchars($mapping['field_label']) . "<div class='resizer'></div></div>";
$headerIndex++; $headerIndex++;
} // Header per AWB Number e Tracking Info
}
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 200px; position: relative;'>AWB Number<div class='resizer'></div></div>"; echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 200px; position: relative;'>AWB Number<div class='resizer'></div></div>";
echo "<div class='grid-header' data-index='" . ($headerIndex + 1) . "' style='flex: 0 0 250px; position: relative;'>Tracking Info<div class='resizer'></div></div>"; $headerIndex++;
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 250px; position: relative;'>Tracking Info<div class='resizer'></div></div>";
?> ?>
</div> </div>
<?php foreach ($importedData as $index => $row): ?> <?php foreach ($importedData as $index => $row): ?>
<div class="grid-row" data-id="<?= $row['iddatadb'] ?>"> <div class="grid-row" data-id="<?= $row['iddatadb'] ?>">
<div class="grid-cell" style="flex: 0 0 100px; position: relative;"> <div class="grid-cell actions-cell" style="flex: 0 0 200px; position: relative;">
<div style="display: flex; gap: 5px; justify-content: center;">
<?php if (!$is_readonly): ?> <?php if (!$is_readonly): ?>
<button type="button" class="save-btn action-btn" data-row="<?= $index ?>" style="background: #28a745; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: pointer; width: 100%; box-sizing: border-box;"><i class="fas fa-save"></i></button> <button type="button" class="save-btn action-btn" data-row="<?= $index ?>" style="background: #28a745; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: pointer; flex: 1;"><i class="fas fa-save"></i></button>
<button type="button" class="photos-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" style="background: #007bff; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: pointer; flex: 1;"><i class="fas fa-camera"></i></button>
<button type="button" class="parts-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" style="background: #ffc107; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: pointer; flex: 1;"><i class="fas fa-puzzle-piece"></i></button>
<?php else: ?> <?php else: ?>
<button type="button" class="save-btn action-btn" data-row="<?= $index ?>" style="background: #ccc; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: not-allowed; width: 100%; box-sizing: border-box;" disabled><i class="fas fa-save"></i></button> <button type="button" class="save-btn action-btn" data-row="<?= $index ?>" style="background: #ccc; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: not-allowed; flex: 1;" disabled><i class="fas fa-save"></i></button>
<button type="button" class="photos-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" style="background: #ccc; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: not-allowed; flex: 1;" disabled><i class="fas fa-camera"></i></button>
<button type="button" class="parts-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" style="background: #ccc; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: not-allowed; flex: 1;" disabled><i class="fas fa-puzzle-piece"></i></button>
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="grid-cell" style="flex: 0 0 100px; position: relative;">
<button type="button" class="photos-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" style="background: #007bff; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: pointer; width: 100%; box-sizing: border-box;"><i class="fas fa-camera"></i></button>
</div>
<div class="grid-cell" style="flex: 0 0 100px; position: relative;">
<button type="button" class="parts-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" style="background: #ffc107; color: white; border: none; padding: 8px 12px; border-radius: 5px; cursor: pointer; width: 100%; box-sizing: border-box;"><i class="fas fa-puzzle-piece"></i></button>
</div> </div>
<?php <?php
$cellIndex = 3; $cellIndex = 1;
echo "<div class='grid-cell' data-col='importreferencecode' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
echo "<span>" . htmlspecialchars($row['importreferencecode']) . "</span>";
echo "<input type='hidden' name='rows[$index][importreferencecode]' value='" . htmlspecialchars($row['importreferencecode']) . "'>";
echo "</div>";
$cellIndex++;
foreach ($fixedColumns as $col) {
$value = $row[$col] ?? '';
echo "<div class='grid-cell editable-cell' data-col='$col' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
if ($col === 'importdate') {
echo "<span>" . htmlspecialchars($value) . "</span>";
echo "<input type='hidden' name='rows[$index][$col]' value='" . htmlspecialchars($value) . "'>";
} elseif ($col === 'filename_import') {
echo "<a href='imported_trf/" . htmlspecialchars($value) . "' target='_blank'>File</a>";
echo "<input type='hidden' name='rows[$index][$col]' value='" . htmlspecialchars($value) . "'>";
} elseif ($col === 'status') {
$badgeClass = $value === 'i' ? 'status-i' : ($value === 'P' ? 'status-P' : 'status-l');
$badgeText = $value === 'i' ? 'Imported' : ($value === 'P' ? 'Progress' : 'LIMS');
echo "<span class='status-badge $badgeClass'>" . htmlspecialchars($badgeText) . "</span>";
echo "<input type='hidden' name='rows[$index][$col]' value='" . htmlspecialchars($value ?? 'i') . "'>";
}
echo "</div>";
$cellIndex++;
}
$rowDetails = array_filter($manualDetails, fn($d) => $d['datadb_id'] == $row['iddatadb']); $rowDetails = array_filter($manualDetails, fn($d) => $d['datadb_id'] == $row['iddatadb']);
$autoIndex = 0; // Campo con main_field = 1
if ($mainFieldMapping) {
$detail = array_filter($rowDetails, fn($d) => $d['mapping_id'] == $mainFieldMapping['id']);
$detail = reset($detail) ?: ['field_value' => $mainFieldMapping['manual_default']];
$fieldValue = $detail['field_value'] ?? $mainFieldMapping['manual_default'] ?? '';
$requiredClass = ($mainFieldMapping['is_required'] && (is_null($fieldValue) || $fieldValue === '')) ? 'missing-required' : '';
$inputClass = $mainFieldMapping['is_manual'] ? 'manual-input' : 'auto-input';
if ($mainFieldMapping['is_required']) $inputClass .= ' required-input';
$indexField = $mainFieldMapping['is_manual'] ? "manual_0" : "auto_0";
echo "<div class='grid-cell editable-cell $requiredClass' data-col='$indexField' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
if ($mainFieldMapping['data_type'] === 'SceltaMultipla') {
echo "<select name='rows[$index][details][{$mainFieldMapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mainFieldMapping['id']}' data-field-id='{$mainFieldMapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
echo "<option value=''>Seleziona...</option>";
echo "</select>";
} elseif ($mainFieldMapping['data_type'] === 'DATE') {
echo "<input type='date' name='rows[$index][details][{$mainFieldMapping['id']}][field_value]' value='" . htmlspecialchars($fieldValue) . "' class='cell-input $inputClass' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
} elseif ($mainFieldMapping['data_type'] === 'INT') {
echo "<input type='number' name='rows[$index][details][{$mainFieldMapping['id']}][field_value]' value='" . htmlspecialchars($fieldValue) . "' class='cell-input $inputClass' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
} else {
echo "<input type='text' name='rows[$index][details][{$mainFieldMapping['id']}][field_value]' value='" . htmlspecialchars($fieldValue) . "' class='cell-input $inputClass' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
}
echo "</div>";
$cellIndex++;
}
// Campi automatici (escluso main_field)
$autoIndex = ($mainFieldMapping && !$mainFieldMapping['is_manual']) ? 1 : 0;
foreach ($allMappings as $mapping) { foreach ($allMappings as $mapping) {
if (!$mapping['is_manual']) { if (!$mapping['is_manual'] && $mapping['main_field'] != 1) {
$detail = array_filter($rowDetails, fn($d) => $d['mapping_id'] == $mapping['id']); $detail = array_filter($rowDetails, fn($d) => $d['mapping_id'] == $mapping['id']);
$detail = reset($detail) ?: ['field_value' => $mapping['manual_default']]; $detail = reset($detail) ?: ['field_value' => $mapping['manual_default']];
$fieldValue = $detail['field_value'] ?? $mapping['manual_default'] ?? ''; $fieldValue = $detail['field_value'] ?? $mapping['manual_default'] ?? '';
@@ -754,7 +821,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if ($mapping['is_required']) $inputClass .= ' required-input'; if ($mapping['is_required']) $inputClass .= ' required-input';
echo "<div class='grid-cell editable-cell $requiredClass' data-col='auto_$autoIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>"; echo "<div class='grid-cell editable-cell $requiredClass' data-col='auto_$autoIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
if ($mapping['data_type'] === 'SceltaMultipla') { if ($mapping['data_type'] === 'SceltaMultipla') {
echo "<select name='rows[$index][details][{$mapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mapping['id']}' data-field-id='{$mapping['field_id']}' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">"; echo "<select name='rows[$index][details][{$mapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mapping['id']}' data-field-id='{$mapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
} elseif ($mapping['data_type'] === 'DATE') { } elseif ($mapping['data_type'] === 'DATE') {
@@ -769,9 +836,10 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$autoIndex++; $autoIndex++;
} }
} }
$manualIndex = 0; // Campi manuali (escluso main_field)
$manualIndex = ($mainFieldMapping && $mainFieldMapping['is_manual']) ? 1 : 0;
foreach ($allMappings as $mapping) { foreach ($allMappings as $mapping) {
if ($mapping['is_manual']) { if ($mapping['is_manual'] && $mapping['main_field'] != 1) {
$detail = array_filter($rowDetails, fn($d) => $d['mapping_id'] == $mapping['id']); $detail = array_filter($rowDetails, fn($d) => $d['mapping_id'] == $mapping['id']);
$detail = reset($detail) ?: ['field_value' => $mapping['manual_default']]; $detail = reset($detail) ?: ['field_value' => $mapping['manual_default']];
$fieldValue = $detail['field_value'] ?? $mapping['manual_default'] ?? ''; $fieldValue = $detail['field_value'] ?? $mapping['manual_default'] ?? '';
@@ -783,7 +851,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if ($mapping['is_required']) $inputClass .= ' required-input'; if ($mapping['is_required']) $inputClass .= ' required-input';
echo "<div class='grid-cell editable-cell $requiredClass' data-col='manual_$manualIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>"; echo "<div class='grid-cell editable-cell $requiredClass' data-col='manual_$manualIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
if ($mapping['data_type'] === 'SceltaMultipla') { if ($mapping['data_type'] === 'SceltaMultipla') {
echo "<select name='rows[$index][details][{$mapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mapping['id']}' data-field-id='{$mapping['field_id']}' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">"; echo "<select name='rows[$index][details][{$mapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mapping['id']}' data-field-id='{$mapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ($is_readonly ? ' readonly' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
} elseif ($mapping['data_type'] === 'DATE') { } elseif ($mapping['data_type'] === 'DATE') {
@@ -798,6 +866,32 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$manualIndex++; $manualIndex++;
} }
} }
// Colonna status
$fixedColumnsReduced = ['status'];
foreach ($fixedColumnsReduced as $col) {
$value = $row[$col] ?? '';
echo "<div class='grid-cell editable-cell' data-col='$col' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
if ($col === 'status') {
$badgeClass = $value === 'i' ? 'status-i' : ($value === 'P' ? 'status-P' : 'status-l');
$badgeText = $value === 'i' ? 'Imported' : ($value === 'P' ? 'Progress' : 'LIMS');
echo "<span class='status-badge $badgeClass'>" . htmlspecialchars($badgeText) . "</span>";
echo "<input type='hidden' name='rows[$index][$col]' value='" . htmlspecialchars($value ?? 'i') . "'>";
}
echo "</div>";
$cellIndex++;
}
// Colonne Import Reference Code e filename_import
echo "<div class='grid-cell' data-col='importreferencecode' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
echo "<span>" . htmlspecialchars($row['importreferencecode']) . "</span>";
echo "<input type='hidden' name='rows[$index][importreferencecode]' value='" . htmlspecialchars($row['importreferencecode']) . "'>";
echo "</div>";
$cellIndex++;
echo "<div class='grid-cell' data-col='filename_import' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
echo "<a href='imported_trf/" . htmlspecialchars($row['filename_import']) . "' target='_blank'>File</a>";
echo "<input type='hidden' name='rows[$index][filename_import]' value='" . htmlspecialchars($row['filename_import']) . "'>";
echo "</div>";
$cellIndex++;
// Colonne AWB Number e Tracking Info
?> ?>
<div class="grid-cell" style="flex: 0 0 200px;"> <div class="grid-cell" style="flex: 0 0 200px;">
<select name="rows[<?= $index ?>][carrier]" class="carrier-select" <?= $is_readonly ? 'disabled' : '' ?>> <select name="rows[<?= $index ?>][carrier]" class="carrier-select" <?= $is_readonly ? 'disabled' : '' ?>>
@@ -833,6 +927,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
</ul> </ul>
</nav> </nav>
</form> </form>
<?php <?php
if (file_exists('modal_parts.php')) { if (file_exists('modal_parts.php')) {
include 'modal_parts.php'; include 'modal_parts.php';
@@ -855,7 +950,8 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
<?php include('include/footer.php'); ?> <?php include('include/footer.php'); ?>
</div> </div>
<?php include('jsinclude.php'); ?> <?php include('jsinclude.php'); ?>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
<script src="photos.js"></script> <script src="photos.js"></script>
<script src="parts.js"></script> <script src="parts.js"></script>
<script src="tracking.js"></script> <script src="tracking.js"></script>
@@ -890,7 +986,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
const cells = row.querySelectorAll('td'); const cells = row.querySelectorAll('td');
let match = false; let match = false;
cells.forEach((cell, index) => { cells.forEach((cell, index) => {
if (index >= 1 && index <= 3) { if (index >= 1 && index <= 4) { // Cerca in ID, main_field, importreferencecode, filename
const text = cell.textContent.toLowerCase(); const text = cell.textContent.toLowerCase();
if (text.includes(filter)) { if (text.includes(filter)) {
match = true; match = true;
@@ -934,6 +1030,18 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
} }
}); });
}); });
// Gestione eliminazione multipla
const bulkActionForm = document.getElementById('bulkActionForm');
bulkActionForm.addEventListener('submit', function(e) {
const selectedCheckboxes = document.querySelectorAll('input[name="selected_ids[]"]:checked');
if (selectedCheckboxes.length === 0) {
e.preventDefault();
alert('Seleziona almeno un record da eliminare.');
} else if (!confirm('Sicuro di voler eliminare i record selezionati?')) {
e.preventDefault();
}
});
<?php else: ?> <?php else: ?>
// Gestione input e celle espandibili // Gestione input e celle espandibili
const inputs = document.querySelectorAll('.cell-input'); const inputs = document.querySelectorAll('.cell-input');
@@ -961,8 +1069,13 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
inputs.forEach(input => { inputs.forEach(input => {
const name = input.name.replace(`rows[${rowIndex}]`, '').replace(/\[|\]/g, ''); const name = input.name.replace(`rows[${rowIndex}]`, '').replace(/\[|\]/g, '');
formData.append(name, input.value); formData.append(name, input.value);
// Aggiorna data-selected-value per i dropdown
if (input.tagName === 'SELECT' && input.classList.contains('dropdown-select')) {
input.setAttribute('data-selected-value', input.value);
}
}); });
formData.append('iddatadb', iddatadb); formData.append('iddatadb', iddatadb);
formData.append('mapping', JSON.stringify(<?= json_encode($allMappings) ?>));
fetch('save_edited_row.php', { fetch('save_edited_row.php', {
method: 'POST', method: 'POST',
body: formData body: formData
@@ -977,6 +1090,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
cell.classList.add('flash-success'); cell.classList.add('flash-success');
}); });
setTimeout(() => cells.forEach(cell => cell.classList.remove('flash-success')), 500); setTimeout(() => cells.forEach(cell => cell.classList.remove('flash-success')), 500);
alert('Salvataggio avvenuto con successo!');
} else { } else {
alert('Errore durante il salvataggio: ' + data.message); alert('Errore durante il salvataggio: ' + data.message);
} }
@@ -990,12 +1104,12 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
propagateButtons.forEach(button => { propagateButtons.forEach(button => {
button.addEventListener('click', function() { button.addEventListener('click', function() {
if (this.hasAttribute('disabled')) return; if (this.hasAttribute('disabled')) return;
const columnIndex = this.getAttribute('data-column').replace('manual_', ''); const column = this.getAttribute('data-column');
const input = this.previousElementSibling; const input = this.previousElementSibling;
const value = input.value; const value = input.value;
const gridTopCells = document.querySelector('.grid-top').querySelectorAll('.grid-cell'); const gridTopCells = document.querySelector('.grid-top').querySelectorAll('.grid-cell');
const targetTopIndex = Array.from(gridTopCells).findIndex(cell => const targetTopIndex = Array.from(gridTopCells).findIndex(cell =>
cell.querySelector('.propagate-btn') === button cell.querySelector('.propagate-btn[data-column="' + column + '"]')
); );
if (targetTopIndex !== -1) { if (targetTopIndex !== -1) {
const rows = document.querySelectorAll('.grid-row'); const rows = document.querySelectorAll('.grid-row');
@@ -1004,9 +1118,12 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if (cells.length > targetTopIndex) { if (cells.length > targetTopIndex) {
const targetInput = cells[targetTopIndex].querySelector('input, select'); const targetInput = cells[targetTopIndex].querySelector('input, select');
if (targetInput && !targetInput.hasAttribute('readonly')) { if (targetInput && !targetInput.hasAttribute('readonly')) {
if (targetInput.type === 'date') targetInput.value = value; targetInput.value = value;
else if (targetInput.tagName === 'SELECT') targetInput.value = value; if (targetInput.tagName === 'SELECT') {
else targetInput.value = value; targetInput.setAttribute('data-selected-value', value);
const event = new Event('change');
targetInput.dispatchEvent(event);
}
} }
} }
}); });
@@ -1123,47 +1240,80 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
async function populateDropdowns() { async function populateDropdowns() {
if (<?= json_encode($is_readonly) ?>) return; if (<?= json_encode($is_readonly) ?>) return;
const dropdowns = document.querySelectorAll('.dropdown-select'); const dropdowns = document.querySelectorAll('.dropdown-select');
if (dropdowns.length === 0) return; console.log('Dropdown trovati:', dropdowns.length);
const uniqueFieldIds = [...new Set(Array.from(dropdowns).map(d => d.getAttribute('data-field-id')))].filter(fieldId => fieldId); if (dropdowns.length === 0) {
for (const fieldId of uniqueFieldIds) { console.warn('Nessun dropdown trovato con classe .dropdown-select');
if (!dropdownData[fieldId]) {
try {
const response = await fetch(`get_customfield_values.php?field_id=${fieldId}`);
const data = await response.json();
if (data.error) {
console.error('Errore per field_id', fieldId, ':', data.error);
continue;
}
dropdownData[fieldId] = data.CustomFieldsValues || [];
} catch (error) {
console.error('Errore nel fetch per field_id', fieldId, ':', error);
}
}
}
dropdowns.forEach(dropdown => {
const fieldId = dropdown.getAttribute('data-field-id');
if (!fieldId || !dropdownData[fieldId]) {
dropdown.innerHTML = '<option value="">Errore nel caricamento</option>';
return; return;
} }
const uniqueFieldIds = [...new Set(Array.from(dropdowns).map(d => d.getAttribute('data-field-id')))].filter(fieldId => fieldId);
console.log('Field IDs unici:', uniqueFieldIds);
const missingFieldIds = uniqueFieldIds.filter(fieldId => !dropdownData[fieldId]);
if (missingFieldIds.length > 0) {
try {
const response = await fetch(`get_customfield_values.php?field_ids=${missingFieldIds.join(',')}`);
if (!response.ok) {
throw new Error(`Errore HTTP: ${response.status} ${response.statusText}`);
}
const data = await response.json();
console.log('Risposta da get_customfield_values.php:', data);
if (data.error) {
console.error('Errore dal server:', data.error);
dropdowns.forEach(dropdown => {
dropdown.innerHTML = '<option value="">Errore server</option>';
});
return;
}
for (const fieldId of Object.keys(data)) {
dropdownData[fieldId] = data[fieldId] || [];
}
} catch (error) {
console.error('Errore nel fetch dei valori dei dropdown:', error);
dropdowns.forEach(dropdown => {
dropdown.innerHTML = '<option value="">Errore caricamento</option>';
});
return;
}
}
dropdowns.forEach(dropdown => {
const fieldId = dropdown.getAttribute('data-field-id');
const mappingId = dropdown.getAttribute('data-mapping-id');
const selectedValue = dropdown.getAttribute('data-selected-value') || '';
const currentValue = dropdown.value || '';
console.log(`Popolamento dropdown field_id=${fieldId}, mapping_id=${mappingId}, valore corrente=${currentValue}, valore selezionato=${selectedValue}`);
if (!fieldId || !dropdownData[fieldId]) {
dropdown.innerHTML = '<option value="">Nessun dato</option>';
return;
}
// Preserva il valore corrente o usa quello salvato
dropdown.innerHTML = '<option value="">Seleziona...</option>'; dropdown.innerHTML = '<option value="">Seleziona...</option>';
dropdownData[fieldId].forEach(value => { dropdownData[fieldId].forEach(value => {
const option = document.createElement('option'); const option = document.createElement('option');
option.value = value.IdCustomFieldsValue; option.value = value.IdCustomFieldsValue;
option.textContent = value.Valore; option.textContent = value.Valore;
if (dropdown.value === option.value) option.selected = true; // Dai priorità a data-selected-value per il caricamento iniziale
if (selectedValue === String(value.IdCustomFieldsValue)) {
option.selected = true;
} else if (currentValue === String(value.IdCustomFieldsValue)) {
option.selected = true;
}
dropdown.appendChild(option); dropdown.appendChild(option);
}); });
// Verifica se il valore selezionato esiste tra le opzioni
if ((selectedValue || currentValue) && dropdown.value !== (selectedValue || currentValue)) {
dropdown.value = '';
console.warn(`Valore ${selectedValue || currentValue} non trovato per fieldId ${fieldId}`);
}
}); });
} }
populateDropdowns(); populateDropdowns();
saveButtons.forEach(btn => {
btn.addEventListener('click', function() {
if (!this.hasAttribute('disabled')) {
setTimeout(populateDropdowns, 100);
}
});
});
<?php endif; ?> <?php endif; ?>
}); });
</script> </script>
File diff suppressed because one or more lines are too long
+255 -144
View File
@@ -21,8 +21,8 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['template_id']) || !i
$template_id = intval($_POST['template_id']) ?? $_SESSION['template_id']; $template_id = intval($_POST['template_id']) ?? $_SESSION['template_id'];
$selected_rows = $_POST['selected_rows'] ?? $_SESSION['selected_rows']; $selected_rows = $_POST['selected_rows'] ?? $_SESSION['selected_rows'];
$columns = json_decode($_POST['columns'], true) ?? $_SESSION['columns']; // Header dell'XLS $columns = json_decode($_POST['columns'], true) ?? $_SESSION['columns'];
$rows = json_decode($_POST['rows'], true) ?? $_SESSION['rows']; // Dati dell'XLS $rows = json_decode($_POST['rows'], true) ?? $_SESSION['rows'];
$newFilename = htmlspecialchars($_POST['filename']) ?? $_SESSION['filename']; $newFilename = htmlspecialchars($_POST['filename']) ?? $_SESSION['filename'];
// Log dei dati ricevuti // Log dei dati ricevuti
@@ -31,7 +31,7 @@ error_log("Columns: " . json_encode($columns));
error_log("Rows: " . json_encode($rows)); error_log("Rows: " . json_encode($rows));
// Recupera l'ID dell'utente loggato // Recupera l'ID dell'utente loggato
$user_id = $iduserlogin ?? 1; // Default a 1 se non definito $user_id = $iduserlogin ?? 1;
$db = DBHandlerSelect::getInstance(); $db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection(); $pdo = $db->getConnection();
@@ -98,26 +98,26 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
<?php include('cssinclude.php'); ?> <?php include('cssinclude.php'); ?>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2Lw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2Lw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style> <style>
/* Colori pastello per input/select */ .cell-changed {
background-color: #fff3b0 !important;
transition: background-color 0.3s ease;
}
input.auto-input, input.auto-input,
select.auto-input { select.auto-input {
background-color: #d4edda; background-color: #d4edda;
/* Verde pastello */
} }
input.manual-input, input.manual-input,
select.manual-input { select.manual-input {
background-color: #fff3cd; background-color: #fff3cd;
/* Giallino pastello */
} }
input.required-input, input.required-input,
select.required-input { select.required-input {
background-color: #f8d7da; background-color: #f8d7da;
/* Rossino chiaro */
} }
/* Stili base per input/select */
input, input,
select { select {
width: 100%; width: 100%;
@@ -128,14 +128,11 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
font-size: 14px; font-size: 14px;
} }
/* Mantieni leggibilità del testo */
input, input,
select { select {
color: #333; color: #333;
/* Colore scuro per contrasto */
} }
/* Stili per i badge di stato */
.status-badge { .status-badge {
display: inline-block; display: inline-block;
padding: 2px 8px; padding: 2px 8px;
@@ -161,7 +158,6 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
color: white; color: white;
} }
/* Stili esistenti rimangono invariati */
.grid-container { .grid-container {
overflow-x: auto; overflow-x: auto;
max-width: 100%; max-width: 100%;
@@ -254,6 +250,11 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
align-items: center; align-items: center;
} }
.grid-top .save-all-cell {
flex: 0 0 210px;
align-items: flex-start;
}
.propagate-btn { .propagate-btn {
background: none; background: none;
border: none; border: none;
@@ -370,7 +371,6 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5); box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
} }
/* Stile per l'header dei pulsanti combinati */
.grid-cell.button-cell, .grid-cell.button-cell,
.grid-header.button-header { .grid-header.button-header {
min-width: 210px !important; min-width: 210px !important;
@@ -383,9 +383,28 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
border: none; border: none;
border-radius: 5px; border-radius: 5px;
cursor: pointer; cursor: pointer;
width: 50px; width: 35px;
box-sizing: border-box; box-sizing: border-box;
} }
.flash-success {
background-color: #d4edda !important;
transition: background-color 0.3s ease;
}
.save-all-btn {
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
padding: 8px 16px;
cursor: pointer;
font-size: 14px;
}
.save-all-btn:hover {
background-color: #218838;
}
</style> </style>
<title>Edit Imported Data - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title> <title>Edit Imported Data - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
</head> </head>
@@ -408,6 +427,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
<h6 class="mb-0">Modifica Dati Importati</h6> <h6 class="mb-0">Modifica Dati Importati</h6>
<div id="unsavedChanges" style="display:none; color: red; font-weight: bold; margin:10px 0;"> <div id="unsavedChanges" style="display:none; color: red; font-weight: bold; margin:10px 0;">
⚠️ Unsaved changes detected! Please save before leaving this page. ⚠️ Unsaved changes detected! Please save before leaving this page.
<ul id="changedFields" style="margin-top:5px; font-weight:normal; color:darkred;"></ul>
</div> </div>
</div> </div>
</div> </div>
@@ -415,9 +435,10 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
<div class="card-body"> <div class="card-body">
<form id="editForm"> <form id="editForm">
<div class="grid-container"> <div class="grid-container">
<!-- Riga superiore per gli input dei campi manuali -->
<div class="grid-top"> <div class="grid-top">
<div class="grid-cell button-cell" style="flex: 0 0 210px;"></div> <!-- Actions --> <div class="grid-cell save-all-cell">
<button type="button" class="save-all-btn" title="Save All Rows"><i class="fas fa-save"></i> Save All</button>
</div>
<?php if ($mainFieldMapping): ?> <?php if ($mainFieldMapping): ?>
<div class="grid-cell" style="flex: 0 0 150px;"> <div class="grid-cell" style="flex: 0 0 150px;">
<?php <?php
@@ -428,7 +449,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$inputClass = $mainFieldMapping['is_manual'] ? 'manual-input' : 'auto-input'; $inputClass = $mainFieldMapping['is_manual'] ? 'manual-input' : 'auto-input';
if ($mainFieldMapping['is_required']) $inputClass .= ' required-input'; if ($mainFieldMapping['is_required']) $inputClass .= ' required-input';
if ($mainFieldMapping['data_type'] === 'SceltaMultipla') { if ($mainFieldMapping['data_type'] === 'SceltaMultipla') {
echo "<select class='custom-field dropdown-select $inputClass' data-column='main_field' data-field-id='{$mainFieldMapping['field_id']}' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ">"; echo "<select class='custom-field dropdown-select $inputClass' data-column='main_field' data-field-id='{$mainFieldMapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
echo "<button type='button' class='propagate-btn' data-column='main_field'><i class='fas fa-arrow-down'></i></button>"; echo "<button type='button' class='propagate-btn' data-column='main_field'><i class='fas fa-arrow-down'></i></button>";
@@ -445,9 +466,8 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
?> ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
<div class="grid-cell" style="flex: 0 0 150px;"></div> <!-- status --> <div class="grid-cell" style="flex: 0 0 150px;"></div>
<?php <?php
// Campi automatici (is_manual = 0) escluso main_field
$autoIndex = 0; $autoIndex = 0;
foreach ($allMappings as $mapping) { foreach ($allMappings as $mapping) {
if (!$mapping['is_manual'] && $mapping['main_field'] != 1) { if (!$mapping['is_manual'] && $mapping['main_field'] != 1) {
@@ -455,7 +475,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if ($mapping['is_required']) $inputClass .= ' required-input'; if ($mapping['is_required']) $inputClass .= ' required-input';
if ($mapping['data_type'] === 'SceltaMultipla') { if ($mapping['data_type'] === 'SceltaMultipla') {
echo "<div class='grid-cell' style='flex: 0 0 150px;'>"; echo "<div class='grid-cell' style='flex: 0 0 150px;'>";
echo "<select class='custom-field dropdown-select $inputClass' data-column='auto_$autoIndex' data-field-id='{$mapping['field_id']}' " . ($mapping['is_required'] ? 'required' : '') . ">"; echo "<select class='custom-field dropdown-select $inputClass' data-column='auto_$autoIndex' data-field-id='{$mapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
echo "<button type='button' class='propagate-btn' data-column='auto_$autoIndex'><i class='fas fa-arrow-down'></i></button>"; echo "<button type='button' class='propagate-btn' data-column='auto_$autoIndex'><i class='fas fa-arrow-down'></i></button>";
@@ -466,7 +486,6 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$autoIndex++; $autoIndex++;
} }
} }
// Campi manuali (is_manual = 1) escluso main_field
$manualIndex = 0; $manualIndex = 0;
foreach ($allMappings as $mapping) { foreach ($allMappings as $mapping) {
if ($mapping['is_manual'] && $mapping['main_field'] != 1) { if ($mapping['is_manual'] && $mapping['main_field'] != 1) {
@@ -478,7 +497,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if ($mapping['is_required']) $inputClass .= ' required-input'; if ($mapping['is_required']) $inputClass .= ' required-input';
echo "<div class='grid-cell' style='flex: 0 0 150px;'>"; echo "<div class='grid-cell' style='flex: 0 0 150px;'>";
if ($mapping['data_type'] === 'SceltaMultipla') { if ($mapping['data_type'] === 'SceltaMultipla') {
echo "<select class='custom-field dropdown-select $inputClass' data-column='manual_$manualIndex' data-field-id='{$mapping['field_id']}' " . ($mapping['is_required'] ? 'required' : '') . ">"; echo "<select class='custom-field dropdown-select $inputClass' data-column='manual_$manualIndex' data-field-id='{$mapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mainFieldMapping['is_required'] ? 'required' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
} elseif ($mapping['data_type'] === 'DATE') { } elseif ($mapping['data_type'] === 'DATE') {
@@ -493,15 +512,14 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$manualIndex++; $manualIndex++;
} }
} }
echo "<div class='grid-cell' style='flex: 0 0 200px;'></div>"; // AWB echo "<div class='grid-cell' style='flex: 0 0 200px;'></div>";
echo "<div class='grid-cell' style='flex: 0 0 250px;'></div>"; // Tracking Info echo "<div class='grid-cell' style='flex: 0 0 250px;'></div>";
echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>"; // importreferencecode echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>";
echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>"; // filename_import echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>";
echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>"; // importdate echo "<div class='grid-cell' style='flex: 0 0 150px;'></div>";
?> ?>
</div> </div>
<!-- Header della tabella -->
<div class="grid-row"> <div class="grid-row">
<div class="grid-header button-header" style="flex: 0 0 210px;">Actions</div> <div class="grid-header button-header" style="flex: 0 0 210px;">Actions</div>
<?php if ($mainFieldMapping): ?> <?php if ($mainFieldMapping): ?>
@@ -538,10 +556,10 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
?> ?>
</div> </div>
<!-- Righe della tabella -->
<?php foreach ($importedData as $index => $row): ?> <?php foreach ($importedData as $index => $row): ?>
<div class="grid-row" data-id="<?= $row['iddatadb'] ?>"> <div class="grid-row" data-id="<?= $row['iddatadb'] ?>">
<div class="grid-cell button-cell" style="flex: 0 0 210px; position: relative;"> <div class="grid-cell button-cell" style="flex: 0 0 210px; position: relative;">
<button type="button" class="export-lims-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" title="Export to LIMS" style="background: #eb0b0bff; color: white; border: none; border-radius: 5px; cursor: pointer;"><i class="fas fa-upload"></i></button>
<button type="button" class="save-btn action-btn" data-row="<?= $index ?>" title="Save" style="background: #28a745; color: white; border: none; border-radius: 5px; cursor: pointer;"><i class="fas fa-save"></i></button> <button type="button" class="save-btn action-btn" data-row="<?= $index ?>" title="Save" style="background: #28a745; color: white; border: none; border-radius: 5px; cursor: pointer;"><i class="fas fa-save"></i></button>
<button type="button" class="photos-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" title="Photos" style="background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer;"><i class="fas fa-camera"></i></button> <button type="button" class="photos-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" title="Photos" style="background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer;"><i class="fas fa-camera"></i></button>
<button type="button" class="parts-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" title="Parts" style="background: #ffc107; color: white; border: none; border-radius: 5px; cursor: pointer;"><i class="fas fa-puzzle-piece"></i></button> <button type="button" class="parts-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" title="Parts" style="background: #ffc107; color: white; border: none; border-radius: 5px; cursor: pointer;"><i class="fas fa-puzzle-piece"></i></button>
@@ -560,7 +578,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
?> ?>
<div class="grid-cell editable-cell <?= $requiredClass ?>" data-col="main_field" data-row="<?= $index ?>" data-index="1" style="flex: 0 0 150px;"> <div class="grid-cell editable-cell <?= $requiredClass ?>" data-col="main_field" data-row="<?= $index ?>" data-index="1" style="flex: 0 0 150px;">
<?php if ($mainFieldMapping['data_type'] === 'SceltaMultipla'): ?> <?php if ($mainFieldMapping['data_type'] === 'SceltaMultipla'): ?>
<select name="rows[<?= $index ?>][details][<?= $mainFieldMapping['id'] ?>][field_value]" class="cell-input dropdown-select <?= $inputClass ?>" data-mapping-id="<?= $mainFieldMapping['id'] ?>" data-field-id="<?= $mainFieldMapping['field_id'] ?>" <?= $mainFieldMapping['is_required'] ? 'required' : '' ?>> <select name="rows[<?= $index ?>][details][<?= $mainFieldMapping['id'] ?>][field_value]" class="cell-input dropdown-select <?= $inputClass ?>" data-mapping-id="<?= $mainFieldMapping['id'] ?>" data-field-id="<?= $mainFieldMapping['field_id'] ?>" data-selected-value="<?= htmlspecialchars($fieldValue) ?>" <?= $mainFieldMapping['is_required'] ? 'required' : '' ?>>
<option value="">Seleziona...</option> <option value="">Seleziona...</option>
</select> </select>
<?php elseif ($mainFieldMapping['data_type'] === 'DATE'): ?> <?php elseif ($mainFieldMapping['data_type'] === 'DATE'): ?>
@@ -592,7 +610,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if ($mapping['is_required']) $inputClass .= ' required-input'; if ($mapping['is_required']) $inputClass .= ' required-input';
echo "<div class='grid-cell editable-cell $requiredClass' data-col='auto_$autoIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>"; echo "<div class='grid-cell editable-cell $requiredClass' data-col='auto_$autoIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
if ($mapping['data_type'] === 'SceltaMultipla') { if ($mapping['data_type'] === 'SceltaMultipla') {
echo "<select name='rows[$index][details][{$mapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mapping['id']}' data-field-id='{$mapping['field_id']}' " . ($mapping['is_required'] ? 'required' : '') . ">"; echo "<select name='rows[$index][details][{$mapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mapping['id']}' data-field-id='{$mapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
} elseif ($mapping['data_type'] === 'DATE') { } elseif ($mapping['data_type'] === 'DATE') {
@@ -621,7 +639,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if ($mapping['is_required']) $inputClass .= ' required-input'; if ($mapping['is_required']) $inputClass .= ' required-input';
echo "<div class='grid-cell editable-cell $requiredClass' data-col='manual_$manualIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>"; echo "<div class='grid-cell editable-cell $requiredClass' data-col='manual_$manualIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
if ($mapping['data_type'] === 'SceltaMultipla') { if ($mapping['data_type'] === 'SceltaMultipla') {
echo "<select name='rows[$index][details][{$mapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mapping['id']}' data-field-id='{$mapping['field_id']}' " . ($mapping['is_required'] ? 'required' : '') . ">"; echo "<select name='rows[$index][details][{$mapping['id']}][field_value]' class='cell-input dropdown-select $inputClass' data-mapping-id='{$mapping['id']}' data-field-id='{$mapping['field_id']}' data-selected-value='" . htmlspecialchars($fieldValue) . "' " . ($mapping['is_required'] ? 'required' : '') . ">";
echo "<option value=''>Seleziona...</option>"; echo "<option value=''>Seleziona...</option>";
echo "</select>"; echo "</select>";
} elseif ($mapping['data_type'] === 'DATE') { } elseif ($mapping['data_type'] === 'DATE') {
@@ -686,101 +704,95 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
</div> </div>
<?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://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
<script src="photos.js"></script> <script src="photos.js"></script>
<script src="parts.js"></script> <script src="parts.js"></script>
<script src="tracking.js"></script> <script src="tracking.js"></script>
<script> <script>
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
console.log("Page loaded, initializing event listeners");
const inputs = document.querySelectorAll(".cell-input, .dropdown-select, .carrier-select, .awb-input"); const inputs = document.querySelectorAll(".cell-input, .dropdown-select, .carrier-select, .awb-input");
const unsavedDiv = document.getElementById("unsavedChanges"); const unsavedDiv = document.getElementById("unsavedChanges");
const changedList = document.getElementById("changedFields");
let hasChanges = false; let hasChanges = false;
let changedFields = {};
function renderChangedList() {
console.log("Rendering changed fields list:", changedFields);
changedList.innerHTML = "";
Object.keys(changedFields).forEach(rowIndex => {
const fields = changedFields[rowIndex];
if (fields.length > 0) {
const li = document.createElement("li");
li.textContent = `Row ${parseInt(rowIndex) + 1}: ${fields.join(", ")}`;
changedList.appendChild(li);
}
});
unsavedDiv.style.display = Object.keys(changedFields).length > 0 ? "block" : "none";
}
inputs.forEach(el => { inputs.forEach(el => {
el.addEventListener("change", () => { el.addEventListener("change", () => {
console.log("Input changed:", el.name);
hasChanges = true; hasChanges = true;
unsavedDiv.style.display = "block"; const gridCell = el.closest(".grid-cell");
const colIndex = gridCell?.dataset.index;
const rowIndex = gridCell?.dataset.row;
let label = "Unknown field";
if (colIndex) {
const header = document.querySelector(`.grid-header[data-index="${colIndex}"]`);
if (header) {
label = header.textContent.replace(":", "").trim();
}
}
if (rowIndex !== undefined) {
if (!changedFields[rowIndex]) {
changedFields[rowIndex] = [];
}
if (!changedFields[rowIndex].includes(label)) {
changedFields[rowIndex].push(label);
}
gridCell.classList.add("cell-changed");
}
renderChangedList();
}); });
}); });
document.querySelectorAll(".save-btn").forEach(btn => { document.querySelectorAll(".save-btn").forEach(btn => {
btn.addEventListener("click", () => { btn.addEventListener("click", () => {
hasChanges = false; const rowIndex = btn.dataset.row;
unsavedDiv.style.display = "none"; console.log(`Saving row ${rowIndex}`);
}); const row = btn.closest('.grid-row');
});
window.addEventListener("beforeunload", function(e) {
if (hasChanges) {
e.preventDefault();
e.returnValue = "";
}
});
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const inputs = document.querySelectorAll('.cell-input');
inputs.forEach(input => {
input.addEventListener('focus', function() {
this.closest('.grid-cell').classList.add('expanded');
});
input.addEventListener('blur', function() {
this.closest('.grid-cell').classList.remove('expanded');
});
});
const saveButtons = document.querySelectorAll('.save-btn');
saveButtons.forEach(button => {
btn.addEventListener('click', function() {
hasChanges = false;
unsavedDiv.style.display = "none";
});
});
window.addEventListener("beforeunload", function(e) {
if (hasChanges) {
e.preventDefault();
e.returnValue = "";
}
});
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const inputs = document.querySelectorAll('.cell-input');
inputs.forEach(input => {
input.addEventListener('focus', function() {
this.closest('.grid-cell').classList.add('expanded');
});
input.addEventListener('blur', function() {
this.closest('.grid-cell').classList.remove('expanded');
});
});
const saveButtons = document.querySelectorAll('.save-btn');
saveButtons.forEach(button => {
button.addEventListener('click', function() {
const rowIndex = this.getAttribute('data-row');
const row = this.closest('.grid-row');
const iddatadb = row.getAttribute('data-id'); const iddatadb = row.getAttribute('data-id');
const formData = new FormData(); const formData = new FormData();
const inputs = row.querySelectorAll(`input[name^="rows[${rowIndex}]"], select[name^="rows[${rowIndex}]"]`); const inputs = row.querySelectorAll(`input[name^="rows[${rowIndex}][details]"], select[name^="rows[${rowIndex}][details]"]`);
inputs.forEach(input => { inputs.forEach(input => {
const name = input.name.replace(`rows[${rowIndex}]`, '').replace(/\[|\]/g, ''); const matches = input.name.match(/rows\[\d+\]\[details\]\[(\d+)\]\[field_value\]/);
formData.append(name, input.value); if (matches) {
const mappingId = matches[1];
formData.append(`details${mappingId}field_value`, input.value);
if (input.tagName === 'SELECT' && input.classList.contains('dropdown-select')) {
input.setAttribute('data-selected-value', input.value);
}
}
}); });
formData.append('iddatadb', iddatadb); formData.append('iddatadb', iddatadb);
formData.append('mapping', JSON.stringify(<?= json_encode($allMappings) ?>));
fetch('save_edited_row.php', { fetch('save_edited_row.php', {
method: 'POST', method: 'POST',
body: formData body: formData
}) })
.then(response => response.json()) .then(response => {
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.json();
})
.then(data => { .then(data => {
console.log("Save response:", data);
if (data.success) { if (data.success) {
const cells = row.querySelectorAll('.grid-cell'); const cells = row.querySelectorAll('.grid-cell');
cells.forEach(cell => { cells.forEach(cell => {
@@ -789,18 +801,130 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
cell.classList.add('flash-success'); cell.classList.add('flash-success');
}); });
setTimeout(() => cells.forEach(cell => cell.classList.remove('flash-success')), 500); setTimeout(() => cells.forEach(cell => cell.classList.remove('flash-success')), 500);
alert('Salvataggio avvenuto con successo!');
if (changedFields[rowIndex]) {
delete changedFields[rowIndex];
document.querySelectorAll(`.grid-cell[data-row="${rowIndex}"]`)
.forEach(cell => cell.classList.remove("cell-changed"));
renderChangedList();
hasChanges = Object.keys(changedFields).length > 0;
}
alert('Salvataggio riga avvenuto con successo!');
} else { } else {
alert('Errore durante il salvataggio: ' + data.message); alert('Errore durante il salvataggio: ' + data.message);
} }
}) })
.catch(error => alert('Errore durante il salvataggio: ' + error.message)); .catch(error => {
console.error("Save error:", error);
alert('Errore durante il salvataggio: ' + error.message);
});
});
});
document.querySelector('.save-all-btn').addEventListener('click', async () => {
console.log("Saving all rows");
const rows = document.querySelectorAll('.grid-row');
let successCount = 0;
let errorMessages = [];
for (const row of rows) {
const saveBtn = row.querySelector('.save-btn');
if (!saveBtn) {
console.warn(`No save button found in row with data-id: ${row.getAttribute('data-id')}`);
continue;
}
const rowIndex = saveBtn.dataset.row;
const iddatadb = row.getAttribute('data-id');
if (!rowIndex || !iddatadb) {
console.warn(`Missing rowIndex or iddatadb in row:`, row);
continue;
}
console.log(`Processing row ${rowIndex} with iddatadb ${iddatadb}`);
const formData = new FormData();
const inputs = row.querySelectorAll(`input[name^="rows[${rowIndex}][details]"], select[name^="rows[${rowIndex}][details]"]`);
inputs.forEach(input => {
const matches = input.name.match(/rows\[\d+\]\[details\]\[(\d+)\]\[field_value\]/);
if (matches) {
const mappingId = matches[1];
formData.append(`details${mappingId}field_value`, input.value);
if (input.tagName === 'SELECT' && input.classList.contains('dropdown-select')) {
input.setAttribute('data-selected-value', input.value);
}
}
});
formData.append('iddatadb', iddatadb);
try {
const response = await fetch('save_edited_row.php', {
method: 'POST',
body: formData
});
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json();
console.log(`Row ${rowIndex} save response:`, data);
if (data.success) {
successCount++;
const cells = row.querySelectorAll('.grid-cell');
cells.forEach(cell => {
cell.classList.remove('flash-success');
void cell.offsetWidth;
cell.classList.add('flash-success');
});
setTimeout(() => cells.forEach(cell => cell.classList.remove('flash-success')), 500);
if (changedFields[rowIndex]) {
delete changedFields[rowIndex];
document.querySelectorAll(`.grid-cell[data-row="${rowIndex}"]`)
.forEach(cell => cell.classList.remove("cell-changed"));
}
} else {
errorMessages.push(`Riga ${parseInt(rowIndex) + 1}: ${data.message}`);
}
} catch (error) {
console.error(`Row ${rowIndex} save error:`, error);
errorMessages.push(`Riga ${parseInt(rowIndex) + 1}: ${error.message}`);
}
}
renderChangedList();
hasChanges = Object.keys(changedFields).length > 0;
console.log(`Save all completed: ${successCount} successes, ${errorMessages.length} errors`);
if (errorMessages.length === 0) {
alert(`Tutte le ${successCount} righe salvate con successo!`);
} else {
alert(`Salvate ${successCount} righe con successo.\nErrori:\n${errorMessages.join('\n')}`);
}
});
window.addEventListener("beforeunload", function(e) {
if (hasChanges) {
e.preventDefault();
e.returnValue = "";
}
});
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
console.log("Initializing cell expansion and propagation");
const inputs = document.querySelectorAll('.cell-input');
inputs.forEach(input => {
input.addEventListener('focus', function() {
this.closest('.grid-cell').classList.add('expanded');
});
input.addEventListener('blur', function() {
this.closest('.grid-cell').classList.remove('expanded');
}); });
}); });
const propagateButtons = document.querySelectorAll('.propagate-btn'); const propagateButtons = document.querySelectorAll('.propagate-btn');
propagateButtons.forEach(button => { propagateButtons.forEach(button => {
button.addEventListener('click', function() { button.addEventListener('click', function() {
console.log("Propagating value for column:", this.getAttribute('data-column'));
const column = this.getAttribute('data-column'); const column = this.getAttribute('data-column');
const input = this.previousElementSibling; const input = this.previousElementSibling;
const value = input.value; const value = input.value;
@@ -817,9 +941,12 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
if (cells.length > targetTopIndex) { if (cells.length > targetTopIndex) {
const targetInput = cells[targetTopIndex].querySelector('input, select'); const targetInput = cells[targetTopIndex].querySelector('input, select');
if (targetInput) { if (targetInput) {
if (targetInput.type === 'date') targetInput.value = value; targetInput.value = value;
else if (targetInput.tagName === 'SELECT') targetInput.value = value; if (targetInput.tagName === 'SELECT') {
else targetInput.value = value; targetInput.setAttribute('data-selected-value', value);
const event = new Event('change');
targetInput.dispatchEvent(event);
}
} }
} }
}); });
@@ -834,6 +961,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
let columnIndex = 0; let columnIndex = 0;
resizers.forEach(resizer => { resizers.forEach(resizer => {
resizer.addEventListener('mousedown', function(e) { resizer.addEventListener('mousedown', function(e) {
console.log("Starting column resize");
currentResizer = resizer; currentResizer = resizer;
const header = resizer.parentElement; const header = resizer.parentElement;
columnIndex = header.getAttribute('data-index'); columnIndex = header.getAttribute('data-index');
@@ -856,6 +984,7 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
function stopResize() { function stopResize() {
if (currentResizer) { if (currentResizer) {
console.log("Stopping column resize");
document.removeEventListener('mousemove', resize); document.removeEventListener('mousemove', resize);
document.removeEventListener('mouseup', stopResize); document.removeEventListener('mouseup', stopResize);
currentResizer = null; currentResizer = null;
@@ -866,11 +995,15 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
</script> </script>
<script> <script>
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
console.log("Initializing dropdown population");
const dropdownData = {}; const dropdownData = {};
async function populateDropdowns() { async function populateDropdowns() {
const dropdowns = document.querySelectorAll('.dropdown-select'); const dropdowns = document.querySelectorAll('.dropdown-select');
if (dropdowns.length === 0) return; if (dropdowns.length === 0) {
console.log("No dropdowns found");
return;
}
const uniqueFieldIds = [ const uniqueFieldIds = [
...new Set(Array.from(dropdowns).map(d => d.getAttribute('data-field-id'))) ...new Set(Array.from(dropdowns).map(d => d.getAttribute('data-field-id')))
@@ -879,28 +1012,34 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
const missingFieldIds = uniqueFieldIds.filter(fieldId => !dropdownData[fieldId]); const missingFieldIds = uniqueFieldIds.filter(fieldId => !dropdownData[fieldId]);
if (missingFieldIds.length > 0) { if (missingFieldIds.length > 0) {
console.log("Fetching dropdown data for field IDs:", missingFieldIds);
try { try {
const response = await fetch( const response = await fetch(
`get_customfield_values.php?field_ids=${missingFieldIds.join(",")}` `get_customfield_values.php?field_ids=${missingFieldIds.join(",")}`
); );
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json(); const data = await response.json();
if (data.error) { if (data.error) {
console.error("Errore fetch multiplo:", data.error); console.error("Fetch error:", data.error);
} else { } else {
for (const fieldId of Object.keys(data)) { for (const fieldId of Object.keys(data)) {
dropdownData[fieldId] = data[fieldId] || []; dropdownData[fieldId] = data[fieldId] || [];
} }
} }
} catch (error) { } catch (error) {
console.error("Errore generale nel fetch multiplo:", error); console.error("Fetch error:", error);
} }
} }
dropdowns.forEach(dropdown => { dropdowns.forEach(dropdown => {
const fieldId = dropdown.getAttribute('data-field-id'); const fieldId = dropdown.getAttribute('data-field-id');
const selectedValue = dropdown.getAttribute('data-selected-value') || '';
const currentValue = dropdown.value;
if (!fieldId || !dropdownData[fieldId]) { if (!fieldId || !dropdownData[fieldId]) {
dropdown.innerHTML = '<option value="">Errore nel caricamento</option>'; dropdown.innerHTML = '<option value="">Errore nel caricamento</option>';
console.warn(`No data for fieldId ${fieldId}`);
return; return;
} }
@@ -909,50 +1048,22 @@ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
const option = document.createElement('option'); const option = document.createElement('option');
option.value = value.IdCustomFieldsValue; option.value = value.IdCustomFieldsValue;
option.textContent = value.Valore; option.textContent = value.Valore;
if (dropdown.value === option.value) option.selected = true; if (currentValue && currentValue === String(value.IdCustomFieldsValue)) {
option.selected = true;
} else if (!currentValue && selectedValue === String(value.IdCustomFieldsValue)) {
option.selected = true;
}
dropdown.appendChild(option); dropdown.appendChild(option);
}); });
if ((currentValue || selectedValue) && dropdown.value !== (currentValue || selectedValue)) {
dropdown.value = '';
console.warn(`Value ${currentValue || selectedValue} not found for fieldId ${fieldId}`);
}
}); });
} }
populateDropdowns(); populateDropdowns();
document.querySelectorAll('.save-btn').forEach(btn => {
btn.addEventListener('click', function() {
setTimeout(populateDropdowns, 100);
});
});
const propagateButtons = document.querySelectorAll('.propagate-btn');
propagateButtons.forEach(button => {
button.addEventListener('click', function() {
const column = this.getAttribute('data-column');
const input = this.previousElementSibling;
const value = input.value;
const gridTopCells = document.querySelector('.grid-top').querySelectorAll('.grid-cell');
const targetTopIndex = Array.from(gridTopCells).findIndex(cell =>
cell.querySelector('.propagate-btn[data-column="' + column + '"]')
);
if (targetTopIndex !== -1) {
const rows = document.querySelectorAll('.grid-row');
rows.forEach(row => {
const cells = row.querySelectorAll('.grid-cell');
if (cells.length > targetTopIndex) {
const targetInput = cells[targetTopIndex].querySelector('select.dropdown-select, input');
if (targetInput) {
targetInput.value = value;
if (targetInput.tagName === 'SELECT') {
const event = new Event('change');
targetInput.dispatchEvent(event);
}
}
}
});
}
});
});
}); });
</script> </script>
</body> </body>
+1 -1
View File
@@ -1,7 +1,7 @@
<!-- Bootstrap JS --> <!-- Bootstrap JS -->
<script src="assets/js/bootstrap.bundle.min.js"></script> <script src="assets/js/bootstrap.bundle.min.js"></script>
<!--plugins--> <!--plugins-->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/plugins/simplebar/js/simplebar.min.js"></script> <script src="assets/plugins/simplebar/js/simplebar.min.js"></script>
<script src="assets/plugins/metismenu/js/metisMenu.min.js"></script> <script src="assets/plugins/metismenu/js/metisMenu.min.js"></script>
<script src="assets/plugins/perfect-scrollbar/js/perfect-scrollbar.js"></script> <script src="assets/plugins/perfect-scrollbar/js/perfect-scrollbar.js"></script>
+2 -2
View File
@@ -14,9 +14,9 @@ if (!$iddatadb) {
} }
try { try {
$stmt = $pdo->prepare("SELECT id, iddatadb, part_number, part_description FROM identification_parts WHERE iddatadb = :iddatadb ORDER BY part_number ASC"); $stmt = $pdo->prepare("SELECT id, iddatadb, part_number, part_description, idmatrice FROM identification_parts WHERE iddatadb = :iddatadb ORDER BY part_number ASC");
$stmt->execute([':iddatadb' => $iddatadb]); $stmt->execute([':iddatadb' => $iddatadb]);
$parts = $stmt->fetchAll(); $parts = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'parts' => $parts]); echo json_encode(['success' => true, 'parts' => $parts]);
} catch (PDOException $e) { } catch (PDOException $e) {
@@ -21,7 +21,7 @@ $schemajson = $template['schemajson'] ? json_decode($template['schemajson'], tru
$isSchemajsonEmpty = empty(trim($template['schemajson'])); $isSchemajsonEmpty = empty(trim($template['schemajson']));
// Recupera i campi dalla tabella template_mapping // Recupera i campi dalla tabella template_mapping
$stmt = $pdo->prepare("SELECT id, field_id, excel_column, is_manual, manual_default, data_type, is_required, default_value, has_list, length, decimals, min_value, max_value, default_curr_date, tablename, field_label, main_field FROM template_mapping WHERE template_id = ?"); $stmt = $pdo->prepare("SELECT id, field_id, excel_column, is_manual, manual_default, data_type, is_required, default_value, has_list, length, decimals, min_value, max_value, default_curr_date, tablename, field_label, main_field, is_visible_import FROM template_mapping WHERE template_id = ?");
$stmt->execute([$id]); $stmt->execute([$id]);
$mappings = $stmt->fetchAll(PDO::FETCH_ASSOC); $mappings = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -83,8 +83,10 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
} }
#schemaFieldsTable th:first-child, #schemaFieldsTable th:first-child,
#schemaFieldsTable td:first-child { #schemaFieldsTable td:first-child,
width: 50px; #schemaFieldsTable th:nth-child(2),
#schemaFieldsTable td:nth-child(2) {
width: 100px;
text-align: center; text-align: center;
} }
</style> </style>
@@ -137,8 +139,8 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
<thead> <thead>
<tr> <tr>
<th>Main</th> <th>Main</th>
<th>Visible on Import</th>
<th>Title</th> <th>Title</th>
<th>ID</th>
<th>Type</th> <th>Type</th>
<th>Mapping</th> <th>Mapping</th>
<th>Default Value</th> <th>Default Value</th>
@@ -150,8 +152,15 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
<td> <td>
<input type="checkbox" class="main-field-checkbox" data-mapping-id="<?php echo $mapping['id']; ?>" <?php echo $mapping['main_field'] == 1 ? 'checked' : ''; ?>> <input type="checkbox" class="main-field-checkbox" data-mapping-id="<?php echo $mapping['id']; ?>" <?php echo $mapping['main_field'] == 1 ? 'checked' : ''; ?>>
</td> </td>
<td><?php echo htmlspecialchars($mapping['field_label'] ?? 'N/A'); ?></td> <td>
<td><?php echo htmlspecialchars($mapping['field_id'] ?? 'N/A'); ?></td> <input type="checkbox" class="visible-import-checkbox" data-mapping-id="<?php echo $mapping['id']; ?>" <?php echo (isset($mapping['is_visible_import']) ? $mapping['is_visible_import'] : 1) == 1 ? 'checked' : ''; ?>>
</td>
<td>
<?php echo htmlspecialchars($mapping['field_label'] ?? 'N/A'); ?>
<?php if ($mapping['is_required'] == 1): ?>
<span class="badge bg-danger ms-2">Required</span>
<?php endif; ?>
</td>
<td><?php echo htmlspecialchars($mapping['data_type'] ?? 'N/A'); ?></td> <td><?php echo htmlspecialchars($mapping['data_type'] ?? 'N/A'); ?></td>
<td> <td>
<?php <?php
@@ -428,7 +437,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
async function updateSchemaDetails() { async function updateSchemaDetails() {
if (!schemaId) { if (!schemaId) {
document.getElementById('schemaFieldsBody').innerHTML = '<tr><td colspan="6" class="text-warning">No schema associated.</td></tr>'; // Aggiornato colspan a 6 document.getElementById('schemaFieldsBody').innerHTML = '<tr><td colspan="6" class="text-warning">No schema associated.</td></tr>';
return; return;
} }
@@ -445,7 +454,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
await saveSchemaJson(templateId, JSON.stringify(data)); await saveSchemaJson(templateId, JSON.stringify(data));
alert('Schema updated successfully. Refresh the page to see changes.'); alert('Schema updated successfully. Refresh the page to see changes.');
} catch (error) { } catch (error) {
document.getElementById('schemaFieldsBody').innerHTML = '<tr><td colspan="6" class="text-danger">Error: ' + error.message + '</td></tr>'; // Aggiornato colspan a 6 document.getElementById('schemaFieldsBody').innerHTML = '<tr><td colspan="6" class="text-danger">Error: ' + error.message + '</td></tr>';
} finally { } finally {
updateSchemaButton.disabled = false; updateSchemaButton.disabled = false;
updateSchemaButton.textContent = 'Update Schema Details'; updateSchemaButton.textContent = 'Update Schema Details';
@@ -524,16 +533,11 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
.then(data => { .then(data => {
if (!data.success) { if (!data.success) {
console.error("❌ Error updating main_field:", data.message); console.error("❌ Error updating main_field:", data.message);
// Revert checkbox state on error
checkbox.checked = !checkbox.checked; checkbox.checked = !checkbox.checked;
// Riselezione visiva degli altri se errore
if (value === 1) {
document.querySelectorAll('.main-field-checkbox').forEach(cb => { document.querySelectorAll('.main-field-checkbox').forEach(cb => {
cb.checked = cb.dataset.originalChecked === 'true'; cb.checked = cb.dataset.originalChecked === 'true';
}); });
}
} else { } else {
// Aggiorna lo stato originale dopo successo
document.querySelectorAll('.main-field-checkbox').forEach(cb => { document.querySelectorAll('.main-field-checkbox').forEach(cb => {
cb.dataset.originalChecked = cb.checked; cb.dataset.originalChecked = cb.checked;
}); });
@@ -542,12 +546,36 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
.catch(error => { .catch(error => {
console.error("❌ Fetch error:", error); console.error("❌ Fetch error:", error);
checkbox.checked = !checkbox.checked; checkbox.checked = !checkbox.checked;
// Riselezione visiva degli altri se errore
if (value === 1) {
document.querySelectorAll('.main-field-checkbox').forEach(cb => { document.querySelectorAll('.main-field-checkbox').forEach(cb => {
cb.checked = cb.dataset.originalChecked === 'true'; cb.checked = cb.dataset.originalChecked === 'true';
}); });
});
} else if (event.target.classList.contains('visible-import-checkbox')) {
const checkbox = event.target;
const mappingId = checkbox.dataset.mappingId;
const value = checkbox.checked ? 1 : 0;
fetch('update_visible_import.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
template_id: <?php echo $id; ?>,
mapping_id: mappingId,
value: value
})
})
.then(response => response.json())
.then(data => {
if (!data.success) {
console.error("❌ Error updating is_visible_import:", data.message);
checkbox.checked = !checkbox.checked;
} }
})
.catch(error => {
console.error("❌ Fetch error:", error);
checkbox.checked = !checkbox.checked;
}); });
} }
}); });
@@ -569,7 +597,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
mappedColumn = document.createElement('span'); mappedColumn = document.createElement('span');
mappedColumn.className = 'mapped-column'; mappedColumn.className = 'mapped-column';
mappedColumn.style.marginLeft = '5px'; mappedColumn.style.marginLeft = '5px';
tr.querySelector('td:nth-child(5)').appendChild(mappedColumn); // Aggiornato a nth-child(5) per la nuova colonna tr.querySelector('td:nth-child(5)').appendChild(mappedColumn);
} }
if (!removeBtn) { if (!removeBtn) {
removeBtn = document.createElement('button'); removeBtn = document.createElement('button');
@@ -577,7 +605,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
removeBtn.textContent = 'X'; removeBtn.textContent = 'X';
removeBtn.style.marginLeft = '5px'; removeBtn.style.marginLeft = '5px';
removeBtn.setAttribute('data-id', mappingId); removeBtn.setAttribute('data-id', mappingId);
tr.querySelector('td:nth-child(5)').appendChild(removeBtn); // Aggiornato a nth-child(5) tr.querySelector('td:nth-child(5)').appendChild(removeBtn);
removeBtn.addEventListener('click', function(e) { removeBtn.addEventListener('click', function(e) {
let tr = e.target.closest('tr'); let tr = e.target.closest('tr');
+93 -12
View File
@@ -1,4 +1,4 @@
<!-- Modal --> <!-- Modal modificato con pulsante per riconoscimento vocale -->
<div class="modal fade" id="partsModal" tabindex="-1" aria-labelledby="partsModalLabel" aria-hidden="true"> <div class="modal fade" id="partsModal" tabindex="-1" aria-labelledby="partsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl" style="max-width: 80% !important; width: 80% !important;"> <div class="modal-dialog modal-xl" style="max-width: 80% !important; width: 80% !important;">
<div class="modal-content"> <div class="modal-content">
@@ -9,7 +9,17 @@
<div class="modal-body"> <div class="modal-body">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<h6>Elenco Parti</h6> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; min-width: 0;">
<h6 style="margin: 0; white-space: nowrap;">Elenco Parti</h6>
<div style="display: flex; align-items: center; min-width: 0;">
<select id="global-matrice" class="ms-2" style="width: 250px !important; min-width: 250px !important;">
</select>
<input type="checkbox" id="showMixParts" name="showMixParts" style="margin-right: 5px; margin-left: 10px;">
<label for="showMixParts" style="font-size: 0.9rem; margin-right: 10px;">Mix</label>
<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>
</div>
</div>
<ul id="partsList" class="list-group"></ul> <ul id="partsList" class="list-group"></ul>
<table class="table table-striped table-sm mt-3" id="partsTable"> <table class="table table-striped table-sm mt-3" id="partsTable">
<thead> <thead>
@@ -50,7 +60,8 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-primary btn-sm" id="addDescriptionsBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Aggiungi Lista Descrizioni</button> <button type="button" class="btn btn-primary btn-sm" id="addDescriptionsBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Aggiungi Lista Descrizioni</button>
<button type="button" class="btn btn-danger btn-sm" id="removeAnnotationsBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Rimuovi Annotazioni</button> <button type="button" class="btn btn-danger btn-sm" id="removeAnnotationsBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Rimuovi Descrizioni</button>
<button type="button" class="btn btn-warning btn-sm" id="undoMarkerBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Undo Marker</button>
<button type="button" class="btn btn-success btn-sm" id="savePhotoBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Salva Foto con Nome</button> <button type="button" class="btn btn-success btn-sm" id="savePhotoBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Salva Foto con Nome</button>
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Chiudi</button> <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">Chiudi</button>
</div> </div>
@@ -99,12 +110,21 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 5px 10px;
} }
#partsList .list-group-item:hover { #partsList .list-group-item:hover {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
#partsList input[type="color"] {
width: 30px;
height: 24px;
padding: 0;
margin-left: 5px;
cursor: pointer;
}
.draggable-description { .draggable-description {
position: absolute; position: absolute;
background: rgba(255, 255, 255, 0.8); background: rgba(255, 255, 255, 0.8);
@@ -121,8 +141,6 @@
position: absolute; position: absolute;
width: 24px; width: 24px;
height: 24px; height: 24px;
background: rgba(255, 0, 0, 0.5);
border: 1px solid #ff0000;
border-radius: 50%; border-radius: 50%;
color: #ffffff; color: #ffffff;
text-align: center; text-align: center;
@@ -146,23 +164,86 @@
font-size: 0.8rem; font-size: 0.8rem;
} }
/* ნორმალური Save ღილაკი */ /* Normale Save button */
#savePhotoBtn { #savePhotoBtn {
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
/* დაუმახსოვრებელი ცვლილებები */ /* Unsaved changes */
#savePhotoBtn.unsaved { #savePhotoBtn.unsaved {
background-color: #dc3545 !important; /* წითელი */ background-color: #dc3545 !important;
border-color: #dc3545 !important; border-color: #dc3545 !important;
color: white !important; color: white !important;
animation: pulse 1.2s infinite; animation: pulse 1.2s infinite;
} }
/* ლამაზი პულსაცია */ /* Animazione pulsante */
@keyframes pulse { @keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7); } 0% {
70% { box-shadow: 0 0 10px 15px rgba(220, 53, 69, 0); } box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7);
100% { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0); } }
70% {
box-shadow: 0 0 10px 15px rgba(220, 53, 69, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(220, 53, 69, 0);
}
}
/* Stili per Select2 in #partsList e #global-matrice */
#partsList .select2-container,
.select2-container--default #global-matrice {
width: 250px !important;
min-width: 250px !important;
margin-left: 10px;
}
#partsList .select2-selection--single,
.select2-container--default #global-matrice .select2-selection--single {
height: 26px !important;
padding: 0.2rem 0.5rem !important;
font-size: 0.9rem !important;
border: 1px solid #ced4da !important;
background-color: #fff !important;
}
#partsList .select2-selection__rendered,
.select2-container--default #global-matrice .select2-selection__rendered {
line-height: 24px !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
}
#partsList .select2-selection__arrow,
.select2-container--default #global-matrice .select2-selection__arrow {
height: 26px !important;
}
#partsList .save-status,
#partsList .save-loading {
margin-left: 5px;
}
.select2-container--open .select2-dropdown {
z-index: 1051 !important;
border: 1px solid #aaa !important;
border-radius: 4px !important;
background: white !important;
overflow-y: auto !important;
max-height: 200px !important;
}
.select2-container--default .select2-search--dropdown .select2-search__field {
width: 100% !important;
padding: 0.2rem !important;
}
.select2-container--default .part-matrice,
.select2-container--default #global-matrice {
width: 250px !important;
min-width: 250px !important;
} }
</style> </style>
+725 -120
View File
File diff suppressed because it is too large Load Diff
+771 -95
View File
File diff suppressed because it is too large Load Diff
+124 -1
View File
@@ -1,6 +1,12 @@
<?php <?php
// photos_popup.php // photos_popup.php
include('include/headscript.php'); include('include/headscript.php');
// Includi Fabric.js solo per questa pagina
?>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
<?php
// Includi l'autoloader di Composer // Includi l'autoloader di Composer
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
@@ -15,7 +21,6 @@ use Endroid\QrCode\Writer\PngWriter;
try { try {
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../../'); $dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../../');
$dotenv->load(); $dotenv->load();
error_log("File .env caricato correttamente da " . __DIR__ . '/../../.env');
} catch (Exception $e) { } catch (Exception $e) {
error_log("Errore nel caricamento del file .env: " . $e->getMessage()); error_log("Errore nel caricamento del file .env: " . $e->getMessage());
echo json_encode(['error' => 'Errore nel caricamento del file di configurazione']); echo json_encode(['error' => 'Errore nel caricamento del file di configurazione']);
@@ -118,6 +123,9 @@ $result->saveToFile($qrCodeFile);
<!-- Area per la webcam --> <!-- Area per la webcam -->
<div id="webcamArea" style="display: none; text-align: center; margin-bottom: 20px;"> <div id="webcamArea" style="display: none; text-align: center; margin-bottom: 20px;">
<p>Webcam Preview</p> <p>Webcam Preview</p>
<select id="webcamSelect" style="margin-bottom: 10px; padding: 5px;">
<option value="">Select a webcam</option>
</select>
<video id="webcamVideo" autoplay playsinline style="max-width: 100%; max-height: 300px;"></video> <video id="webcamVideo" autoplay playsinline style="max-width: 100%; max-height: 300px;"></video>
<div style="margin-top: 10px;"> <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="captureBtn" style="padding: 10px 20px; background: #28a745; color: white; border: none; cursor: pointer;">Capture Photo</button>
@@ -153,6 +161,8 @@ $result->saveToFile($qrCodeFile);
</button> </button>
</div> </div>
<?php endforeach; ?> <?php endforeach; ?>
<!-- Bottone Crea Collage -->
<button id="createCollageBtn" style="padding: 10px 20px; background: #ffc107; color: white; border: none; cursor: pointer; margin-top: 20px;">Crea Collage</button>
<?php endif; ?> <?php endif; ?>
</div> </div>
@@ -161,6 +171,52 @@ $result->saveToFile($qrCodeFile);
<span class="image-modal-close">&times;</span> <span class="image-modal-close">&times;</span>
<img id="enlargedImage" class="image-modal-content" src="" alt="Immagine ingrandita"> <img id="enlargedImage" class="image-modal-content" src="" alt="Immagine ingrandita">
</div> </div>
<!-- Modale per collage -->
<div id="collageModal" class="modal" style="display: none; position: fixed; z-index: 1002; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.8);">
<div class="modal-content" style="background: white; margin: 5% auto; padding: 20px; width: 80%; max-width: 1200px; position: relative;">
<span class="close-collage" style="position: absolute; top: 10px; right: 20px; font-size: 30px; font-weight: bold; color: #333; cursor: pointer; z-index: 1003; background: #fff; padding: 5px 10px; border-radius: 50%;">&times;</span>
<h3>Crea Collage</h3>
<!-- Lista foto selezionabili -->
<div id="collagePhotoList" style="max-height: 200px; overflow-y: auto; margin-bottom: 20px;">
<?php foreach ($photos as $photo): ?>
<div style="display: inline-block; margin: 10px;">
<input type="checkbox" class="photo-checkbox" data-path="../photostrf/<?= htmlspecialchars($photo['file_path']) ?>">
<img src="../photostrf/<?= htmlspecialchars($photo['file_path']) ?>" alt="" style="width: 80px; height: 80px;">
</div>
<?php endforeach; ?>
</div>
<!-- Bottone per aggiungere selezionate al canvas -->
<button id="addToCanvasBtn">Aggiungi Selezionate al Canvas</button>
<!-- Canvas per editing -->
<canvas id="collageCanvas" width="800" height="600" style="border: 1px solid #ccc; margin-top: 20px;"></canvas>
<!-- Pannello dei livelli -->
<div id="layersPanel" style="width: 120px; max-height: 600px; overflow-y: auto; background: #f8f9fa; padding: 10px; position: absolute; right: 0; top: 60px;">
<h4 style="margin: 0 0 10px 0; font-size: 16px;">Livelli</h4>
<ul id="layersList" style="list-style: none; padding: 0;"></ul>
</div>
<!-- Bottoni azioni -->
<div style="margin-top: 20px; display: flex; flex-wrap: wrap; gap: 5px;">
<button id="saveCollageBtn" title="Salva il collage"><i class="fas fa-save"></i></button>
<button id="bringToFrontBtn" title="Porta in primo piano"><i class="fas fa-arrow-up"></i></button>
<button id="sendToBackBtn" title="Manda in fondo"><i class="fas fa-arrow-down"></i></button>
<button id="bringForwardBtn" title="Sposta avanti di un livello"><i class="fas fa-arrow-circle-up"></i></button>
<button id="sendBackwardBtn" title="Sposta indietro di un livello"><i class="fas fa-arrow-circle-down"></i></button>
<button id="cropImageBtn" title="Ritaglia immagine selezionata" disabled><i class="fas fa-crop"></i></button>
<button id="applyCropBtn" title="Applica ritaglio" disabled><i class="fas fa-crop"></i> Applica</button>
<button id="cancelCropBtn" title="Annulla ritaglio" disabled><i class="fas fa-crop"></i> Annulla</button>
<button id="removeBackgroundBtn" title="Rimuovi sfondo immagine selezionata" disabled><i class="fas fa-eraser"></i> Rimuovi Sfondo</button>
<button id="removeImageBtn" title="Rimuovi immagine selezionata" disabled><i class="fas fa-trash-alt"></i> Rimuovi</button>
<button id="undoBtn" title="Annulla ultima azione" disabled><i class="fas fa-undo"></i></button>
<p id="backgroundRemovalInstruction" style="display: none; color: #007bff;">Clicca sull'immagine per selezionare il colore dello sfondo da rimuovere</p>
</div>
</div>
</div>
</div> </div>
<style> <style>
@@ -240,4 +296,71 @@ $result->saveToFile($qrCodeFile);
font-size: 16px; font-size: 16px;
color: white; color: white;
} }
/* Stile per i pulsanti del modale collage */
#collageModal button {
padding: 8px 12px;
margin: 5px;
border: none;
cursor: pointer;
border-radius: 4px;
display: flex;
align-items: center;
gap: 5px;
font-size: 14px;
}
#saveCollageBtn {
background: #28a745;
color: white;
}
#bringToFrontBtn,
#sendToBackBtn,
#bringForwardBtn,
#sendBackwardBtn {
background: #007bff;
color: white;
padding: 8px;
}
#cropImageBtn,
#applyCropBtn,
#cancelCropBtn,
#removeBackgroundBtn,
#removeImageBtn,
#undoBtn {
background: #ffc107;
color: white;
}
#collageModal button:disabled {
background: #ccc;
cursor: not-allowed;
}
#collageModal button i {
font-size: 16px;
}
/* Stile per il pannello dei livelli */
#layersPanel {
z-index: 1002;
}
#layersPanel li {
margin-bottom: 5px;
}
#layersPanel img {
width: 50px;
height: 50px;
border: 2px solid #ccc;
cursor: pointer;
object-fit: cover;
}
#layersPanel img:hover {
border-color: #007bff;
}
</style> </style>
+381
View File
@@ -0,0 +1,381 @@
<?php
// Abilita errori per debug
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/quotations_debug.log');
if (!file_exists(__DIR__ . '/quotations_debug.log')) {
file_put_contents(__DIR__ . '/quotations_debug.log', "Inizio operazioni alle " . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
}
// Log iniziale
error_log("Inizio operazioni alle " . date('Y-m-d H:i:s'));
include('include/headscript.php');
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Recupera l'ID dell'utente loggato
$user_id = $iduserlogin ?? 1;
// Gestione creazione nuova quotation (crea record vuoto su conferma)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'create') {
$description = '';
$customer = '';
$stmt = $pdo->prepare("INSERT INTO quotations (description, customer, iduser) VALUES (?, ?, ?)");
$stmt->execute([$description, $customer, $user_id]);
$newId = $pdo->lastInsertId();
// Log creazione
error_log("Creata nuova quotation ID: $newId");
// Reindirizza alla modifica della nuova quotation
header("Location: quotations.php?edit_id=" . $newId . "&status=success&message=" . urlencode("Quotation creata con successo"));
exit;
}
// Gestione modifica quotation
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update' && isset($_POST['id'])) {
$id = intval($_POST['id']);
$description = $_POST['description'] ?? '';
$customer = $_POST['customer'] ?? '';
$stmt = $pdo->prepare("UPDATE quotations SET description = ?, customer = ? WHERE id = ? AND iduser = ?");
$stmt->execute([$description, $customer, $id, $user_id]);
// Log modifica
error_log("Modificata quotation ID: $id");
// Reindirizza alla lista delle quotations
header("Location: quotations.php?status=success&message=" . urlencode("Quotation modificata con successo"));
exit;
}
// Gestione cancellazione quotation
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'delete' && isset($_POST['id'])) {
$id = intval($_POST['id']);
$stmt = $pdo->prepare("DELETE FROM quotations WHERE id = ? AND iduser = ?");
$stmt->execute([$id, $user_id]);
// Log cancellazione
error_log("Cancellata quotation ID: $id");
header("Location: quotations.php?status=success&message=" . urlencode("Quotation cancellata con successo"));
exit;
}
// Recupera tutte le quotations per l'utente
$stmt = $pdo->prepare("SELECT * FROM quotations WHERE iduser = ? ORDER BY creation_date DESC");
$stmt->execute([$user_id]);
$quotations = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Verifica se è richiesta la modifica di una quotation
$editQuotation = null;
if (isset($_GET['edit_id'])) {
$editId = intval($_GET['edit_id']);
$stmt = $pdo->prepare("SELECT * FROM quotations WHERE id = ? AND iduser = ?");
$stmt->execute([$editId, $user_id]);
$editQuotation = $stmt->fetch(PDO::FETCH_ASSOC);
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
<?php include('cssinclude.php'); ?>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2Lw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
<style>
/* Stili simili alla pagina fornita, adattati */
.cell-changed {
background-color: #fff3b0 !important;
transition: background-color 0.3s ease;
}
input.manual-input,
select.manual-input {
background-color: #fff3cd;
}
input.required-input,
select.required-input {
background-color: #f8d7da;
}
input,
select,
textarea {
width: 100%;
box-sizing: border-box;
border: 1px solid #ced4da;
border-radius: 4px;
padding: 5px;
font-size: 14px;
}
.action-btn {
padding: 6px 8px;
margin-right: 5px;
border: none;
border-radius: 5px;
cursor: pointer;
width: 35px;
box-sizing: border-box;
}
.save-btn {
background-color: #28a745;
color: white;
}
.delete-btn {
background-color: #dc3545;
color: white;
}
.photos-btn {
background-color: #007bff;
color: white;
}
.parts-btn {
background-color: #ffc107;
color: white;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group textarea {
height: 100px;
resize: vertical;
}
.flash-success {
background-color: #d4edda !important;
transition: background-color 0.3s ease;
}
.quotation-actions {
margin-top: 20px;
}
</style>
<title>Gestione Quotations - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
</head>
<body>
<div class="wrapper">
<?php include('include/navbar.php'); ?>
<?php include('include/topbar.php'); ?>
<div class="page-wrapper">
<div class="page-content">
<div class="card radius-10">
<div class="card-header">
<div class="d-flex align-items-center">
<div>
<h6 class="mb-0">Gestione Quotations</h6>
</div>
</div>
</div>
<div class="card-body">
<?php if ($editQuotation): ?>
<!-- Modifica Quotation -->
<h6 class="mb-3">Modifica Quotation ID: <?= $editQuotation['id'] ?></h6>
<form id="editForm" method="post">
<input type="hidden" name="action" value="update">
<input type="hidden" name="id" value="<?= $editQuotation['id'] ?>">
<div class="form-group">
<label for="description">Descrizione</label>
<textarea id="description" name="description" class="manual-input required-input" required><?= htmlspecialchars($editQuotation['description']) ?></textarea>
</div>
<div class="form-group">
<label for="customer">Cliente</label>
<input type="text" id="customer" name="customer" class="manual-input required-input" value="<?= htmlspecialchars($editQuotation['customer']) ?>" required>
</div>
<button type="submit" class="btn btn-primary">Salva Modifiche</button>
<a href="quotations.php" class="btn btn-secondary">Torna alla Lista</a>
</form>
<div class="quotation-actions">
<h6 class="mb-3">Azioni</h6>
<button type="button" class="photos-btn action-btn" data-idquotations="<?= $editQuotation['id'] ?>" title="Photos"><i class="fas fa-camera"></i></button>
<button type="button" class="parts-btn action-btn" data-idquotations="<?= $editQuotation['id'] ?>" title="Parts"><i class="fas fa-puzzle-piece"></i></button>
</div>
<?php else: ?>
<!-- Lista Quotations -->
<div class="mb-3">
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#createModal">Crea Nuova Quotation</button>
</div>
<h6 class="mb-3">Quotations Esistenti</h6>
<table id="quotationsTable" class="table table-striped table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Data Creazione</th>
<th>Descrizione</th>
<th>Cliente</th>
<th>Azioni</th>
</tr>
</thead>
<tbody>
<?php foreach ($quotations as $row): ?>
<tr data-id="<?= $row['id'] ?>">
<td><?= htmlspecialchars($row['id']) ?></td>
<td><?= htmlspecialchars($row['creation_date']) ?></td>
<td>
<textarea name="description" class="cell-input manual-input form-control"><?= htmlspecialchars($row['description']) ?></textarea>
</td>
<td>
<input type="text" name="customer" class="cell-input manual-input form-control" value="<?= htmlspecialchars($row['customer']) ?>">
</td>
<td>
<button type="button" class="save-btn action-btn edit-btn" data-id="<?= $row['id'] ?>" title="Salva Modifiche"><i class="fas fa-save"></i></button>
<button type="button" class="delete-btn action-btn" data-id="<?= $row['id'] ?>" title="Cancella" data-bs-toggle="modal" data-bs-target="#deleteModal"><i class="fas fa-trash"></i></button>
<button type="button" class="photos-btn action-btn" data-idquotations="<?= $row['id'] ?>" title="Photos"><i class="fas fa-camera"></i></button>
<button type="button" class="parts-btn action-btn" data-idquotations="<?= $row['id'] ?>" title="Parts"><i class="fas fa-puzzle-piece"></i></button>
<a href="quotations.php?edit_id=<?= $row['id'] ?>" class="btn btn-secondary action-btn" title="Modifica Dettagliata"><i class="fas fa-edit"></i></a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div>
</div>
<!-- Modal per conferma creazione nuova quotation -->
<div class="modal fade" id="createModal" tabindex="-1" aria-labelledby="createModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="createModalLabel">Conferma Creazione Nuova Quotation</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Vuoi creare una nuova quotation?</p>
<form id="createModalForm" method="post">
<input type="hidden" name="action" value="create">
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
<button type="button" class="btn btn-primary" id="confirmCreate">Conferma</button>
</div>
</div>
</div>
</div>
<!-- Modal per conferma cancellazione -->
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteModalLabel">Conferma Cancellazione</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Sicuro di voler cancellare questa quotation?</p>
<form id="deleteForm" method="post">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" id="deleteQuotationId">
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
<button type="button" class="btn btn-danger" id="confirmDelete">Conferma</button>
</div>
</div>
</div>
</div>
<div class="overlay toggle-icon"></div>
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
<?php include('include/footer.php'); ?>
</div>
<?php include('modal_parts.php'); ?>
<?php include('photos_functions.php'); ?>
<?php include('jsinclude.php'); ?>
<script src="https://code.jquery.com/jquery-3.6.0.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="parts.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
// Inizializza DataTables se non siamo in modalità modifica
if (!document.querySelector('#editForm')) {
$('#quotationsTable').DataTable({
"paging": true,
"searching": true,
"ordering": true,
"info": true,
"autoWidth": false,
"responsive": true
});
}
// Gestione conferma creazione nel modal
document.getElementById('confirmCreate').addEventListener('click', function() {
document.getElementById('createModalForm').submit();
});
// Gestione modifica inline e save nella lista
document.querySelectorAll('.edit-btn').forEach(btn => {
btn.addEventListener('click', function() {
const row = this.closest('tr');
const id = row.dataset.id;
const description = row.querySelector('textarea[name="description"]').value;
const customer = row.querySelector('input[name="customer"]').value;
const formData = new FormData();
formData.append('action', 'update');
formData.append('id', id);
formData.append('description', description);
formData.append('customer', customer);
fetch('quotations.php', {
method: 'POST',
body: formData
}).then(response => {
if (response.ok) {
row.classList.add('flash-success');
setTimeout(() => row.classList.remove('flash-success'), 500);
alert('Quotation modificata con successo!');
} else {
alert('Errore durante la modifica.');
}
});
});
});
// Gestione apertura modal di cancellazione
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', function() {
const id = this.dataset.id;
document.getElementById('deleteQuotationId').value = id;
});
});
// Gestione conferma cancellazione nel modal
document.getElementById('confirmDelete').addEventListener('click', function() {
document.getElementById('deleteForm').submit();
});
// I bottoni photos e parts usano gli script esistenti (photos.js, parts.js), passando data-idquotations
});
</script>
</body>
</html>
+63
View File
@@ -0,0 +1,63 @@
<?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;
$parts = $data['parts'] ?? [];
if (!$iddatadb || empty($parts)) {
echo json_encode(['success' => false, 'message' => 'Dati mancanti']);
exit;
}
try {
$pdo->beginTransaction();
// Elimina tutte le parti esistenti per l'iddatadb per evitare conflitti di unicità
$stmt = $pdo->prepare("DELETE FROM identification_parts WHERE iddatadb = :iddatadb");
$stmt->execute([':iddatadb' => $iddatadb]);
// Prepara l'inserimento delle nuove parti
$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())
");
$part_ids = [];
foreach ($parts as $part) {
$partNumber = $part['part_number'] ?? null;
$partDescription = $part['part_description'] ?? '';
$mix = $part['mix'] ?? 'N';
if (!$partNumber || !$partDescription) {
throw new PDOException("Numero parte o descrizione mancante per parte: " . json_encode($part));
}
$stmt->execute([
':iddatadb' => $iddatadb,
':part_number' => $partNumber,
':part_description' => $partDescription,
':mix' => $mix
]);
$part_ids[] = $pdo->lastInsertId();
}
$pdo->commit();
echo json_encode([
'success' => true,
'part_ids' => $part_ids,
'message' => 'Parti rinumerate con successo'
]);
} catch (PDOException $e) {
$pdo->rollBack();
echo json_encode([
'success' => false,
'message' => 'Errore nel salvataggio: ' . $e->getMessage()
]);
}
+44
View File
@@ -0,0 +1,44 @@
<?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;
$parts = $data['parts'] ?? [];
if (!$iddatadb || empty($parts)) {
echo json_encode(['success' => false, 'message' => 'Dati mancanti']);
exit;
}
$part = $parts[0];
$partId = $part['id'] ?? null;
$idmatrice = $part['idmatrice'] ?? null;
if (!$partId) {
echo json_encode(['success' => false, 'message' => 'ID della parte mancante']);
exit;
}
try {
$stmt = $pdo->prepare("UPDATE identification_parts
SET idmatrice = :idmatrice, updated_at = NOW()
WHERE id = :id AND iddatadb = :iddatadb");
$stmt->execute([
':idmatrice' => $idmatrice,
':id' => $partId,
':iddatadb' => $iddatadb
]);
if ($stmt->rowCount() > 0) {
echo json_encode(['success' => true, 'message' => 'Matrice salvata con successo']);
} else {
echo json_encode(['success' => false, 'message' => 'Nessuna riga aggiornata. Verifica l\'ID della parte.']);
}
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => 'Errore nel salvataggio della matrice: ' . $e->getMessage()]);
}
+26
View File
@@ -0,0 +1,26 @@
<?php
require_once 'include/headscript.php';
header('Content-Type: application/json');
$data = json_decode(file_get_contents('php://input'), true);
$template_id = $data['template_id'] ?? null;
$mapping_id = $data['mapping_id'] ?? null;
$value = $data['value'] ?? null;
if (!$template_id || !$mapping_id || !isset($value)) {
echo json_encode(['success' => false, 'message' => 'Invalid input']);
exit;
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
$stmt = $pdo->prepare("UPDATE template_mapping SET is_visible_import = ? WHERE id = ? AND template_id = ?");
$result = $stmt->execute([$value, $mapping_id, $template_id]);
if ($result) {
echo json_encode(['success' => true]);
} else {
echo json_encode(['success' => false, 'message' => 'Failed to update is_visible_import']);
}