Comment-only tidy from the feng-shui audit — no code behavior changes. The features/ directory was renamed to components/ during modularization, but several header banners and inline comments still named the old path: - 6 component module headers (admin/tasks/backup/dashboard/updater/index.js + updater/js/updater-page.js) now name their real components/<id>/… path - core/kernel/js/spa.js + core/tasks/js/task-router.js comments - backend/routes/features.js doc-banner (drop a components/<id>/ folder …) - core/update-notifier/css/update-notifier.css header (js/update-notifier.js) Guarded the rewrite so the LIVE /api/features/list endpoint name (feature- registry.js sources + backend route) is untouched — only stale 'features/<path>' directory references were updated. Signed-off-by: librelad <librelad@digitalangels.vip>
46 lines
2.0 KiB
JavaScript
46 lines
2.0 KiB
JavaScript
// components/tasks/index.js — the Tasks page as a feature module.
|
|
//
|
|
// window.tasksManager is a system-loader singleton (its "task-system" component
|
|
// loads all task scripts, starts the shared SSE bus, then news TasksManager).
|
|
// So mount() does NOT new it or load scripts — it renders the fragment and
|
|
// re-inits the view, exactly like the old handleTasks(). unmount() releases
|
|
// only this view's per-mount leaks (the 30s auto-refresh interval + open log
|
|
// streams); it must never stop the shared taskEventBus or null the singleton.
|
|
LP.features.register({
|
|
id: 'tasks',
|
|
routes: ['/tasks', '/tasks*'],
|
|
|
|
async mount(ctx) {
|
|
const html = await ctx.loadFragment('/components/tasks/html/tasks-content.html');
|
|
ctx.setContent(html, 'Tasks');
|
|
|
|
if (window.tasksManager) {
|
|
await window.tasksManager.init();
|
|
} else {
|
|
// Don't throw — matches handleTasks: the page still renders, task
|
|
// functionality is just limited until the task-system component is ready.
|
|
console.warn('TasksManager not available yet, task functionality will be limited');
|
|
}
|
|
},
|
|
|
|
async unmount() {
|
|
const tm = window.tasksManager;
|
|
// The one per-view leak init() opens: the 30s auto-refresh interval stored
|
|
// on the singleton. Each init() recreates it, so clearing here is idempotent.
|
|
if (tm && tm.refreshInterval) {
|
|
clearInterval(tm.refreshInterval);
|
|
tm.refreshInterval = null;
|
|
}
|
|
// Stop any open per-task log streams this view started (each removes its own
|
|
// SSE listeners + map entry). Snapshot keys first — stopLogStreaming mutates
|
|
// the map. Does NOT touch the shared bus.
|
|
if (tm && tm.activeLogStreams && typeof tm.stopLogStreaming === 'function') {
|
|
for (const id of Array.from(tm.activeLogStreams.keys())) {
|
|
try { tm.stopLogStreaming(id); } catch (_) {}
|
|
}
|
|
}
|
|
// DO NOT: stop window.taskEventBus (shared SSE singleton), remove the
|
|
// singleton's once-bound task listeners, or null window.tasksManager.
|
|
},
|
|
});
|