Files
serv_benchmark/docs/SESSION_2025-12-31_EDIT_PERIPHERAL.md
Gilles Soulier c67befc549 addon
2026-01-05 16:08:01 +01:00

451 lines
11 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Session 2025-12-31 : Implémentation du bouton "Modifier"
## 🎯 Objectif
Implémenter le bouton "Modifier" dans la page de détail du périphérique pour permettre l'édition complète des informations.
## 📊 État initial
**Avant** :
- ✅ Bouton "Modifier" présent dans l'interface
- ❌ Fonction `toggleEditMode()` affichait juste "Mode édition à venir"
- ❌ Pas de modale d'édition
- ❌ Pas de fonction de sauvegarde
## ✅ Implémentation
### 1. Modale d'édition HTML
**Fichier** : `frontend/peripheral-detail.html` (lignes 305-453)
**Structure** :
```html
<div id="modal-edit" class="modal">
<div class="modal-content modal-large">
<form id="form-edit-peripheral" onsubmit="savePeripheral(event)">
<!-- 3 sections principales -->
<div class="form-section">Identification</div>
<div class="form-section">Achat</div>
<div class="form-section">État et localisation</div>
<div class="form-section full-width">Documentation technique</div>
</form>
</div>
</div>
```
**Champs disponibles** :
#### Section Identification
- `nom` * (requis)
- `type_principal` * (requis)
- `sous_type`
- `marque`
- `modele`
- `numero_serie`
#### Section Achat
- `boutique`
- `date_achat` (type date)
- `prix` (number)
- `devise` (3 caractères, défaut: EUR)
- `garantie_duree_mois` (number)
#### Section État et localisation
- `etat` (select: Neuf, Bon, Usagé, Défectueux, Retiré)
- `rating` (0-5 étoiles cliquables)
- `quantite_totale` (number)
- `quantite_disponible` (number)
#### Section Documentation technique
- `synthese` (textarea Markdown)
- `cli_yaml` (textarea YAML)
- `cli_raw` (textarea Markdown)
- `specifications` (textarea Markdown)
- `notes` (textarea Markdown)
### 2. Fonction JavaScript : `toggleEditMode()`
**Fichier** : `frontend/js/peripheral-detail.js` (lignes 461-494)
```javascript
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 champs)
// Special handling for rating (star system)
setEditRating(peripheral.rating || 0);
// Show modal
document.getElementById('modal-edit').style.display = 'block';
}
```
**Fonctionnement** :
1. Vérifie que le périphérique est chargé
2. Remplit tous les champs du formulaire avec les données actuelles
3. Applique la note avec le système d'étoiles
4. Affiche la modale
### 3. Fonction : `setEditRating()`
**Fichier** : `frontend/js/peripheral-detail.js` (lignes 500-513)
```javascript
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');
}
});
}
```
**Fonctionnement** :
- Active les étoiles jusqu'à la note donnée
- Stocke la valeur dans le champ hidden
- Utilisé à la fois lors du chargement et lors du clic
### 4. Event listeners pour les étoiles
**Fichier** : `frontend/js/peripheral-detail.js` (lignes 515-525)
```javascript
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);
});
});
});
```
**Fonctionnement** :
- Attache un event listener à chaque étoile
- Au clic, récupère la note (1-5)
- Appelle `setEditRating()` pour mettre à jour visuellement
### 5. Fonction : `savePeripheral()`
**Fichier** : `frontend/js/peripheral-detail.js` (lignes 527-559)
```javascript
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');
}
}
```
**Fonctionnement** :
1. Empêche le submit par défaut
2. Récupère toutes les données du formulaire
3. Convertit les champs numériques en `float`
4. Envoie une requête `PUT` à l'API
5. Affiche un message de succès/erreur
6. Ferme la modale
7. Recharge les données du périphérique pour afficher les changements
### 6. Fonction : `closeEditModal()`
**Fichier** : `frontend/js/peripheral-detail.js` (lignes 496-498)
```javascript
function closeEditModal() {
document.getElementById('modal-edit').style.display = 'none';
}
```
**Utilisation** :
- Bouton "Annuler" dans la modale
- Croix de fermeture (×)
- Clic en dehors de la modale (via `window.onclick`)
### 7. Style CSS pour grande modale
**Fichier** : `frontend/css/peripherals.css` (lignes 284-287)
```css
.modal-content.modal-large {
max-width: 1400px;
width: 95%;
}
```
**Usage** : Classe `.modal-large` appliquée à la modale d'édition pour afficher tous les champs confortablement.
## 🔄 Flux complet
```
1. User clique "Modifier"
2. toggleEditMode()
├─> Vérifie que peripheral est chargé
├─> Remplit tous les champs du formulaire
├─> Applique la note (étoiles)
└─> Affiche la modale
3. User modifie les champs
├─> Clic sur étoiles → setEditRating()
└─> Saisie texte, nombres, dates
4. User clique "Enregistrer"
5. savePeripheral()
├─> Prévient le submit par défaut
├─> Récupère FormData
├─> Convertit types (string → number)
├─> PUT /api/peripherals/{id}
├─> Succès → showSuccess() + closeEditModal()
├─> Erreur → showError()
└─> Recharge → loadPeripheral()
6. Page mise à jour avec nouvelles données
```
## 📋 Requête API
### Endpoint
```
PUT /api/peripherals/{id}
```
### Headers
```json
{
"Content-Type": "application/json",
"X-API-Token": "YOUR_TOKEN"
}
```
### Body (exemple)
```json
{
"nom": "Logitech MX Master 3S",
"type_principal": "Souris",
"sous_type": "Sans fil",
"marque": "Logitech",
"modele": "MX Master 3S",
"numero_serie": "LGI-2024-001",
"boutique": "Amazon",
"date_achat": "2024-12-01",
"prix": 99.99,
"devise": "EUR",
"garantie_duree_mois": 24,
"etat": "Neuf",
"rating": 5,
"quantite_totale": 1,
"quantite_disponible": 1,
"synthese": "# Souris ergonomique\n\nExcellente souris pour le travail.",
"cli_yaml": "identification:\n vendor_id: 046d\n product_id: 4082",
"cli_raw": "```\nBus 001 Device 005: ID 046d:4082 Logitech, Inc.\n```",
"specifications": "## Caractéristiques\n- DPI : 8000\n- Bluetooth 5.0",
"notes": "Achetée en promotion"
}
```
### Réponse (200 OK)
```json
{
"id": 3,
"nom": "Logitech MX Master 3S",
"type_principal": "Souris",
// ... tous les champs mis à jour
"updated_at": "2025-12-31T12:00:00"
}
```
## 🧪 Test de validation
### 1. Ouvrir la page de détail
```
http://10.0.0.50:8087/peripheral-detail.html?id=3
```
### 2. Cliquer sur "Modifier"
**Vérifications** :
- ✅ La modale s'affiche
- ✅ Tous les champs sont pré-remplis avec les données actuelles
- ✅ Les étoiles correspondent à la note actuelle
### 3. Modifier des champs
**Test** :
- Modifier le nom
- Changer la note (clic sur étoiles)
- Modifier le prix
- Ajouter des notes
**Vérifications** :
- ✅ Les étoiles s'activent au clic
- ✅ Les champs acceptent la saisie
- ✅ La validation fonctionne (champs requis)
### 4. Enregistrer
**Vérifications** :
- ✅ Message "Périphérique mis à jour avec succès"
- ✅ Modale se ferme
- ✅ Données affichées sont mises à jour
- ✅ Pas d'erreur console
### 5. Vérifier la persistance
**Test** :
- Rafraîchir la page (F5)
- Vérifier que les modifications sont conservées
**Vérifications** :
- ✅ Les données modifiées sont affichées
- ✅ La base de données a bien été mise à jour
## 🎨 Interface utilisateur
### Bouton "Modifier"
**Position** : En haut à droite de la carte "Informations générales"
```html
<button class="btn btn-primary" onclick="toggleEditMode()" id="btn-edit">
<i class="fas fa-edit"></i> Modifier
</button>
```
### Modale d'édition
**Largeur** : 95% (max 1400px) grâce à `.modal-large`
**Layout** : Grid responsive avec 3 colonnes sur desktop
**Sections** :
1. Identification (colonne 1)
2. Achat (colonne 2)
3. État et localisation (colonne 3)
4. Documentation technique (pleine largeur)
### Boutons d'action
```html
<div class="form-actions">
<button type="button" class="btn btn-secondary" onclick="closeEditModal()">
Annuler
</button>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> Enregistrer
</button>
</div>
```
## 📝 Notes techniques
### Gestion des types de données
**String vers Number** :
```javascript
if (['prix', 'garantie_duree_mois', 'quantite_totale', 'quantite_disponible', 'rating'].includes(key)) {
data[key] = value ? parseFloat(value) : null;
}
```
**Date** : Format `YYYY-MM-DD` (HTML5 input type="date")
**Null values** : Les champs vides sont envoyés comme `null` au lieu de chaînes vides
### Validation
**Côté client** :
- Champs requis : `nom`, `type_principal`
- Type number : min="0" pour prix et quantités
- Type date : format ISO 8601
**Côté serveur** : Validation Pydantic dans le backend FastAPI
### Système d'étoiles
**État actif** : Classe CSS `.active` ajoutée aux étoiles
**HTML structure** :
```html
<div class="star-rating" id="edit-star-rating">
<input type="hidden" id="edit-rating" name="rating" value="0">
<i class="fas fa-star" data-rating="1"></i>
<i class="fas fa-star" data-rating="2"></i>
<!-- ... -->
</div>
```
**CSS** :
```css
.star-rating .fa-star.active {
color: #f1c40f;
text-shadow: 0 0 3px rgba(241, 196, 15, 0.5);
}
```
## 🔧 Améliorations futures possibles
- [ ] Validation en temps réel des champs
- [ ] Preview Markdown pour les textareas
- [ ] Auto-save (brouillon local)
- [ ] Historique des modifications (qui/quand)
- [ ] Undo/Redo
- [ ] Dropdowns pour type_principal/sous_type (au lieu de input text)
- [ ] Upload photo directement depuis la modale d'édition
- [ ] Confirmation avant fermeture si modifications non sauvegardées
---
**Date** : 31 décembre 2025
**Statut** : ✅ Implémenté et testé
**Impact** : Édition complète des périphériques depuis la page de détail