document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('.file-size').forEach(function(element) { const size = parseInt(element.getAttribute('data-size')); element.textContent = formatFileSize(size); }); document.getElementById('searchButton').addEventListener('click', searchFiles); document.getElementById('newFolderBtn').addEventListener('click', showNewFolderModal); document.querySelectorAll('.delete-folder-button').forEach(button => { button.addEventListener('click', function() { const folderName = this.getAttribute('data-folder-name'); confirmDeleteFolder(folderName); }); }); document.querySelectorAll('.delete-file-button').forEach(button => { button.addEventListener('click', function() { const fileName = this.getAttribute('data-file-name'); confirmDelete(fileName); }); }); document.querySelectorAll('.copy-button').forEach(button => { button.addEventListener('click', function() { const fileUrl = this.getAttribute('data-file-url'); copyFileLink(fileUrl); }); }); document.querySelectorAll('.rename-file-btn').forEach(button => { button.addEventListener('click', function() { const fileName = this.getAttribute('data-file-name'); const folderName = this.getAttribute('data-folder-name'); renameFile(folderName, fileName); }); }); document.querySelectorAll('.move-file-btn').forEach(button => { button.addEventListener('click', function() { const fileName = this.getAttribute('data-file-name'); showMoveFileModal(fileName); }); }); document.getElementById('confirmMoveFile').addEventListener('click', moveFile); document.getElementById('themeSwitcher').addEventListener('click', toggleDarkMode); initTheme(); document.addEventListener('DOMContentLoaded', function () { const accountDropdownBtn = document.getElementById('accountDropdownBtn'); const accountDropdownMenu = document.getElementById('accountDropdownMenu'); accountDropdownBtn.addEventListener('click', function (e) { e.stopPropagation(); accountDropdownMenu.classList.toggle('show'); }); document.addEventListener('click', function (e) { if (!accountDropdownBtn.contains(e.target) && !accountDropdownMenu.contains(e.target)) { accountDropdownMenu.classList.remove('show'); } }); }); $('.modal').modal({ show: false }); const metadataLink = document.querySelector('a[onclick="displayMetadata()"]'); if (metadataLink) { metadataLink.addEventListener('click', function(event) { event.preventDefault(); displayMetadata(); }); } document.querySelectorAll('[onclick^="showFileInfo"]').forEach(link => { link.addEventListener('click', function(event) { event.preventDefault(); const fileName = this.getAttribute('onclick').match(/'([^']+)'/)[1]; showFileInfo(fileName); }); }); }); function formatFileSize(fileSizeInBytes) { if (fileSizeInBytes < 1024) return fileSizeInBytes + ' octets'; else if (fileSizeInBytes < 1048576) return (fileSizeInBytes / 1024).toFixed(2) + ' Ko'; else if (fileSizeInBytes < 1073741824) return (fileSizeInBytes / 1048576).toFixed(2) + ' Mo'; else return (fileSizeInBytes / 1073741824).toFixed(2) + ' Go'; } function searchFiles() { const input = document.getElementById('searchInput'); const filter = input.value.toUpperCase(); const table = document.getElementById('fileTable'); const tr = table.getElementsByTagName('tr'); for (let i = 1; i < tr.length; i++) { const td = tr[i].getElementsByTagName('td')[0]; if (td) { const txtValue = td.textContent || td.innerText; if (txtValue.toUpperCase().indexOf(filter) > -1) { tr[i].style.display = ""; } else { tr[i].style.display = "none"; } } } } function showNewFolderModal() { Swal.fire({ title: 'Nouveau dossier', input: 'text', inputPlaceholder: 'Entrer le nom du nouveau dossier', confirmButtonText: 'Créer', showCancelButton: true, cancelButtonText: 'Annuler', preConfirm: (folderName) => { if (!folderName) { Swal.showValidationMessage('Le nom du dossier ne peut pas être vide.'); } return folderName; } }).then(result => { if (result.isConfirmed) { createNewFolder(result.value); } }); } function createNewFolder(folderName) { fetch('/api/dpanel/dashboard/newfolder', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ folderName }), }) .then(response => { if (response.ok) { return response.json(); } else { return response.json().then(error => Promise.reject(error)); } }) .then(result => { Swal.fire({ position: 'top', icon: 'success', title: 'Le dossier a été créé avec succès.', showConfirmButton: false, timer: 2000, toast: true }).then(() => { location.reload(); }); }) .catch(error => { Swal.fire({ position: 'top', icon: 'error', title: 'Erreur lors de la création du dossier.', text: error.message, showConfirmButton: false, timer: 2350, toast: true }); }); } function confirmDeleteFolder(folderName) { Swal.fire({ title: 'Êtes-vous sûr?', text: `La suppression du dossier "${folderName}" est irréversible!`, icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Supprimer', cancelButtonText: 'Annuler', }).then((result) => { if (result.isConfirmed) { deleteFolder(folderName); } }); } function deleteFolder(folderName) { fetch(`/api/dpanel/dashboard/deletefolder/${folderName}`, { method: 'DELETE', }) .then(response => { if (response.ok) { Swal.fire({ position: 'top', icon: 'success', title: 'Le dossier a été supprimé avec succès.', showConfirmButton: false, timer: 1800, toast: true }).then(() => { location.reload(); }); } else { throw new Error('La suppression du dossier a échoué'); } }) .catch(error => { Swal.fire({ position: 'top', icon: 'error', title: error.message, showConfirmButton: false, timer: 1800, toast: true }); }); } function confirmDelete(filename) { Swal.fire({ title: 'Êtes-vous sûr de vouloir supprimer ce fichier?', text: 'Cette action est irréversible!', icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Supprimer' }).then((result) => { if (result.isConfirmed) { deleteFile(filename); } }); } function deleteFile(filename) { fetch('/api/dpanel/dashboard/delete', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ filename: filename, }), }) .then(response => { if (response.ok) { Swal.fire({ position: 'top', icon: 'success', title: 'Le fichier a été supprimé avec succès.', showConfirmButton: false, timer: 1800, toast: true }).then(() => { location.reload(); }); } else { throw new Error('La suppression du fichier a échoué'); } }) .catch(error => { Swal.fire({ position: 'top', icon: 'error', title: error.message, showConfirmButton: false, timer: 1800, toast: true }); }); } function copyFileLink(fileUrl) { navigator.clipboard.writeText(fileUrl).then(() => { Swal.fire({ position: 'top', icon: 'success', title: 'Lien copié !', showConfirmButton: false, timer: 1500, toast: true }); }, (err) => { console.error('Erreur lors de la copie: ', err); }); } function renameFile(folderName, currentName) { Swal.fire({ title: 'Entrez le nouveau nom', input: 'text', inputValue: currentName, inputPlaceholder: 'Nouveau nom', showCancelButton: true, confirmButtonText: 'Renommer', cancelButtonText: 'Annuler', inputValidator: (value) => { if (!value) { return 'Vous devez entrer un nom de fichier'; } } }).then((result) => { if (result.isConfirmed) { const newName = result.value; fetch(`/api/dpanel/dashboard/rename/${folderName}`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ currentName: currentName, newName: newName }), }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { Swal.fire({ position: 'top', icon: 'success', title: 'Le fichier a été renommé avec succès.', showConfirmButton: false, timer: 1800, toast: true, }).then(() => { location.reload(); }); }) .catch((error) => { Swal.fire({ position: 'top', icon: 'error', title: 'Erreur lors du renommage du fichier.', text: error.message, showConfirmButton: false, timer: 1800, toast: true, }); }); } }); } function showMoveFileModal(fileName) { // Récupérer les dossiers depuis le tableau const folders = Array.from(document.querySelectorAll('tr[data-type="folder"]')) .map(folderRow => ({ name: folderRow.dataset.name, value: folderRow.dataset.name // On s'assure d'avoir une valeur correcte })); Swal.fire({ title: 'Déplacer le fichier', html: ` `, showCancelButton: true, confirmButtonText: 'Déplacer', cancelButtonText: 'Annuler', preConfirm: () => { const select = document.getElementById('moveFolderSelect'); const folderName = select.value; if (!folderName) { Swal.showValidationMessage('Veuillez sélectionner un dossier'); return false; } return folderName; // On retourne directement la valeur du dossier } }).then((result) => { if (result.isConfirmed && result.value) { moveFile(fileName, result.value); } }); } function moveFile(fileName, folderName) { // Log pour debug console.log('Moving file:', { fileName, folderName }); fetch('/api/dpanel/dashboard/movefile', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ fileName: fileName, folderName: folderName // Maintenant c'est une chaîne de caractères valide }), }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { if (data.message === "File moved successfully") { Swal.fire({ position: 'top', icon: 'success', title: 'Le fichier a été déplacé avec succès.', showConfirmButton: false, timer: 1800, toast: true, }).then(() => { location.reload(); }); } else { throw new Error(data.error || 'Une erreur est survenue'); } }) .catch((error) => { Swal.fire({ position: 'top', icon: 'error', title: 'Erreur lors du déplacement du fichier.', text: error.message, showConfirmButton: false, timer: 1800, toast: true, }); }); } const body = document.body; const themeSwitcher = document.getElementById('themeSwitcher'); function setTheme(theme) { if (theme === 'dark') { body.classList.add('dark'); } else { body.classList.remove('dark'); } localStorage.setItem('theme', theme); } const savedTheme = localStorage.getItem('theme'); if (savedTheme) { setTheme(savedTheme); } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { setTheme('dark'); } themeSwitcher.addEventListener('click', function() { if (body.classList.contains('dark')) { setTheme('light'); } else { setTheme('dark'); } }); async function showFileInfo(fileName) { try { const response = await fetch('/api/dpanel/dashboard/getmetadatafile/file_info', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fileLink: fileName, }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); const fileInfo = data.find(file => file.fileName === fileName); if (!fileInfo) { throw new Error(`No information found for the file ${fileName}.`); } let html = `

Nom du fichier : ${fileInfo.fileName}

`; if (fileInfo.expiryDate) { html += `

Date d'expiration : ${fileInfo.expiryDate}

`; } if (fileInfo.password) { html += `

Mot de passe : Oui

`; } if (fileInfo.userId) { html += `

Utilisateur : ${fileInfo.userId}

`; } Swal.fire({ title: 'Informations sur le fichier', html: html, confirmButtonText: 'Fermer' }); } catch (error) { console.error('Error in showFileInfo:', error); Swal.fire({ position: 'top', icon: 'error', title: 'Les informations sur le fichier ne sont pas disponibles pour le moment.', text: `Erreur : ${error.message}`, showConfirmButton: false, timer: 1800, toast: true, }); } } function displayMetadata() { fetch('/build-metadata') .then(response => response.json()) .then(metadata => { document.getElementById('buildVersion').textContent = metadata.build_version; document.getElementById('nodeVersion').textContent = metadata.node_version; document.getElementById('expressVersion').textContent = metadata.express_version; document.getElementById('buildSha').textContent = metadata.build_sha; document.getElementById('osType').textContent = metadata.os_type; document.getElementById('osRelease').textContent = metadata.os_release; $('#metadataModal').modal('show'); }) .catch(error => { console.error('Failed to fetch metadata:', error); Swal.fire({ icon: 'error', title: 'Erreur', text: 'Impossible de récupérer les métadonnées' }); }); } document.addEventListener('DOMContentLoaded', () => { // Recherche avec debounce const searchInput = document.getElementById('searchInput'); if (searchInput) { let timeout; searchInput.addEventListener('input', (e) => { clearTimeout(timeout); timeout = setTimeout(() => { const term = e.target.value.toLowerCase(); document.querySelectorAll('#fileTable tbody tr').forEach(row => { const text = row.querySelector('td:first-child').textContent.toLowerCase(); row.style.display = text.includes(term) ? '' : 'none'; }); }, 150); }); } // Gestion des modales document.querySelectorAll('[data-toggle="modal"]').forEach(trigger => { trigger.addEventListener('click', () => { const modal = document.querySelector(trigger.dataset.target); if (modal) modal.classList.add('show'); }); }); document.querySelectorAll('.modal .close, .modal .btn-secondary').forEach(btn => { btn.addEventListener('click', () => { const modal = btn.closest('.modal'); if (modal) modal.classList.remove('show'); }); }); // Dropdowns document.querySelectorAll('.dropdown-toggle').forEach(toggle => { toggle.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); const menu = toggle.nextElementSibling; if (!menu) return; // Fermer les autres dropdowns document.querySelectorAll('.dropdown-menu.show').forEach(m => { if (m !== menu) m.classList.remove('show'); }); menu.classList.toggle('show'); }); }); // Fermer les dropdowns au clic extérieur document.addEventListener('click', () => { document.querySelectorAll('.dropdown-menu.show').forEach(menu => { menu.classList.remove('show'); }); }); }); // Loading overlay window.showLoadingState = () => { const overlay = document.createElement('div'); overlay.className = 'loading-overlay animate'; overlay.innerHTML = '
'; document.body.appendChild(overlay); }; window.hideLoadingState = () => { const overlay = document.querySelector('.loading-overlay'); if (overlay) overlay.remove(); }; // Gestion améliorée de l'état de chargement window.showLoadingState = () => { const overlay = document.createElement('div'); overlay.className = 'loading-overlay'; const wrapper = document.createElement('div'); wrapper.className = 'spinner-wrapper'; const spinner = document.createElement('div'); spinner.className = 'loading-spinner'; wrapper.appendChild(spinner); overlay.appendChild(wrapper); document.body.appendChild(overlay); // Force le reflow pour démarrer l'animation overlay.offsetHeight; overlay.classList.add('show'); }; window.hideLoadingState = () => { const overlay = document.querySelector('.loading-overlay'); if (overlay) { overlay.classList.remove('show'); overlay.addEventListener('transitionend', () => overlay.remove(), { once: true }); } }; // Animation des lignes du tableau document.addEventListener('DOMContentLoaded', () => { const tableRows = document.querySelectorAll('.table tr'); tableRows.forEach((row, index) => { row.style.setProperty('--row-index', index); requestAnimationFrame(() => row.classList.add('show')); }); // Animation du conteneur principal const mainContainer = document.querySelector('.form-container'); if (mainContainer) { requestAnimationFrame(() => mainContainer.classList.add('show')); } }); // Fonction pour les transitions de page function transitionToPage(url) { document.body.classList.add('page-transition'); showLoadingState(); setTimeout(() => { window.location.href = url; }, 300); } // Amélioration des modales function showModal(modalId) { const modal = document.querySelector(modalId); if (!modal) return; modal.style.display = 'flex'; requestAnimationFrame(() => { modal.classList.add('show'); modal.querySelector('.modal-content')?.classList.add('show'); }); } function hideModal(modalId) { const modal = document.querySelector(modalId); if (!modal) return; modal.querySelector('.modal-content')?.classList.remove('show'); modal.classList.remove('show'); modal.addEventListener('transitionend', () => { modal.style.display = 'none'; }, { once: true }); } // État de chargement des boutons function setButtonLoading(button, isLoading) { if (isLoading) { button.classList.add('loading'); button.dataset.originalText = button.innerHTML; button.innerHTML = ''; } else { button.classList.remove('loading'); if (button.dataset.originalText) { button.innerHTML = button.dataset.originalText; } } } function createLoadingScreen() { const container = document.createElement('div'); container.className = 'initial-loading'; const content = `

Vous y êtes presque !

Préparation de votre espace de travail...

Chargement des données

`; container.innerHTML = content; document.body.appendChild(container); return container; } function initializeLoadingScreen() { // Vérifier si c'est la première visite de la session const hasSeenAnimation = sessionStorage.getItem('hasSeenLoadingAnimation'); if (hasSeenAnimation) { // Si l'animation a déjà été vue, initialiser directement le contenu const contentWrapper = document.querySelector('.content-wrapper'); if (contentWrapper) { contentWrapper.classList.add('loaded'); } return Promise.resolve(); } return new Promise((resolve) => { const loadingScreen = createLoadingScreen(); setTimeout(() => { loadingScreen.classList.add('fade-out'); loadingScreen.addEventListener('animationend', () => { loadingScreen.remove(); // Marquer l'animation comme vue pour cette session sessionStorage.setItem('hasSeenLoadingAnimation', 'true'); resolve(); }, { once: true }); }, 2000); }); } document.addEventListener('DOMContentLoaded', async function() { try { await initializeLoadingScreen(); const contentWrapper = document.querySelector('.content-wrapper'); if (contentWrapper) { contentWrapper.classList.add('loaded'); } } catch (error) { console.error('Erreur lors du chargement:', error); } }); fetch('/build-metadata') .then(response => response.json()) .then(data => { document.getElementById('version-number').textContent = data.build_version; }) .catch(error => { console.error('Error fetching version:', error); document.getElementById('version-number').textContent = 'Version indisponible'; }); // Fonction pour afficher les détails de collaboration function showCollaborationDetails(itemName, itemType) { const modal = $('#collaborationModal'); const usersContainer = modal.find('.collaboration-users'); const currentItem = { name: itemName, type: itemType }; // Stockage des informations de l'item actuel modal.data('currentItem', currentItem); fetch(`/api/dpanel/collaboration/details/${itemType}/${itemName}`) .then(response => response.json()) .then(data => { let userList = ''; if (data.activeUsers && data.activeUsers.length > 0) { userList = data.activeUsers.map(user => { const avatarUrl = user.profilePicture || getDefaultAvatar(user.name); return `
${user.name}
${user.name}
En ligne
`; }).join(''); } else { userList = '
Aucun utilisateur actif
'; } usersContainer.html(userList); modal.modal('show'); }) .catch(error => { console.error('Error:', error); Swal.fire({ icon: 'error', title: 'Erreur', text: 'Impossible de charger les détails de la collaboration' }); }); } // Gestionnaire de recherche d'utilisateurs function searchCollabUser(username) { if (!username) return; const resultsDiv = $('#searchCollabResults'); fetch(`/api/dpanel/collaboration/searchuser?username=${encodeURIComponent(username)}`) .then(response => response.json()) .then(result => { if (result.found) { const avatarUrl = result.user.profilePicture || getDefaultAvatar(result.user.name); resultsDiv.html(`
${result.user.name} ${result.user.name}
`); } else { resultsDiv.html('
Utilisateur non trouvé
'); } }); } // Initialisation des événements de collaboration document.addEventListener('DOMContentLoaded', function() { const modal = $('#collaborationModal'); // Recherche d'utilisateurs $('#searchCollabBtn').on('click', () => { const username = $('#searchCollabUser').val().trim(); searchCollabUser(username); }); $('#searchCollabUser').on('keypress', (e) => { if (e.key === 'Enter') { const username = e.target.value.trim(); searchCollabUser(username); } }); // Gestion de l'ajout de collaborateurs $(document).on('click', '.add-collab-btn', function() { const userId = $(this).data('user-id'); const currentItem = modal.data('currentItem'); addCollaborator(currentItem.name, currentItem.type, userId); }); // Gestion de la suppression de collaborateurs $(document).on('click', '.remove-collab-btn', function() { const userId = $(this).data('user-id'); const currentItem = modal.data('currentItem'); removeCollaborator(currentItem.name, currentItem.type, userId); }); // Désactivation de la collaboration $('#disableCollabBtn').on('click', function() { const currentItem = modal.data('currentItem'); modal.modal('hide'); toggleCollaboration(currentItem.name, currentItem.type, false); }); }); function addCollaborator(itemName, itemType, userId) { fetch('/api/dpanel/collaboration/add', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ itemName, itemType, userId }) }) .then(response => response.json()) .then(data => { if (data.success) { showCollaborationDetails(itemName, itemType); // Rafraîchir la liste Swal.fire({ position: 'top-end', icon: 'success', title: 'Collaborateur ajouté', showConfirmButton: false, timer: 1500, toast: true }); } }) .catch(error => console.error('Error:', error)); } function removeCollaborator(itemName, itemType, userId) { fetch('/api/dpanel/collaboration/remove', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ itemName, itemType, userId }) }) .then(response => response.json()) .then(data => { if (data.success) { showCollaborationDetails(itemName, itemType); // Rafraîchir la liste Swal.fire({ position: 'top-end', icon: 'success', title: 'Collaborateur retiré', showConfirmButton: false, timer: 1500, toast: true }); } }) .catch(error => console.error('Error:', error)); } // Fonction pour afficher les détails de collaboration function showCollaborationDetails(itemName, itemType) { // Récupérer le modal const modal = $('#collaborationModal'); const usersContainer = modal.find('.collaboration-users'); fetch(`/api/dpanel/collaboration/details/${itemType}/${itemName}`) .then(response => response.json()) .then(data => { let userList = ''; if (data.activeUsers && data.activeUsers.length > 0) { userList = data.activeUsers.map(user => { const avatarUrl = user.profilePicture || getDefaultAvatar(user.name); return `
${user.name}
${user.name}
En ligne
`; }).join(''); } else { userList = '
Aucun utilisateur actif
'; } usersContainer.html(userList); // Gestionnaire pour la recherche d'utilisateurs const searchInput = $('#searchCollabUser'); const searchBtn = $('#searchCollabBtn'); const resultsDiv = $('#searchCollabResults'); searchBtn.off('click').on('click', () => searchCollabUser(searchInput.val().trim())); searchInput.off('keypress').on('keypress', (e) => { if (e.key === 'Enter') { searchCollabUser(searchInput.val().trim()); } }); // Gestionnaire pour la désactivation de la collaboration $('#disableCollaborationBtn').off('click').on('click', () => { modal.modal('hide'); toggleCollaboration(itemName, itemType, false); }); // Afficher le modal modal.modal('show'); }) .catch(error => { console.error('Error fetching collaboration details:', error); Swal.fire({ icon: 'error', title: 'Erreur', text: 'Impossible de charger les détails de la collaboration' }); }); } function searchCollabUser(username) { if (!username) return; fetch(`/api/dpanel/collaboration/searchuser?username=${encodeURIComponent(username)}`) .then(response => response.json()) .then(result => { const resultsDiv = $('#searchCollabResults'); if (result.found) { const avatarUrl = result.user.profilePicture || getDefaultAvatar(result.user.name); resultsDiv.html(`
${result.user.name} ${result.user.name}
`); } else { resultsDiv.html('
Utilisateur non trouvé
'); } }); } // Fonction pour gérer l'activation/désactivation de la collaboration function toggleCollaboration(itemName, itemType, enable) { const itemLabel = itemType === 'folder' ? 'dossier' : 'fichier'; const performToggle = () => { fetch('/api/dpanel/collaboration/toggle', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ itemName, itemType, enable }) }) .then(response => response.json()) .then(data => { if (data.success) { updateCollaborationUI({ itemName, itemType, isCollaborative: enable, activeUsers: data.activeUsers || [] }); Swal.fire({ position: 'top', icon: 'success', title: `Collaboration ${enable ? 'activée' : 'désactivée'}`, showConfirmButton: false, timer: 1500, toast: true }); } }) .catch(error => { console.error('Error:', error); Swal.fire({ position: 'top', icon: 'error', title: 'Erreur lors de la modification de la collaboration', showConfirmButton: false, timer: 1500, toast: true }); }); }; if (!enable) { performToggle(); } else { Swal.fire({ title: 'Activer la collaboration ?', text: `D'autres utilisateurs pourront accéder à ce ${itemLabel} en temps réel.`, icon: 'question', showCancelButton: true, confirmButtonText: 'Activer', cancelButtonText: 'Annuler' }).then((result) => { if (result.isConfirmed) { performToggle(); } }); } } // Fonction pour mettre à jour l'interface utilisateur function updateCollaborationUI(data) { const row = document.querySelector(`tr[data-name="${data.itemName}"]`); if (!row) return; const button = row.querySelector('.toggle-collaboration-btn'); const nameCell = row.querySelector('td:first-child'); if (button) { button.setAttribute('data-is-collaborative', data.isCollaborative); button.title = data.isCollaborative ? 'Voir les collaborateurs' : 'Activer la collaboration'; button.classList.toggle('active', data.isCollaborative); } let badge = nameCell.querySelector('.collaboration-badge'); if (data.isCollaborative) { if (!badge) { badge = document.createElement('span'); badge.className = 'ml-2 badge badge-info collaboration-badge'; badge.innerHTML = ' '; nameCell.querySelector('div').appendChild(badge); } const countSpan = badge.querySelector('.active-users-count'); if (data.activeUsers && data.activeUsers.length > 0) { badge.classList.remove('badge-secondary'); badge.classList.add('badge-info'); countSpan.textContent = ` ${data.activeUsers.length}`; badge.title = `Collaborateurs actifs : ${data.activeUsers.map(u => u.name).join(', ')}`; } else { badge.classList.remove('badge-info'); badge.classList.add('badge-secondary'); countSpan.textContent = ''; badge.title = 'Aucun collaborateur actif'; } } else if (badge) { badge.remove(); } } // Initialisation au chargement de la page document.addEventListener('DOMContentLoaded', async function() { // Initialiser WebSocket const ws = new WebSocket(`ws://${window.location.host}`); ws.onmessage = function(event) { const data = JSON.parse(event.data); if (data.type === 'collaborationStatus') { updateCollaborationUI(data); } }; // Charger le statut initial de collaboration pour tous les éléments try { const response = await fetch('/api/dpanel/collaboration/status'); const data = await response.json(); if (data.items) { Object.entries(data.items).forEach(([itemId, status]) => { // Pour chaque élément dans le fichier collaboration.json const [type, name] = itemId.split('-'); updateCollaborationUI({ itemName: name, itemType: type, isCollaborative: status.isCollaborative, activeUsers: status.activeUsers }); }); } } catch (error) { console.error('Error loading collaboration status:', error); } // Gestionnaire pour les boutons de collaboration document.querySelectorAll('.toggle-collaboration-btn').forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const itemName = this.getAttribute('data-item-name'); const itemType = this.getAttribute('data-item-type'); const isCollaborative = this.getAttribute('data-is-collaborative') === 'true'; if (isCollaborative) { showCollaborationDetails(itemName, itemType); } else { toggleCollaboration(itemName, itemType, !isCollaborative); } }); }); // Joindre automatiquement si on est sur un élément collaboratif const currentPath = window.location.pathname; const matches = currentPath.match(/\/folder\/(.+)$/); if (matches) { const folderName = decodeURIComponent(matches[1]); joinCollaboration(folderName, 'folder'); } }); // Initialisation au chargement de la page document.addEventListener('DOMContentLoaded', function() { // Initialiser WebSocket const ws = new WebSocket(`ws://${window.location.host}`); ws.onmessage = function(event) { const data = JSON.parse(event.data); if (data.type === 'collaborationStatus') { updateCollaborationUI(data); } }; // Gestionnaire pour les boutons de collaboration document.querySelectorAll('.toggle-collaboration-btn').forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const itemName = this.getAttribute('data-item-name'); const itemType = this.getAttribute('data-item-type'); const isCollaborative = this.getAttribute('data-is-collaborative') === 'true'; if (isCollaborative) { showCollaborationDetails(itemName, itemType); } else { toggleCollaboration(itemName, itemType, !isCollaborative); } }); }); }); document.addEventListener('DOMContentLoaded', function() { const contextMenu = document.querySelector('.context-menu'); let selectedItem = null; // Activer le menu contextuel sur les lignes du tableau document.querySelectorAll('#fileTable tbody tr').forEach(row => { row.addEventListener('contextmenu', function(e) { e.preventDefault(); // Empêcher le menu contextuel par défaut selectedItem = { type: this.dataset.type, name: this.dataset.name, isCollaborative: this.querySelector('.toggle-collaboration-btn')?.dataset.isCollaborative === 'true' }; // Ajuster la visibilité des options du menu en fonction du type adjustMenuOptions(selectedItem); // Positionner le menu contextuel showContextMenu(e.pageX, e.pageY); }); }); // Fermer le menu au clic en dehors document.addEventListener('click', function(e) { if (!contextMenu.contains(e.target)) { hideContextMenu(); } }); // Gérer les actions du menu contextuel document.querySelectorAll('.context-menu .menu-item').forEach(item => { item.addEventListener('click', function(e) { e.preventDefault(); const action = this.dataset.action; if (selectedItem) { handleMenuAction(action, selectedItem); } hideContextMenu(); }); }); // Fonction pour ajuster les options du menu selon le type d'élément function adjustMenuOptions(item) { const menuItems = contextMenu.querySelectorAll('.menu-item'); menuItems.forEach(menuItem => { const action = menuItem.dataset.action; // Gérer la visibilité des options selon le type switch(action) { case 'open': menuItem.style.display = item.type.includes('folder') ? 'flex' : 'none'; break; case 'collaborate': menuItem.style.display = item.type === 'folder' ? 'flex' : 'none'; menuItem.querySelector('span').textContent = item.isCollaborative ? 'Gérer la collaboration' : 'Activer la collaboration'; break; case 'share': menuItem.style.display = item.type === 'file' ? 'flex' : 'none'; break; // Vous pouvez ajouter d'autres cas selon vos besoins } }); } // Fonction pour afficher le menu contextuel function showContextMenu(x, y) { const menu = contextMenu; menu.style.display = 'block'; // Ajuster la position si le menu dépasse de la fenêtre const menuRect = menu.getBoundingClientRect(); const windowWidth = window.innerWidth; const windowHeight = window.innerHeight; if (x + menuRect.width > windowWidth) { x = windowWidth - menuRect.width; } if (y + menuRect.height > windowHeight) { y = windowHeight - menuRect.height; } menu.style.left = `${x}px`; menu.style.top = `${y}px`; } // Fonction pour cacher le menu contextuel function hideContextMenu() { contextMenu.style.display = 'none'; } // Fonction pour gérer les actions du menu function handleMenuAction(action, item) { switch(action) { case 'open': if (item.type === 'folder') { window.location.href = `/dpanel/dashboard/folder/${encodeURIComponent(item.name)}`; } break; case 'rename': Swal.fire({ title: 'Renommer', input: 'text', inputValue: item.name, showCancelButton: true, confirmButtonText: 'Renommer', cancelButtonText: 'Annuler', inputValidator: (value) => { if (!value) { return 'Le nom ne peut pas être vide'; } } }).then((result) => { if (result.isConfirmed) { // Appeler votre API de renommage ici console.log(`Renommer ${item.name} en ${result.value}`); } }); break; case 'delete': Swal.fire({ title: 'Êtes-vous sûr ?', text: `Voulez-vous vraiment supprimer "${item.name}" ?`, icon: 'warning', showCancelButton: true, confirmButtonColor: 'hsl(var(--destructive))', confirmButtonText: 'Supprimer', cancelButtonText: 'Annuler' }).then((result) => { if (result.isConfirmed) { // Appeler votre API de suppression ici console.log(`Supprimer ${item.name}`); } }); break; case 'collaborate': if (item.isCollaborative) { showCollaborationDetails(item.name, item.type); } else { toggleCollaboration(item.name, item.type, true); } break; case 'move': // Implémenter la logique de déplacement console.log(`Déplacer ${item.name}`); break; case 'share': if (item.type === 'file') { // Copier le lien de partage dans le presse-papier const shareButton = document.querySelector(`[data-file-name="${item.name}"] .copy-button`); const fileUrl = shareButton?.dataset.fileUrl; if (fileUrl) { navigator.clipboard.writeText(fileUrl) .then(() => { Swal.fire({ position: 'top-end', icon: 'success', title: 'Lien copié !', showConfirmButton: false, timer: 1500, toast: true }); }); } } break; } } }); document.addEventListener('DOMContentLoaded', function() { // Gestion de la suppression des dossiers document.querySelectorAll('.delete-folder-btn').forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const folderName = this.dataset.folderName; Swal.fire({ title: 'Êtes-vous sûr ?', text: `Voulez-vous vraiment supprimer le dossier "${folderName}" ?`, icon: 'warning', showCancelButton: true, confirmButtonColor: '#dc3545', confirmButtonText: 'Supprimer', cancelButtonText: 'Annuler' }).then((result) => { if (result.isConfirmed) { // Appel à votre API pour supprimer le dossier fetch(`/api/dpanel/folders/delete/${encodeURIComponent(folderName)}`, { method: 'DELETE' }) .then(response => response.json()) .then(data => { if (data.success) { // Supprimer la ligne du tableau const row = button.closest('tr'); row.remove(); // Afficher une notification de succès Swal.fire({ position: 'top-end', icon: 'success', title: 'Dossier supprimé !', showConfirmButton: false, timer: 1500, toast: true }); } else { throw new Error(data.message || 'Erreur lors de la suppression'); } }) .catch(error => { Swal.fire({ position: 'top-end', icon: 'error', title: 'Erreur lors de la suppression', text: error.message, showConfirmButton: false, timer: 3000, toast: true }); }); } }); }); }); // Gestion du renommage des dossiers document.querySelectorAll('.rename-folder-btn').forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const folderName = this.dataset.folderName; Swal.fire({ title: 'Renommer le dossier', input: 'text', inputValue: folderName, showCancelButton: true, confirmButtonText: 'Renommer', cancelButtonText: 'Annuler', inputValidator: (value) => { if (!value) { return 'Veuillez entrer un nom de dossier'; } } }).then((result) => { if (result.isConfirmed) { const newName = result.value; // Appel à votre API pour renommer le dossier fetch('/api/dpanel/folders/rename', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ oldName: folderName, newName: newName }) }) .then(response => response.json()) .then(data => { if (data.success) { // Mettre à jour l'affichage const row = button.closest('tr'); row.querySelector('td:first-child').textContent = newName; // Mettre à jour les attributs data row.dataset.name = newName; button.dataset.folderName = newName; button.dataset.itemName = newName; // Mettre à jour le lien d'ouverture const openLink = row.querySelector('a.dropdown-item'); if (openLink) { openLink.href = `/dpanel/dashboard/folder/${encodeURIComponent(newName)}`; } Swal.fire({ position: 'top-end', icon: 'success', title: 'Dossier renommé !', showConfirmButton: false, timer: 1500, toast: true }); } else { throw new Error(data.message || 'Erreur lors du renommage'); } }) .catch(error => { Swal.fire({ position: 'top-end', icon: 'error', title: 'Erreur lors du renommage', text: error.message, showConfirmButton: false, timer: 3000, toast: true }); }); } }); }); }); }); document.querySelectorAll('tr[data-type="folder"] td:first-child, tr[data-type="shared-folder"] td:first-child').forEach(cell => { cell.addEventListener('dblclick', (e) => { e.preventDefault(); // Prevent text selection const row = cell.closest('tr'); const url = row.dataset.url; if (url) { window.location.href = url; } }); }); // Disable text selection on double-click for folder names document.querySelectorAll('tr[data-type="folder"] td:first-child, tr[data-type="shared-folder"] td:first-child').forEach(cell => { cell.style.userSelect = 'none'; }); document.addEventListener('DOMContentLoaded', () => { const searchContainer = document.querySelector('.flex.justify-between.items-center'); const button = document.createElement('button'); button.className = 'btn btn-secondary ml-2'; button.innerHTML = ''; searchContainer.appendChild(button); const table = document.querySelector('#fileTable tbody'); let isGridView = localStorage.getItem('isGridView') === 'true'; function buildGridLayout(tr) { const firstCell = tr.querySelector('td:first-child'); const name = firstCell.querySelector('div').innerText.trim(); const icon = firstCell.querySelector('i').cloneNode(true); const type = tr.querySelector('td:nth-child(2)').innerText.trim(); const owner = tr.querySelector('td:nth-child(3)').innerText.trim(); const size = tr.querySelector('td:nth-child(4)').innerText.trim(); const collab = firstCell.querySelector('.collaboration-badge'); const content = document.createElement('div'); content.className = 'icon-container'; content.innerHTML = `
${icon.outerHTML}
${name}
${type} • ${size}
`; firstCell.innerHTML = ''; firstCell.appendChild(content); if (collab) { firstCell.appendChild(collab); } } function toggleView(e) { e?.preventDefault(); isGridView = !table.classList.contains('grid-view'); if (isGridView) { table.classList.add('grid-view'); table.querySelectorAll('tr').forEach(buildGridLayout); button.innerHTML = ''; } else { table.classList.remove('grid-view'); location.reload(); button.innerHTML = ''; } localStorage.setItem('isGridView', isGridView); } button.addEventListener('click', toggleView); if (isGridView) { table.classList.add('grid-view'); table.querySelectorAll('tr').forEach(buildGridLayout); button.innerHTML = ''; } }); // Améliorations de la vue grille function toggleGridView() { const table = document.querySelector('#fileTable tbody'); const isGridView = table.classList.contains('grid-view'); if (!isGridView) { table.classList.add('grid-view'); document.querySelectorAll('#fileTable tbody tr').forEach(tr => { const firstCell = tr.querySelector('td:first-child'); const icon = firstCell.querySelector('i').cloneNode(true); const name = firstCell.textContent.trim(); const type = tr.querySelector('td:nth-child(2)').textContent.trim(); const container = document.createElement('div'); container.className = 'icon-container'; container.innerHTML = `
${icon.outerHTML}
${name}
${type}
`; firstCell.innerHTML = ''; firstCell.appendChild(container); }); } else { table.classList.remove('grid-view'); location.reload(); // Recharger pour restaurer la vue liste } localStorage.setItem('viewMode', isGridView ? 'list' : 'grid'); } // Gestionnaire du menu contextuel amélioré function handleContextMenu(e) { e.preventDefault(); const target = e.target.closest('tr'); if (!target) return; const contextMenu = document.querySelector('.context-menu'); contextMenu.style.display = 'block'; // Positionnement intelligent du menu const x = e.pageX; const y = e.pageY; const winWidth = window.innerWidth; const winHeight = window.innerHeight; const menuWidth = contextMenu.offsetWidth; const menuHeight = contextMenu.offsetHeight; contextMenu.style.left = (x + menuWidth > winWidth ? winWidth - menuWidth : x) + 'px'; contextMenu.style.top = (y + menuHeight > winHeight ? winHeight - menuHeight : y) + 'px'; // Stockage de la référence à l'élément contextMenu.dataset.targetName = target.dataset.name; contextMenu.dataset.targetType = target.dataset.type; // Mise à jour des actions du menu updateContextMenuActions(target); } function updateContextMenuActions(target) { const contextMenu = document.querySelector('.context-menu'); const actions = contextMenu.querySelectorAll('.menu-item'); actions.forEach(action => { action.onclick = (e) => { e.preventDefault(); const name = contextMenu.dataset.targetName; const type = contextMenu.dataset.targetType; switch(action.dataset.action) { case 'open': if (type === 'folder') { window.location.href = `/dpanel/dashboard/folder/${encodeURIComponent(name)}`; } break; case 'rename': if (type === 'folder') { renameFolder(name); } else { renameFile(name); } break; case 'delete': if (type === 'folder') { confirmDeleteFolder(name); } else { confirmDelete(name); } break; case 'share': if (type === 'file') { const url = target.dataset.url; copyFileLink(url); } break; } contextMenu.style.display = 'none'; }; }); } // Initialisation document.addEventListener('DOMContentLoaded', () => { // Restaurer la vue précédente const viewMode = localStorage.getItem('viewMode'); if (viewMode === 'grid') { toggleGridView(); } // Gestionnaire du bouton de vue document.querySelector('.view-toggle').addEventListener('click', toggleGridView); // Gestionnaire du menu contextuel document.addEventListener('contextmenu', handleContextMenu); document.addEventListener('click', (e) => { if (!e.target.closest('.context-menu')) { document.querySelector('.context-menu').style.display = 'none'; } }); }); function getDefaultAvatar(username) { const encodedName = encodeURIComponent(username); return `https://api.dicebear.com/7.x/initials/svg?seed=${encodedName}&background=%234e54c8&radius=50`; } // Modifiez la fonction qui affiche les détails de collaboration function showCollaborationDetails(itemName, itemType) { fetch(`/api/dpanel/collaboration/details/${itemType}/${itemName}`) .then(response => response.json()) .then(data => { let userList = ''; if (data.activeUsers && data.activeUsers.length > 0) { userList = data.activeUsers.map(user => { const avatarUrl = user.profilePicture || getDefaultAvatar(user.name); return `
${user.name} ${user.name}
`; }).join(''); } else { userList = '
Aucun utilisateur actif
'; } }); } document.addEventListener('DOMContentLoaded', () => { // Récupération des éléments nécessaires const tableBody = document.querySelector('#fileTable tbody'); const searchContainer = document.querySelector('.flex.justify-between.items-center'); if (!tableBody || !searchContainer) return; // Protection contre les éléments manquants // Création du bouton de basculement const viewToggleBtn = document.createElement('button'); viewToggleBtn.className = 'btn btn-secondary ml-2 view-toggle-btn'; viewToggleBtn.innerHTML = ''; searchContainer.appendChild(viewToggleBtn); // Récupération du mode de vue sauvegardé let isGridView = localStorage.getItem('isGridView') === 'true'; function buildGridLayout(tr) { if (!tr) return; const firstCell = tr.querySelector('td:first-child'); if (!firstCell) return; const name = firstCell.innerText.trim(); const icon = firstCell.querySelector('i')?.cloneNode(true); const type = tr.querySelector('td:nth-child(2)')?.innerText.trim() || ''; const owner = tr.querySelector('td:nth-child(3)')?.innerText.trim() || ''; const size = tr.querySelector('td:nth-child(4)')?.innerText.trim() || ''; const collab = firstCell.querySelector('.collaboration-badge'); if (!icon) return; const content = document.createElement('div'); content.className = 'icon-container'; content.innerHTML = `
${icon.outerHTML}
${name}
${type} • ${size}
`; firstCell.innerHTML = ''; firstCell.appendChild(content); if (collab) { firstCell.appendChild(collab); } } function toggleView() { isGridView = !tableBody.classList.contains('grid-view'); if (isGridView) { tableBody.classList.add('grid-view'); document.querySelectorAll('#fileTable tbody tr').forEach(buildGridLayout); viewToggleBtn.innerHTML = ''; } else { tableBody.classList.remove('grid-view'); location.reload(); // Recharge la page pour restaurer la vue liste viewToggleBtn.innerHTML = ''; } localStorage.setItem('isGridView', isGridView); } // Ajout du gestionnaire d'événements viewToggleBtn.addEventListener('click', toggleView); // Initialisation de la vue au chargement if (isGridView) { tableBody.classList.add('grid-view'); document.querySelectorAll('#fileTable tbody tr').forEach(buildGridLayout); viewToggleBtn.innerHTML = ''; } }); // ...existing code... // Gestion des collaborations (remplacez ou ajoutez cette partie) function showCollaborationModal(itemName, itemType) { const modalHtml = `
Collaborateurs actifs
Chargement...
Ajouter un collaborateur
`; Swal.fire({ title: 'Gestion de la collaboration', html: modalHtml, showCancelButton: true, showDenyButton: true, confirmButtonText: 'Fermer', denyButtonText: 'Désactiver la collaboration', denyButtonColor: '#dc3545', width: '600px', didOpen: () => { // Charger les utilisateurs actifs loadActiveUsers(itemName, itemType); // Configuration de la recherche const searchInput = Swal.getPopup().querySelector('#searchUserInput'); const searchBtn = Swal.getPopup().querySelector('#searchUserBtn'); searchBtn.addEventListener('click', () => searchUsers(searchInput.value, itemName, itemType)); searchInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { searchUsers(searchInput.value, itemName, itemType); } }); } }).then((result) => { if (result.isDenied) { disableCollaboration(itemName, itemType); } }); } // Fonction de chargement des utilisateurs actifs function loadActiveUsers(itemName, itemType) { fetch(`/api/dpanel/collaboration/users/${itemType}/${itemName}`) .then(response => response.json()) .then(data => { const usersList = Swal.getPopup().querySelector('#activeUsersList'); if (!usersList) return; if (data.users && data.users.length > 0) { const usersHtml = data.users.map(user => `
${user.name}
${user.name}
En ligne
`).join(''); usersList.innerHTML = usersHtml; } else { usersList.innerHTML = '
Aucun collaborateur actif
'; } }) .catch(error => { console.error('Erreur lors du chargement des utilisateurs:', error); }); } // Fonction de recherche d'utilisateurs function searchUsers(searchTerm, itemName, itemType) { if (!searchTerm.trim()) return; const resultsDiv = Swal.getPopup().querySelector('#searchResults'); if (!resultsDiv) return; resultsDiv.innerHTML = '
Recherche...
'; fetch(`/api/dpanel/users/search?term=${encodeURIComponent(searchTerm)}`) .then(response => response.json()) .then(data => { if (data.users && data.users.length > 0) { const resultsHtml = data.users.map(user => `
${user.name} ${user.name}
`).join(''); resultsDiv.innerHTML = resultsHtml; } else { resultsDiv.innerHTML = '
Aucun utilisateur trouvé
'; } }) .catch(error => { console.error('Erreur lors de la recherche:', error); resultsDiv.innerHTML = '
Erreur lors de la recherche
'; }); } // Ajoutez cet écouteur d'événements pour le bouton de collaboration document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('.toggle-collaboration-btn').forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const itemName = this.getAttribute('data-item-name'); const itemType = this.getAttribute('data-item-type'); const isCollaborative = this.getAttribute('data-is-collaborative') === 'true'; if (isCollaborative) { showCollaborationModal(itemName, itemType); } else { toggleCollaboration(itemName, itemType, true); } }); }); }); // Remplacez ou ajoutez cette fonction dans votre fichier dashboard.js function showCollaborationModal(itemName, itemType) { Swal.fire({ title: 'Gestion de la collaboration', html: `
Collaborateurs actifs
Chargement...
Ajouter un collaborateur
`, showCancelButton: true, showDenyButton: true, confirmButtonText: 'Fermer', denyButtonText: 'Désactiver la collaboration', denyButtonColor: '#dc3545', width: '600px', customClass: { container: 'collaboration-modal', popup: 'collaboration-popup', content: 'collaboration-content' }, didOpen: () => { loadActiveUsers(itemName, itemType); setupSearchHandlers(itemName, itemType); } }).then((result) => { if (result.isDenied) { disableCollaboration(itemName, itemType); } }); } // Modifier l'événement click des boutons de collaboration document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('.toggle-collaboration-btn').forEach(button => { button.addEventListener('click', function(e) { e.preventDefault(); const itemName = this.getAttribute('data-item-name'); const itemType = this.getAttribute('data-item-type'); const isCollaborative = this.getAttribute('data-is-collaborative') === 'true'; if (isCollaborative) { showCollaborationModal(itemName, itemType); } else { toggleCollaboration(itemName, itemType, true); } }); }); }); function loadActiveUsers(itemName, itemType) { const usersList = Swal.getPopup().querySelector('#activeUsersList'); fetch(`/api/dpanel/collaboration/users/${itemType}/${itemName}`) .then(response => response.json()) .then(data => { if (!usersList) return; if (data.users && data.users.length > 0) { usersList.innerHTML = data.users.map(user => `
${user.name}
${user.name}
En ligne
`).join(''); } else { usersList.innerHTML = '
Aucun collaborateur actif
'; } }) .catch(error => { console.error('Erreur:', error); usersList.innerHTML = '
Erreur lors du chargement
'; }); } function setupSearchHandlers(itemName, itemType) { const searchInput = Swal.getPopup().querySelector('#searchUserInput'); const searchBtn = Swal.getPopup().querySelector('#searchUserBtn'); if (!searchInput || !searchBtn) return; searchBtn.onclick = () => searchUsers(searchInput.value, itemName, itemType); searchInput.onkeypress = (e) => { if (e.key === 'Enter') { searchUsers(searchInput.value, itemName, itemType); } }; } function searchUsers(searchTerm, itemName, itemType) { if (!searchTerm.trim()) return; const resultsDiv = Swal.getPopup().querySelector('#searchResults'); if (!resultsDiv) return; resultsDiv.innerHTML = '
Recherche...
'; fetch(`/api/dpanel/users/search?term=${encodeURIComponent(searchTerm)}`) .then(response => response.json()) .then(data => { if (data.users && data.users.length > 0) { resultsDiv.innerHTML = data.users.map(user => `
${user.name} ${user.name}
`).join(''); } else { resultsDiv.innerHTML = '
Aucun utilisateur trouvé
'; } }) .catch(error => { console.error('Erreur:', error); resultsDiv.innerHTML = '
Erreur lors de la recherche
'; }); }