tolims filter, pagination
This commit is contained in:
parent
3e66d67dc5
commit
c573a46318
@ -5,6 +5,7 @@ header('Content-Type: application/json');
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$templateId = intval($input['template_id'] ?? 0);
|
||||
$importRefFromClient = trim($input['importreferencecode'] ?? '');
|
||||
|
||||
if (!$templateId) {
|
||||
throw new Exception('Template ID missing');
|
||||
@ -21,8 +22,8 @@ try {
|
||||
$template = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$idclient = $template['idclient'] ?? null;
|
||||
|
||||
// Generate import reference code
|
||||
$importReferenceCode = date('YmdHis') . '-' . uniqid();
|
||||
// Use provided importreferencecode (from filtered page) or generate new
|
||||
$importReferenceCode = $importRefFromClient !== '' ? $importRefFromClient : date('YmdHis') . '-' . uniqid();
|
||||
|
||||
// Insert empty record
|
||||
$stmt = $pdo->prepare("
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
const data = window.gridData || [];
|
||||
const meta = window.gridMeta || {};
|
||||
const columns = meta.columns || [];
|
||||
const totalRows = data.length;
|
||||
let totalRows = data.length;
|
||||
|
||||
// ── DOM refs ────────────────────────────────────────────────────────────
|
||||
let rowContainer = null;
|
||||
@ -463,6 +463,10 @@
|
||||
function renderVisibleRows() {
|
||||
if (!rowContainer) return;
|
||||
|
||||
// Refresh totalRows in case data was modified externally
|
||||
totalRows = data.length;
|
||||
if (revealedCount < totalRows) revealedCount = totalRows;
|
||||
|
||||
// Destroy Select2 on existing rows
|
||||
$(rowContainer).find('.select2-hidden-accessible').select2('destroy');
|
||||
|
||||
|
||||
@ -147,28 +147,6 @@ foreach ($selected_rows as $rowIndex) {
|
||||
|
||||
$_SESSION['inserted_ids'] = $insertedIds;
|
||||
|
||||
$params = [
|
||||
'template_id' => $template_id,
|
||||
'filename' => $newFilename,
|
||||
];
|
||||
|
||||
?>
|
||||
<form id="redirectForm" action="import_edit2.php" method="post">
|
||||
<input type="hidden" name="template_id" value="<?= htmlspecialchars($template_id) ?>">
|
||||
<input type="hidden" name="filename" value="<?= htmlspecialchars($newFilename) ?>">
|
||||
<?php foreach ($selected_rows as $row): ?>
|
||||
<input type="hidden" name="selected_rows[]" value="<?= htmlspecialchars($row) ?>">
|
||||
<?php endforeach; ?>
|
||||
<?php foreach ($insertedIds as $id): ?>
|
||||
<input type="hidden" name="inserted_ids[]" value="<?= htmlspecialchars($id) ?>">
|
||||
<?php endforeach; ?>
|
||||
<input type="hidden" name="columns" value='<?= json_encode($columns) ?>'>
|
||||
<input type="hidden" name="rows" value='<?= json_encode($rows) ?>'>
|
||||
<input type="hidden" name="excelrows" value='<?= json_encode($excelrows) ?>'>
|
||||
</form>
|
||||
<script>
|
||||
document.getElementById('redirectForm').submit();
|
||||
</script>
|
||||
<?php
|
||||
header("Location: imported.php?id=" . urlencode($template_id) . "&importref=" . urlencode($importReferenceCode));
|
||||
exit;
|
||||
?>
|
||||
@ -13,6 +13,12 @@ if (!$template_id) {
|
||||
|
||||
$user_id = $iduserlogin ?? 1;
|
||||
$show_all_users = isset($_GET['all_users']) && $_GET['all_users'] == '1';
|
||||
$importref = trim($_GET['importref'] ?? '');
|
||||
$usePagination = ($importref === '');
|
||||
$allowedLimits = [20, 40, 60, 100];
|
||||
$rawLimit = (int)($_GET['limit'] ?? 20);
|
||||
$perPage = in_array($rawLimit, $allowedLimits) ? $rawLimit : 20;
|
||||
$page = max(1, (int)($_GET['page'] ?? 1));
|
||||
|
||||
$db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
@ -70,16 +76,29 @@ $default_idclient = $template['idclient'] ?? null;
|
||||
|
||||
// Fetch records with status='i' for this template
|
||||
$userFilter = $show_all_users ? '' : 'AND d.user_id = ?';
|
||||
$importrefFilter = $importref !== '' ? 'AND d.importreferencecode = ?' : '';
|
||||
$baseWhere = "WHERE d.templateid = ? AND d.status = 'i' {$userFilter} {$importrefFilter}";
|
||||
$baseParams = [$template_id];
|
||||
if (!$show_all_users) $baseParams[] = $user_id;
|
||||
if ($importref !== '') $baseParams[] = $importref;
|
||||
|
||||
// Count total records
|
||||
$countStmt = $pdo->prepare("SELECT COUNT(*) FROM datadb d {$baseWhere}");
|
||||
$countStmt->execute($baseParams);
|
||||
$totalRows = (int)$countStmt->fetchColumn();
|
||||
$totalPages = $usePagination ? max(1, (int)ceil($totalRows / $perPage)) : 1;
|
||||
if ($page > $totalPages) $page = $totalPages;
|
||||
|
||||
$limitClause = $usePagination ? 'LIMIT ' . $perPage . ' OFFSET ' . (($page - 1) * $perPage) : '';
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT d.*, CONCAT(u.first_name, ' ', u.last_name) AS user_name
|
||||
FROM datadb d
|
||||
LEFT JOIN auth_users u ON d.user_id = u.id
|
||||
WHERE d.templateid = ? AND d.status = 'i' {$userFilter}
|
||||
{$baseWhere}
|
||||
ORDER BY d.iddatadb DESC
|
||||
{$limitClause}
|
||||
");
|
||||
$params = [$template_id];
|
||||
if (!$show_all_users) $params[] = $user_id;
|
||||
$stmt->execute($params);
|
||||
$stmt->execute($baseParams);
|
||||
$importedData = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$insertedIds = array_column($importedData, 'iddatadb');
|
||||
@ -872,6 +891,14 @@ window.gridMeta = <?= json_encode($gridMeta, JSON_UNESCAPED_UNICODE | JSON_UNESC
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes new-row-pulse {
|
||||
0%, 100% { background-color: transparent; }
|
||||
50% { background-color: #cce5ff; }
|
||||
}
|
||||
.row-just-created {
|
||||
animation: new-row-pulse 1s ease-in-out 3;
|
||||
}
|
||||
|
||||
.actions-dropdown .dropdown-toggle {
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
@ -990,6 +1017,87 @@ window.gridMeta = <?= json_encode($gridMeta, JSON_UNESCAPED_UNICODE | JSON_UNESC
|
||||
border-color: #dc3545 !important;
|
||||
}
|
||||
|
||||
/* ── Pagination bar ── */
|
||||
.pager-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 6px;
|
||||
padding: 6px 14px;
|
||||
font-size: 13px;
|
||||
color: #495057;
|
||||
}
|
||||
.pager-rows-per-page {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.pager-label {
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.pager-limit-group {
|
||||
display: inline-flex;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.pager-limit-btn {
|
||||
padding: 3px 10px;
|
||||
text-decoration: none;
|
||||
color: #495057;
|
||||
border-right: 1px solid #ced4da;
|
||||
transition: background .15s, color .15s;
|
||||
font-weight: 500;
|
||||
}
|
||||
.pager-limit-btn:last-child { border-right: none; }
|
||||
.pager-limit-btn:hover { background: #e9ecef; text-decoration: none; color: #212529; }
|
||||
.pager-limit-btn.active {
|
||||
background: #0d6efd;
|
||||
color: #fff;
|
||||
}
|
||||
.pager-limit-btn.active:hover { background: #0b5ed7; color: #fff; }
|
||||
.pager-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.pager-info {
|
||||
margin-right: 8px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.pager-btn, .pager-num {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 28px;
|
||||
height: 28px;
|
||||
padding: 0 6px;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
color: #495057;
|
||||
font-weight: 500;
|
||||
transition: background .15s, color .15s, border-color .15s;
|
||||
}
|
||||
.pager-btn:hover, .pager-num:hover { background: #e9ecef; text-decoration: none; color: #212529; }
|
||||
.pager-num.active {
|
||||
background: #0d6efd;
|
||||
color: #fff;
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
.pager-btn.disabled {
|
||||
pointer-events: none;
|
||||
opacity: .4;
|
||||
}
|
||||
.pager-dots {
|
||||
padding: 0 2px;
|
||||
color: #adb5bd;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
<title>Edit Imported Data - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
|
||||
</head>
|
||||
@ -1003,6 +1111,7 @@ window.gridMeta = <?= json_encode($gridMeta, JSON_UNESCAPED_UNICODE | JSON_UNESC
|
||||
<div class="mb-3 text d-flex align-items-center gap-2">
|
||||
<a href="imported.php?id=<?= $template_id ?>" class="btn btn-warning me-2">Imported (i)</a>
|
||||
<a href="tolims.php?id=<?= $template_id ?>" class="btn btn-success">To LIMS (l)</a>
|
||||
<?php if ($importref === ''): ?>
|
||||
<span class="ms-3">
|
||||
<label class="form-check-label" style="font-size: 13px; cursor: pointer;">
|
||||
<input type="checkbox" class="form-check-input" id="showAllUsers" <?= $show_all_users ? 'checked' : '' ?>
|
||||
@ -1010,8 +1119,58 @@ window.gridMeta = <?= json_encode($gridMeta, JSON_UNESCAPED_UNICODE | JSON_UNESC
|
||||
Show all users
|
||||
</label>
|
||||
</span>
|
||||
<span class="text-muted" style="font-size: 12px;">(<?= count($importedData) ?> records<?= !$show_all_users ? ' — my records only' : '' ?>)</span>
|
||||
<span class="text-muted" style="font-size: 12px;">
|
||||
(<?= $usePagination ? count($importedData) . " of {$totalRows}" : count($importedData) ?> records<?= !$show_all_users ? ' — my records only' : '' ?>)
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php if ($usePagination): ?>
|
||||
<?php
|
||||
$baseQuery = $_GET;
|
||||
unset($baseQuery['limit'], $baseQuery['page']);
|
||||
$pageQuery = $_GET;
|
||||
unset($pageQuery['page']);
|
||||
$pageBase = 'imported.php?' . http_build_query($pageQuery);
|
||||
$fromRow = ($page - 1) * $perPage + 1;
|
||||
$toRow = min($page * $perPage, $totalRows);
|
||||
?>
|
||||
<div class="pager-bar mb-2">
|
||||
<div class="pager-rows-per-page">
|
||||
<span class="pager-label">Rows per page</span>
|
||||
<div class="pager-limit-group">
|
||||
<?php foreach ($allowedLimits as $lim):
|
||||
$isActive = ($perPage === $lim);
|
||||
$url = 'imported.php?' . http_build_query(array_merge($baseQuery, ['limit' => $lim]));
|
||||
?>
|
||||
<a href="<?= htmlspecialchars($url) ?>" class="pager-limit-btn <?= $isActive ? 'active' : '' ?>"><?= $lim ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($totalPages > 1): ?>
|
||||
<div class="pager-nav">
|
||||
<span class="pager-info"><?= $fromRow ?>–<?= $toRow ?> of <?= $totalRows ?></span>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=1') ?>" class="pager-btn <?= $page <= 1 ? 'disabled' : '' ?>" title="First"><i class="fas fa-angle-double-left"></i></a>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . ($page - 1)) ?>" class="pager-btn <?= $page <= 1 ? 'disabled' : '' ?>" title="Previous"><i class="fas fa-angle-left"></i></a>
|
||||
<?php
|
||||
$startPage = max(1, $page - 2);
|
||||
$endPage = min($totalPages, $page + 2);
|
||||
if ($startPage > 1): ?>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=1') ?>" class="pager-num">1</a>
|
||||
<?php if ($startPage > 2): ?><span class="pager-dots">...</span><?php endif; ?>
|
||||
<?php endif;
|
||||
for ($p = $startPage; $p <= $endPage; $p++): ?>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . $p) ?>" class="pager-num <?= $p === $page ? 'active' : '' ?>"><?= $p ?></a>
|
||||
<?php endfor;
|
||||
if ($endPage < $totalPages): ?>
|
||||
<?php if ($endPage < $totalPages - 1): ?><span class="pager-dots">...</span><?php endif; ?>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . $totalPages) ?>" class="pager-num"><?= $totalPages ?></a>
|
||||
<?php endif; ?>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . ($page + 1)) ?>" class="pager-btn <?= $page >= $totalPages ? 'disabled' : '' ?>" title="Next"><i class="fas fa-angle-right"></i></a>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . $totalPages) ?>" class="pager-btn <?= $page >= $totalPages ? 'disabled' : '' ?>" title="Last"><i class="fas fa-angle-double-right"></i></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="card radius-10">
|
||||
<div class="card-header">
|
||||
<div class="d-flex align-items-center" style="min-height: 42px; gap: 12px;">
|
||||
|
||||
@ -164,10 +164,12 @@
|
||||
const templateId = window.gridMeta?.templateId;
|
||||
if (!templateId) { alert('Template ID missing'); return; }
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const importref = urlParams.get('importref') || '';
|
||||
const resp = await fetch('add_record.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ template_id: templateId })
|
||||
body: JSON.stringify({ template_id: templateId, importreferencecode: importref })
|
||||
});
|
||||
const result = await resp.json();
|
||||
|
||||
@ -186,7 +188,7 @@
|
||||
fixedFields: {},
|
||||
details: {},
|
||||
mainFieldValue: '',
|
||||
_dirty: true,
|
||||
_dirty: false,
|
||||
};
|
||||
|
||||
// Add to beginning of gridData
|
||||
@ -195,6 +197,14 @@
|
||||
// Re-render
|
||||
const gr = window.gridRenderer;
|
||||
if (gr) gr.renderVisibleRows();
|
||||
|
||||
// Highlight new row briefly
|
||||
const newGridRow = document.querySelector(`.grid-row[data-id="${result.iddatadb}"]`);
|
||||
if (newGridRow) {
|
||||
newGridRow.classList.add('row-just-created');
|
||||
newGridRow.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
setTimeout(() => newGridRow.classList.remove('row-just-created'), 4000);
|
||||
}
|
||||
} else {
|
||||
alert('Error: ' + (result.message || 'Unknown error'));
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
|
||||
if (result.success) {
|
||||
row._dirty = false;
|
||||
if (window.gridRenderer?.clearDirty) window.gridRenderer.clearDirty(rowIndex);
|
||||
// Flash success on row without re-rendering (preserves Select2 state)
|
||||
const gridRow = document.querySelector(`.grid-row[data-id="${row.iddatadb}"]`);
|
||||
if (gridRow) {
|
||||
@ -94,6 +95,7 @@
|
||||
const result = await resp.json();
|
||||
if (result.success) {
|
||||
data[idx]._dirty = false;
|
||||
if (window.gridRenderer?.clearDirty) window.gridRenderer.clearDirty(idx);
|
||||
success++;
|
||||
} else {
|
||||
fail++;
|
||||
|
||||
@ -14,6 +14,10 @@ if (!$template_id) {
|
||||
$user_id = $iduserlogin ?? 1;
|
||||
$is_readonly = true;
|
||||
$show_all_users = isset($_GET['all_users']) && $_GET['all_users'] == '1';
|
||||
$allowedLimits = [20, 40, 60, 100];
|
||||
$rawLimit = (int)($_GET['limit'] ?? 20);
|
||||
$perPage = in_array($rawLimit, $allowedLimits) ? $rawLimit : 20;
|
||||
$page = max(1, (int)($_GET['page'] ?? 1));
|
||||
|
||||
$db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
@ -69,18 +73,80 @@ $template_stmt->execute([$template_id]);
|
||||
$template = $template_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$default_idclient = $template['idclient'] ?? null;
|
||||
|
||||
// Maps logical fixed_field_key → real datadb column name
|
||||
$fixedAliasMap = [
|
||||
'ClienteResponsabile' => 'cliente_responsabile_id',
|
||||
'ClienteFornitore' => 'cliente_fornitore_id',
|
||||
'ClienteAnalisi' => 'clienteAnalisi',
|
||||
'MoltiplicatorePrezzo' => 'moltiplicatore_prezzo_id',
|
||||
'AnagraficaCertestObject' => 'anagrafica_certest_object_id',
|
||||
'AnagraficaCertestService' => 'anagrafica_certest_service_id',
|
||||
'ConsegnaRichiesta' => 'consegna_richiesta',
|
||||
];
|
||||
|
||||
// Fetch records with status='l' (exported to LIMS) for this template
|
||||
$userFilter = $show_all_users ? '' : 'AND d.user_id = ?';
|
||||
$filters = $_GET['f'] ?? [];
|
||||
if (!is_array($filters)) $filters = [];
|
||||
|
||||
// Map of filter keys → datadb columns (direct columns)
|
||||
$directColumnMap = [
|
||||
'commessaweb' => 'd.commessaweb',
|
||||
'idclient' => 'd.idclient',
|
||||
'importreferencecode' => 'd.importreferencecode',
|
||||
'importdate' => 'd.importdate',
|
||||
'filename_import' => 'd.filename_import',
|
||||
'user_name' => "CONCAT(u.first_name, ' ', u.last_name)",
|
||||
];
|
||||
// Add fixed field columns
|
||||
foreach ($fixedAliasMap as $fixedKey => $dbCol) {
|
||||
$directColumnMap[$fixedKey] = 'd.' . $dbCol;
|
||||
}
|
||||
|
||||
$filterSQL = '';
|
||||
$filterParams = [];
|
||||
foreach ($filters as $key => $val) {
|
||||
$val = trim($val);
|
||||
if ($val === '') continue;
|
||||
|
||||
if (isset($directColumnMap[$key])) {
|
||||
// Direct datadb column
|
||||
$filterSQL .= " AND {$directColumnMap[$key]} LIKE ?";
|
||||
$filterParams[] = '%' . $val . '%';
|
||||
} elseif (str_starts_with($key, 'detail_')) {
|
||||
// import_data_details field: detail_{mapping_id}
|
||||
$mappingId = (int)substr($key, 7);
|
||||
if ($mappingId > 0) {
|
||||
$filterSQL .= " AND EXISTS (SELECT 1 FROM import_data_details dd WHERE dd.id = d.iddatadb AND dd.mapping_id = ? AND dd.field_value LIKE ?)";
|
||||
$filterParams[] = $mappingId;
|
||||
$filterParams[] = '%' . $val . '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$baseWhere = "WHERE d.templateid = ? AND d.status = 'l' {$userFilter} {$filterSQL}";
|
||||
$baseParams = [$template_id];
|
||||
if (!$show_all_users) $baseParams[] = $user_id;
|
||||
$baseParams = array_merge($baseParams, $filterParams);
|
||||
|
||||
// Check if any filter is active
|
||||
$hasActiveFilters = !empty(array_filter($filters, fn($v) => trim($v) !== ''));
|
||||
|
||||
$countStmt = $pdo->prepare("SELECT COUNT(*) FROM datadb d LEFT JOIN auth_users u ON d.user_id = u.id {$baseWhere}");
|
||||
$countStmt->execute($baseParams);
|
||||
$totalRows = (int)$countStmt->fetchColumn();
|
||||
$totalPages = max(1, (int)ceil($totalRows / $perPage));
|
||||
if ($page > $totalPages) $page = $totalPages;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT d.*, CONCAT(u.first_name, ' ', u.last_name) AS user_name
|
||||
FROM datadb d
|
||||
LEFT JOIN auth_users u ON d.user_id = u.id
|
||||
WHERE d.templateid = ? AND d.status = 'l' {$userFilter}
|
||||
{$baseWhere}
|
||||
ORDER BY d.iddatadb DESC
|
||||
LIMIT {$perPage} OFFSET " . (($page - 1) * $perPage) . "
|
||||
");
|
||||
$params = [$template_id];
|
||||
if (!$show_all_users) $params[] = $user_id;
|
||||
$stmt->execute($params);
|
||||
$stmt->execute($baseParams);
|
||||
$importedData = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$insertedIds = array_column($importedData, 'iddatadb');
|
||||
@ -154,17 +220,6 @@ foreach ($tempMap as $f) {
|
||||
$fixedFields[] = $f;
|
||||
}
|
||||
|
||||
// Maps logical fixed_field_key → real datadb column name (mirrors JS fixedAliasMap)
|
||||
$fixedAliasMap = [
|
||||
'ClienteResponsabile' => 'cliente_responsabile_id',
|
||||
'ClienteFornitore' => 'cliente_fornitore_id',
|
||||
'ClienteAnalisi' => 'clienteAnalisi',
|
||||
'MoltiplicatorePrezzo' => 'moltiplicatore_prezzo_id',
|
||||
'AnagraficaCertestObject' => 'anagrafica_certest_object_id',
|
||||
'AnagraficaCertestService' => 'anagrafica_certest_service_id',
|
||||
'ConsegnaRichiesta' => 'consegna_richiesta',
|
||||
];
|
||||
|
||||
// helper default (DATE can use 'today' if you already use it elsewhere)
|
||||
function fixedDefaultValue(array $f): string
|
||||
{
|
||||
@ -173,6 +228,66 @@ function fixedDefaultValue(array $f): string
|
||||
return (string)$v;
|
||||
}
|
||||
|
||||
// ── Build lookup maps: id → label for fixed fields ──
|
||||
$fixedLookup = []; // e.g. $fixedLookup['MoltiplicatorePrezzo'][2] = 'Urgente (1.5x)'
|
||||
|
||||
function loadCacheJson(string $path): ?array {
|
||||
if (file_exists($path) && (time() - filemtime($path) < 3600)) {
|
||||
return json_decode(file_get_contents($path), true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// MoltiplicatorePrezzo
|
||||
$cached = loadCacheJson(__DIR__ . '/cache/moltiplicatori_prezzo.json');
|
||||
if ($cached) {
|
||||
$items = $cached['value'] ?? $cached;
|
||||
foreach ($items as $item) {
|
||||
$id = $item['IdMoltiplicatorePrezzo'] ?? null;
|
||||
if ($id !== null) $fixedLookup['MoltiplicatorePrezzo'][$id] = $item['Descrizione'] ?? $item['Codice'] ?? $id;
|
||||
}
|
||||
}
|
||||
|
||||
// AnagraficaCertestObject
|
||||
$cached = loadCacheJson(__DIR__ . '/cache/anagrafica_certest_object.json');
|
||||
if ($cached) {
|
||||
$items = $cached['value'] ?? $cached;
|
||||
foreach ($items as $item) {
|
||||
$id = $item['IdAnagrafica'] ?? null;
|
||||
if ($id !== null) $fixedLookup['AnagraficaCertestObject'][$id] = $item['NomeAnagrafica'] ?? $item['Codice'] ?? $id;
|
||||
}
|
||||
}
|
||||
|
||||
// AnagraficaCertestService
|
||||
$cached = loadCacheJson(__DIR__ . '/cache/anagrafica_certest_service.json');
|
||||
if ($cached) {
|
||||
$items = $cached['value'] ?? $cached;
|
||||
foreach ($items as $item) {
|
||||
$id = $item['IdAnagrafica'] ?? null;
|
||||
if ($id !== null) $fixedLookup['AnagraficaCertestService'][$id] = $item['NomeAnagrafica'] ?? $item['Codice'] ?? $id;
|
||||
}
|
||||
}
|
||||
|
||||
// ClienteResponsabile — per-client cache files
|
||||
$clienteIds = array_unique(array_filter(array_column($importedData, 'idclient')));
|
||||
foreach ($clienteIds as $cid) {
|
||||
$cached = loadCacheJson(__DIR__ . '/cache/cliente_responsabili_' . (int)$cid . '.json');
|
||||
if ($cached) {
|
||||
$items = $cached['Responsabili'] ?? [];
|
||||
foreach ($items as $item) {
|
||||
$id = $item['IdClienteResponsabile'] ?? null;
|
||||
if ($id !== null) $fixedLookup['ClienteResponsabile'][$id] = $item['Nominativo'] ?? $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: resolve fixed field id → label
|
||||
function resolveFixedValue(string $key, $val, array $fixedLookup): string {
|
||||
if ($val === '' || $val === null) return '';
|
||||
if (isset($fixedLookup[$key][(int)$val])) return $fixedLookup[$key][(int)$val];
|
||||
return (string)$val;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<!doctype html>
|
||||
@ -850,6 +965,161 @@ function fixedDefaultValue(array $f): string
|
||||
/* View modals — ensure they sit above backdrop */
|
||||
#partsViewModal, #photosViewModal { z-index: 1060 !important; }
|
||||
.modal-backdrop { z-index: 1050 !important; }
|
||||
/* ── Grid filter row ── */
|
||||
.grid-filter-row {
|
||||
background: #f0f4f8 !important;
|
||||
border-bottom: 2px solid #dee2e6 !important;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
}
|
||||
.grid-filter-row:hover {
|
||||
background: #f0f4f8 !important;
|
||||
}
|
||||
.grid-filter-row .grid-cell {
|
||||
padding: 4px 6px !important;
|
||||
}
|
||||
.grid-filter-input {
|
||||
width: 100% !important;
|
||||
padding: 3px 6px !important;
|
||||
font-size: 11px !important;
|
||||
border: 1px solid #ced4da !important;
|
||||
border-radius: 3px !important;
|
||||
background: #fff !important;
|
||||
color: #333 !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.grid-filter-input:focus {
|
||||
border-color: #80bdff !important;
|
||||
box-shadow: 0 0 0 2px rgba(0,123,255,.15) !important;
|
||||
outline: none !important;
|
||||
}
|
||||
.grid-filter-input::placeholder {
|
||||
color: #adb5bd;
|
||||
font-style: italic;
|
||||
}
|
||||
.grid-filter-row .grid-filter-input.has-value {
|
||||
border-color: #0d6efd !important;
|
||||
background: #f0f7ff !important;
|
||||
}
|
||||
select.grid-filter-input {
|
||||
cursor: pointer;
|
||||
padding-right: 18px !important;
|
||||
appearance: auto;
|
||||
}
|
||||
.filter-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
width: 100%;
|
||||
}
|
||||
.filter-wrap .grid-filter-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.filter-clear-btn {
|
||||
flex-shrink: 0;
|
||||
border: none;
|
||||
background: #dc3545;
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
cursor: pointer;
|
||||
padding: 2px 4px;
|
||||
line-height: 1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.filter-clear-btn:hover {
|
||||
background: #c82333;
|
||||
}
|
||||
.grid-filter-row .grid-cell {
|
||||
background: #f0f4f8 !important;
|
||||
}
|
||||
/* First sticky cell fills full row height */
|
||||
.grid-filter-row .grid-cell.button-cell {
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
/* ── Pagination bar ── */
|
||||
.pager-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 6px;
|
||||
padding: 6px 14px;
|
||||
font-size: 13px;
|
||||
color: #495057;
|
||||
}
|
||||
.pager-rows-per-page {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.pager-label {
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.pager-limit-group {
|
||||
display: inline-flex;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.pager-limit-btn {
|
||||
padding: 3px 10px;
|
||||
text-decoration: none;
|
||||
color: #495057;
|
||||
border-right: 1px solid #ced4da;
|
||||
transition: background .15s, color .15s;
|
||||
font-weight: 500;
|
||||
}
|
||||
.pager-limit-btn:last-child { border-right: none; }
|
||||
.pager-limit-btn:hover { background: #e9ecef; text-decoration: none; color: #212529; }
|
||||
.pager-limit-btn.active {
|
||||
background: #0d6efd;
|
||||
color: #fff;
|
||||
}
|
||||
.pager-limit-btn.active:hover { background: #0b5ed7; color: #fff; }
|
||||
.pager-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.pager-info {
|
||||
margin-right: 8px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.pager-btn, .pager-num {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 28px;
|
||||
height: 28px;
|
||||
padding: 0 6px;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
color: #495057;
|
||||
font-weight: 500;
|
||||
transition: background .15s, color .15s, border-color .15s;
|
||||
}
|
||||
.pager-btn:hover, .pager-num:hover { background: #e9ecef; text-decoration: none; color: #212529; }
|
||||
.pager-num.active {
|
||||
background: #0d6efd;
|
||||
color: #fff;
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
.pager-btn.disabled {
|
||||
pointer-events: none;
|
||||
opacity: .4;
|
||||
}
|
||||
.pager-dots {
|
||||
padding: 0 2px;
|
||||
color: #adb5bd;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
<title>Edit Imported Data - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
|
||||
</head>
|
||||
@ -865,17 +1135,72 @@ function fixedDefaultValue(array $f): string
|
||||
<a href="tolims.php?id=<?= $template_id ?>" class="btn btn-success">To LIMS (l)</a>
|
||||
<span class="ms-3">
|
||||
<label class="form-check-label" style="font-size: 13px; cursor: pointer;">
|
||||
<?php
|
||||
$toggleParams = $_GET;
|
||||
unset($toggleParams['all_users']);
|
||||
$toggleBase = 'tolims.php?' . http_build_query($toggleParams);
|
||||
?>
|
||||
<input type="checkbox" class="form-check-input" id="showAllUsers" <?= $show_all_users ? 'checked' : '' ?>
|
||||
onchange="window.location.href='tolims.php?id=<?= $template_id ?>' + (this.checked ? '&all_users=1' : '')">
|
||||
onchange="window.location.href='<?= htmlspecialchars($toggleBase) ?>' + (this.checked ? '&all_users=1' : '')">
|
||||
Show all users
|
||||
</label>
|
||||
</span>
|
||||
<span class="text-muted" style="font-size: 12px;">(<?= count($importedData) ?> records<?= !$show_all_users ? ' — my records' : '' ?>)</span>
|
||||
<span class="text-muted" style="font-size: 12px;">
|
||||
(<?= count($importedData) ?> of <?= $totalRows ?> records<?= !$show_all_users ? ' — my records' : '' ?>)
|
||||
</span>
|
||||
</div>
|
||||
<?php
|
||||
$baseQuery = $_GET;
|
||||
unset($baseQuery['limit'], $baseQuery['page']);
|
||||
$pageQuery = $_GET;
|
||||
unset($pageQuery['page']);
|
||||
$pageBase = 'tolims.php?' . http_build_query($pageQuery);
|
||||
$fromRow = ($page - 1) * $perPage + 1;
|
||||
$toRow = min($page * $perPage, $totalRows);
|
||||
?>
|
||||
<div class="pager-bar mb-2">
|
||||
<div class="pager-rows-per-page">
|
||||
<span class="pager-label">Rows per page</span>
|
||||
<div class="pager-limit-group">
|
||||
<?php foreach ($allowedLimits as $lim):
|
||||
$isActive = ($perPage === $lim);
|
||||
$url = 'tolims.php?' . http_build_query(array_merge($baseQuery, ['limit' => $lim]));
|
||||
?>
|
||||
<a href="<?= htmlspecialchars($url) ?>" class="pager-limit-btn <?= $isActive ? 'active' : '' ?>"><?= $lim ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($totalPages > 1): ?>
|
||||
<div class="pager-nav">
|
||||
<span class="pager-info"><?= $fromRow ?>–<?= $toRow ?> of <?= $totalRows ?></span>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=1') ?>" class="pager-btn <?= $page <= 1 ? 'disabled' : '' ?>" title="First"><i class="fas fa-angle-double-left"></i></a>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . ($page - 1)) ?>" class="pager-btn <?= $page <= 1 ? 'disabled' : '' ?>" title="Previous"><i class="fas fa-angle-left"></i></a>
|
||||
<?php
|
||||
$startPage = max(1, $page - 2);
|
||||
$endPage = min($totalPages, $page + 2);
|
||||
if ($startPage > 1): ?>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=1') ?>" class="pager-num">1</a>
|
||||
<?php if ($startPage > 2): ?><span class="pager-dots">...</span><?php endif; ?>
|
||||
<?php endif;
|
||||
for ($p = $startPage; $p <= $endPage; $p++): ?>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . $p) ?>" class="pager-num <?= $p === $page ? 'active' : '' ?>"><?= $p ?></a>
|
||||
<?php endfor;
|
||||
if ($endPage < $totalPages): ?>
|
||||
<?php if ($endPage < $totalPages - 1): ?><span class="pager-dots">...</span><?php endif; ?>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . $totalPages) ?>" class="pager-num"><?= $totalPages ?></a>
|
||||
<?php endif; ?>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . ($page + 1)) ?>" class="pager-btn <?= $page >= $totalPages ? 'disabled' : '' ?>" title="Next"><i class="fas fa-angle-right"></i></a>
|
||||
<a href="<?= htmlspecialchars($pageBase . '&page=' . $totalPages) ?>" class="pager-btn <?= $page >= $totalPages ? 'disabled' : '' ?>" title="Last"><i class="fas fa-angle-double-right"></i></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="card radius-10">
|
||||
<div class="card-header">
|
||||
<div class="d-flex align-items-center" style="min-height: 42px; gap: 12px;">
|
||||
<span style="font-weight: 600; font-size: 14px;"><i class="fas fa-check-circle" style="color: #28a745;"></i> Exported to LIMS</span>
|
||||
<?php if ($hasActiveFilters): ?>
|
||||
<a href="tolims.php?id=<?= $template_id ?><?= $show_all_users ? '&all_users=1' : '' ?><?= $perPage !== 20 ? '&limit=' . $perPage : '' ?>" class="btn btn-outline-danger btn-sm" style="font-size: 12px;"><i class="fas fa-times"></i> Clear filters</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@ -1146,6 +1471,131 @@ function fixedDefaultValue(array $f): string
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Filter row (server-side) -->
|
||||
<?php
|
||||
// Helper: wrap filter element with clear button
|
||||
function wrapFilter(string $inner, bool $hasValue): string {
|
||||
$btn = $hasValue
|
||||
? "<button type='button' class='filter-clear-btn' onclick='clearOneFilter(this)' title='Clear'>×</button>"
|
||||
: '';
|
||||
return "<div class='filter-wrap'>{$inner}{$btn}</div>";
|
||||
}
|
||||
// Helper: render a select filter from a lookup array
|
||||
function renderFilterSelect(string $name, array $options, string $currentVal, string $style = ''): string {
|
||||
$html = "<select class='grid-filter-input' name='" . htmlspecialchars($name) . "' style='" . htmlspecialchars($style) . "' onchange='submitFilters()'>";
|
||||
$html .= "<option value=''>All</option>";
|
||||
foreach ($options as $id => $label) {
|
||||
$sel = ((string)$id === $currentVal) ? ' selected' : '';
|
||||
$html .= "<option value='" . htmlspecialchars((string)$id) . "'{$sel}>" . htmlspecialchars($label) . "</option>";
|
||||
}
|
||||
$html .= "</select>";
|
||||
return wrapFilter($html, $currentVal !== '');
|
||||
}
|
||||
// Helper: render a text filter
|
||||
function renderFilterInput(string $name, string $currentVal): string {
|
||||
$inner = "<input type='text' class='grid-filter-input' name='" . htmlspecialchars($name) . "' value='" . htmlspecialchars($currentVal) . "' placeholder='⌕'>";
|
||||
return wrapFilter($inner, $currentVal !== '');
|
||||
}
|
||||
// Helper: render a select filter populated by JS
|
||||
function renderFilterSelectJS(string $name, string $currentVal, string $jsClass, string $dataAttr = ''): string {
|
||||
$html = "<select class='grid-filter-input {$jsClass}' name='" . htmlspecialchars($name) . "' {$dataAttr} onchange='submitFilters()'>";
|
||||
$html .= "<option value=''>All</option>";
|
||||
if ($currentVal !== '') {
|
||||
$html .= "<option value='" . htmlspecialchars($currentVal) . "' selected>" . htmlspecialchars($currentVal) . "</option>";
|
||||
}
|
||||
$html .= "</select>";
|
||||
return wrapFilter($html, $currentVal !== '');
|
||||
}
|
||||
// Fields that are client-id lookups
|
||||
$clientFilterKeys = ['ClienteFornitore', 'ClienteAnalisi'];
|
||||
?>
|
||||
<div class="grid-row grid-filter-row" id="gridFilterRow">
|
||||
<div class="grid-cell button-cell"></div>
|
||||
<?php if ($mainFieldMapping):
|
||||
$fKey = 'detail_' . $mainFieldMapping['id'];
|
||||
$fVal = $filters[$fKey] ?? '';
|
||||
?>
|
||||
<div class="grid-cell" style="flex: 0 0 150px; padding: 4px 6px;">
|
||||
<?php if ($mainFieldMapping['data_type'] === 'SceltaMultipla'): ?>
|
||||
<?= renderFilterSelectJS("f[$fKey]", $fVal, 'scelta-filter', "data-field-id='{$mainFieldMapping['field_id']}'") ?>
|
||||
<?php else: ?>
|
||||
<?= renderFilterInput("f[$fKey]", $fVal) ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<!-- Status/CommessaWeb -->
|
||||
<div class="grid-cell" style="flex: 0 0 150px; padding: 4px 6px;">
|
||||
<?= renderFilterInput('f[commessaweb]', $filters['commessaweb'] ?? '') ?>
|
||||
</div>
|
||||
<!-- Client -->
|
||||
<div class="grid-cell" style="flex: 0 0 300px; padding: 4px 6px;">
|
||||
<?= renderFilterSelectJS('f[idclient]', $filters['idclient'] ?? '', 'client-filter') ?>
|
||||
</div>
|
||||
<?php
|
||||
// Auto fields
|
||||
foreach ($allMappings as $mapping) {
|
||||
if (!$mapping['is_manual'] && $mapping['main_field'] != 1 && $mapping['is_visible_import'] == 1) {
|
||||
$fKey = 'detail_' . $mapping['id'];
|
||||
$fVal = $filters[$fKey] ?? '';
|
||||
echo "<div class='grid-cell' style='flex: 0 0 150px; padding: 4px 6px;'>";
|
||||
if ($mapping['data_type'] === 'SceltaMultipla') {
|
||||
echo renderFilterSelectJS("f[$fKey]", $fVal, 'scelta-filter', "data-field-id='{$mapping['field_id']}'");
|
||||
} else {
|
||||
echo renderFilterInput("f[$fKey]", $fVal);
|
||||
}
|
||||
echo "</div>";
|
||||
}
|
||||
}
|
||||
// Manual fields
|
||||
foreach ($allMappings as $mapping) {
|
||||
if ($mapping['is_manual'] && $mapping['main_field'] != 1 && $mapping['is_visible_import'] == 1) {
|
||||
$fKey = 'detail_' . $mapping['id'];
|
||||
$fVal = $filters[$fKey] ?? '';
|
||||
echo "<div class='grid-cell' style='flex: 0 0 150px; padding: 4px 6px;'>";
|
||||
if ($mapping['data_type'] === 'SceltaMultipla') {
|
||||
echo renderFilterSelectJS("f[$fKey]", $fVal, 'scelta-filter', "data-field-id='{$mapping['field_id']}'");
|
||||
} else {
|
||||
echo renderFilterInput("f[$fKey]", $fVal);
|
||||
}
|
||||
echo "</div>";
|
||||
}
|
||||
}
|
||||
// Tested Component, AWB, Tracking
|
||||
echo "<div class='grid-cell' style='flex: 0 0 150px; padding: 4px 6px;'></div>";
|
||||
echo "<div class='grid-cell' style='flex: 0 0 200px; padding: 4px 6px;'></div>";
|
||||
echo "<div class='grid-cell' style='flex: 0 0 250px; padding: 4px 6px;'></div>";
|
||||
|
||||
// Fixed fields
|
||||
if (!empty($fixedFields)) {
|
||||
$insertedFilterAfterConsegna = false;
|
||||
foreach ($fixedFields as $f) {
|
||||
$key = $f['fixed_field_key'];
|
||||
$fVal = $filters[$key] ?? '';
|
||||
echo "<div class='grid-cell' style='flex: 0 0 180px; padding: 4px 6px;'>";
|
||||
if (in_array($key, $clientFilterKeys, true)) {
|
||||
// Client-based selects (populated by JS)
|
||||
echo renderFilterSelectJS("f[$key]", $fVal, 'client-filter');
|
||||
} elseif (isset($fixedLookup[$key]) && !empty($fixedLookup[$key])) {
|
||||
// PHP-cached lookups
|
||||
echo renderFilterSelect("f[$key]", $fixedLookup[$key], $fVal);
|
||||
} elseif ($key === 'ConsegnaRichiesta') {
|
||||
echo renderFilterInput("f[$key]", $fVal);
|
||||
} else {
|
||||
echo renderFilterInput("f[$key]", $fVal);
|
||||
}
|
||||
echo "</div>";
|
||||
|
||||
if ($key === 'ConsegnaRichiesta' && !$insertedFilterAfterConsegna) {
|
||||
echo "<div class='grid-cell' style='flex: 0 0 150px; padding: 4px 6px;'>" . renderFilterInput('f[importreferencecode]', $filters['importreferencecode'] ?? '') . "</div>";
|
||||
echo "<div class='grid-cell' style='flex: 0 0 150px; padding: 4px 6px;'>" . renderFilterInput('f[filename_import]', $filters['filename_import'] ?? '') . "</div>";
|
||||
echo "<div class='grid-cell' style='flex: 0 0 150px; padding: 4px 6px;'>" . renderFilterInput('f[importdate]', $filters['importdate'] ?? '') . "</div>";
|
||||
$insertedFilterAfterConsegna = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php foreach ($importedData as $index => $row): ?>
|
||||
<div class="grid-row" data-id="<?= $row['iddatadb'] ?>">
|
||||
<div class="grid-cell button-cell" style="flex: 0 0 120px; position: relative;">
|
||||
@ -1156,9 +1606,10 @@ function fixedDefaultValue(array $f): string
|
||||
$detail = array_filter($manualDetails, fn($d) => $d['mapping_id'] == $mainFieldMapping['id'] && $d['datadb_id'] == $row['iddatadb']);
|
||||
$detail = reset($detail) ?: ['field_value' => $mainFieldMapping['manual_default']];
|
||||
$fieldValue = $detail['field_value'] ?? $mainFieldMapping['manual_default'] ?? '';
|
||||
$isScelta = ($mainFieldMapping['data_type'] === 'SceltaMultipla');
|
||||
?>
|
||||
<div class="grid-cell" data-col="main_field" data-row="<?= $index ?>" data-index="1" style="flex: 0 0 150px;">
|
||||
<span><?= htmlspecialchars($fieldValue) ?></span>
|
||||
<span <?= $isScelta ? "class='scelta-value' data-field-id='{$mainFieldMapping['field_id']}'" : '' ?>><?= htmlspecialchars($fieldValue) ?></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="grid-cell" data-col="status" data-row="<?= $index ?>" data-index="<?= $mainFieldMapping ? 2 : 1 ?>" style="flex: 0 0 150px;">
|
||||
@ -1180,8 +1631,11 @@ function fixedDefaultValue(array $f): string
|
||||
$detail = array_filter($rowDetails, fn($d) => $d['mapping_id'] == $mapping['id']);
|
||||
$detail = reset($detail) ?: ['field_value' => $mapping['manual_default']];
|
||||
$fieldValue = $detail['field_value'] ?? $mapping['manual_default'] ?? '';
|
||||
$isScelta = ($mapping['data_type'] === 'SceltaMultipla');
|
||||
echo "<div class='grid-cell' data-col='auto_$autoIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
|
||||
echo "<span>" . htmlspecialchars($fieldValue) . "</span>";
|
||||
echo $isScelta
|
||||
? "<span class='scelta-value' data-field-id='{$mapping['field_id']}'>" . htmlspecialchars($fieldValue) . "</span>"
|
||||
: "<span>" . htmlspecialchars($fieldValue) . "</span>";
|
||||
echo "</div>";
|
||||
$cellIndex++;
|
||||
$autoIndex++;
|
||||
@ -1192,8 +1646,11 @@ function fixedDefaultValue(array $f): string
|
||||
$detail = array_filter($rowDetails, fn($d) => $d['mapping_id'] == $mapping['id']);
|
||||
$detail = reset($detail) ?: ['field_value' => $mapping['manual_default']];
|
||||
$fieldValue = $detail['field_value'] ?? $mapping['manual_default'] ?? '';
|
||||
$isScelta = ($mapping['data_type'] === 'SceltaMultipla');
|
||||
echo "<div class='grid-cell' data-col='manual_$autoIndex' data-row='$index' data-index='$cellIndex' style='flex: 0 0 150px;'>";
|
||||
echo "<span>" . htmlspecialchars($fieldValue) . "</span>";
|
||||
echo $isScelta
|
||||
? "<span class='scelta-value' data-field-id='{$mapping['field_id']}'>" . htmlspecialchars($fieldValue) . "</span>"
|
||||
: "<span>" . htmlspecialchars($fieldValue) . "</span>";
|
||||
echo "</div>";
|
||||
$cellIndex++;
|
||||
}
|
||||
@ -1218,9 +1675,15 @@ function fixedDefaultValue(array $f): string
|
||||
$key = $f['fixed_field_key'];
|
||||
$dbCol = $fixedAliasMap[$key] ?? $key;
|
||||
$val = $row[$dbCol] ?? '';
|
||||
$isClientField = in_array($key, ['ClienteFornitore', 'ClienteAnalisi'], true);
|
||||
$displayVal = $isClientField ? (string)$val : resolveFixedValue($key, $val, $fixedLookup);
|
||||
|
||||
echo "<div class='grid-cell' data-col='" . htmlspecialchars($key) . "' data-row='$index' data-index='$cellIndex' style='flex: 0 0 180px;'>";
|
||||
echo "<span>" . htmlspecialchars((string)$val) . "</span>";
|
||||
if ($isClientField && $val !== '' && $val !== null) {
|
||||
echo "<span class='client-text' data-client-id='" . htmlspecialchars((string)$val) . "'>" . htmlspecialchars((string)$val) . "</span>";
|
||||
} else {
|
||||
echo "<span>" . htmlspecialchars($displayVal) . "</span>";
|
||||
}
|
||||
echo "</div>";
|
||||
$cellIndex++;
|
||||
|
||||
@ -1286,18 +1749,80 @@ function fixedDefaultValue(array $f): string
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Load client names to replace IDs
|
||||
// Resolve SceltaMultipla IDs → Valore (cells + filter selects)
|
||||
(function() {
|
||||
const sceltaEls = document.querySelectorAll('.scelta-value');
|
||||
const sceltaFilters = document.querySelectorAll('select.scelta-filter');
|
||||
const fieldIds = new Set();
|
||||
sceltaEls.forEach(el => { if (el.dataset.fieldId) fieldIds.add(el.dataset.fieldId); });
|
||||
sceltaFilters.forEach(el => { if (el.dataset.fieldId) fieldIds.add(el.dataset.fieldId); });
|
||||
if (!fieldIds.size) return;
|
||||
|
||||
$.getJSON('get_customfield_values.php', { field_ids: [...fieldIds].join(',') }, function(data) {
|
||||
const lookup = {};
|
||||
for (const [fid, values] of Object.entries(data)) {
|
||||
lookup[fid] = {};
|
||||
(values || []).forEach(v => {
|
||||
lookup[fid][v.IdCustomFieldsValue] = v.Valore;
|
||||
});
|
||||
}
|
||||
// Resolve cell values
|
||||
sceltaEls.forEach(el => {
|
||||
const fid = el.dataset.fieldId;
|
||||
const raw = (el.textContent || '').trim();
|
||||
if (fid && lookup[fid] && lookup[fid][raw]) {
|
||||
el.textContent = lookup[fid][raw];
|
||||
}
|
||||
});
|
||||
// Populate filter selects
|
||||
sceltaFilters.forEach(sel => {
|
||||
const fid = sel.dataset.fieldId;
|
||||
if (!fid || !lookup[fid]) return;
|
||||
const currentVal = sel.value;
|
||||
// Sort by Valore
|
||||
const sorted = Object.entries(lookup[fid]).sort((a, b) => a[1].localeCompare(b[1]));
|
||||
sel.innerHTML = '<option value="">All</option>';
|
||||
sorted.forEach(([id, label]) => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = id;
|
||||
opt.textContent = label;
|
||||
if (id === currentVal) opt.selected = true;
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
// Load client names → resolve cells + populate filter selects
|
||||
$.getJSON('get_clienti.php', function(data) {
|
||||
const clients = data.value || [];
|
||||
const map = {};
|
||||
const sorted = [];
|
||||
clients.forEach(c => {
|
||||
const code = (c.CodiceCliente || '').split('_')[1] || c.CodiceCliente || '';
|
||||
map[c.IdCliente] = (c.Nominativo || '').trim() + (code ? ' - ' + code : '') + ' (' + c.IdCliente + ')';
|
||||
const name = (c.Nominativo || '').trim();
|
||||
map[c.IdCliente] = name;
|
||||
sorted.push({ id: c.IdCliente, name: name });
|
||||
});
|
||||
sorted.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
// Resolve cell values
|
||||
document.querySelectorAll('.client-text').forEach(el => {
|
||||
const id = el.getAttribute('data-client-id');
|
||||
if (id && map[id]) el.textContent = map[id];
|
||||
});
|
||||
|
||||
// Populate client filter selects
|
||||
document.querySelectorAll('select.client-filter').forEach(sel => {
|
||||
const currentVal = sel.value;
|
||||
sel.innerHTML = '<option value="">All</option>';
|
||||
sorted.forEach(c => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = c.id;
|
||||
opt.textContent = c.name;
|
||||
if (String(c.id) === currentVal) opt.selected = true;
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Modal close handlers
|
||||
@ -1358,6 +1883,38 @@ function fixedDefaultValue(array $f): string
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ── Column filters ──
|
||||
function clearOneFilter(btn) {
|
||||
const wrap = btn.closest('.filter-wrap');
|
||||
const el = wrap.querySelector('.grid-filter-input');
|
||||
if (el) { el.value = ''; submitFilters(); }
|
||||
}
|
||||
function submitFilters() {
|
||||
const filterRow = document.getElementById('gridFilterRow');
|
||||
if (!filterRow) return;
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
for (const key of [...params.keys()]) {
|
||||
if (key.startsWith('f[') || key === 'page') params.delete(key);
|
||||
}
|
||||
filterRow.querySelectorAll('.grid-filter-input').forEach(el => {
|
||||
const val = el.value.trim();
|
||||
if (val) params.set(el.name, val);
|
||||
});
|
||||
window.location.href = 'tolims.php?' + params.toString();
|
||||
}
|
||||
(function() {
|
||||
const filterRow = document.getElementById('gridFilterRow');
|
||||
if (!filterRow) return;
|
||||
filterRow.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') { e.preventDefault(); submitFilters(); }
|
||||
});
|
||||
filterRow.querySelectorAll('.grid-filter-input').forEach(el => {
|
||||
el.classList.toggle('has-value', el.value.trim() !== '');
|
||||
el.addEventListener('input', () => el.classList.toggle('has-value', el.value.trim() !== ''));
|
||||
el.addEventListener('change', () => el.classList.toggle('has-value', el.value.trim() !== ''));
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user