diff --git a/CHANGELOG.md b/CHANGELOG.md index 12b49ce..ba882c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,12 @@ # Changelog -## Changes 4//13/2025 +## Changes 4/13/2025 - Decreased header height some more and clickable logo. - authModals.js fully updated with i18n.js keys. - main.js added Dark & Light mode i18n.js keys. +- New Admin section Header Settings to change Header Title. +- Admin Panel confirm unsaved changes. ## Changes 4/12/2025 diff --git a/getConfig.php b/getConfig.php index b8f5e3f..a9ca029 100644 --- a/getConfig.php +++ b/getConfig.php @@ -11,14 +11,24 @@ if (file_exists($configFile)) { echo json_encode(['error' => 'Failed to decrypt configuration.']); exit; } - // Decode the configuration and ensure globalOtpauthUrl is set + // Decode the configuration and ensure required fields are set $config = json_decode($decryptedContent, true); + + // Ensure globalOtpauthUrl is set if (!isset($config['globalOtpauthUrl'])) { $config['globalOtpauthUrl'] = ""; } + + // NEW: Ensure header_title is set. + if (!isset($config['header_title']) || empty($config['header_title'])) { + $config['header_title'] = "FileRise"; // default value + } + echo json_encode($config); } else { + // If no config file exists, provide defaults echo json_encode([ + 'header_title' => "FileRise", 'oidc' => [ 'providerUrl' => 'https://your-oidc-provider.com', 'clientId' => 'YOUR_CLIENT_ID', diff --git a/js/auth.js b/js/auth.js index d9a8da2..7e838ab 100644 --- a/js/auth.js +++ b/js/auth.js @@ -97,18 +97,36 @@ function loadAdminConfigFunc() { return fetch("getConfig.php", { credentials: "include" }) .then(response => response.json()) .then(config => { + // Save header_title into localStorage (if needed) + localStorage.setItem("headerTitle", config.header_title || "FileRise"); + + // Update login options and global OTPAuth URL as before localStorage.setItem("disableFormLogin", config.loginOptions.disableFormLogin); localStorage.setItem("disableBasicAuth", config.loginOptions.disableBasicAuth); localStorage.setItem("disableOIDCLogin", config.loginOptions.disableOIDCLogin); localStorage.setItem("globalOtpauthUrl", config.globalOtpauthUrl || "otpauth://totp/{label}?secret={secret}&issuer=FileRise"); + + // Update the UI for login options updateLoginOptionsUIFromStorage(); + + const headerTitleElem = document.querySelector(".header-title h1"); + if (headerTitleElem) { + headerTitleElem.textContent = config.header_title || "FileRise"; + } }) .catch(() => { + // Fallback defaults in case of error + localStorage.setItem("headerTitle", "FileRise"); localStorage.setItem("disableFormLogin", "false"); localStorage.setItem("disableBasicAuth", "false"); localStorage.setItem("disableOIDCLogin", "false"); localStorage.setItem("globalOtpauthUrl", "otpauth://totp/{label}?secret={secret}&issuer=FileRise"); updateLoginOptionsUIFromStorage(); + + const headerTitleElem = document.querySelector(".header-title h1"); + if (headerTitleElem) { + headerTitleElem.textContent = "FileRise"; + } }); } diff --git a/js/authModals.js b/js/authModals.js index b651a78..5060d14 100644 --- a/js/authModals.js +++ b/js/authModals.js @@ -487,10 +487,81 @@ export function closeTOTPModal(disable = true) { } } +// Global variable to hold the initial state of the admin form. +let originalAdminConfig = {}; + +// Capture the initial state of the admin form fields. +function captureInitialAdminConfig() { + originalAdminConfig = { + headerTitle: document.getElementById("headerTitle").value.trim(), + oidcProviderUrl: document.getElementById("oidcProviderUrl").value.trim(), + oidcClientId: document.getElementById("oidcClientId").value.trim(), + oidcClientSecret: document.getElementById("oidcClientSecret").value.trim(), + oidcRedirectUri: document.getElementById("oidcRedirectUri").value.trim(), + disableFormLogin: document.getElementById("disableFormLogin").checked, + disableBasicAuth: document.getElementById("disableBasicAuth").checked, + disableOIDCLogin: document.getElementById("disableOIDCLogin").checked, + globalOtpauthUrl: document.getElementById("globalOtpauthUrl").value.trim() + }; +} + +// Compare current values to the captured initial state. +function hasUnsavedChanges() { + return ( + document.getElementById("headerTitle").value.trim() !== originalAdminConfig.headerTitle || + document.getElementById("oidcProviderUrl").value.trim() !== originalAdminConfig.oidcProviderUrl || + document.getElementById("oidcClientId").value.trim() !== originalAdminConfig.oidcClientId || + document.getElementById("oidcClientSecret").value.trim() !== originalAdminConfig.oidcClientSecret || + document.getElementById("oidcRedirectUri").value.trim() !== originalAdminConfig.oidcRedirectUri || + document.getElementById("disableFormLogin").checked !== originalAdminConfig.disableFormLogin || + document.getElementById("disableBasicAuth").checked !== originalAdminConfig.disableBasicAuth || + document.getElementById("disableOIDCLogin").checked !== originalAdminConfig.disableOIDCLogin || + document.getElementById("globalOtpauthUrl").value.trim() !== originalAdminConfig.globalOtpauthUrl + ); +} + +// Use your custom confirmation modal. +function showCustomConfirmModal(message) { + return new Promise((resolve) => { + // Get modal elements from DOM. + const modal = document.getElementById("customConfirmModal"); + const messageElem = document.getElementById("confirmMessage"); + const yesBtn = document.getElementById("confirmYesBtn"); + const noBtn = document.getElementById("confirmNoBtn"); + + // Set the message in the modal. + messageElem.textContent = message; + modal.style.display = "block"; + + // Define event handlers. + function onYes() { + cleanup(); + resolve(true); + } + function onNo() { + cleanup(); + resolve(false); + } + // Remove event listeners and hide modal after choice. + function cleanup() { + yesBtn.removeEventListener("click", onYes); + noBtn.removeEventListener("click", onNo); + modal.style.display = "none"; + } + + yesBtn.addEventListener("click", onYes); + noBtn.addEventListener("click", onNo); + }); +} + export function openAdminPanel() { fetch("getConfig.php", { credentials: "include" }) .then(response => response.json()) .then(config => { + if (config.header_title) { + document.querySelector(".header-title h1").textContent = config.header_title; + window.headerTitle = config.header_title || "FileRise"; + } if (config.oidc) Object.assign(window.currentOIDCConfig, config.oidc); if (config.globalOtpauthUrl) window.currentOIDCConfig.globalOtpauthUrl = config.globalOtpauthUrl; const isDarkMode = document.body.classList.contains("dark-mode"); @@ -537,6 +608,28 @@ export function openAdminPanel() { +
+ -