more commits..

This commit is contained in:
pika 2025-03-23 03:53:45 +01:00
parent 6dda02141e
commit 7823be6481
20 changed files with 1835 additions and 631 deletions

View file

@ -243,4 +243,133 @@ document.addEventListener('DOMContentLoaded', function () {
document.getElementById('new-name').focus();
});
}
});
// Delete functionality
const deleteModal = document.getElementById('delete-modal');
const deleteForm = document.getElementById('delete-form');
const deleteItemIdInput = document.getElementById('delete-item-id');
if (deleteModal && deleteForm) {
// Update the form action when the modal is shown
document.querySelectorAll('.action-btn.delete').forEach(btn => {
btn.addEventListener('click', function (e) {
e.preventDefault();
e.stopPropagation();
const itemElement = this.closest('.folder-item, .file-item');
const itemId = itemElement.dataset.id;
// Set the item ID in the form
deleteItemIdInput.value = itemId;
// Update the form action URL
const formAction = deleteForm.action;
deleteForm.action = formAction.replace('placeholder', itemId);
// Show the modal
deleteModal.classList.add('active');
});
});
// Close modal when cancel is clicked
deleteModal.querySelector('.modal-cancel').addEventListener('click', function () {
deleteModal.classList.remove('active');
});
// Close modal when X is clicked
deleteModal.querySelector('.modal-close').addEventListener('click', function () {
deleteModal.classList.remove('active');
});
}
});
// Browser-specific functionality
document.addEventListener('DOMContentLoaded', function () {
// Initialize folder browser view
initializeFolderBrowser();
});
function initializeFolderBrowser() {
// Handle item selection
const items = document.querySelectorAll('.folder-item, .file-item');
items.forEach(item => {
item.addEventListener('click', function (e) {
// Only select if not clicking on an action button
if (!e.target.closest('.file-actions')) {
// Remove selection from all items
items.forEach(i => i.classList.remove('selected'));
// Select this item
this.classList.add('selected');
}
});
});
// Handle folder creation form submission
const newFolderForm = document.getElementById('new-folder-form');
if (newFolderForm) {
newFolderForm.addEventListener('submit', function (e) {
// Form will be submitted normally, we just close the modal
const modal = document.getElementById('new-folder-modal');
if (modal) {
modal.classList.remove('active');
}
});
}
// Handle file/folder actions from context menu
document.querySelectorAll('.context-menu-item').forEach(item => {
item.addEventListener('click', function () {
const action = this.getAttribute('data-action');
const menu = this.closest('.context-menu');
const itemId = menu.getAttribute('data-item-id');
const itemType = menu.getAttribute('data-item-type');
// Handle different actions
switch (action) {
case 'open':
if (itemType === 'folder') {
window.location.href = `/files/browser/${itemId}`;
}
break;
case 'download':
if (itemType === 'file') {
window.location.href = `/files/download/${itemId}`;
}
break;
case 'share':
// TODO: Implement share functionality
alert('Share functionality coming soon');
break;
case 'rename':
// TODO: Implement rename functionality
alert('Rename functionality coming soon');
break;
case 'delete':
if (confirm(`Are you sure you want to delete this ${itemType}?`)) {
// Send delete request to server
fetch(`/files/delete/${itemType}/${itemId}`, {
method: 'POST',
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Remove item from DOM
document.querySelector(`[data-id="${itemId}"]`).remove();
} else {
alert(`Failed to delete ${itemType}: ${data.error}`);
}
})
.catch(error => {
console.error('Error:', error);
alert(`An error occurred while deleting the ${itemType}`);
});
}
break;
}
// Hide menu after action
menu.style.display = 'none';
});
});
}

View file

