Ajout de la gestion des lieux
This commit is contained in:
parent
2df11abda3
commit
c6352091ea
@ -1,8 +1,8 @@
|
||||
from django.forms import ModelForm, ValidationError, TextInput, Form, URLField, MultipleHiddenInput, Textarea, CharField, ChoiceField, RadioSelect, MultipleChoiceField, BooleanField, HiddenInput
|
||||
from django.forms import ModelForm, ValidationError, TextInput, Form, URLField, MultipleHiddenInput, Textarea, CharField, ChoiceField, RadioSelect, MultipleChoiceField, BooleanField, HiddenInput, ModelChoiceField
|
||||
from datetime import date
|
||||
from django_better_admin_arrayfield.forms.widgets import DynamicArrayWidget
|
||||
|
||||
from .models import Event, BatchImportation, RecurrentImport, CategorisationRule, ModerationAnswer, ModerationQuestion
|
||||
from .models import Event, BatchImportation, RecurrentImport, CategorisationRule, ModerationAnswer, ModerationQuestion, Place
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from string import ascii_uppercase as auc
|
||||
from .templatetags.utils_extra import int_to_abc
|
||||
@ -283,8 +283,6 @@ class CategorisationForm(Form):
|
||||
if '_' not in f:
|
||||
if f + '_cat' in args[0]:
|
||||
events.append((Event.objects.get(pk=int(f)), args[0][f + '_cat']))
|
||||
|
||||
# TODO
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for e, c in events:
|
||||
@ -294,3 +292,48 @@ class CategorisationForm(Form):
|
||||
def get_validated(self):
|
||||
return [(e, self.cleaned_data.get(e + '_cat')) for e in self.fields if '_' not in e and self.cleaned_data.get(e)]
|
||||
|
||||
|
||||
class EventAddPlaceForm(Form):
|
||||
|
||||
place = ModelChoiceField(label=_("Place"), queryset=Place.objects.all(), empty_label=_("Create a missing place"), required=False)
|
||||
add_alias = BooleanField(initial=True, required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.instance = kwargs.pop('instance', False)
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.instance.location:
|
||||
self.fields["add_alias"].label = _("Add \"{}\" to the aliases of the place").format(self.instance.location)
|
||||
else:
|
||||
self.fields.pop("add_alias")
|
||||
|
||||
def modified_event(self):
|
||||
return self.cleaned_data.get('place')
|
||||
|
||||
def save(self):
|
||||
if self.cleaned_data.get("place"):
|
||||
place = self.cleaned_data.get("place")
|
||||
self.instance.exact_location = place
|
||||
self.instance.save()
|
||||
if self.cleaned_data.get('add_alias'):
|
||||
place.aliases.append(self.instance.location)
|
||||
place.save()
|
||||
|
||||
return self.instance
|
||||
|
||||
class PlaceForm(ModelForm):
|
||||
apply_to_all = BooleanField(initial=True, label=_('On saving, use aliases to detect all matching events with missing place'), required=False)
|
||||
|
||||
class Meta:
|
||||
model = Place
|
||||
fields = '__all__'
|
||||
widgets = {
|
||||
'location': TextInput()
|
||||
}
|
||||
|
||||
def as_grid(self):
|
||||
return mark_safe('<div class="grid"><div>' + super().as_p() + '</div><div><div class="map-widget">' +
|
||||
'<div id="map_location" style="width: 100%; aspect-ratio: 16/9"></div></div></div></div>')
|
||||
|
||||
|
||||
def apply(self):
|
||||
return self.cleaned_data.get("apply_to_all")
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: agenda_culturel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-26 14:59+0000\n"
|
||||
"POT-Creation-Date: 2024-04-27 16:25+0000\n"
|
||||
"PO-Revision-Date: 2023-10-29 14:16+0000\n"
|
||||
"Last-Translator: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n"
|
||||
"Language-Team: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n"
|
||||
@ -29,19 +29,35 @@ msgstr "L'heure de fin ne peut pas être avant l'heure de début."
|
||||
msgid "JSON in the format expected for the import."
|
||||
msgstr "JSON dans le format attendu pour l'import"
|
||||
|
||||
#: agenda_culturel/forms.py:291
|
||||
#, fuzzy
|
||||
#| msgid "Category of the event"
|
||||
#: agenda_culturel/forms.py:289
|
||||
msgid "Apply category {} to the event {}"
|
||||
msgstr "Catégorie de l'événement"
|
||||
msgstr "Appliquer la catégorie {} à l'événement {}"
|
||||
|
||||
#: agenda_culturel/forms.py:298 agenda_culturel/models.py:170
|
||||
msgid "Place"
|
||||
msgstr "Lieu"
|
||||
|
||||
#: agenda_culturel/forms.py:298
|
||||
msgid "Create a missing place"
|
||||
msgstr "Créer un lieu manquant"
|
||||
|
||||
#: agenda_culturel/forms.py:305
|
||||
msgid "Add \"{}\" to the aliases of the place"
|
||||
msgstr "Ajouter « {} » aux alias du lieu"
|
||||
|
||||
#: agenda_culturel/forms.py:324
|
||||
msgid "On saving, use aliases to detect all matching events with missing place"
|
||||
msgstr ""
|
||||
"Lors de l'enregistrement, utiliser des alias pour détecter tous les "
|
||||
"événements correspondants dont la place est manquante."
|
||||
|
||||
#: agenda_culturel/import_tasks/generic_extractors.py:151
|
||||
msgid "Cannot extract event from url {}"
|
||||
msgstr "Impossible d'extraire l'événement depuis l'url {}"
|
||||
|
||||
#: 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
|
||||
#: agenda_culturel/models.py:162 agenda_culturel/models.py:770
|
||||
#: agenda_culturel/models.py:809
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
@ -89,8 +105,8 @@ msgstr "Couleur"
|
||||
msgid "Color used as background for the category"
|
||||
msgstr "Couleur utilisée comme fond de la catégorie"
|
||||
|
||||
#: agenda_culturel/models.py:115 agenda_culturel/models.py:195
|
||||
#: agenda_culturel/models.py:804 agenda_culturel/models.py:855
|
||||
#: agenda_culturel/models.py:115 agenda_culturel/models.py:205
|
||||
#: agenda_culturel/models.py:821 agenda_culturel/models.py:872
|
||||
msgid "Category"
|
||||
msgstr "Catégorie"
|
||||
|
||||
@ -107,14 +123,22 @@ msgid "Address"
|
||||
msgstr "Adresse"
|
||||
|
||||
#: agenda_culturel/models.py:163
|
||||
msgid "Address of this place"
|
||||
msgstr "Adresse de ce lieu"
|
||||
msgid "Address of this place (without city name)"
|
||||
msgstr "Adresse de ce lieu (sans le nom de la ville)"
|
||||
|
||||
#: agenda_culturel/models.py:166
|
||||
#: agenda_culturel/models.py:164
|
||||
msgid "City"
|
||||
msgstr "Ville"
|
||||
|
||||
#: agenda_culturel/models.py:164
|
||||
msgid "City name"
|
||||
msgstr "Nom de la ville"
|
||||
|
||||
#: agenda_culturel/models.py:167
|
||||
msgid "Alternative names"
|
||||
msgstr "Noms alternatifs"
|
||||
|
||||
#: agenda_culturel/models.py:166
|
||||
#: agenda_culturel/models.py:167
|
||||
msgid ""
|
||||
"Alternative names or addresses used to match a place with the free-form "
|
||||
"location of an event."
|
||||
@ -122,81 +146,77 @@ 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
|
||||
#: agenda_culturel/models.py:171
|
||||
msgid "Places"
|
||||
msgstr "Lieux"
|
||||
|
||||
#: agenda_culturel/models.py:179 agenda_culturel/models.py:802
|
||||
#: agenda_culturel/models.py:189 agenda_culturel/models.py:819
|
||||
msgid "Published"
|
||||
msgstr "Publié"
|
||||
|
||||
#: agenda_culturel/models.py:180
|
||||
#: agenda_culturel/models.py:190
|
||||
msgid "Draft"
|
||||
msgstr "Brouillon"
|
||||
|
||||
#: agenda_culturel/models.py:181
|
||||
#: agenda_culturel/models.py:191
|
||||
msgid "Trash"
|
||||
msgstr "Corbeille"
|
||||
|
||||
#: agenda_culturel/models.py:191
|
||||
#: agenda_culturel/models.py:201
|
||||
msgid "Title"
|
||||
msgstr "Titre"
|
||||
|
||||
#: agenda_culturel/models.py:191
|
||||
#: agenda_culturel/models.py:201
|
||||
msgid "Short title"
|
||||
msgstr "Titre court"
|
||||
|
||||
#: agenda_culturel/models.py:193 agenda_culturel/models.py:839
|
||||
#: agenda_culturel/models.py:203 agenda_culturel/models.py:856
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
#: agenda_culturel/models.py:195
|
||||
#: agenda_culturel/models.py:205
|
||||
msgid "Category of the event"
|
||||
msgstr "Catégorie de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:197
|
||||
#: agenda_culturel/models.py:207
|
||||
msgid "Day of the event"
|
||||
msgstr "Date de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:198
|
||||
#: agenda_culturel/models.py:208
|
||||
msgid "Starting time"
|
||||
msgstr "Heure de début"
|
||||
|
||||
#: agenda_culturel/models.py:200
|
||||
#: agenda_culturel/models.py:210
|
||||
msgid "End day of the event"
|
||||
msgstr "Fin de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:200
|
||||
#: agenda_culturel/models.py:210
|
||||
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:201
|
||||
#: agenda_culturel/models.py:211
|
||||
msgid "Final time"
|
||||
msgstr "Heure de fin"
|
||||
|
||||
#: agenda_culturel/models.py:203
|
||||
#: agenda_culturel/models.py:213
|
||||
msgid "Recurrence"
|
||||
msgstr "Récurrence"
|
||||
|
||||
#: agenda_culturel/models.py:205 agenda_culturel/models.py:803
|
||||
#: agenda_culturel/models.py:215 agenda_culturel/models.py:820
|
||||
msgid "Location"
|
||||
msgstr "Localisation"
|
||||
|
||||
#: agenda_culturel/models.py:205
|
||||
#: agenda_culturel/models.py:215
|
||||
msgid "Address of the event"
|
||||
msgstr "Adresse de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:206
|
||||
#: agenda_culturel/models.py:216
|
||||
msgid "Location (free form)"
|
||||
msgstr "Localisation (forme libre)"
|
||||
|
||||
#: agenda_culturel/models.py:206
|
||||
#: agenda_culturel/models.py:216
|
||||
msgid ""
|
||||
"Address of the event in case its not available in the already known places "
|
||||
"(free form)"
|
||||
@ -204,189 +224,187 @@ 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
|
||||
#: agenda_culturel/models.py:218
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#: agenda_culturel/models.py:208
|
||||
#: agenda_culturel/models.py:218
|
||||
msgid "General description of the event"
|
||||
msgstr "Description générale de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:210
|
||||
#: agenda_culturel/models.py:220
|
||||
msgid "Illustration (local image)"
|
||||
msgstr "Illustration (image locale)"
|
||||
|
||||
#: agenda_culturel/models.py:210
|
||||
#: agenda_culturel/models.py:220
|
||||
msgid "Illustration image stored in the agenda server"
|
||||
msgstr "Image d'illustration stockée sur le serveur de l'agenda"
|
||||
|
||||
#: agenda_culturel/models.py:212
|
||||
#: agenda_culturel/models.py:222
|
||||
msgid "Illustration"
|
||||
msgstr "Illustration"
|
||||
|
||||
#: agenda_culturel/models.py:212
|
||||
#: agenda_culturel/models.py:222
|
||||
msgid "URL of the illustration image"
|
||||
msgstr "URL de l'image illustrative"
|
||||
|
||||
#: agenda_culturel/models.py:213
|
||||
#: agenda_culturel/models.py:223
|
||||
msgid "Illustration description"
|
||||
msgstr "Description de l'illustration"
|
||||
|
||||
#: agenda_culturel/models.py:213
|
||||
#: agenda_culturel/models.py:223
|
||||
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:215
|
||||
#: agenda_culturel/models.py:225
|
||||
msgid "Importation source"
|
||||
msgstr "Source d'importation"
|
||||
|
||||
#: agenda_culturel/models.py:215
|
||||
#: agenda_culturel/models.py:225
|
||||
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:216
|
||||
#: agenda_culturel/models.py:226
|
||||
msgid "UUIDs"
|
||||
msgstr "UUIDs"
|
||||
|
||||
#: agenda_culturel/models.py:216
|
||||
#: agenda_culturel/models.py:226
|
||||
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:217
|
||||
#: agenda_culturel/models.py:227
|
||||
msgid "URLs"
|
||||
msgstr "URLs"
|
||||
|
||||
#: agenda_culturel/models.py:217
|
||||
#: agenda_culturel/models.py:227
|
||||
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:219
|
||||
#: agenda_culturel/models.py:229
|
||||
msgid "Tags"
|
||||
msgstr "Étiquettes"
|
||||
|
||||
#: agenda_culturel/models.py:219
|
||||
#: agenda_culturel/models.py:229
|
||||
msgid "A list of tags that describe the event."
|
||||
msgstr "Une liste d'étiquettes décrivant l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:221
|
||||
#: agenda_culturel/models.py:231
|
||||
msgid "Possibly duplicated"
|
||||
msgstr "Possibles doublons"
|
||||
|
||||
#: agenda_culturel/models.py:262
|
||||
#: agenda_culturel/models.py:272
|
||||
msgid "Event"
|
||||
msgstr "Événement"
|
||||
|
||||
#: agenda_culturel/models.py:263
|
||||
#: agenda_culturel/models.py:273
|
||||
msgid "Events"
|
||||
msgstr "Événements"
|
||||
|
||||
#: agenda_culturel/models.py:749
|
||||
#: agenda_culturel/models.py:766
|
||||
msgid "Contact message"
|
||||
msgstr "Message de contact"
|
||||
|
||||
#: agenda_culturel/models.py:750
|
||||
#, fuzzy
|
||||
#| msgid "Your message"
|
||||
#: agenda_culturel/models.py:767
|
||||
msgid "Contact messages"
|
||||
msgstr "Messages de contact"
|
||||
|
||||
#: agenda_culturel/models.py:752
|
||||
#: agenda_culturel/models.py:769
|
||||
msgid "Subject"
|
||||
msgstr "Sujet"
|
||||
|
||||
#: agenda_culturel/models.py:752
|
||||
#: agenda_culturel/models.py:769
|
||||
msgid "The subject of your message"
|
||||
msgstr "Sujet de votre message"
|
||||
|
||||
#: agenda_culturel/models.py:753
|
||||
#: agenda_culturel/models.py:770
|
||||
msgid "Your name"
|
||||
msgstr "Votre nom"
|
||||
|
||||
#: agenda_culturel/models.py:754
|
||||
#: agenda_culturel/models.py:771
|
||||
msgid "Email address"
|
||||
msgstr "Adresse email"
|
||||
|
||||
#: agenda_culturel/models.py:754
|
||||
#: agenda_culturel/models.py:771
|
||||
msgid "Your email address"
|
||||
msgstr "Votre adresse email"
|
||||
|
||||
#: agenda_culturel/models.py:755
|
||||
#: agenda_culturel/models.py:772
|
||||
msgid "Message"
|
||||
msgstr "Message"
|
||||
|
||||
#: agenda_culturel/models.py:755
|
||||
#: agenda_culturel/models.py:772
|
||||
msgid "Your message"
|
||||
msgstr "Votre message"
|
||||
|
||||
#: agenda_culturel/models.py:759 agenda_culturel/views.py:462
|
||||
#: agenda_culturel/models.py:776 agenda_culturel/views.py:470
|
||||
msgid "Closed"
|
||||
msgstr "Fermé"
|
||||
|
||||
#: agenda_culturel/models.py:759
|
||||
#: agenda_culturel/models.py:776
|
||||
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:760
|
||||
#: agenda_culturel/models.py:777
|
||||
msgid "Comments"
|
||||
msgstr "Commentaires"
|
||||
|
||||
#: agenda_culturel/models.py:760
|
||||
#: agenda_culturel/models.py:777
|
||||
msgid "Comments on the message from the moderation team"
|
||||
msgstr "Commentaires sur ce message par l'équipe de modération"
|
||||
|
||||
#: agenda_culturel/models.py:770 agenda_culturel/models.py:837
|
||||
#: agenda_culturel/models.py:787 agenda_culturel/models.py:854
|
||||
msgid "Recurrent import"
|
||||
msgstr "Import récurrent"
|
||||
|
||||
#: agenda_culturel/models.py:771
|
||||
#: agenda_culturel/models.py:788
|
||||
msgid "Recurrent imports"
|
||||
msgstr "Imports récurrents"
|
||||
|
||||
#: agenda_culturel/models.py:775
|
||||
#: agenda_culturel/models.py:792
|
||||
msgid "ical"
|
||||
msgstr "ical"
|
||||
|
||||
#: agenda_culturel/models.py:776
|
||||
#: agenda_culturel/models.py:793
|
||||
msgid "ical no busy"
|
||||
msgstr "ical sans busy"
|
||||
|
||||
#: agenda_culturel/models.py:777
|
||||
#: agenda_culturel/models.py:794
|
||||
msgid "ical no VC"
|
||||
msgstr "ical sans VC"
|
||||
|
||||
#: agenda_culturel/models.py:778
|
||||
#: agenda_culturel/models.py:795
|
||||
msgid "lacoope.org"
|
||||
msgstr "lacoope.org"
|
||||
|
||||
#: agenda_culturel/models.py:779
|
||||
#: agenda_culturel/models.py:796
|
||||
msgid "la comédie"
|
||||
msgstr "la comédie"
|
||||
|
||||
#: agenda_culturel/models.py:780
|
||||
#: agenda_culturel/models.py:797
|
||||
msgid "le fotomat"
|
||||
msgstr "le fotomat"
|
||||
|
||||
#: agenda_culturel/models.py:781
|
||||
#: agenda_culturel/models.py:798
|
||||
msgid "la puce à loreille"
|
||||
msgstr "la puce à loreille"
|
||||
|
||||
#: agenda_culturel/models.py:784
|
||||
#: agenda_culturel/models.py:801
|
||||
msgid "simple"
|
||||
msgstr "simple"
|
||||
|
||||
#: agenda_culturel/models.py:785
|
||||
#: agenda_culturel/models.py:802
|
||||
msgid "Headless Chromium"
|
||||
msgstr "chromium sans interface"
|
||||
|
||||
#: agenda_culturel/models.py:789
|
||||
#: agenda_culturel/models.py:806
|
||||
msgid "daily"
|
||||
msgstr "chaque jour"
|
||||
|
||||
#: agenda_culturel/models.py:790
|
||||
#: agenda_culturel/models.py:807
|
||||
msgid "weekly"
|
||||
msgstr "chaque semaine"
|
||||
|
||||
#: agenda_culturel/models.py:792
|
||||
#: agenda_culturel/models.py:809
|
||||
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."
|
||||
@ -394,127 +412,127 @@ 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:793
|
||||
#: agenda_culturel/models.py:810
|
||||
msgid "Processor"
|
||||
msgstr "Processeur"
|
||||
|
||||
#: agenda_culturel/models.py:794
|
||||
#: agenda_culturel/models.py:811
|
||||
msgid "Downloader"
|
||||
msgstr "Téléchargeur"
|
||||
|
||||
#: agenda_culturel/models.py:796
|
||||
#: agenda_culturel/models.py:813
|
||||
msgid "Import recurrence"
|
||||
msgstr "Récurrence d'import"
|
||||
|
||||
#: agenda_culturel/models.py:799
|
||||
#: agenda_culturel/models.py:816
|
||||
msgid "Source"
|
||||
msgstr "Source"
|
||||
|
||||
#: agenda_culturel/models.py:799
|
||||
#: agenda_culturel/models.py:816
|
||||
msgid "URL of the source document"
|
||||
msgstr "URL du document source"
|
||||
|
||||
#: agenda_culturel/models.py:800
|
||||
#: agenda_culturel/models.py:817
|
||||
msgid "Browsable url"
|
||||
msgstr "URL navigable"
|
||||
|
||||
#: agenda_culturel/models.py:800
|
||||
#: agenda_culturel/models.py:817
|
||||
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:802
|
||||
#: agenda_culturel/models.py:819
|
||||
msgid "Status of each imported event (published or draft)"
|
||||
msgstr "Status de chaque événement importé (publié ou brouillon)"
|
||||
|
||||
#: agenda_culturel/models.py:803
|
||||
#: agenda_culturel/models.py:820
|
||||
msgid "Address for each imported event"
|
||||
msgstr "Adresse de chaque événement importé"
|
||||
|
||||
#: agenda_culturel/models.py:804
|
||||
#: agenda_culturel/models.py:821
|
||||
msgid "Category of each imported event"
|
||||
msgstr "Catégorie de chaque événement importé"
|
||||
|
||||
#: agenda_culturel/models.py:805
|
||||
#: agenda_culturel/models.py:822
|
||||
msgid "Tags for each imported event"
|
||||
msgstr "Étiquettes de chaque événement importé"
|
||||
|
||||
#: agenda_culturel/models.py:805
|
||||
#: agenda_culturel/models.py:822
|
||||
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:824
|
||||
#: agenda_culturel/models.py:841
|
||||
msgid "Running"
|
||||
msgstr "En cours"
|
||||
|
||||
#: agenda_culturel/models.py:825
|
||||
#: agenda_culturel/models.py:842
|
||||
msgid "Canceled"
|
||||
msgstr "Annulé"
|
||||
|
||||
#: agenda_culturel/models.py:826
|
||||
#: agenda_culturel/models.py:843
|
||||
msgid "Success"
|
||||
msgstr "Succès"
|
||||
|
||||
#: agenda_culturel/models.py:827
|
||||
#: agenda_culturel/models.py:844
|
||||
msgid "Failed"
|
||||
msgstr "Erreur"
|
||||
|
||||
#: agenda_culturel/models.py:830
|
||||
#: agenda_culturel/models.py:847
|
||||
msgid "Batch importation"
|
||||
msgstr "Importation par lot"
|
||||
|
||||
#: agenda_culturel/models.py:831
|
||||
#: agenda_culturel/models.py:848
|
||||
msgid "Batch importations"
|
||||
msgstr "Importations par lot"
|
||||
|
||||
#: agenda_culturel/models.py:837
|
||||
#: agenda_culturel/models.py:854
|
||||
msgid "Reference to the recurrent import processing"
|
||||
msgstr "Référence du processus d'import récurrent"
|
||||
|
||||
#: agenda_culturel/models.py:841
|
||||
#: agenda_culturel/models.py:858
|
||||
msgid "Error message"
|
||||
msgstr "Votre message"
|
||||
|
||||
#: agenda_culturel/models.py:843
|
||||
#: agenda_culturel/models.py:860
|
||||
msgid "Number of collected events"
|
||||
msgstr "Nombre d'événements collectés"
|
||||
|
||||
#: agenda_culturel/models.py:844
|
||||
#: agenda_culturel/models.py:861
|
||||
msgid "Number of imported events"
|
||||
msgstr "Nombre d'événements importés"
|
||||
|
||||
#: agenda_culturel/models.py:845
|
||||
#: agenda_culturel/models.py:862
|
||||
msgid "Number of updated events"
|
||||
msgstr "Nombre d'événements mis à jour"
|
||||
|
||||
#: agenda_culturel/models.py:846
|
||||
#: agenda_culturel/models.py:863
|
||||
msgid "Number of removed events"
|
||||
msgstr "Nombre d'événements supprimés"
|
||||
|
||||
#: agenda_culturel/models.py:853
|
||||
#: agenda_culturel/models.py:870
|
||||
msgid "Weight"
|
||||
msgstr "Poids"
|
||||
|
||||
#: agenda_culturel/models.py:853
|
||||
#: agenda_culturel/models.py:870
|
||||
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:855
|
||||
#: agenda_culturel/models.py:872
|
||||
msgid "Category applied to the event"
|
||||
msgstr "Catégorie appliquée à l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:857
|
||||
#: agenda_culturel/models.py:874
|
||||
msgid "Contained in the title"
|
||||
msgstr "Contenu dans le titre"
|
||||
|
||||
#: agenda_culturel/models.py:857
|
||||
#: agenda_culturel/models.py:874
|
||||
msgid "Text contained in the event title"
|
||||
msgstr "Texte contenu dans le titre de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:858
|
||||
#: agenda_culturel/models.py:875
|
||||
msgid "Exact title extract"
|
||||
msgstr "Extrait exact du titre"
|
||||
|
||||
#: agenda_culturel/models.py:858
|
||||
#: agenda_culturel/models.py:875
|
||||
msgid ""
|
||||
"If checked, the extract will be searched for in the title using the exact "
|
||||
"form (capitals, accents)."
|
||||
@ -522,19 +540,19 @@ msgstr ""
|
||||
"Si coché, l'extrait sera recherché dans le titre en utilisant la forme "
|
||||
"exacte (majuscules, accents)"
|
||||
|
||||
#: agenda_culturel/models.py:860
|
||||
#: agenda_culturel/models.py:877
|
||||
msgid "Contained in the description"
|
||||
msgstr "Contenu dans la description"
|
||||
|
||||
#: agenda_culturel/models.py:860
|
||||
#: agenda_culturel/models.py:877
|
||||
msgid "Text contained in the description"
|
||||
msgstr "Texte contenu dans la description"
|
||||
|
||||
#: agenda_culturel/models.py:861
|
||||
#: agenda_culturel/models.py:878
|
||||
msgid "Exact description extract"
|
||||
msgstr "Extrait exact de description"
|
||||
|
||||
#: agenda_culturel/models.py:861
|
||||
#: agenda_culturel/models.py:878
|
||||
msgid ""
|
||||
"If checked, the extract will be searched for in the description using the "
|
||||
"exact form (capitals, accents)."
|
||||
@ -542,19 +560,19 @@ msgstr ""
|
||||
"Si coché, l'extrait sera recherché dans la description en utilisant la forme "
|
||||
"exacte (majuscules, accents)"
|
||||
|
||||
#: agenda_culturel/models.py:863
|
||||
#: agenda_culturel/models.py:880
|
||||
msgid "Contained in the location"
|
||||
msgstr "Contenu dans la localisation"
|
||||
|
||||
#: agenda_culturel/models.py:863
|
||||
#: agenda_culturel/models.py:880
|
||||
msgid "Text contained in the event location"
|
||||
msgstr "Texte contenu dans la localisation de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:864
|
||||
#: agenda_culturel/models.py:881
|
||||
msgid "Exact location extract"
|
||||
msgstr "Extrait exact de localisation"
|
||||
|
||||
#: agenda_culturel/models.py:864
|
||||
#: agenda_culturel/models.py:881
|
||||
msgid ""
|
||||
"If checked, the extract will be searched for in the location using the exact "
|
||||
"form (capitals, accents)."
|
||||
@ -562,52 +580,52 @@ msgstr ""
|
||||
"Si coché, l'extrait sera recherché dans la localisation en utilisant la "
|
||||
"forme exacte (majuscules, accents)"
|
||||
|
||||
#: agenda_culturel/models.py:867
|
||||
#: agenda_culturel/models.py:884
|
||||
msgid "Categorisation rule"
|
||||
msgstr "Règle de catégorisation"
|
||||
|
||||
#: agenda_culturel/models.py:868
|
||||
#: agenda_culturel/models.py:885
|
||||
msgid "Categorisation rules"
|
||||
msgstr "Règles de catégorisation"
|
||||
|
||||
#: agenda_culturel/models.py:924 agenda_culturel/models.py:945
|
||||
#: agenda_culturel/models.py:941 agenda_culturel/models.py:962
|
||||
msgid "Question"
|
||||
msgstr "Question"
|
||||
|
||||
#: agenda_culturel/models.py:924 agenda_culturel/models.py:947
|
||||
#: agenda_culturel/models.py:941 agenda_culturel/models.py:964
|
||||
msgid "Text that will be shown to moderators"
|
||||
msgstr "Text tel que présenté aux modérateurices"
|
||||
|
||||
#: agenda_culturel/models.py:927
|
||||
#: agenda_culturel/models.py:944
|
||||
msgid "Moderation question"
|
||||
msgstr "Question de modération"
|
||||
|
||||
#: agenda_culturel/models.py:928
|
||||
#: agenda_culturel/models.py:945
|
||||
msgid "Moderation questions"
|
||||
msgstr "Questions de modération"
|
||||
|
||||
#: agenda_culturel/models.py:945
|
||||
#: agenda_culturel/models.py:962
|
||||
msgid "Associated question from moderation"
|
||||
msgstr "Question associée pour la modération"
|
||||
|
||||
#: agenda_culturel/models.py:947
|
||||
#: agenda_culturel/models.py:964
|
||||
msgid "Answer"
|
||||
msgstr "Réponse"
|
||||
|
||||
#: agenda_culturel/models.py:949
|
||||
#: agenda_culturel/models.py:966
|
||||
msgid "Adds tags"
|
||||
msgstr "Ajoute les étiquettes"
|
||||
|
||||
#: agenda_culturel/models.py:949
|
||||
#: agenda_culturel/models.py:966
|
||||
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:950
|
||||
#: agenda_culturel/models.py:967
|
||||
msgid "Removes tags"
|
||||
msgstr "Retire les étiquettes"
|
||||
|
||||
#: agenda_culturel/models.py:950
|
||||
#: agenda_culturel/models.py:967
|
||||
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."
|
||||
@ -620,27 +638,27 @@ msgstr "anglais"
|
||||
msgid "French"
|
||||
msgstr "français"
|
||||
|
||||
#: agenda_culturel/views.py:261
|
||||
#: agenda_culturel/views.py:269
|
||||
msgid "The static content has been successfully updated."
|
||||
msgstr "Le contenu statique a été modifié avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:268 agenda_culturel/views.py:303
|
||||
#: agenda_culturel/views.py:276 agenda_culturel/views.py:311
|
||||
msgid "The event has been successfully modified."
|
||||
msgstr "L'événement a été modifié avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:280
|
||||
#: agenda_culturel/views.py:288
|
||||
msgid "The event has been successfully deleted."
|
||||
msgstr "L'événement a été supprimé avec succès"
|
||||
|
||||
#: agenda_culturel/views.py:329
|
||||
#: agenda_culturel/views.py:337
|
||||
msgid "The status has been successfully modified."
|
||||
msgstr "Le status a été modifié avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:351
|
||||
#: agenda_culturel/views.py:359
|
||||
msgid "The event is saved."
|
||||
msgstr "L'événement est enregistré."
|
||||
|
||||
#: agenda_culturel/views.py:354
|
||||
#: agenda_culturel/views.py:362
|
||||
msgid ""
|
||||
"The event has been submitted and will be published as soon as it has been "
|
||||
"validated by the moderation team."
|
||||
@ -648,7 +666,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:391
|
||||
#: agenda_culturel/views.py:399
|
||||
msgid ""
|
||||
"The event has been successfully extracted, and you can now submit it after "
|
||||
"modifying it if necessary."
|
||||
@ -656,7 +674,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:395
|
||||
#: agenda_culturel/views.py:403
|
||||
msgid ""
|
||||
"Unable to extract an event from the proposed URL. Please use the form below "
|
||||
"to submit the event."
|
||||
@ -664,16 +682,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:404
|
||||
#: agenda_culturel/views.py:412
|
||||
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:408
|
||||
#: agenda_culturel/views.py:416
|
||||
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:410
|
||||
#: agenda_culturel/views.py:418
|
||||
msgid ""
|
||||
"This URL has already been submitted, but has not been selected for "
|
||||
"publication by the moderation team."
|
||||
@ -681,51 +699,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:432
|
||||
#: agenda_culturel/views.py:440
|
||||
msgid "Your message has been sent successfully."
|
||||
msgstr "Votre message a été envoyé avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:447
|
||||
#: agenda_culturel/views.py:455
|
||||
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:462
|
||||
#: agenda_culturel/views.py:470
|
||||
msgid "Open"
|
||||
msgstr "Ouvert"
|
||||
|
||||
#: agenda_culturel/views.py:504
|
||||
#: agenda_culturel/views.py:512
|
||||
msgid "Search"
|
||||
msgstr "Rechercher"
|
||||
|
||||
#: agenda_culturel/views.py:639
|
||||
#: agenda_culturel/views.py:647
|
||||
msgid "The import has been run successfully."
|
||||
msgstr "L'import a été lancé avec succès"
|
||||
|
||||
#: agenda_culturel/views.py:656
|
||||
#: agenda_culturel/views.py:664
|
||||
msgid "The import has been canceled."
|
||||
msgstr "L'import a été annulé"
|
||||
|
||||
#: agenda_culturel/views.py:693
|
||||
#: agenda_culturel/views.py:701
|
||||
msgid "The recurrent import has been successfully modified."
|
||||
msgstr "L'import récurrent a été modifié avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:700
|
||||
#: agenda_culturel/views.py:708
|
||||
msgid "The recurrent import has been successfully deleted."
|
||||
msgstr "L'import récurrent a été supprimé avec succès"
|
||||
|
||||
#: agenda_culturel/views.py:731
|
||||
#: agenda_culturel/views.py:739
|
||||
msgid "The import has been launched."
|
||||
msgstr "L'import a été lancé"
|
||||
|
||||
#: agenda_culturel/views.py:791
|
||||
#: agenda_culturel/views.py:799
|
||||
msgid "The merge has been successfully completed."
|
||||
msgstr "La fusion a été réalisée avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:821
|
||||
#: agenda_culturel/views.py:829
|
||||
msgid "Events have been marked as unduplicated."
|
||||
msgstr "Les événements ont été marqués comme non dupliqués."
|
||||
|
||||
#: agenda_culturel/views.py:838
|
||||
#: agenda_culturel/views.py:846
|
||||
msgid ""
|
||||
"The selected event has been retained, while the other has been moved to the "
|
||||
"recycle bin."
|
||||
@ -733,7 +751,7 @@ msgstr ""
|
||||
"L'événement sélectionné a été conservé, l'autre a été déplacé dans la "
|
||||
"corbeille."
|
||||
|
||||
#: agenda_culturel/views.py:840
|
||||
#: agenda_culturel/views.py:848
|
||||
msgid ""
|
||||
"The selected event has been retained, while the others have been moved to "
|
||||
"the recycle bin."
|
||||
@ -741,15 +759,15 @@ msgstr ""
|
||||
"L'événement sélectionné a été conservé, les autres ont été déplacés dans la "
|
||||
"corbeille."
|
||||
|
||||
#: agenda_culturel/views.py:846
|
||||
#: agenda_culturel/views.py:854
|
||||
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:893
|
||||
#: agenda_culturel/views.py:901
|
||||
msgid "The event was successfully duplicated."
|
||||
msgstr "L'événement a été marqué dupliqué avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:896
|
||||
#: agenda_culturel/views.py:904
|
||||
msgid ""
|
||||
"The event has been successfully flagged as a duplicate. The moderation team "
|
||||
"will deal with your suggestion shortly."
|
||||
@ -757,35 +775,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:935
|
||||
#: agenda_culturel/views.py:943
|
||||
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:942
|
||||
#: agenda_culturel/views.py:950
|
||||
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:962 agenda_culturel/views.py:991
|
||||
#: agenda_culturel/views.py:970 agenda_culturel/views.py:999
|
||||
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:964 agenda_culturel/views.py:993
|
||||
#: agenda_culturel/views.py:972 agenda_culturel/views.py:1001
|
||||
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:966 agenda_culturel/views.py:995
|
||||
#: agenda_culturel/views.py:974 agenda_culturel/views.py:1003
|
||||
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:1023
|
||||
#: agenda_culturel/views.py:1031
|
||||
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:1123 agenda_culturel/views.py:1178
|
||||
msgid "{} events have been updated."
|
||||
msgstr "{} événements ont été mis à jour."
|
||||
|
||||
#: agenda_culturel/views.py:1125 agenda_culturel/views.py:1180
|
||||
msgid "1 event has been updated."
|
||||
msgstr "1 événement a été mis à jour"
|
||||
|
||||
#: agenda_culturel/views.py:1127 agenda_culturel/views.py:1182
|
||||
msgid "No events have been modified."
|
||||
msgstr "Aucun événement n'a été modifié."
|
||||
|
||||
#: agenda_culturel/views.py:1135
|
||||
msgid "The place has been successfully updated."
|
||||
msgstr "Le lieu a été modifié avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:1142
|
||||
msgid "The place has been successfully created."
|
||||
msgstr "Le lieu a été créé avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:1201
|
||||
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:1203
|
||||
msgid "A new alias has been added to the selected place. "
|
||||
msgstr "Un nouvel alias a été créé pour le lieu sélectionné. "
|
||||
|
||||
msgid "Recurrent import name"
|
||||
msgstr "Nome de l'import récurrent"
|
||||
|
||||
|
19
src/agenda_culturel/migrations/0057_alter_place_aliases.py
Normal file
19
src/agenda_culturel/migrations/0057_alter_place_aliases.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 4.2.7 on 2024-04-27 07:44
|
||||
|
||||
from django.db import migrations, models
|
||||
import django_better_admin_arrayfield.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('agenda_culturel', '0056_place_alter_event_location_event_exact_location'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='aliases',
|
||||
field=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 the free-form location of an event.', null=True, size=None, verbose_name='Alternative names'),
|
||||
),
|
||||
]
|
@ -0,0 +1,24 @@
|
||||
# Generated by Django 4.2.7 on 2024-04-27 15:55
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('agenda_culturel', '0057_alter_place_aliases'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='place',
|
||||
name='city',
|
||||
field=models.CharField(default='', help_text='City name', verbose_name='City'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='address',
|
||||
field=models.CharField(help_text='Address of this place (without city name)', verbose_name='Address'),
|
||||
),
|
||||
]
|
23
src/agenda_culturel/migrations/0059_auto_20240427_1829.py
Normal file
23
src/agenda_culturel/migrations/0059_auto_20240427_1829.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.7 on 2024-04-27 16:29
|
||||
|
||||
from django.db import migrations
|
||||
from django.contrib.auth.management import create_permissions
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
|
||||
def update_groups_permissions(apps, schema_editor):
|
||||
|
||||
all_perms = Permission.objects.all()
|
||||
|
||||
# set permissions for moderators
|
||||
moderator_perms = [i for i in all_perms if i.content_type.app_label == 'agenda_culturel' and i.content_type.model in ['place']]
|
||||
Group.objects.get(name="Moderator").permissions.add(*moderator_perms)
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('agenda_culturel', '0058_place_city_alter_place_address'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(update_groups_permissions),
|
||||
]
|
@ -160,8 +160,9 @@ class DuplicatedEvents(models.Model):
|
||||
|
||||
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)
|
||||
address = models.CharField(verbose_name=_('Address'), help_text=_('Address of this place (without city name)'))
|
||||
city = models.CharField(verbose_name=_('City'), help_text=_('City name'))
|
||||
location = PlainLocationField(based_fields=['name', 'address', 'city'], 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)
|
||||
|
||||
@ -175,6 +176,11 @@ class Place(models.Model):
|
||||
def get_absolute_url(self):
|
||||
return reverse("view_place", kwargs={"pk": self.pk})
|
||||
|
||||
def nb_events(self):
|
||||
return Event.objects.filter(exact_location=self).count()
|
||||
|
||||
def match(self, event):
|
||||
return event.location in self.aliases
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
@ -396,9 +402,16 @@ class Event(models.Model):
|
||||
if self.image and not self.local_image:
|
||||
self.download_image()
|
||||
|
||||
# try to detect category
|
||||
if self.is_in_importation_process():
|
||||
# try to detect category
|
||||
CategorisationRule.apply_rules(self)
|
||||
# try to detect location
|
||||
if not self.exact_location:
|
||||
for p in Place.objects.all():
|
||||
if p.match(self):
|
||||
logger.warning("Found a place for an imported event: " + p.name)
|
||||
self.exact_location = p
|
||||
break
|
||||
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
@ -308,6 +308,10 @@ header .title {
|
||||
}
|
||||
}
|
||||
|
||||
article form label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
article#filters {
|
||||
.buttons-filter {
|
||||
float: right;
|
||||
@ -838,4 +842,12 @@ table .buttons {
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.missing-data {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#filters #id_city {
|
||||
columns: 4;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
|
||||
{% if event.exact_location %}
|
||||
{% if nolink %}
|
||||
{{ event.exact_location.name }}, {{ event.exact_location.city }}
|
||||
{% else %}
|
||||
<a href="{% url 'view_place' event.exact_location.pk %}">{{ event.exact_location.name }}, {{ event.exact_location.city }}</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if perms.agenda_culturel.change_event and perms.agenda_culturel.change_place %}
|
||||
<a href="{% url 'add_place_to_event' event.pk %}" class="missing-data">{{ event.location }}</a>
|
||||
{% else %}
|
||||
{{ event.location }}
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -18,6 +18,9 @@
|
||||
{% for s in filter.get_status_names %}
|
||||
{{ s }}
|
||||
{% endfor %}
|
||||
{% for c in filter.get_cities %}
|
||||
{{ c }}
|
||||
{% endfor %}
|
||||
{{ filter.get_recurrence_filtering }}
|
||||
{% else %}
|
||||
Filtrer
|
||||
|
@ -52,6 +52,9 @@
|
||||
{% if perms.agenda_culturel.change_duplicatedevents %}
|
||||
{% show_badge_duplicated "bottom" %}
|
||||
{% endif %}
|
||||
{% if perms.agenda_culturel.change_place and perms.agenda_culturel.change_event %}
|
||||
{% show_badge_unknown_places "bottom" %}
|
||||
{% endif %}
|
||||
{% if perms.agenda_culturel.view_contactmessage %}
|
||||
{% show_badge_contactmessages "bottom" %}
|
||||
{% endif %}
|
||||
|
@ -10,8 +10,16 @@
|
||||
<header>
|
||||
<h1>Suppression du lieu {{ object.name }}</h1>
|
||||
</header>
|
||||
{% with nb_events=object.nb_events %}
|
||||
{% if nb_events > 0 %}
|
||||
<p class="message warning"><strong>Attention :</strong> {{ nb_events }} événement{{ nb_events|pluralize }}
|
||||
{% if nb_events > 1 %}sont enregistrés{% else %}est enregistré{% endif %} dans ce lieu.</p>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<p>Ê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 }} ?</p>
|
||||
|
||||
<form method="post">{% csrf_token %}
|
||||
<p>Ê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 }} ?</p>
|
||||
|
||||
{{ form }}
|
||||
<div class="grid buttons">
|
||||
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{{ object.get_absolute_url }}{% endif %}" role="button" class="secondary">Annuler</a>
|
||||
|
@ -25,8 +25,8 @@
|
||||
{% if perms.agenda_culturel.change_place %}
|
||||
<a href="{% url 'view_places' %}" role="button">< Tous les lieux</a>
|
||||
{% endif %}
|
||||
<div class="slide-buttons">
|
||||
{% if perms.agenda_culturel.change_place %}
|
||||
<div class="slide-buttons">
|
||||
<a href="{% url 'edit_place' place.pk %}" role="button">Modifier {% picto_from_name "edit-3" %}</a>
|
||||
<a href="{% url 'delete_place' place.pk %}" role="button">Supprimer {% picto_from_name "trash-2" %}</a>
|
||||
</div>
|
||||
@ -36,8 +36,13 @@
|
||||
<div class="grid">
|
||||
<div>
|
||||
<ul>
|
||||
<li><strong>Adresse :</strong> {{ object.address }}</li>
|
||||
<li><strong>Adresse :</strong> {{ object.address }}, {{ object.city }}</li>
|
||||
<li><strong>Coordonnée GPS :</strong> <a href="geo:{{ object.location }}">{{ object.location }}</a></li>
|
||||
{% if object.nb_events > 0 %}
|
||||
<li><strong>Nombre d'événements :</strong> {{ object.nb_events }}</li>
|
||||
{% else %}
|
||||
<li><em>Aucun événement n'est enregistré dans ce lieu</em></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if user.is_authenticated %}
|
||||
{% if object.aliases|length > 0 %}
|
||||
|
@ -18,13 +18,20 @@
|
||||
|
||||
<h1>{% if form.instance.pk %}Modification{% else %}Création{% endif %} d'un lieu</h1>
|
||||
<article>
|
||||
{% if event %}
|
||||
<p>Création d'un lieu depuis l'événement « {{ event }} » (voir en bas de page le détail de l'événement).</p>
|
||||
{% endif %}
|
||||
<form method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
{{ form.as_grid }}
|
||||
<div class="grid buttons">
|
||||
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{{ object.get_absolute_url }}{% endif %}" role="button" class="secondary">Annuler</a>
|
||||
<input type="submit" value="Envoyer">
|
||||
</div>
|
||||
</form>
|
||||
{% if event %}
|
||||
<h2>Description du lieu :</h2>
|
||||
{% include "agenda_culturel/single-event/event-single-inc.html" with event=event noedit=1 %}
|
||||
{% endif %}
|
||||
</article>
|
||||
|
||||
{% endblock %}
|
@ -12,7 +12,10 @@
|
||||
<div class="grid two-columns">
|
||||
<article>
|
||||
<header>
|
||||
<a class="slide-buttons" href="{% url 'add_place' %}" role="button">Ajouter {% picto_from_name "plus-circle" %}</a>
|
||||
<div class="slide-buttons">
|
||||
<a href="{% url 'fix_unknown_places' %}" role="button" data-tooltip="Utiliser les alias des lieux pour les associer aux événements sans lieu">Détecter par alias {% picto_from_name "link" %}</a>
|
||||
<a href="{% url 'add_place' %}" role="button">Ajouter {% picto_from_name "plus-circle" %}</a>
|
||||
</div>
|
||||
<h1>Lieux</h1>
|
||||
</header>
|
||||
{% if object_list %}
|
||||
@ -26,7 +29,7 @@
|
||||
</div>
|
||||
<h2>Lieu #{{ place.pk }} : {{ place.name }}</h2>
|
||||
<ul>
|
||||
<li><strong>Adresse :</strong> {{ place.address }}</li>
|
||||
<li><strong>Adresse :</strong> {{ place.address }}, {{ place.city }}</li>
|
||||
<li><strong>Coordonnée GPS :</strong> {{ place.location }}</li>
|
||||
</ul>
|
||||
{% if place.aliases|length > 0 %}
|
||||
@ -34,6 +37,11 @@
|
||||
{% else %}
|
||||
<p><em>Ce lieu n'a pas d'alias défini</em></p>
|
||||
{% endif %}
|
||||
{% if place.nb_events > 0 %}
|
||||
<p><strong>Nombre d'événements :</strong> {{ place.nb_events }}</p>
|
||||
{% else %}
|
||||
<p><em>Aucun événement n'est enregistré dans ce lieu</em></p>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
</article>
|
||||
|
@ -0,0 +1,49 @@
|
||||
{% extends "agenda_culturel/page.html" %}
|
||||
{% load static %}
|
||||
|
||||
|
||||
{% block title %}Ajouter un lieu à {{ object.title }}{% endblock %}
|
||||
|
||||
{% block entete_header %}
|
||||
<script src="{% url 'jsi18n' %}"></script>
|
||||
<script src="/static/admin/js/vendor/jquery/jquery.js"></script>
|
||||
<script src="/static/admin/js/jquery.init.js"></script>
|
||||
<script src="/static/admin/js/admin/DateTimeShortcuts.js"></script>
|
||||
<script src="{% static 'recurrence/js/recurrence.js' %}"></script>
|
||||
<script src="{% static 'recurrence/js/recurrence.js' %}"></script>
|
||||
<script src="/static/admin/js/admin/RelatedObjectLookups.js"></script>
|
||||
|
||||
|
||||
<script>window.CKEDITOR_BASEPATH = '/static/ckeditor/ckeditor/';</script>
|
||||
<script src="/static/admin/js/vendor/jquery/jquery.js"></script>
|
||||
<script src="/static/admin/js/jquery.init.js"></script>
|
||||
<link href="{% static 'css/django_better_admin_arrayfield.min.css' %}" type="text/css" media="all" rel="stylesheet">
|
||||
<script src="{% static 'js/django_better_admin_arrayfield.min.js' %}"></script>
|
||||
<script src="{% static 'js/adjust_datetimes.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block fluid %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% load static_content_extra %}
|
||||
|
||||
<article>
|
||||
<header>
|
||||
<h1>Ajouter un lieu à {{ object.title }} ({{ object.start_day }})</h1>
|
||||
</header>
|
||||
|
||||
<p>Si le lieu est disponible dans la liste, veuillez le sélectionner.</p>
|
||||
<form method="post">{% csrf_token %}
|
||||
{{ form.media }}
|
||||
{{ form.as_p }}
|
||||
<div class="grid buttons">
|
||||
<a href="{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}{{ object.get_absolute_url }}{% endif %}" role="button" class="secondary">Annuler</a>
|
||||
<input type="submit" value="Valider">
|
||||
</div>
|
||||
</form>
|
||||
<h2>Description du lieu :</h2>
|
||||
{% include "agenda_culturel/single-event/event-single-inc.html" with event=object noedit=1 %}
|
||||
</article>
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,49 @@
|
||||
{% extends "agenda_culturel/page.html" %}
|
||||
{% load utils_extra %}
|
||||
|
||||
|
||||
{% block title %}Événements sans lieu{% endblock %}
|
||||
|
||||
{% load cat_extra %}
|
||||
{% block entete_header %}
|
||||
{% css_categories %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="grid two-columns">
|
||||
<article>
|
||||
<header>
|
||||
<div class="slide-buttons">
|
||||
<a href="{% url 'fix_unknown_places' %}" role="button" data-tooltip="Utiliser les alias des lieux pour les associer aux événements sans lieu">Détecter par alias {% picto_from_name "link" %}</a>
|
||||
</div>
|
||||
<h1>Événements sans lieu</h1>
|
||||
</header>
|
||||
|
||||
<div>
|
||||
{% for obj in object_list %}
|
||||
<article>{% include "agenda_culturel/single-event/event-in-unknown-place-list-inc.html" with event=obj %}</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<footer>
|
||||
<span>
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?page=1" role="button">« premier</a>
|
||||
<a href="?page={{ page_obj.previous_page_number }}" role="button">précédent</a>
|
||||
{% endif %}
|
||||
|
||||
<span>
|
||||
Page {{ page_obj.number }} sur {{ page_obj.paginator.num_pages }}
|
||||
</span>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.next_page_number }}" role="button">suivant</a>
|
||||
<a href="?page={{ page_obj.paginator.num_pages }}" role="button">dernier »</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</footer>
|
||||
</article>
|
||||
|
||||
{% include "agenda_culturel/side-nav.html" with current="unknown_places" %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -24,6 +24,9 @@
|
||||
{% if perms.agenda_culturel.change_place %}
|
||||
<li><a {% if current == "places" %}class="selected" {% endif %}href="{% url 'view_places' %}">Liste des lieux</a></li>
|
||||
{% endif %}
|
||||
{% if perms.agenda_culturel.change_place and perms.agenda_culturel.change_event %}
|
||||
<li><a {% if current == "unknown_places" %}class="selected" {% endif %}href="{% url 'view_unknown_places' %}">Événements sans lieu</a>{% show_badge_unknown_places "left" %}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% if perms.agenda_culturel.view_batchimportation or perms.agenda_culturel.view_recurrentimport or perms.agenda_culturel.view_categorisationrule%}
|
||||
|
@ -12,7 +12,7 @@
|
||||
</header>
|
||||
<p class="subentry-search"></p>
|
||||
{% picto_from_name "map-pin" %}
|
||||
{% if event.location_hl %}{{ event.location_hl | safe }}{% else %}{{ event.location }}{% endif %}</p>
|
||||
{% if event.location_hl %}{{ event.location_hl | safe }}{% else %}{% include "agenda_culturel/event-location-inc.html" with event=event %}{% endif %}</p>
|
||||
{% if event.has_recurrences %}
|
||||
<p class="subentry-search">
|
||||
{% picto_from_name "repeat" %}
|
||||
|
@ -21,14 +21,14 @@
|
||||
{% endif %}
|
||||
|
||||
{{ event.category | small_cat_recurrent:event.has_recurrences }}
|
||||
{% if event.location %}<hgroup>{% endif %}
|
||||
{% if event.location or event.exact_location %}<hgroup>{% endif %}
|
||||
<h3>
|
||||
{{ event|picto_status }}
|
||||
<a href="{{ event.get_absolute_url }}">{{ event.title }}</a></h3>
|
||||
{% if event.location %}
|
||||
{% if event.location or event.exact_location %}
|
||||
<h4>
|
||||
{% picto_from_name "map-pin" %}
|
||||
{{ event.location }}
|
||||
{% include "agenda_culturel/event-location-inc.html" with event=event %}
|
||||
</h4>
|
||||
</hgroup>
|
||||
{% endif %}
|
||||
|
@ -8,16 +8,16 @@
|
||||
{% include "agenda_culturel/ephemeris-inc.html" with event=event filter=filter %}
|
||||
|
||||
{{ event.category | small_cat_recurrent:event.has_recurrences }}
|
||||
{% if event.location %}<hgroup>{% endif %}
|
||||
{% if event.location or event.exact_location %}<hgroup>{% endif %}
|
||||
<h2>
|
||||
{{ event|picto_status }}
|
||||
<a href="{{ event.get_absolute_url }}">{{ event.title }}</a>
|
||||
</h2>
|
||||
{% if event.location %}
|
||||
{% if event.location or event.exact_location %}
|
||||
<h3>
|
||||
{% picto_from_name "map-pin" %}
|
||||
|
||||
{{ event.location }}
|
||||
{% include "agenda_culturel/event-location-inc.html" with event=event %}
|
||||
</h3>
|
||||
</hgroup>
|
||||
{% endif %}
|
||||
|
@ -0,0 +1,46 @@
|
||||
{% load utils_extra %}
|
||||
{% load cat_extra %}
|
||||
{% load event_extra %}
|
||||
|
||||
<header>
|
||||
<div class="slide-buttons">
|
||||
<div class="buttons">
|
||||
<a href="{% url 'add_place_to_event' event.pk %}" role="button">Ajouter le lieu {% picto_from_name "map-pin" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{ event.category | small_cat_recurrent:event.has_recurrences }}
|
||||
{{ event|picto_status }}
|
||||
<a href="{{ event.get_absolute_url }}">
|
||||
{{ event.title }}</a></p>
|
||||
{% picto_from_name "map-pin" %}
|
||||
{% include "agenda_culturel/event-location-inc.html" with event=event %}
|
||||
</header>
|
||||
<p>{% picto_from_name "calendar" %}
|
||||
{% if event.end_day and event.end_day != event.start_day %}du{% else %}le{% endif %}
|
||||
{% include "agenda_culturel/date-times-inc.html" with event=event %}
|
||||
{% if event.has_recurrences %}
|
||||
<p>
|
||||
{% picto_from_name "repeat" %}
|
||||
<!-- TODO: see https://forge.chapril.org/jmtrivial/agenda_culturel/issues/65 -->
|
||||
{% for r in event.recurrences.rrules %}
|
||||
{{ r.to_text }}{% if not forloop.first %}, {% endif %}{% endfor %}, depuis le
|
||||
{% if event.recurrences.dtstart.date %}
|
||||
{{ event.recurrences.dtstart.date }}
|
||||
{% else %}
|
||||
{{ event.start_day }}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% picto_from_name "tag" %}
|
||||
{% for tag in event.tags %}
|
||||
<a href="{% url 'view_tag' tag %}">{{ tag }}</a>
|
||||
{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
<div class="description">
|
||||
{% if event.description %}{{ event.description |truncatewords:60 }}{% else %}<em>pas de description</em>{% endif %}
|
||||
|
||||
</div>
|
@ -15,7 +15,7 @@
|
||||
|
||||
<p>
|
||||
{% picto_from_name "map-pin" %}
|
||||
{{ event.location }}
|
||||
{% include "agenda_culturel/event-location-inc.html" with event=event nolink=1 %}
|
||||
</p>
|
||||
<p>
|
||||
{% picto_from_name "calendar" %}
|
||||
|
@ -16,7 +16,7 @@
|
||||
</p>
|
||||
<p>
|
||||
{% picto_from_name "map-pin" %}
|
||||
{{ event.location }}
|
||||
{% include "agenda_culturel/event-location-inc.html" with event=event %}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
|
@ -1,12 +1 @@
|
||||
<div class="grid">
|
||||
<div>
|
||||
{{field_input}}
|
||||
</div>
|
||||
<div>
|
||||
<div class="map-widget" style="margin-top: 4px">
|
||||
<label></label>
|
||||
|
||||
<div id="map_{{field_name}}" style="width: 100%; aspect-ratio: 16/9"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{field_input}}
|
||||
|
@ -50,7 +50,16 @@ def show_badges_events(placement="top"):
|
||||
return mark_safe('<a href="' + reverse_lazy("moderation") + '?status=draft" class="badge" data-placement="' + placement + '" data-tooltip="' + str(nb_drafts) + ' brouillon' + pluralize(nb_drafts) + ' à valider">' + picto_from_name("calendar") + " " + str(nb_drafts) + '</a>')
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def show_badge_unknown_places(placement="top"):
|
||||
nb_unknown = Event.objects.filter(exact_location__isnull=True).count()
|
||||
if nb_unknown != 0:
|
||||
return mark_safe('<a href="' + reverse_lazy("view_unknown_places") + '" class="badge" data-placement="' + placement + '" data-tooltip="' + str(nb_unknown) + ' événement' + pluralize(nb_unknown) + ' sans lieu défini">' + picto_from_name("map-pin") + " " + str(nb_unknown) + '</a>')
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def event_field_verbose_name(the_field):
|
||||
return Event._meta.get_field(the_field).verbose_name
|
||||
|
@ -72,6 +72,11 @@ urlpatterns = [
|
||||
path("place/<int:pk>/delete", PlaceDeleteView.as_view(), name="delete_place"),
|
||||
path("places/", PlaceListView.as_view(), name="view_places"),
|
||||
path("places/add", PlaceCreateView.as_view(), name="add_place"),
|
||||
path("places/add/<int:pk>", PlaceFromEventCreateView.as_view(), name="add_place_from_event"),
|
||||
path("events/unknown-places", UnknownPlacesListView.as_view(), name="view_unknown_places"),
|
||||
path("events/unknown-places/fix", fix_unknown_places, name="fix_unknown_places"),
|
||||
path("event/<int:pk>/addplace", UnknownPlaceAddView.as_view(), name="add_place_to_event"),
|
||||
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
|
@ -12,7 +12,7 @@ from django.urls import reverse
|
||||
import urllib
|
||||
from collections import Counter
|
||||
|
||||
from .forms import EventSubmissionForm, EventForm, BatchImportationForm, FixDuplicates, SelectEventInList, MergeDuplicates, RecurrentImportForm, CategorisationRuleImportForm, ModerationQuestionForm, ModerationAnswerForm, ModerateForm, CategorisationForm
|
||||
from .forms import EventSubmissionForm, EventForm, BatchImportationForm, FixDuplicates, SelectEventInList, MergeDuplicates, RecurrentImportForm, CategorisationRuleImportForm, ModerationQuestionForm, ModerationAnswerForm, ModerateForm, CategorisationForm, EventAddPlaceForm, PlaceForm
|
||||
|
||||
from .models import Event, Category, StaticContent, ContactMessage, BatchImportation, DuplicatedEvents, RecurrentImport, CategorisationRule, remove_accents, ModerationQuestion, ModerationAnswer, Place
|
||||
from django.utils import timezone
|
||||
@ -94,6 +94,11 @@ class EventFilter(django_filters.FilterSet):
|
||||
queryset=Category.objects.all(),
|
||||
widget=CategoryCheckboxSelectMultiple)
|
||||
|
||||
city = django_filters.MultipleChoiceFilter(label="Filtrer par ville",
|
||||
field_name='exact_location__city',
|
||||
choices=[(p["city"], p["city"]) for p in Place.objects.values("city").distinct().order_by("city")],
|
||||
widget=forms.CheckboxSelectMultiple)
|
||||
|
||||
status = django_filters.MultipleChoiceFilter(label="Filtrer par status",
|
||||
choices=Event.STATUS.choices,
|
||||
field_name="status",
|
||||
@ -102,7 +107,7 @@ class EventFilter(django_filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = Event
|
||||
fields = ["category", "tags", "exclude_tags", "status", "recurrences"]
|
||||
fields = ["category", "city", "tags", "exclude_tags", "status", "recurrences"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@ -136,6 +141,9 @@ class EventFilter(django_filters.FilterSet):
|
||||
def get_status(self):
|
||||
return self.form.cleaned_data["status"]
|
||||
|
||||
def get_cities(self):
|
||||
return self.form.cleaned_data["city"]
|
||||
|
||||
def get_status_names(self):
|
||||
if "status" in self.form.cleaned_data:
|
||||
return [dict(Event.STATUS.choices)[s] for s in self.form.cleaned_data["status"]]
|
||||
@ -158,7 +166,7 @@ class EventFilter(django_filters.FilterSet):
|
||||
else:
|
||||
if "status" in self.form.cleaned_data and len(self.form.cleaned_data["status"]) != 0:
|
||||
return True
|
||||
return len(self.form.cleaned_data["category"]) != 0 or len(self.form.cleaned_data["tags"]) != 0 or len(self.form.cleaned_data["exclude_tags"]) != 0 or len(self.form.cleaned_data["recurrences"]) != 0
|
||||
return len(self.form.cleaned_data["category"]) != 0 or len(self.form.cleaned_data["tags"]) != 0 or len(self.form.cleaned_data["exclude_tags"]) != 0 or len(self.form.cleaned_data["recurrences"]) != 0 or len(self.form.cleaned_data["city"]) != 0
|
||||
|
||||
def is_selected(self, cat):
|
||||
return cat in self.form.cleaned_data["category"]
|
||||
@ -1081,22 +1089,138 @@ class ModerationAnswerDeleteView(PermissionRequiredMixin, DeleteView):
|
||||
|
||||
class PlaceListView(ListView):
|
||||
model = Place
|
||||
paginate_by = 10
|
||||
ordering = ['-pk']
|
||||
|
||||
class PlaceDetailView(PermissionRequiredMixin, DetailView):
|
||||
model = Place
|
||||
permission_required = ("agenda_culturel.view_place")
|
||||
|
||||
class PlaceUpdateView(PermissionRequiredMixin, UpdateView):
|
||||
class PlaceDetailView(DetailView):
|
||||
model = Place
|
||||
|
||||
class UpdatePlaces:
|
||||
def form_valid(self, form):
|
||||
result = super().form_valid(form)
|
||||
p = form.instance
|
||||
|
||||
if not hasattr(self, "nb_applied"):
|
||||
self.nb_applied = 0
|
||||
|
||||
# if required, find all matching events
|
||||
if form.apply():
|
||||
u_events = Event.objects.filter(exact_location__isnull=True)
|
||||
|
||||
to_be_updated = []
|
||||
# try to find matches
|
||||
for ue in u_events:
|
||||
if p.match(ue):
|
||||
ue.exact_location = p
|
||||
to_be_updated.append(ue)
|
||||
continue
|
||||
# update events with a location
|
||||
Event.objects.bulk_update(to_be_updated, fields=["exact_location"])
|
||||
self.nb_applied += len(to_be_updated)
|
||||
|
||||
if self.nb_applied > 1:
|
||||
messages.success(self.request, _("{} events have been updated.").format(self.nb_applied))
|
||||
elif self.nb_applied == 1:
|
||||
messages.success(self.request, _("1 event has been updated."))
|
||||
else:
|
||||
messages.info(self.request, _("No events have been modified."))
|
||||
return result
|
||||
|
||||
|
||||
|
||||
class PlaceUpdateView(UpdatePlaces, PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
|
||||
model = Place
|
||||
fields = '__all__'
|
||||
permission_required = ("agenda_culturel.change_place")
|
||||
success_message = _('The place has been successfully updated.')
|
||||
form_class = PlaceForm
|
||||
|
||||
class PlaceCreateView(PermissionRequiredMixin, SuccessMessageMixin, CreateView):
|
||||
|
||||
class PlaceCreateView(UpdatePlaces, PermissionRequiredMixin, SuccessMessageMixin, CreateView):
|
||||
model = Place
|
||||
permission_required = ("agenda_culturel.add_place")
|
||||
success_message = _('The place has been successfully created.')
|
||||
form_class = PlaceForm
|
||||
|
||||
|
||||
class PlaceDeleteView(PermissionRequiredMixin, DeleteView):
|
||||
model = Place
|
||||
permission_required = ("agenda_culturel.delete_place")
|
||||
success_url = reverse_lazy('view_places')
|
||||
|
||||
class UnknownPlacesListView(PermissionRequiredMixin, ListView):
|
||||
model = Event
|
||||
permission_required = ("agenda_culturel.add_place")
|
||||
paginate_by = 10
|
||||
template_name = 'agenda_culturel/place_unknown_list.html'
|
||||
queryset = Event.objects.filter(exact_location__isnull=True)
|
||||
|
||||
def fix_unknown_places(request):
|
||||
# get all places
|
||||
places = Place.objects.all()
|
||||
# get all events without exact location
|
||||
u_events = Event.objects.filter(exact_location__isnull=True)
|
||||
|
||||
to_be_updated = []
|
||||
# try to find matches
|
||||
for ue in u_events:
|
||||
for p in places:
|
||||
if p.match(ue):
|
||||
ue.exact_location = p
|
||||
to_be_updated.append(ue)
|
||||
continue
|
||||
# update events with a location
|
||||
Event.objects.bulk_update(to_be_updated, fields=["exact_location"])
|
||||
|
||||
# create a success message
|
||||
nb = len(to_be_updated)
|
||||
if nb > 1:
|
||||
messages.success(request, _("{} events have been updated.").format(nb))
|
||||
elif nb == 1:
|
||||
messages.success(request, _("1 event has been updated."))
|
||||
else:
|
||||
messages.info(request, _("No events have been modified."))
|
||||
|
||||
# come back to the list of places
|
||||
return HttpResponseRedirect(reverse_lazy("view_unknown_places"))
|
||||
|
||||
|
||||
class UnknownPlaceAddView(PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
|
||||
model = Event
|
||||
permission_required = ("agenda_culturel.change_place", "agenda_culturel.change_event")
|
||||
form_class = EventAddPlaceForm
|
||||
template_name = 'agenda_culturel/place_unknown_form.html'
|
||||
|
||||
def form_valid(self, form):
|
||||
self.modified_event = form.modified_event()
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_message(self, cleaned_data):
|
||||
msg = ""
|
||||
if cleaned_data.get("place"):
|
||||
msg += _('The selected place has been assigned to the event. ')
|
||||
if cleaned_data.get('add_alias'):
|
||||
msg += _('A new alias has been added to the selected place. ')
|
||||
return msg
|
||||
|
||||
def get_success_url(self):
|
||||
if self.modified_event:
|
||||
return reverse_lazy('view_unknown_places')
|
||||
else:
|
||||
return reverse_lazy('add_place_from_event', args=[self.object.pk])
|
||||
|
||||
|
||||
class PlaceFromEventCreateView(PlaceCreateView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["event"] = self.event
|
||||
return context
|
||||
|
||||
def get_initial(self, *args, **kwargs):
|
||||
initial = super().get_initial(**kwargs)
|
||||
self.event = get_object_or_404(Event, pk=self.kwargs['pk'])
|
||||
if self.event.location:
|
||||
initial['aliases'] = [self.event.location]
|
||||
return initial
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user