some refactoring

This commit is contained in:
error311
2025-03-03 04:03:58 -05:00
parent 1a1ae98232
commit 7b3127384c
6 changed files with 977 additions and 912 deletions

View File

@@ -1,60 +1,70 @@
let fileData = []; // Store file data globally
let sortOrder = { column: "uploaded", ascending: false }; // Default sorting by uploaded date (newest first)
// displayFileList.js
import { sendRequest, toggleVisibility } from './utils.js';
// Load and display the file list
window.loadFileList = function () {
fetch("checkAuth.php")
.then(response => response.json())
.then(authData => {
if (!authData.authenticated) {
console.warn("User not authenticated, hiding file list.");
document.getElementById("fileListContainer").style.display = "none";
return;
}
document.getElementById("fileListContainer").style.display = "block";
fetch("getFileList.php")
.then(response => response.json())
.then(data => {
if (data.error) {
document.getElementById("fileList").innerHTML = `<p style="color:red;">Error: ${data.error}</p>`;
return;
}
if (!Array.isArray(data.files)) {
console.error("Unexpected response format:", data);
return;
}
fileData = data.files; // Store file data globally
sortFiles("uploaded", false); // Sort by upload date (newest first) on load
})
.catch(error => console.error("Error fetching file list:", error));
})
.catch(error => console.error("Error checking authentication:", error));
};
let fileData = [];
let sortOrder = { column: "uploaded", ascending: false };
// Sort files when clicking headers
function sortFiles(column, forceAscending = null) {
if (sortOrder.column === column) {
sortOrder.ascending = forceAscending !== null ? forceAscending : !sortOrder.ascending; // Toggle order
} else {
sortOrder.column = column;
sortOrder.ascending = forceAscending !== null ? forceAscending : true; // Default to ascending when switching column
}
fileData.sort((a, b) => {
let valA = a[column] || "";
let valB = b[column] || "";
if (typeof valA === "string") valA = valA.toLowerCase();
if (typeof valB === "string") valB = valB.toLowerCase();
if (valA < valB) return sortOrder.ascending ? -1 : 1;
if (valA > valB) return sortOrder.ascending ? 1 : -1;
return 0;
});
renderFileTable(); // Re-render table after sorting
export function loadFileList() {
sendRequest("checkAuth.php")
.then(authData => {
if (!authData.authenticated) {
console.warn("User not authenticated, hiding file list.");
toggleVisibility("fileListContainer", false);
return;
}
toggleVisibility("fileListContainer", true);
return sendRequest("getFileList.php");
})
.then(data => {
if (!data) return;
if (data.error) {
document.getElementById("fileList").innerHTML = `<p style="color:red;">Error: ${data.error}</p>`;
return;
}
if (!Array.isArray(data.files)) {
console.error("Unexpected response format:", data);
return;
}
fileData = data.files;
sortFiles("uploaded", false);
})
.catch(error => console.error("Error loading file list:", error));
}
// Function to render file table
function renderFileTable() {
const fileListContainer = document.getElementById("fileList");
let tableHTML = `<table class="table">
export function sortFiles(column, forceAscending = null) {
if (sortOrder.column === column) {
sortOrder.ascending = forceAscending !== null ? forceAscending : !sortOrder.ascending;
} else {
sortOrder.column = column;
sortOrder.ascending = forceAscending !== null ? forceAscending : true;
}
fileData.sort((a, b) => {
let valA = a[column] || "";
let valB = b[column] || "";
if (column === "modified" || column === "uploaded") {
const dateA = new Date(valA);
const dateB = new Date(valB);
if (!isNaN(dateA.getTime()) && !isNaN(dateB.getTime())) {
valA = dateA.getTime();
valB = dateB.getTime();
} else {
valA = valA.toLowerCase();
valB = valB.toLowerCase();
}
} else if (typeof valA === "string") {
valA = valA.toLowerCase();
valB = valB.toLowerCase();
}
if (valA < valB) return sortOrder.ascending ? -1 : 1;
if (valA > valB) return sortOrder.ascending ? 1 : -1;
return 0;
});
renderFileTable();
}
export function renderFileTable() {
const fileListContainer = document.getElementById("fileList");
let tableHTML = `<table class="table">
<thead>
<tr>
<th><input type="checkbox" id="selectAll" onclick="toggleAllCheckboxes(this)"></th>
@@ -67,8 +77,8 @@ function renderFileTable() {
<th onclick="sortFiles('uploaded')" style="cursor:pointer; text-decoration: underline; white-space: nowrap;">
<span>Upload Date</span> <span>${sortOrder.column === "uploaded" ? (sortOrder.ascending ? "▲" : "▼") : ""}</span>
</th>
<th onclick="sortFiles('sizeBytes')" style="cursor:pointer; text-decoration: underline; white-space: nowrap;">
<span>File Size</span> <span>${sortOrder.column === "sizeBytes" ? (sortOrder.ascending ? "▲" : "▼") : ""}</span>
<th onclick="sortFiles('size')" style="cursor:pointer; text-decoration: underline; white-space: nowrap;">
<span>File Size</span> <span>${sortOrder.column === "size" ? (sortOrder.ascending ? "▲" : "▼") : ""}</span>
</th>
<th onclick="sortFiles('uploader')" style="cursor:pointer; text-decoration: underline; white-space: nowrap;">
<span>Uploader</span> <span>${sortOrder.column === "uploader" ? (sortOrder.ascending ? "▲" : "▼") : ""}</span>
@@ -77,18 +87,18 @@ function renderFileTable() {
</tr>
</thead>
<tbody>`;
fileData.forEach(file => {
const isEditable = file.name.endsWith(".txt") || file.name.endsWith(".json") ||
file.name.endsWith(".ini") || file.name.endsWith(".css") ||
file.name.endsWith(".js") || file.name.endsWith(".csv") ||
file.name.endsWith(".md") || file.name.endsWith(".xml") ||
file.name.endsWith(".html") || file.name.endsWith(".py") ||
file.name.endsWith(".log") || file.name.endsWith(".conf") ||
file.name.endsWith(".config") || file.name.endsWith(".bat") ||
file.name.endsWith(".rtf") || file.name.endsWith(".doc") ||
file.name.endsWith(".docx");
tableHTML += `<tr>
fileData.forEach(file => {
const isEditable = file.name.endsWith(".txt") || file.name.endsWith(".json") ||
file.name.endsWith(".ini") || file.name.endsWith(".css") ||
file.name.endsWith(".js") || file.name.endsWith(".csv") ||
file.name.endsWith(".md") || file.name.endsWith(".xml") ||
file.name.endsWith(".html") || file.name.endsWith(".py") ||
file.name.endsWith(".log") || file.name.endsWith(".conf") ||
file.name.endsWith(".config") || file.name.endsWith(".bat") ||
file.name.endsWith(".rtf") || file.name.endsWith(".doc") ||
file.name.endsWith(".docx");
tableHTML += `<tr>
<td><input type="checkbox" class="file-checkbox" value="${file.name}" onclick="toggleDeleteButton()"></td>
<td>${file.name}</td>
<td style="white-space: nowrap;">${file.modified}</td>
@@ -102,73 +112,60 @@ function renderFileTable() {
</div>
</td>
</tr>`;
});
tableHTML += `</tbody></table>`;
fileListContainer.innerHTML = tableHTML;
// Always display the batch delete button if there are files; disable it if no file is selected.
const deleteBtn = document.getElementById("deleteSelectedBtn");
if (fileData.length > 0) {
deleteBtn.style.display = "block";
// Check if any checkboxes are selected to enable the button; if none, disable it.
const selectedFiles = document.querySelectorAll(".file-checkbox:checked");
deleteBtn.disabled = selectedFiles.length === 0;
} else {
deleteBtn.style.display = "none";
}
}
// Function to toggle delete button enabled state
function toggleDeleteButton() {
});
tableHTML += `</tbody></table>`;
fileListContainer.innerHTML = tableHTML;
const deleteBtn = document.getElementById("deleteSelectedBtn");
if (fileData.length > 0) {
deleteBtn.style.display = "block";
const selectedFiles = document.querySelectorAll(".file-checkbox:checked");
const deleteBtn = document.getElementById("deleteSelectedBtn");
deleteBtn.disabled = selectedFiles.length === 0;
} else {
deleteBtn.style.display = "none";
}
}
// Select/Deselect All Checkboxes
window.toggleAllCheckboxes = function (source) {
const checkboxes = document.querySelectorAll(".file-checkbox");
checkboxes.forEach(checkbox => checkbox.checked = source.checked);
toggleDeleteButton();
};
export function toggleDeleteButton() {
const selectedFiles = document.querySelectorAll(".file-checkbox:checked");
const deleteBtn = document.getElementById("deleteSelectedBtn");
deleteBtn.disabled = selectedFiles.length === 0;
}
// Batch delete function
window.deleteSelectedFiles = function () {
const selectedFiles = Array.from(document.querySelectorAll(".file-checkbox:checked"))
.map(checkbox => checkbox.value);
if (selectedFiles.length === 0) {
alert("No files selected for deletion.");
return;
}
if (!confirm(`Are you sure you want to delete the selected files?`)) {
return;
}
fetch("deleteFiles.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ files: selectedFiles })
})
.then(response => response.json())
export function toggleAllCheckboxes(source) {
const checkboxes = document.querySelectorAll(".file-checkbox");
checkboxes.forEach(checkbox => checkbox.checked = source.checked);
toggleDeleteButton();
}
export function deleteSelectedFiles() {
const selectedFiles = Array.from(document.querySelectorAll(".file-checkbox:checked"))
.map(checkbox => checkbox.value);
if (selectedFiles.length === 0) {
alert("No files selected for deletion.");
return;
}
if (!confirm("Are you sure you want to delete the selected files?")) {
return;
}
sendRequest("deleteFiles.php", "POST", { files: selectedFiles })
.then(result => {
alert(result.success || result.error);
loadFileList();
alert(result.success || result.error);
loadFileList();
})
.catch(error => console.error("Error deleting files:", error));
};
}
// Attach event listener to batch delete button
document.addEventListener("DOMContentLoaded", function () {
const deleteBtn = document.getElementById("deleteSelectedBtn");
if (deleteBtn) {
deleteBtn.addEventListener("click", deleteSelectedFiles);
}
const deleteBtn = document.getElementById("deleteSelectedBtn");
if (deleteBtn) {
deleteBtn.addEventListener("click", deleteSelectedFiles);
}
});
window.editFile = function(fileName) {
export function editFile(fileName) {
const threshold = 10 * 1024 * 1024; // 10 MB threshold
// Check file size via HEAD request.
fetch(`uploads/${encodeURIComponent(fileName)}`, { method: 'HEAD' })
.then(response => {
const fileSize = parseInt(response.headers.get('Content-Length') || "0", 10);
@@ -187,7 +184,6 @@ window.editFile = function(fileName) {
if (!content) return;
const modal = document.createElement("div");
modal.id = "editorContainer";
// Use your existing classes for styling.
modal.classList.add("modal", "editor-modal");
modal.innerHTML = `
<h3>Editing: ${fileName}</h3>
@@ -201,28 +197,32 @@ window.editFile = function(fileName) {
modal.style.display = "block";
})
.catch(error => console.error("Error in editFile:", error));
};
}
window.saveFile = function(fileName) {
const editor = document.getElementById("fileEditor");
if (!editor) {
console.error("Editor not found!");
return;
}
const fileData = {
fileName: fileName,
content: editor.value
};
fetch("saveFile.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(fileData)
})
.then(response => response.json())
export function saveFile(fileName) {
const editor = document.getElementById("fileEditor");
if (!editor) {
console.error("Editor not found!");
return;
}
const fileData = {
fileName: fileName,
content: editor.value
};
sendRequest("saveFile.php", "POST", fileData)
.then(result => {
alert(result.success || result.error);
document.getElementById("editorContainer")?.remove();
loadFileList();
alert(result.success || result.error);
document.getElementById("editorContainer")?.remove();
loadFileList();
})
.catch(error => console.error("Error saving file:", error));
};
}
// To support inline onclick attributes in the generated HTML, attach these functions to window.
window.sortFiles = sortFiles;
window.toggleDeleteButton = toggleDeleteButton;
window.toggleAllCheckboxes = toggleAllCheckboxes;
window.deleteSelectedFiles = deleteSelectedFiles;
window.editFile = editFile;
window.saveFile = saveFile;
window.loadFileList = loadFileList;