@ -17,6 +17,12 @@ document.addEventListener('DOMContentLoaded', function () {
console.log('Service Worker registration failed:', error);
});
}
// Initialize flash message close buttons
initFlashMessages();
// Initialize any other global functionality
initGlobalDropzone();
});
// Toggle between grid and list views
@ -205,4 +211,82 @@ function initializeUploadFunctionality() {
}
});
}
}
function initFlashMessages() {
document.querySelectorAll('.flash-close').forEach(btn => {
btn.addEventListener('click', function () {
this.closest('.flash-message').remove();
});
});
}
function initGlobalDropzone() {
// Setup global dropzone for file uploads
const body = document.body;
// Only setup if we're on a page that can handle uploads
if (document.getElementById('file-upload')) {
// Create dropzone overlay if it doesn't exist
if (!document.querySelector('.global-dropzone')) {
const dropzone = document.createElement('div');
dropzone.className = 'global-dropzone';
dropzone.innerHTML = `
<div class="dropzone-content">
<div class="dropzone-icon">
<i class="fas fa-cloud-upload-alt fa-3x"></i>
</div>
<h3>Drop files to upload</h3>
<p>Your files will be uploaded to the current folder</p>
</div>
`;
document.body.appendChild(dropzone);
}
// Get the dropzone element
const dropzone = document.querySelector('.global-dropzone');
// Handle drag events
body.addEventListener('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
dropzone.classList.add('active');
});
body.addEventListener('dragleave', function (e) {
if (e.target === body || e.target === dropzone) {
dropzone.classList.remove('active');
}
});
dropzone.addEventListener('dragleave', function (e) {
if (e.target === dropzone) {
dropzone.classList.remove('active');
}
});
dropzone.addEventListener('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
});
dropzone.addEventListener('drop', function (e) {
e.preventDefault();
e.stopPropagation();
dropzone.classList.remove('active');
// Get the file input element
const fileInput = document.getElementById('file-upload');
// Handle the dropped files
if (e.dataTransfer.files.length > 0) {
// Set the files to the file input
fileInput.files = e.dataTransfer.files;
// Trigger the change event
const event = new Event('change', { bubbles: true });
fileInput.dispatchEvent(event);
}
});
}
}

View file

@ -0,0 +1,40 @@
// Mobile Menu Functionality
document.addEventListener('DOMContentLoaded', function () {
const mobileFab = document.getElementById('mobile-fab');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileFab && mobileMenu) {
// Toggle menu on FAB click
mobileFab.addEventListener('click', function () {
this.classList.toggle('active');
mobileMenu.classList.toggle('active');
});
// Add staggered animation to menu items
const menuItems = document.querySelectorAll('.mobile-menu-item');
menuItems.forEach((item, index) => {
item.style.transitionDelay = `${index * 0.05}s`;
});
// Close menu when clicking outside
document.addEventListener('click', function (e) {
if (mobileMenu.classList.contains('active') &&
!mobileFab.contains(e.target) &&
!mobileMenu.contains(e.target)) {
mobileFab.classList.remove('active');
mobileMenu.classList.remove('active');
}
});
// Add hover effect to menu items
menuItems.forEach(item => {
item.addEventListener('mouseenter', function () {
this.style.transform = 'translateX(-5px)';
});
item.addEventListener('mouseleave', function () {
this.style.transform = '';
});
});
}
});

86
app/static/js/modal.js Normal file
View file

