diff --git a/src/agenda_culturel/admin.py b/src/agenda_culturel/admin.py index c73b08c..c1aa90d 100644 --- a/src/agenda_culturel/admin.py +++ b/src/agenda_culturel/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from django import forms -from .models import Event, Category, StaticContent, DuplicatedEvents, BatchImportation, RecurrentImport +from .models import Event, Category, StaticContent, DuplicatedEvents, BatchImportation, RecurrentImport, Place from django_better_admin_arrayfield.admin.mixins import DynamicArrayMixin from django_better_admin_arrayfield.forms.widgets import DynamicArrayWidget from django_better_admin_arrayfield.models.fields import DynamicArrayField @@ -11,6 +11,7 @@ admin.site.register(StaticContent) admin.site.register(DuplicatedEvents) admin.site.register(BatchImportation) admin.site.register(RecurrentImport) +admin.site.register(Place) class URLWidget(DynamicArrayWidget): diff --git a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po index 8416e27..785f14b 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-04-22 09:16+0000\n" +"POT-Creation-Date: 2024-04-26 14:59+0000\n" "PO-Revision-Date: 2023-10-29 14:16+0000\n" "Last-Translator: Jean-Marie Favreau \n" "Language-Team: Jean-Marie Favreau \n" @@ -39,457 +39,482 @@ msgstr "Catégorie de l'événement" msgid "Cannot extract event from url {}" msgstr "Impossible d'extraire l'événement depuis l'url {}" -#: agenda_culturel/models.py:37 agenda_culturel/models.py:66 -#: agenda_culturel/models.py:735 agenda_culturel/models.py:774 +#: agenda_culturel/models.py:39 agenda_culturel/models.py:68 +#: agenda_culturel/models.py:162 agenda_culturel/models.py:753 +#: agenda_culturel/models.py:792 msgid "Name" msgstr "Nom" -#: agenda_culturel/models.py:37 agenda_culturel/models.py:66 +#: agenda_culturel/models.py:39 agenda_culturel/models.py:68 msgid "Category name" msgstr "Nom de la catégorie" -#: agenda_culturel/models.py:38 +#: agenda_culturel/models.py:40 msgid "Content" msgstr "Contenu" -#: agenda_culturel/models.py:38 +#: agenda_culturel/models.py:40 msgid "Text as shown to the visitors" msgstr "Text tel que présenté aux visiteureuses" -#: agenda_culturel/models.py:39 +#: agenda_culturel/models.py:41 msgid "URL path" msgstr "Chemin URL" -#: agenda_culturel/models.py:39 +#: agenda_culturel/models.py:41 msgid "URL path where the content is included." msgstr "Chemin URL où le contenu est présent." -#: agenda_culturel/models.py:67 +#: agenda_culturel/models.py:69 msgid "Alternative Name" msgstr "Nom alternatif" -#: agenda_culturel/models.py:67 +#: agenda_culturel/models.py:69 msgid "Alternative name used with a time period" msgstr "Nom alternatif utilisé avec une période de temps" -#: agenda_culturel/models.py:68 +#: agenda_culturel/models.py:70 msgid "Short name" msgstr "Nom court" -#: agenda_culturel/models.py:68 +#: agenda_culturel/models.py:70 msgid "Short name of the category" msgstr "Nom court de la catégorie" -#: agenda_culturel/models.py:69 +#: agenda_culturel/models.py:71 msgid "Color" msgstr "Couleur" -#: agenda_culturel/models.py:69 +#: agenda_culturel/models.py:71 msgid "Color used as background for the category" msgstr "Couleur utilisée comme fond de la catégorie" -#: agenda_culturel/models.py:106 agenda_culturel/models.py:174 -#: agenda_culturel/models.py:786 agenda_culturel/models.py:837 +#: agenda_culturel/models.py:115 agenda_culturel/models.py:195 +#: agenda_culturel/models.py:804 agenda_culturel/models.py:855 msgid "Category" msgstr "Catégorie" -#: agenda_culturel/models.py:107 +#: agenda_culturel/models.py:116 msgid "Categories" msgstr "Catégories" -#: agenda_culturel/models.py:158 agenda_culturel/models.py:784 +#: agenda_culturel/models.py:162 +msgid "Name of the place" +msgstr "Nom du lieu" + +#: agenda_culturel/models.py:163 +msgid "Address" +msgstr "Adresse" + +#: agenda_culturel/models.py:163 +msgid "Address of this place" +msgstr "Adresse de ce lieu" + +#: agenda_culturel/models.py:166 +msgid "Alternative names" +msgstr "Noms alternatifs" + +#: agenda_culturel/models.py:166 +msgid "" +"Alternative names or addresses used to match a place with the free-form " +"location of an event." +msgstr "" +"Noms et adresses alternatives qui seront utilisées pour associer une adresse " +"avec la localisation en forme libre d'un événement" + +#: agenda_culturel/models.py:169 +msgid "Place" +msgstr "Lieu" + +#: agenda_culturel/models.py:170 +msgid "Places" +msgstr "Lieux" + +#: agenda_culturel/models.py:179 agenda_culturel/models.py:802 msgid "Published" msgstr "Publié" -#: agenda_culturel/models.py:159 +#: agenda_culturel/models.py:180 msgid "Draft" msgstr "Brouillon" -#: agenda_culturel/models.py:160 +#: agenda_culturel/models.py:181 msgid "Trash" msgstr "Corbeille" -#: agenda_culturel/models.py:170 +#: agenda_culturel/models.py:191 msgid "Title" msgstr "Titre" -#: agenda_culturel/models.py:170 +#: agenda_culturel/models.py:191 msgid "Short title" msgstr "Titre court" -#: agenda_culturel/models.py:172 agenda_culturel/models.py:821 +#: agenda_culturel/models.py:193 agenda_culturel/models.py:839 msgid "Status" msgstr "Status" -#: agenda_culturel/models.py:174 +#: agenda_culturel/models.py:195 msgid "Category of the event" msgstr "Catégorie de l'événement" -#: agenda_culturel/models.py:176 +#: agenda_culturel/models.py:197 msgid "Day of the event" msgstr "Date de l'événement" -#: agenda_culturel/models.py:177 +#: agenda_culturel/models.py:198 msgid "Starting time" msgstr "Heure de début" -#: agenda_culturel/models.py:179 +#: agenda_culturel/models.py:200 msgid "End day of the event" msgstr "Fin de l'événement" -#: agenda_culturel/models.py:179 +#: agenda_culturel/models.py:200 msgid "End day of the event, only required if different from the start day." msgstr "" "Date de fin de l'événement, uniquement nécessaire s'il est différent du " "premier jour de l'événement" -#: agenda_culturel/models.py:180 +#: agenda_culturel/models.py:201 msgid "Final time" msgstr "Heure de fin" -#: agenda_culturel/models.py:182 +#: agenda_culturel/models.py:203 msgid "Recurrence" msgstr "Récurrence" -#: agenda_culturel/models.py:184 agenda_culturel/models.py:785 +#: agenda_culturel/models.py:205 agenda_culturel/models.py:803 msgid "Location" msgstr "Localisation" -#: agenda_culturel/models.py:184 +#: agenda_culturel/models.py:205 msgid "Address of the event" msgstr "Adresse de l'événement" -#: agenda_culturel/models.py:186 +#: agenda_culturel/models.py:206 +msgid "Location (free form)" +msgstr "Localisation (forme libre)" + +#: agenda_culturel/models.py:206 +msgid "" +"Address of the event in case its not available in the already known places " +"(free form)" +msgstr "" +"Addresse d'un événement si elle n'est pas déjà présente dans la liste des " +"lieux disponible (forme libre)" + +#: agenda_culturel/models.py:208 msgid "Description" msgstr "Description" -#: agenda_culturel/models.py:186 +#: agenda_culturel/models.py:208 msgid "General description of the event" msgstr "Description générale de l'événement" -#: agenda_culturel/models.py:188 +#: agenda_culturel/models.py:210 msgid "Illustration (local image)" msgstr "Illustration (image locale)" -#: agenda_culturel/models.py:188 +#: agenda_culturel/models.py:210 msgid "Illustration image stored in the agenda server" msgstr "Image d'illustration stockée sur le serveur de l'agenda" -#: agenda_culturel/models.py:190 +#: agenda_culturel/models.py:212 msgid "Illustration" msgstr "Illustration" -#: agenda_culturel/models.py:190 +#: agenda_culturel/models.py:212 msgid "URL of the illustration image" msgstr "URL de l'image illustrative" -#: agenda_culturel/models.py:191 +#: agenda_culturel/models.py:213 msgid "Illustration description" msgstr "Description de l'illustration" -#: agenda_culturel/models.py:191 +#: agenda_culturel/models.py:213 msgid "Alternative text used by screen readers for the image" msgstr "Texte alternatif utiliser par les lecteurs d'écrans pour l'image" -#: agenda_culturel/models.py:193 +#: agenda_culturel/models.py:215 msgid "Importation source" msgstr "Source d'importation" -#: agenda_culturel/models.py:193 +#: agenda_culturel/models.py:215 msgid "Importation source used to detect removed entries." msgstr "Source d'importation utilisée pour détecter les éléments supprimés/" -#: agenda_culturel/models.py:194 +#: agenda_culturel/models.py:216 msgid "UUIDs" msgstr "UUIDs" -#: agenda_culturel/models.py:194 +#: agenda_culturel/models.py:216 msgid "UUIDs from import to detect duplicated entries." msgstr "UUIDs utilisés pendant l'import pour détecter les entrées dupliquées" -#: agenda_culturel/models.py:195 +#: agenda_culturel/models.py:217 msgid "URLs" msgstr "URLs" -#: agenda_culturel/models.py:195 +#: agenda_culturel/models.py:217 msgid "List of all the urls where this event can be found." msgstr "Liste de toutes les urls où l'événement peut être trouvé." -#: agenda_culturel/models.py:197 +#: agenda_culturel/models.py:219 msgid "Tags" msgstr "Étiquettes" -#: agenda_culturel/models.py:197 +#: agenda_culturel/models.py:219 msgid "A list of tags that describe the event." msgstr "Une liste d'étiquettes décrivant l'événement" -#: agenda_culturel/models.py:199 +#: agenda_culturel/models.py:221 msgid "Possibly duplicated" msgstr "Possibles doublons" -#: agenda_culturel/models.py:240 +#: agenda_culturel/models.py:262 msgid "Event" msgstr "Événement" -#: agenda_culturel/models.py:241 +#: agenda_culturel/models.py:263 msgid "Events" msgstr "Événements" -#: agenda_culturel/models.py:731 +#: agenda_culturel/models.py:749 msgid "Contact message" msgstr "Message de contact" -#: agenda_culturel/models.py:732 +#: agenda_culturel/models.py:750 #, fuzzy #| msgid "Your message" msgid "Contact messages" msgstr "Messages de contact" -#: agenda_culturel/models.py:734 +#: agenda_culturel/models.py:752 msgid "Subject" msgstr "Sujet" -#: agenda_culturel/models.py:734 +#: agenda_culturel/models.py:752 msgid "The subject of your message" msgstr "Sujet de votre message" -#: agenda_culturel/models.py:735 +#: agenda_culturel/models.py:753 msgid "Your name" msgstr "Votre nom" -#: agenda_culturel/models.py:736 +#: agenda_culturel/models.py:754 msgid "Email address" msgstr "Adresse email" -#: agenda_culturel/models.py:736 +#: agenda_culturel/models.py:754 msgid "Your email address" msgstr "Votre adresse email" -#: agenda_culturel/models.py:737 +#: agenda_culturel/models.py:755 msgid "Message" msgstr "Message" -#: agenda_culturel/models.py:737 +#: agenda_culturel/models.py:755 msgid "Your message" msgstr "Votre message" -#: agenda_culturel/models.py:741 agenda_culturel/views.py:437 +#: agenda_culturel/models.py:759 agenda_culturel/views.py:462 msgid "Closed" msgstr "Fermé" -#: agenda_culturel/models.py:741 +#: agenda_culturel/models.py:759 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:742 +#: agenda_culturel/models.py:760 msgid "Comments" msgstr "Commentaires" -#: agenda_culturel/models.py:742 +#: agenda_culturel/models.py:760 msgid "Comments on the message from the moderation team" msgstr "Commentaires sur ce message par l'équipe de modération" -#: agenda_culturel/models.py:752 agenda_culturel/models.py:819 +#: agenda_culturel/models.py:770 agenda_culturel/models.py:837 msgid "Recurrent import" msgstr "Import récurrent" -#: agenda_culturel/models.py:753 +#: agenda_culturel/models.py:771 msgid "Recurrent imports" msgstr "Imports récurrents" -#: agenda_culturel/models.py:757 +#: agenda_culturel/models.py:775 msgid "ical" msgstr "ical" -#: agenda_culturel/models.py:758 +#: agenda_culturel/models.py:776 msgid "ical no busy" msgstr "ical sans busy" -#: agenda_culturel/models.py:759 +#: agenda_culturel/models.py:777 msgid "ical no VC" msgstr "ical sans VC" -#: agenda_culturel/models.py:760 +#: agenda_culturel/models.py:778 msgid "lacoope.org" msgstr "lacoope.org" -#: agenda_culturel/models.py:761 +#: agenda_culturel/models.py:779 msgid "la comédie" msgstr "la comédie" -#: agenda_culturel/models.py:762 +#: agenda_culturel/models.py:780 msgid "le fotomat" msgstr "le fotomat" -#: agenda_culturel/models.py:763 +#: agenda_culturel/models.py:781 msgid "la puce à loreille" msgstr "la puce à loreille" -#: agenda_culturel/models.py:766 +#: agenda_culturel/models.py:784 msgid "simple" msgstr "simple" -#: agenda_culturel/models.py:767 +#: agenda_culturel/models.py:785 msgid "Headless Chromium" msgstr "chromium sans interface" -#: agenda_culturel/models.py:771 +#: agenda_culturel/models.py:789 msgid "daily" msgstr "chaque jour" -#: agenda_culturel/models.py:772 +#: agenda_culturel/models.py:790 msgid "weekly" msgstr "chaque semaine" -#: agenda_culturel/models.py:774 +#: agenda_culturel/models.py:792 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." 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." +"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:775 +#: agenda_culturel/models.py:793 msgid "Processor" msgstr "Processeur" -#: agenda_culturel/models.py:776 +#: agenda_culturel/models.py:794 msgid "Downloader" msgstr "Téléchargeur" -#: agenda_culturel/models.py:778 +#: agenda_culturel/models.py:796 msgid "Import recurrence" msgstr "Récurrence d'import" -#: agenda_culturel/models.py:781 +#: agenda_culturel/models.py:799 msgid "Source" msgstr "Source" -#: agenda_culturel/models.py:781 +#: agenda_culturel/models.py:799 msgid "URL of the source document" msgstr "URL du document source" -#: agenda_culturel/models.py:782 +#: agenda_culturel/models.py:800 msgid "Browsable url" msgstr "URL navigable" -#: agenda_culturel/models.py:782 +#: agenda_culturel/models.py:800 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:784 +#: agenda_culturel/models.py:802 msgid "Status of each imported event (published or draft)" msgstr "Status de chaque événement importé (publié ou brouillon)" -#: agenda_culturel/models.py:785 +#: agenda_culturel/models.py:803 msgid "Address for each imported event" msgstr "Adresse de chaque événement importé" -#: agenda_culturel/models.py:786 +#: agenda_culturel/models.py:804 msgid "Category of each imported event" msgstr "Catégorie de chaque événement importé" -#: agenda_culturel/models.py:787 +#: agenda_culturel/models.py:805 msgid "Tags for each imported event" msgstr "Étiquettes de chaque événement importé" -#: agenda_culturel/models.py:787 +#: agenda_culturel/models.py:805 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:806 +#: agenda_culturel/models.py:824 msgid "Running" msgstr "En cours" -#: agenda_culturel/models.py:807 +#: agenda_culturel/models.py:825 msgid "Canceled" msgstr "Annulé" -#: agenda_culturel/models.py:808 +#: agenda_culturel/models.py:826 msgid "Success" msgstr "Succès" -#: agenda_culturel/models.py:809 +#: agenda_culturel/models.py:827 msgid "Failed" msgstr "Erreur" -#: agenda_culturel/models.py:812 +#: agenda_culturel/models.py:830 msgid "Batch importation" msgstr "Importation par lot" -#: agenda_culturel/models.py:813 +#: agenda_culturel/models.py:831 msgid "Batch importations" msgstr "Importations par lot" -#: agenda_culturel/models.py:819 +#: agenda_culturel/models.py:837 msgid "Reference to the recurrent import processing" msgstr "Référence du processus d'import récurrent" -#: agenda_culturel/models.py:823 +#: agenda_culturel/models.py:841 msgid "Error message" msgstr "Votre message" -#: agenda_culturel/models.py:825 +#: agenda_culturel/models.py:843 msgid "Number of collected events" msgstr "Nombre d'événements collectés" -#: agenda_culturel/models.py:826 +#: agenda_culturel/models.py:844 msgid "Number of imported events" msgstr "Nombre d'événements importés" -#: agenda_culturel/models.py:827 +#: agenda_culturel/models.py:845 msgid "Number of updated events" msgstr "Nombre d'événements mis à jour" -#: agenda_culturel/models.py:828 +#: agenda_culturel/models.py:846 msgid "Number of removed events" msgstr "Nombre d'événements supprimés" -#: agenda_culturel/models.py:835 +#: agenda_culturel/models.py:853 msgid "Weight" msgstr "Poids" -#: agenda_culturel/models.py:835 +#: agenda_culturel/models.py:853 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:837 +#: agenda_culturel/models.py:855 msgid "Category applied to the event" msgstr "Catégorie appliquée à l'événement" -#: agenda_culturel/models.py:839 -msgid "Contained in the description" -msgstr "Contenu dans la description" - -#: agenda_culturel/models.py:839 -msgid "Text contained in the description" -msgstr "Texte contenu dans la description" - -#: agenda_culturel/models.py:840 -msgid "Exact description extract" -msgstr "Extrait exact de description" - -#: agenda_culturel/models.py:840 -msgid "" -"If checked, the extract will be searched for in the description using the " -"exact form (capitals, accents)." -msgstr "" -"Si coché, l'extrait sera recherché dans la description en utilisant la forme " -"exacte (majuscules, accents)" - -#: agenda_culturel/models.py:842 +#: agenda_culturel/models.py:857 msgid "Contained in the title" msgstr "Contenu dans le titre" -#: agenda_culturel/models.py:842 +#: agenda_culturel/models.py:857 msgid "Text contained in the event title" msgstr "Texte contenu dans le titre de l'événement" -#: agenda_culturel/models.py:843 +#: agenda_culturel/models.py:858 msgid "Exact title extract" msgstr "Extrait exact du titre" -#: agenda_culturel/models.py:843 +#: agenda_culturel/models.py:858 msgid "" "If checked, the extract will be searched for in the title using the exact " "form (capitals, accents)." @@ -497,19 +522,39 @@ msgstr "" "Si coché, l'extrait sera recherché dans le titre en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:845 +#: agenda_culturel/models.py:860 +msgid "Contained in the description" +msgstr "Contenu dans la description" + +#: agenda_culturel/models.py:860 +msgid "Text contained in the description" +msgstr "Texte contenu dans la description" + +#: agenda_culturel/models.py:861 +msgid "Exact description extract" +msgstr "Extrait exact de description" + +#: agenda_culturel/models.py:861 +msgid "" +"If checked, the extract will be searched for in the description using the " +"exact form (capitals, accents)." +msgstr "" +"Si coché, l'extrait sera recherché dans la description en utilisant la forme " +"exacte (majuscules, accents)" + +#: agenda_culturel/models.py:863 msgid "Contained in the location" msgstr "Contenu dans la localisation" -#: agenda_culturel/models.py:845 +#: agenda_culturel/models.py:863 msgid "Text contained in the event location" msgstr "Texte contenu dans la localisation de l'événement" -#: agenda_culturel/models.py:846 +#: agenda_culturel/models.py:864 msgid "Exact location extract" msgstr "Extrait exact de localisation" -#: agenda_culturel/models.py:846 +#: agenda_culturel/models.py:864 msgid "" "If checked, the extract will be searched for in the location using the exact " "form (capitals, accents)." @@ -517,85 +562,85 @@ msgstr "" "Si coché, l'extrait sera recherché dans la localisation en utilisant la " "forme exacte (majuscules, accents)" -#: agenda_culturel/models.py:849 +#: agenda_culturel/models.py:867 msgid "Categorisation rule" msgstr "Règle de catégorisation" -#: agenda_culturel/models.py:850 +#: agenda_culturel/models.py:868 msgid "Categorisation rules" msgstr "Règles de catégorisation" -#: agenda_culturel/models.py:911 agenda_culturel/models.py:932 +#: agenda_culturel/models.py:924 agenda_culturel/models.py:945 msgid "Question" msgstr "Question" -#: agenda_culturel/models.py:911 agenda_culturel/models.py:934 +#: agenda_culturel/models.py:924 agenda_culturel/models.py:947 msgid "Text that will be shown to moderators" msgstr "Text tel que présenté aux modérateurices" -#: agenda_culturel/models.py:914 +#: agenda_culturel/models.py:927 msgid "Moderation question" msgstr "Question de modération" -#: agenda_culturel/models.py:915 +#: agenda_culturel/models.py:928 msgid "Moderation questions" msgstr "Questions de modération" -#: agenda_culturel/models.py:932 +#: agenda_culturel/models.py:945 msgid "Associated question from moderation" msgstr "Question associée pour la modération" -#: agenda_culturel/models.py:934 +#: agenda_culturel/models.py:947 msgid "Answer" msgstr "Réponse" -#: agenda_culturel/models.py:936 +#: agenda_culturel/models.py:949 msgid "Adds tags" msgstr "Ajoute les étiquettes" -#: agenda_culturel/models.py:936 +#: agenda_culturel/models.py:949 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:937 +#: agenda_culturel/models.py:950 msgid "Removes tags" msgstr "Retire les étiquettes" -#: agenda_culturel/models.py:937 +#: agenda_culturel/models.py:950 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." -#: agenda_culturel/settings/base.py:137 +#: agenda_culturel/settings/base.py:138 msgid "English" msgstr "anglais" -#: agenda_culturel/settings/base.py:138 +#: agenda_culturel/settings/base.py:139 msgid "French" msgstr "français" -#: agenda_culturel/views.py:236 +#: agenda_culturel/views.py:261 msgid "The static content has been successfully updated." msgstr "Le contenu statique a été modifié avec succès." -#: agenda_culturel/views.py:243 agenda_culturel/views.py:278 +#: agenda_culturel/views.py:268 agenda_culturel/views.py:303 msgid "The event has been successfully modified." msgstr "L'événement a été modifié avec succès." -#: agenda_culturel/views.py:255 +#: agenda_culturel/views.py:280 msgid "The event has been successfully deleted." msgstr "L'événement a été supprimé avec succès" -#: agenda_culturel/views.py:304 +#: agenda_culturel/views.py:329 msgid "The status has been successfully modified." msgstr "Le status a été modifié avec succès." -#: agenda_culturel/views.py:326 +#: agenda_culturel/views.py:351 msgid "The event is saved." msgstr "L'événement est enregistré." -#: agenda_culturel/views.py:329 +#: agenda_culturel/views.py:354 msgid "" "The event has been submitted and will be published as soon as it has been " "validated by the moderation team." @@ -603,7 +648,7 @@ 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:366 +#: agenda_culturel/views.py:391 msgid "" "The event has been successfully extracted, and you can now submit it after " "modifying it if necessary." @@ -611,7 +656,7 @@ msgstr "" "L'événement a été extrait avec succès, vous pouvez maintenant le soumettre " "après l'avoir modifié au besoin." -#: agenda_culturel/views.py:370 +#: agenda_culturel/views.py:395 msgid "" "Unable to extract an event from the proposed URL. Please use the form below " "to submit the event." @@ -619,16 +664,16 @@ msgstr "" "Impossible d'extraire un événement depuis l'URL proposée. Veuillez utiliser " "le formulaire ci-dessous pour soumettre l'événement." -#: agenda_culturel/views.py:379 +#: agenda_culturel/views.py:404 msgid "This URL has already been submitted, and you can find the event below." msgstr "" "Cette URL a déjà été soumise, et vous trouverez l'événement ci-dessous." -#: agenda_culturel/views.py:383 +#: agenda_culturel/views.py:408 msgid "This URL has already been submitted and is awaiting moderation." msgstr "Cette URL a déjà été soumise, et est en attente de modération" -#: agenda_culturel/views.py:385 +#: agenda_culturel/views.py:410 msgid "" "This URL has already been submitted, but has not been selected for " "publication by the moderation team." @@ -636,51 +681,51 @@ msgstr "" "Cette URL a déjà été soumise, mais n'a pas été retenue par l'équipe de " "modération pour la publication." -#: agenda_culturel/views.py:407 +#: agenda_culturel/views.py:432 msgid "Your message has been sent successfully." msgstr "Votre message a été envoyé avec succès." -#: agenda_culturel/views.py:422 +#: agenda_culturel/views.py:447 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:437 +#: agenda_culturel/views.py:462 msgid "Open" msgstr "Ouvert" -#: agenda_culturel/views.py:479 +#: agenda_culturel/views.py:504 msgid "Search" msgstr "Rechercher" -#: agenda_culturel/views.py:596 +#: agenda_culturel/views.py:639 msgid "The import has been run successfully." msgstr "L'import a été lancé avec succès" -#: agenda_culturel/views.py:613 +#: agenda_culturel/views.py:656 msgid "The import has been canceled." msgstr "L'import a été annulé" -#: agenda_culturel/views.py:650 +#: agenda_culturel/views.py:693 msgid "The recurrent import has been successfully modified." msgstr "L'import récurrent a été modifié avec succès." -#: agenda_culturel/views.py:657 +#: agenda_culturel/views.py:700 msgid "The recurrent import has been successfully deleted." msgstr "L'import récurrent a été supprimé avec succès" -#: agenda_culturel/views.py:688 +#: agenda_culturel/views.py:731 msgid "The import has been launched." msgstr "L'import a été lancé" -#: agenda_culturel/views.py:748 +#: agenda_culturel/views.py:791 msgid "The merge has been successfully completed." msgstr "La fusion a été réalisée avec succès." -#: agenda_culturel/views.py:778 +#: agenda_culturel/views.py:821 msgid "Events have been marked as unduplicated." msgstr "Les événements ont été marqués comme non dupliqués." -#: agenda_culturel/views.py:795 +#: agenda_culturel/views.py:838 msgid "" "The selected event has been retained, while the other has been moved to the " "recycle bin." @@ -688,7 +733,7 @@ msgstr "" "L'événement sélectionné a été conservé, l'autre a été déplacé dans la " "corbeille." -#: agenda_culturel/views.py:797 +#: agenda_culturel/views.py:840 msgid "" "The selected event has been retained, while the others have been moved to " "the recycle bin." @@ -696,15 +741,15 @@ msgstr "" "L'événement sélectionné a été conservé, les autres ont été déplacés dans la " "corbeille." -#: agenda_culturel/views.py:803 +#: agenda_culturel/views.py:846 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:850 +#: agenda_culturel/views.py:893 msgid "The event was successfully duplicated." msgstr "L'événement a été marqué dupliqué avec succès." -#: agenda_culturel/views.py:853 +#: agenda_culturel/views.py:896 msgid "" "The event has been successfully flagged as a duplicate. The moderation team " "will deal with your suggestion shortly." @@ -712,32 +757,32 @@ 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:892 +#: agenda_culturel/views.py:935 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:899 +#: agenda_culturel/views.py:942 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:919 agenda_culturel/views.py:948 +#: agenda_culturel/views.py:962 agenda_culturel/views.py:991 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:921 agenda_culturel/views.py:950 +#: agenda_culturel/views.py:964 agenda_culturel/views.py:993 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:923 agenda_culturel/views.py:952 +#: agenda_culturel/views.py:966 agenda_culturel/views.py:995 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:980 +#: agenda_culturel/views.py:1023 msgid "The moderation question has been created with success." msgstr "La question de modération a été créée avec succès." diff --git a/src/agenda_culturel/migrations/0056_place_alter_event_location_event_exact_location.py b/src/agenda_culturel/migrations/0056_place_alter_event_location_event_exact_location.py new file mode 100644 index 0000000..bde4a6d --- /dev/null +++ b/src/agenda_culturel/migrations/0056_place_alter_event_location_event_exact_location.py @@ -0,0 +1,40 @@ +# Generated by Django 4.2.7 on 2024-04-26 14:24 + +from django.db import migrations, models +import django.db.models.deletion +import django_better_admin_arrayfield.models.fields +import location_field.models.plain + + +class Migration(migrations.Migration): + + dependencies = [ + ('agenda_culturel', '0055_alter_recurrentimport_name'), + ] + + operations = [ + migrations.CreateModel( + name='Place', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Name of the place', verbose_name='Name')), + ('address', models.CharField(help_text='Address of this place', verbose_name='Address')), + ('location', location_field.models.plain.PlainLocationField(max_length=63)), + ('aliases', django_better_admin_arrayfield.models.fields.ArrayField(base_field=models.CharField(max_length=512), blank=True, help_text='Alternative names or addresses used to match a place with a description form an event.', null=True, size=None, verbose_name='Alternative names')), + ], + options={ + 'verbose_name': 'Place', + 'verbose_name_plural': 'Places', + }, + ), + migrations.AlterField( + model_name='event', + name='location', + field=models.CharField(default='', help_text='Address of the event in case its not available in the already known places (free form)', max_length=512, verbose_name='Location (free form)'), + ), + migrations.AddField( + model_name='event', + name='exact_location', + field=models.ForeignKey(help_text='Address of the event', null=True, on_delete=django.db.models.deletion.SET_NULL, to='agenda_culturel.place', verbose_name='Location'), + ), + ] diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py index 772c33f..21debb5 100644 --- a/src/agenda_culturel/models.py +++ b/src/agenda_culturel/models.py @@ -23,6 +23,8 @@ from datetime import time, timedelta, date from django.utils.timezone import datetime from django.utils import timezone +from location_field.models.plain import PlainLocationField + from .calendar import CalendarList, CalendarDay import logging @@ -156,6 +158,25 @@ class DuplicatedEvents(models.Model): def get_items_comparison(self): return [self.get_item_comparison(e) for e in Event.data_fields(all=True)] +class Place(models.Model): + name = models.CharField(verbose_name=_('Name'), help_text=_('Name of the place')) + address = models.CharField(verbose_name=_('Address'), help_text=_('Address of this place')) + location = PlainLocationField(based_fields=['name', 'address'], zoom=12) + + aliases = ArrayField(models.CharField(max_length=512), verbose_name=_('Alternative names'), help_text=_("Alternative names or addresses used to match a place with the free-form location of an event."), blank=True, null=True) + + class Meta: + verbose_name = _('Place') + verbose_name_plural = _('Places') + + def __str__(self): + return self.name + ", " + self.address + + def get_absolute_url(self): + return reverse("view_place", kwargs={"pk": self.pk}) + + + class Event(models.Model): class STATUS(models.TextChoices): @@ -185,7 +206,8 @@ class Event(models.Model): recurrences = recurrence.fields.RecurrenceField(verbose_name=_("Recurrence"), include_dtstart=False, blank=True, null=True) - location = models.CharField(verbose_name=_('Location'), help_text=_('Address of the event'), max_length=512, default="") + exact_location = models.ForeignKey(Place, verbose_name=_('Location'), help_text=_('Address of the event'), null=True, on_delete=models.SET_NULL) + location = models.CharField(verbose_name=_('Location (free form)'), help_text=_('Address of the event in case its not available in the already known places (free form)'), max_length=512, default="") description = models.TextField(verbose_name=_('Description'), help_text=_('General description of the event'), blank=True, null=True) diff --git a/src/agenda_culturel/settings/base.py b/src/agenda_culturel/settings/base.py index cd0447a..6be9f26 100644 --- a/src/agenda_culturel/settings/base.py +++ b/src/agenda_culturel/settings/base.py @@ -47,6 +47,7 @@ INSTALLED_APPS = [ 'compressor', 'ckeditor', 'recurrence', + 'location_field.apps.DefaultConfig', ] MIDDLEWARE = [ @@ -206,4 +207,12 @@ DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000 # recurrence translation -RECURRENCE_I18N_URL = "javascript-catalog" \ No newline at end of file +RECURRENCE_I18N_URL = "javascript-catalog" + +# location field + +LOCATION_FIELD = { + 'map.provider': 'openstreetmap', + 'provider.openstreetmap.max_zoom': 18, + 'search.provider': 'addok', +} diff --git a/src/agenda_culturel/static/style.scss b/src/agenda_culturel/static/style.scss index 2e1fda5..620f553 100644 --- a/src/agenda_culturel/static/style.scss +++ b/src/agenda_culturel/static/style.scss @@ -629,6 +629,10 @@ form [role="button"], form button { margin: var(--spacing) 0 var(--spacing) 0; } +form .buttons [role="button"] { + margin: 0 0 var(--spacing) 0; +} + .large { margin: 2em auto; } @@ -810,3 +814,28 @@ table .buttons { margin: 4em auto; } } + +/** maps ***/ +.leaflet-container { + width: 100%; + border-radius: var(--border-radius); + [role="button"].leaflet-marker-icon { + background: none; + border: none; + } + + .leaflet-control { + a { + margin: 0; + padding: 0; + } + a:first-child { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + a:last-child { + border-top-left-radius: 0; + border-top-right-radius: 0; + } + } +} \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/categorisationrule_confirm_delete.html b/src/agenda_culturel/templates/agenda_culturel/categorisationrule_confirm_delete.html index a3e7cc1..2eeab7b 100644 --- a/src/agenda_culturel/templates/agenda_culturel/categorisationrule_confirm_delete.html +++ b/src/agenda_culturel/templates/agenda_culturel/categorisationrule_confirm_delete.html @@ -21,7 +21,7 @@ {{ form }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/categorisationrule_form.html b/src/agenda_culturel/templates/agenda_culturel/categorisationrule_form.html index dcd19ac..b5bb4a4 100644 --- a/src/agenda_culturel/templates/agenda_culturel/categorisationrule_form.html +++ b/src/agenda_culturel/templates/agenda_culturel/categorisationrule_form.html @@ -17,7 +17,7 @@
{% csrf_token %} {{ form.as_p }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/categorise_events_form.html b/src/agenda_culturel/templates/agenda_culturel/categorise_events_form.html index c786dbe..bc2e653 100644 --- a/src/agenda_culturel/templates/agenda_culturel/categorise_events_form.html +++ b/src/agenda_culturel/templates/agenda_culturel/categorise_events_form.html @@ -69,7 +69,7 @@ {{ field }} {% endif %} {% endfor %} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/event_form.html b/src/agenda_culturel/templates/agenda_culturel/event_form.html index fbbb4be..3fdd95f 100644 --- a/src/agenda_culturel/templates/agenda_culturel/event_form.html +++ b/src/agenda_culturel/templates/agenda_culturel/event_form.html @@ -40,7 +40,7 @@ {% csrf_token %} {{ form.media }} {{ form.as_p }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/event_moderation_form.html b/src/agenda_culturel/templates/agenda_culturel/event_moderation_form.html index c44f54d..6928d75 100644 --- a/src/agenda_culturel/templates/agenda_culturel/event_moderation_form.html +++ b/src/agenda_culturel/templates/agenda_culturel/event_moderation_form.html @@ -21,7 +21,7 @@ {% csrf_token %} {{ form.media }} {{ form.as_p }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/merge_duplicate.html b/src/agenda_culturel/templates/agenda_culturel/merge_duplicate.html index aeb7c33..1c948b5 100644 --- a/src/agenda_culturel/templates/agenda_culturel/merge_duplicate.html +++ b/src/agenda_culturel/templates/agenda_culturel/merge_duplicate.html @@ -21,7 +21,7 @@ {% csrf_token %} {{ form.as_grid }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/moderationanswer_confirm_delete.html b/src/agenda_culturel/templates/agenda_culturel/moderationanswer_confirm_delete.html index 09c4e9e..f94e8b9 100644 --- a/src/agenda_culturel/templates/agenda_culturel/moderationanswer_confirm_delete.html +++ b/src/agenda_culturel/templates/agenda_culturel/moderationanswer_confirm_delete.html @@ -10,7 +10,7 @@

Êtes-vous sûr·e de vouloir supprimer la réponse de modération #{{object.pk}} « {{ object.answer }} » associée à la question « {{ object.question.question }} » ?

{{ form }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/moderationanswer_form.html b/src/agenda_culturel/templates/agenda_culturel/moderationanswer_form.html index 516fa24..6482b0c 100644 --- a/src/agenda_culturel/templates/agenda_culturel/moderationanswer_form.html +++ b/src/agenda_culturel/templates/agenda_culturel/moderationanswer_form.html @@ -21,7 +21,7 @@
{% csrf_token %} {{ form.as_p }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/moderationquestion_confirm_delete.html b/src/agenda_culturel/templates/agenda_culturel/moderationquestion_confirm_delete.html index 907b9be..1f88a12 100644 --- a/src/agenda_culturel/templates/agenda_culturel/moderationquestion_confirm_delete.html +++ b/src/agenda_culturel/templates/agenda_culturel/moderationquestion_confirm_delete.html @@ -10,7 +10,7 @@

Êtes-vous sûr·e de vouloir supprimer la question de modération #{{object.pk}} « {{ object.question }} » ainsi que les réponses associées ?

{{ form }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/moderationquestion_form.html b/src/agenda_culturel/templates/agenda_culturel/moderationquestion_form.html index b10a0a9..fb0d90e 100644 --- a/src/agenda_culturel/templates/agenda_culturel/moderationquestion_form.html +++ b/src/agenda_culturel/templates/agenda_culturel/moderationquestion_form.html @@ -12,7 +12,7 @@
{% csrf_token %} {{ form.as_p }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/page-single.html b/src/agenda_culturel/templates/agenda_culturel/page-single.html index fca405b..59ef243 100644 --- a/src/agenda_culturel/templates/agenda_culturel/page-single.html +++ b/src/agenda_culturel/templates/agenda_culturel/page-single.html @@ -23,7 +23,7 @@

{{ title }}

{% include "agenda_culturel/static_content.html" with name=static_content url_path=url_path %} -
+
diff --git a/src/agenda_culturel/templates/agenda_culturel/place_confirm_delete.html b/src/agenda_culturel/templates/agenda_culturel/place_confirm_delete.html new file mode 100644 index 0000000..d066473 --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/place_confirm_delete.html @@ -0,0 +1,23 @@ +{% extends "agenda_culturel/page.html" %} + +{% block title %}Supprimer {{ object.name }}{% endblock %} + +{% block fluid %}{% endblock %} + +{% block content %} + +
+
+

Suppression du lieu {{ object.name }}

+
+ {% csrf_token %} +

Êtes-vous sûr·e de vouloir supprimer le lieu « {{ object.name }} ({{ object.pk }}) » situé à l'adresse {{ object.address }}, et de coordonnées {{ object.location }} ?

+ {{ form }} +
+ Annuler + +
+ +
+ +{% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/place_detail.html b/src/agenda_culturel/templates/agenda_culturel/place_detail.html new file mode 100644 index 0000000..671dddb --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/place_detail.html @@ -0,0 +1,72 @@ +{% extends "agenda_culturel/page.html" %} + +{% block title %}#{{ object.name }}{% endblock %} + +{% load tag_extra %} +{% load utils_extra %} +{% load cat_extra %} +{% load static %} + + +{% block entete_header %} + {% css_categories %} + + + + +{% endblock %} + +{% block fluid %}{% endblock %} + +{% block content %} + +
+
+ {% if perms.agenda_culturel.change_place %} + < Tous les lieux + {% endif %} +
+ {% if perms.agenda_culturel.change_place %} + Modifier {% picto_from_name "edit-3" %} + Supprimer {% picto_from_name "trash-2" %} +
+ {% endif %} +

{{ object.name }}

+
+
+
+ + {% if user.is_authenticated %} + {% if object.aliases|length > 0 %} +

Alias associés à ce lieu :

+
    + {% for alias in object.aliases %} +
  • {{ alias }}
  • + {% endfor %} +
+ {% else %} +

Ce lieu n'a pas d'alias défini

+ {% endif %} + {% endif %} +
+
+
+ +
+
+
+ +
+
+ +{% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/place_form.html b/src/agenda_culturel/templates/agenda_culturel/place_form.html new file mode 100644 index 0000000..345c71c --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/place_form.html @@ -0,0 +1,30 @@ +{% extends "agenda_culturel/page.html" %} +{% load static %} + +{% block title %} +{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'un lieu +{% endblock %} + +{% block entete_header %} + + + + + {{form.media}} +{% endblock %} + + +{% block content %} + +

{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'un lieu

+
+
{% csrf_token %} + {{ form.as_p }} +
+ Annuler + +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/place_list.html b/src/agenda_culturel/templates/agenda_culturel/place_list.html new file mode 100644 index 0000000..acea469 --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/place_list.html @@ -0,0 +1,67 @@ +{% extends "agenda_culturel/page.html" %} + +{% block title %}Questions de modération{% endblock %} + +{% load utils_extra %} +{% load cat_extra %} +{% block entete_header %} + {% css_categories %} +{% endblock %} + +{% block content %} +
+
+
+ Ajouter {% picto_from_name "plus-circle" %} +

Lieux

+
+ {% if object_list %} + {% for place in object_list %} + + {% endfor %} + {% else %} +

Il n'y a aucun lieu défini.

+ {% endif %} +
+ + {% if page_obj.has_previous %} + « premier + précédent + {% endif %} + + + Page {{ page_obj.number }} sur {{ page_obj.paginator.num_pages }} + + + {% if page_obj.has_next %} + suivant + dernier » + {% endif %} + +
+ +
+ +{% include "agenda_culturel/side-nav.html" with current="places" %} +
+ +{% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/recurrentimport_confirm_delete.html b/src/agenda_culturel/templates/agenda_culturel/recurrentimport_confirm_delete.html index 7e53e40..447f925 100644 --- a/src/agenda_culturel/templates/agenda_culturel/recurrentimport_confirm_delete.html +++ b/src/agenda_culturel/templates/agenda_culturel/recurrentimport_confirm_delete.html @@ -9,7 +9,7 @@
{% csrf_token %}

Êtes-vous sûr·e de vouloir supprimer l'import récurrent « {{ object.name }} ({{ object.pk }}) » correspondant à la source {{ object.source }} ?

{{ form }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/recurrentimport_form.html b/src/agenda_culturel/templates/agenda_culturel/recurrentimport_form.html index e195de0..90c9af5 100644 --- a/src/agenda_culturel/templates/agenda_culturel/recurrentimport_form.html +++ b/src/agenda_culturel/templates/agenda_culturel/recurrentimport_form.html @@ -17,7 +17,7 @@
{% csrf_token %} {{ form.as_p }} -
+ diff --git a/src/agenda_culturel/templates/agenda_culturel/run_rimport_confirm.html b/src/agenda_culturel/templates/agenda_culturel/run_rimport_confirm.html index 61a819c..074418f 100644 --- a/src/agenda_culturel/templates/agenda_culturel/run_rimport_confirm.html +++ b/src/agenda_culturel/templates/agenda_culturel/run_rimport_confirm.html @@ -14,7 +14,7 @@ {{ form }}