From a84631b28e04ab70a16655a1cc85b683f436f3ce Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau Date: Thu, 10 Oct 2024 14:22:47 +0200 Subject: [PATCH] =?UTF-8?q?Ajout=20d'une=20gestion=20manuelle=20des=20mess?= =?UTF-8?q?ages=20ind=C3=A9sirables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../locale/fr/LC_MESSAGES/django.po | 314 ++++++++++-------- .../migrations/0079_contactmessage_spam.py | 18 + src/agenda_culturel/models.py | 6 + src/agenda_culturel/static/style.scss | 15 + .../contactmessage_confirm_delete.html | 26 ++ .../contactmessage_moderation_form.html | 5 + .../agenda_culturel/contactmessages.html | 12 +- .../agenda_culturel/delete_spams_confirm.html | 32 ++ src/agenda_culturel/urls.py | 6 + src/agenda_culturel/views.py | 43 ++- 10 files changed, 325 insertions(+), 152 deletions(-) create mode 100644 src/agenda_culturel/migrations/0079_contactmessage_spam.py create mode 100644 src/agenda_culturel/templates/agenda_culturel/contactmessage_confirm_delete.html create mode 100644 src/agenda_culturel/templates/agenda_culturel/delete_spams_confirm.html diff --git a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po index 3db1bba..bac901e 100644 --- a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po +++ b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: agenda_culturel\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-05 18:53+0200\n" +"POT-Creation-Date: 2024-10-10 14:22+0200\n" "PO-Revision-Date: 2023-10-29 14:16+0000\n" "Last-Translator: Jean-Marie Favreau \n" "Language-Team: Jean-Marie Favreau \n" @@ -17,82 +17,82 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: agenda_culturel/calendar.py:149 +#: agenda_culturel/calendar.py:147 msgid "All day today" msgstr "Aujourd'hui toute la journée" -#: agenda_culturel/calendar.py:150 +#: agenda_culturel/calendar.py:148 msgid "This morning" msgstr "Ce matin" -#: agenda_culturel/calendar.py:150 +#: agenda_culturel/calendar.py:148 msgid "This noon" msgstr "Ce midi" -#: agenda_culturel/calendar.py:150 +#: agenda_culturel/calendar.py:148 msgid "This afternoon" msgstr "Cet après-midi" -#: agenda_culturel/calendar.py:150 +#: agenda_culturel/calendar.py:148 msgid "This evening" msgstr "Ce soir" -#: agenda_culturel/calendar.py:152 +#: agenda_culturel/calendar.py:150 msgid "Tomorrow" msgstr "Demain" -#: agenda_culturel/calendar.py:153 +#: agenda_culturel/calendar.py:151 msgid "All day tomorrow" msgstr "Toute la journée de demain" -#: agenda_culturel/calendar.py:154 agenda_culturel/calendar.py:158 +#: agenda_culturel/calendar.py:152 agenda_culturel/calendar.py:156 #, python-format msgid "%s morning" msgstr "%s matin" -#: agenda_culturel/calendar.py:154 agenda_culturel/calendar.py:158 +#: agenda_culturel/calendar.py:152 agenda_culturel/calendar.py:156 #, python-format msgid "%s noon" msgstr "%s midi" -#: agenda_culturel/calendar.py:154 agenda_culturel/calendar.py:158 +#: agenda_culturel/calendar.py:152 agenda_culturel/calendar.py:156 #, python-format msgid "%s afternoon" msgstr "%s après-midi" -#: agenda_culturel/calendar.py:154 agenda_culturel/calendar.py:158 +#: agenda_culturel/calendar.py:152 agenda_culturel/calendar.py:156 #, python-format msgid "%s evening" msgstr "%s soir" -#: agenda_culturel/calendar.py:157 +#: agenda_culturel/calendar.py:155 #, python-format msgid "All day %s" msgstr "Toute la journée de %s" -#: agenda_culturel/calendar.py:159 +#: agenda_culturel/calendar.py:157 msgid "All day" msgstr "Toute la journée" -#: agenda_culturel/calendar.py:160 +#: agenda_culturel/calendar.py:158 msgid "Morning" msgstr "Matin" -#: agenda_culturel/calendar.py:160 +#: agenda_culturel/calendar.py:158 msgid "Noon" msgstr "Midi" -#: agenda_culturel/calendar.py:160 +#: agenda_culturel/calendar.py:158 msgid "Afternoon" msgstr "Après-midi" -#: agenda_culturel/calendar.py:160 +#: agenda_culturel/calendar.py:158 msgid "Evening" msgstr "Soir" #: agenda_culturel/forms.py:44 agenda_culturel/models.py:168 -#: agenda_culturel/models.py:336 agenda_culturel/models.py:1341 -#: agenda_culturel/models.py:1441 +#: agenda_culturel/models.py:336 agenda_culturel/models.py:1347 +#: agenda_culturel/models.py:1447 msgid "Category" msgstr "Catégorie" @@ -122,7 +122,7 @@ msgid "Apply category {} to the event {}" msgstr "Appliquer la catégorie {} à l'événement {}" #: agenda_culturel/forms.py:418 agenda_culturel/models.py:260 -#: agenda_culturel/models.py:1493 +#: agenda_culturel/models.py:1499 msgid "Place" msgstr "Lieu" @@ -142,7 +142,7 @@ msgstr "" #: agenda_culturel/models.py:47 agenda_culturel/models.py:92 #: agenda_culturel/models.py:239 agenda_culturel/models.py:1220 -#: agenda_culturel/models.py:1287 +#: agenda_culturel/models.py:1293 msgid "Name" msgstr "Nom" @@ -256,7 +256,7 @@ msgstr "" msgid "Places" msgstr "Lieux" -#: agenda_culturel/models.py:314 agenda_culturel/models.py:1328 +#: agenda_culturel/models.py:314 agenda_culturel/models.py:1334 msgid "Published" msgstr "Publié" @@ -276,7 +276,7 @@ msgstr "Titre" msgid "Short title" msgstr "Titre court" -#: agenda_culturel/models.py:331 agenda_culturel/models.py:1409 +#: agenda_culturel/models.py:331 agenda_culturel/models.py:1415 msgid "Status" msgstr "Status" @@ -310,7 +310,7 @@ msgstr "Heure de fin" msgid "Recurrence" msgstr "Récurrence" -#: agenda_culturel/models.py:371 agenda_culturel/models.py:1333 +#: agenda_culturel/models.py:371 agenda_culturel/models.py:1339 msgid "Location" msgstr "Localisation" @@ -442,93 +442,101 @@ msgstr "Message" msgid "Your message" msgstr "Votre message" -#: agenda_culturel/models.py:1238 agenda_culturel/views.py:895 +#: agenda_culturel/models.py:1238 agenda_culturel/views.py:883 +msgid "Spam" +msgstr "Spam" + +#: agenda_culturel/models.py:1239 +msgid "This message is a spam." +msgstr "Ce message est un spam." + +#: agenda_culturel/models.py:1244 agenda_culturel/views.py:878 msgid "Closed" msgstr "Fermé" -#: agenda_culturel/models.py:1240 +#: agenda_culturel/models.py:1246 msgid "this message has been processed and no longer needs to be handled" msgstr "Ce message a été traité et ne nécessite plus d'être pris en charge" -#: agenda_culturel/models.py:1245 +#: agenda_culturel/models.py:1251 msgid "Comments" msgstr "Commentaires" -#: agenda_culturel/models.py:1246 +#: agenda_culturel/models.py:1252 msgid "Comments on the message from the moderation team" msgstr "Commentaires sur ce message par l'équipe de modération" -#: agenda_culturel/models.py:1258 agenda_culturel/models.py:1389 +#: agenda_culturel/models.py:1264 agenda_culturel/models.py:1395 msgid "Recurrent import" msgstr "Import récurrent" -#: agenda_culturel/models.py:1259 +#: agenda_culturel/models.py:1265 msgid "Recurrent imports" msgstr "Imports récurrents" -#: agenda_culturel/models.py:1263 +#: agenda_culturel/models.py:1269 msgid "ical" msgstr "ical" -#: agenda_culturel/models.py:1264 +#: agenda_culturel/models.py:1270 msgid "ical no busy" msgstr "ical sans busy" -#: agenda_culturel/models.py:1265 +#: agenda_culturel/models.py:1271 msgid "ical no VC" msgstr "ical sans VC" -#: agenda_culturel/models.py:1266 +#: agenda_culturel/models.py:1272 msgid "lacoope.org" msgstr "lacoope.org" -#: agenda_culturel/models.py:1267 +#: agenda_culturel/models.py:1273 msgid "la comédie" msgstr "la comédie" -#: agenda_culturel/models.py:1268 +#: agenda_culturel/models.py:1274 msgid "le fotomat" msgstr "le fotomat" -#: agenda_culturel/models.py:1269 +#: agenda_culturel/models.py:1275 #, fuzzy #| msgid "la puce à loreille" msgid "la puce à l'oreille" msgstr "la puce à loreille" -#: agenda_culturel/models.py:1270 +#: agenda_culturel/models.py:1276 msgid "Plugin wordpress MEC" msgstr "Plugin wordpress MEC" -#: agenda_culturel/models.py:1271 +#: agenda_culturel/models.py:1277 msgid "Événements d'une page" msgstr "Événements d'une page" -#: agenda_culturel/models.py:1272 +#: agenda_culturel/models.py:1278 msgid "la cour des 3 coquins" msgstr "la cour des 3 coquins" -#: agenda_culturel/models.py:1275 +#: agenda_culturel/models.py:1281 msgid "simple" msgstr "simple" -#: agenda_culturel/models.py:1276 +#: agenda_culturel/models.py:1282 msgid "Headless Chromium" msgstr "chromium sans interface" -#: agenda_culturel/models.py:1277 +#: agenda_culturel/models.py:1283 msgid "Headless Chromium (pause)" msgstr "chromium sans interface (pause)" -#: agenda_culturel/models.py:1282 +#: agenda_culturel/models.py:1288 msgid "daily" msgstr "chaque jour" -#: agenda_culturel/models.py:1284 +#: agenda_culturel/models.py:1290 msgid "weekly" msgstr "chaque semaine" -#: agenda_culturel/models.py:1289 +#: agenda_culturel/models.py:1295 msgid "" "Recurrent import name. Be careful to choose a name that is easy to " "understand, as it will be public and displayed on the sites About page." @@ -536,135 +544,135 @@ msgstr "" "Nom de l'import récurrent. Attention à choisir un nom compréhensible, car il " "sera public, et affiché sur la page à propos du site." -#: agenda_culturel/models.py:1296 +#: agenda_culturel/models.py:1302 msgid "Processor" msgstr "Processeur" -#: agenda_culturel/models.py:1299 +#: agenda_culturel/models.py:1305 msgid "Downloader" msgstr "Téléchargeur" -#: agenda_culturel/models.py:1306 +#: agenda_culturel/models.py:1312 msgid "Import recurrence" msgstr "Récurrence d'import" -#: agenda_culturel/models.py:1313 +#: agenda_culturel/models.py:1319 msgid "Source" msgstr "Source" -#: agenda_culturel/models.py:1314 +#: agenda_culturel/models.py:1320 msgid "URL of the source document" msgstr "URL du document source" -#: agenda_culturel/models.py:1318 +#: agenda_culturel/models.py:1324 msgid "Browsable url" msgstr "URL navigable" -#: agenda_culturel/models.py:1320 +#: agenda_culturel/models.py:1326 msgid "URL of the corresponding document that will be shown to visitors." msgstr "URL correspondant au document et qui sera montrée aux visiteurs" -#: agenda_culturel/models.py:1329 +#: agenda_culturel/models.py:1335 msgid "Status of each imported event (published or draft)" msgstr "Status de chaque événement importé (publié ou brouillon)" -#: agenda_culturel/models.py:1334 +#: agenda_culturel/models.py:1340 msgid "Address for each imported event" msgstr "Adresse de chaque événement importé" -#: agenda_culturel/models.py:1342 +#: agenda_culturel/models.py:1348 msgid "Category of each imported event" msgstr "Catégorie de chaque événement importé" -#: agenda_culturel/models.py:1348 +#: agenda_culturel/models.py:1354 msgid "Tags for each imported event" msgstr "Étiquettes de chaque événement importé" -#: agenda_culturel/models.py:1349 +#: agenda_culturel/models.py:1355 msgid "A list of tags that describe each imported event." msgstr "Une liste d'étiquettes décrivant chaque événement importé" -#: agenda_culturel/models.py:1375 +#: agenda_culturel/models.py:1381 msgid "Running" msgstr "En cours" -#: agenda_culturel/models.py:1376 +#: agenda_culturel/models.py:1382 msgid "Canceled" msgstr "Annulé" -#: agenda_culturel/models.py:1377 +#: agenda_culturel/models.py:1383 msgid "Success" msgstr "Succès" -#: agenda_culturel/models.py:1378 +#: agenda_culturel/models.py:1384 msgid "Failed" msgstr "Erreur" -#: agenda_culturel/models.py:1381 +#: agenda_culturel/models.py:1387 msgid "Batch importation" msgstr "Importation par lot" -#: agenda_culturel/models.py:1382 +#: agenda_culturel/models.py:1388 msgid "Batch importations" msgstr "Importations par lot" -#: agenda_culturel/models.py:1390 +#: agenda_culturel/models.py:1396 msgid "Reference to the recurrent import processing" msgstr "Référence du processus d'import récurrent" -#: agenda_culturel/models.py:1398 +#: agenda_culturel/models.py:1404 msgid "URL (if not recurrent import)" msgstr "URL (si pas d'import récurrent)" -#: agenda_culturel/models.py:1400 +#: agenda_culturel/models.py:1406 msgid "Source URL if no RecurrentImport is associated." msgstr "URL source si aucun import récurrent n'est associé" -#: agenda_culturel/models.py:1413 +#: agenda_culturel/models.py:1419 msgid "Error message" msgstr "Votre message" -#: agenda_culturel/models.py:1417 +#: agenda_culturel/models.py:1423 msgid "Number of collected events" msgstr "Nombre d'événements collectés" -#: agenda_culturel/models.py:1420 +#: agenda_culturel/models.py:1426 msgid "Number of imported events" msgstr "Nombre d'événements importés" -#: agenda_culturel/models.py:1423 +#: agenda_culturel/models.py:1429 msgid "Number of updated events" msgstr "Nombre d'événements mis à jour" -#: agenda_culturel/models.py:1426 +#: agenda_culturel/models.py:1432 msgid "Number of removed events" msgstr "Nombre d'événements supprimés" -#: agenda_culturel/models.py:1434 +#: agenda_culturel/models.py:1440 msgid "Weight" msgstr "Poids" -#: agenda_culturel/models.py:1435 +#: agenda_culturel/models.py:1441 msgid "The lower is the weight, the earlier the filter is applied" msgstr "Plus le poids est léger, plus le filtre sera appliqué tôt" -#: agenda_culturel/models.py:1442 +#: agenda_culturel/models.py:1448 msgid "Category applied to the event" msgstr "Catégorie appliquée à l'événement" -#: agenda_culturel/models.py:1447 +#: agenda_culturel/models.py:1453 msgid "Contained in the title" msgstr "Contenu dans le titre" -#: agenda_culturel/models.py:1448 +#: agenda_culturel/models.py:1454 msgid "Text contained in the event title" msgstr "Texte contenu dans le titre de l'événement" -#: agenda_culturel/models.py:1454 +#: agenda_culturel/models.py:1460 msgid "Exact title extract" msgstr "Extrait exact du titre" -#: agenda_culturel/models.py:1456 +#: agenda_culturel/models.py:1462 msgid "" "If checked, the extract will be searched for in the title using the exact " "form (capitals, accents)." @@ -672,19 +680,19 @@ msgstr "" "Si coché, l'extrait sera recherché dans le titre en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:1462 +#: agenda_culturel/models.py:1468 msgid "Contained in the description" msgstr "Contenu dans la description" -#: agenda_culturel/models.py:1463 +#: agenda_culturel/models.py:1469 msgid "Text contained in the description" msgstr "Texte contenu dans la description" -#: agenda_culturel/models.py:1469 +#: agenda_culturel/models.py:1475 msgid "Exact description extract" msgstr "Extrait exact de description" -#: agenda_culturel/models.py:1471 +#: agenda_culturel/models.py:1477 msgid "" "If checked, the extract will be searched for in the description using the " "exact form (capitals, accents)." @@ -692,19 +700,19 @@ msgstr "" "Si coché, l'extrait sera recherché dans la description en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:1477 +#: agenda_culturel/models.py:1483 msgid "Contained in the location" msgstr "Contenu dans la localisation" -#: agenda_culturel/models.py:1478 +#: agenda_culturel/models.py:1484 msgid "Text contained in the event location" msgstr "Texte contenu dans la localisation de l'événement" -#: agenda_culturel/models.py:1484 +#: agenda_culturel/models.py:1490 msgid "Exact location extract" msgstr "Extrait exact de localisation" -#: agenda_culturel/models.py:1486 +#: agenda_culturel/models.py:1492 msgid "" "If checked, the extract will be searched for in the location using the exact " "form (capitals, accents)." @@ -712,56 +720,56 @@ msgstr "" "Si coché, l'extrait sera recherché dans la localisation en utilisant la " "forme exacte (majuscules, accents)" -#: agenda_culturel/models.py:1494 +#: agenda_culturel/models.py:1500 msgid "Location from place" msgstr "Localisation depuis le lieu" -#: agenda_culturel/models.py:1501 +#: agenda_culturel/models.py:1507 msgid "Categorisation rule" msgstr "Règle de catégorisation" -#: agenda_culturel/models.py:1502 +#: agenda_culturel/models.py:1508 msgid "Categorisation rules" msgstr "Règles de catégorisation" -#: agenda_culturel/models.py:1569 agenda_culturel/models.py:1601 +#: agenda_culturel/models.py:1575 agenda_culturel/models.py:1607 msgid "Question" msgstr "Question" -#: agenda_culturel/models.py:1570 agenda_culturel/models.py:1608 +#: agenda_culturel/models.py:1576 agenda_culturel/models.py:1614 msgid "Text that will be shown to moderators" msgstr "Text tel que présenté aux modérateurices" -#: agenda_culturel/models.py:1576 +#: agenda_culturel/models.py:1582 msgid "Moderation question" msgstr "Question de modération" -#: agenda_culturel/models.py:1577 +#: agenda_culturel/models.py:1583 msgid "Moderation questions" msgstr "Questions de modération" -#: agenda_culturel/models.py:1602 +#: agenda_culturel/models.py:1608 msgid "Associated question from moderation" msgstr "Question associée pour la modération" -#: agenda_culturel/models.py:1607 +#: agenda_culturel/models.py:1613 msgid "Answer" msgstr "Réponse" -#: agenda_culturel/models.py:1614 +#: agenda_culturel/models.py:1620 msgid "Adds tags" msgstr "Ajoute les étiquettes" -#: agenda_culturel/models.py:1615 +#: agenda_culturel/models.py:1621 msgid "A list of tags that will be added if you choose this answer." msgstr "" "Une liste d'étiquettes qui seront ajoutées si vous choisissez cette réponse." -#: agenda_culturel/models.py:1621 +#: agenda_culturel/models.py:1627 msgid "Removes tags" msgstr "Retire les étiquettes" -#: agenda_culturel/models.py:1622 +#: agenda_culturel/models.py:1628 msgid "A list of tags that will be removed if you choose this answer." msgstr "" "Une liste d'étiquettes qui seront retirées si vous choisissez cette réponse." @@ -790,15 +798,15 @@ msgstr "Naviguer..." msgid "No file selected." msgstr "Pas de fichier sélectionné." -#: agenda_culturel/views.py:529 +#: agenda_culturel/views.py:505 msgid "The static content has been successfully updated." msgstr "Le contenu statique a été modifié avec succès." -#: agenda_culturel/views.py:538 agenda_culturel/views.py:586 +#: agenda_culturel/views.py:514 agenda_culturel/views.py:562 msgid "The event has been successfully modified." msgstr "L'événement a été modifié avec succès." -#: agenda_culturel/views.py:543 +#: agenda_culturel/views.py:519 msgid "" "Please note that this event has not been modified since it was last updated " "by import. If you modify any information from this import, the event will be " @@ -810,15 +818,15 @@ msgstr "" "l'événement sera désynchronisé d'avec la source, et nécessitera une fusion à " "chaque import automatique futurs." -#: agenda_culturel/views.py:555 +#: agenda_culturel/views.py:531 msgid "The event has been successfully deleted." msgstr "L'événement a été supprimé avec succès" -#: agenda_culturel/views.py:611 +#: agenda_culturel/views.py:587 msgid "The status has been successfully modified." msgstr "Le status a été modifié avec succès." -#: agenda_culturel/views.py:633 agenda_culturel/views.py:648 +#: agenda_culturel/views.py:609 agenda_culturel/views.py:624 msgid "" "The event has been submitted and will be published as soon as it has been " "validated by the moderation team." @@ -826,77 +834,91 @@ msgstr "" "L'événement a été soumis et sera publié dès qu'il aura été validé par " "l'équipe de modération." -#: agenda_culturel/views.py:642 +#: agenda_culturel/views.py:618 msgid "The event is saved." msgstr "L'événement est enregistré." -#: agenda_culturel/views.py:734 agenda_culturel/views.py:786 +#: agenda_culturel/views.py:710 agenda_culturel/views.py:762 msgid "{} has not been submitted since its already known: {}." msgstr "{} n'a pas été soumis car il est déjà connu: {}." -#: agenda_culturel/views.py:739 agenda_culturel/views.py:792 +#: agenda_culturel/views.py:715 agenda_culturel/views.py:768 msgid "" "{} has not been submitted since its already known and currently into " "moderation process." msgstr "{} n'a pas été soumis car il est déjà connu et en cours de modération" -#: agenda_culturel/views.py:749 +#: agenda_culturel/views.py:725 msgid "Integrating {} url(s) into our import process." msgstr "Intégration de {} url(s) dans notre processus d'import." -#: agenda_culturel/views.py:799 +#: agenda_culturel/views.py:775 msgid "Integrating {} into our import process." msgstr "Intégration de {} dans notre processus d'import." -#: agenda_culturel/views.py:862 +#: agenda_culturel/views.py:838 msgid "Your message has been sent successfully." msgstr "Votre message a été envoyé avec succès." -#: agenda_culturel/views.py:879 +#: agenda_culturel/views.py:848 +msgid "The contact message has been successfully deleted." +msgstr "Le message de contact a été supprimé avec succès." + +#: agenda_culturel/views.py:862 msgid "The contact message properties has been successfully modified." msgstr "Les propriétés du message de contact ont été modifié avec succès." -#: agenda_culturel/views.py:895 +#: agenda_culturel/views.py:878 msgid "Open" msgstr "Ouvert" -#: agenda_culturel/views.py:952 +#: agenda_culturel/views.py:883 +msgid "Non spam" +msgstr "Non spam" + +#: agenda_culturel/views.py:946 +#, fuzzy +#| msgid "The event has been successfully deleted." +msgid "Spam has been successfully deleted." +msgstr "L'événement a été supprimé avec succès" + +#: agenda_culturel/views.py:963 msgid "Search" msgstr "Rechercher" -#: agenda_culturel/views.py:1138 +#: agenda_culturel/views.py:1149 msgid "The import has been run successfully." msgstr "L'import a été lancé avec succès" -#: agenda_culturel/views.py:1157 +#: agenda_culturel/views.py:1168 msgid "The import has been canceled." msgstr "L'import a été annulé" -#: agenda_culturel/views.py:1231 +#: agenda_culturel/views.py:1242 msgid "The recurrent import has been successfully modified." msgstr "L'import récurrent a été modifié avec succès." -#: agenda_culturel/views.py:1240 +#: agenda_culturel/views.py:1251 msgid "The recurrent import has been successfully deleted." msgstr "L'import récurrent a été supprimé avec succès" -#: agenda_culturel/views.py:1280 +#: agenda_culturel/views.py:1291 msgid "The import has been launched." msgstr "L'import a été lancé" -#: agenda_culturel/views.py:1302 +#: agenda_culturel/views.py:1313 msgid "Imports has been launched." msgstr "Les imports ont été lancés" -#: agenda_culturel/views.py:1387 +#: agenda_culturel/views.py:1398 msgid "The merge has been successfully completed." msgstr "La fusion a été réalisée avec succès." -#: agenda_culturel/views.py:1421 +#: agenda_culturel/views.py:1432 msgid "Events have been marked as unduplicated." msgstr "Les événements ont été marqués comme non dupliqués." -#: agenda_culturel/views.py:1443 +#: agenda_culturel/views.py:1454 msgid "" "The selected event has been retained, while the other has been moved to the " "recycle bin." @@ -904,7 +926,7 @@ msgstr "" "L'événement sélectionné a été conservé, l'autre a été déplacé dans la " "corbeille." -#: agenda_culturel/views.py:1450 +#: agenda_culturel/views.py:1461 msgid "" "The selected event has been retained, while the others have been moved to " "the recycle bin." @@ -912,19 +934,19 @@ msgstr "" "L'événement sélectionné a été conservé, les autres ont été déplacés dans la " "corbeille." -#: agenda_culturel/views.py:1461 +#: agenda_culturel/views.py:1472 msgid "The event has been withdrawn from the group and made independent." msgstr "L'événement a été retiré du groupe et rendu indépendant." -#: agenda_culturel/views.py:1494 +#: agenda_culturel/views.py:1505 msgid "Cleaning up duplicates: {} item(s) removed." msgstr "Nettoyage des dupliqués: {} élément(s) supprimés." -#: agenda_culturel/views.py:1538 +#: agenda_culturel/views.py:1549 msgid "The event was successfully duplicated." msgstr "L'événement a été marqué dupliqué avec succès." -#: agenda_culturel/views.py:1546 +#: agenda_culturel/views.py:1557 msgid "" "The event has been successfully flagged as a duplicate. The moderation team " "will deal with your suggestion shortly." @@ -932,63 +954,63 @@ msgstr "" "L'événement a été signalé comme dupliqué avec succès. Votre suggestion sera " "prochainement prise en charge par l'équipe de modération." -#: agenda_culturel/views.py:1599 +#: agenda_culturel/views.py:1610 msgid "The categorisation rule has been successfully modified." msgstr "La règle de catégorisation a été modifiée avec succès." -#: agenda_culturel/views.py:1608 +#: agenda_culturel/views.py:1619 msgid "The categorisation rule has been successfully deleted." msgstr "La règle de catégorisation a été supprimée avec succès" -#: agenda_culturel/views.py:1630 agenda_culturel/views.py:1677 +#: agenda_culturel/views.py:1641 agenda_culturel/views.py:1688 msgid "The rules were successfully applied and 1 event was categorised." msgstr "" "Les règles ont été appliquées avec succès et 1 événement a été catégorisé" -#: agenda_culturel/views.py:1637 agenda_culturel/views.py:1684 +#: agenda_culturel/views.py:1648 agenda_culturel/views.py:1695 msgid "The rules were successfully applied and {} events were categorised." msgstr "" "Les règles ont été appliquées avec succès et {} événements ont été " "catégorisés" -#: agenda_culturel/views.py:1644 agenda_culturel/views.py:1691 +#: agenda_culturel/views.py:1655 agenda_culturel/views.py:1702 msgid "The rules were successfully applied and no events were categorised." msgstr "" "Les règles ont été appliquées avec succès et aucun événement n'a été " "catégorisé" -#: agenda_culturel/views.py:1731 +#: agenda_culturel/views.py:1742 msgid "The moderation question has been created with success." msgstr "La question de modération a été créée avec succès." -#: agenda_culturel/views.py:1857 agenda_culturel/views.py:1919 -#: agenda_culturel/views.py:1957 +#: agenda_culturel/views.py:1868 agenda_culturel/views.py:1930 +#: agenda_culturel/views.py:1968 msgid "{} events have been updated." msgstr "{} événements ont été mis à jour." -#: agenda_culturel/views.py:1860 agenda_culturel/views.py:1921 -#: agenda_culturel/views.py:1960 +#: agenda_culturel/views.py:1871 agenda_culturel/views.py:1932 +#: agenda_culturel/views.py:1971 msgid "1 event has been updated." msgstr "1 événement a été mis à jour" -#: agenda_culturel/views.py:1862 agenda_culturel/views.py:1923 -#: agenda_culturel/views.py:1962 +#: agenda_culturel/views.py:1873 agenda_culturel/views.py:1934 +#: agenda_culturel/views.py:1973 msgid "No events have been modified." msgstr "Aucun événement n'a été modifié." -#: agenda_culturel/views.py:1871 +#: agenda_culturel/views.py:1882 msgid "The place has been successfully updated." msgstr "Le lieu a été modifié avec succès." -#: agenda_culturel/views.py:1880 +#: agenda_culturel/views.py:1891 msgid "The place has been successfully created." msgstr "Le lieu a été créé avec succès." -#: agenda_culturel/views.py:1945 +#: agenda_culturel/views.py:1956 msgid "The selected place has been assigned to the event." msgstr "Le lieu sélectionné a été assigné à l'événement." -#: agenda_culturel/views.py:1949 +#: agenda_culturel/views.py:1960 msgid "A new alias has been added to the selected place." msgstr "Un nouvel alias a été créé pour le lieu sélectionné." diff --git a/src/agenda_culturel/migrations/0079_contactmessage_spam.py b/src/agenda_culturel/migrations/0079_contactmessage_spam.py new file mode 100644 index 0000000..9e566f2 --- /dev/null +++ b/src/agenda_culturel/migrations/0079_contactmessage_spam.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.9 on 2024-10-09 16:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('agenda_culturel', '0078_alter_event_category_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='contactmessage', + name='spam', + field=models.BooleanField(default=False, help_text='This message is a spam.', verbose_name='Spam'), + ), + ] diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py index 042871f..34a2e77 100644 --- a/src/agenda_culturel/models.py +++ b/src/agenda_culturel/models.py @@ -1234,6 +1234,12 @@ class ContactMessage(models.Model): date = models.DateTimeField(auto_now_add=True) + spam = models.BooleanField( + verbose_name=_("Spam"), + help_text=_("This message is a spam."), + default=False, + ) + closed = models.BooleanField( verbose_name=_("Closed"), help_text=_( diff --git a/src/agenda_culturel/static/style.scss b/src/agenda_culturel/static/style.scss index d7ec869..ce218a8 100644 --- a/src/agenda_culturel/static/style.scss +++ b/src/agenda_culturel/static/style.scss @@ -1234,4 +1234,19 @@ article { } } } +} + +form.messages div { + fieldset { + float: left; + margin-right: 1em; + } + label { + clear: both; + float: left; + } + div { + display: inline-block; + margin-right: 1em; + } } \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/contactmessage_confirm_delete.html b/src/agenda_culturel/templates/agenda_culturel/contactmessage_confirm_delete.html new file mode 100644 index 0000000..39ad54c --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/contactmessage_confirm_delete.html @@ -0,0 +1,26 @@ +{% extends "agenda_culturel/page.html" %} + +{% block title %}{% block og_title %}Supprimer {{ object.subject }}{% endblock %}{% endblock %} + +{% block fluid %}{% endblock %} + +{% block content %} + +
+
+

Suppression du message {{ object.subject }}

+
+
{% csrf_token %} +

Êtes-vous sûr·e de vouloir supprimer le message « {{ object.subject }} » de {{ object.name }} ({{ object.id }}) ?

+ {{ form }} + + +
+
+ +{% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/contactmessage_moderation_form.html b/src/agenda_culturel/templates/agenda_culturel/contactmessage_moderation_form.html index 72ee47e..280a554 100644 --- a/src/agenda_culturel/templates/agenda_culturel/contactmessage_moderation_form.html +++ b/src/agenda_culturel/templates/agenda_culturel/contactmessage_moderation_form.html @@ -1,5 +1,6 @@ {% extends "agenda_culturel/page.html" %} {% load static %} +{% load utils_extra %} {% block title %}{% block og_title %}Message de contact : {{ obj.subject }}{% endblock %}{% endblock %} @@ -18,6 +19,10 @@
+ +

Modération du message « {{ object.subject }} »

  • Date : {{ object.date }}
  • diff --git a/src/agenda_culturel/templates/agenda_culturel/contactmessages.html b/src/agenda_culturel/templates/agenda_culturel/contactmessages.html index 5e1ae2c..945e7c1 100644 --- a/src/agenda_culturel/templates/agenda_culturel/contactmessages.html +++ b/src/agenda_culturel/templates/agenda_culturel/contactmessages.html @@ -12,9 +12,15 @@
    + {% if nb_spams > 0 %} + + {% endif %} +

    Derniers messages de contact reçus

    -
    - {{ filter.form }}
    + + {{ filter.form.as_div }}

    @@ -25,6 +31,7 @@ Sujet Auteur Fermé + Spam @@ -34,6 +41,7 @@ {{ obj.subject }} {{ obj.name }} {% if obj.closed %}{% picto_from_name "check-square" "fermé" %}{% else %}{% picto_from_name "square" "ouvert" %}{% endif %} + {% if obj.spam %}{% picto_from_name "check-square" "spam" %}{% else %}{% picto_from_name "square" "non spam" %}{% endif %} {% endfor %} diff --git a/src/agenda_culturel/templates/agenda_culturel/delete_spams_confirm.html b/src/agenda_culturel/templates/agenda_culturel/delete_spams_confirm.html new file mode 100644 index 0000000..1ba9090 --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/delete_spams_confirm.html @@ -0,0 +1,32 @@ +{% extends "agenda_culturel/page.html" %} + + +{% block fluid %}{% endblock %} + +{% block content %} + +
    +
    +

    {% block title %}{% block og_title %}Suppressions des spams{% endblock %}{% endblock %}

    +
    + {% csrf_token %} +

    Êtes-vous sûr·e de vouloir supprimer + {% if nb_spams > 1 %} + les {{ nb_spams }} messages + {% else %} + le message + {% endif %} de contact annoté{{ nb_spams|pluralize }} comme spam ? + Cette suppression sera définitive. +

    + {{ form }} + + + +
    + +{% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/urls.py b/src/agenda_culturel/urls.py index bf8468a..6824c23 100644 --- a/src/agenda_culturel/urls.py +++ b/src/agenda_culturel/urls.py @@ -63,11 +63,17 @@ urlpatterns = [ path("merci", thank_you, name="thank_you"), path("contact", ContactMessageCreateView.as_view(), name="contact"), path("contactmessages", contactmessages, name="contactmessages"), + path("contactmessages/spams/delete", delete_cm_spam, name="delete_cm_spam"), path( "contactmessage/", ContactMessageUpdateView.as_view(), name="contactmessage", ), + path( + "contactmessage//delete", + ContactMessageDeleteView.as_view(), + name="delete_contactmessage", + ), path("imports/", imports, name="imports"), path("imports/add", add_import, name="add_import"), path("imports//cancel", cancel_import, name="cancel_import"), diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py index 279328e..a354a47 100644 --- a/src/agenda_culturel/views.py +++ b/src/agenda_culturel/views.py @@ -53,7 +53,7 @@ from django.utils import timezone from django.utils.html import escape from datetime import date, timedelta from django.utils.timezone import datetime -from django.db.models import Q, Subquery, OuterRef +from django.db.models import Q, Subquery, OuterRef, Count from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ @@ -842,6 +842,13 @@ class ContactMessageCreateView(SuccessMessageMixin, CreateView): form_class = self.get_form_class() return form_class(**self.get_form_kwargs()) +class ContactMessageDeleteView(SuccessMessageMixin, DeleteView): + model = ContactMessage + success_message = _( + "The contact message has been successfully deleted." + ) + success_url = reverse_lazy("contactmessages") + class ContactMessageUpdateView( SuccessMessageMixin, PermissionRequiredMixin, LoginRequiredMixin, UpdateView @@ -849,7 +856,7 @@ class ContactMessageUpdateView( model = ContactMessage permission_required = "agenda_culturel.change_contactmessage" template_name = "agenda_culturel/contactmessage_moderation_form.html" - fields = ("closed", "comments") + fields = ("spam", "closed", "comments") success_message = _( "The contact message properties has been successfully modified." @@ -871,10 +878,15 @@ class ContactMessagesFilterAdmin(django_filters.FilterSet): choices=((True, _("Closed")), (False, _("Open"))), widget=forms.CheckboxSelectMultiple, ) + spam = django_filters.MultipleChoiceFilter( + label="Spam", + choices=((True, _("Spam")), (False, _("Non spam"))), + widget=forms.CheckboxSelectMultiple, + ) class Meta: model = ContactMessage - fields = ["closed"] + fields = ["closed", "spam"] @login_required(login_url="/accounts/login/") @@ -909,6 +921,8 @@ def contactmessages(request): paginator = PaginatorFilter(filter, 10, request) page = request.GET.get("page") + nb_spams = ContactMessage.objects.filter(spam=True).count() + try: response = paginator.page(page) except PageNotAnInteger: @@ -919,9 +933,30 @@ def contactmessages(request): return render( request, "agenda_culturel/contactmessages.html", - {"filter": filter, "paginator_filter": response}, + {"filter": filter, "nb_spams": nb_spams, "paginator_filter": response}, ) +@login_required(login_url="/accounts/login/") +@permission_required("agenda_culturel.view_contactmessage") +def delete_cm_spam(request): + + if request.method == "POST": + ContactMessage.objects.filter(spam=True).delete() + + messages.success(request, _("Spam has been successfully deleted.")) + return HttpResponseRedirect(reverse_lazy("contactmessages")) + else: + nb_msgs = ContactMessage.objects.values('spam').annotate(total=Count('spam')) + nb_total = sum([nb["total"] for nb in nb_msgs]) + nb_spams = sum([nb["total"] for nb in nb_msgs if nb["spam"]]) + cancel_url = reverse_lazy("contactmessages") + return render( + request, + "agenda_culturel/delete_spams_confirm.html", + { "nb_total": nb_total, "nb_spams": nb_spams, "cancel_url": cancel_url}, + ) + + class SimpleSearchEventFilter(django_filters.FilterSet): q = django_filters.CharFilter(method="custom_filter",