Prise en charge assistée des messages "attention" date/heure mal importée

Fix #367
This commit is contained in:
Jean-Marie Favreau 2025-05-03 10:38:01 +02:00
parent cbed16ac42
commit 3ac59ef3a2
9 changed files with 353 additions and 106 deletions

View File

@ -9,6 +9,7 @@ from django.core.files.storage import default_storage
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import recurrence import recurrence
import recurrence.fields import recurrence.fields
from .models.constants import TITLE_ISSUE_DATE_IMPORTATION, TITLE_ISSUE_TIME_IMPORTATION
from django.utils import timezone from django.utils import timezone
@ -371,19 +372,9 @@ class DBImporterEvents:
for w in warnings: for w in warnings:
if w == Extractor.Warning.NO_START_DATE: if w == Extractor.Warning.NO_START_DATE:
event_structure["title"] += ( event_structure["title"] += TITLE_ISSUE_DATE_IMPORTATION
" - "
+ _("Warning")
+ ": "
+ _("the date has not been imported correctly.")
)
if w == Extractor.Warning.NO_START_TIME: if w == Extractor.Warning.NO_START_TIME:
event_structure["title"] += ( event_structure["title"] += TITLE_ISSUE_TIME_IMPORTATION
" - "
+ _("Warning")
+ ": "
+ _("the time has not been imported correctly.")
)
if "category" in event_structure and event_structure["category"] is not None: if "category" in event_structure and event_structure["category"] is not None:
try: try:

View File

