fixed tested components

This commit is contained in:
Claudio 2026-02-05 10:32:28 +01:00
parent 9fe9243e60
commit 78154e43a9
2 changed files with 154 additions and 26 deletions

View File

@ -0,0 +1,52 @@
<?php
header('Content-Type: application/json');
ini_set('display_errors', 1);
error_reporting(E_ALL);
require_once(__DIR__ . '/include/headscript.php'); // così hai Auth + $iduserlogin + DBHandlerSelect
try {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
throw new Exception('Invalid request method');
}
$iddatadb = isset($_POST['iddatadb']) ? (int)$_POST['iddatadb'] : 0;
$part_description = isset($_POST['part_description']) ? trim($_POST['part_description']) : '';
if ($iddatadb <= 0) {
throw new Exception('Missing iddatadb');
}
if ($part_description === '') {
throw new Exception('Part description is empty');
}
// (opzionale ma consigliato) limita lunghezza come da DB varchar(255)
if (mb_strlen($part_description) > 255) {
$part_description = mb_substr($part_description, 0, 255);
}
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
// Insert minimal
$stmt = $pdo->prepare("
INSERT INTO identification_parts (iddatadb, part_number, part_description)
VALUES (?, 1, ?)
");
$ok = $stmt->execute([$iddatadb, $part_description]);
if (!$ok) {
throw new Exception('Insert failed');
}
echo json_encode([
'success' => true,
'message' => 'Part added',
'id' => $pdo->lastInsertId()
]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
exit;

View File

@ -278,8 +278,8 @@ function fixedDefaultValue(array $f): string
}
/* Sticky columns - first column (Actions) */
.grid-top .grid-cell.save-all-cell,
.grid-header.button-header,
.grid-top .grid-cell.save-all-cell,
.grid-header.button-header,
.grid-cell.button-cell {
position: sticky !important;
left: 0;
@ -301,7 +301,7 @@ function fixedDefaultValue(array $f): string
background-color: #e9ecef;
}
.grid-top .grid-cell:nth-child(2),
.grid-top .grid-cell:nth-child(2),
.grid-row .grid-header:nth-child(2),
.grid-row .grid-cell:nth-child(2) {
position: sticky !important;
@ -323,7 +323,7 @@ function fixedDefaultValue(array $f): string
.grid-row:hover .grid-cell:nth-child(2) {
background-color: #e9ecef;
}
.grid-row {
position: relative;
}
@ -336,7 +336,7 @@ function fixedDefaultValue(array $f): string
background-color: #e0f7fa !important;
flex: 0 0 500px !important;
}
.grid-header.expanded {
background-color: #e0f7fa !important;
}
@ -748,8 +748,8 @@ function fixedDefaultValue(array $f): string
$topColIndex++;
}
}
echo "<div class='grid-cell grid-top-cell' style='flex: 0 0 150px;' data-index='$topColIndex'></div>";
echo "<div class='grid-cell grid-top-cell' style='flex: 0 0 150px;' data-index='$topColIndex'></div>";
$topColIndex++;
echo "<div class='grid-cell grid-top-cell' style='flex: 0 0 200px;' data-index='$topColIndex'></div>";
$topColIndex++;
@ -1125,9 +1125,9 @@ function fixedDefaultValue(array $f): string
function expandColumn(cell, expand) {
const columnIndex = cell.getAttribute('data-index');
if (!columnIndex) return;
const allColumnCells = document.querySelectorAll(`.grid-cell[data-index="${columnIndex}"], .grid-header[data-index="${columnIndex}"], .grid-top-cell[data-index="${columnIndex}"]`);
allColumnCells.forEach(colCell => {
if (expand) {
colCell.classList.add('expanded');
@ -1511,8 +1511,8 @@ function fixedDefaultValue(array $f): string
// Gestione degli input
inputs.forEach(input => {
if (input.tagName === 'SELECT' ||
input.classList.contains('date-picker') ||
if (input.tagName === 'SELECT' ||
input.classList.contains('date-picker') ||
input.type === 'number' ||
input.type === 'date') {
input.addEventListener('focus', function() {
@ -1532,7 +1532,7 @@ function fixedDefaultValue(array $f): string
expandColumn(cell, true);
cell.dataset.convertingToTextarea = 'true';
const textarea = document.createElement('textarea');
textarea.value = this.value;
@ -1546,9 +1546,9 @@ function fixedDefaultValue(array $f): string
textarea.setAttribute('data-current-value', this.getAttribute('data-current-value') || '');
textarea.setAttribute('data-fixed-key', this.getAttribute('data-fixed-key') || '');
textarea.dataset.originalInput = 'true';
this.parentNode.replaceChild(textarea, this);
setTimeout(() => {
textarea.focus();
delete cell.dataset.convertingToTextarea;
@ -1566,7 +1566,7 @@ function fixedDefaultValue(array $f): string
const element = e.target;
if (element.tagName === 'TEXTAREA' && element.dataset.originalInput === 'true') {
const cell = element.closest('.grid-cell');
const input = document.createElement('input');
input.type = 'text';
input.value = element.value;
@ -1578,16 +1578,16 @@ function fixedDefaultValue(array $f): string
input.setAttribute('data-selected-value', element.getAttribute('data-selected-value') || '');
input.setAttribute('data-current-value', element.getAttribute('data-current-value') || '');
input.setAttribute('data-fixed-key', element.getAttribute('data-fixed-key') || '');
element.parentNode.replaceChild(input, element);
expandColumn(cell, false);
input.addEventListener('focus', function() {
const cell = this.closest('.grid-cell');
expandColumn(cell, true);
cell.dataset.convertingToTextarea = 'true';
const textarea = document.createElement('textarea');
textarea.value = this.value;
textarea.name = this.name;
@ -1600,15 +1600,17 @@ function fixedDefaultValue(array $f): string
textarea.setAttribute('data-current-value', this.getAttribute('data-current-value') || '');
textarea.setAttribute('data-fixed-key', this.getAttribute('data-fixed-key') || '');
textarea.dataset.originalInput = 'true';
this.parentNode.replaceChild(textarea, this);
setTimeout(() => {
textarea.focus();
delete cell.dataset.convertingToTextarea;
}, 0);
});
const changeEvent = new Event('change', { bubbles: true });
const changeEvent = new Event('change', {
bubbles: true
});
input.dispatchEvent(changeEvent);
} else if (element.tagName === 'INPUT' && element.type === 'text') {
const cell = element.closest('.grid-cell');
@ -1952,6 +1954,80 @@ function fixedDefaultValue(array $f): string
});
});
// Quick add part from "Tested Component" (+ button)
$(document).on('click', '.add-part-btn', async function() {
const rowIndex = $(this).data('row');
const $row = $(this).closest('.grid-row');
const iddatadb = $row.data('id');
// Input inside the same cell
const $cell = $(this).closest('.grid-cell');
const $input = $cell.find('input[name^="rows["][name$="[tested_component]"]');
const partDescription = ($input.val() || '').trim();
if (!iddatadb) {
alert('❌ iddatadb not found on row');
return;
}
if (!partDescription) {
alert('⚠️ Inserisci prima una descrizione nel campo Tested Component.');
$input.focus();
return;
}
try {
const formData = new FormData();
formData.append('iddatadb', iddatadb);
formData.append('part_description', partDescription);
const resp = await fetch('add_part_quick.php', {
method: 'POST',
body: formData
});
const data = await resp.json();
if (!resp.ok || !data.success) {
throw new Error(data.message || ('HTTP ' + resp.status));
}
// ✅ Do NOT clear tested_component: keep it as a warning/notice
$input.addClass('cell-changed');
setTimeout(() => $input.removeClass('cell-changed'), 1200);
// opzionale: se vuoi comunque “registrare” il cambiamento nel tracker unsaved
$input.trigger('change');
showQuickPartModal('✅ Parte aggiunta con successo!');
} catch (err) {
alert('❌ Errore aggiunta parte: ' + err.message);
console.error(err);
}
});
function showQuickPartModal(message) {
const modalEl = document.getElementById('quickPartModal');
if (!modalEl) {
alert(message); // fallback se il modal non esiste
return;
}
document.getElementById('quickPartModalMessage').textContent = message;
let modal = bootstrap.Modal.getInstance(modalEl);
if (!modal) modal = new bootstrap.Modal(modalEl, {
backdrop: true,
keyboard: true
});
modal.show();
}
$(document).on('click', '.parts-btn', function() {
const iddatadb = $(this).data('iddatadb') || null;
const idquotations = $(this).data('idquotations') || null;
@ -2256,7 +2332,7 @@ function fixedDefaultValue(array $f): string
});
}
});
// Fix for sticky columns
const gridContainer = document.querySelector('.grid-container');
if (gridContainer) {
@ -2266,16 +2342,16 @@ function fixedDefaultValue(array $f): string
row.style.minWidth = 'max-content';
}
});
const gridTop = document.querySelector('.grid-top');
if (gridTop && !gridTop.style.minWidth) {
gridTop.style.minWidth = 'max-content';
}
const stickyTopCells = document.querySelectorAll('.grid-top .grid-cell.save-all-cell, .grid-top .grid-cell:nth-child(2)');
stickyTopCells.forEach(cell => {
if (!cell.style.minWidth && !cell.style.flex) {
const computedStyle = window.getComputedStyle(cell);
if (computedStyle.flex === '0 0 auto' || !computedStyle.flex.includes('0 0')) {
cell.style.minWidth = cell.offsetWidth + 'px';