union ids

This commit is contained in:
2026-07-19 14:23:23 +03:00
parent c3f3e824dc
commit 69bb029d9d
2 changed files with 163 additions and 10 deletions
+54
View File
@@ -28,6 +28,60 @@ $wantAllIds = !empty($body['want_all_ids']);
$cacheDir = __DIR__ . '/cache';
$explicitIds = [];
if (isset($body['ids']) && is_array($body['ids'])) {
$explicitIds = array_values(array_unique(array_filter(
array_map('intval', $body['ids']),
fn($v) => $v > 0
)));
}
if (!empty($explicitIds)) {
// Scoping di sicurezza: solo record del template/utente/import corretti.
$conds = ['d.templateid = ?', 'd.status = ?'];
$params = [$templateId, $status];
if (!$showAll) { $conds[] = 'd.user_id = ?'; $params[] = $userId; }
if ($importref !== '') { $conds[] = 'd.importreferencecode = ?'; $params[] = $importref; }
$ph = implode(',', array_fill(0, count($explicitIds), '?'));
$conds[] = "d.iddatadb IN ($ph)";
foreach ($explicitIds as $id) $params[] = $id;
$whereSql = implode(' AND ', $conds);
try {
$countStmt = $pdo->prepare("SELECT COUNT(*) FROM datadb d WHERE {$whereSql}");
$countStmt->execute($params);
$total = (int)$countStmt->fetchColumn();
$totalPages = max(1, (int)ceil($total / $perPage));
if ($page > $totalPages) $page = $totalPages;
$offset = ($page - 1) * $perPage;
$idStmt = $pdo->prepare("
SELECT d.iddatadb FROM datadb d
WHERE {$whereSql}
ORDER BY d.excelrow ASC, d.iddatadb ASC
LIMIT {$perPage} OFFSET {$offset}
");
$idStmt->execute($params);
$pageIds = array_map('intval', $idStmt->fetchAll(PDO::FETCH_COLUMN));
$config = buildGridConfig($pdo, $templateId);
$rows = buildGridRows($pdo, $pageIds, $config);
echo json_encode([
'success' => true,
'total' => $total,
'page' => $page,
'per_page' => $perPage,
'total_pages' => $totalPages,
'rows' => $rows,
'mode' => 'selection',
]);
} catch (Exception $e) {
error_log('filter_records (ids mode) error: ' . $e->getMessage());
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
exit;
}
$fixedAliasMap = [
'ClienteResponsabile' => 'cliente_responsabile_id',
'ClienteFornitore' => 'cliente_fornitore_id',
+109 -10
View File
@@ -39,6 +39,8 @@
let filterTotal = 0;
let originalData = null; // snapshot della pagina originale (per ripristino)
let filterReqSeq = 0;
let showingSelection = false; // true quando mostriamo l'UNIONE dei selezionati
let pagerFn = null; // paginazione corrente (applyServerFilter | showSelectedRecords)
function collectActiveFilters() {
const cols = meta().columns || [];
@@ -77,14 +79,16 @@
return;
}
el.style.display = "inline-flex";
const label = showingSelection ? "selezionati" : "trovati";
el.innerHTML =
`<button type="button" class="btn btn-outline-secondary btn-sm" id="filterPrevBtn" ${filterPage <= 1 ? "disabled" : ""}></button>` +
`<span style="font-size:12px;color:#333;">${filterTotal} trovati · pag ${filterPage}/${filterTotalPages}</span>` +
`<span style="font-size:12px;color:#333;">${filterTotal} ${label} · pag ${filterPage}/${filterTotalPages}</span>` +
`<button type="button" class="btn btn-outline-secondary btn-sm" id="filterNextBtn" ${filterPage >= filterTotalPages ? "disabled" : ""}></button>`;
const go = pagerFn || applyServerFilter;
const prev = document.getElementById("filterPrevBtn");
const next = document.getElementById("filterNextBtn");
if (prev) prev.addEventListener("click", () => applyServerFilter(filterPage - 1));
if (next) next.addEventListener("click", () => applyServerFilter(filterPage + 1));
if (prev) prev.addEventListener("click", () => go(filterPage - 1));
if (next) next.addEventListener("click", () => go(filterPage + 1));
}
function restoreOriginal() {
@@ -128,6 +132,8 @@
return;
}
serverFiltered = true;
showingSelection = false;
pagerFn = applyServerFilter;
filterPage = json.page;
filterTotalPages = json.total_pages;
filterTotal = json.total;
@@ -140,6 +146,91 @@
}
}
// ── Mostra i SELEZIONATI (unione tra filtri diversi) ──────────────────
// La selezione si accumula tra filtri; questo carica dal server TUTTI i record
// selezionati (per id) e li mostra, paginati, a prescindere dai filtri correnti.
async function showSelectedRecords(page = 1) {
const ids = [...selected];
if (!ids.length) {
showingSelection = false;
updateToolbar();
return;
}
pagerFn = showSelectedRecords;
try {
const resp = await fetch("filter_records.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
template_id: parseInt(TEMPLATE_ID, 10),
all_users: SHOW_ALL,
importref: IMPORTREF,
status: "i",
ids: ids,
page: Math.max(1, page),
per_page: FILTER_PER_PAGE,
}),
});
const json = await resp.json();
if (!json.success) {
console.error("[gridFilter] mostra selezionati:", json.message);
return;
}
if (!originalData) originalData = [...data()];
showingSelection = true;
serverFiltered = true;
filterPage = json.page;
filterTotalPages = json.total_pages;
filterTotal = json.total;
swapData(json.rows || []);
updateFilterPager();
hidePagination(true);
updateToolbar();
} catch (e) {
console.error("[gridFilter] mostra selezionati fallita", e);
}
}
// Tumbler "Mostra selezionati" / "Torna al filtro".
function toggleShowSelected() {
if (!showingSelection) {
if (!selected.size) return;
showSelectedRecords(1);
} else {
exitSelectionView();
}
}
// Torna dal "mostra selezionati" al filtro corrente (o alla pagina originale).
function exitSelectionView() {
showingSelection = false;
pagerFn = applyServerFilter;
if (collectActiveFilters().length) {
applyServerFilter(1);
} else {
restoreOriginal();
}
updateToolbar();
}
// Deseleziona tutto.
function clearSelection() {
selected.clear();
document
.querySelectorAll("#gridRowContainer .grid-row.row-selected")
.forEach((el) => el.classList.remove("row-selected"));
document
.querySelectorAll(".filter-row-checkbox")
.forEach((cb) => (cb.checked = false));
const sa = document.getElementById("filterSelectAll");
if (sa) sa.checked = false;
if (showingSelection) {
exitSelectionView();
} else {
updateToolbar();
}
}
// "Seleziona tutti i filtrati": chiede al server TUTTI gli id del match e li seleziona.
async function selectAllMatching(on) {
if (!serverFiltered) return;
@@ -466,11 +557,15 @@
const cntEl = document.getElementById("filterSelCount");
if (cntEl) cntEl.textContent = count;
document.getElementById("filterDeleteBtn").disabled = count === 0;
document.getElementById("filterRestrictBtn").disabled =
count === 0 && !restricted;
document.getElementById("filterRestrictBtn").innerHTML = restricted
? '<i class="fas fa-eye"></i> Mostra tutti'
: '<i class="fas fa-compress"></i> Restringi selezione';
const showBtn = document.getElementById("filterRestrictBtn");
showBtn.disabled = count === 0 && !showingSelection;
showBtn.innerHTML = showingSelection
? '<i class="fas fa-eye"></i> Torna al filtro'
: '<i class="fas fa-list-check"></i> Mostra selezionati';
const clearSelBtn = document.getElementById("filterClearSelBtn");
if (clearSelBtn) clearSelBtn.disabled = count === 0;
}
// ── Main toggle ──
@@ -584,7 +679,8 @@
<span id="filterPager" style="display:none;align-items:center;gap:6px;"></span>
<button type="button" id="filterClearBtn" class="btn btn-outline-secondary btn-sm"><i class="fas fa-times"></i> Pulisci filtri</button>
<span style="font-size:12px;color:#555;">Selezionate: <strong id="filterSelCount">0</strong></span>
<button type="button" id="filterRestrictBtn" class="btn btn-outline-primary btn-sm"><i class="fas fa-compress"></i> Restringi selezione</button>
<button type="button" id="filterRestrictBtn" class="btn btn-outline-primary btn-sm"><i class="fas fa-list-check"></i> Mostra selezionati</button>
<button type="button" id="filterClearSelBtn" class="btn btn-outline-secondary btn-sm"><i class="fas fa-square"></i> Deseleziona</button>
<button type="button" id="filterDeleteBtn" class="btn btn-outline-danger btn-sm"><i class="fas fa-trash"></i> Elimina selezionati</button>
`;
fBtn.parentNode.insertBefore(bar, fBtn.nextSibling);
@@ -598,7 +694,10 @@
.addEventListener("click", batchDelete);
document
.getElementById("filterRestrictBtn")
.addEventListener("click", toggleRestrict);
.addEventListener("click", toggleShowSelected);
document
.getElementById("filterClearSelBtn")
.addEventListener("click", clearSelection);
}
// Svuota tutti i filtri di colonna (input + select) e torna alla pagina originale.