fixed tested components
This commit is contained in:
parent
9fe9243e60
commit
78154e43a9
52
public/userarea/add_part_quick.php
Normal file
52
public/userarea/add_part_quick.php
Normal 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;
|
||||
@ -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';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user