Refactor auth flow: add loading overlay, separate login, extract initializeApp
This commit is contained in:
42
CHANGELOG.md
42
CHANGELOG.md
@@ -1,6 +1,6 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## Changes 5/4/2025
|
## Changes 5/4/2025 v1.3.1
|
||||||
|
|
||||||
### Modals
|
### Modals
|
||||||
|
|
||||||
@@ -10,9 +10,47 @@
|
|||||||
- TOTP Login & Setup
|
- TOTP Login & Setup
|
||||||
- Change Password
|
- Change Password
|
||||||
- **Truncated** long filenames in the File Tags modal header using CSS `text-overflow: ellipsis`.
|
- **Truncated** long filenames in the File Tags modal header using CSS `text-overflow: ellipsis`.
|
||||||
- **Resized** File Tags modal from 400px → 450px wide (with `max-width: 90vw` fallback).
|
- **Resized** File Tags modal from 400px to 450px wide (with `max-width: 90vw` fallback).
|
||||||
- **Capped** User Panel height at 381px and hidden scrollbars to eliminate layout jumps on hover.
|
- **Capped** User Panel height at 381px and hidden scrollbars to eliminate layout jumps on hover.
|
||||||
|
|
||||||
|
### HTML
|
||||||
|
|
||||||
|
- **Moved** `<div id="loginForm">…</div>` out of `.main-wrapper` so the login form can show independently of the app shell.
|
||||||
|
- **Added** `<div id="loadingOverlay"></div>` immediately inside `<body>` to cover the UI during auth checks.
|
||||||
|
- **Inserted** inline `<style>` in `<head>` to:
|
||||||
|
- Hide `.main-wrapper` by default.
|
||||||
|
- Style `#loadingOverlay` as a full-viewport white overlay.
|
||||||
|
|
||||||
|
- **Added** `addUserModal`, `removeUserModal` & `renameFileModal` modals to `style="display:none;"`
|
||||||
|
|
||||||
|
### `main.js`
|
||||||
|
|
||||||
|
- **Extracted** `initializeApp()` helper to centralize post-auth startup (tag search, file list, drag-and-drop, folder tree, upload, trash/restore, admin config).
|
||||||
|
- **Updated** DOMContentLoaded `checkAuthentication()` flow to call `initializeApp()` when already authenticated.
|
||||||
|
- **Extended** `updateAuthenticatedUI()` to call `initializeApp()` after a fresh login so all UI modules re-hydrate.
|
||||||
|
- **Enhanced** setup-mode in `checkAuthentication()`:
|
||||||
|
- Show `#addUserModal` as a flex overlay (`style.display = 'flex'`).
|
||||||
|
- Keep `.main-wrapper` hidden until setup completes.
|
||||||
|
- **Added** post-setup handler in the Add-User modal’s save button:
|
||||||
|
- Hide setup modal.
|
||||||
|
- Show login form.
|
||||||
|
- Keep app shell hidden.
|
||||||
|
- Pre-fill and focus the new username in the login inputs.
|
||||||
|
|
||||||
|
### `auth.js` / Auth Logic
|
||||||
|
|
||||||
|
- **Refactored** `checkAuthentication()` to handle three states:
|
||||||
|
1. **`data.setup`** remove overlay, hide main UI, show setup modal.
|
||||||
|
2. **`data.authenticated`** remove overlay, call `updateAuthenticatedUI()`.
|
||||||
|
3. **not authenticated** remove overlay, show login form, keep main UI hidden.
|
||||||
|
- **Refined** `updateAuthenticatedUI()` to:
|
||||||
|
- Remove loading overlay.
|
||||||
|
- Show `.main-wrapper` and main operations.
|
||||||
|
- Hide `#loginForm`.
|
||||||
|
- Reveal header buttons.
|
||||||
|
- Initialize dynamic header buttons (restore, admin, user-panel).
|
||||||
|
- Call `initializeApp()` to load all modules after login.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Changes 5/3/2025 v1.3.0
|
## Changes 5/3/2025 v1.3.0
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
cd /var/www/public
|
|
||||||
ln -s ../uploads uploads
|
|
||||||
@@ -9,6 +9,21 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/assets/logo.svg">
|
<link rel="icon" type="image/svg+xml" href="/assets/logo.svg">
|
||||||
<meta name="csrf-token" content="">
|
<meta name="csrf-token" content="">
|
||||||
<meta name="share-url" content="">
|
<meta name="share-url" content="">
|
||||||
|
<style>
|
||||||
|
/* hide the app shell until JS says otherwise */
|
||||||
|
.main-wrapper { display: none; }
|
||||||
|
|
||||||
|
/* full-screen white overlay while we check auth */
|
||||||
|
#loadingOverlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
|
background: var(--bg-color,#fff);
|
||||||
|
z-index: 9999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<!-- Google Fonts and Material Icons -->
|
<!-- Google Fonts and Material Icons -->
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap" rel="stylesheet" />
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
||||||
@@ -165,10 +180,42 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<div id="loadingOverlay"></div>
|
||||||
|
|
||||||
<!-- Custom Toast Container -->
|
<!-- Custom Toast Container -->
|
||||||
<div id="customToast"></div>
|
<div id="customToast"></div>
|
||||||
<div id="hiddenCardsContainer" style="display:none;"></div>
|
<div id="hiddenCardsContainer" style="display:none;"></div>
|
||||||
|
|
||||||
|
<div class="row mt-4" id="loginForm">
|
||||||
|
<div class="col-12">
|
||||||
|
<form id="authForm" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="loginUsername" data-i18n-key="user">User:</label>
|
||||||
|
<input type="text" class="form-control" id="loginUsername" name="username" required autofocus />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="loginPassword" data-i18n-key="password">Password:</label>
|
||||||
|
<input type="password" class="form-control" id="loginPassword" name="password" required />
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary btn-block btn-login" data-i18n-key="login">Login</button>
|
||||||
|
<div class="form-group remember-me-container">
|
||||||
|
<input type="checkbox" id="rememberMeCheckbox" name="remember_me" />
|
||||||
|
<label for="rememberMeCheckbox" data-i18n-key="remember_me">Remember me</label>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<!-- OIDC Login Option -->
|
||||||
|
<div class="text-center mt-3">
|
||||||
|
<button id="oidcLoginBtn" class="btn btn-secondary" data-i18n-key="login_oidc">Login with OIDC</button>
|
||||||
|
</div>
|
||||||
|
<!-- Basic HTTP Login Option -->
|
||||||
|
<div class="text-center mt-3">
|
||||||
|
<a href="/api/auth/login_basic.php" class="btn btn-secondary" data-i18n-key="basic_http_login">Use Basic
|
||||||
|
HTTP
|
||||||
|
Login</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Main Wrapper: Hidden by default; remove "display: none;" after login -->
|
<!-- Main Wrapper: Hidden by default; remove "display: none;" after login -->
|
||||||
<div class="main-wrapper">
|
<div class="main-wrapper">
|
||||||
<!-- Sidebar Drop Zone: Hidden until you drag a card (display controlled by JS) -->
|
<!-- Sidebar Drop Zone: Hidden until you drag a card (display controlled by JS) -->
|
||||||
@@ -176,37 +223,6 @@
|
|||||||
<!-- Main Column -->
|
<!-- Main Column -->
|
||||||
<div id="mainColumn" class="main-column">
|
<div id="mainColumn" class="main-column">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<!-- Login Form (unchanged) -->
|
|
||||||
<div class="row" id="loginForm">
|
|
||||||
<div class="col-12">
|
|
||||||
<form id="authForm" method="post">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="loginUsername" data-i18n-key="user">User:</label>
|
|
||||||
<input type="text" class="form-control" id="loginUsername" name="username" required autofocus />
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="loginPassword" data-i18n-key="password">Password:</label>
|
|
||||||
<input type="password" class="form-control" id="loginPassword" name="password" required />
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary btn-block btn-login" data-i18n-key="login">Login</button>
|
|
||||||
<div class="form-group remember-me-container">
|
|
||||||
<input type="checkbox" id="rememberMeCheckbox" name="remember_me" />
|
|
||||||
<label for="rememberMeCheckbox" data-i18n-key="remember_me">Remember me</label>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<!-- OIDC Login Option -->
|
|
||||||
<div class="text-center mt-3">
|
|
||||||
<button id="oidcLoginBtn" class="btn btn-secondary" data-i18n-key="login_oidc">Login with OIDC</button>
|
|
||||||
</div>
|
|
||||||
<!-- Basic HTTP Login Option -->
|
|
||||||
<div class="text-center mt-3">
|
|
||||||
<a href="/api/auth/login_basic.php" class="btn btn-secondary" data-i18n-key="basic_http_login">Use Basic
|
|
||||||
HTTP
|
|
||||||
Login</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Main Operations: Upload and Folder Management -->
|
<!-- Main Operations: Upload and Folder Management -->
|
||||||
<div id="mainOperations">
|
<div id="mainOperations">
|
||||||
<div class="container" style="max-width: 1400px; margin: 0 auto;">
|
<div class="container" style="max-width: 1400px; margin: 0 auto;">
|
||||||
@@ -439,7 +455,7 @@
|
|||||||
<button id="saveNewPasswordBtn" class="btn btn-primary" data-i18n-key="save" style="width:100%;">Save</button>
|
<button id="saveNewPasswordBtn" class="btn btn-primary" data-i18n-key="save" style="width:100%;">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="addUserModal" class="modal">
|
<div id="addUserModal" class="modal" style="display:none;">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<h3 data-i18n-key="create_new_user_title">Create New User</h3>
|
<h3 data-i18n-key="create_new_user_title">Create New User</h3>
|
||||||
<!-- 1) Add a form around these fields -->
|
<!-- 1) Add a form around these fields -->
|
||||||
@@ -468,7 +484,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="removeUserModal" class="modal">
|
<div id="removeUserModal" class="modal" style="display:none;">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<h3 data-i18n-key="remove_user_title">Remove User</h3>
|
<h3 data-i18n-key="remove_user_title">Remove User</h3>
|
||||||
<label for="removeUsernameSelect" data-i18n-key="select_user_remove">Select a user to remove:</label>
|
<label for="removeUsernameSelect" data-i18n-key="select_user_remove">Select a user to remove:</label>
|
||||||
@@ -479,7 +495,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="renameFileModal" class="modal">
|
<div id="renameFileModal" class="modal" style="display:none;">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<h4 data-i18n-key="rename_file_title">Rename File</h4>
|
<h4 data-i18n-key="rename_file_title">Rename File</h4>
|
||||||
<input type="text" id="newFileName" class="form-control" data-i18n-placeholder="rename_file_placeholder"
|
<input type="text" id="newFileName" class="form-control" data-i18n-placeholder="rename_file_placeholder"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { loadAdminConfigFunc } from './auth.js';
|
|||||||
import { showToast, toggleVisibility, attachEnterKeyListener } from './domUtils.js';
|
import { showToast, toggleVisibility, attachEnterKeyListener } from './domUtils.js';
|
||||||
import { sendRequest } from './networkUtils.js';
|
import { sendRequest } from './networkUtils.js';
|
||||||
|
|
||||||
const version = "v1.3.0";
|
const version = "v1.3.1";
|
||||||
const adminTitle = `${t("admin_panel")} <small style="font-size:12px;color:gray;">${version}</small>`;
|
const adminTitle = `${t("admin_panel")} <small style="font-size:12px;color:gray;">${version}</small>`;
|
||||||
|
|
||||||
// ————— Inject updated styles —————
|
// ————— Inject updated styles —————
|
||||||
@@ -389,7 +389,7 @@ export function openAdminPanel() {
|
|||||||
// — Header Settings —
|
// — Header Settings —
|
||||||
document.getElementById("headerSettingsContent").innerHTML = `
|
document.getElementById("headerSettingsContent").innerHTML = `
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="headerTitle">${t("header_title")}:</label>
|
<label for="headerTitle">${t("header_title_text")}:</label>
|
||||||
<input type="text" id="headerTitle" class="form-control" value="${window.headerTitle}" />
|
<input type="text" id="headerTitle" class="form-control" value="${window.headerTitle}" />
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -548,7 +548,7 @@ export function openUserPermissionsModal() {
|
|||||||
`;
|
`;
|
||||||
userPermissionsModal.innerHTML = `
|
userPermissionsModal.innerHTML = `
|
||||||
<div class="modal-content" style="${modalContentStyles}">
|
<div class="modal-content" style="${modalContentStyles}">
|
||||||
<span id="closeUserPermissionsModal" style="position: absolute; top: 10px; right: 10px; cursor: pointer; font-size: 24px;">×</span>
|
<span id="closeUserPermissionsModal" class="editor-close-btn">×</span>
|
||||||
<h3>${t("user_permissions")}</h3>
|
<h3>${t("user_permissions")}</h3>
|
||||||
<div id="userPermissionsList" style="max-height: 300px; overflow-y: auto; margin-bottom: 15px;">
|
<div id="userPermissionsList" style="max-height: 300px; overflow-y: auto; margin-bottom: 15px;">
|
||||||
<!-- User rows will be loaded here -->
|
<!-- User rows will be loaded here -->
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
setLastLoginData
|
setLastLoginData
|
||||||
} from './authModals.js';
|
} from './authModals.js';
|
||||||
import { openAdminPanel } from './adminPanel.js';
|
import { openAdminPanel } from './adminPanel.js';
|
||||||
|
import { initializeApp } from './main.js';
|
||||||
|
|
||||||
// Production OIDC configuration (override via API as needed)
|
// Production OIDC configuration (override via API as needed)
|
||||||
const currentOIDCConfig = {
|
const currentOIDCConfig = {
|
||||||
@@ -127,13 +128,13 @@ function updateItemsPerPageSelect() {
|
|||||||
|
|
||||||
function updateLoginOptionsUI({ disableFormLogin, disableBasicAuth, disableOIDCLogin }) {
|
function updateLoginOptionsUI({ disableFormLogin, disableBasicAuth, disableOIDCLogin }) {
|
||||||
const authForm = document.getElementById("authForm");
|
const authForm = document.getElementById("authForm");
|
||||||
if
|
if
|
||||||
(authForm) {
|
(authForm) {
|
||||||
authForm.style.display = disableFormLogin ? "none" : "block";
|
authForm.style.display = disableFormLogin ? "none" : "block";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const loginInput = document.getElementById('loginUsername');
|
const loginInput = document.getElementById('loginUsername');
|
||||||
if (loginInput) loginInput.focus();
|
if (loginInput) loginInput.focus();
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
const basicAuthLink = document.querySelector("a[href='/api/auth/login_basic.php']");
|
const basicAuthLink = document.querySelector("a[href='/api/auth/login_basic.php']");
|
||||||
if (basicAuthLink) basicAuthLink.style.display = disableBasicAuth ? "none" : "inline-block";
|
if (basicAuthLink) basicAuthLink.style.display = disableBasicAuth ? "none" : "inline-block";
|
||||||
@@ -189,6 +190,11 @@ function insertAfter(newNode, referenceNode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateAuthenticatedUI(data) {
|
function updateAuthenticatedUI(data) {
|
||||||
|
document.getElementById('loadingOverlay').remove();
|
||||||
|
|
||||||
|
// show the wrapper (so the login form can be visible)
|
||||||
|
document.querySelector('.main-wrapper').style.display = '';
|
||||||
|
document.getElementById('loginForm').style.display = 'none';
|
||||||
toggleVisibility("loginForm", false);
|
toggleVisibility("loginForm", false);
|
||||||
toggleVisibility("mainOperations", true);
|
toggleVisibility("mainOperations", true);
|
||||||
toggleVisibility("uploadFileForm", true);
|
toggleVisibility("uploadFileForm", true);
|
||||||
@@ -263,6 +269,7 @@ function updateAuthenticatedUI(data) {
|
|||||||
userPanelBtn.style.display = "block";
|
userPanelBtn.style.display = "block";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initializeApp();
|
||||||
applyTranslations();
|
applyTranslations();
|
||||||
updateItemsPerPageSelect();
|
updateItemsPerPageSelect();
|
||||||
updateLoginOptionsUIFromStorage();
|
updateLoginOptionsUIFromStorage();
|
||||||
@@ -272,6 +279,11 @@ function checkAuthentication(showLoginToast = true) {
|
|||||||
return sendRequest("/api/auth/checkAuth.php")
|
return sendRequest("/api/auth/checkAuth.php")
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.setup) {
|
if (data.setup) {
|
||||||
|
document.getElementById('loadingOverlay').remove();
|
||||||
|
|
||||||
|
// show the wrapper (so the login form can be visible)
|
||||||
|
document.querySelector('.main-wrapper').style.display = '';
|
||||||
|
document.getElementById('loginForm').style.display = 'none';
|
||||||
window.setupMode = true;
|
window.setupMode = true;
|
||||||
if (showLoginToast) showToast("Setup mode: No users found. Please add an admin user.");
|
if (showLoginToast) showToast("Setup mode: No users found. Please add an admin user.");
|
||||||
toggleVisibility("loginForm", false);
|
toggleVisibility("loginForm", false);
|
||||||
@@ -283,6 +295,7 @@ function checkAuthentication(showLoginToast = true) {
|
|||||||
}
|
}
|
||||||
window.setupMode = false;
|
window.setupMode = false;
|
||||||
if (data.authenticated) {
|
if (data.authenticated) {
|
||||||
|
|
||||||
localStorage.setItem('isAdmin', data.isAdmin ? 'true' : 'false');
|
localStorage.setItem('isAdmin', data.isAdmin ? 'true' : 'false');
|
||||||
localStorage.setItem("folderOnly", data.folderOnly);
|
localStorage.setItem("folderOnly", data.folderOnly);
|
||||||
localStorage.setItem("readOnly", data.readOnly);
|
localStorage.setItem("readOnly", data.readOnly);
|
||||||
@@ -298,6 +311,11 @@ function checkAuthentication(showLoginToast = true) {
|
|||||||
updateAuthenticatedUI(data);
|
updateAuthenticatedUI(data);
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
|
document.getElementById('loadingOverlay').remove();
|
||||||
|
|
||||||
|
// show the wrapper (so the login form can be visible)
|
||||||
|
document.querySelector('.main-wrapper').style.display = '';
|
||||||
|
document.getElementById('loginForm').style.display = '';
|
||||||
if (showLoginToast) showToast("Please log in to continue.");
|
if (showLoginToast) showToast("Please log in to continue.");
|
||||||
toggleVisibility("loginForm", true);
|
toggleVisibility("loginForm", true);
|
||||||
toggleVisibility("mainOperations", false);
|
toggleVisibility("mainOperations", false);
|
||||||
@@ -443,52 +461,55 @@ function initAuth() {
|
|||||||
submitLogin(formData);
|
submitLogin(formData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("addUserBtn").addEventListener("click", function () {
|
document.getElementById("addUserBtn").addEventListener("click", function () {
|
||||||
resetUserForm();
|
resetUserForm();
|
||||||
toggleVisibility("addUserModal", true);
|
toggleVisibility("addUserModal", true);
|
||||||
document.getElementById("newUsername").focus();
|
document.getElementById("newUsername").focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove your old saveUserBtn click-handler…
|
|
||||||
|
|
||||||
// instead:
|
// remove your old saveUserBtn click-handler…
|
||||||
const addUserForm = document.getElementById("addUserForm");
|
|
||||||
addUserForm.addEventListener("submit", function (e) {
|
|
||||||
e.preventDefault(); // stop the browser from reloading the page
|
|
||||||
|
|
||||||
const newUsername = document.getElementById("newUsername").value.trim();
|
// instead:
|
||||||
const newPassword = document.getElementById("addUserPassword").value.trim();
|
const addUserForm = document.getElementById("addUserForm");
|
||||||
const isAdmin = document.getElementById("isAdmin").checked;
|
addUserForm.addEventListener("submit", function (e) {
|
||||||
|
e.preventDefault(); // stop the browser from reloading the page
|
||||||
|
|
||||||
if (!newUsername || !newPassword) {
|
const newUsername = document.getElementById("newUsername").value.trim();
|
||||||
showToast("Username and password are required!");
|
const newPassword = document.getElementById("addUserPassword").value.trim();
|
||||||
return;
|
const isAdmin = document.getElementById("isAdmin").checked;
|
||||||
}
|
|
||||||
|
|
||||||
let url = "/api/addUser.php";
|
if (!newUsername || !newPassword) {
|
||||||
if (window.setupMode) url += "?setup=1";
|
showToast("Username and password are required!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fetchWithCsrf(url, {
|
let url = "/api/addUser.php";
|
||||||
method: "POST",
|
if (window.setupMode) url += "?setup=1";
|
||||||
credentials: "include",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
fetchWithCsrf(url, {
|
||||||
body: JSON.stringify({ username: newUsername, password: newPassword, isAdmin })
|
method: "POST",
|
||||||
})
|
credentials: "include",
|
||||||
.then(r => r.json())
|
headers: { "Content-Type": "application/json" },
|
||||||
.then(data => {
|
body: JSON.stringify({ username: newUsername, password: newPassword, isAdmin })
|
||||||
if (data.success) {
|
|
||||||
showToast("User added successfully!");
|
|
||||||
closeAddUserModal();
|
|
||||||
checkAuthentication(false);
|
|
||||||
} else {
|
|
||||||
showToast("Error: " + (data.error || "Could not add user"));
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.then(r => r.json())
|
||||||
showToast("Error: Could not add user");
|
.then(data => {
|
||||||
});
|
if (data.success) {
|
||||||
});
|
showToast("User added successfully!");
|
||||||
|
closeAddUserModal();
|
||||||
|
checkAuthentication(false);
|
||||||
|
if (window.setupMode) {
|
||||||
|
toggleVisibility("loginForm", true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showToast("Error: " + (data.error || "Could not add user"));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
showToast("Error: Could not add user");
|
||||||
|
});
|
||||||
|
});
|
||||||
document.getElementById("cancelUserBtn").addEventListener("click", closeAddUserModal);
|
document.getElementById("cancelUserBtn").addEventListener("click", closeAddUserModal);
|
||||||
|
|
||||||
document.getElementById("removeUserBtn").addEventListener("click", function () {
|
document.getElementById("removeUserBtn").addEventListener("click", function () {
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ export function openUserPanel() {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
max-height: 381px !important;
|
max-height: 383px !important;
|
||||||
flex-shrink: 0 !important;
|
flex-shrink: 0 !important;
|
||||||
scrollbar-gutter: stable both-edges;
|
scrollbar-gutter: stable both-edges;
|
||||||
border: ${isDarkMode ? "1px solid #444" : "1px solid #ccc"};
|
border: ${isDarkMode ? "1px solid #444" : "1px solid #ccc"};
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ const translations = {
|
|||||||
// Additional keys for HTML translations:
|
// Additional keys for HTML translations:
|
||||||
"title": "FileRise",
|
"title": "FileRise",
|
||||||
"header_title": "FileRise",
|
"header_title": "FileRise",
|
||||||
|
"header_title_text": "Header Title",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
"change_password": "Change Password",
|
"change_password": "Change Password",
|
||||||
"restore_text": "Restore or",
|
"restore_text": "Restore or",
|
||||||
@@ -316,6 +317,7 @@ const translations = {
|
|||||||
// Additional keys for HTML translations:
|
// Additional keys for HTML translations:
|
||||||
"title": "FileRise",
|
"title": "FileRise",
|
||||||
"header_title": "FileRise",
|
"header_title": "FileRise",
|
||||||
|
"header_title_text": "Header Title",
|
||||||
"logout": "Cerrar sesión",
|
"logout": "Cerrar sesión",
|
||||||
"change_password": "Cambiar contraseña",
|
"change_password": "Cambiar contraseña",
|
||||||
"restore_text": "Restaurar o",
|
"restore_text": "Restaurar o",
|
||||||
|
|||||||
@@ -14,6 +14,28 @@ import { initFileActions, renameFile, openDownloadModal, confirmSingleDownload }
|
|||||||
import { editFile, saveFile } from './fileEditor.js';
|
import { editFile, saveFile } from './fileEditor.js';
|
||||||
import { t, applyTranslations, setLocale } from './i18n.js';
|
import { t, applyTranslations, setLocale } from './i18n.js';
|
||||||
|
|
||||||
|
export function initializeApp() {
|
||||||
|
window.currentFolder = "root";
|
||||||
|
initTagSearch();
|
||||||
|
loadFileList(window.currentFolder);
|
||||||
|
initDragAndDrop();
|
||||||
|
loadSidebarOrder();
|
||||||
|
loadHeaderOrder();
|
||||||
|
initFileActions();
|
||||||
|
initUpload();
|
||||||
|
loadFolderTree();
|
||||||
|
setupTrashRestoreDelete();
|
||||||
|
loadAdminConfigFunc();
|
||||||
|
|
||||||
|
const helpBtn = document.getElementById("folderHelpBtn");
|
||||||
|
const helpTooltip = document.getElementById("folderHelpTooltip");
|
||||||
|
if (helpBtn && helpTooltip) {
|
||||||
|
helpBtn.addEventListener("click", () => {
|
||||||
|
helpTooltip.style.display =
|
||||||
|
helpTooltip.style.display === "block" ? "none" : "block";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function loadCsrfToken() {
|
export function loadCsrfToken() {
|
||||||
return fetchWithCsrf('/api/auth/token.php', {
|
return fetchWithCsrf('/api/auth/token.php', {
|
||||||
@@ -100,31 +122,9 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Continue with initializations that rely on a valid CSRF token:
|
// Continue with initializations that rely on a valid CSRF token:
|
||||||
checkAuthentication().then(authenticated => {
|
checkAuthentication().then(authenticated => {
|
||||||
if (authenticated) {
|
if (authenticated) {
|
||||||
window.currentFolder = "root";
|
document.getElementById('loadingOverlay').remove();
|
||||||
initTagSearch();
|
initializeApp();
|
||||||
loadFileList(window.currentFolder);
|
}
|
||||||
initDragAndDrop();
|
|
||||||
loadSidebarOrder();
|
|
||||||
loadHeaderOrder();
|
|
||||||
initFileActions();
|
|
||||||
initUpload();
|
|
||||||
loadFolderTree();
|
|
||||||
setupTrashRestoreDelete();
|
|
||||||
loadAdminConfigFunc();
|
|
||||||
|
|
||||||
const helpBtn = document.getElementById("folderHelpBtn");
|
|
||||||
const helpTooltip = document.getElementById("folderHelpTooltip");
|
|
||||||
helpBtn.addEventListener("click", function () {
|
|
||||||
// Toggle display of the tooltip.
|
|
||||||
if (helpTooltip.style.display === "none" || helpTooltip.style.display === "") {
|
|
||||||
helpTooltip.style.display = "block";
|
|
||||||
} else {
|
|
||||||
helpTooltip.style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.warn("User not authenticated. Data loading deferred.");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Other DOM initialization that can happen after CSRF is ready.
|
// Other DOM initialization that can happen after CSRF is ready.
|
||||||
|
|||||||
Reference in New Issue
Block a user