Files
serv_benchmark/docs/FIXES_UI_IMPROVEMENTS.md
Gilles Soulier c67befc549 addon
2026-01-05 16:08:01 +01:00

10 KiB
Executable File

Corrections UI - Icônes par type, Localisation, Boutons

🎯 Problèmes corrigés

  1. Icônes génériques → Icônes spécifiques selon le type de périphérique
  2. Localisation manquante dans la modale d'édition
  3. Boutons Annuler/Enregistrer s'affichaient en haut au lieu d'en bas

1. Icônes spécifiques par type

Problème

Tous les périphériques sans photo affichaient l'icône générique fa-microchip.

Solution

Fichier : frontend/js/peripherals.js (lignes 973-1011)

Nouvelle fonction getTypeIcon(type) :

// Get icon based on peripheral type
function getTypeIcon(type) {
    if (!type) return 'fa-microchip';

    const typeUpper = type.toUpperCase();

    // USB devices
    if (typeUpper.includes('USB')) return 'fa-usb';

    // Storage devices
    if (typeUpper.includes('STOCKAGE') || typeUpper.includes('DISK') ||
        typeUpper.includes('SSD') || typeUpper.includes('HDD') ||
        typeUpper.includes('FLASH')) return 'fa-hdd';

    // Network devices
    if (typeUpper.includes('RÉSEAU') || typeUpper.includes('RESEAU') ||
        typeUpper.includes('NETWORK') || typeUpper.includes('WIFI') ||
        typeUpper.includes('ETHERNET')) return 'fa-network-wired';

    // Audio devices
    if (typeUpper.includes('AUDIO') || typeUpper.includes('SOUND') ||
        typeUpper.includes('SPEAKER') || typeUpper.includes('HEADPHONE')) return 'fa-volume-up';

    // Video devices
    if (typeUpper.includes('VIDEO') || typeUpper.includes('VIDÉO') ||
        typeUpper.includes('WEBCAM') || typeUpper.includes('CAMERA')) return 'fa-video';

    // Input devices
    if (typeUpper.includes('CLAVIER') || typeUpper.includes('KEYBOARD')) return 'fa-keyboard';
    if (typeUpper.includes('SOURIS') || typeUpper.includes('MOUSE')) return 'fa-mouse';

    // Other devices
    if (typeUpper.includes('BLUETOOTH')) return 'fa-bluetooth';
    if (typeUpper.includes('HUB')) return 'fa-project-diagram';
    if (typeUpper.includes('ADAPTATEUR') || typeUpper.includes('ADAPTER')) return 'fa-plug';

    // Default
    return 'fa-microchip';
}

Logique :

  • Détection par mots-clés dans le type (insensible à la casse)
  • Support français et anglais
  • Fallback vers fa-microchip si aucun match

Utilisation dans le tableau (lignes 327-328) :

${p.thumbnail_url
    ? `<img src="${escapeHtml(p.thumbnail_url)}" alt="${escapeHtml(p.nom)}" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
       <i class="fas ${getTypeIcon(p.type_principal)}" style="display:none;"></i>`
    : `<i class="fas ${getTypeIcon(p.type_principal)}"></i>`
}

Mapping des icônes

Type Mots-clés Icône Font Awesome Rendu
USB USB fa-usb 🔌
Stockage STOCKAGE, DISK, SSD, HDD, FLASH fa-hdd 💾
Réseau RÉSEAU, NETWORK, WIFI, ETHERNET fa-network-wired 🌐
Audio AUDIO, SOUND, SPEAKER, HEADPHONE fa-volume-up 🔊
Vidéo VIDEO, VIDÉO, WEBCAM, CAMERA fa-video 📹
Clavier CLAVIER, KEYBOARD fa-keyboard ⌨️
Souris SOURIS, MOUSE fa-mouse 🖱️
Bluetooth BLUETOOTH fa-bluetooth 🔵
Hub HUB fa-project-diagram 🔀
Adaptateur ADAPTATEUR, ADAPTER fa-plug 🔌
Défaut Autre fa-microchip 💻

Exemples

getTypeIcon('USB')             // → 'fa-usb'
getTypeIcon('Stockage SSD')    // → 'fa-hdd'
getTypeIcon('Réseau WiFi')     // → 'fa-network-wired'
getTypeIcon('Webcam')          // → 'fa-video'
getTypeIcon('Clavier')         // → 'fa-keyboard'
getTypeIcon('Bluetooth')       // → 'fa-bluetooth'
getTypeIcon('Hub USB')         // → 'fa-usb' (USB détecté en premier)
getTypeIcon('Unknown Type')    // → 'fa-microchip' (fallback)

2. Champ Localisation ajouté

Problème

Le champ "Localisation" était absent de la section "État et localisation" dans la modale d'édition.

Solution HTML

Fichier : frontend/peripheral-detail.html (lignes 393-398)

Ajout du champ :

<div class="form-group">
    <label for="edit-location_id">Localisation</label>
    <select id="edit-location_id" name="location_id">
        <option value="">Non définie</option>
    </select>
</div>

Position : Entre "Note" et "Quantité totale"

Solution JavaScript

Fichier : frontend/js/peripheral-detail.js (lignes 512-539)

1. Appel dans toggleEditMode() (ligne 513) :

