Admin Panel Refactor & Enhancements
This commit is contained in:
49
CHANGELOG.md
49
CHANGELOG.md
@@ -1,5 +1,54 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Changes 5/3/2025 v1.3.0
|
||||||
|
|
||||||
|
**Admin Panel Refactor & Enhancements**
|
||||||
|
|
||||||
|
### Moved from `authModals.js` to `adminPanel.js`
|
||||||
|
|
||||||
|
- Extracted all admin-related UI and logic out of `authModals.js`
|
||||||
|
- Created a standalone `adminPanel.js` module
|
||||||
|
- Initialized `openAdminPanel()` and `closeAdminPanel()` exports
|
||||||
|
|
||||||
|
### Responsive, Collapsible Sections
|
||||||
|
|
||||||
|
- Injected new CSS via JS (`adminPanelStyles`)
|
||||||
|
- Default modal width: 50%
|
||||||
|
- Small-screen override (`@media (max-width: 600px)`) to 90% width
|
||||||
|
- Introduced `.section-header` / `.section-content` pattern
|
||||||
|
- Click header to expand/collapse its content
|
||||||
|
- Animated arrow via Material Icons
|
||||||
|
- Indented and padded expanded content
|
||||||
|
|
||||||
|
### “Manage Shared Links” Feature
|
||||||
|
|
||||||
|
- Added new **Manage Shared Links** section to Admin Panel
|
||||||
|
- Endpoint **GET** `/api/admin/readMetadata.php?file=…`
|
||||||
|
- Reads `share_folder_links.json` & `share_links.json` under `META_DIR`
|
||||||
|
- Endpoint **POST**
|
||||||
|
- `/api/folder/deleteShareFolderLink.php`
|
||||||
|
- `/api/file/deleteShareLink.php`
|
||||||
|
- `loadShareLinksSection()` AJAX loader
|
||||||
|
- Displays folder & file shares, expiry dates, upload-allowed, and 🔒 if password-protected
|
||||||
|
- “🗑️” delete buttons refresh the list on success
|
||||||
|
|
||||||
|
### Dark-Mode & Theming Fixes
|
||||||
|
|
||||||
|
- Dark-mode CSS overrides for:
|
||||||
|
- Modal border
|
||||||
|
- `.btn-primary`, `.btn-secondary`
|
||||||
|
- `.form-control` backgrounds & placeholders
|
||||||
|
- Section headers & icons
|
||||||
|
- Close button restyled to use shared **.editor-close-btn** look
|
||||||
|
|
||||||
|
### API and Controller changes
|
||||||
|
|
||||||
|
- Updated all endpoints to use correct controller casing
|
||||||
|
- Renamed controller files to PascalCase (e.g. `adminController.php` to `AdminController.php`, `fileController.php` to `FileController.php`, `folderController.php` to `FolderController.php`)
|
||||||
|
- Adjusted endpoint paths to match controller filenames
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Changes 4/30/2025 v1.2.8
|
## Changes 4/30/2025 v1.2.8
|
||||||
|
|
||||||
- **Added** PDF preview in `filePreview.js` (the `extension === "pdf"` block): replaced in-modal `<embed>` with `window.open(urlWithTs, "_blank")` and closed the modal to avoid CSP `frame-ancestors 'none'` restrictions.
|
- **Added** PDF preview in `filePreview.js` (the `extension === "pdf"` block): replaced in-modal `<embed>` with `window.open(urlWithTs, "_blank")` and closed the modal to avoid CSP `frame-ancestors 'none'` restrictions.
|
||||||
|
|||||||
@@ -184,21 +184,29 @@ function loadShareLinksSection() {
|
|||||||
const container = document.getElementById("shareLinksContent");
|
const container = document.getElementById("shareLinksContent");
|
||||||
container.textContent = t("loading") + "...";
|
container.textContent = t("loading") + "...";
|
||||||
|
|
||||||
|
// Helper to fetch a metadata file or return {} on any error
|
||||||
|
const fetchMeta = file =>
|
||||||
|
fetch(`/api/admin/readMetadata.php?file=${file}`, { credentials: "include" })
|
||||||
|
.then(r => r.ok ? r.json() : {}) // non-2xx → treat as empty
|
||||||
|
.catch(() => ({}));
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
fetch("/api/admin/readMetadata.php?file=share_folder_links.json", { credentials: "include" })
|
fetchMeta("share_folder_links.json"),
|
||||||
.then(r => r.ok ? r.json() : Promise.reject(`Folder fetch ${r.status}`)),
|
fetchMeta("share_links.json")
|
||||||
fetch("/api/admin/readMetadata.php?file=share_links.json", { credentials: "include" })
|
|
||||||
.then(r => r.ok ? r.json() : Promise.reject(`File fetch ${r.status}`))
|
|
||||||
])
|
])
|
||||||
.then(([folders, files]) => {
|
.then(([folders, files]) => {
|
||||||
let html = `<h5>${t("folder_shares")}</h5><ul>`;
|
// If nothing at all, show a friendly message
|
||||||
|
if (Object.keys(folders).length === 0 && Object.keys(files).length === 0) {
|
||||||
|
container.textContent = t("no_shared_links_available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let html = `<h5>${t("folder_shares")}</h5><ul>`;
|
||||||
Object.entries(folders).forEach(([token, o]) => {
|
Object.entries(folders).forEach(([token, o]) => {
|
||||||
const lock = o.password ? `🔒 ` : "";
|
const lock = o.password ? `🔒 ` : "";
|
||||||
html += `
|
html += `
|
||||||
<li>
|
<li>
|
||||||
${lock}
|
${lock}<strong>${o.folder}</strong>
|
||||||
<strong>${o.folder}</strong>
|
|
||||||
<small>(${new Date(o.expires * 1000).toLocaleString()})</small>
|
<small>(${new Date(o.expires * 1000).toLocaleString()})</small>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
data-key="${token}"
|
data-key="${token}"
|
||||||
@@ -208,13 +216,11 @@ function loadShareLinksSection() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
html += `</ul><h5 style="margin-top:1em;">${t("file_shares")}</h5><ul>`;
|
html += `</ul><h5 style="margin-top:1em;">${t("file_shares")}</h5><ul>`;
|
||||||
|
|
||||||
Object.entries(files).forEach(([token, o]) => {
|
Object.entries(files).forEach(([token, o]) => {
|
||||||
const lock = o.password ? `🔒 ` : "";
|
const lock = o.password ? `🔒 ` : "";
|
||||||
html += `
|
html += `
|
||||||
<li>
|
<li>
|
||||||
${lock}
|
${lock}<strong>${o.folder}/${o.file}</strong>
|
||||||
<strong>${o.folder}/${o.file}</strong>
|
|
||||||
<small>(${new Date(o.expires * 1000).toLocaleString()})</small>
|
<small>(${new Date(o.expires * 1000).toLocaleString()})</small>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
data-key="${token}"
|
data-key="${token}"
|
||||||
@@ -222,8 +228,8 @@ function loadShareLinksSection() {
|
|||||||
class="btn btn-sm btn-link delete-share">🗑️</button>
|
class="btn btn-sm btn-link delete-share">🗑️</button>
|
||||||
</li>`;
|
</li>`;
|
||||||
});
|
});
|
||||||
|
|
||||||
html += `</ul>`;
|
html += `</ul>`;
|
||||||
|
|
||||||
container.innerHTML = html;
|
container.innerHTML = html;
|
||||||
|
|
||||||
// wire up delete buttons
|
// wire up delete buttons
|
||||||
@@ -314,7 +320,7 @@ export function openAdminPanel() {
|
|||||||
{ id: "headerSettings", label: t("header_settings") },
|
{ id: "headerSettings", label: t("header_settings") },
|
||||||
{ id: "loginOptions", label: t("login_options") },
|
{ id: "loginOptions", label: t("login_options") },
|
||||||
{ id: "webdav", label: "WebDAV Access" },
|
{ id: "webdav", label: "WebDAV Access" },
|
||||||
{ id:"upload", label:t("shared_max_upload_size_bytes") },
|
{ id: "upload", label: t("shared_max_upload_size_bytes_title") },
|
||||||
{ id: "oidc", label: t("oidc_configuration") + " & TOTP" },
|
{ id: "oidc", label: t("oidc_configuration") + " & TOTP" },
|
||||||
{ id: "shareLinks", label: t("manage_shared_links") }
|
{ id: "shareLinks", label: t("manage_shared_links") }
|
||||||
].map(sec => `
|
].map(sec => `
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ const translations = {
|
|||||||
|
|
||||||
// Admin Panel
|
// Admin Panel
|
||||||
"header_settings": "Header Settings",
|
"header_settings": "Header Settings",
|
||||||
|
"shared_max_upload_size_bytes_title": "Shared Max Upload Size",
|
||||||
"shared_max_upload_size_bytes": "Shared Max Upload Size (bytes)",
|
"shared_max_upload_size_bytes": "Shared Max Upload Size (bytes)",
|
||||||
"max_bytes_shared_uploads_note": "Enter maximum bytes allowed for shared-folder uploads",
|
"max_bytes_shared_uploads_note": "Enter maximum bytes allowed for shared-folder uploads",
|
||||||
"manage_shared_links": "Manage Shared Links",
|
"manage_shared_links": "Manage Shared Links",
|
||||||
@@ -194,6 +195,7 @@ const translations = {
|
|||||||
"share_deleted_successfully": "Share deleted successfully",
|
"share_deleted_successfully": "Share deleted successfully",
|
||||||
"error_deleting_share": "Error deleting share",
|
"error_deleting_share": "Error deleting share",
|
||||||
"password_protected": "Password protected",
|
"password_protected": "Password protected",
|
||||||
|
"no_shared_links_available": "No shared links available",
|
||||||
|
|
||||||
|
|
||||||
// NEW KEYS ADDED FOR ADMIN, USER PANELS, AND TOTP MODALS:
|
// NEW KEYS ADDED FOR ADMIN, USER PANELS, AND TOTP MODALS:
|
||||||
|
|||||||
Reference in New Issue
Block a user