|
|
|
|
@ -286,11 +286,6 @@
|
|
|
|
|
|
|
|
|
|
var btnMarkAllReviewed = document.getElementById('rcm_mark_all_reviewed');
|
|
|
|
|
|
|
|
|
|
// Shift multi-select support for the overview table.
|
|
|
|
|
// Works like file explorers: click a checkbox, then Shift+click another checkbox
|
|
|
|
|
// to toggle the full range in between.
|
|
|
|
|
var lastClickedIndex = null;
|
|
|
|
|
|
|
|
|
|
function statusClass(status) {
|
|
|
|
|
var s = (status || "").toString().toLowerCase();
|
|
|
|
|
|
|
|
|
|
@ -348,71 +343,65 @@
|
|
|
|
|
return ids.filter(function (x) { return Number.isFinite(x); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateSelectAllState() {
|
|
|
|
|
if (!selectAll) return;
|
|
|
|
|
var cbs = table.querySelectorAll('tbody .rc_row_cb');
|
|
|
|
|
var total = cbs.length;
|
|
|
|
|
var checked = 0;
|
|
|
|
|
cbs.forEach(function (cb) { if (cb.checked) checked++; });
|
|
|
|
|
|
|
|
|
|
if (total === 0) {
|
|
|
|
|
selectAll.checked = false;
|
|
|
|
|
selectAll.indeterminate = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
selectAll.checked = checked === total;
|
|
|
|
|
selectAll.indeterminate = checked > 0 && checked < total;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateButtons() {
|
|
|
|
|
var ids = getSelectedJobIds();
|
|
|
|
|
if (btnMark) btnMark.disabled = ids.length === 0;
|
|
|
|
|
if (btnUnmark) btnUnmark.disabled = ids.length === 0;
|
|
|
|
|
if (statusEl) statusEl.textContent = ids.length ? (ids.length + ' selected') : '';
|
|
|
|
|
|
|
|
|
|
updateSelectAllState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lastRowCheckbox = null;
|
|
|
|
|
|
|
|
|
|
if (selectAll) {
|
|
|
|
|
selectAll.addEventListener('change', function () {
|
|
|
|
|
var cbs = table.querySelectorAll('tbody .rc_row_cb');
|
|
|
|
|
cbs.forEach(function (cb) { cb.checked = selectAll.checked; });
|
|
|
|
|
selectAll.indeterminate = false;
|
|
|
|
|
updateButtons();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle Shift+click range selection on checkboxes.
|
|
|
|
|
// Shift-click multi select for row checkboxes (continuous range)
|
|
|
|
|
table.addEventListener('click', function (e) {
|
|
|
|
|
if (!e.target || !e.target.classList || !e.target.classList.contains('rc_row_cb')) return;
|
|
|
|
|
if (!(e.target && e.target.classList && e.target.classList.contains('rc_row_cb'))) return;
|
|
|
|
|
|
|
|
|
|
// Prevent row click handlers and stop the browser from doing text-range selection.
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
|
|
|
|
// If shift is held, apply the checkbox state to the whole range.
|
|
|
|
|
if (e.shiftKey && lastRowCheckbox && lastRowCheckbox !== e.target) {
|
|
|
|
|
var cbs = Array.prototype.slice.call(table.querySelectorAll('tbody .rc_row_cb'));
|
|
|
|
|
var idx = cbs.indexOf(e.target);
|
|
|
|
|
if (idx === -1) return;
|
|
|
|
|
var start = cbs.indexOf(lastRowCheckbox);
|
|
|
|
|
var end = cbs.indexOf(e.target);
|
|
|
|
|
|
|
|
|
|
if (e.shiftKey && lastClickedIndex !== null) {
|
|
|
|
|
var start = Math.min(lastClickedIndex, idx);
|
|
|
|
|
var end = Math.max(lastClickedIndex, idx);
|
|
|
|
|
var newState = e.target.checked;
|
|
|
|
|
for (var i = start; i <= end; i++) {
|
|
|
|
|
cbs[i].checked = newState;
|
|
|
|
|
if (start !== -1 && end !== -1) {
|
|
|
|
|
var min = Math.min(start, end);
|
|
|
|
|
var max = Math.max(start, end);
|
|
|
|
|
var state = e.target.checked;
|
|
|
|
|
|
|
|
|
|
for (var i = min; i <= max; i++) {
|
|
|
|
|
cbs[i].checked = state;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lastClickedIndex = idx;
|
|
|
|
|
lastRowCheckbox = e.target;
|
|
|
|
|
|
|
|
|
|
// Clear any accidental text selection caused by Shift-click.
|
|
|
|
|
try {
|
|
|
|
|
var sel = window.getSelection ? window.getSelection() : null;
|
|
|
|
|
if (sel && sel.removeAllRanges) sel.removeAllRanges();
|
|
|
|
|
} catch (err) {}
|
|
|
|
|
|
|
|
|
|
updateButtons();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Fallback: any checkbox change should still update the buttons.
|
|
|
|
|
table.addEventListener('change', function (e) {
|
|
|
|
|
if (e.target && e.target.classList && e.target.classList.contains('rc_row_cb')) {
|
|
|
|
|
updateButtons();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Initialize select-all state on page load.
|
|
|
|
|
updateButtons();
|
|
|
|
|
|
|
|
|
|
function postJson(url, body) {
|
|
|
|
|
return fetch(url, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|