@ -0,0 +1,86 @@
// Modal management script
document.addEventListener('DOMContentLoaded', function () {
// Initialize all modals
initializeModals();
});
function initializeModals() {
// Setup modal triggers
document.querySelectorAll('[data-toggle="modal"]').forEach(trigger => {
const targetId = trigger.getAttribute('data-target');
const targetModal = document.querySelector(targetId);
if (targetModal) {
trigger.addEventListener('click', function (e) {
e.preventDefault();
openModal(targetId);
});
}
});
// Setup direct modal triggers (like the new folder button)
const newFolderBtn = document.getElementById('new-folder-btn');
if (newFolderBtn) {
newFolderBtn.addEventListener('click', function () {
openModal('#new-folder-modal');
});
}
const emptyNewFolderBtn = document.getElementById('empty-new-folder-btn');
if (emptyNewFolderBtn) {
emptyNewFolderBtn.addEventListener('click', function () {
openModal('#new-folder-modal');
});
}
// Close buttons
document.querySelectorAll('.modal-close, .modal-cancel').forEach(closeBtn => {
closeBtn.addEventListener('click', function () {
const modal = this.closest('.modal');
if (modal) {
closeModal('#' + modal.id);
}
});
});
// Close on background click
document.querySelectorAll('.modal').forEach(modal => {
modal.addEventListener('click', function (e) {
if (e.target === this) {
closeModal('#' + this.id);
}
});
});
// Close on escape key
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
const activeModal = document.querySelector('.modal.active');
if (activeModal) {
closeModal('#' + activeModal.id);
}
}
});
}
// Open a modal by ID
function openModal(modalId) {
const modal = typeof modalId === 'string' ?
document.querySelector(modalId) :
modalId;
if (modal) {
modal.classList.add('active');
}
}
// Close a modal by ID
function closeModal(modalId) {
const modal = typeof modalId === 'string' ?
document.querySelector(modalId) :
modalId;
if (modal) {
modal.classList.remove('active');
}
}

View file

@ -470,4 +470,143 @@ document.addEventListener('DOMContentLoaded', function () {
});
}
}
// File upload functionality
const uploadBtn = document.querySelector('.btn.primary [class*="fa-upload"]');
const fileInput = document.getElementById('file-upload');
// Check if we're on upload page or have upload elements
if (uploadBtn && fileInput) {
uploadBtn.addEventListener('click', function (e) {
// Trigger the hidden file input
fileInput.click();
});
fileInput.addEventListener('change', function () {
if (this.files.length) {
handleFileUpload(this.files);
}
});
// Setup drag and drop zone if exists
const dropzone = document.getElementById('dropzone');
if (dropzone) {
setupDragAndDrop(dropzone);
}
}
// Handle file upload process
function handleFileUpload(files) {
// Show progress indicator
showUploadProgress();
const formData = new FormData();
// Add all files to FormData
for (let i = 0; i < files.length; i++) {
formData.append('file', files[i]);
}
// Get current folder ID from URL if available
const urlParams = new URLSearchParams(window.location.search);
const folderId = urlParams.get('folder_id');
if (folderId) {
formData.append('folder_id', folderId);
}
// Submit the upload
fetch('/files/upload', {
method: 'POST',
body: formData
})
.then(response => {
if (!response.ok) {
throw new Error('Upload failed');
}
return response.json();
})
.then(data => {
if (data.success) {
// Show success message
showUploadSuccess();
// Refresh the page to show the new file
setTimeout(() => {
window.location.reload();
}, 1000);
} else {
showUploadError(data.error || 'Upload failed');
}
})
.catch(error => {
console.error('Error:', error);
showUploadError('An error occurred during upload');
})
.finally(() => {
// Hide progress indicator
hideUploadProgress();
});
}
// Setup drag and drop functionality
function setupDragAndDrop(dropzone) {
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropzone.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, unhighlight, false);
});
function highlight() {
dropzone.classList.add('highlight');
}
function unhighlight() {
dropzone.classList.remove('highlight');
}
dropzone.addEventListener('drop', handleDrop, false);
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
if (files.length > 0) {
handleFileUpload(files);
}
}
}
// UI feedback functions
function showUploadProgress() {
// Implementation depends on your UI
console.log('Uploading...');
// Could show a toast notification or progress bar
}
function hideUploadProgress() {
// Hide any progress indicators
}
function showUploadSuccess() {
// Show success message
console.log('Upload successful!');
}
function showUploadError(message) {
// Show error message
console.error('Upload error:', message);
alert('Upload failed: ' + message);
}
});