(() => { function init() { const table = document.querySelector('table[data-storage-key="software-jobs"]'); const master = document.getElementById('select-all-restartable-jobs'); const button = document.getElementById('restart-selected-jobs-button'); const form = document.getElementById('restart-selected-jobs-form'); const idContainer = document.getElementById('restart-selected-job-ids'); if (!table || !master || !button || !form || !idContainer) return; const boxes = () => [...table.querySelectorAll('tbody .software-job-restart-select:not(:disabled)')]; const isVisible = box => { const row = box.closest('tr'); return Boolean(row && !row.hidden && getComputedStyle(row).display !== 'none'); }; const visibleBoxes = () => boxes().filter(isVisible); const selectedBoxes = () => boxes().filter(box => box.checked && isVisible(box)); function update() { boxes().filter(box => !isVisible(box)).forEach(box => { box.checked = false; }); const visible = visibleBoxes(); const selected = selectedBoxes(); const count = selected.length; const baseLabel = button.dataset.baseLabel || button.textContent.trim(); button.disabled = count === 0; button.textContent = count > 0 ? `${baseLabel} (${count})` : baseLabel; master.disabled = visible.length === 0; master.checked = visible.length > 0 && count === visible.length; master.indeterminate = count > 0 && count < visible.length; } master.addEventListener('change', () => { visibleBoxes().forEach(box => { box.checked = master.checked; }); update(); }); table.addEventListener('change', event => { if (event.target.matches('.software-job-restart-select')) update(); }); button.addEventListener('click', () => { const selected = selectedBoxes(); if (!selected.length) return; const template = form.dataset.confirmTemplate || 'Restart {count} selected jobs?'; if (!window.confirm(template.replace('{count}', String(selected.length)))) return; idContainer.replaceChildren(); selected.forEach(box => { const input = document.createElement('input'); input.type = 'hidden'; input.name = 'job_ids'; input.value = box.value; idContainer.appendChild(input); }); form.requestSubmit(); }); const observer = new MutationObserver(update); table.querySelectorAll('tbody tr').forEach(row => { observer.observe(row, {attributes: true, attributeFilter: ['style', 'class', 'hidden']}); }); window.addEventListener('asset-table-filter-changed', event => { if (!event.detail?.table || event.detail.table === table) update(); }); window.addEventListener('software-job-status-changed', update); window.addEventListener('asset-table-content-reloaded', event => { if (event.detail?.table === table) update(); }); update(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init, {once: true}); } else { init(); } })();