- Service Filter Bar: search by name, filter by status (online/offline) - Batch Operations: multi-select containers for start/stop/restart - Container Snapshots: create and manage Docker checkpoints - Added filter bar and batch action bar to index.html - Added snapshot button to Admin tools section - New JS modules: service-filter.js, batch-operations.js, snapshot.js - Updated build.js to include new modules in bundle
58 lines
1.8 KiB
JavaScript
58 lines
1.8 KiB
JavaScript
// ========== SERVICE FILTER ==========
|
|
(function() {
|
|
const searchInput = document.getElementById('service-filter-search');
|
|
const statusSelect = document.getElementById('service-filter-status');
|
|
const countSpan = document.getElementById('service-filter-count');
|
|
|
|
function updateFilter() {
|
|
const query = searchInput.value.toLowerCase().trim();
|
|
const statusFilter = statusSelect.value; // 'all', 'on', or 'off'
|
|
|
|
const cards = document.querySelectorAll('#cards .card');
|
|
let visibleCount = 0;
|
|
|
|
cards.forEach(card => {
|
|
const name = card.querySelector('.name')?.textContent?.toLowerCase() || '';
|
|
const app = card.dataset.app?.toLowerCase() || '';
|
|
const status = card.dataset.status || 'off'; // 'on' or 'off'
|
|
|
|
const matchesSearch = !query || name.includes(query) || app.includes(query);
|
|
const matchesStatus = statusFilter === 'all' || status === statusFilter;
|
|
|
|
if (matchesSearch && matchesStatus) {
|
|
card.style.display = '';
|
|
visibleCount++;
|
|
} else {
|
|
card.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
if (countSpan) {
|
|
const total = cards.length;
|
|
countSpan.textContent = `${visibleCount} of ${total} services`;
|
|
}
|
|
}
|
|
|
|
// Debounce helper
|
|
function debounce(fn, delay) {
|
|
let timeout;
|
|
return function(...args) {
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(() => fn.apply(this, args), delay);
|
|
};
|
|
}
|
|
|
|
searchInput?.addEventListener('input', debounce(updateFilter, 200));
|
|
statusSelect?.addEventListener('change', updateFilter);
|
|
|
|
// Initial count on page load
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => setTimeout(updateFilter, 500));
|
|
} else {
|
|
setTimeout(updateFilter, 500);
|
|
}
|
|
|
|
// Expose for external triggers
|
|
window.refreshServiceFilter = updateFilter;
|
|
})();
|