Déduplication des publications (MurVille)
Contexte
Les imports automatiques depuis les sites mairie peuvent créer des doublons
en base : deux publications avec des id différents mais un contenu identique
(même titre, même date). Cela arrive lors d'un double import ou d'un import
manuel suivi du cron.
La déduplication côté front est un garde-fou de présentation. Elle ne remplace pas une correction en base mais évite d'afficher des doublons à l'utilisateur même si la base en contient.
Implémentation (MurVille.tsx et PublicationCard.tsx)
Clé de contenu
function normalizeTitre(titre: string): string {
return titre
.toLowerCase()
.normalize("NFD")
.replace(/[̀-ͯ]/g, "") // retire les accents
.replace(/\s+/g, " ")
.trim();
}
function pubContentKey(p: { titre: string; date_debut?: string | null; publie_le: string | null }): string {
const date = (p.date_debut ?? p.publie_le ?? "").slice(0, 10);
return `${normalizeTitre(p.titre)}|${date}`;
}
La clé est titre normalisé | YYYY-MM-DD. Elle est insensible à la casse, aux
accents et aux espaces multiples.
Algorithme
function deduplicateByContent<T extends { id: string; titre: string; date_debut?: string | null; publie_le: string | null }>(list: T[]): T[] {
const seen = new Map<string, T>();
for (const item of list) {
const key = pubContentKey(item);
const existing = seen.get(key);
if (!existing || (item.publie_le ?? "") > (existing.publie_le ?? "")) {
seen.set(key, item);
}
}
return [...seen.values()];
}
En cas de doublon, on conserve la publication avec le publie_le le plus récent.
Points d'application
filteredPubsuseMemo : déduplication avant l'affichage de la liste principale (tous filtres confondus).publicationAgendaEventsuseMemo : déduplication avant l'expansion des occurrences agenda pour éviter les événements en double dans le calendrier.
Gestion des doublons dans le backoffice
Le backoffice (dmv_backoffice) propose une interface de détection et suppression :
- Sidebar : badge orange sur "Publications" indiquant le nombre de groupes de doublons détectés (refresh toutes les 5 minutes).
- Dashboard : texte "X doublon(s)" sur la tuile Publications.
- Page Publications : bannière amber dépliable listant chaque groupe de doublons avec actions "Éditer" et "Supprimer" (soft-delete) sur chaque entrée.
La détection utilise les mêmes règles de normalisation que le frontend
(lib/duplicatePublications.js).
Limites
- La déduplication frontend ne s'applique qu'aux publications chargées en mémoire. Les doublons restent en base et sont fetchés à chaque fois.
- Le cache
localStorage(3 jours) stocke les deux exemplaires — la déduplication intervient uniquement au moment du rendu. - Correction pérenne : supprimer un des deux doublons depuis le backoffice (section "Doublons" de la page Publications).