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) */
|
/* Sticky columns - first column (Actions) */
|
||||||
.grid-top .grid-cell.save-all-cell,
|
.grid-top .grid-cell.save-all-cell,
|
||||||
.grid-header.button-header,
|
.grid-header.button-header,
|
||||||
.grid-cell.button-cell {
|
.grid-cell.button-cell {
|
||||||
position: sticky !important;
|
position: sticky !important;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -301,7 +301,7 @@ function fixedDefaultValue(array $f): string
|
|||||||
background-color: #e9ecef;
|
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-header:nth-child(2),
|
||||||
.grid-row .grid-cell:nth-child(2) {
|
.grid-row .grid-cell:nth-child(2) {
|
||||||
position: sticky !important;
|
position: sticky !important;
|
||||||
@ -323,7 +323,7 @@ function fixedDefaultValue(array $f): string
|
|||||||
.grid-row:hover .grid-cell:nth-child(2) {
|
.grid-row:hover .grid-cell:nth-child(2) {
|
||||||
background-color: #e9ecef;
|
background-color: #e9ecef;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-row {
|
.grid-row {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -336,7 +336,7 @@ function fixedDefaultValue(array $f): string
|
|||||||
background-color: #e0f7fa !important;
|
background-color: #e0f7fa !important;
|
||||||
flex: 0 0 500px !important;
|
flex: 0 0 500px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-header.expanded {
|
.grid-header.expanded {
|
||||||
background-color: #e0f7fa !important;
|
background-color: #e0f7fa !important;
|
||||||
}
|
}
|
||||||
@ -748,8 +748,8 @@ function fixedDefaultValue(array $f): string
|
|||||||
$topColIndex++;
|
$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++;
|
$topColIndex++;
|
||||||
echo "<div class='grid-cell grid-top-cell' style='flex: 0 0 200px;' data-index='$topColIndex'></div>";
|
echo "<div class='grid-cell grid-top-cell' style='flex: 0 0 200px;' data-index='$topColIndex'></div>";
|
||||||
$topColIndex++;
|
$topColIndex++;
|
||||||
@ -1125,9 +1125,9 @@ function fixedDefaultValue(array $f): string
|
|||||||
function expandColumn(cell, expand) {
|
function expandColumn(cell, expand) {
|
||||||
const columnIndex = cell.getAttribute('data-index');
|
const columnIndex = cell.getAttribute('data-index');
|
||||||
if (!columnIndex) return;
|
if (!columnIndex) return;
|
||||||
|
|
||||||
const allColumnCells = document.querySelectorAll(`.grid-cell[data-index="${columnIndex}"], .grid-header[data-index="${columnIndex}"], .grid-top-cell[data-index="${columnIndex}"]`);
|
const allColumnCells = document.querySelectorAll(`.grid-cell[data-index="${columnIndex}"], .grid-header[data-index="${columnIndex}"], .grid-top-cell[data-index="${columnIndex}"]`);
|
||||||
|
|
||||||
allColumnCells.forEach(colCell => {
|
allColumnCells.forEach(colCell => {
|
||||||
if (expand) {
|
if (expand) {
|
||||||
colCell.classList.add('expanded');
|
colCell.classList.add('expanded');
|
||||||
@ -1511,8 +1511,8 @@ function fixedDefaultValue(array $f): string
|
|||||||
|
|
||||||
// Gestione degli input
|
// Gestione degli input
|
||||||
inputs.forEach(input => {
|
inputs.forEach(input => {
|
||||||
if (input.tagName === 'SELECT' ||
|
if (input.tagName === 'SELECT' ||
|
||||||
input.classList.contains('date-picker') ||
|
input.classList.contains('date-picker') ||
|
||||||
input.type === 'number' ||
|
input.type === 'number' ||
|
||||||
input.type === 'date') {
|
input.type === 'date') {
|
||||||
input.addEventListener('focus', function() {
|
input.addEventListener('focus', function() {
|
||||||
@ -1532,7 +1532,7 @@ function fixedDefaultValue(array $f): string
|
|||||||
|
|
||||||
expandColumn(cell, true);
|
expandColumn(cell, true);
|
||||||
cell.dataset.convertingToTextarea = 'true';
|
cell.dataset.convertingToTextarea = 'true';
|
||||||
|
|
||||||
const textarea = document.createElement('textarea');
|
const textarea = document.createElement('textarea');
|
||||||
|
|
||||||
textarea.value = this.value;
|
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-current-value', this.getAttribute('data-current-value') || '');
|
||||||
textarea.setAttribute('data-fixed-key', this.getAttribute('data-fixed-key') || '');
|
textarea.setAttribute('data-fixed-key', this.getAttribute('data-fixed-key') || '');
|
||||||
textarea.dataset.originalInput = 'true';
|
textarea.dataset.originalInput = 'true';
|
||||||
|
|
||||||
this.parentNode.replaceChild(textarea, this);
|
this.parentNode.replaceChild(textarea, this);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
textarea.focus();
|
textarea.focus();
|
||||||
delete cell.dataset.convertingToTextarea;
|
delete cell.dataset.convertingToTextarea;
|
||||||
@ -1566,7 +1566,7 @@ function fixedDefaultValue(array $f): string
|
|||||||
const element = e.target;
|
const element = e.target;
|
||||||
if (element.tagName === 'TEXTAREA' && element.dataset.originalInput === 'true') {
|
if (element.tagName === 'TEXTAREA' && element.dataset.originalInput === 'true') {
|
||||||
const cell = element.closest('.grid-cell');
|
const cell = element.closest('.grid-cell');
|
||||||
|
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.type = 'text';
|
input.type = 'text';
|
||||||
input.value = element.value;
|
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-selected-value', element.getAttribute('data-selected-value') || '');
|
||||||
input.setAttribute('data-current-value', element.getAttribute('data-current-value') || '');
|
input.setAttribute('data-current-value', element.getAttribute('data-current-value') || '');
|
||||||
input.setAttribute('data-fixed-key', element.getAttribute('data-fixed-key') || '');
|
input.setAttribute('data-fixed-key', element.getAttribute('data-fixed-key') || '');
|
||||||
|
|
||||||
element.parentNode.replaceChild(input, element);
|
element.parentNode.replaceChild(input, element);
|
||||||
|
|
||||||
expandColumn(cell, false);
|
expandColumn(cell, false);
|
||||||
|
|
||||||
input.addEventListener('focus', function() {
|
input.addEventListener('focus', function() {
|
||||||
const cell = this.closest('.grid-cell');
|
const cell = this.closest('.grid-cell');
|
||||||
expandColumn(cell, true);
|
expandColumn(cell, true);
|
||||||
cell.dataset.convertingToTextarea = 'true';
|
cell.dataset.convertingToTextarea = 'true';
|
||||||
|
|
||||||
const textarea = document.createElement('textarea');
|
const textarea = document.createElement('textarea');
|
||||||
textarea.value = this.value;
|
textarea.value = this.value;
|
||||||
textarea.name = this.name;
|
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-current-value', this.getAttribute('data-current-value') || '');
|
||||||
textarea.setAttribute('data-fixed-key', this.getAttribute('data-fixed-key') || '');
|
textarea.setAttribute('data-fixed-key', this.getAttribute('data-fixed-key') || '');
|
||||||
textarea.dataset.originalInput = 'true';
|
textarea.dataset.originalInput = 'true';
|
||||||
|
|
||||||
this.parentNode.replaceChild(textarea, this);
|
this.parentNode.replaceChild(textarea, this);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
textarea.focus();
|
textarea.focus();
|
||||||
delete cell.dataset.convertingToTextarea;
|
delete cell.dataset.convertingToTextarea;
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
const changeEvent = new Event('change', { bubbles: true });
|
const changeEvent = new Event('change', {
|
||||||
|
bubbles: true
|
||||||
|
});
|
||||||
input.dispatchEvent(changeEvent);
|
input.dispatchEvent(changeEvent);
|
||||||
} else if (element.tagName === 'INPUT' && element.type === 'text') {
|
} else if (element.tagName === 'INPUT' && element.type === 'text') {
|
||||||
const cell = element.closest('.grid-cell');
|
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() {
|
$(document).on('click', '.parts-btn', function() {
|
||||||
const iddatadb = $(this).data('iddatadb') || null;
|
const iddatadb = $(this).data('iddatadb') || null;
|
||||||
const idquotations = $(this).data('idquotations') || null;
|
const idquotations = $(this).data('idquotations') || null;
|
||||||
@ -2256,7 +2332,7 @@ function fixedDefaultValue(array $f): string
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fix for sticky columns
|
// Fix for sticky columns
|
||||||
const gridContainer = document.querySelector('.grid-container');
|
const gridContainer = document.querySelector('.grid-container');
|
||||||
if (gridContainer) {
|
if (gridContainer) {
|
||||||
@ -2266,16 +2342,16 @@ function fixedDefaultValue(array $f): string
|
|||||||
row.style.minWidth = 'max-content';
|
row.style.minWidth = 'max-content';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const gridTop = document.querySelector('.grid-top');
|
const gridTop = document.querySelector('.grid-top');
|
||||||
if (gridTop && !gridTop.style.minWidth) {
|
if (gridTop && !gridTop.style.minWidth) {
|
||||||
gridTop.style.minWidth = 'max-content';
|
gridTop.style.minWidth = 'max-content';
|
||||||
}
|
}
|
||||||
|
|
||||||
const stickyTopCells = document.querySelectorAll('.grid-top .grid-cell.save-all-cell, .grid-top .grid-cell:nth-child(2)');
|
const stickyTopCells = document.querySelectorAll('.grid-top .grid-cell.save-all-cell, .grid-top .grid-cell:nth-child(2)');
|
||||||
stickyTopCells.forEach(cell => {
|
stickyTopCells.forEach(cell => {
|
||||||
if (!cell.style.minWidth && !cell.style.flex) {
|
if (!cell.style.minWidth && !cell.style.flex) {
|
||||||
|
|
||||||
const computedStyle = window.getComputedStyle(cell);
|
const computedStyle = window.getComputedStyle(cell);
|
||||||
if (computedStyle.flex === '0 0 auto' || !computedStyle.flex.includes('0 0')) {
|
if (computedStyle.flex === '0 0 auto' || !computedStyle.flex.includes('0 0')) {
|
||||||
cell.style.minWidth = cell.offsetWidth + 'px';
|
cell.style.minWidth = cell.offsetWidth + 'px';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user