Both found in a user's console log. 1. ReferenceError: setupMobileMenu is not defined (dashboard.js:98) core/topbar/js/mobile-menu.js defines that global, and index.html never loaded it. dashboard.js called it unguarded as the FIRST line of setupEventListeners, so dashboard init threw every page load and took loadInstalledApps() with it — and the burger menu was dead on mobile. system-loader already guarded its own call with a typeof check, which is why this survived unnoticed. Loads the script (before dashboard.js) and guards the call, so optional nav chrome can never take down the page below it again. 2. Endless 404s on /api/tasks/<id> for tasks that no longer exist queue.json is append-only from the enqueue side and nothing ever pruned it, so any task file removed afterwards left an id the WebUI re-fetched forever, one 404 per poll per orphan. Adds cleanupOrphanQueueEntries to the idle housekeeping pass: entries with no task file are dropped and logged. Self-heals existing strays. (Provoked by my own clean-up of two test tasks earlier in this session, but the gap is real and predates it.) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
137 lines
7.2 KiB
HTML
Executable File
137 lines
7.2 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>LibrePortal - Modern Docker Management</title>
|
|
|
|
<link rel="icon" type="image/svg+xml" href="/core/icons/libreportal.svg">
|
|
<link rel="icon" type="image/x-icon" href="/core/icons/favicon.ico" sizes="any">
|
|
<link rel="apple-touch-icon" href="/core/icons/libreportal.svg">
|
|
|
|
<!-- Styles -->
|
|
<!-- Base token layer (theme-agnostic): --font-mono, --page-* identity hues -->
|
|
<link rel="stylesheet" href="/core/theme/css/tokens.css">
|
|
<link rel="stylesheet" href="/core/theme/css/themes.css">
|
|
<link rel="stylesheet" href="/core/loading/css/loading-screen.css">
|
|
<link rel="stylesheet" href="/core/setup/css/setup-wizard.css">
|
|
<link rel="stylesheet" href="/core/theme/css/base.css">
|
|
<link rel="stylesheet" href="/components/admin/config/css/ip-whitelist.css">
|
|
<link rel="stylesheet" href="/components/apps/port-manager/css/port-manager.css">
|
|
<link rel="stylesheet" href="/components/backup/core/css/backup.css">
|
|
<link rel="stylesheet" href="/components/admin/ssh/css/ssh.css">
|
|
<link rel="stylesheet" href="/components/admin/core/css/admin.css">
|
|
<link rel="stylesheet" href="/components/apps/services/css/services.css">
|
|
<link rel="stylesheet" href="/core/overlays/css/modal.css">
|
|
<link rel="stylesheet" href="/components/apps/tools/css/tools.css">
|
|
<link rel="stylesheet" href="/components/apps/routing/css/routing.css">
|
|
<link rel="stylesheet" href="/core/boot/auth/css/login.css">
|
|
<link rel="stylesheet" href="/core/theme/css/aurora-background.css">
|
|
<link rel="stylesheet" href="/core/topbar/css/topbar.css">
|
|
<link rel="stylesheet" href="/core/topbar/css/sidebar.css">
|
|
<link rel="stylesheet" href="/components/apps/core/css/apps-layout.css">
|
|
<link rel="stylesheet" href="/components/apps/core/css/apps.css">
|
|
<link rel="stylesheet" href="/components/apps/overview/css/overview.css">
|
|
<link rel="stylesheet" href="/core/forms/css/forms.css">
|
|
<link rel="stylesheet" href="/core/forms/css/config.css">
|
|
<link rel="stylesheet" href="/components/apps/core/css/service-buttons.css">
|
|
<link rel="stylesheet" href="/components/dashboard/css/dashboard.css">
|
|
<link rel="stylesheet" href="/components/tasks/css/tasks.css">
|
|
<link rel="stylesheet" href="/components/updater/css/updater.css">
|
|
<link rel="stylesheet" href="/core/update-notifier/css/update-notifier.css">
|
|
<link rel="stylesheet" href="/core/network-notifier/css/network-notifier.css">
|
|
<link rel="stylesheet" href="/core/health-notifier/css/health-notifier.css">
|
|
<script>
|
|
// Inline data-theme bootstrap — runs before any rendering so the right
|
|
// palette tokens resolve on first paint. Synchronously injects a
|
|
// <link> to the saved theme's CSS (which lives at
|
|
// /themes/<name>/theme.css) so even the very first frame paints with
|
|
// the correct palette. ThemeRegistry below additionally <link>s every
|
|
// discovered theme so the dropdown can switch between them without
|
|
// another fetch.
|
|
(function () {
|
|
var legacy = localStorage.getItem('selectedTheme');
|
|
if (legacy && !localStorage.getItem('theme')) localStorage.setItem('theme', legacy);
|
|
if (legacy) localStorage.removeItem('selectedTheme');
|
|
var theme = localStorage.getItem('theme');
|
|
if (theme === 'dark' || theme === 'blue') theme = 'dark-blue';
|
|
if (!theme) theme = 'nebula';
|
|
localStorage.setItem('theme', theme);
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
|
|
// Synchronous <link> injection. Inserted via document.write so the
|
|
// parser blocks on this stylesheet — guarantees first paint has
|
|
// the palette tokens defined. Marked with data-theme-css="<name>"
|
|
// so ThemeRegistry can detect and skip duplicates.
|
|
document.write(
|
|
'<link rel="stylesheet" href="/themes/' + theme +
|
|
'/theme.css" data-theme-css="' + theme + '">'
|
|
);
|
|
})();
|
|
</script>
|
|
<script src="/core/theme/js/theme-registry.js"></script>
|
|
<script src="/core/forms/js/custom-select.js"></script>
|
|
<script src="/core/forms/js/custom-number.js"></script>
|
|
</head>
|
|
<body>
|
|
<!-- Topbar Container -->
|
|
<div id="topbar-container">
|
|
<!-- Topbar will be loaded here -->
|
|
</div>
|
|
|
|
<!-- Main Content Container -->
|
|
<main id="main-content" class="main">
|
|
<div id="app-content">
|
|
<!-- App content will be loaded here -->
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Scripts -->
|
|
<!-- Auth must load first — gates all other initialization -->
|
|
<script src="/core/boot/auth/js/auth-manager.js"></script>
|
|
<!-- Essential Bootstrap -->
|
|
<!-- LpUi runs first so body.lp-ui--advanced / lp-ui--dev are set
|
|
before any page/component renders → no FOUC of advanced sections. -->
|
|
<script src="/core/ui-mode/js/lp-ui.js"></script>
|
|
<script src="/core/dom/js/dom-helpers.js"></script>
|
|
<script src="/core/app-meta/js/app-helpers.js"></script>
|
|
<script src="/core/data-loader/js/data-loader.js"></script>
|
|
<script src="/core/live/js/live-system.js"></script>
|
|
<script src="/core/ui-state/js/dismissible.js"></script>
|
|
<script src="/core/overlays/js/eo-modal.js"></script>
|
|
<script src="/core/tasks/js/task-refresh-coordinator.js"></script>
|
|
<!-- Defines the global setupMobileMenu(), which dashboard.js calls from
|
|
setupEventListeners() and system-loader registers as a component. It was
|
|
never loaded here, so dashboard init died on a ReferenceError at that
|
|
call — taking loadInstalledApps() with it — and the burger menu was dead
|
|
on mobile. Must come before dashboard.js. -->
|
|
<script src="/core/topbar/js/mobile-menu.js"></script>
|
|
<script src="/components/dashboard/js/dashboard.js"></script>
|
|
<script src="/core/boot/js/system-loader.js"></script>
|
|
<script src="/core/loading/js/loading-ui.js"></script>
|
|
<script src="/core/setup/js/setup-detector.js"></script>
|
|
<script src="/core/setup/js/setup-wizard.js"></script>
|
|
<script src="/core/setup/js/setup-completion-watcher.js"></script>
|
|
<script src="/core/boot/js/system-orchestrator.js"></script>
|
|
<!-- Feature-module kernel. Currently passive: defines window.LP.features and
|
|
loads the page manifest; spa.js consults it for routing. See
|
|
docs/architecture/webui-architecture.md. -->
|
|
<script src="/core/kernel/js/feature-registry.js"></script>
|
|
<script src="/core/kernel/js/services.js"></script>
|
|
<script src="/core/kernel/js/lifecycle.js"></script>
|
|
<!-- Component (page) modules are NOT listed here: the kernel loads each one's
|
|
self-registering index.js from the manifest (components/manifest.dev.json)
|
|
before routing. Adding a page = drop a components/<id>/ folder + a manifest
|
|
entry, no index.html edit. Heavy controllers stay lazy (loaded by mount). -->
|
|
<!--
|
|
Page-specific controllers are loaded on demand by spa.js / config-manager.js
|
|
when the user navigates to the relevant route. Keeping them out of the
|
|
initial <script> block trims ~200 KB raw (~50 KB gzipped) off the cold-load
|
|
cost AND avoids parsing them up front on the dashboard, which most users
|
|
land on. Each handler's loadScript() call is idempotent — subsequent
|
|
navigations to the same route are free.
|
|
-->
|
|
<script src="/core/kernel/js/spa.js"></script>
|
|
</body>
|
|
</html>
|