feat: service categories end-to-end + monitoring widgets on main dashboard
Service categories (described in README roadmap, never wired): - Backend: POST /services now persists category/containerId/port/ip/tailscaleOnly - Backend: POST /services/update accepts category for in-place changes - Frontend: category <select> in add-service modal (local + external) - Frontend: category <select> in edit-service modal with current value - Frontend: All Categories dropdown in service filter bar (auto-populated from both API categories and any categories present on rendered cards) - Frontend: colored category badge (icon + name) on service cards - Frontend: filter auto-refreshes after buildGrid Monitoring on main dashboard (replaces orphaned monitoring-dashboard.html): - New monitoring-widgets.js embeds a 5-card System Overview panel above the filter bar: Services, Containers Up, Avg CPU, Avg Memory, Health - Pulls /api/v1/monitoring/stats + /api/v1/health-checks/status - Auto-refreshes on DC.POLL.STATS (5s), color-coded bars (warn >=65%, bad >=85%) Build: - Added monitoring-widgets.js to init.js bundle in build.js - Rebuilt dist/ bundles (core.js, features.js, init.js) - sw.js cache version bumped automatically - CSP hash regenerated
This commit is contained in:
@@ -19,6 +19,16 @@
|
||||
document.getElementById('edit-tailscale-only').checked = service.tailscaleOnly || false;
|
||||
document.getElementById('edit-logo-url').value = service.logo || '';
|
||||
|
||||
// Populate the category select for this service, then set the current value.
|
||||
// populateCategorySelects() uses data-current so we set it first, then call.
|
||||
const categorySelect = document.getElementById('edit-service-category');
|
||||
if (categorySelect) {
|
||||
categorySelect.dataset.current = service.category || '';
|
||||
if (typeof window.populateCategorySelects === 'function') {
|
||||
window.populateCategorySelects();
|
||||
}
|
||||
}
|
||||
|
||||
modal.classList.add('show');
|
||||
}
|
||||
|
||||
@@ -36,6 +46,7 @@
|
||||
const newIp = document.getElementById('edit-ip').value.trim() || 'localhost';
|
||||
const tailscaleOnly = document.getElementById('edit-tailscale-only').checked;
|
||||
const newLogo = document.getElementById('edit-logo-url').value.trim();
|
||||
const newCategory = document.getElementById('edit-service-category')?.value || '';
|
||||
|
||||
if (!newSubdomain) {
|
||||
showNotification('Subdomain is required', 'warning');
|
||||
@@ -51,6 +62,7 @@
|
||||
if (newIp !== currentEditService.ip) changes.push('ip');
|
||||
if (tailscaleOnly !== (currentEditService.tailscaleOnly || false)) changes.push('tailscale');
|
||||
if (newLogo && newLogo !== currentEditService.logo) changes.push('logo');
|
||||
if (newCategory !== (currentEditService.category || '')) changes.push('category');
|
||||
|
||||
if (changes.length === 0) {
|
||||
closeServiceEditModal();
|
||||
@@ -72,7 +84,8 @@
|
||||
port: newPort || currentEditService.port,
|
||||
ip: newIp,
|
||||
tailscaleOnly,
|
||||
logo: newLogo || undefined
|
||||
logo: newLogo || undefined,
|
||||
category: newCategory
|
||||
})
|
||||
});
|
||||
|
||||
@@ -91,7 +104,8 @@
|
||||
port: newPort || window.APPS[appIndex].port,
|
||||
ip: newIp,
|
||||
tailscaleOnly,
|
||||
logo: newLogo || window.APPS[appIndex].logo
|
||||
logo: newLogo || window.APPS[appIndex].logo,
|
||||
category: newCategory || undefined
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user