Folder sharing added
This commit is contained in:
@@ -2,7 +2,7 @@ import { showToast, toggleVisibility, attachEnterKeyListener } from './domUtils.
|
||||
import { sendRequest } from './networkUtils.js';
|
||||
import { t, applyTranslations, setLocale } from './i18n.js';
|
||||
|
||||
const version = "v1.0.9";
|
||||
const version = "v1.1.0";
|
||||
const adminTitle = `Admin Panel <small style="font-size: 12px; color: gray;">${version}</small>`;
|
||||
|
||||
let lastLoginData = null;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { loadFileList } from './fileListView.js';
|
||||
import { showToast, escapeHTML, attachEnterKeyListener } from './domUtils.js';
|
||||
import { t } from './i18n.js';
|
||||
import { openFolderShareModal } from './folderShareModal.js';
|
||||
|
||||
/* ----------------------
|
||||
Helper Functions (Data/State)
|
||||
@@ -418,7 +419,7 @@ export async function loadFolderTree(selectedFolder) {
|
||||
localStorage.setItem("lastOpenedFolder", window.currentFolder);
|
||||
|
||||
const titleEl = document.getElementById("fileListTitle");
|
||||
titleEl.innerHTML = "Files in (" + renderBreadcrumb(window.currentFolder) + ")";
|
||||
titleEl.innerHTML = t("files_in") + " (" + renderBreadcrumb(window.currentFolder) + ")";
|
||||
setupBreadcrumbDelegation();
|
||||
loadFileList(window.currentFolder);
|
||||
|
||||
@@ -442,7 +443,7 @@ export async function loadFolderTree(selectedFolder) {
|
||||
window.currentFolder = selected;
|
||||
localStorage.setItem("lastOpenedFolder", selected);
|
||||
const titleEl = document.getElementById("fileListTitle");
|
||||
titleEl.innerHTML = "Files in (" + renderBreadcrumb(selected) + ")";
|
||||
titleEl.innerHTML = t("files_in") + " (" + renderBreadcrumb(selected) + ")";
|
||||
setupBreadcrumbDelegation();
|
||||
loadFileList(selected);
|
||||
});
|
||||
@@ -735,18 +736,22 @@ function folderManagerContextMenuHandler(e) {
|
||||
target.classList.add("selected");
|
||||
const menuItems = [
|
||||
{
|
||||
label: "Create Folder",
|
||||
label: t("create_folder"),
|
||||
action: () => {
|
||||
document.getElementById("createFolderModal").style.display = "block";
|
||||
document.getElementById("newFolderName").focus();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Rename Folder",
|
||||
label: t("rename_folder"),
|
||||
action: () => { openRenameFolderModal(); }
|
||||
},
|
||||
{
|
||||
label: "Delete Folder",
|
||||
label: t("folder_share"),
|
||||
action: () => { openFolderShareModal(); }
|
||||
},
|
||||
{
|
||||
label: t("delete_folder"),
|
||||
action: () => { openDeleteFolderModal(); }
|
||||
}
|
||||
];
|
||||
@@ -785,4 +790,21 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const shareFolderBtn = document.getElementById("shareFolderBtn");
|
||||
if (shareFolderBtn) {
|
||||
shareFolderBtn.addEventListener("click", () => {
|
||||
const selectedFolder = window.currentFolder || "root";
|
||||
if (!selectedFolder || selectedFolder === "root") {
|
||||
showToast("Please select a valid folder to share.");
|
||||
return;
|
||||
}
|
||||
// Call the folder share modal from the module.
|
||||
openFolderShareModal(selectedFolder);
|
||||
});
|
||||
} else {
|
||||
console.warn("shareFolderBtn element not found in the DOM.");
|
||||
}
|
||||
});
|
||||
|
||||
bindFolderManagerContextMenu();
|
||||
107
js/folderShareModal.js
Normal file
107
js/folderShareModal.js
Normal file
@@ -0,0 +1,107 @@
|
||||
// folderShareModal.js
|
||||
import { escapeHTML, showToast } from './domUtils.js';
|
||||
import { t } from './i18n.js';
|
||||
|
||||
export function openFolderShareModal(folder) {
|
||||
// Remove any existing folder share modal
|
||||
const existing = document.getElementById("folderShareModal");
|
||||
if (existing) existing.remove();
|
||||
|
||||
// Create the modal container
|
||||
const modal = document.createElement("div");
|
||||
modal.id = "folderShareModal";
|
||||
modal.classList.add("modal");
|
||||
modal.innerHTML = `
|
||||
<div class="modal-content share-modal-content" style="width: 600px; max-width: 90vw;">
|
||||
<div class="modal-header">
|
||||
<h3>${t("share_folder")}: ${escapeHTML(folder)}</h3>
|
||||
<span class="close-image-modal" id="closeFolderShareModal" title="Close">×</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>${t("set_expiration")}</p>
|
||||
<select id="folderShareExpiration">
|
||||
<option value="30">30 ${t("minutes")}</option>
|
||||
<option value="60" selected>60 ${t("minutes")}</option>
|
||||
<option value="120">120 ${t("minutes")}</option>
|
||||
<option value="180">180 ${t("minutes")}</option>
|
||||
<option value="240">240 ${t("minutes")}</option>
|
||||
<option value="1440">1 ${t("day")}</option>
|
||||
</select>
|
||||
<p>${t("password_optional")}</p>
|
||||
<input type="text" id="folderSharePassword" placeholder="${t("password")}" style="width: 100%;"/>
|
||||
<br>
|
||||
<label>
|
||||
<input type="checkbox" id="folderShareAllowUpload"> ${t("allow_uploads")}
|
||||
</label>
|
||||
<br><br>
|
||||
<button id="generateFolderShareLinkBtn" class="btn btn-primary" style="margin-top: 10px;">${t("generate_share_link")}</button>
|
||||
<div id="folderShareLinkDisplay" style="margin-top: 10px; display: none;">
|
||||
<p>${t("shareable_link")}</p>
|
||||
<input type="text" id="folderShareLinkInput" readonly style="width: 100%;"/>
|
||||
<button id="copyFolderShareLinkBtn" class="btn btn-primary" style="margin-top: 5px;">${t("copy_link")}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(modal);
|
||||
modal.style.display = "block";
|
||||
|
||||
// Close button handler
|
||||
document.getElementById("closeFolderShareModal").addEventListener("click", () => {
|
||||
modal.remove();
|
||||
});
|
||||
|
||||
// Handler for generating the share link
|
||||
document.getElementById("generateFolderShareLinkBtn").addEventListener("click", () => {
|
||||
const expiration = document.getElementById("folderShareExpiration").value;
|
||||
const password = document.getElementById("folderSharePassword").value;
|
||||
const allowUpload = document.getElementById("folderShareAllowUpload").checked ? 1 : 0;
|
||||
|
||||
// Retrieve the CSRF token from the meta tag.
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute("content");
|
||||
if (!csrfToken) {
|
||||
showToast(t("csrf_error"));
|
||||
return;
|
||||
}
|
||||
// Post to the createFolderShareLink endpoint.
|
||||
fetch("/createFolderShareLink.php", {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-CSRF-Token": csrfToken
|
||||
},
|
||||
body: JSON.stringify({
|
||||
folder: folder,
|
||||
expirationMinutes: parseInt(expiration, 10),
|
||||
password: password,
|
||||
allowUpload: allowUpload
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.token && data.link) {
|
||||
const shareUrl = data.link;
|
||||
const displayDiv = document.getElementById("folderShareLinkDisplay");
|
||||
const inputField = document.getElementById("folderShareLinkInput");
|
||||
inputField.value = shareUrl;
|
||||
displayDiv.style.display = "block";
|
||||
showToast(t("share_link_generated"));
|
||||
} else {
|
||||
showToast(t("error_generating_share_link") + ": " + (data.error || t("unknown_error")));
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Error generating folder share link:", err);
|
||||
showToast(t("error_generating_share_link") + ": " + (err.error || t("unknown_error")));
|
||||
});
|
||||
});
|
||||
|
||||
// Copy share link button handler
|
||||
document.getElementById("copyFolderShareLinkBtn").addEventListener("click", () => {
|
||||
const input = document.getElementById("folderShareLinkInput");
|
||||
input.select();
|
||||
document.execCommand("copy");
|
||||
showToast(t("link_copied"));
|
||||
});
|
||||
}
|
||||
22
js/i18n.js
22
js/i18n.js
@@ -84,6 +84,7 @@ const translations = {
|
||||
|
||||
// File List keys:
|
||||
"file_list_title": "Files in (Root)",
|
||||
"files_in": "Files in",
|
||||
"delete_files": "Delete Files",
|
||||
"delete_selected_files_title": "Delete Selected Files",
|
||||
"delete_files_message": "Are you sure you want to delete the selected files?",
|
||||
@@ -126,6 +127,18 @@ const translations = {
|
||||
// Rename File keys:
|
||||
"rename_file_title": "Rename File",
|
||||
"rename_file_placeholder": "Enter new file name",
|
||||
|
||||
// Folder Share
|
||||
"share_folder": "Share Folder",
|
||||
"allow_uploads": "Allow Uploads",
|
||||
"share_link_generated": "Share Link Generated",
|
||||
"error_generating_share_link": "Error Generating Share Link",
|
||||
|
||||
// Folder
|
||||
"create_folder": "Create Folder",
|
||||
"rename_folder": "Rename Folder",
|
||||
"folder_share": "Share Folder",
|
||||
"delete_folder": "Delete Folder",
|
||||
|
||||
// Custom Confirm Modal keys:
|
||||
"yes": "Yes",
|
||||
@@ -136,7 +149,14 @@ const translations = {
|
||||
"copy": "Copy",
|
||||
"extract": "Extract",
|
||||
"user": "User:",
|
||||
"password": "Password:",
|
||||
"unknown_error": "Unknown Error",
|
||||
"link_copied": "Link Copied to Clipboard",
|
||||
"minutes": "minutes",
|
||||
"hours": "hours",
|
||||
"days": "days",
|
||||
"weeks": "weeks",
|
||||
"months": "months",
|
||||
"seconds": "seconds",
|
||||
|
||||
// Dark Mode Toggle
|
||||
"dark_mode_toggle": "Dark Mode",
|
||||
|
||||
@@ -48,9 +48,6 @@ function getFilesFromDataTransferItems(items) {
|
||||
return Promise.all(promises).then(results => results.flat());
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
UI Helpers (Mostly unchanged from your original code)
|
||||
----------------------------------------------------- */
|
||||
function setDropAreaDefault() {
|
||||
const dropArea = document.getElementById("uploadDropArea");
|
||||
if (dropArea) {
|
||||
|
||||
Reference in New Issue
Block a user