amélioration gestion des étiquettes:

- suppression des étiquettes: Fix #197
- renommage des étiquettes: Fix #200
This commit is contained in:
Jean-Marie Favreau 2024-11-17 22:52:19 +01:00
parent 1e9698da91
commit 47aedc706b
9 changed files with 381 additions and 110 deletions

View File

@ -40,6 +40,41 @@ import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class TagForm(ModelForm):
class Meta:
model = Tag
fields = ["name", "description", "in_included_suggestions", "in_excluded_suggestions", "principal", "category"]
widgets = {
"name": HiddenInput()
}
class TagRenameForm(Form):
name = CharField(
label=_('Name of new tag'),
required=True
)
force = BooleanField(
label=_('Force renaming despite the existence of events already using the chosen tag.'),
)
def __init__(self, *args, **kwargs):
force = kwargs.pop("force", False)
name = kwargs.pop("name", None)
super().__init__(*args, **kwargs)
if not (force or (not len(args) == 0 and 'force' in args[0])):
logger.warning('on delete ' + str(args))
del self.fields["force"]
else:
logger.warning('on delete pas')
if not name is None and self.fields["name"].initial is None:
self.fields["name"].initial = name
def is_force(self):
logger.warning(self.cleaned_data)
return "force" in self.fields and self.cleaned_data["force"] == True
class URLSubmissionForm(Form): class URLSubmissionForm(Form):
url = URLField(max_length=512) url = URLField(max_length=512)
category = ModelChoiceField( category = ModelChoiceField(

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: agenda_culturel\n" "Project-Id-Version: agenda_culturel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-17 14:11+0100\n" "POT-Creation-Date: 2024-11-17 22:38+0100\n"
"PO-Revision-Date: 2023-10-29 14:16+0000\n" "PO-Revision-Date: 2023-10-29 14:16+0000\n"
"Last-Translator: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n" "Last-Translator: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n"
"Language-Team: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n" "Language-Team: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n"
@ -90,63 +90,74 @@ msgstr "Après-midi"
msgid "Evening" msgid "Evening"
msgstr "Soir" msgstr "Soir"
#: agenda_culturel/filters.py:60 #: agenda_culturel/filters.py:63
msgid "Select a location" msgid "Select a location"
msgstr "Choisir une localité" msgstr "Choisir une localité"
#: agenda_culturel/filters.py:318 #: agenda_culturel/filters.py:321
msgid "Representative version" msgid "Representative version"
msgstr "Version représentative" msgstr "Version représentative"
#: agenda_culturel/filters.py:319 #: agenda_culturel/filters.py:322
msgid "Yes" msgid "Yes"
msgstr "Oui" msgstr "Oui"
#: agenda_culturel/filters.py:319 #: agenda_culturel/filters.py:322
msgid "Non" msgid "Non"
msgstr "Non" msgstr "Non"
#: agenda_culturel/filters.py:324 #: agenda_culturel/filters.py:327
msgid "Imported from" msgid "Imported from"
msgstr "Importé depuis" msgstr "Importé depuis"
#: agenda_culturel/filters.py:354 agenda_culturel/models.py:1564 #: agenda_culturel/filters.py:357 agenda_culturel/models.py:1564
msgid "Closed" msgid "Closed"
msgstr "Fermé" msgstr "Fermé"
#: agenda_culturel/filters.py:354 #: agenda_culturel/filters.py:357
msgid "Open" msgid "Open"
msgstr "Ouvert" msgstr "Ouvert"
#: agenda_culturel/filters.py:359 agenda_culturel/models.py:1558 #: agenda_culturel/filters.py:362 agenda_culturel/models.py:1558
msgid "Spam" msgid "Spam"
msgstr "Spam" msgstr "Spam"
#: agenda_culturel/filters.py:359 #: agenda_culturel/filters.py:362
msgid "Non spam" msgid "Non spam"
msgstr "Non spam" msgstr "Non spam"
#: agenda_culturel/filters.py:370 #: agenda_culturel/filters.py:373
msgid "Search" msgid "Search"
msgstr "Rechercher" msgstr "Rechercher"
#: agenda_culturel/forms.py:46 agenda_culturel/models.py:169 #: agenda_culturel/forms.py:53
msgid "Name of new tag"
msgstr "Nom de la nouvelle étiquette"
#: agenda_culturel/forms.py:58
msgid ""
"Force renaming despite the existence of events already using the chosen tag."
msgstr ""
"Forcer le renommage malgré l'existence d'événements utilisant déjà "
"l'étiquette choisie."
#: agenda_culturel/forms.py:81 agenda_culturel/models.py:169
#: agenda_culturel/models.py:207 agenda_culturel/models.py:508 #: agenda_culturel/models.py:207 agenda_culturel/models.py:508
#: agenda_culturel/models.py:1668 agenda_culturel/models.py:1773 #: agenda_culturel/models.py:1668 agenda_culturel/models.py:1773
msgid "Category" msgid "Category"
msgstr "Catégorie" msgstr "Catégorie"
#: agenda_culturel/forms.py:49 #: agenda_culturel/forms.py:84
msgid "Optional. If you dont specify a category, well find it for you." msgid "Optional. If you dont specify a category, well find it for you."
msgstr "" msgstr ""
"Facultatif. Si tu ne donnes pas la catégorie, on s'occupe de la trouver." "Facultatif. Si tu ne donnes pas la catégorie, on s'occupe de la trouver."
#: agenda_culturel/forms.py:53 agenda_culturel/forms.py:94 #: agenda_culturel/forms.py:88 agenda_culturel/forms.py:129
#: agenda_culturel/forms.py:193 agenda_culturel/models.py:614 #: agenda_culturel/forms.py:228 agenda_culturel/models.py:614
msgid "Tags" msgid "Tags"
msgstr "Étiquettes" msgstr "Étiquettes"
#: agenda_culturel/forms.py:56 agenda_culturel/forms.py:97 #: agenda_culturel/forms.py:91 agenda_culturel/forms.py:132
msgid "" msgid ""
"Optional. If you offer labels, theyll make it easier for your girlfriends to " "Optional. If you offer labels, theyll make it easier for your girlfriends to "
"find your event." "find your event."
@ -154,90 +165,90 @@ msgstr ""
"Facultatif. Si tu proposes des étiquettes, ça aidera les copaines à " "Facultatif. Si tu proposes des étiquettes, ça aidera les copaines à "
"retrouver facilement ton événement." "retrouver facilement ton événement."
#: agenda_culturel/forms.py:152 #: agenda_culturel/forms.py:187
msgid "The end date must be after the start date." msgid "The end date must be after the start date."
msgstr "La date de fin doit être après la date de début." msgstr "La date de fin doit être après la date de début."
#: agenda_culturel/forms.py:168 #: agenda_culturel/forms.py:203
msgid "The end time cannot be earlier than the start time." msgid "The end time cannot be earlier than the start time."
msgstr "L'heure de fin ne peut pas être avant l'heure de début." msgstr "L'heure de fin ne peut pas être avant l'heure de début."
#: agenda_culturel/forms.py:194 #: agenda_culturel/forms.py:229
msgid "Select tags from existing ones." msgid "Select tags from existing ones."
msgstr "Sélectionner des étiquettes depuis celles existantes." msgstr "Sélectionner des étiquettes depuis celles existantes."
#: agenda_culturel/forms.py:199 #: agenda_culturel/forms.py:234
msgid "New tags" msgid "New tags"
msgstr "Nouvelles étiquettes" msgstr "Nouvelles étiquettes"
#: agenda_culturel/forms.py:200 #: agenda_culturel/forms.py:235
msgid "Create new labels (sparingly)." msgid "Create new labels (sparingly)."
msgstr "Créer (avec parcimonie) de nouvelles étiquettes." msgstr "Créer (avec parcimonie) de nouvelles étiquettes."
#: agenda_culturel/forms.py:240 #: agenda_culturel/forms.py:275
msgid "JSON in the format expected for the import." msgid "JSON in the format expected for the import."
msgstr "JSON dans le format attendu pour l'import" msgstr "JSON dans le format attendu pour l'import"
#: agenda_culturel/forms.py:260 #: agenda_culturel/forms.py:295
msgid " (locally modified version)" msgid " (locally modified version)"
msgstr " (version modifiée localement)" msgstr " (version modifiée localement)"
#: agenda_culturel/forms.py:264 #: agenda_culturel/forms.py:299
msgid " (synchronized on import version)" msgid " (synchronized on import version)"
msgstr " (version synchronisée sur l'import)" msgstr " (version synchronisée sur l'import)"
#: agenda_culturel/forms.py:268 #: agenda_culturel/forms.py:303
msgid "Select {} as representative version." msgid "Select {} as representative version."
msgstr "Sélectionner {} comme version représentative" msgstr "Sélectionner {} comme version représentative"
#: agenda_culturel/forms.py:277 #: agenda_culturel/forms.py:312
msgid "Update {} using some fields from other versions (interactive mode)." msgid "Update {} using some fields from other versions (interactive mode)."
msgstr "" msgstr ""
"Mettre à jour {} en utilisant quelques champs des autres versions (mode " "Mettre à jour {} en utilisant quelques champs des autres versions (mode "
"interactif)." "interactif)."
#: agenda_culturel/forms.py:284 #: agenda_culturel/forms.py:319
msgid " Warning: a version is already locally modified." msgid " Warning: a version is already locally modified."
msgstr " Attention: une version a déjà été modifiée localement." msgstr " Attention: une version a déjà été modifiée localement."
#: agenda_culturel/forms.py:289 #: agenda_culturel/forms.py:324
msgid "Create a new version by merging (interactive mode)." msgid "Create a new version by merging (interactive mode)."
msgstr "Créer une nouvelle version par fusion (mode interactif)." msgstr "Créer une nouvelle version par fusion (mode interactif)."
#: agenda_culturel/forms.py:296 #: agenda_culturel/forms.py:331
msgid "Make {} independent." msgid "Make {} independent."
msgstr "Rendre {} indépendant." msgstr "Rendre {} indépendant."
#: agenda_culturel/forms.py:298 #: agenda_culturel/forms.py:333
msgid "Make all versions independent." msgid "Make all versions independent."
msgstr "Rendre toutes les versions indépendantes." msgstr "Rendre toutes les versions indépendantes."
#: agenda_culturel/forms.py:353 #: agenda_culturel/forms.py:388
msgid "Value of the selected version" msgid "Value of the selected version"
msgstr "Valeur de la version sélectionnée" msgstr "Valeur de la version sélectionnée"
#: agenda_culturel/forms.py:355 agenda_culturel/forms.py:359 #: agenda_culturel/forms.py:390 agenda_culturel/forms.py:394
msgid "Value of version {}" msgid "Value of version {}"
msgstr "Valeur de la version {}" msgstr "Valeur de la version {}"
#: agenda_culturel/forms.py:506 #: agenda_culturel/forms.py:541
msgid "Apply category {} to the event {}" msgid "Apply category {} to the event {}"
msgstr "Appliquer la catégorie {} à l'événement {}" msgstr "Appliquer la catégorie {} à l'événement {}"
#: agenda_culturel/forms.py:521 agenda_culturel/models.py:432 #: agenda_culturel/forms.py:556 agenda_culturel/models.py:432
#: agenda_culturel/models.py:1825 #: agenda_culturel/models.py:1825
msgid "Place" msgid "Place"
msgstr "Lieu" msgstr "Lieu"
#: agenda_culturel/forms.py:523 #: agenda_culturel/forms.py:558
msgid "Create a missing place" msgid "Create a missing place"
msgstr "Créer un lieu manquant" msgstr "Créer un lieu manquant"
#: agenda_culturel/forms.py:533 #: agenda_culturel/forms.py:568
msgid "Add \"{}\" to the aliases of the place" msgid "Add \"{}\" to the aliases of the place"
msgstr "Ajouter « {} » aux alias du lieu" msgstr "Ajouter « {} » aux alias du lieu"
#: agenda_culturel/forms.py:560 #: agenda_culturel/forms.py:595
msgid "On saving, use aliases to detect all matching events with missing place" msgid "On saving, use aliases to detect all matching events with missing place"
msgstr "" msgstr ""
"Lors de l'enregistrement, utiliser des alias pour détecter tous les " "Lors de l'enregistrement, utiliser des alias pour détecter tous les "
@ -378,7 +389,9 @@ msgstr "Principale"
#: agenda_culturel/models.py:398 #: agenda_culturel/models.py:398
msgid "This location is one of the main locations (shown first higher values)." msgid "This location is one of the main locations (shown first higher values)."
msgstr "Cette position est une position principale (affichage en premier des plus grandes valeurs)." msgstr ""
"Cette position est une position principale (affichage en premier des plus "
"grandes valeurs)."
#: agenda_culturel/models.py:403 #: agenda_culturel/models.py:403
msgid "Reference location" msgid "Reference location"
@ -894,27 +907,27 @@ msgstr "anglais"
msgid "French" msgid "French"
msgstr "français" msgstr "français"
#: agenda_culturel/views.py:141 #: agenda_culturel/views.py:143
msgid "Recurrent import name" msgid "Recurrent import name"
msgstr "Nome de l'import récurrent" msgstr "Nome de l'import récurrent"
#: agenda_culturel/views.py:142 #: agenda_culturel/views.py:144
msgid "Add another" msgid "Add another"
msgstr "Ajouter un autre" msgstr "Ajouter un autre"
#: agenda_culturel/views.py:143 #: agenda_culturel/views.py:145
msgid "Browse..." msgid "Browse..."
msgstr "Naviguer..." msgstr "Naviguer..."
#: agenda_culturel/views.py:144 #: agenda_culturel/views.py:146
msgid "No file selected." msgid "No file selected."
msgstr "Pas de fichier sélectionné." msgstr "Pas de fichier sélectionné."
#: agenda_culturel/views.py:280 #: agenda_culturel/views.py:282
msgid "The static content has been successfully updated." msgid "The static content has been successfully updated."
msgstr "Le contenu statique a été modifié avec succès." msgstr "Le contenu statique a été modifié avec succès."
#: agenda_culturel/views.py:288 #: agenda_culturel/views.py:290
msgid "" msgid ""
"The event cannot be updated because the import process is not available for " "The event cannot be updated because the import process is not available for "
"the referenced sources." "the referenced sources."
@ -922,33 +935,33 @@ msgstr ""
"La mise à jour de l'événement n'est pas possible car le processus d'import " "La mise à jour de l'événement n'est pas possible car le processus d'import "
"n'est pas disponible pour les sources référencées." "n'est pas disponible pour les sources référencées."
#: agenda_culturel/views.py:291 #: agenda_culturel/views.py:293
msgid "The event update has been queued and will be completed shortly." msgid "The event update has been queued and will be completed shortly."
msgstr "" msgstr ""
"La mise à jour de l'événement a été mise en attente et sera effectuée sous " "La mise à jour de l'événement a été mise en attente et sera effectuée sous "
"peu." "peu."
#: agenda_culturel/views.py:301 #: agenda_culturel/views.py:303
msgid "The event has been successfully modified." msgid "The event has been successfully modified."
msgstr "L'événement a été modifié avec succès." msgstr "L'événement a été modifié avec succès."
#: agenda_culturel/views.py:345 #: agenda_culturel/views.py:347
msgid "The event has been successfully moderated." msgid "The event has been successfully moderated."
msgstr "L'événement a été modéré avec succès." msgstr "L'événement a été modéré avec succès."
#: agenda_culturel/views.py:433 #: agenda_culturel/views.py:435
msgid "The event has been successfully deleted." msgid "The event has been successfully deleted."
msgstr "L'événement a été supprimé avec succès." msgstr "L'événement a été supprimé avec succès."
#: agenda_culturel/views.py:465 #: agenda_culturel/views.py:467
msgid "The status has been successfully modified." msgid "The status has been successfully modified."
msgstr "Le status a été modifié avec succès." msgstr "Le status a été modifié avec succès."
#: agenda_culturel/views.py:501 #: agenda_culturel/views.py:503
msgid "The event was created: <a href=\"{}\">{}</a>." msgid "The event was created: <a href=\"{}\">{}</a>."
msgstr "L'événement a été créé: <a href=\"{}\">{}</a>." msgstr "L'événement a été créé: <a href=\"{}\">{}</a>."
#: agenda_culturel/views.py:503 agenda_culturel/views.py:517 #: agenda_culturel/views.py:505 agenda_culturel/views.py:519
msgid "" msgid ""
"The event has been submitted and will be published as soon as it has been " "The event has been submitted and will be published as soon as it has been "
"validated by the moderation team." "validated by the moderation team."
@ -956,82 +969,82 @@ msgstr ""
"L'événement a été soumis et sera publié dès qu'il aura été validé par " "L'événement a été soumis et sera publié dès qu'il aura été validé par "
"l'équipe de modération." "l'équipe de modération."
#: agenda_culturel/views.py:511 #: agenda_culturel/views.py:513
msgid "The event is saved." msgid "The event is saved."
msgstr "L'événement est enregistré." msgstr "L'événement est enregistré."
#: agenda_culturel/views.py:605 agenda_culturel/views.py:657 #: agenda_culturel/views.py:607 agenda_culturel/views.py:659
msgid "{} has not been submitted since its already known: {}." msgid "{} has not been submitted since its already known: {}."
msgstr "{} n'a pas été soumis car il est déjà connu: {}." msgstr "{} n'a pas été soumis car il est déjà connu: {}."
#: agenda_culturel/views.py:610 agenda_culturel/views.py:663 #: agenda_culturel/views.py:612 agenda_culturel/views.py:665
msgid "" msgid ""
"{} has not been submitted since its already known and currently into " "{} has not been submitted since its already known and currently into "
"moderation process." "moderation process."
msgstr "{} n'a pas été soumis car il est déjà connu et en cours de modération" msgstr "{} n'a pas été soumis car il est déjà connu et en cours de modération"
#: agenda_culturel/views.py:620 #: agenda_culturel/views.py:622
msgid "Integrating {} url(s) into our import process." msgid "Integrating {} url(s) into our import process."
msgstr "Intégration de {} url(s) dans notre processus d'import." msgstr "Intégration de {} url(s) dans notre processus d'import."
#: agenda_culturel/views.py:670 #: agenda_culturel/views.py:672
msgid "Integrating {} into our import process." msgid "Integrating {} into our import process."
msgstr "Intégration de {} dans notre processus d'import." msgstr "Intégration de {} dans notre processus d'import."
#: agenda_culturel/views.py:725 #: agenda_culturel/views.py:727
msgid "Your message has been sent successfully." msgid "Your message has been sent successfully."
msgstr "Votre message a été envoyé avec succès." msgstr "Votre message a été envoyé avec succès."
#: agenda_culturel/views.py:735 #: agenda_culturel/views.py:737
msgid "The contact message has been successfully deleted." msgid "The contact message has been successfully deleted."
msgstr "Le message de contact a été supprimé avec succès." msgstr "Le message de contact a été supprimé avec succès."
#: agenda_culturel/views.py:749 #: agenda_culturel/views.py:751
msgid "The contact message properties has been successfully modified." msgid "The contact message properties has been successfully modified."
msgstr "Les propriétés du message de contact ont été modifié avec succès." msgstr "Les propriétés du message de contact ont été modifié avec succès."
#: agenda_culturel/views.py:886 #: agenda_culturel/views.py:888
msgid "Spam has been successfully deleted." msgid "Spam has been successfully deleted."
msgstr "Le spam a été supprimé avec succès" msgstr "Le spam a été supprimé avec succès"
#: agenda_culturel/views.py:998 #: agenda_culturel/views.py:1000
msgid "The import has been run successfully." msgid "The import has been run successfully."
msgstr "L'import a été lancé avec succès" msgstr "L'import a été lancé avec succès"
#: agenda_culturel/views.py:1017 #: agenda_culturel/views.py:1019
msgid "The import has been canceled." msgid "The import has been canceled."
msgstr "L'import a été annulé" msgstr "L'import a été annulé"
#: agenda_culturel/views.py:1091 #: agenda_culturel/views.py:1093
msgid "The recurrent import has been successfully modified." msgid "The recurrent import has been successfully modified."
msgstr "L'import récurrent a été modifié avec succès." msgstr "L'import récurrent a été modifié avec succès."
#: agenda_culturel/views.py:1100 #: agenda_culturel/views.py:1102
msgid "The recurrent import has been successfully deleted." msgid "The recurrent import has been successfully deleted."
msgstr "L'import récurrent a été supprimé avec succès" msgstr "L'import récurrent a été supprimé avec succès"
#: agenda_culturel/views.py:1140 #: agenda_culturel/views.py:1142
msgid "The import has been launched." msgid "The import has been launched."
msgstr "L'import a été lancé" msgstr "L'import a été lancé"
#: agenda_culturel/views.py:1162 #: agenda_culturel/views.py:1164
msgid "Imports has been launched." msgid "Imports has been launched."
msgstr "Les imports ont été lancés" msgstr "Les imports ont été lancés"
#: agenda_culturel/views.py:1221 #: agenda_culturel/views.py:1223
msgid "Update successfully completed." msgid "Update successfully completed."
msgstr "Mise à jour réalisée avec succès." msgstr "Mise à jour réalisée avec succès."
#: agenda_culturel/views.py:1279 #: agenda_culturel/views.py:1281
msgid "Creation of a merged event has been successfully completed." msgid "Creation of a merged event has been successfully completed."
msgstr "Création d'un événement fusionné réalisée avec succès." msgstr "Création d'un événement fusionné réalisée avec succès."
#: agenda_culturel/views.py:1315 #: agenda_culturel/views.py:1317
msgid "Events have been marked as unduplicated." msgid "Events have been marked as unduplicated."
msgstr "Les événements ont été marqués comme non dupliqués." msgstr "Les événements ont été marqués comme non dupliqués."
#: agenda_culturel/views.py:1329 agenda_culturel/views.py:1338 #: agenda_culturel/views.py:1331 agenda_culturel/views.py:1340
#: agenda_culturel/views.py:1356 #: agenda_culturel/views.py:1358
msgid "" msgid ""
"The selected item is no longer included in the list of duplicates. Someone " "The selected item is no longer included in the list of duplicates. Someone "
"else has probably modified the list in the meantime." "else has probably modified the list in the meantime."
@ -1039,23 +1052,23 @@ msgstr ""
"L'élément sélectionné ne fait plus partie de la liste des dupliqués. Une " "L'élément sélectionné ne fait plus partie de la liste des dupliqués. Une "
"autre personne a probablement modifié la liste entre temps." "autre personne a probablement modifié la liste entre temps."
#: agenda_culturel/views.py:1332 #: agenda_culturel/views.py:1334
msgid "The selected event has been set as representative" msgid "The selected event has been set as representative"
msgstr "L'événement sélectionné a été défini comme representatif." msgstr "L'événement sélectionné a été défini comme representatif."
#: agenda_culturel/views.py:1347 #: agenda_culturel/views.py:1349
msgid "The event has been withdrawn from the group and made independent." 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." msgstr "L'événement a été retiré du groupe et rendu indépendant."
#: agenda_culturel/views.py:1391 #: agenda_culturel/views.py:1393
msgid "Cleaning up duplicates: {} item(s) fixed." msgid "Cleaning up duplicates: {} item(s) fixed."
msgstr "Nettoyage des dupliqués: {} élément(s) corrigé(s)." msgstr "Nettoyage des dupliqués: {} élément(s) corrigé(s)."
#: agenda_culturel/views.py:1440 #: agenda_culturel/views.py:1442
msgid "The event was successfully duplicated." msgid "The event was successfully duplicated."
msgstr "L'événement a été marqué dupliqué avec succès." msgstr "L'événement a été marqué dupliqué avec succès."
#: agenda_culturel/views.py:1448 #: agenda_culturel/views.py:1450
msgid "" msgid ""
"The event has been successfully flagged as a duplicate. The moderation team " "The event has been successfully flagged as a duplicate. The moderation team "
"will deal with your suggestion shortly." "will deal with your suggestion shortly."
@ -1063,32 +1076,32 @@ msgstr ""
"L'événement a été signalé comme dupliqué avec succès. Votre suggestion sera " "L'événement a été signalé comme dupliqué avec succès. Votre suggestion sera "
"prochainement prise en charge par l'équipe de modération." "prochainement prise en charge par l'équipe de modération."
#: agenda_culturel/views.py:1501 #: agenda_culturel/views.py:1503
msgid "The categorisation rule has been successfully modified." msgid "The categorisation rule has been successfully modified."
msgstr "La règle de catégorisation a été modifiée avec succès." msgstr "La règle de catégorisation a été modifiée avec succès."
#: agenda_culturel/views.py:1510 #: agenda_culturel/views.py:1512
msgid "The categorisation rule has been successfully deleted." msgid "The categorisation rule has been successfully deleted."
msgstr "La règle de catégorisation a été supprimée avec succès" msgstr "La règle de catégorisation a été supprimée avec succès"
#: agenda_culturel/views.py:1532 #: agenda_culturel/views.py:1534
msgid "The rules were successfully applied and 1 event was categorised." msgid "The rules were successfully applied and 1 event was categorised."
msgstr "" msgstr ""
"Les règles ont été appliquées avec succès et 1 événement a été catégorisé" "Les règles ont été appliquées avec succès et 1 événement a été catégorisé"
#: agenda_culturel/views.py:1539 #: agenda_culturel/views.py:1541
msgid "The rules were successfully applied and {} events were categorised." msgid "The rules were successfully applied and {} events were categorised."
msgstr "" msgstr ""
"Les règles ont été appliquées avec succès et {} événements ont été " "Les règles ont été appliquées avec succès et {} événements ont été "
"catégorisés" "catégorisés"
#: agenda_culturel/views.py:1546 agenda_culturel/views.py:1599 #: agenda_culturel/views.py:1548 agenda_culturel/views.py:1601
msgid "The rules were successfully applied and no events were categorised." msgid "The rules were successfully applied and no events were categorised."
msgstr "" msgstr ""
"Les règles ont été appliquées avec succès et aucun événement n'a été " "Les règles ont été appliquées avec succès et aucun événement n'a été "
"catégorisé" "catégorisé"
#: agenda_culturel/views.py:1585 #: agenda_culturel/views.py:1587
msgid "" msgid ""
"The rules were successfully applied and 1 event with default category was " "The rules were successfully applied and 1 event with default category was "
"categorised." "categorised."
@ -1096,7 +1109,7 @@ msgstr ""
"Les règles ont été appliquées avec succès et 1 événement avec catégorie par " "Les règles ont été appliquées avec succès et 1 événement avec catégorie par "
"défaut a été catégorisé" "défaut a été catégorisé"
#: agenda_culturel/views.py:1592 #: agenda_culturel/views.py:1594
msgid "" msgid ""
"The rules were successfully applied and {} events with default category were " "The rules were successfully applied and {} events with default category were "
"categorised." "categorised."
@ -1104,41 +1117,70 @@ msgstr ""
"Les règles ont été appliquées avec succès et {} événements avec catégorie " "Les règles ont été appliquées avec succès et {} événements avec catégorie "
"par défaut ont été catégorisés" "par défaut ont été catégorisés"
#: agenda_culturel/views.py:1681 agenda_culturel/views.py:1743 #: agenda_culturel/views.py:1683 agenda_culturel/views.py:1745
#: agenda_culturel/views.py:1781 #: agenda_culturel/views.py:1783
msgid "{} events have been updated." msgid "{} events have been updated."
msgstr "{} événements ont été mis à jour." msgstr "{} événements ont été mis à jour."
#: agenda_culturel/views.py:1684 agenda_culturel/views.py:1745 #: agenda_culturel/views.py:1686 agenda_culturel/views.py:1747
#: agenda_culturel/views.py:1784 #: agenda_culturel/views.py:1786
msgid "1 event has been updated." msgid "1 event has been updated."
msgstr "1 événement a été mis à jour" msgstr "1 événement a été mis à jour"
#: agenda_culturel/views.py:1686 agenda_culturel/views.py:1747 #: agenda_culturel/views.py:1688 agenda_culturel/views.py:1749
#: agenda_culturel/views.py:1786 #: agenda_culturel/views.py:1788
msgid "No events have been modified." msgid "No events have been modified."
msgstr "Aucun événement n'a été modifié." msgstr "Aucun événement n'a été modifié."
#: agenda_culturel/views.py:1695 #: agenda_culturel/views.py:1697
msgid "The place has been successfully updated." msgid "The place has been successfully updated."
msgstr "Le lieu a été modifié avec succès." msgstr "Le lieu a été modifié avec succès."
#: agenda_culturel/views.py:1704 #: agenda_culturel/views.py:1706
msgid "The place has been successfully created." msgid "The place has been successfully created."
msgstr "Le lieu a été créé avec succès." msgstr "Le lieu a été créé avec succès."
#: agenda_culturel/views.py:1769 #: agenda_culturel/views.py:1771
msgid "The selected place has been assigned to the event." msgid "The selected place has been assigned to the event."
msgstr "Le lieu sélectionné a été assigné à l'événement." msgstr "Le lieu sélectionné a été assigné à l'événement."
#: agenda_culturel/views.py:1773 #: agenda_culturel/views.py:1775
msgid "A new alias has been added to the selected place." msgid "A new alias has been added to the selected place."
msgstr "Un nouvel alias a été créé pour le lieu sélectionné." msgstr "Un nouvel alias a été créé pour le lieu sélectionné."
#: agenda_culturel/views.py:1829 #: agenda_culturel/views.py:1831
msgid "The tag has been successfully updated." msgid "The tag has been successfully updated."
msgstr "L'étiquette a été modifiée avec succès." msgstr "L'étiquette a été modifiée avec succès."
#: agenda_culturel/views.py:1836 #: agenda_culturel/views.py:1838
msgid "The tag has been successfully created." msgid "The tag has been successfully created."
msgstr "L'étiquette a été créée avec succès." msgstr "L'étiquette a été créée avec succès."
#: agenda_culturel/views.py:1901
msgid "You have not modified the tag name."
msgstr "Vous n'avez pas modifié le nom de l'étiquette."
#: agenda_culturel/views.py:1911
msgid ""
"This tag {} is already in use, and is described by different information "
"from the current tag. You can force renaming by checking the corresponding "
"option. The information associated with tag {} will be deleted, and all "
"events associated with tag {} will be associated with tag {}."
msgstr ""
"Cette étiquette {} est déjà utilisée, et est décrite par des informations "
"différentes de l'étiquette courante. Vous pouvez forcer le renommage en "
"cochant l'option correspondante. L'information associée à l'étiquette {} "
"sera supprimée, et tous les événements associés à l'étiquette {} seront "
"associés à l'étiquette {}."
#: agenda_culturel/views.py:1918
msgid ""
"This tag {} is already in use. You can force renaming by checking the "
"corresponding option."
msgstr ""
"Cette étiquette {} est déjà utilisée. Vous pouvez forcer le renommage en "
"cochant l'option correspondante."
#: agenda_culturel/views.py:1941
msgid "The tag {} has been successfully renamed to {}."
msgstr "L'étiquette {} a été renommée avec succès en {}."

View File

@ -549,6 +549,12 @@ article#filters {
font-size: 100%; font-size: 100%;
} }
} }
.helptext {
display: block;
margin-top: 0;
}
header .remarque { header .remarque {
font-style: italic; font-style: italic;
} }
@ -567,6 +573,8 @@ header .remarque {
.slide-buttons { .slide-buttons {
float: right; float: right;
max-width: 30em;
text-align: right;
} }
.left-buttons { .left-buttons {
display: inline-block; display: inline-block;

View File

@ -3,6 +3,7 @@
{% block title %}{% block og_title %}Les événements {{ tag }}{% endblock %}{% endblock %} {% block title %}{% block og_title %}Les événements {{ tag }}{% endblock %}{% endblock %}
{% load cat_extra %} {% load cat_extra %}
{% load utils_extra %}
{% block fluid %}{% endblock %} {% block fluid %}{% endblock %}
@ -16,21 +17,28 @@
{% block content %} {% block content %}
<article> <article>
<header> <header>
<a href="{% url 'view_all_tags' %}" role="button">&lt; Toutes les étiquettes</a>
<div class="slide-buttons"> <div class="slide-buttons">
{% if object %} {% if object %}
{% if perms.agenda_culturel.change_tag %} {% if perms.agenda_culturel.change_tag %}
<a href="{% url 'edit_tag' object.pk %}" role="button">Modifier</a> <a href="{% url 'edit_tag' object.pk %}" role="button">Modifier {% picto_from_name "edit" %}</a>
{% endif %} {% endif %}
{% if perms.agenda_culturel.delete_tag %} {% if perms.agenda_culturel.delete_tag %}
<a href="{% url 'delete_tag' object.pk %}" role="button">Supprimer les informations</a> <a href="{% url 'delete_object_tag' object.pk %}" role="button">Supprimer les informations {% picto_from_name "trash-2" %}</a>
{% endif %} {% endif %}
{% else %} {% else %}
{% if perms.agenda_culturel.add_tag %} {% if perms.agenda_culturel.add_tag %}
<a href="{% url 'add_tag' %}?name={{ tag|urlencode }}" role="button">Renseigner l'étiquette</a> <a href="{% url 'add_tag' %}?name={{ tag|urlencode }}" role="button">Renseigner {% picto_from_name "edit" %}</a>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if perms.agenda_culturel.change_tag %}
<a href="{% url 'rename_tag' tag %}" role="button">Renommer {% picto_from_name "edit-3" %}</a>
<a href="{% url 'delete_tag' tag %}" role="button">Supprimer {% picto_from_name "trash-2" %}</a>
{% endif %}
</div> </div>
<h1>Les événements <em>{{ tag }}</em></h1> <h1>Les événements <em>{{ tag }}</em></h1>
{% if user.is_authenticated and object %} {% if user.is_authenticated and object %}
{% if object.in_excluded_suggestions %} {% if object.in_excluded_suggestions %}
<p class="remarque">Cette étiquette fait partie des étiquettes suggérées pour l'exclusion.</p> <p class="remarque">Cette étiquette fait partie des étiquettes suggérées pour l'exclusion.</p>
@ -42,6 +50,7 @@
<p class="remarque">Cette étiquette fait partie des étiquettes principales mises en avant.</p> <p class="remarque">Cette étiquette fait partie des étiquettes principales mises en avant.</p>
{% endif %} {% endif %}
{% endif %} {% endif %}
<div style="clear: both;"></div>
</header> </header>

View File

@ -0,0 +1,35 @@
{% extends "agenda_culturel/page.html" %}
{% block title %}{% block og_title %}Suppression de l'étiquette {{ tag }}{% endblock %}{% endblock %}
{% block fluid %}{% endblock %}
{% block configurer-bouton %}{% endblock %}
{% block content %}
<article>
<header>
<h1>Suppression de l'étiquette {{ yag }}</h1>
</header>
<form method="post">{% csrf_token %}
<p>Êtes-vous sûr·e de vouloir supprimer l'étiquette «&nbsp;{{ tag }}&nbsp;»&nbsp;?</p>
{% if nb > 0 %}
<p>Remarquez qu'elle est associée à {{ nb }} événement{{ nb|pluralize }}, qui
{% if nb > 1 %} seront bien sûr conservés, mais perdront cette étiquette.
{% else %} sera bien sûr conservé, mais perdra cette étiquette.
{% endif %}</p>
{% endif %}
{% if obj %}
<p>Différentes informations sont associées à cette étiquette (description, suggestion d'inclusion, etc)
seront également perdues lors de cette suppression.</p>
{% endif %}
{{ 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>
<input type="submit" value="Confirmer">
</div>
</form>
</article>
{% endblock %}

View File

@ -8,15 +8,17 @@
<script>window.CKEDITOR_BASEPATH = '/static/ckeditor/ckeditor/';</script> <script>window.CKEDITOR_BASEPATH = '/static/ckeditor/ckeditor/';</script>
{% endblock %} {% endblock %}
{% block title %}{% block og_title %}Renseignement d'une étiquette{% endblock %}{% endblock %} {% block title %}{% block og_title %}Renseignement de l'étiquette {{ form.name.value }}{% endblock %}{% endblock %}
{% block fluid %}{% endblock %} {% block fluid %}{% endblock %}
{% block content %} {% block content %}
<h1>Renseignement d'une étiquette</h1>
<article> <article>
<header>
<h1>Renseignement de l'étiquette <em>{{ form.name.value }}</em></h1>
</header>
<form method="post">{% csrf_token %} <form method="post">{% csrf_token %}
{{ form.media }} {{ form.media }}
{{ form.as_p }} {{ form.as_p }}

View File

@ -0,0 +1,34 @@
{% extends "agenda_culturel/page-admin.html" %}
{% load static %}
{% 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>window.CKEDITOR_BASEPATH = '/static/ckeditor/ckeditor/';</script>
{% endblock %}
{% block title %}{% block og_title %}Renommer l'étiquette {{ tag }}{% endblock %}{% endblock %}
{% block fluid %}{% endblock %}
{% block content %}
<article>
<header>
<h1>Renommer l'étiquette {{ tag }}</em></h1>
<p>En renommant l'étiquette {{ tag }}, vous remplacerez cette étiquette par la nouvelle pour tous les événements concernés.</p>
</header>
<form method="post">{% csrf_token %}
{{ form.media }}
{{ form.as_p }}
<div class="grid buttons">
<a href="{% url 'view_tag' tag %}" role="button" class="secondary">Annuler</a>
<input type="submit" value="Envoyer">
</div>
</form>
</article>
{% endblock %}

View File

@ -21,7 +21,9 @@ urlpatterns = [
path("tag/<t>/", view_tag, name="view_tag"), path("tag/<t>/", view_tag, name="view_tag"),
path("tags/", tag_list, name="view_all_tags"), path("tags/", tag_list, name="view_all_tags"),
path("tag/<int:pk>/edit", TagUpdateView.as_view(), name="edit_tag"), path("tag/<int:pk>/edit", TagUpdateView.as_view(), name="edit_tag"),
path("tag/<int:pk>/delete", TagDeleteView.as_view(), name="delete_tag"), path("tag/<int:pk>/delete", TagDeleteView.as_view(), name="delete_object_tag"),
path("tag/<t>/rename", rename_tag, name="rename_tag"),
path("tag/<t>/delete", delete_tag, name="delete_tag"),
path("tags/add", TagCreateView.as_view(), name="add_tag"), path("tags/add", TagCreateView.as_view(), name="add_tag"),
path("recent/", recent, name="recent"), path("recent/", recent, name="recent"),
path("administration/", administration, name="administration"), path("administration/", administration, name="administration"),

View File

@ -33,7 +33,9 @@ from .forms import (
EventAddPlaceForm, EventAddPlaceForm,
PlaceForm, PlaceForm,
MultipleHiddenInput, MultipleHiddenInput,
EventModerateForm EventModerateForm,
TagForm,
TagRenameForm
) )
from .filters import ( from .filters import (
@ -1825,14 +1827,14 @@ class PlaceFromEventCreateView(PlaceCreateView):
class TagUpdateView(PermissionRequiredMixin, SuccessMessageMixin, UpdateView): class TagUpdateView(PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
model = Tag model = Tag
permission_required = "agenda_culturel.change_tag" permission_required = "agenda_culturel.change_tag"
fields = ["name", "description", "principal", "category", "in_excluded_suggestions", "in_included_suggestions"] form_class = TagForm
success_message = _("The tag has been successfully updated.") success_message = _("The tag has been successfully updated.")
class TagCreateView(PermissionRequiredMixin, SuccessMessageMixin, CreateView): class TagCreateView(PermissionRequiredMixin, SuccessMessageMixin, CreateView):
model = Tag model = Tag
permission_required = "agenda_culturel.add_tag" permission_required = "agenda_culturel.add_tag"
fields = ["name", "description", "principal", "category", "in_excluded_suggestions", "in_included_suggestions"] form_class = TagForm
success_message = _("The tag has been successfully created.") success_message = _("The tag has been successfully created.")
def get_initial(self, *args, **kwargs): def get_initial(self, *args, **kwargs):
@ -1882,3 +1884,105 @@ def tag_list(request):
context = {"tags": sorted(tags, key=lambda x: remove_accents(x["tag"]).lower())} context = {"tags": sorted(tags, key=lambda x: remove_accents(x["tag"]).lower())}
return render(request, "agenda_culturel/tags.html", context) return render(request, "agenda_culturel/tags.html", context)
@login_required(login_url="/accounts/login/")
@permission_required("agenda_culturel.change_tag")
def rename_tag(request, t):
form = TagRenameForm(name=t)
force = False
if request.method == "POST":
form = TagRenameForm(request.POST, name=t)
if form.is_valid():
save = True
if form.cleaned_data["name"] == t:
messages.warning(
request,
_(
"You have not modified the tag name."
),
)
save = False
elif not form.is_force():
if Event.objects.filter(tags__contains=[form.cleaned_data["name"]]).count() > 0:
if Tag.objects.filter(name=form.cleaned_data["name"]):
messages.warning(
request,
(_(
"This tag {} is already in use, and is described by different information from the current tag. You can force renaming by checking the corresponding option. The information associated with tag {} will be deleted, and all events associated with tag {} will be associated with tag {}."
)).format(form.cleaned_data["name"], t, t, form.cleaned_data["name"]),
)
else:
messages.warning(
request,
(_(
"This tag {} is already in use. You can force renaming by checking the corresponding option."
)).format(form.cleaned_data["name"]),
)
save = False
form = TagRenameForm(request.POST, name=t, force=True)
if save:
# find all matching events and update them
events = Event.objects.filter(tags__contains=[t])
new_name = form.cleaned_data["name"]
for e in events:
e.tags = [te for te in e.tags if te != t]
if not new_name in e.tags:
e.tags += [new_name]
Event.objects.bulk_update(events, fields=["tags"])
# find tag object
tag_object = Tag.objects.filter(name=t).first()
if tag_object:
tag_object.delete()
messages.success(
request,
(_(
"The tag {} has been successfully renamed to {}."
)).format(t, form.cleaned_data["name"]),
)
return HttpResponseRedirect(reverse_lazy("view_tag", kwargs={"t": form.cleaned_data["name"]}))
nb = Event.objects.filter(tags__contains=[t]).count()
return render(
request, "agenda_culturel/tag_rename_form.html", context={"form": form, "tag": t, "nb": nb}
)
@login_required(login_url="/accounts/login/")
@permission_required("agenda_culturel.delete_tag")
def delete_tag(request, t):
respage = reverse_lazy("view_all_tags")
nb = Event.objects.filter(tags__contains=[t]).count()
obj = Tag.objects.filter(name=t).first()
if request.method == "POST":
# remove tag from events
events = Event.objects.filter(tags__contains=[t])
for e in events:
e.tags = [te for te in e.tags if te != t]
Event.objects.bulk_update(events, fields=["tags"])
# find tag object
tag_object = Tag.objects.filter(name=t).first()
if tag_object:
tag_object.delete()
messages.success(
request,
(_(
"The tag {} has been successfully deleted."
)).format(t),
)
return HttpResponseRedirect(respage)
else:
cancel_url = request.META.get("HTTP_REFERER", "")
if cancel_url == "":
cancel_url = respage
return render(
request,
"agenda_culturel/tag_confirm_delete_by_name.html",
{"tag": t, "nb": nb, "cancel_url": cancel_url, "obj": obj},
)