Double root empty folder fix, side bar drag zone adjusted
This commit is contained in:
20
README.md
20
README.md
@@ -9,7 +9,7 @@ https://github.com/user-attachments/assets/179e6940-5798-4482-9a69-696f806c37de
|
|||||||
|
|
||||||
changelogs available here: <https://github.com/error311/FileRise-docker/>
|
changelogs available here: <https://github.com/error311/FileRise-docker/>
|
||||||
|
|
||||||
FileRise - Multi File Upload Editor is a lightweight, secure, self-hosted web application for uploading, syntax highlight editing, drag & drop and managing files. Built with an Apache/PHP backend and a modern JavaScript (ES6 modules) frontend, it offers a responsive, dynamic file management interface. It serves as an alternative to solutions like FileGator TinyFileManager or ProjectSend, providing an easy-to-setup experience ideal for document management, image galleries, firmware file hosting, and more.
|
FileRise is a lightweight, secure, self-hosted web application for uploading, syntax-highlight editing, drag & drop file management, and more. Built with an Apache/PHP backend and a modern JavaScript (ES6 modules) frontend, it offers a responsive and dynamic interface designed to simplify file handling. As an alternative to solutions like FileGator, TinyFileManager, or ProjectSend, FileRise provides an easy-to-set-up experience ideal for document management, image galleries, firmware hosting, and other file-intensive applications.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ FileRise - Multi File Upload Editor is a lightweight, secure, self-hosted web ap
|
|||||||
- **Move Files:** Move selected files to a different folder, automatically generating a unique filename if needed to avoid data loss.
|
- **Move Files:** Move selected files to a different folder, automatically generating a unique filename if needed to avoid data loss.
|
||||||
- **Download Files as ZIP:** Download selected files as a ZIP archive. Users can specify a custom name for the ZIP file via a modal dialog.
|
- **Download Files as ZIP:** Download selected files as a ZIP archive. Users can specify a custom name for the ZIP file via a modal dialog.
|
||||||
- **Extract Zip:** When one or more ZIP files are selected, users can extract the archive(s) directly into the current folder.
|
- **Extract Zip:** When one or more ZIP files are selected, users can extract the archive(s) directly into the current folder.
|
||||||
- **Drag & Drop:** Easily move files by selecting them from the file list and simply dragging them onto your desired folder in the folder tree or breadcrumb. When you drop the files onto a folder, the system automatically moves them, updating your file organization in one seamless action.
|
- **Drag & Drop (File Movement):** Easily move files by selecting them from the file list and dragging them onto your desired folder in the folder tree or breadcrumb. When you drop the files onto a folder, the system automatically moves them, updating your file organization in one seamless action.
|
||||||
- **Enhanced Context Menu & Keyboard Shortcuts:**
|
- **Enhanced Context Menu & Keyboard Shortcuts:**
|
||||||
- **Right-Click Context Menu:**
|
- **Right-Click Context Menu:**
|
||||||
- A custom context menu appears on right-clicking within the file list.
|
- A custom context menu appears on right-clicking within the file list.
|
||||||
@@ -126,6 +126,16 @@ FileRise - Multi File Upload Editor is a lightweight, secure, self-hosted web ap
|
|||||||
- The trash modal displays details such as file name, uploader/deleter, and the trashed date/time.
|
- The trash modal displays details such as file name, uploader/deleter, and the trashed date/time.
|
||||||
- Material icons with tooltips visually represent the restore and delete actions.
|
- Material icons with tooltips visually represent the restore and delete actions.
|
||||||
|
|
||||||
|
- **Drag & Drop Cards with Dedicated Drop Zones:**
|
||||||
|
- **Sidebar Drop Zone:**
|
||||||
|
- Cards (such as the upload card or folder management card) can be dragged into a dedicated sidebar drop zone for quick access to frequently used operations.
|
||||||
|
- The sidebar drop zone expands dynamically to accept drops anywhere within its visual area.
|
||||||
|
- **Top Bar Drop Zone:**
|
||||||
|
- A top drop zone is available for reordering or managing cards quickly.
|
||||||
|
- Dragging a card to the top drop zone provides immediate visual feedback, ensuring a fluid and customizable workflow.
|
||||||
|
- **Seamless Interaction:**
|
||||||
|
- Both drop zones support smooth drag and drop interactions with animations and pointer event adjustments to prevent interference, ensuring that cards can be dropped reliably regardless of screen position.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
@@ -214,6 +224,12 @@ For users who prefer containerization, a Docker image is available
|
|||||||
docker pull error311/filerise-docker:latest
|
docker pull error311/filerise-docker:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
macos M series:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker pull --platform linux/x86_64 error311/filerise-docker:latest
|
||||||
|
```
|
||||||
|
|
||||||
2. **Run the Container:**
|
2. **Run the Container:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ export function loadSidebarOrder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Vertical slide/fade animation helper.
|
// Vertical slide/fade animation helper.
|
||||||
// It sets an initial vertical offset (30px down) and opacity 0, then animates to normal position and full opacity.
|
|
||||||
function animateVerticalSlide(card) {
|
function animateVerticalSlide(card) {
|
||||||
card.style.transform = 'translateY(30px)';
|
card.style.transform = 'translateY(30px)';
|
||||||
card.style.opacity = '0';
|
card.style.opacity = '0';
|
||||||
@@ -213,7 +212,17 @@ export function loadSidebarOrder() {
|
|||||||
dragTimer = setTimeout(() => {
|
dragTimer = setTimeout(() => {
|
||||||
isDragging = true;
|
isDragging = true;
|
||||||
card.classList.add('dragging');
|
card.classList.add('dragging');
|
||||||
|
// Disable pointer events on the card so it doesn't block drop detection.
|
||||||
|
card.style.pointerEvents = 'none';
|
||||||
addTopZoneHighlight();
|
addTopZoneHighlight();
|
||||||
|
const sidebar = document.getElementById('sidebarDropArea');
|
||||||
|
if (sidebar) {
|
||||||
|
sidebar.classList.add('active');
|
||||||
|
sidebar.style.display = 'block';
|
||||||
|
sidebar.classList.add('highlight');
|
||||||
|
// Force the sidebar to have a tall drop zone while dragging.
|
||||||
|
sidebar.style.height = '800px';
|
||||||
|
}
|
||||||
const rect = card.getBoundingClientRect();
|
const rect = card.getBoundingClientRect();
|
||||||
initialLeft = rect.left + window.pageXOffset;
|
initialLeft = rect.left + window.pageXOffset;
|
||||||
initialTop = rect.top + window.pageYOffset;
|
initialTop = rect.top + window.pageYOffset;
|
||||||
@@ -225,12 +234,6 @@ export function loadSidebarOrder() {
|
|||||||
card.style.top = initialTop + 'px';
|
card.style.top = initialTop + 'px';
|
||||||
card.style.width = rect.width + 'px';
|
card.style.width = rect.width + 'px';
|
||||||
card.style.zIndex = '10000';
|
card.style.zIndex = '10000';
|
||||||
const sidebar = document.getElementById('sidebarDropArea');
|
|
||||||
if (sidebar) {
|
|
||||||
sidebar.classList.add('active');
|
|
||||||
sidebar.style.display = 'block';
|
|
||||||
sidebar.classList.add('highlight');
|
|
||||||
}
|
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
header.addEventListener('mouseup', function () {
|
header.addEventListener('mouseup', function () {
|
||||||
@@ -248,11 +251,15 @@ export function loadSidebarOrder() {
|
|||||||
document.addEventListener('mouseup', function (e) {
|
document.addEventListener('mouseup', function (e) {
|
||||||
if (isDragging) {
|
if (isDragging) {
|
||||||
isDragging = false;
|
isDragging = false;
|
||||||
|
// Re-enable pointer events on the card.
|
||||||
|
card.style.pointerEvents = '';
|
||||||
card.classList.remove('dragging');
|
card.classList.remove('dragging');
|
||||||
removeTopZoneHighlight();
|
removeTopZoneHighlight();
|
||||||
const sidebar = document.getElementById('sidebarDropArea');
|
const sidebar = document.getElementById('sidebarDropArea');
|
||||||
if (sidebar) {
|
if (sidebar) {
|
||||||
sidebar.classList.remove('highlight');
|
sidebar.classList.remove('highlight');
|
||||||
|
// Remove the forced height once the drag ends.
|
||||||
|
sidebar.style.height = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const leftCol = document.getElementById('leftCol');
|
const leftCol = document.getElementById('leftCol');
|
||||||
@@ -262,12 +269,15 @@ export function loadSidebarOrder() {
|
|||||||
|
|
||||||
const sidebarElem = document.getElementById('sidebarDropArea');
|
const sidebarElem = document.getElementById('sidebarDropArea');
|
||||||
if (sidebarElem) {
|
if (sidebarElem) {
|
||||||
|
// Instead of using elementsFromPoint, use a virtual drop zone.
|
||||||
const rect = sidebarElem.getBoundingClientRect();
|
const rect = sidebarElem.getBoundingClientRect();
|
||||||
|
// Define a drop zone from the top of the sidebar to 1000px below its top.
|
||||||
|
const dropZoneBottom = rect.top + 800;
|
||||||
if (
|
if (
|
||||||
e.clientX >= rect.left &&
|
e.clientX >= rect.left &&
|
||||||
e.clientX <= rect.right &&
|
e.clientX <= rect.right &&
|
||||||
e.clientY >= rect.top &&
|
e.clientY >= rect.top &&
|
||||||
e.clientY <= rect.bottom
|
e.clientY <= dropZoneBottom
|
||||||
) {
|
) {
|
||||||
insertCardInSidebar(card, e);
|
insertCardInSidebar(card, e);
|
||||||
droppedInSidebar = true;
|
droppedInSidebar = true;
|
||||||
@@ -299,7 +309,7 @@ export function loadSidebarOrder() {
|
|||||||
card.style.position = 'absolute';
|
card.style.position = 'absolute';
|
||||||
card.style.left = '0px';
|
card.style.left = '0px';
|
||||||
|
|
||||||
// For top drop, animate vertical slide/fade.
|
// Animate vertical slide/fade.
|
||||||
card.style.transform = 'translateY(30px)';
|
card.style.transform = 'translateY(30px)';
|
||||||
card.style.opacity = '0';
|
card.style.opacity = '0';
|
||||||
|
|
||||||
@@ -317,7 +327,6 @@ export function loadSidebarOrder() {
|
|||||||
card.style.transition = '';
|
card.style.transition = '';
|
||||||
card.style.transform = '';
|
card.style.transform = '';
|
||||||
card.style.opacity = '';
|
card.style.opacity = '';
|
||||||
// Ensure the card returns to full width (via CSS: width: 100%)
|
|
||||||
card.style.width = '';
|
card.style.width = '';
|
||||||
}, 310);
|
}, 310);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ function getParentFolder(folder) {
|
|||||||
// Breadcrumb Functions
|
// Breadcrumb Functions
|
||||||
// ----------------------
|
// ----------------------
|
||||||
// Render breadcrumb for a normalized folder path.
|
// Render breadcrumb for a normalized folder path.
|
||||||
// For example, if window.currentFolder is "Folder1/Folder1SubFolder2",
|
|
||||||
// this will return: Root / Folder1 / Folder1SubFolder2.
|
|
||||||
function renderBreadcrumb(normalizedFolder) {
|
function renderBreadcrumb(normalizedFolder) {
|
||||||
if (normalizedFolder === "root") {
|
if (normalizedFolder === "root") {
|
||||||
return `<span class="breadcrumb-link" data-folder="root">Root</span>`;
|
return `<span class="breadcrumb-link" data-folder="root">Root</span>`;
|
||||||
@@ -310,13 +308,7 @@ export async function loadFolderTree(selectedFolder) {
|
|||||||
<span class="folder-toggle" data-folder="root">[<span class="custom-dash">-</span>]</span>
|
<span class="folder-toggle" data-folder="root">[<span class="custom-dash">-</span>]</span>
|
||||||
<span class="folder-option root-folder-option" data-folder="root">(Root)</span>
|
<span class="folder-option root-folder-option" data-folder="root">(Root)</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
if (folders.length === 0) {
|
if (folders.length > 0) {
|
||||||
html += `<ul class="folder-tree expanded">
|
|
||||||
<li class="folder-item">
|
|
||||||
<span class="folder-option" data-folder="root">(Root)</span>
|
|
||||||
</li>
|
|
||||||
</ul>`;
|
|
||||||
} else {
|
|
||||||
const tree = buildFolderTree(folders);
|
const tree = buildFolderTree(folders);
|
||||||
html += renderFolderTree(tree, "", "block");
|
html += renderFolderTree(tree, "", "block");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user