union ids
This commit is contained in:
@@ -28,6 +28,60 @@ $wantAllIds = !empty($body['want_all_ids']);
|
|||||||
|
|
||||||
$cacheDir = __DIR__ . '/cache';
|
$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 = [
|
$fixedAliasMap = [
|
||||||
'ClienteResponsabile' => 'cliente_responsabile_id',
|
'ClienteResponsabile' => 'cliente_responsabile_id',
|
||||||
'ClienteFornitore' => 'cliente_fornitore_id',
|
'ClienteFornitore' => 'cliente_fornitore_id',
|
||||||
|
|||||||
+109
-10
@@ -39,6 +39,8 @@
|
|||||||
let filterTotal = 0;
|
let filterTotal = 0;
|
||||||
let originalData = null; // snapshot della pagina originale (per ripristino)
|
let originalData = null; // snapshot della pagina originale (per ripristino)
|
||||||
let filterReqSeq = 0;
|
let filterReqSeq = 0;
|
||||||
|
let showingSelection = false; // true quando mostriamo l'UNIONE dei selezionati
|
||||||
|
let pagerFn = null; // paginazione corrente (applyServerFilter | showSelectedRecords)
|
||||||
|
|
||||||
function collectActiveFilters() {
|
function collectActiveFilters() {
|
||||||
const cols = meta().columns || [];
|
const cols = meta().columns || [];
|
||||||
@@ -77,14 +79,16 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
el.style.display = "inline-flex";
|
el.style.display = "inline-flex";
|
||||||
|
const label = showingSelection ? "selezionati" : "trovati";
|
||||||
el.innerHTML =
|
el.innerHTML =
|
||||||
`<button type="button" class="btn btn-outline-secondary btn-sm" id="filterPrevBtn" ${filterPage <= 1 ? "disabled" : ""}>‹</button>` +
|
`<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>`;
|
`<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 prev = document.getElementById("filterPrevBtn");
|
||||||
const next = document.getElementById("filterNextBtn");
|
const next = document.getElementById("filterNextBtn");
|
||||||
if (prev) prev.addEventListener("click", () => applyServerFilter(filterPage - 1));
|
if (prev) prev.addEventListener("click", () => go(filterPage - 1));
|
||||||
if (next) next.addEventListener("click", () => applyServerFilter(filterPage + 1));
|
if (next) next.addEventListener("click", () => go(filterPage + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function restoreOriginal() {
|
function restoreOriginal() {
|
||||||
@@ -128,6 +132,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
serverFiltered = true;
|
serverFiltered = true;
|
||||||
|
showingSelection = false;
|
||||||
|
pagerFn = applyServerFilter;
|
||||||
filterPage = json.page;
|
filterPage = json.page;
|
||||||
filterTotalPages = json.total_pages;
|
filterTotalPages = json.total_pages;
|
||||||
filterTotal = json.total;
|
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.
|
// "Seleziona tutti i filtrati": chiede al server TUTTI gli id del match e li seleziona.
|
||||||
async function selectAllMatching(on) {
|
async function selectAllMatching(on) {
|
||||||
if (!serverFiltered) return;
|
if (!serverFiltered) return;
|
||||||
@@ -466,11 +557,15 @@
|
|||||||
const cntEl = document.getElementById("filterSelCount");
|
const cntEl = document.getElementById("filterSelCount");
|
||||||
if (cntEl) cntEl.textContent = count;
|
if (cntEl) cntEl.textContent = count;
|
||||||
document.getElementById("filterDeleteBtn").disabled = count === 0;
|
document.getElementById("filterDeleteBtn").disabled = count === 0;
|
||||||
document.getElementById("filterRestrictBtn").disabled =
|
|
||||||
count === 0 && !restricted;
|
const showBtn = document.getElementById("filterRestrictBtn");
|
||||||
document.getElementById("filterRestrictBtn").innerHTML = restricted
|
showBtn.disabled = count === 0 && !showingSelection;
|
||||||
? '<i class="fas fa-eye"></i> Mostra tutti'
|
showBtn.innerHTML = showingSelection
|
||||||
: '<i class="fas fa-compress"></i> Restringi selezione';
|
? '<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 ──
|
// ── Main toggle ──
|
||||||
@@ -584,7 +679,8 @@
|
|||||||
<span id="filterPager" style="display:none;align-items:center;gap:6px;"></span>
|
<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>
|
<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>
|
<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>
|
<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);
|
fBtn.parentNode.insertBefore(bar, fBtn.nextSibling);
|
||||||
@@ -598,7 +694,10 @@
|
|||||||
.addEventListener("click", batchDelete);
|
.addEventListener("click", batchDelete);
|
||||||
document
|
document
|
||||||
.getElementById("filterRestrictBtn")
|
.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.
|
// Svuota tutti i filtri di colonna (input + select) e torna alla pagina originale.
|
||||||
|
|||||||
Reference in New Issue
Block a user