// Load and set location
loadEditLocations(peripheral.location_id);

2. Nouvelle fonction loadEditLocations() :

// Load locations for edit modal
async function loadEditLocations(selectedLocationId) {
    try {
        const locations = await apiRequest('/locations/');
        const select = document.getElementById('edit-location_id');

        select.innerHTML = '<option value="">Non définie</option>';

        locations.forEach(location => {
            const option = document.createElement('option');
            option.value = location.id;
            option.textContent = location.nom;
            if (location.id === selectedLocationId) {
                option.selected = true;
            }
            select.appendChild(option);
        });
    } catch (error) {
        console.error('Error loading locations:', error);
    }
}

Fonctionnement :

  1. Appel API GET /locations/ pour récupérer toutes les localisations
  2. Peuplement du <select> avec les options
  3. Pré-sélection de la localisation actuelle du périphérique (si définie)
  4. Gestion des erreurs avec console.error

Résultat :

  • L'utilisateur peut maintenant modifier la localisation lors de l'édition
  • La localisation actuelle est pré-sélectionnée
  • Option "Non définie" disponible pour retirer la localisation

3. Positionnement des boutons en bas

Problème

Les boutons "Annuler" et "Enregistrer" s'affichaient en haut de la modale au lieu d'en bas.

Cause

La div .form-actions était dans un conteneur .form-grid avec display: grid. Sans instruction spécifique, elle ne prenait pas toute la largeur et pouvait s'afficher dans une colonne du grid.

Solution CSS

Fichier : frontend/css/peripherals.css (ligne 446)

Modification :

.form-actions {
    grid-column: 1 / -1;  /* Take full width of grid */
    margin-top: 2rem;
    display: flex;
    justify-content: flex-end;
    gap: 1rem;
    padding-top: 1.5rem;
    border-top: 1px solid #3e3d32;
}

Ajout de grid-column: 1 / -1 :

  • Force .form-actions à occuper toutes les colonnes du grid
  • -1 = dernière colonne (quelle que soit la taille du grid)
  • Assure que les boutons soient toujours en bas, sur toute la largeur

Résultat :

┌─────────────────────────────────────────────────────┐
│ [Identification]  [Achat]  [État et localisation]  │
│                                                     │
│ [Documentation technique - pleine largeur]         │
│                                                     │
├─────────────────────────────────────────────────────┤
│                        [Annuler] [Enregistrer]     │
└─────────────────────────────────────────────────────┘

📊 Résumé des modifications

Fichiers modifiés

Fichier Lignes Modification
frontend/js/peripherals.js 973-1011 Fonction getTypeIcon()
frontend/js/peripherals.js 327-328 Utilisation de getTypeIcon()
frontend/peripheral-detail.html 393-398 Champ localisation ajouté
frontend/js/peripheral-detail.js 513 Appel loadEditLocations()
frontend/js/peripheral-detail.js 519-539 Fonction loadEditLocations()
frontend/css/peripherals.css 446 grid-column: 1 / -1

Nouveaux éléments

Fonctions JavaScript :

  • getTypeIcon(type) - Retourne l'icône selon le type
  • loadEditLocations(selectedLocationId) - Charge les localisations

Champs HTML :

  • <select id="edit-location_id"> - Sélecteur de localisation

🧪 Tests

Test 1 : Icônes spécifiques

  1. Ouvrir http://10.0.0.50:8087/peripherals.html
  2. Observer la colonne "Photo"
  3. Vérifier que les périphériques sans photo affichent des icônes différentes :
    • USB → Icône USB
    • Stockage → Icône disque dur
    • Réseau → Icône réseau
    • Clavier → Icône clavier
    • Souris → Icône souris

Test 2 : Localisation dans édition

  1. Ouvrir un périphérique : http://10.0.0.50:8087/peripheral-detail.html?id=3
  2. Cliquer sur "Modifier"
  3. Vérifier la section "État et localisation"
  4. Le champ "Localisation" est présent
  5. Le select est pré-rempli avec les localisations disponibles
  6. La localisation actuelle est sélectionnée
  7. Modifier la localisation et enregistrer
  8. La modification est sauvegardée

Test 3 : Boutons en bas

  1. Ouvrir un périphérique
  2. Cliquer sur "Modifier"
  3. Les boutons "Annuler" et "Enregistrer" sont en bas de la modale
  4. Ils occupent toute la largeur (ligne séparatrice visible)
  5. Boutons alignés à droite

💡 Améliorations futures possibles

Icônes

  • Icônes personnalisées pour plus de types (Scanner, Imprimante, etc.)
  • Couleurs différentes selon l'état (Neuf = vert, Défectueux = rouge)
  • Possibilité de définir une icône personnalisée par périphérique

Localisation

  • Création rapide de localisation depuis la modale
  • Affichage du chemin complet (location parent → enfant)
  • Icône de localisation à côté du nom

Boutons

  • Raccourci clavier (Ctrl+S pour sauvegarder)
  • Confirmation avant fermeture si modifications non sauvegardées
  • Bouton "Appliquer" qui sauvegarde sans fermer la modale

Date : 31 décembre 2025 Statut : Toutes les corrections appliquées et testées Impact : Interface plus intuitive avec icônes contextuelles, localisation éditable, et boutons correctement positionnés