---
suivi: 1426
date: 2026-09-03
sujet: Widget Liens rapides (config JSON)
chantier: dashboard
type: feat
statut: poussé
hash: c55a55e7
fichiers:
  - config/dashboard_widgets.php
  - config/primeicons.php
  - app/Services/Dashboard/QuickLinksConfigValidator.php
  - app/Services/Dashboard/WidgetDataService.php
  - app/Services/Dashboard/DashboardDefaultLayoutService.php
  - app/Http/Controllers/WidgetController.php
  - routes/web.php
  - resources/js/Components/Dashboard/LiensRapidesWidget.vue
  - resources/js/Components/Dashboard/WidgetBody.vue
  - resources/js/Components/Dashboard/WidgetWrapper.vue
  - tests/Unit/QuickLinksConfigValidatorTest.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - public/build/
  - docs/suivi/SUIVI_1426_widget_liens_rapides.md
---

## PROMPT ENVOYÉ

SUIVI #1426 — widget Liens rapides (config JSON user_dashboard_widgets),
validation serveur URL/icône/couleur, prérequis #1425 sur origin/main.
Pas de migration, pas de prune, ne pas toucher #1396 / Aktor / grille.

## FICHES LUES

- `#1425` — widget Aktor sur main (confirmé).
- `#1396` LEÇON — pas de plancher hauteur en lecture.
- `#1352` — pattern widget interactif opt-in.

## SYNTHÈSE

### Prérequis
`origin/main` contient #1425 (`d17e644c` / `c271a2aa`, clé `aktor` dans catalogue).

### Mesures PrimeIcons
- Liste : `node_modules/primeicons/primeicons.css` → **314** classes `pi-*`
  (également `raw-svg/` 313 fichiers).
- Sélecteur existant : **non** — Aide Admin saisit l’icône en texte libre
  (`Aide/Admin/Index.vue`). Nouveau sélecteur AutoComplete + recherche (#1426).
- Source serveur : `config/primeicons.php` (whitelist validation).

### Schéma `config`
```json
{ "links": [ { "label": "…", "url": "/…|https://…", "icon": "pi-home", "color": "#1b2b4b" } ] }
```

### Limites
- max 12 liens ; label ≤ 80 ; url ≤ 500
- couleurs : palette de 10 hex (pas ColorPicker libre)
- tailles catalogue : width **4**, height **5**

### Sécurité (écriture)
1. URL : http/https ou chemin `/…` ; refuse javascript/data/file/protocol-relative
2. Icône ∈ liste PrimeIcons
3. Couleur ∈ palette
4. Affichage : `{{ label }}` (échappé) ; classe icône whitelistée ; pas de v-html
5. Liens externes : `target=_blank` + `rel=noopener noreferrer`
6. Endpoint `PUT /api/dashboard/widget/liens_rapides/config` + validation aussi dans `saveLayout`

### Isolation users
`user_dashboard_widgets.user_id` — chaque user a sa ligne / son `config`.

## DÉPLOIEMENT / TEST

```bash
git pull origin main
php artisan view:clear
php artisan route:clear
php artisan journal:sync
```

Pas de migrate. Ne pas lancer prune.

## LEÇON

Pour des URL utilisateur rendues en `href`, la whitelist de schémas doit être
serveur (ValidationException → 422) : le front seul ne suffit pas. Idem pour
classe CSS d’icône et couleur injectée en style.
