3.1 KiB
3.1 KiB
name, description, metadata
| name | description | metadata | ||||||
|---|---|---|---|---|---|---|---|---|
| project-communication | Page Communication — tickets support + notifications : architecture, comportements UI, jobs backend |
|
Page Communication (frontend/src/pages/Communication.jsx)
Architecture générale
3 volets : sidebar (volet 1), liste (volet 2), détail (volet 3).
Onglets : support (tickets) | notifications.
Filtres chips (volet 2)
- Tickets : multi-select via
useState(new Set(['open', 'pending'])); si aucune chip active → liste vide (pas "tout afficher") - Notifications : multi-select
useState(new Set(['unread']))au démarrage ; même règle liste vide si 0 chip active - Chips actives = fond
var(--primary)+ checkmark SVG blanc ; cumulatives
Comportements notifications
- Pas de présélection automatique au chargement ni au changement d'onglet
- La notification sélectionnée reste jusqu'à clic explicite
- Menu ⋮ dans le volet 3 : "Marquer comme lu" / "Tout considérer comme lu" / "Tout supprimer"
Dropdowns portal (pattern obligatoire)
Tous les dropdowns custom (TagSelect, TypeDropdown, RecipientDropdown) utilisent createPortal(content, document.body) + position: fixed + getBoundingClientRect() pour échapper aux stacking contexts.
Composant RecipientDropdown
Dropdown searchable pour les broadcasts. Trois niveaux :
- "Tous les utilisateurs" (value
'') - "Tous les administrateurs" (value
'admins') — routé versWHERE role='admin'côté backend - Utilisateurs individuels filtrés par
display_name/emailavec avatars initiales
Broadcast payload
payload.user_id = bcUserId === 'admins' ? 'admins' : Number(bcUserId);
Ticket detail header (volet 3)
Structure colonne :
- Ligne 1 : chip Type + titre (flex:1) + StatusBadge
- Ligne 2 : "Ouvert par Nom · date [— assigné à Nom]" à gauche + chips pages à droite
margin-top: 25pxentre les deux lignes
Droits
- Utilisateur : voit uniquement ses tickets et ses notifications
- Admin : voit tous les tickets ; voit ses notifs + notifs
notifyAdmins - Actions admin-only : Assigner à, Mettre en attente, Réouvrir, Clôturer
- "Modifier la catégorisation" : accessible à tous (owner + admin)
- "Fermer" (panneau) : accessible à tous
Pièges React connus
{msg.is_admin && <span>}→ siis_admin = 0(SQLite), affiche "0". Toujours{!!msg.is_admin && ...}- Images dans messages : classe
msg-inline-img+ wrappermsg-img-wrapajouté par useEffect. Margin7pxsur.msg-img-wrapET.msg-inline-imgpour couvrir les deux cas.
Jobs backend
autoTicketStatus.js: open→pending (2j sans réponse), pending→resolved (5j sans réponse créateur) — toutes les heuresautoCleanNotifs.js: supprime notifications >7 jours sauf typesecurity— toutes les heures
Why: Nettoyage automatique pour éviter l'accumulation infinie de notifications lues.
How to apply: Si on ajoute un nouveau type de notification critique à ne jamais purger, l'ajouter à la clause type != 'security' dans autoCleanNotifs.js.