Refactoring interface web : optimisation layout colonnes et zone upload

- Fusion upload + tree en colonnes unifiées avec header unique
  - Déplacement bannière conflits en haut pour séparer les colonnes
  - Infos fichier condensées sur 1 ligne avec bouton icône à droite
  - Drop zone remplacée par tree après upload (gain d'espace ~60%)
  - Support drag & drop sur toute la colonne même avec fichier chargé
  - Styles optimisés : champ recherche intégré, bouton circulaire compact
This commit is contained in:
2026-01-12 05:29:20 +01:00
parent bd6d321ed7
commit afac7042a8
6 changed files with 350 additions and 269 deletions

View File

@@ -11,17 +11,19 @@ class UploadManager {
this.i18n = window.FUZIP_CONFIG?.i18n || {};
// Éléments DOM
this.panel = document.getElementById(`upload-panel-${side}`);
this.panel = document.getElementById(`upload-panel-${side}`); // column-header
this.column = document.getElementById(`column-${side}`);
this.dropZone = document.getElementById(`drop-zone-${side}`);
this.fileInput = document.getElementById(`file-input-${side}`);
this.btnBrowse = document.getElementById(`btn-browse-${side}`);
this.uploadInfo = document.getElementById(`upload-info-${side}`);
this.panelInfo = document.getElementById(`panel-info-${side}`);
this.fileName = document.getElementById(`file-name-${side}`);
this.fileSize = document.getElementById(`file-size-${side}`);
this.fileCount = document.getElementById(`file-count-${side}`);
this.progressBar = document.getElementById(`progress-bar-${side}`);
this.progressFill = document.getElementById(`progress-fill-${side}`);
this.progressText = document.getElementById(`progress-text-${side}`);
this.treePanel = document.getElementById(`tree-panel-${side}`);
// État
this.currentFile = null;
@@ -35,11 +37,15 @@ class UploadManager {
* Initialise les événements
*/
init() {
// Drag & Drop
// Drag & Drop sur toute la colonne
if (this.column) {
this.column.addEventListener('dragover', (e) => this.onDragOver(e));
this.column.addEventListener('dragleave', (e) => this.onDragLeave(e));
this.column.addEventListener('drop', (e) => this.onDrop(e));
}
// Click sur drop zone pour ouvrir file picker
if (this.dropZone) {
this.dropZone.addEventListener('dragover', (e) => this.onDragOver(e));
this.dropZone.addEventListener('dragleave', (e) => this.onDragLeave(e));
this.dropZone.addEventListener('drop', (e) => this.onDrop(e));
this.dropZone.addEventListener('click', () => this.fileInput?.click());
}
@@ -56,6 +62,12 @@ class UploadManager {
this.fileInput.addEventListener('change', (e) => this.onFileSelected(e));
}
// Bouton "Changer"
const btnChange = document.getElementById(`btn-change-${this.side}`);
if (btnChange) {
btnChange.addEventListener('click', () => this.fileInput?.click());
}
console.log(`[UploadManager] Initialized for side: ${this.side}`);
}
@@ -65,7 +77,7 @@ class UploadManager {
onDragOver(e) {
e.preventDefault();
e.stopPropagation();
this.dropZone?.classList.add('drag-over');
this.column?.classList.add('drag-over');
}
/**
@@ -74,7 +86,10 @@ class UploadManager {
onDragLeave(e) {
e.preventDefault();
e.stopPropagation();
this.dropZone?.classList.remove('drag-over');
// Vérifier qu'on quitte vraiment la colonne (pas juste un élément enfant)
if (!this.column?.contains(e.relatedTarget)) {
this.column?.classList.remove('drag-over');
}
}
/**
@@ -83,7 +98,7 @@ class UploadManager {
onDrop(e) {
e.preventDefault();
e.stopPropagation();
this.dropZone?.classList.remove('drag-over');
this.column?.classList.remove('drag-over');
const files = e.dataTransfer?.files;
if (files && files.length > 0) {
@@ -197,10 +212,6 @@ class UploadManager {
* @param {number} percent - 0-100
*/
showProgress(percent) {
if (this.uploadInfo) {
this.uploadInfo.classList.remove('hidden');
}
if (this.progressBar) {
this.progressBar.classList.remove('hidden');
}
@@ -220,7 +231,13 @@ class UploadManager {
*/
showSuccess(stats) {
this.panel?.classList.remove('error');
this.panel?.classList.add('success');
this.panel?.classList.add('success', 'compact');
this.column?.classList.add('success');
// Affiche le panel-info
if (this.panelInfo) {
this.panelInfo.classList.remove('hidden');
}
if (this.fileName) {
this.fileName.textContent = this.currentFile?.name || '';
@@ -234,6 +251,11 @@ class UploadManager {
this.fileCount.textContent = (stats.total_files || 0).toString();
}
// Affiche le tree-panel
if (this.treePanel) {
this.treePanel.classList.remove('hidden');
}
// Cache la progress bar après 1s
setTimeout(() => {
this.progressBar?.classList.add('hidden');
@@ -253,8 +275,8 @@ class UploadManager {
// Réinitialise
this.currentFile = null;
this.structure = null;
if (this.uploadInfo) {
this.uploadInfo.classList.add('hidden');
if (this.panelInfo) {
this.panelInfo.classList.add('hidden');
}
if (this.progressBar) {
this.progressBar.classList.add('hidden');
@@ -290,9 +312,11 @@ class UploadManager {
this.structure = null;
this.isUploading = false;
this.panel?.classList.remove('success', 'error', 'uploading');
this.uploadInfo?.classList.add('hidden');
this.panel?.classList.remove('success', 'error', 'uploading', 'compact');
this.column?.classList.remove('success', 'error');
this.panelInfo?.classList.add('hidden');
this.progressBar?.classList.add('hidden');
this.treePanel?.classList.add('hidden');
if (this.fileInput) {
this.fileInput.value = '';