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

10 KiB
Executable File

Fonctionnalité : Modifier un périphérique

🎯 Objectif

Implémenter le bouton "Modifier" dans la page de détail d'un périphérique pour permettre l'édition complète des informations.

Implémentation

1. Interface HTML

Fichier : frontend/peripheral-detail.html

Modale d'édition (lignes 305-453)

<!-- Edit Peripheral Modal -->
<div id="modal-edit" class="modal">
    <div class="modal-content modal-large">
        <div class="modal-header">
            <h2><i class="fas fa-edit"></i> Modifier le périphérique</h2>
            <span class="close" onclick="closeEditModal()">&times;</span>
        </div>
        <div class="modal-body">
            <form id="form-edit-peripheral" onsubmit="savePeripheral(event)">
                <!-- Formulaire complet avec tous les champs -->
            </form>
        </div>
    </div>
</div>

Sections du formulaire

  1. Identification

    • Nom (requis)
    • Type principal (requis)
    • Sous-type
    • Marque
    • Modèle
    • Numéro de série
  2. Achat

    • Boutique
    • Date d'achat
    • Prix
    • Devise
    • Garantie (mois)
  3. État et localisation

    • État (Neuf, Bon, Usagé, Défectueux, Retiré)
    • Note (système d'étoiles cliquables)
    • Quantité totale
    • Quantité disponible
  4. Documentation technique

    • Synthèse (Markdown)
    • CLI / Données structurées (YAML)
    • CLI / Rapport système (Markdown)
    • Spécifications (Markdown)
    • Notes (Markdown)

2. Style CSS

Fichier : frontend/css/peripherals.css (lignes 284-287)

.modal-content.modal-large {
    max-width: 1400px;
    width: 95%;
}

Caractéristiques :

  • Modale plus large pour afficher tous les champs
  • Responsive (95% de la largeur sur petit écran)
  • Max 1400px sur grand écran

3. JavaScript - Fonctions

Fichier : frontend/js/peripheral-detail.js

toggleEditMode() (ligne 461-494)

Rôle : Ouvrir la modale et pré-remplir le formulaire avec les données actuelles

function toggleEditMode() {
    if (!peripheral) {
        showError('Aucun périphérique chargé');
        return;
    }

    // Populate form with peripheral data
    document.getElementById('edit-nom').value = peripheral.nom || '';
    document.getElementById('edit-type_principal').value = peripheral.type_principal || '';
    // ... tous les autres champs ...

    // Show modal
    document.getElementById('modal-edit').style.display = 'block';
}

Gère :

  • Vérification que le périphérique est chargé
  • Pré-remplissage de tous les champs du formulaire
  • Gestion des valeurs nulles avec fallback
  • Appel setEditRating() pour les étoiles

closeEditModal() (ligne 496-498)

Rôle : Fermer la modale d'édition

function closeEditModal() {
    document.getElementById('modal-edit').style.display = 'none';
}

setEditRating(rating) (ligne 500-513)

Rôle : Mettre à jour l'affichage des étoiles dans le formulaire d'édition

function setEditRating(rating) {
    const stars = document.querySelectorAll('#edit-star-rating .fa-star');
    const ratingInput = document.getElementById('edit-rating');

    ratingInput.value = rating;

    stars.forEach((star, index) => {
        if (index < rating) {
            star.classList.add('active');
        } else {
            star.classList.remove('active');
        }
    });
}

Fonctionnalités :

  • Met à jour le champ hidden edit-rating
  • Ajoute/retire la classe active sur les étoiles
  • Permet sélection visuelle interactive

Event listener étoiles (ligne 516-525)

document.addEventListener('DOMContentLoaded', () => {
    const editStars = document.querySelectorAll('#edit-star-rating .fa-star');

    editStars.forEach(star => {
        star.addEventListener('click', () => {
            const rating = parseInt(star.getAttribute('data-rating'));
            setEditRating(rating);
        });
    });
});

Rôle : Rendre les étoiles cliquables pour modifier la note

savePeripheral(event) (ligne 527-559)

Rôle : Sauvegarder les modifications via l'API

async function savePeripheral(event) {
    event.preventDefault();

    const form = event.target;
    const formData = new FormData(form);
    const data = {};

    // Convert FormData to object
    for (let [key, value] of formData.entries()) {
        // Convert numeric fields
        if (['prix', 'garantie_duree_mois', 'quantite_totale', 'quantite_disponible', 'rating'].includes(key)) {
            data[key] = value ? parseFloat(value) : null;
        } else {
            data[key] = value || null;
        }
    }

    try {
        const response = await apiRequest(`/peripherals/${peripheralId}`, {
            method: 'PUT',
            body: JSON.stringify(data)
        });

        showSuccess('Périphérique mis à jour avec succès');
        closeEditModal();

        // Reload peripheral data
        await loadPeripheral();
    } catch (error) {
        console.error('Error updating peripheral:', error);
        showError('Erreur lors de la mise à jour du périphérique');
    }
}

Processus :

  1. Empêche soumission formulaire par défaut
  2. Récupère les données du formulaire
  3. Convertit FormData en objet JavaScript
  4. Convertit champs numériques en nombres
  5. Envoie requête PUT à l'API
  6. Affiche message succès/erreur
  7. Ferme la modale
  8. Recharge les données pour rafraîchir l'affichage

4. API Backend

Endpoint : PUT /api/peripherals/{peripheral_id}

Fichier : backend/app/api/endpoints/peripherals.py (ligne 177-187)

@router.put("/{peripheral_id}", response_model=PeripheralDetail)
def update_peripheral(
    peripheral_id: int,
    peripheral_data: PeripheralUpdate,
    db: Session = Depends(get_peripherals_db)
):
    """Update a peripheral"""
    peripheral = PeripheralService.update_peripheral(db, peripheral_id, peripheral_data)
    if not peripheral:
        raise HTTPException(status_code=404, detail="Peripheral not found")
    return peripheral

Schéma attendu : PeripheralUpdate (Pydantic)

Retour : PeripheralDetail (données complètes du périphérique)

🔄 Flux d'utilisation

1. User clique "Modifier" dans page détail
   ↓
2. toggleEditMode() appelé
   │  ├─> Vérifie que peripheral est chargé
   │  ├─> Pré-remplit tous les champs du formulaire
   │  ├─> Configure les étoiles de notation
   │  └─> Affiche la modale
   ↓
3. User modifie les champs souhaités
   │  └─> Peut cliquer sur les étoiles pour changer la note
   ↓
4. User clique "Enregistrer"
   ↓
5. savePeripheral() appelé
   │  ├─> Récupère données du formulaire
   │  ├─> Convertit types numériques
   │  ├─> PUT /api/peripherals/{id}
   │  └─> Backend met à jour en BDD
   ↓
6. Success
   │  ├─> Message "Périphérique mis à jour avec succès"
   │  ├─> Ferme modale
   │  └─> Recharge peripheral pour afficher nouvelles données

📊 Champs éditables

Catégorie Champ Type Requis
Identification nom text
type_principal text
sous_type text
marque text
modele text
numero_serie text
Achat boutique text
date_achat date
prix number
devise text(3)
garantie_duree_mois number
État etat select
rating number(0-5)
quantite_totale number
quantite_disponible number
Documentation synthese textarea
cli_yaml textarea
cli_raw textarea
specifications textarea
notes textarea

Total : 22 champs éditables

🎨 Interface utilisateur

Bouton "Modifier"

Position : Dans le header de la carte "Informations générales"

<button class="btn btn-primary" onclick="toggleEditMode()" id="btn-edit">
    <i class="fas fa-edit"></i> Modifier
</button>

Style :

  • Bouton bleu primaire
  • Icône crayon Font Awesome
  • Positionné à droite du header

Modale d'édition

Dimensions :

  • Largeur : 95% (mobile) → max 1400px (desktop)
  • Layout : Grille responsive 3 colonnes

Sections :

  • 3 colonnes pour les champs principaux
  • Pleine largeur pour documentation technique
  • Actions (Annuler / Enregistrer) en bas

Retour utilisateur

Messages :

  • Succès : "Périphérique mis à jour avec succès" (vert)
  • Erreur : "Erreur lors de la mise à jour du périphérique" (rouge)
  • ⚠️ Validation : "Aucun périphérique chargé" (orange)

🧪 Tests

Test manuel

  1. Ouvrir page détail : /peripheral-detail.html?id=3
  2. Cliquer "Modifier" : Modale s'ouvre avec données pré-remplies
  3. Modifier champs : Ex: changer nom, prix, note
  4. Cliquer étoiles : Note change visuellement
  5. Cliquer "Enregistrer" : Message succès + modale se ferme
  6. Vérifier affichage : Nouvelles valeurs affichées

Test API

# Mettre à jour un périphérique
curl -X PUT "http://10.0.0.50:8007/api/peripherals/3" \
  -H "Content-Type: application/json" \
  -H "X-API-Token: YOUR_TOKEN" \
  -d '{
    "nom": "Logitech MX Master 3 (Updated)",
    "prix": 99.99,
    "rating": 5
  }'

Résultat attendu :

{
  "id": 3,
  "nom": "Logitech MX Master 3 (Updated)",
  "prix": 99.99,
  "rating": 5,
  ...
}

📝 Fichiers modifiés

Créés

  • docs/FEATURE_EDIT_PERIPHERAL.md - Cette documentation

Modifiés

  • frontend/peripheral-detail.html - Ajout modale d'édition
  • frontend/js/peripheral-detail.js - Fonctions édition complètes
  • frontend/css/peripherals.css - Style .modal-large

Backend (déjà existant)

  • backend/app/api/endpoints/peripherals.py - Endpoint PUT
  • backend/app/services/peripheral_service.py - Service update
  • backend/app/schemas/peripheral.py - Schema PeripheralUpdate

🚀 Améliorations futures possibles

  • Validation côté client (longueurs, formats)
  • Champs device_id et location_id (dropdowns)
  • Confirmation avant fermeture si modifications non sauvegardées
  • Historique des modifications (audit trail)
  • Mode "édition rapide" (inline editing)
  • Raccourci clavier (Ctrl+E)

Date : 31 décembre 2025 Statut : Implémenté et fonctionnel Impact : Permet l'édition complète des périphériques depuis la page de détail