f2b44f65af
- Fix undefined variable references in handleLogoutClick - Use state.statusRefreshHandle instead of statusRefreshHandle - Use state.currentUser instead of currentUser
177 lines
5.8 KiB
JavaScript
177 lines
5.8 KiB
JavaScript
// Copyright (c) 2026 Gordon Bolton. MIT License.
|
|
|
|
import { state, SPLASH_MIN_MS } from '../state.js';
|
|
import { checkAuthentication, handleLogin as apiHandleLogin, handleLogout as apiHandleLogout } from '../api.js';
|
|
import { startSSE, stopSSE } from '../sse.js';
|
|
import { stopHistoryRefresh, clearHistory, startHistoryRefresh } from './history.js';
|
|
import { closeStatusPanel } from './statusPanel.js';
|
|
|
|
export function fadeOutLogin() {
|
|
return new Promise(resolve => {
|
|
const login = document.getElementById('login-container');
|
|
login.classList.add('fade-out');
|
|
login.addEventListener('transitionend', () => {
|
|
login.classList.add('hidden');
|
|
login.classList.remove('fade-out');
|
|
resolve();
|
|
}, { once: true });
|
|
});
|
|
}
|
|
|
|
export function showSplash() {
|
|
const splash = document.getElementById('splash-screen');
|
|
splash.classList.remove('hidden');
|
|
splash.style.opacity = '1';
|
|
splash.classList.remove('fade-out');
|
|
}
|
|
|
|
export function dismissSplash(startTime) {
|
|
return new Promise(resolve => {
|
|
const elapsed = Date.now() - (startTime || 0);
|
|
const remaining = Math.max(0, SPLASH_MIN_MS - elapsed);
|
|
setTimeout(() => {
|
|
const splash = document.getElementById('splash-screen');
|
|
splash.classList.add('fade-out');
|
|
// Fallback: resolve after transition duration + buffer in case
|
|
// transitionend never fires (e.g. display was toggled in same frame)
|
|
const TRANSITION_MS = 400;
|
|
const fallback = setTimeout(() => {
|
|
splash.classList.add('hidden');
|
|
resolve();
|
|
}, TRANSITION_MS + 100);
|
|
splash.addEventListener('transitionend', () => {
|
|
clearTimeout(fallback);
|
|
splash.classList.add('hidden');
|
|
resolve();
|
|
}, { once: true });
|
|
}, remaining);
|
|
});
|
|
}
|
|
|
|
export async function checkAuthenticationAndInit() {
|
|
const splashStart = Date.now();
|
|
try {
|
|
const result = await checkAuthentication();
|
|
if (result.authenticated) {
|
|
showDashboard();
|
|
showLoading();
|
|
startSSE();
|
|
await dismissSplash(splashStart);
|
|
} else {
|
|
await dismissSplash(splashStart);
|
|
showLogin();
|
|
}
|
|
} catch (err) {
|
|
console.error('Authentication check failed:', err);
|
|
await dismissSplash(splashStart);
|
|
showLogin();
|
|
}
|
|
}
|
|
|
|
export async function handleLogin(e) {
|
|
e.preventDefault();
|
|
|
|
const username = document.getElementById('username').value;
|
|
const password = document.getElementById('password').value;
|
|
const rememberMe = document.getElementById('remember-me').checked;
|
|
|
|
try {
|
|
const result = await apiHandleLogin(username, password, rememberMe);
|
|
|
|
if (result.success) {
|
|
// Fade out login, then show splash while opening SSE stream.
|
|
// requestAnimationFrame ensures the browser paints the splash at
|
|
// opacity:1 before dismissSplash adds fade-out, so the CSS
|
|
// transition fires and transitionend is guaranteed.
|
|
await fadeOutLogin();
|
|
showSplash();
|
|
await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
|
|
showDashboard();
|
|
showLoading();
|
|
const splashStart = Date.now();
|
|
startSSE();
|
|
await dismissSplash(splashStart);
|
|
} else {
|
|
showLoginError(result.error || 'Login failed');
|
|
}
|
|
} catch (err) {
|
|
showLoginError('Login failed. Please try again.');
|
|
console.error(err);
|
|
}
|
|
}
|
|
|
|
export async function handleLogoutClick() {
|
|
try {
|
|
stopSSE();
|
|
stopHistoryRefresh();
|
|
if (state.statusRefreshHandle) { clearInterval(state.statusRefreshHandle); state.statusRefreshHandle = null; }
|
|
await apiHandleLogout();
|
|
state.currentUser = null;
|
|
clearHistory();
|
|
showLogin();
|
|
} catch (err) {
|
|
console.error('Logout failed:', err);
|
|
}
|
|
}
|
|
|
|
export function showLogin() {
|
|
document.getElementById('login-container').classList.remove('hidden');
|
|
document.getElementById('dashboard-container').classList.add('hidden');
|
|
hideLoginError();
|
|
}
|
|
|
|
export function showDashboard() {
|
|
document.getElementById('login-container').classList.add('hidden');
|
|
document.getElementById('dashboard-container').classList.remove('hidden');
|
|
document.getElementById('currentUser').textContent = state.currentUser.name || '-';
|
|
// Always start with status panel hidden (guards against stale display value on re-login)
|
|
const sp = document.getElementById('status-panel');
|
|
sp.classList.add('hidden');
|
|
// Also hide webhooks-section to keep them in sync (both show/hide together)
|
|
const webhooksSection = document.getElementById('webhooks-section');
|
|
if (webhooksSection) webhooksSection.classList.add('hidden');
|
|
const adminControls = document.getElementById('admin-controls');
|
|
if (state.isAdmin) {
|
|
adminControls.classList.remove('hidden');
|
|
} else {
|
|
adminControls.classList.add('hidden');
|
|
}
|
|
// Note: webhooks-section visibility is controlled by toggleStatusPanel()
|
|
// Initialise days input from saved value
|
|
const daysInput = document.getElementById('history-days');
|
|
if (daysInput) daysInput.value = state.historyDays;
|
|
startHistoryRefresh();
|
|
}
|
|
|
|
export function showLoginError(message) {
|
|
const errorDiv = document.getElementById('login-error');
|
|
errorDiv.textContent = message;
|
|
errorDiv.classList.remove('hidden');
|
|
}
|
|
|
|
export function hideLoginError() {
|
|
const errorDiv = document.getElementById('login-error');
|
|
errorDiv.classList.add('hidden');
|
|
}
|
|
|
|
export function showError(message) {
|
|
const errorDiv = document.getElementById('error-message');
|
|
errorDiv.textContent = message;
|
|
errorDiv.classList.remove('hidden');
|
|
}
|
|
|
|
export function hideError() {
|
|
const errorDiv = document.getElementById('error-message');
|
|
errorDiv.classList.add('hidden');
|
|
}
|
|
|
|
export function showLoading() {
|
|
const loading = document.getElementById('loading');
|
|
loading.classList.remove('hidden');
|
|
}
|
|
|
|
export function hideLoading() {
|
|
const loading = document.getElementById('loading');
|
|
loading.classList.add('hidden');
|
|
}
|