89 lines
4.7 KiB
Markdown
89 lines
4.7 KiB
Markdown
# #104 — Configuration : Redesign UI de la section « Clés API Intelligence Artificielle »
|
||
|
||
> **Statut :** ✅ livré (v2.12.0) · **Zone :** `frontend/index.html`, `frontend/js/config.js`,
|
||
> `frontend/js/ai.js`, `frontend/style.css`, `frontend/locales/{fr,en}.json`
|
||
|
||
## Problème
|
||
|
||
La section « 🤖 Clés API IA » du panneau de configuration était une longue liste plate de
|
||
champs de saisie (DeepSeek, OpenRouter, Gemini, NVIDIA, QwenCloud, Xiaomi, Mistral) sans
|
||
structure ni hiérarchie visuelle : les sélecteurs défaut, les clés et les modèles se
|
||
cotoyaient au même niveau, les badges « Configuré » étaient collés à chaque champ, et les
|
||
boutons d'action se perdaient en milieu de section.
|
||
|
||
## Objectifs
|
||
|
||
Interface plus professionnelle, mieux structurée, moins fatigante visuellement (style
|
||
SaaS moderne, dark mode, cartes + accordéons), et qui reste utilisable quand la liste de
|
||
fournisseurs s'allonge.
|
||
|
||
## Structure livrée
|
||
|
||
### 1. En-tête de section
|
||
|
||
- Titre + sous-titre explicatif (i18n `config.ai_header_desc`).
|
||
- **Barre de recherche** (`#cfg-ai-search`) filtrant les cartes fournisseurs via
|
||
`filterAIProviders()` — normalisation insensible à la casse **et aux accents**
|
||
(`_sidebarNorm`), correspondance sur le nom affiché ou l'identifiant. État vide
|
||
« Aucun fournisseur ne correspond » (`#cfg-ai-providers-empty`).
|
||
|
||
### 2. Carte « Configuration par défaut »
|
||
|
||
- Carte visuellement distincte (`.ai-default-card`) : titre en petites capitales.
|
||
- Grille **2 colonnes** : « Fournisseur par défaut » / « Modèle par défaut »
|
||
(`#cfg-ai-default-provider`, `#cfg-ai-default-model`).
|
||
- **Capacités du modèle en badges colorés** : nouveau
|
||
`renderCapabilityBadges(caps)` (`frontend/js/ai.js`) qui n'affiche que les capacités
|
||
actives sous forme de tags (`.ai-cap-badge`), au lieu de la checklist ☑/□
|
||
(`renderCapabilityList`, conservée pour les pickers de l'assistant).
|
||
|
||
### 3. Fournisseurs d'API — cartes dépliables
|
||
|
||
Rendu dynamique par `_renderAIProviderCards()` depuis `AI_PROVIDER_NAMES` + nouveau
|
||
`AI_PROVIDER_META` (nom affiché, placeholder spécifique au fournisseur). Par carte :
|
||
|
||
- **Replié** : logo (initiale dans une pastille), nom, **badge de statut**
|
||
(« Configuré » vert / « Non configuré » gris, `.ai-provider-badge.configured`) et
|
||
**corbeille discrète** (`cfg-<provider>-delete`, visible uniquement si une clé existe ;
|
||
`stopPropagation` pour ne pas déplier la carte ; confirmation conservée).
|
||
- **Déplié** : libellés **au-dessus** des champs (`.ai-field-label`), **API key à 60 % /
|
||
modèle à 40 %** (grille `3fr 2fr`), placeholder par fournisseur.
|
||
- Accessibilité : en-tête en `role="button"` + `tabindex="0"` (clavier Entrée/Espace),
|
||
`aria-expanded` synchronisé, chevron animé, focus visible.
|
||
- Les boutons « Configuré / × Supprimer » redondants dans les champs sont supprimés —
|
||
le statut vit dans l'en-tête de la carte.
|
||
|
||
### 4. Barre d'actions
|
||
|
||
- Footer **sticky** en bas de section (`.ai-keys-footer`) : « Sauvegarder » (primaire
|
||
`.config-btn-save`) et « Tester » (outline `.config-btn-secondary`), plus le span de
|
||
statut du test. Toujours accessible pendant le défilement du panneau.
|
||
|
||
## Compatibilité
|
||
|
||
- Les ID `cfg-<provider>-key`, `cfg-<provider>-model`, `cfg-<provider>-badge`,
|
||
`cfg-<provider>-delete`, `cfg-ai-default-*`, `cfg-ai-status` sont conservés :
|
||
`saveAIKeys()`, `testAIKeys()`, `deleteAIKey()` et le câblage des événements de
|
||
`initConfigModal()` ne changent pas, ni la resynchronisation des pickers IA
|
||
(`refreshAIPickers()` après save/suppression, BUG-043).
|
||
- i18n : nouvelles clés `config.ai_header_desc`, `config.ai_search_placeholder`,
|
||
`config.ai_default_section`, `config.ai_providers_title`, `config.ai_providers_empty`,
|
||
`config.ai_status_configured`, `config.ai_status_not_configured`,
|
||
`config.ai_delete_key_title` (FR + EN).
|
||
|
||
## Styles
|
||
|
||
`.ai-keys-*`, `.ai-provider-*`, `.ai-cap-badge`, `.ai-field*` — uniquement des variables
|
||
CSS existantes (`--surface`, `--bg-secondary`, `--border`, `--accent`, `--success`,
|
||
`--danger`, `--accent-bg`…), focus visibles, responsive 1 colonne < 600 px.
|
||
|
||
## Tests
|
||
|
||
- `tests/frontend/config-ai-keys.test.mjs` (JSDOM, 7 tests) : rendu des 7 cartes,
|
||
badges de statut selon les clés masquées renvoyées par `GET /api/config/ai-keys`,
|
||
bascule replié/déplié (classe `open` + `aria-expanded`), filtre de recherche
|
||
(casse/accents + état vide), collecte et POST des clés saisies par `saveAIKeys()`,
|
||
suppression avec confirmation (DELETE sur l'env name), badges de capacités.
|
||
- Suites existantes (38 modules, validate-imports, ai.test.mjs, sidebar-filters…) : vertes.
|
||
- E2E Playwright (chromium-desktop) : 91 passed / 3 skipped, 100 % sans retries.
|