Started room separation

This commit is contained in:
2025-05-28 11:37:25 +02:00
parent 11446e00db
commit 9b98370989
11 changed files with 1905 additions and 1813 deletions

View File

@@ -0,0 +1,238 @@
export class ModalManager {
constructor(roomManager) {
this.roomManager = roomManager;
// Initialize modals
this.deleteModal = new bootstrap.Modal(document.getElementById('deleteConfirmModal'));
this.newFolderModal = new bootstrap.Modal(document.getElementById('newFolderModal'));
this.renameModal = new bootstrap.Modal(document.getElementById('renameModal'));
this.detailsModal = new bootstrap.Modal(document.getElementById('detailsModal'));
this.overwriteModal = new bootstrap.Modal(document.getElementById('overwriteConfirmModal'), {
backdrop: 'static',
keyboard: false
});
this.moveModal = new bootstrap.Modal(document.getElementById('moveModal'));
this.initializeModals();
}
initializeModals() {
// Initialize delete modal
if (this.roomManager.canDelete) {
document.getElementById('confirmDeleteBtn').addEventListener('click', () => {
this.roomManager.fileManager.deleteFileConfirmed();
});
}
// Initialize new folder modal
if (this.roomManager.canUpload) {
document.getElementById('newFolderBtn').addEventListener('click', () => {
document.getElementById('folderNameInput').value = '';
document.getElementById('folderError').textContent = '';
this.newFolderModal.show();
setTimeout(() => {
document.getElementById('folderNameInput').focus();
}, 100);
});
document.getElementById('createFolderBtn').addEventListener('click', () => {
this.createFolder();
});
}
// Initialize rename modal
if (this.roomManager.canRename) {
document.getElementById('confirmRenameBtn').addEventListener('click', () => {
this.renameFile();
});
}
// Initialize move modal
if (this.roomManager.canMove) {
document.getElementById('confirmMoveBtn').addEventListener('click', () => {
this.roomManager.fileManager.moveFileConfirmed();
});
}
}
showDeleteModal(filename, path = '') {
const fileNameEl = document.getElementById('deleteFileName');
const labelEl = document.getElementById('deleteConfirmLabel');
if (fileNameEl) fileNameEl.textContent = filename;
if (labelEl) labelEl.textContent = 'Move to Trash';
this.deleteModal.show();
}
showRenameModal(filename) {
document.getElementById('renameError').textContent = '';
const ext = filename.includes('.') ? filename.substring(filename.lastIndexOf('.')) : '';
const isFile = ext && filename.lastIndexOf('.') > 0;
const inputGroup = document.getElementById('renameInputGroup');
if (isFile) {
const base = filename.substring(0, filename.lastIndexOf('.'));
inputGroup.innerHTML = `<div class="input-group"><input type="text" id="renameInput" class="form-control" value="${base}" autocomplete="off" /><span class="input-group-text">${ext}</span></div>`;
} else {
inputGroup.innerHTML = `<input type="text" id="renameInput" class="form-control" value="${filename}" autocomplete="off" />`;
}
this.renameModal.show();
setTimeout(() => {
document.getElementById('renameInput').focus();
}, 100);
}
showDetailsModal(file) {
const icon = file.type === 'folder'
? `<i class='fas fa-folder' style='font-size:2.2rem;color:var(--primary-color);'></i>`
: `<i class='fas fa-file-alt' style='font-size:2.2rem;color:var(--secondary-color);'></i>`;
const uploaderPic = file.uploader_profile_pic
? `/uploads/profile_pics/${file.uploader_profile_pic}`
: '/static/default-avatar.png';
const detailsHtml = `
<div class='d-flex align-items-center gap-3 mb-3'>
<div>${icon}</div>
<div style='min-width:0;'>
<div class='fw-bold' style='font-size:1.1rem;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;' title='${file.name}'>${file.name}</div>
<div class='text-muted small'>${file.type === 'folder' ? 'Folder' : 'File'}</div>
</div>
</div>
<div class='mb-2 d-flex align-items-center gap-2'>
<img src='${uploaderPic}' alt='Profile Picture' class='rounded-circle border' style='width:28px;height:28px;object-fit:cover;'>
<span class='fw-semibold' style='font-size:0.98rem;'>${file.uploaded_by || '-'}</span>
</div>
<div class='mb-2 text-muted' style='font-size:0.92rem;'><i class='far fa-clock me-1'></i>${this.roomManager.viewManager.formatDate(file.modified)}</div>
<hr style='margin:0.7rem 0 0.5rem 0; border-color:var(--border-light);'>
<div style='font-size:0.91rem;color:var(--text-muted);'><strong style='color:var(--primary-color);'>Room:</strong> <button class='btn btn-sm' style='background-color:var(--primary-opacity-8);color:var(--primary-color);' onclick='window.location.href=\"/rooms/${this.roomManager.roomId}\"'><i class='fas fa-door-open me-1'></i>${this.roomManager.roomName}</button></div>
<div style='font-size:0.91rem;color:var(--text-muted);'><strong style='color:var(--primary-color);'>Path:</strong> <span style='word-break:break-all;'>${(file.path ? file.path + '/' : '') + file.name}</span></div>
<div style='font-size:0.91rem;color:var(--text-muted);'><strong style='color:var(--primary-color);'>Size:</strong> ${this.roomManager.viewManager.formatFileSize(file.size)}</div>
<div style='font-size:0.91rem;color:var(--text-muted);'><strong style='color:var(--primary-color);'>Uploaded at:</strong> ${file.uploaded_at ? new Date(file.uploaded_at).toLocaleString() : '-'}</div>
`;
document.getElementById('detailsModalBody').innerHTML = detailsHtml;
this.detailsModal.show();
}
showOverwriteModal(filename) {
return new Promise((resolve) => {
const fileNameEl = document.getElementById('overwriteFileName');
if (fileNameEl) fileNameEl.textContent = filename;
const skipBtn = document.getElementById('skipOverwriteBtn');
const skipAllBtn = document.getElementById('skipAllOverwriteBtn');
const overwriteBtn = document.getElementById('confirmOverwriteBtn');
const overwriteAllBtn = document.getElementById('confirmAllOverwriteBtn');
const handleResult = (result) => {
this.overwriteModal.hide();
resolve(result);
};
skipBtn.onclick = () => handleResult('skip');
skipAllBtn.onclick = () => handleResult('skip_all');
overwriteBtn.onclick = () => handleResult('overwrite');
overwriteAllBtn.onclick = () => handleResult('overwrite_all');
this.overwriteModal.show();
});
}
showMoveModal(filename, path) {
document.getElementById('moveError').textContent = '';
fetch(`/api/rooms/${this.roomManager.roomId}/folders`)
.then(r => r.json())
.then(folders => {
const select = document.getElementById('moveTargetFolder');
select.innerHTML = '<option value="">Root Folder</option>';
folders.sort((a, b) => {
if (!a) return -1;
if (!b) return 1;
return a.localeCompare(b);
});
folders.forEach(folderPath => {
if (folderPath === path || (path && folderPath.startsWith(path + '/'))) {
return;
}
const pathParts = folderPath.split('/');
const displayName = pathParts[pathParts.length - 1];
const indent = '&nbsp;&nbsp;&nbsp;&nbsp;'.repeat(pathParts.length - 1);
select.innerHTML += `<option value="${folderPath}">${indent}${displayName}</option>`;
});
this.moveModal.show();
})
.catch(error => {
document.getElementById('moveError').textContent = 'Failed to load folders.';
console.error('Error loading folders:', error);
});
}
async createFolder() {
const folderName = document.getElementById('folderNameInput').value.trim();
if (!folderName) {
document.getElementById('folderError').textContent = 'Folder name is required.';
return;
}
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
try {
const response = await fetch(`/api/rooms/${this.roomManager.roomId}/folders`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
},
body: JSON.stringify({
name: folderName,
path: this.roomManager.currentPath
})
});
const result = await response.json();
if (result.success) {
this.newFolderModal.hide();
await this.roomManager.fileManager.fetchFiles();
} else {
if (result.error === 'A folder with this name exists in the trash') {
document.getElementById('folderError').textContent = `Cannot create folder "${folderName}" because this name is currently in the trash. Please restore or permanently delete the trashed item first.`;
} else if (result.error === 'A folder with this name already exists in this location') {
document.getElementById('folderError').textContent = `A folder named "${folderName}" already exists in this location. Please choose a different name.`;
} else {
document.getElementById('folderError').textContent = result.error || 'Failed to create folder.';
}
}
} catch (error) {
document.getElementById('folderError').textContent = 'Failed to create folder.';
}
}
async renameFile() {
const newName = document.getElementById('renameInput').value.trim();
if (!newName) {
document.getElementById('renameError').textContent = 'New name is required.';
return;
}
const result = await this.roomManager.fileManager.renameFile(
this.renameTarget,
newName,
this.roomManager.currentPath
);
if (result.success) {
this.renameModal.hide();
await this.roomManager.fileManager.fetchFiles();
} else {
document.getElementById('renameError').textContent = result.error || 'Rename failed.';
}
}
}