Migrate frontend from monolithic app.js to vanilla ES modules
Build and Push Docker Image / build (push) Successful in 35s
Licence Check / Licence compatibility and copyright header verification (push) Failing after 49s
CI / Security audit (push) Successful in 1m9s
CI / Tests & coverage (push) Successful in 1m23s

- Delete React files (App.jsx, main.jsx, App.css)
- Create modular vanilla JS structure in client/src/:
  - state.js (global state object)
  - api.js (all fetch calls)
  - sse.js (SSE connection management)
  - ui/auth.js (authentication UI)
  - ui/downloads.js (downloads rendering)
  - ui/history.js (history section)
  - ui/statusPanel.js (status panel)
  - ui/webhooks.js (webhook management)
  - ui/filters.js (download client filter)
  - ui/theme.js (theme switching)
  - ui/tabs.js (tab navigation)
  - utils/format.js (formatting utilities)
  - utils/storage.js (localStorage helpers)
  - main.js (DOMContentLoaded bootstrap)
- Update vite.config.js for vanilla build outputting to ../public/app.js
- Build succeeds: 14 modules, 43.88 kB output
This commit is contained in:
2026-05-20 23:30:24 +01:00
parent a38fc4a8ce
commit 8dc105ff3e
19 changed files with 2173 additions and 2854 deletions
+62
View File
@@ -0,0 +1,62 @@
// Copyright (c) 2026 Gordon Bolton. MIT License.
// Bootstrap - wire all event handlers on DOMContentLoaded
import { checkAuthenticationAndInit, handleLogin, handleLogoutClick } from './ui/auth.js';
import { initDownloadClientFilter } from './ui/filters.js';
import { initHistoryControls } from './ui/history.js';
import { toggleStatusPanel } from './ui/statusPanel.js';
import { initWebhooks } from './ui/webhooks.js';
import { initThemeSwitcher } from './ui/theme.js';
import { initTabs, goHome } from './ui/tabs.js';
import { handleShowAllToggle } from './sse.js';
import { loadAppVersion } from './api.js';
document.addEventListener('DOMContentLoaded', () => {
// Login form
const loginForm = document.getElementById('login-form');
if (loginForm) {
loginForm.addEventListener('submit', handleLogin);
}
// Logout button
const logoutBtn = document.getElementById('logout-btn');
if (logoutBtn) {
logoutBtn.addEventListener('click', handleLogoutClick);
}
// Show all toggle
const showAllToggle = document.getElementById('show-all-toggle');
if (showAllToggle) {
showAllToggle.addEventListener('change', (e) => handleShowAllToggle(e.target.checked));
}
// Status panel toggle
const statusToggle = document.getElementById('status-toggle');
if (statusToggle) {
statusToggle.addEventListener('click', toggleStatusPanel);
}
// Home button
const homeBtn = document.getElementById('home-btn');
if (homeBtn) {
homeBtn.addEventListener('click', goHome);
}
// Initialize UI components
initThemeSwitcher();
initTabs();
initDownloadClientFilter();
initHistoryControls();
initWebhooks();
// Load app version
loadAppVersion().then(version => {
const versionEl = document.getElementById('app-version');
if (versionEl && version) {
versionEl.textContent = 'v' + version;
}
});
// Check authentication and initialize
checkAuthenticationAndInit();
});