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__)
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):
url = URLField(max_length=512)
category = ModelChoiceField(

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: agenda_culturel\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"
"Last-Translator: 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"
msgstr "Soir"
#: agenda_culturel/filters.py:60
#: agenda_culturel/filters.py:63
msgid "Select a location"
msgstr "Choisir une localité"
#: agenda_culturel/filters.py:318
#: agenda_culturel/filters.py:321
msgid "Representative version"
msgstr "Version représentative"
#: agenda_culturel/filters.py:319
#: agenda_culturel/filters.py:322
msgid "Yes"
msgstr "Oui"
#: agenda_culturel/filters.py:319
#: agenda_culturel/filters.py:322
msgid "Non"
msgstr "Non"
#: agenda_culturel/filters.py:324
#: agenda_culturel/filters.py:327
msgid "Imported from"
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"
msgstr "Fermé"
#: agenda_culturel/filters.py:354
#: agenda_culturel/filters.py:357
msgid "Open"
msgstr "Ouvert"
#: agenda_culturel/filters.py:359 agenda_culturel/models.py:1558
#: agenda_culturel/filters.py:362 agenda_culturel/models.py:1558
msgid "Spam"
msgstr "Spam"
#: agenda_culturel/filters.py:359
#: agenda_culturel/filters.py:362
msgid "Non spam"
msgstr "Non spam"
#: agenda_culturel/filters.py:370
#: agenda_culturel/filters.py:373
msgid "Search"
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:1668 agenda_culturel/models.py:1773
msgid "Category"
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."
msgstr ""
"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:193 agenda_culturel/models.py:614
#: agenda_culturel/forms.py:88 agenda_culturel/forms.py:129
#: agenda_culturel/forms.py:228 agenda_culturel/models.py:614
msgid "Tags"
msgstr "Étiquettes"
#: agenda_culturel/forms.py:56 agenda_culturel/forms.py:97
#: agenda_culturel/forms.py:91 agenda_culturel/forms.py:132
msgid ""
"Optional. If you offer labels, theyll make it easier for your girlfriends to "
"find your event."
@ -154,90 +165,90 @@ msgstr ""
"Facultatif. Si tu proposes des étiquettes, ça aidera les copaines à "
"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."
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."
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."
msgstr "Sélectionner des étiquettes depuis celles existantes."
#: agenda_culturel/forms.py:199
#: agenda_culturel/forms.py:234
msgid "New tags"
msgstr "Nouvelles étiquettes"
#: agenda_culturel/forms.py:200
#: agenda_culturel/forms.py:235
msgid "Create new labels (sparingly)."
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."
msgstr "JSON dans le format attendu pour l'import"
#: agenda_culturel/forms.py:260
#: agenda_culturel/forms.py:295
msgid " (locally modified version)"
msgstr " (version modifiée localement)"
#: agenda_culturel/forms.py:264
#: agenda_culturel/forms.py:299
msgid " (synchronized on import version)"
msgstr " (version synchronisée sur l'import)"
#: agenda_culturel/forms.py:268
#: agenda_culturel/forms.py:303
msgid "Select {} as representative version."
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)."
msgstr ""
"Mettre à jour {} en utilisant quelques champs des autres versions (mode "
"interactif)."
#: agenda_culturel/forms.py:284
#: agenda_culturel/forms.py:319
msgid " Warning: a version is already locally modified."
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)."
msgstr "Créer une nouvelle version par fusion (mode interactif)."
#: agenda_culturel/forms.py:296
#: agenda_culturel/forms.py:331
msgid "Make {} independent."
msgstr "Rendre {} indépendant."
#: agenda_culturel/forms.py:298
#: agenda_culturel/forms.py:333
msgid "Make all versions independent."
msgstr "Rendre toutes les versions indépendantes."
#: agenda_culturel/forms.py:353
#: agenda_culturel/forms.py:388
msgid "Value of the selected version"
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 {}"
msgstr "Valeur de la version {}"
#: agenda_culturel/forms.py:506
#: agenda_culturel/forms.py:541
msgid "Apply category {} to the event {}"
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
msgid "Place"
msgstr "Lieu"
#: agenda_culturel/forms.py:523
#: agenda_culturel/forms.py:558
msgid "Create a missing place"
msgstr "Créer un lieu manquant"
#: agenda_culturel/forms.py:533
#: agenda_culturel/forms.py:568
msgid "Add \"{}\" to the aliases of the place"
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"
msgstr ""
"Lors de l'enregistrement, utiliser des alias pour détecter tous les "
@ -378,7 +389,9 @@ msgstr "Principale"
#: agenda_culturel/models.py:398
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
msgid "Reference location"
@ -894,27 +907,27 @@ msgstr "anglais"
msgid "French"
msgstr "français"
#: agenda_culturel/views.py:141
#: agenda_culturel/views.py:143
msgid "Recurrent import name"
msgstr "Nome de l'import récurrent"
#: agenda_culturel/views.py:142
#: agenda_culturel/views.py:144
msgid "Add another"
msgstr "Ajouter un autre"
#: agenda_culturel/views.py:143
#: agenda_culturel/views.py:145
msgid "Browse..."
msgstr "Naviguer..."
#: agenda_culturel/views.py:144
#: agenda_culturel/views.py:146
msgid "No file selected."
msgstr "Pas de fichier sélectionné."
#: agenda_culturel/views.py:280
#: agenda_culturel/views.py:282
msgid "The static content has been successfully updated."
msgstr "Le contenu statique a été modifié avec succès."
#: agenda_culturel/views.py:288
#: agenda_culturel/views.py:290
msgid ""
"The event cannot be updated because the import process is not available for "
"the referenced sources."
@ -922,33 +935,33 @@ msgstr ""
"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."
#: agenda_culturel/views.py:291
#: agenda_culturel/views.py:293
msgid "The event update has been queued and will be completed shortly."
msgstr ""
"La mise à jour de l'événement a été mise en attente et sera effectuée sous "
"peu."
#: agenda_culturel/views.py:301
#: agenda_culturel/views.py:303
msgid "The event has been successfully modified."
msgstr "L'événement a été modifié avec succès."
#: agenda_culturel/views.py:345
#: agenda_culturel/views.py:347
msgid "The event has been successfully moderated."
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."
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."
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>."
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 ""
"The event has been submitted and will be published as soon as it has been "
"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'équipe de modération."
#: agenda_culturel/views.py:511
#: agenda_culturel/views.py:513
msgid "The event is saved."
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: {}."
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 ""
"{} has not been submitted since its already known and currently into "
"moderation process."
msgstr "{} n'a pas été soumis car il est déjà connu et en cours de modération"
#: agenda_culturel/views.py:620
#: agenda_culturel/views.py:622
msgid "Integrating {} url(s) into our import process."
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."
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."
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."
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."
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."
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."
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."
msgstr "L'import a été annulé"
#: agenda_culturel/views.py:1091
#: agenda_culturel/views.py:1093
msgid "The recurrent import has been successfully modified."
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."
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."
msgstr "L'import a été lancé"
#: agenda_culturel/views.py:1162
#: agenda_culturel/views.py:1164
msgid "Imports has been launched."
msgstr "Les imports ont été lancés"
#: agenda_culturel/views.py:1221
#: agenda_culturel/views.py:1223
msgid "Update successfully completed."
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."
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."
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:1356
#: agenda_culturel/views.py:1331 agenda_culturel/views.py:1340
#: agenda_culturel/views.py:1358
msgid ""
"The selected item is no longer included in the list of duplicates. Someone "
"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 "
"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"
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."
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."
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."
msgstr "L'événement a été marqué dupliqué avec succès."
#: agenda_culturel/views.py:1448
#: agenda_culturel/views.py:1450
msgid ""
"The event has been successfully flagged as a duplicate. The moderation team "
"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 "
"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."
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."
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."
msgstr ""
"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."
msgstr ""
"Les règles ont été appliquées avec succès et {} événements ont été "
"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."
msgstr ""
"Les règles ont été appliquées avec succès et aucun événement n'a été "
"catégorisé"
#: agenda_culturel/views.py:1585
#: agenda_culturel/views.py:1587
msgid ""
"The rules were successfully applied and 1 event with default category was "
"categorised."
@ -1096,7 +1109,7 @@ msgstr ""
"Les règles ont été appliquées avec succès et 1 événement avec catégorie par "
"défaut a été catégorisé"
#: agenda_culturel/views.py:1592
#: agenda_culturel/views.py:1594
msgid ""
"The rules were successfully applied and {} events with default category were "
"categorised."
@ -1104,41 +1117,70 @@ msgstr ""
"Les règles ont été appliquées avec succès et {} événements avec catégorie "
"par défaut ont été catégorisés"
#: agenda_culturel/views.py:1681 agenda_culturel/views.py:1743
#: agenda_culturel/views.py:1781
#: agenda_culturel/views.py:1683 agenda_culturel/views.py:1745
#: agenda_culturel/views.py:1783
msgid "{} events have been updated."
msgstr "{} événements ont été mis à jour."
#: agenda_culturel/views.py:1684 agenda_culturel/views.py:1745
#: agenda_culturel/views.py:1784
#: agenda_culturel/views.py:1686 agenda_culturel/views.py:1747
#: agenda_culturel/views.py:1786
msgid "1 event has been updated."
msgstr "1 événement a été mis à jour"
#: agenda_culturel/views.py:1686 agenda_culturel/views.py:1747
#: agenda_culturel/views.py:1786
#: agenda_culturel/views.py:1688 agenda_culturel/views.py:1749
#: agenda_culturel/views.py:1788
msgid "No events have been modified."
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."
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."
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."
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."
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."
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."
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%;
}
}
.helptext {
display: block;
margin-top: 0;
}
header .remarque {
font-style: italic;
}
@ -567,6 +573,8 @@ header .remarque {
.slide-buttons {
float: right;
max-width: 30em;
text-align: right;
}
.left-buttons {
display: inline-block;

View File

@ -3,6 +3,7 @@
{% block title %}{% block og_title %}Les événements {{ tag }}{% endblock %}{% endblock %}
{% load cat_extra %}
{% load utils_extra %}
{% block fluid %}{% endblock %}
@ -16,21 +17,28 @@
{% block content %}
<article>
<header>
<a href="{% url 'view_all_tags' %}" role="button">&lt; Toutes les étiquettes</a>
<div class="slide-buttons">
{% if object %}
{% 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 %}
{% if perms.agenda_culturel.delete_tag %}
<a href="{% url 'delete_tag' object.pk %}" role="button">Supprimer les informations</a>
{% endif %}
{% else %}
{% if perms.agenda_culturel.add_tag %}
<a href="{% url 'add_tag' %}?name={{ tag|urlencode }}" role="button">Renseigner l'étiquette</a>
<a href="{% url 'delete_object_tag' object.pk %}" role="button">Supprimer les informations {% picto_from_name "trash-2" %}</a>
{% endif %}
{% else %}
{% if perms.agenda_culturel.add_tag %}
<a href="{% url 'add_tag' %}?name={{ tag|urlencode }}" role="button">Renseigner {% picto_from_name "edit" %}</a>
{% 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>
<h1>Les événements <em>{{ tag }}</em></h1>
<h1>Les événements <em>{{ tag }}</em></h1>
{% if user.is_authenticated and object %}
{% if object.in_excluded_suggestions %}
<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>
{% endif %}
{% endif %}
<div style="clear: both;"></div>
</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>
{% 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 content %}
<h1>Renseignement d'une étiquette</h1>
<article>
<header>
<h1>Renseignement de l'étiquette <em>{{ form.name.value }}</em></h1>
</header>
<form method="post">{% csrf_token %}
{{ form.media }}
{{ 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("tags/", tag_list, name="view_all_tags"),
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("recent/", recent, name="recent"),
path("administration/", administration, name="administration"),

View File

@ -33,7 +33,9 @@ from .forms import (
EventAddPlaceForm,
PlaceForm,
MultipleHiddenInput,
EventModerateForm
EventModerateForm,
TagForm,
TagRenameForm
)
from .filters import (
@ -1825,14 +1827,14 @@ class PlaceFromEventCreateView(PlaceCreateView):
class TagUpdateView(PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
model = 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.")
class TagCreateView(PermissionRequiredMixin, SuccessMessageMixin, CreateView):
model = 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.")
def get_initial(self, *args, **kwargs):
@ -1881,4 +1883,106 @@ def tag_list(request):
tags = [t | {'obj': d_objects[t["tag"]]} if t["tag"] in d_objects else t for t in tags]
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},
)