@ -42,6 +42,12 @@ from .models import (
from .templatetags.event_extra import event_field_verbose_name, field_to_html from .templatetags.event_extra import event_field_verbose_name, field_to_html
from .templatetags.utils_extra import int_to_abc from .templatetags.utils_extra import int_to_abc
from .models.constants import (
TITLE_ISSUE_DATE_IMPORTATION,
TITLE_ISSUE_TIME_IMPORTATION,
PUBLICATION_ISSUE,
)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -446,7 +452,37 @@ class EventForm(GroupFormMixin, ModelForm):
return list(set(self.cleaned_data.get("new_tags"))) return list(set(self.cleaned_data.get("new_tags")))
def clean(self): def clean(self):
super().clean() cleaned_data = super().clean()
issues = Event.get_title_publication_issues(cleaned_data["title"])
if len(issues) > 0 and cleaned_data["status"] == Event.STATUS.PUBLISHED:
r_issues = []
for i in issues:
if i == PUBLICATION_ISSUE.DATE_IMPORTATION_IN_TITLE:
if cleaned_data.get("start_day") != self.instance.start_day:
cleaned_data["title"] = cleaned_data.get("title").replace(
TITLE_ISSUE_DATE_IMPORTATION, ""
)
else:
r_issues.append(i)
elif i == PUBLICATION_ISSUE.TIME_IMPORTATION_IN_TITLE:
if cleaned_data.get("start_time") is not None:
cleaned_data["title"] = cleaned_data["title"].replace(
TITLE_ISSUE_TIME_IMPORTATION, ""
)
else:
r_issues.append(i)
else:
r_issues.append(i)
if len(r_issues) > 0:
raise ValidationError(
_(
"You can't publish an event without correcting the problems it contains ({})."
).format(", ".join([str(r) for r in r_issues]))
)
if self.is_moderation_expert and self.cleaned_data.get("new_tags") is not None: if self.is_moderation_expert and self.cleaned_data.get("new_tags") is not None:
self.cleaned_data["tags"] += self.cleaned_data.get("new_tags") self.cleaned_data["tags"] += self.cleaned_data.get("new_tags")

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: 2025-04-29 22:23+0200\n" "POT-Creation-Date: 2025-05-01 22:16+0200\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,27 +90,27 @@ msgstr "Après-midi"
msgid "Evening" msgid "Evening"
msgstr "Soir" msgstr "Soir"
#: agenda_culturel/db_importer.py:198 #: agenda_culturel/db_importer.py:199
msgid "Updated field(s): " msgid "Updated field(s): "
msgstr "Champ(s) mis à jour: " msgstr "Champ(s) mis à jour: "
#: agenda_culturel/db_importer.py:202 #: agenda_culturel/db_importer.py:203
msgid "Update" msgid "Update"
msgstr "Mise à jour" msgstr "Mise à jour"
#: agenda_culturel/db_importer.py:203 #: agenda_culturel/db_importer.py:204
msgid "update process" msgid "update process"
msgstr "processus de mise à jour" msgstr "processus de mise à jour"
#: agenda_culturel/db_importer.py:272 #: agenda_culturel/db_importer.py:273
msgid "Import" msgid "Import"
msgstr "Import" msgstr "Import"
#: agenda_culturel/db_importer.py:273 #: agenda_culturel/db_importer.py:274
msgid "import process" msgid "import process"
msgstr "processus d'import" msgstr "processus d'import"
#: agenda_culturel/db_importer.py:275 #: agenda_culturel/db_importer.py:276
msgid "" msgid ""
"The duration of the event is a little too long for direct publication. " "The duration of the event is a little too long for direct publication. "
"Moderators can choose to publish it or not." "Moderators can choose to publish it or not."
@ -118,33 +118,28 @@ msgstr ""
"La durée de l'événement est un peu trop longue pour qu'il soit publié " "La durée de l'événement est un peu trop longue pour qu'il soit publié "
"directement. Les modérateurs peuvent choisir de le publier ou non." "directement. Les modérateurs peuvent choisir de le publier ou non."
#: agenda_culturel/db_importer.py:376 agenda_culturel/db_importer.py:383 #: agenda_culturel/db_importer.py:464
#: agenda_culturel/models/message.py:20
msgid "Warning"
msgstr "Attention"
#: agenda_culturel/db_importer.py:378 agenda_culturel/db_importer.py:491
msgid "the date has not been imported correctly."
msgstr "la date n'a pas été importée correctement."
#: agenda_culturel/db_importer.py:385 agenda_culturel/db_importer.py:501
msgid "the time has not been imported correctly."
msgstr "l'heure n'a pas été importée correctement."
#: agenda_culturel/db_importer.py:473
msgid "during import process" msgid "during import process"
msgstr "pendant le processus d'import" msgstr "pendant le processus d'import"
#: agenda_culturel/db_importer.py:489 agenda_culturel/db_importer.py:499 #: agenda_culturel/db_importer.py:480 agenda_culturel/db_importer.py:490
#: agenda_culturel/db_importer.py:509 agenda_culturel/db_importer.py:520 #: agenda_culturel/db_importer.py:500 agenda_culturel/db_importer.py:511
msgid "warning" msgid "warning"
msgstr "attention" msgstr "attention"
#: agenda_culturel/db_importer.py:511 #: agenda_culturel/db_importer.py:482 agenda_culturel/models/constants.py:14
msgid "the date has not been imported correctly."
msgstr "la date n'a pas été importée correctement."
#: agenda_culturel/db_importer.py:492 agenda_culturel/models/constants.py:20
msgid "the time has not been imported correctly."
msgstr "l'heure n'a pas été importée correctement."
#: agenda_culturel/db_importer.py:502
msgid "the title has not been imported correctly." msgid "the title has not been imported correctly."
msgstr "le titre n'a pas été importé correctement." msgstr "le titre n'a pas été importé correctement."
#: agenda_culturel/db_importer.py:523 #: agenda_culturel/db_importer.py:514
msgid "The import was unable to find an event in the page." msgid "The import was unable to find an event in the page."
msgstr "L'import a été incapable de trouver un événement dans la page." msgstr "L'import a été incapable de trouver un événement dans la page."
@ -652,6 +647,18 @@ msgstr "Illustration (version de développement)"
msgid "Site Configuration" msgid "Site Configuration"
msgstr "Configuration du site" msgstr "Configuration du site"
#: agenda_culturel/models/constants.py:5 agenda_culturel/models/message.py:20
msgid "Warning"
msgstr "Attention"
#: agenda_culturel/models/constants.py:29
msgid "date import problem"
msgstr "problème de date pendant l'import"
#: agenda_culturel/models/constants.py:30
msgid "time import problem"
msgstr "problème d'heure pendant l'import"
#: agenda_culturel/models/event.py:48 #: agenda_culturel/models/event.py:48
msgid "Representative event" msgid "Representative event"
msgstr "Événement représentatif" msgstr "Événement représentatif"
@ -1521,7 +1528,7 @@ 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/event_views.py:66 #: agenda_culturel/views/event_views.py:67
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."
@ -1529,22 +1536,29 @@ 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/event_views.py:79 #: agenda_culturel/views/event_views.py:80
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/event_views.py:108 #: agenda_culturel/views/event_views.py:109
#: agenda_culturel/views/moderation_views.py:38 #: agenda_culturel/views/moderation_views.py:39
msgid " A message has been sent to the person who proposed the event." msgid " A message has been sent to the person who proposed the event."
msgstr " Un message a été envoyé à la personne qui a proposé l'événement." msgstr " Un message a été envoyé à la personne qui a proposé l'événement."
#: agenda_culturel/views/event_views.py:112 #: agenda_culturel/views/event_views.py:113
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/event_views.py:136 #: agenda_culturel/views/event_views.py:154
msgid ""
"You can't publish an event without correcting the problems it contains ({})."
msgstr ""
"Vous ne pouvez pas publiez un événement sans avoir corrigé les problèmes "
"qu'il contient ({})."
#: agenda_culturel/views/event_views.py:169
msgid "" msgid ""
"Changes will be visible on a local copy of the event. The version identical " "Changes will be visible on a local copy of the event. The version identical "
"to the imported source will be hidden." "to the imported source will be hidden."
@ -1552,15 +1566,15 @@ msgstr ""
"Les modifications seront visibles sur une copie locale de l'événement. La " "Les modifications seront visibles sur une copie locale de l'événement. La "
"version fidèle à la source importée sera masquée." "version fidèle à la source importée sera masquée."
#: agenda_culturel/views/event_views.py:181 #: agenda_culturel/views/event_views.py:214
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/event_views.py:261 #: agenda_culturel/views/event_views.py:294
msgid "Comment" msgid "Comment"
msgstr "Commentaire" msgstr "Commentaire"
#: agenda_culturel/views/event_views.py:285 #: agenda_culturel/views/event_views.py:318
msgid "" msgid ""
"The status has been successfully modified and a message has been sent to the " "The status has been successfully modified and a message has been sent to the "
"person who proposed the event." "person who proposed the event."
@ -1568,13 +1582,13 @@ msgstr ""
"Le status a été modifié avec succès et un message a été envoyé à la personne " "Le status a été modifié avec succès et un message a été envoyé à la personne "
"qui a proposé l'événement." "qui a proposé l'événement."
#: agenda_culturel/views/event_views.py:289 #: agenda_culturel/views/event_views.py:322
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/event_views.py:319 #: agenda_culturel/views/event_views.py:352
#: agenda_culturel/views/event_views.py:539 #: agenda_culturel/views/event_views.py:572
#: agenda_culturel/views/event_views.py:608 #: agenda_culturel/views/event_views.py:641
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."
@ -1582,13 +1596,13 @@ msgstr ""
"{} n'a pas été soumis car il est déjà connu et actuellement en cours de " "{} n'a pas été soumis car il est déjà connu et actuellement en cours de "
"modération." "modération."
#: agenda_culturel/views/event_views.py:329 #: agenda_culturel/views/event_views.py:362
#: agenda_culturel/views/event_views.py:530 #: agenda_culturel/views/event_views.py:563
#: agenda_culturel/views/event_views.py:599 #: agenda_culturel/views/event_views.py:632
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/event_views.py:346 #: agenda_culturel/views/event_views.py:379
msgid "" msgid ""
"This type of address is known to the calendar, so an automatic import is " "This type of address is known to the calendar, so an automatic import is "
"proposed." "proposed."
@ -1596,7 +1610,7 @@ msgstr ""
"Ce type d'adresse est connue du calendrier, alors un import automatique est " "Ce type d'adresse est connue du calendrier, alors un import automatique est "
"proposé." "proposé."
#: agenda_culturel/views/event_views.py:359 #: agenda_culturel/views/event_views.py:392
msgid "" msgid ""
"This type of address is unknown to the agenda. As a logged-in user, you can " "This type of address is unknown to the agenda. As a logged-in user, you can "
"still try to import the event, which may work if the page contains a google " "still try to import the event, which may work if the page contains a google "
@ -1608,7 +1622,7 @@ msgstr ""
"lorsque la page contient un lien google agenda par exemple. Dans le doute, " "lorsque la page contient un lien google agenda par exemple. Dans le doute, "
"privilégie une <a href=\"{}\">saisie manuelle</a>." "privilégie une <a href=\"{}\">saisie manuelle</a>."
#: agenda_culturel/views/event_views.py:370 #: agenda_culturel/views/event_views.py:403
msgid "" msgid ""
"This type of address is unknown to the calendar, so we suggest that you " "This type of address is unknown to the calendar, so we suggest that you "
"enter the information for the event you wish to import, in addition to the " "enter the information for the event you wish to import, in addition to the "
@ -1618,11 +1632,11 @@ msgstr ""
"informations de l'événement que tu souhaites importer, pour compléter " "informations de l'événement que tu souhaites importer, pour compléter "
"l'adresse que tu nous as donnée." "l'adresse que tu nous as donnée."
#: agenda_culturel/views/event_views.py:405 #: agenda_culturel/views/event_views.py:438
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/event_views.py:411 #: agenda_culturel/views/event_views.py:444
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."
@ -1630,20 +1644,20 @@ 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/event_views.py:425 #: agenda_culturel/views/event_views.py:458
msgid "during the creation process" msgid "during the creation process"
msgstr "pendant le processus d'import" msgstr "pendant le processus d'import"
#: agenda_culturel/views/event_views.py:448 #: agenda_culturel/views/event_views.py:481
msgid "A message has been sent to the person who proposed the initial event." msgid "A message has been sent to the person who proposed the initial event."
msgstr "" msgstr ""
"Un message a été envoyé à la personne qui a proposé l'événement initial." "Un message a été envoyé à la personne qui a proposé l'événement initial."
#: agenda_culturel/views/event_views.py:551 #: agenda_culturel/views/event_views.py:584
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/event_views.py:617 #: agenda_culturel/views/event_views.py:650
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."
@ -1723,10 +1737,72 @@ msgstr "Les propriétés du message de contact ont été modifié avec succès."
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/moderation_views.py:43 #: agenda_culturel/views/moderation_views.py:44
msgid "The event <a href=\"{}\">{}</a> has been moderated with success." msgid "The event <a href=\"{}\">{}</a> has been moderated with success."
msgstr "L'événement <a href=\"{}\">{}</a> a été modéré avec succès." msgstr "L'événement <a href=\"{}\">{}</a> a été modéré avec succès."
#: agenda_culturel/views/moderation_views.py:152
msgid ""
"There are several versions of this event, and you're moderating a version "
"that isn't the one being promoted. Most of the time, you don't need to do "
"this, just move on to the next one."
msgstr ""
"Cet événement existe en plusieurs versions, et vous êtes en train de modérer "
"une version qui n'est pas celle mise en avant. C'est la plupart du temps "
"inutile de le faire, vous pouvez passer au suivant."
#: agenda_culturel/views/moderation_views.py:160
msgid ""
"This event exists in several versions, and has no highlighted version. You "
"should <a href=\"{}\">correct this situation</a> before moderating only the "
"selected event."
msgstr ""
"Cet événement existe en plusieurs versions, et n'a pas de version mise en "
"avant. Vous devriez <a href=\"{}\">corriger cette situation</a> avant de "
"modérer uniquement l'événement retenu."
#: agenda_culturel/views/moderation_views.py:173
msgid ""
"This event is synchronized to a source, and has properties that prevent it "
"from being published as is ({}). We've redirected your moderation to event "
"editing to correct these problems before publication."
msgstr ""
"Cet événement est synchronisé sur une source, et comporte des propriétés "
"qui l'empêchent d'être publié en l'état ({}). On a redirigé ta modération "
"vers l'édition de l'événement afin de corriger ces problèmes avant "
"publication."
#: agenda_culturel/views/moderation_views.py:185
msgid ""
"The event is synchronized to a source and is not publishable as is ({}), "
"but there is <a href=\"{}\">local version</a> that is publishable. You may "
"wish to <a href=\"{}\">modify the highlighted event</a>."
msgstr ""
"L'événement est synchronisé sur une source et n'est pas publiable en l'état "
"({}), mais il existe une <a href=\"{}\">version locale</a> qui est "
"publiable. Vous pourriez <a href=\"{}\">modifier l'événement mis en avant</"
"a>."
#: agenda_culturel/views/moderation_views.py:192
msgid ""
"The event is synchronized on a source and is not publishable as is ({}), "
"and the <a href=\"{}\">local version</a> is not publishable ({}). You should "
"first <a href=\"{}\">fix it</a>, then <a href=\"{}\">modify the event "
"displayed</a>."
msgstr ""
"L'événement est synchronisé sur la source et n'est pas publiable en l'état "
"({}), et il la <a href=\"{}\">version locale</a> n'est pas publiable ({}). "
"Vous devriez d'abord <a href=\"{}\">la corriger</a>, puis <a "
"href=\"{}\">modifier l'événement</a> mis en avant."
#: agenda_culturel/views/moderation_views.py:199
msgid ""
"Simple moderation is not available as the event is not publishable in its "
"current state ({}). We therefore switch to editing mode."
msgstr ""
"La modération simple n'est pas disponible car l'événement n'est pas "
"publiable dans son état actuel ({}). Nous passons donc en mode édition."
#: agenda_culturel/views/organisations_views.py:78 #: agenda_culturel/views/organisations_views.py:78
msgid "The organisation has been successfully updated." msgid "The organisation has been successfully updated."
msgstr "L'organisme a été modifié avec succès." msgstr "L'organisme a été modifié avec succès."

View File

@ -37,7 +37,11 @@ from ..models.utils import remove_accents
from ..models.configuration import SiteConfiguration from ..models.configuration import SiteConfiguration
from ..calendar import CalendarDay from ..calendar import CalendarDay
from ..import_tasks.extractor import Extractor from ..import_tasks.extractor import Extractor
from .constants import (
TITLE_ISSUE_DATE_IMPORTATION,
TITLE_ISSUE_TIME_IMPORTATION,
PUBLICATION_ISSUE,
)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -1792,3 +1796,19 @@ class Event(models.Model):
def get_count_modifications(when_list): def get_count_modifications(when_list):
return [Event.get_count_modification(w) for w in when_list] return [Event.get_count_modification(w) for w in when_list]
@classmethod
def get_title_publication_issues(cls, title):
result = []
if TITLE_ISSUE_DATE_IMPORTATION in title:
result.append(PUBLICATION_ISSUE.DATE_IMPORTATION_IN_TITLE)
if TITLE_ISSUE_TIME_IMPORTATION in title:
result.append(PUBLICATION_ISSUE.TIME_IMPORTATION_IN_TITLE)
return result
def get_publication_issues(self):
return Event.get_title_publication_issues(self.title)
def has_publication_issues(self):
return len(self.get_publication_issues()) > 0

View File

@ -43,8 +43,15 @@
{% endfor %} {% endfor %}
<li> <li>
État&nbsp;: État&nbsp;:
{% if e.pure_import %}version fidèle à la source importée{% endif %} {% if e.pure_import %}
{% if e.local_version %}<strong>version modifiée localement</strong>{% endif %} version fidèle à la source importée
{% else %}
{% if e.local_version %}
<strong>version modifiée localement</strong>
{% else %}
<strong>version créée localement</strong>
{% endif %}
{% endif %}
</li> </li>
</ul> </ul>
{% with e.get_import_messages as messages %} {% with e.get_import_messages as messages %}

View File

@ -1,40 +1,44 @@
{% load utils_extra %} {% load utils_extra %}
{% if event.moderated_date %} {% with event.has_publication_issues as pub_issues %}
<a href="{% url 'moderate_event' event.id %}" role="button">modérer de nouveau {% picto_from_name "check-square" %}</a> {% if not pub_issues %}
{% else %} {% if event.moderated_date %}
<a href="{% url 'moderate_event' event.id %}" role="button">modérer {% picto_from_name "check-square" %}</a> <a href="{% url 'moderate_event' event.id %}" role="button">modérer de nouveau {% picto_from_name "check-square" %}</a>
{% endif %}
{% if event.pure_import %}
{% with event.get_local_version as local %}
{% if local %}
<a href="{{ local.get_absolute_url }}" role="button">Voir la version locale {% picto_from_name "eye" %}</a>
{% else %} {% else %}
{% if user.userprofile.is_moderation_expert %} <a href="{% url 'moderate_event' event.id %}" role="button">modérer {% picto_from_name "check-square" %}</a>
<a href="{% url 'clone_edit' event.id %}" role="button">modifier & modérer {% picto_from_name "edit-3" %}</a>
{% endif %}
{% endif %} {% endif %}
{% endwith %}
{% else %}
<a href="{% url 'edit_event' event.id %}" role="button">modifier & modérer {% picto_from_name "edit-3" %}</a>
{% endif %}
{% if event.is_updateable %}
<a href="{% url 'update_from_source' event.id %}" role="button">réimporter {% picto_from_name "download-cloud" %}</a>
{% endif %}
{% if event.status == "draft" and details == 1 %}
<a href="{% url 'change_status_event' event.id 'published' %}"
role="button">publier {% picto_from_name "eye" %}</a>
{% endif %}
{% if event.status == "trash" %}
{% if details == 1 %}
<a href="{% url 'change_status_event' event.id 'published' %}"
role="button">restaurer {% picto_from_name "eye" %}</a>
{% endif %} {% endif %}
{% else %} {% if event.pure_import %}
<a href="{% url 'change_status_event' event.id 'trash' %}" role="button">supprimer {% picto_from_name "trash-2" %}</a> {% with event.get_local_version as local %}
{% endif %} {% if local %}
{% if event.status == "trash" %} <a href="{{ local.get_absolute_url }}" role="button">Voir la version locale {% picto_from_name "eye" %}</a>
<a href="{% url 'delete_event' event.id %}" role="button">supprimer définitivement {% picto_from_name "x-circle" %}</a> {% else %}
{% endif %} {% if user.userprofile.is_moderation_expert %}
{% if details == 1 %} <a href="{% url 'clone_edit' event.id %}" role="button">modifier & modérer {% picto_from_name "edit-3" %}</a>
<a href="{% url 'simple_clone_edit' event.id %}" role="button">dupliquer {% picto_from_name "copy" %}</a> {% endif %}
{% endif %} {% endif %}
{% endwith %}
{% else %}
<a href="{% url 'edit_event' event.id %}" role="button">modifier & modérer {% picto_from_name "edit-3" %}</a>
{% endif %}
{% if event.is_updateable %}
<a href="{% url 'update_from_source' event.id %}" role="button">réimporter {% picto_from_name "download-cloud" %}</a>
{% endif %}
{% if event.status == "draft" and details == 1 and not pub_issues %}
<a href="{% url 'change_status_event' event.id 'published' %}"
role="button">publier {% picto_from_name "eye" %}</a>
{% endif %}
{% if event.status == "trash" %}
{% if details == 1 %}
<a href="{% url 'change_status_event' event.id 'published' %}"
role="button">restaurer {% picto_from_name "eye" %}</a>
{% endif %}
{% else %}
<a href="{% url 'change_status_event' event.id 'trash' %}" role="button">supprimer {% picto_from_name "trash-2" %}</a>
{% endif %}
{% if event.status == "trash" %}
<a href="{% url 'delete_event' event.id %}" role="button">supprimer définitivement {% picto_from_name "x-circle" %}</a>
{% endif %}
{% if details == 1 %}
<a href="{% url 'simple_clone_edit' event.id %}" role="button">dupliquer {% picto_from_name "copy" %}</a>
{% endif %}
{% endwith %}

View File

@ -146,6 +146,15 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
</header> </header>
{% if event.has_publication_issues %}
<div class="message warning">
Attention, l'événement n'est pas publiable en l'état&nbsp;:
{% for i in event.get_publication_issues %}
{{ i }}
{% if not forloop.last %},{% endif %}
{% endfor %}
</div>
{% endif %}
{% csrf_token %} {% csrf_token %}
{{ form.media }} {{ form.media }}
{{ form }} {{ form }}

View File

@ -251,12 +251,12 @@ urlpatterns = [
EventUpdateForceView.as_view(), EventUpdateForceView.as_view(),
name="edit_event_force", name="edit_event_force",
), ),
path( path( # clone function used to create an independant copy
"event/<int:pk>/simple-clone/edit", "event/<int:pk>/simple-clone/edit",
EventCreateIndependantView.as_view(), EventCreateIndependantView.as_view(),
name="simple_clone_edit", name="simple_clone_edit",
), ),
path( path( # clone function to have a local version of the event, thus modify it
"event/<int:pk>/clone/edit", "event/<int:pk>/clone/edit",
EventCreateLocalView.as_view(), EventCreateLocalView.as_view(),
name="clone_edit", name="clone_edit",

View File

@ -4,13 +4,14 @@ from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin, LoginRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin, LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.http import Http404, HttpResponseRedirect from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render, redirect
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import UpdateView from django.views.generic import UpdateView
from django.db.models import Q, F from django.db.models import Q, F
from django.utils.timezone import datetime from django.utils.timezone import datetime
from django.contrib import messages
from ..forms import EventModerateForm from ..forms import EventModerateForm
from ..models import Event from ..models import Event
@ -106,6 +107,109 @@ class EventModerateView(
else: else:
return self.object.get_absolute_url() return self.object.get_absolute_url()
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
msg = False
if (
self.object.other_versions is not None
and self.object.other_versions.nb_duplicated() > 1
):
representative = self.object.other_versions.representative
if representative is not None:
if representative != self.object:
msg = True
messages.warning(
request,
mark_safe(
_(
"There are several versions of this event, and you're moderating a version that isn't the one being promoted. Most of the time, you don't need to do this, just move on to the next one."
)
),
)
else:
msg = True
messages.warning(
request,
mark_safe(
_(
'This event exists in several versions, and has no highlighted version. You should <a href="{}">correct this situation</a> before moderating only the selected event.'
).format(
reverse_lazy(
"fix_duplicate",
kwargs={"pk": self.object.other_versions.pk},
)
)
),
)
issues = self.object.get_publication_issues()
print([str(i) for i in issues])
if len(issues) > 0 and not msg:
if self.object.pure_import:
lv = self.object.get_local_version()
if lv is None:
messages.warning(
request,
mark_safe(
_(
"This event is synchronized to a source, and has properties that prevent it from being published as is ({}). We've redirected your moderation to event editing to correct these problems before publication."
).format(", ".join([str(i) for i in issues]))
),
)
# clone edit
return redirect(
reverse_lazy("clone_edit", kwargs={"pk": self.object.pk})
)
else:
# msg is False, thus representative = self.object. Strange configuration. Anyway...
issues_lv = lv.get_publication_issues()
if len(issues_lv) == 0:
messages.warning(
request,
mark_safe(
_(
'The event is synchronized to a source and is not publishable as is ({}), but there is <a href="{}">local version</a> that is publishable. You may wish to <a href="{}">modify the highlighted event</a>.'
).format(
", ".join([str(i) for i in issues]),
lv.get_absolute_url(),
reverse_lazy("fix_duplicate"),
kwargs={"pk": self.object.other_versions.pk},
)
),
)
else:
messages.warning(
request,
mark_safe(
_(
'The event is synchronized on a source and is not publishable as is ({}), and the <a href="{}">local version</a> is not publishable ({}). You should first <a href="{}">fix it</a>, then <a href="{}">modify the event displayed</a>.'
).format(
", ".join([str(i) for i in issues]),
lv.get_absolute_url(),
", ".join([str(i) for i in issues_lv]),
reverse_lazy("edit_event", kwargs={"pk": lv.pk}),
reverse_lazy(
"fix_duplicate",
kwargs={"pk": self.object.other_versions.pk},
),
)
),
)
else:
messages.info(
request,
mark_safe(
_(
"Simple moderation is not available as the event is not publishable in its current state ({}). We therefore switch to editing mode."
).format(", ".join([str(i) for i in issues]))
),
)
return redirect(
reverse_lazy("edit_event", kwargs={"pk": self.object.pk})
)
return super().dispatch(request, *args, **kwargs)
class EventModerateNextView(EventModerateView): class EventModerateNextView(EventModerateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):