Filter menus: None first, documented picks; Custom View drag preview
- Fix: sorting a software column stopped its filter listing apps individually (the sort arrow written into the header changed the label used to recognise list columns) - "None" (nothing missing) is pinned to the top of the value list, so the easy devices are one click away - Software columns get "Documented" / "Undocumented" quick picks that tick only apps with / without a knowledge-base article; documented apps are marked in the list - Custom View: remove Reset Filters / Reset Sort (Clear filters and the column menus replace them); old saved filters are cleared since nothing else could clear them - Custom View column drag: a ghost of the column follows the cursor, the column being moved is dimmed, and a line shows where it will land
This commit is contained in:
1 parent
318c59e610
commit
973ff592a4
4 files changed
+149
-5
No files matched your search
@@ -142,6 +142,67 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Custom View column drag: a ghost of the column follows the cursor, the column being
|
||||
// moved is dimmed, and a line shows exactly where it will land. Adds to the dashboard's
|
||||
// own drag-and-drop (attachColDragHandlers), which still performs the move.
|
||||
function enhanceColumnDrag() {
|
||||
const table = document.getElementById('table-custom');
|
||||
const host = document.getElementById('custom-table-host');
|
||||
if (!table || !host) return;
|
||||
const headers = Array.from(table.querySelectorAll('thead th.custom-th'));
|
||||
let from = null, marker = null;
|
||||
|
||||
const setDimmed = (idx, on) => {
|
||||
for (const row of table.rows) { const c = row.cells[idx]; if (c) c.classList.toggle('col-moving', on); }
|
||||
};
|
||||
const clear = () => {
|
||||
if (from !== null) setDimmed(from, false);
|
||||
if (marker) marker.remove();
|
||||
marker = null; from = null;
|
||||
};
|
||||
|
||||
headers.forEach((th, idx) => {
|
||||
const grip = th.querySelector('.col-grip');
|
||||
if (!grip || grip.dataset.ghost) return;
|
||||
grip.dataset.ghost = '1';
|
||||
|
||||
grip.addEventListener('dragstart', e => {
|
||||
from = idx;
|
||||
const ghost = document.createElement('div');
|
||||
ghost.className = 'col-drag-ghost';
|
||||
const head = document.createElement('div');
|
||||
head.className = 'col-drag-ghost-head';
|
||||
head.textContent = th.querySelector('.label-text') ? th.querySelector('.label-text').textContent : th.textContent.trim();
|
||||
ghost.appendChild(head);
|
||||
Array.from(table.tBodies[0].rows).filter(r => r.style.display !== 'none').slice(0, 7).forEach(r => {
|
||||
const cell = document.createElement('div');
|
||||
cell.className = 'col-drag-ghost-cell';
|
||||
cell.textContent = r.cells[idx] ? r.cells[idx].textContent.trim() : '';
|
||||
ghost.appendChild(cell);
|
||||
});
|
||||
ghost.style.width = Math.min(280, Math.max(140, th.getBoundingClientRect().width)) + 'px';
|
||||
document.body.appendChild(ghost);
|
||||
try { e.dataTransfer.setDragImage(ghost, 24, 18); } catch (_) {}
|
||||
setTimeout(() => ghost.remove(), 0);
|
||||
setDimmed(idx, true);
|
||||
});
|
||||
grip.addEventListener('dragend', clear);
|
||||
|
||||
th.addEventListener('dragover', () => {
|
||||
if (from === null) return;
|
||||
if (!marker) { marker = document.createElement('div'); marker.className = 'col-drop-marker'; host.appendChild(marker); }
|
||||
// moveCustomColumn(from, to) lands the column after the target when moving right,
|
||||
// before it when moving left
|
||||
const hostBox = host.getBoundingClientRect(), box = th.getBoundingClientRect();
|
||||
const x = (idx > from ? box.right : box.left) - hostBox.left;
|
||||
marker.style.left = (x - 2) + 'px';
|
||||
marker.style.height = table.getBoundingClientRect().height + 'px';
|
||||
marker.hidden = idx === from;
|
||||
});
|
||||
th.addEventListener('drop', clear);
|
||||
});
|
||||
}
|
||||
|
||||
let queued = false;
|
||||
function run() {
|
||||
queued = false;
|
||||
@@ -164,6 +225,12 @@
|
||||
// Groups and pages are shown by toggling display (not a DOM change), so also
|
||||
// re-measure as the user scrolls; writes only happen when a value changes.
|
||||
window.addEventListener('scroll', schedule, { passive: true });
|
||||
// Custom View rebuilds its header (and re-attaches drag handlers) on every render
|
||||
if (typeof window.attachColDragHandlers === 'function') {
|
||||
const origDrag = window.attachColDragHandlers;
|
||||
window.attachColDragHandlers = function () { const r = origDrag.apply(this, arguments); enhanceColumnDrag(); return r; };
|
||||
enhanceColumnDrag();
|
||||
}
|
||||
// Page switches show and hide pages without changing the DOM
|
||||
if (typeof window.switchPage === 'function') {
|
||||
const orig = window.switchPage;
|
||||
|
||||
Reference in new issue
Block a user