292 lines
No EOL
9.9 KiB
JavaScript
292 lines
No EOL
9.9 KiB
JavaScript
// Main JavaScript file for Flask Files
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// Initialize components
|
|
initializeViewToggle();
|
|
initializeFolderNavigation();
|
|
initializeModals();
|
|
initializeContextMenu();
|
|
initializeUploadFunctionality();
|
|
|
|
// Register service worker if supported
|
|
if ('serviceWorker' in navigator) {
|
|
navigator.serviceWorker.register('/static/js/service-worker.js')
|
|
.then(function (registration) {
|
|
console.log('Service Worker registered with scope:', registration.scope);
|
|
}).catch(function (error) {
|
|
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
|
|
function initializeViewToggle() {
|
|
const gridViewBtn = document.getElementById('grid-view-btn');
|
|
const listViewBtn = document.getElementById('list-view-btn');
|
|
const filesContainer = document.getElementById('files-container');
|
|
|
|
if (gridViewBtn && listViewBtn && filesContainer) {
|
|
gridViewBtn.addEventListener('click', function () {
|
|
filesContainer.classList.add('grid-view');
|
|
filesContainer.classList.remove('list-view');
|
|
gridViewBtn.classList.add('active');
|
|
listViewBtn.classList.remove('active');
|
|
localStorage.setItem('fileViewPreference', 'grid');
|
|
});
|
|
|
|
listViewBtn.addEventListener('click', function () {
|
|
filesContainer.classList.add('list-view');
|
|
filesContainer.classList.remove('grid-view');
|
|
listViewBtn.classList.add('active');
|
|
gridViewBtn.classList.remove('active');
|
|
localStorage.setItem('fileViewPreference', 'list');
|
|
});
|
|
|
|
// Load user preference from localStorage
|
|
const viewPreference = localStorage.getItem('fileViewPreference') || 'grid';
|
|
if (viewPreference === 'grid') {
|
|
gridViewBtn.click();
|
|
} else {
|
|
listViewBtn.click();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add animations for folder navigation
|
|
function initializeFolderNavigation() {
|
|
// Add click event to folder items
|
|
document.querySelectorAll('.folder-item').forEach(folder => {
|
|
folder.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
|
|
const href = this.getAttribute('href');
|
|
const filesContainer = document.getElementById('files-container');
|
|
|
|
// Add transition class
|
|
filesContainer.classList.add('changing');
|
|
|
|
// After a short delay, navigate to the folder
|
|
setTimeout(() => {
|
|
window.location.href = href;
|
|
}, 200);
|
|
});
|
|
});
|
|
|
|
// Add the animation class when page loads
|
|
const filesContainer = document.getElementById('files-container');
|
|
if (filesContainer) {
|
|
// Remove the class to trigger animation
|
|
filesContainer.classList.add('folder-enter-active');
|
|
}
|
|
}
|
|
|
|
// Modal handling
|
|
function initializeModals() {
|
|
// New folder modal
|
|
const newFolderBtn = document.getElementById('new-folder-btn');
|
|
const newFolderModal = document.getElementById('new-folder-modal');
|
|
const emptyNewFolderBtn = document.getElementById('empty-new-folder-btn');
|
|
|
|
if (newFolderBtn && newFolderModal) {
|
|
newFolderBtn.addEventListener('click', function () {
|
|
newFolderModal.style.display = 'flex';
|
|
document.getElementById('folder-name').focus();
|
|
});
|
|
|
|
if (emptyNewFolderBtn) {
|
|
emptyNewFolderBtn.addEventListener('click', function () {
|
|
newFolderModal.style.display = 'flex';
|
|
document.getElementById('folder-name').focus();
|
|
});
|
|
}
|
|
|
|
// Close modal
|
|
document.querySelectorAll('.modal-close, .modal-cancel').forEach(btn => {
|
|
btn.addEventListener('click', function () {
|
|
newFolderModal.style.display = 'none';
|
|
});
|
|
});
|
|
|
|
// Close on click outside
|
|
window.addEventListener('click', function (event) {
|
|
if (event.target === newFolderModal) {
|
|
newFolderModal.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Context menu for right-click on files/folders
|
|
function initializeContextMenu() {
|
|
const contextMenu = document.getElementById('context-menu');
|
|
|
|
if (!contextMenu) return;
|
|
|
|
document.addEventListener('contextmenu', function (e) {
|
|
const fileItem = e.target.closest('.file-item, .folder-item');
|
|
|
|
if (fileItem) {
|
|
e.preventDefault();
|
|
|
|
const itemId = fileItem.getAttribute('data-id');
|
|
const itemType = fileItem.classList.contains('file-item') ? 'file' : 'folder';
|
|
|
|
// Position menu
|
|
contextMenu.style.left = `${e.pageX}px`;
|
|
contextMenu.style.top = `${e.pageY}px`;
|
|
|
|
// Show menu
|
|
contextMenu.style.display = 'block';
|
|
contextMenu.setAttribute('data-item-id', itemId);
|
|
contextMenu.setAttribute('data-item-type', itemType);
|
|
|
|
// Set up buttons for different item types
|
|
setupContextMenuActions(contextMenu, itemId, itemType);
|
|
}
|
|
});
|
|
|
|
// Hide menu on click elsewhere
|
|
document.addEventListener('click', function () {
|
|
contextMenu.style.display = 'none';
|
|
});
|
|
}
|
|
|
|
function setupContextMenuActions(menu, itemId, itemType) {
|
|
// Show/hide appropriate actions based on item type
|
|
menu.querySelectorAll('[data-action]').forEach(action => {
|
|
const forType = action.getAttribute('data-for');
|
|
if (forType === 'all' || forType === itemType) {
|
|
action.style.display = 'block';
|
|
} else {
|
|
action.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
// Initialize file upload functionality
|
|
function initializeUploadFunctionality() {
|
|
const uploadBtn = document.querySelector('a[href*="upload"]');
|
|
const fileInput = document.getElementById('file-upload');
|
|
|
|
if (uploadBtn && fileInput) {
|
|
fileInput.addEventListener('change', function (e) {
|
|
if (this.files.length) {
|
|
const formData = new FormData();
|
|
|
|
for (let i = 0; i < this.files.length; i++) {
|
|
formData.append('file', this.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);
|
|
}
|
|
|
|
fetch('/files/upload', {
|
|
method: 'POST',
|
|
body: formData,
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Refresh page to show new file
|
|
window.location.reload();
|
|
} else {
|
|
alert('Upload failed: ' + data.error);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert('Upload failed. Please try again.');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
});
|
|
}
|
|
}
|