fix file batch deletion
This commit is contained in:
@@ -227,6 +227,16 @@ export class FileManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out folders and get only file IDs
|
||||
const fileIds = selectedItems
|
||||
.filter(item => item.type !== 'folder')
|
||||
.map(item => item.id);
|
||||
|
||||
if (fileIds.length === 0) {
|
||||
console.log('[FileManager] No files to download (only folders selected)');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/rooms/${this.roomManager.roomId}/files/download`, {
|
||||
method: 'POST',
|
||||
@@ -234,7 +244,7 @@ export class FileManager {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
},
|
||||
body: JSON.stringify({ file_ids: selectedItems.map(item => item.id) })
|
||||
body: JSON.stringify({ file_ids: fileIds })
|
||||
});
|
||||
console.log('[FileManager] Download response status:', response.status);
|
||||
|
||||
@@ -256,6 +266,7 @@ export class FileManager {
|
||||
console.log('[FileManager] Download initiated');
|
||||
} catch (error) {
|
||||
console.error('[FileManager] Error downloading files:', error);
|
||||
document.getElementById('fileError').textContent = 'Failed to download files. Please try again.';
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -322,14 +333,63 @@ export class FileManager {
|
||||
}
|
||||
}
|
||||
|
||||
updateSelection(index, event) {
|
||||
console.log('[FileManager] Updating selection:', { index, event });
|
||||
|
||||
// Prevent selection if clicking on a checkbox or action button
|
||||
if (event.target.classList.contains('select-item-checkbox') || event.target.closest('.file-action-btn')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const checkboxes = document.querySelectorAll('.select-item-checkbox');
|
||||
const checkbox = checkboxes[index];
|
||||
if (!checkbox) return;
|
||||
|
||||
if (event.ctrlKey) {
|
||||
// CTRL + Click: Toggle individual selection
|
||||
checkbox.checked = !checkbox.checked;
|
||||
if (checkbox.checked) {
|
||||
this.selectedItems.add(index);
|
||||
} else {
|
||||
this.selectedItems.delete(index);
|
||||
}
|
||||
} else if (event.shiftKey && this.lastSelectedIndex !== -1) {
|
||||
// SHIFT + Click: Select range
|
||||
const start = Math.min(this.lastSelectedIndex, index);
|
||||
const end = Math.max(this.lastSelectedIndex, index);
|
||||
for (let i = start; i <= end; i++) {
|
||||
checkboxes[i].checked = true;
|
||||
this.selectedItems.add(i);
|
||||
}
|
||||
} else {
|
||||
// Normal click: Select single item
|
||||
const wasChecked = checkbox.checked;
|
||||
checkboxes.forEach(cb => {
|
||||
cb.checked = false;
|
||||
this.selectedItems.delete(parseInt(cb.dataset.index));
|
||||
});
|
||||
checkbox.checked = !wasChecked;
|
||||
if (!wasChecked) {
|
||||
this.selectedItems.add(index);
|
||||
}
|
||||
}
|
||||
|
||||
this.lastSelectedIndex = index;
|
||||
this.roomManager.viewManager.updateMultiSelectUI();
|
||||
}
|
||||
|
||||
getSelectedItems() {
|
||||
console.log('[FileManager] Getting selected items');
|
||||
return Array.from(this.selectedItems).map(index => this.currentFiles[index]);
|
||||
}
|
||||
|
||||
updateSelection(index, event) {
|
||||
console.log('[FileManager] Updating selection:', { index, event });
|
||||
// Implementation of selection logic
|
||||
clearSelection() {
|
||||
console.log('[FileManager] Clearing selection');
|
||||
this.selectedItems.clear();
|
||||
this.lastSelectedIndex = -1;
|
||||
const checkboxes = document.querySelectorAll('.select-item-checkbox');
|
||||
checkboxes.forEach(cb => cb.checked = false);
|
||||
this.roomManager.viewManager.updateMultiSelectUI();
|
||||
}
|
||||
|
||||
navigateToParent() {
|
||||
|
||||
@@ -65,6 +65,53 @@ export class ModalManager {
|
||||
this.deleteModal.show();
|
||||
}
|
||||
|
||||
showBatchDeleteModal() {
|
||||
const selectedCheckboxes = document.querySelectorAll('.select-item-checkbox:checked');
|
||||
if (selectedCheckboxes.length === 0) return;
|
||||
|
||||
const selectedItems = Array.from(selectedCheckboxes).map(cb => {
|
||||
const idx = parseInt(cb.dataset.index);
|
||||
console.log('[ModalManager] Processing checkbox with idx:', idx);
|
||||
console.log('[ModalManager] Current files:', this.roomManager.fileManager.currentFiles);
|
||||
|
||||
if (isNaN(idx) || idx < 0 || idx >= this.roomManager.fileManager.currentFiles.length) {
|
||||
console.error('[ModalManager] Invalid index:', idx);
|
||||
return null;
|
||||
}
|
||||
|
||||
const file = this.roomManager.fileManager.currentFiles[idx];
|
||||
if (!file) {
|
||||
console.error('[ModalManager] No file found at index:', idx);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log('[ModalManager] Found file:', file);
|
||||
return {
|
||||
name: file.name,
|
||||
path: file.path || '',
|
||||
type: file.type
|
||||
};
|
||||
}).filter(item => item !== null); // Remove any null items
|
||||
|
||||
if (selectedItems.length === 0) {
|
||||
console.error('[ModalManager] No valid items selected for deletion');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update modal content
|
||||
const fileNameEl = document.getElementById('deleteFileName');
|
||||
const labelEl = document.getElementById('deleteConfirmLabel');
|
||||
|
||||
if (fileNameEl) fileNameEl.textContent = `${selectedItems.length} item${selectedItems.length > 1 ? 's' : ''}`;
|
||||
if (labelEl) labelEl.textContent = 'Move to Trash';
|
||||
|
||||
// Store the items to delete in the FileManager
|
||||
this.roomManager.fileManager.batchDeleteItems = selectedItems;
|
||||
|
||||
// Show the modal
|
||||
this.deleteModal.show();
|
||||
}
|
||||
|
||||
showRenameModal(filename) {
|
||||
document.getElementById('renameError').textContent = '';
|
||||
const ext = filename.includes('.') ? filename.substring(filename.lastIndexOf('.')) : '';
|
||||
|
||||
@@ -74,7 +74,46 @@ class RoomManager {
|
||||
|
||||
initializeEventListeners() {
|
||||
console.log('[RoomManager] Setting up event listeners');
|
||||
// Add any global event listeners here
|
||||
|
||||
// Add event listener for select all checkbox
|
||||
const selectAllCheckbox = document.querySelector('.select-all-checkbox');
|
||||
if (selectAllCheckbox) {
|
||||
selectAllCheckbox.addEventListener('change', (event) => {
|
||||
const checkboxes = document.querySelectorAll('.select-item-checkbox');
|
||||
checkboxes.forEach((cb, index) => {
|
||||
cb.checked = event.target.checked;
|
||||
if (event.target.checked) {
|
||||
this.fileManager.selectedItems.add(index);
|
||||
} else {
|
||||
this.fileManager.selectedItems.delete(index);
|
||||
}
|
||||
});
|
||||
this.viewManager.updateMultiSelectUI();
|
||||
});
|
||||
}
|
||||
|
||||
// Add event listener for download selected button
|
||||
const downloadSelectedBtn = document.getElementById('downloadSelectedBtn');
|
||||
if (downloadSelectedBtn && this.canDownload) {
|
||||
downloadSelectedBtn.addEventListener('click', () => {
|
||||
this.fileManager.downloadSelected();
|
||||
});
|
||||
}
|
||||
|
||||
// Add event listener for delete selected button
|
||||
const deleteSelectedBtn = document.getElementById('deleteSelectedBtn');
|
||||
if (deleteSelectedBtn && this.canDelete) {
|
||||
deleteSelectedBtn.addEventListener('click', () => {
|
||||
this.modalManager.showBatchDeleteModal();
|
||||
});
|
||||
}
|
||||
|
||||
// Add event listener for clicking outside to clear selection
|
||||
document.addEventListener('click', (event) => {
|
||||
if (!event.target.closest('.file-card') && !event.target.closest('.file-row') && !event.target.closest('.file-action-btn')) {
|
||||
this.fileManager.clearSelection();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,8 +74,7 @@ export class UploadManager {
|
||||
async startUpload(files) {
|
||||
this.uploadProgressContainer.style.display = 'block';
|
||||
this.uploadProgressBar.style.width = '0%';
|
||||
this.uploadProgressBar.classList.remove('bg-success');
|
||||
this.uploadProgressBar.classList.add('bg-info');
|
||||
this.uploadProgressBar.className = 'progress-bar bg-primary-opacity-15 text-primary';
|
||||
this.uploadProgressText.textContent = '';
|
||||
|
||||
this.pendingUploads = files;
|
||||
@@ -109,8 +108,7 @@ export class UploadManager {
|
||||
// All files processed
|
||||
this.uploadProgressBar.style.width = '100%';
|
||||
this.uploadProgressBar.textContent = '100%';
|
||||
this.uploadProgressBar.classList.remove('bg-info');
|
||||
this.uploadProgressBar.classList.add('bg-success');
|
||||
this.uploadProgressBar.className = 'progress-bar bg-success-opacity-15 text-success';
|
||||
this.uploadProgressText.textContent = 'Upload complete!';
|
||||
|
||||
// Reset state
|
||||
@@ -123,8 +121,7 @@ export class UploadManager {
|
||||
setTimeout(() => {
|
||||
this.uploadProgressContainer.style.display = 'none';
|
||||
this.uploadProgressText.textContent = '';
|
||||
this.uploadProgressBar.style.backgroundColor = '#16767b';
|
||||
this.uploadProgressBar.style.color = '#fff';
|
||||
this.uploadProgressBar.className = 'progress-bar bg-primary-opacity-15 text-primary';
|
||||
}, 3000);
|
||||
|
||||
// Refresh file list
|
||||
@@ -175,8 +172,7 @@ export class UploadManager {
|
||||
} catch (error) {
|
||||
console.error('Upload error:', error);
|
||||
this.uploadProgressText.textContent = `Error uploading ${file.name}`;
|
||||
this.uploadProgressBar.style.backgroundColor = '#ef4444';
|
||||
this.uploadProgressBar.style.color = '#fff';
|
||||
this.uploadProgressBar.className = 'progress-bar bg-danger-opacity-15 text-danger';
|
||||
currentFileIndex++;
|
||||
updateProgress();
|
||||
await processNextFile();
|
||||
@@ -226,8 +222,7 @@ export class UploadManager {
|
||||
}
|
||||
|
||||
uploadError.style.display = 'block';
|
||||
this.uploadProgressBar.style.backgroundColor = '#ef4444';
|
||||
this.uploadProgressBar.style.color = '#fff';
|
||||
this.uploadProgressBar.className = 'progress-bar bg-danger-opacity-15 text-danger';
|
||||
}
|
||||
|
||||
async handleFileExists(file, formData) {
|
||||
|
||||
@@ -127,7 +127,9 @@ export class ViewManager {
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 40px;"></th>
|
||||
<th style="width: 40px;">
|
||||
<input type="checkbox" class="form-check-input select-all-checkbox" style="margin: 0;">
|
||||
</th>
|
||||
<th style="width: 40px;"></th>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
@@ -151,7 +153,14 @@ export class ViewManager {
|
||||
async renderGridView(files) {
|
||||
console.log('[ViewManager] Rendering grid view');
|
||||
const fileGrid = document.getElementById('fileGrid');
|
||||
let html = '';
|
||||
let html = `
|
||||
<div class="col-12 mb-3">
|
||||
<div class="d-flex align-items-center">
|
||||
<input type="checkbox" class="form-check-input select-all-checkbox me-2" style="margin: 0;">
|
||||
<span class="text-muted">Select All</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
files.forEach((file, index) => {
|
||||
console.log('[ViewManager] Rendering grid item:', file);
|
||||
@@ -170,10 +179,11 @@ export class ViewManager {
|
||||
const modified = new Date(file.modified).toLocaleString();
|
||||
|
||||
return `
|
||||
<tr data-index="${index}" class="file-row" style="cursor: pointer;">
|
||||
<tr data-index="${index}" class="file-row" style="cursor: pointer;" onclick="window.roomManager.fileManager.updateSelection(${index}, event)">
|
||||
<td>
|
||||
<input type="checkbox" class="form-check-input select-item-checkbox"
|
||||
data-index="${index}" style="margin: 0;">
|
||||
data-index="${index}" style="margin: 0;"
|
||||
onclick="event.stopPropagation(); window.roomManager.fileManager.updateSelection(${index}, event)">
|
||||
</td>
|
||||
<td>
|
||||
<i class="fas ${icon}" style="font-size:1.5rem;color:${isFolder ? 'var(--primary-color)' : 'var(--secondary-color)'}"></i>
|
||||
@@ -201,8 +211,13 @@ export class ViewManager {
|
||||
|
||||
return `
|
||||
<div class="col-12 col-sm-6 col-md-4 col-lg-3 mb-3">
|
||||
<div class="card file-card h-100 border-0 shadow-sm position-relative" data-index="${index}">
|
||||
<div class="card file-card h-100 border-0 shadow-sm position-relative" data-index="${index}" onclick="window.roomManager.fileManager.updateSelection(${index}, event)">
|
||||
<div class="card-body d-flex flex-column align-items-center justify-content-center text-center p-4">
|
||||
<div class="mb-2 w-100 d-flex justify-content-start">
|
||||
<input type="checkbox" class="form-check-input select-item-checkbox"
|
||||
data-index="${index}" style="margin: 0;"
|
||||
onclick="event.stopPropagation(); window.roomManager.fileManager.updateSelection(${index}, event)">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<i class="fas ${icon}" style="font-size:2.5rem;color:${isFolder ? 'var(--primary-color)' : 'var(--secondary-color)'};"></i>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user