From a14232f0f57498a328a5a9e804391f4a2b0078e4 Mon Sep 17 00:00:00 2001 From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com> Date: Sat, 19 Oct 2024 09:08:20 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Rend=20g=C3=A9n=C3=A9rique=20en=20fonction?= =?UTF-8?q?=20du=20type=20la=20vue=20"WarnTypo"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * supprime la distinction de type de publication * préfère le terme "publication" à "contenu" * renomme les vues pour adopter la convention de Django * déplace le formulaire à côté de la vue --- templates/tutorialv2/messages/warn_typo.md | 4 +- zds/tutorialv2/forms.py | 83 ---------------- zds/tutorialv2/urls/urls_contents.py | 4 +- zds/tutorialv2/views/display/container.py | 2 +- zds/tutorialv2/views/display/content.py | 2 +- zds/tutorialv2/views/misc.py | 104 +++++++++++++++++---- 6 files changed, 91 insertions(+), 108 deletions(-) diff --git a/templates/tutorialv2/messages/warn_typo.md b/templates/tutorialv2/messages/warn_typo.md index 7c1f288c83..ad16dd616b 100644 --- a/templates/tutorialv2/messages/warn_typo.md +++ b/templates/tutorialv2/messages/warn_typo.md @@ -16,10 +16,10 @@ -{% blocktrans with username=user.username|safe title=content.title|safe type=type|safe %} +{% blocktrans with username=user.username|safe title=content.title|safe %} Salut ! -Il me semble avoir déniché une erreur dans {{ type }} « [{{ title }}]({{ content_url }}) ».{% endblocktrans %} +Il me semble avoir déniché une erreur dans « [{{ title }}]({{ content_url }}) ».{% endblocktrans %} {% if target != content %} {% blocktrans with title=target.title|safe %}Fourbe, elle se situe sournoisement dans {{ feminized }} {{ level }} « [{{ title }}]({{ target_url }}) ».{% endblocktrans %} {% endif %} diff --git a/zds/tutorialv2/forms.py b/zds/tutorialv2/forms.py index a9d73013e2..c2cc469347 100644 --- a/zds/tutorialv2/forms.py +++ b/zds/tutorialv2/forms.py @@ -693,89 +693,6 @@ def __init__(self, *args, **kwargs): ) -class WarnTypoForm(forms.Form): - text = forms.CharField( - label="", - required=True, - widget=forms.Textarea(attrs={"placeholder": _("Expliquez la faute"), "rows": "3", "id": "warn_text"}), - ) - - target = forms.CharField(widget=forms.HiddenInput(), required=False) - version = forms.CharField(widget=forms.HiddenInput(), required=True) - - def __init__(self, content, targeted, public=True, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.content = content - self.targeted = targeted - - # modal form, send back to previous page if any: - if public: - self.previous_page_url = targeted.get_absolute_url_online() - else: - self.previous_page_url = targeted.get_absolute_url_beta() - - # add an additional link to send PM if needed - type_ = _("l'article") - - if content.is_tutorial: - type_ = _("le tutoriel") - elif content.is_opinion: - type_ = _("le billet") - - if targeted.get_tree_depth() == 0: - pm_title = _("J'ai trouvé une faute dans {} « {} ».").format(type_, targeted.title) - else: - pm_title = _("J'ai trouvé une faute dans le chapitre « {} ».").format(targeted.title) - - usernames = "" - num_of_authors = content.authors.count() - for index, user in enumerate(content.authors.all()): - if index != 0: - usernames += "&" - usernames += "username=" + user.username - - msg = _('
Pas assez de place ? Envoyez un MP {} !').format(
- reverse("mp:create"), pm_title, usernames, _("à l'auteur") if num_of_authors == 1 else _("aux auteurs")
- )
-
- version = content.sha_beta
- if public:
- version = content.sha_public
-
- # create form
- self.helper = FormHelper()
- self.helper.form_action = reverse("content:warn-typo") + f"?pk={content.pk}"
- self.helper.form_method = "post"
- self.helper.form_class = "modal modal-flex"
- self.helper.form_id = "warn-typo-modal"
- self.helper.layout = Layout(
- Field("target"),
- Field("text"),
- HTML(msg),
- Hidden("pk", "{{ content.pk }}"),
- Hidden("version", version),
- ButtonHolder(StrictButton(_("Envoyer"), type="submit", css_class="btn-submit")),
- )
-
- def clean(self):
- cleaned_data = super().clean()
-
- text = cleaned_data.get("text")
-
- if text is None or not text.strip():
- self._errors["text"] = self.error_class([_("Vous devez indiquer la faute commise.")])
- if "text" in cleaned_data:
- del cleaned_data["text"]
-
- elif len(text) < 3:
- self._errors["text"] = self.error_class([_("Votre commentaire doit faire au moins 3 caractères.")])
- if "text" in cleaned_data:
- del cleaned_data["text"]
-
- return cleaned_data
-
-
class PublicationForm(forms.Form):
"""
The publication form (used only for content without preliminary validation).
diff --git a/zds/tutorialv2/urls/urls_contents.py b/zds/tutorialv2/urls/urls_contents.py
index 0f99c9e62c..6274330219 100644
--- a/zds/tutorialv2/urls/urls_contents.py
+++ b/zds/tutorialv2/urls/urls_contents.py
@@ -51,7 +51,7 @@
from zds.tutorialv2.views.lists import TagsListView, ContentOfAuthor, ListContentReactions
from zds.tutorialv2.views.alerts import SendContentAlert, SolveContentAlert
-from zds.tutorialv2.views.misc import RequestFeaturedContent, FollowNewContent, WarnTypo
+from zds.tutorialv2.views.misc import RequestFeaturedContent, FollowNewContent, WarnTypoView
from zds.tutorialv2.views.statistics import ContentStatisticsView
from zds.tutorialv2.views.comments import (
SendNoteFormView,
@@ -167,7 +167,7 @@ def get_version_pages():
path("alerter/ Pas assez de place ? Envoyez un MP {} !').format(
+ reverse("mp:create"), pm_title, usernames, _("à l'auteur") if num_of_authors == 1 else _("aux auteurs")
+ )
+
+ version = content.sha_beta
+ if public:
+ version = content.sha_public
+
+ # create form
+ self.helper = FormHelper()
+ self.helper.form_action = reverse("content:warn-typo") + f"?pk={content.pk}"
+ self.helper.form_method = "post"
+ self.helper.form_class = "modal modal-flex"
+ self.helper.form_id = "warn-typo-modal"
+ self.helper.layout = Layout(
+ Field("target"),
+ Field("text"),
+ HTML(msg),
+ Hidden("pk", "{{ content.pk }}"),
+ Hidden("version", version),
+ ButtonHolder(StrictButton(_("Envoyer"), type="submit", css_class="btn-submit")),
+ )
+
+ def clean(self):
+ cleaned_data = super().clean()
+
+ text = cleaned_data.get("text")
+
+ if text is None or not text.strip():
+ self._errors["text"] = self.error_class([_("Vous devez indiquer la faute commise.")])
+ if "text" in cleaned_data:
+ del cleaned_data["text"]
+
+ elif len(text) < 3:
+ self._errors["text"] = self.error_class([_("Votre commentaire doit faire au moins 3 caractères.")])
+ if "text" in cleaned_data:
+ del cleaned_data["text"]
+
+ return cleaned_data
+
+
+class WarnTypoView(SingleContentFormViewMixin):
modal_form = True
form_class = WarnTypoForm
must_be_author = False
@@ -106,9 +185,8 @@ def form_valid(self, form):
authors = list(Profile.objects.contactable_members().filter(user__in=self.object.authors.all()))
authors = list(author.user for author in authors)
- # check if the warn is done on a public or beta version :
+ # Check if the warning is done on a public or beta version
is_public = False
-
if form.content.is_public:
is_public = True
elif not form.content.is_beta:
@@ -120,35 +198,23 @@ def form_valid(self, form):
else:
messages.error(self.request, _("L'auteur est malheureusement injoignable."))
- elif user in authors: # author try to PM himself
+ elif user in authors: # Author is trying to PM himself
messages.error(self.request, _("Impossible d'envoyer la proposition de correction : vous êtes auteur."))
- else: # send correction
+ else: # Send correction
text = "\n".join(["> " + line for line in form.cleaned_data["text"].split("\n")])
-
- _type = _("l'article")
- if form.content.is_tutorial:
- _type = _("le tutoriel")
- if form.content.is_opinion:
- _type = _("le billet")
-
- pm_title = _("J'ai trouvé une faute dans {} « {} ».").format(_type, form.content.title)
-
+ pm_title = _("J'ai trouvé une faute dans « {} ».").format(form.content.title)
msg = render_to_string(
"tutorialv2/messages/warn_typo.md",
{
"user": user,
"content": form.content,
"target": form.targeted,
- "type": _type,
"public": is_public,
"text": text,
},
)
-
- # send it :
send_mp(user, authors, pm_title, "", msg, leave=False)
-
messages.success(self.request, _("Merci pour votre proposition de correction."))
return redirect(form.previous_page_url)
From 786e88e2b3d49feced2f7abac071150c523e09bc Mon Sep 17 00:00:00 2001
From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com>
Date: Sun, 2 Feb 2025 08:12:25 +0100
Subject: [PATCH 2/3] Fix doublon "WarnTypo"
---
zds/tutorialv2/views/display/content.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/zds/tutorialv2/views/display/content.py b/zds/tutorialv2/views/display/content.py
index be1f12c47d..55c45a1685 100644
--- a/zds/tutorialv2/views/display/content.py
+++ b/zds/tutorialv2/views/display/content.py
@@ -88,7 +88,6 @@ def get_context_data(self, **kwargs):
data_form_unpublication = data_form_revoke
context["form_unpublication"] = UnpublicationForm(versioned, initial=data_form_unpublication)
- context["form_warn_typo"] = WarnTypoForm(versioned, versioned, public=False)
context["form_jsfiddle"] = JsFiddleActivationForm(initial={"js_support": self.object.js_support})
context["form_edit_license"] = EditContentLicenseForm(versioned)
From c95feaf2f99739e032f24e3c4a38c60402f04b21 Mon Sep 17 00:00:00 2001
From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com>
Date: Sun, 2 Feb 2025 09:40:17 +0100
Subject: [PATCH 3/3] Refacto WarnTypo
---
zds/member/models.py | 2 -
zds/tutorialv2/urls/urls_contents.py | 3 +-
zds/tutorialv2/views/display/container.py | 2 +-
zds/tutorialv2/views/display/content.py | 2 +-
zds/tutorialv2/views/misc.py | 155 +---------------------
zds/tutorialv2/views/warntypo.py | 151 +++++++++++++++++++++
6 files changed, 156 insertions(+), 159 deletions(-)
create mode 100644 zds/tutorialv2/views/warntypo.py
diff --git a/zds/member/models.py b/zds/member/models.py
index 53fefa63d9..16017a72f9 100644
--- a/zds/member/models.py
+++ b/zds/member/models.py
@@ -1,6 +1,4 @@
from datetime import datetime
-from hashlib import md5
-import logging
from django.conf import settings
from django.contrib.auth.models import User
diff --git a/zds/tutorialv2/urls/urls_contents.py b/zds/tutorialv2/urls/urls_contents.py
index 6274330219..b87e6f1dfd 100644
--- a/zds/tutorialv2/urls/urls_contents.py
+++ b/zds/tutorialv2/urls/urls_contents.py
@@ -51,7 +51,8 @@
from zds.tutorialv2.views.lists import TagsListView, ContentOfAuthor, ListContentReactions
from zds.tutorialv2.views.alerts import SendContentAlert, SolveContentAlert
-from zds.tutorialv2.views.misc import RequestFeaturedContent, FollowNewContent, WarnTypoView
+from zds.tutorialv2.views.misc import RequestFeaturedContent, FollowNewContent
+from zds.tutorialv2.views.warntypo import WarnTypoView
from zds.tutorialv2.views.statistics import ContentStatisticsView
from zds.tutorialv2.views.comments import (
SendNoteFormView,
diff --git a/zds/tutorialv2/views/display/container.py b/zds/tutorialv2/views/display/container.py
index cb313bbdef..0e007182ca 100644
--- a/zds/tutorialv2/views/display/container.py
+++ b/zds/tutorialv2/views/display/container.py
@@ -3,7 +3,7 @@
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
-from zds.tutorialv2.views.misc import WarnTypoForm
+from zds.tutorialv2.views.warntypo import WarnTypoForm
from zds.tutorialv2.mixins import SingleContentDetailViewMixin, SingleOnlineContentDetailViewMixin
from zds.tutorialv2.models.database import PublishableContent
from zds.tutorialv2.utils import search_container_or_404, get_target_tagged_tree
diff --git a/zds/tutorialv2/views/display/content.py b/zds/tutorialv2/views/display/content.py
index 55c45a1685..9c02b5ee6f 100644
--- a/zds/tutorialv2/views/display/content.py
+++ b/zds/tutorialv2/views/display/content.py
@@ -24,7 +24,7 @@
UnpickOpinionForm,
PromoteOpinionToArticleForm,
)
-from zds.tutorialv2.views.misc import WarnTypoForm
+from zds.tutorialv2.views.warntypo import WarnTypoForm
from zds.tutorialv2.views.canonical import EditCanonicalLinkForm
from zds.tutorialv2.views.contributors import ContributionForm
from zds.tutorialv2.views.suggestions import SearchSuggestionForm
diff --git a/zds/tutorialv2/views/misc.py b/zds/tutorialv2/views/misc.py
index 7b4325517e..5d335e5f7c 100644
--- a/zds/tutorialv2/views/misc.py
+++ b/zds/tutorialv2/views/misc.py
@@ -1,26 +1,15 @@
-from crispy_forms.bootstrap import StrictButton
-from crispy_forms.helper import FormHelper
-from crispy_forms.layout import Layout, Field, HTML, Hidden, ButtonHolder
-from django import forms
-from django.contrib import messages
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.http import HttpResponse, Http404
from django.shortcuts import redirect
-from django.template.loader import render_to_string
-from django.urls import reverse
-from django.utils.translation import gettext_lazy as _
from django.views.generic import FormView
from zds import json_handler
from zds.featured.mixins import FeatureableMixin
from zds.member.decorator import LoggedWithReadWriteHability
-from zds.member.models import Profile
from zds.notification.models import NewPublicationSubscription
-from zds.tutorialv2.mixins import SingleOnlineContentViewMixin, SingleContentFormViewMixin
-from zds.tutorialv2.utils import search_container_or_404
-from zds.mp.utils import send_mp
+from zds.tutorialv2.mixins import SingleOnlineContentViewMixin
from zds.utils.misc import is_ajax
@@ -76,145 +65,3 @@ def post(self, request, *args, **kwargs):
if is_ajax(self.request):
return HttpResponse(json_handler.dumps(response), content_type="application/json")
return redirect(request.META.get("HTTP_REFERER"))
-
-
-class WarnTypoForm(forms.Form):
- text = forms.CharField(
- label="",
- required=True,
- widget=forms.Textarea(attrs={"placeholder": _("Expliquez la faute"), "rows": "3", "id": "warn_text"}),
- )
-
- target = forms.CharField(widget=forms.HiddenInput(), required=False)
- version = forms.CharField(widget=forms.HiddenInput(), required=True)
-
- def __init__(self, content, targeted, public=True, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- self.content = content
- self.targeted = targeted
-
- # Modal form, send back to previous page if any
- if public:
- self.previous_page_url = targeted.get_absolute_url_online()
- else:
- self.previous_page_url = targeted.get_absolute_url_beta()
-
- if targeted.get_tree_depth() == 0:
- pm_title = _("J'ai trouvé une faute dans « {} ».").format(targeted.title)
- else:
- pm_title = _("J'ai trouvé une faute dans le chapitre « {} ».").format(targeted.title)
-
- usernames = ""
- num_of_authors = content.authors.count()
- for index, user in enumerate(content.authors.all()):
- if index != 0:
- usernames += "&"
- usernames += "username=" + user.username
-
- msg = _(' Pas assez de place ? Envoyez un MP {} !').format(
- reverse("mp:create"), pm_title, usernames, _("à l'auteur") if num_of_authors == 1 else _("aux auteurs")
- )
-
- version = content.sha_beta
- if public:
- version = content.sha_public
-
- # create form
- self.helper = FormHelper()
- self.helper.form_action = reverse("content:warn-typo") + f"?pk={content.pk}"
- self.helper.form_method = "post"
- self.helper.form_class = "modal modal-flex"
- self.helper.form_id = "warn-typo-modal"
- self.helper.layout = Layout(
- Field("target"),
- Field("text"),
- HTML(msg),
- Hidden("pk", "{{ content.pk }}"),
- Hidden("version", version),
- ButtonHolder(StrictButton(_("Envoyer"), type="submit", css_class="btn-submit")),
- )
-
- def clean(self):
- cleaned_data = super().clean()
-
- text = cleaned_data.get("text")
-
- if text is None or not text.strip():
- self._errors["text"] = self.error_class([_("Vous devez indiquer la faute commise.")])
- if "text" in cleaned_data:
- del cleaned_data["text"]
-
- elif len(text) < 3:
- self._errors["text"] = self.error_class([_("Votre commentaire doit faire au moins 3 caractères.")])
- if "text" in cleaned_data:
- del cleaned_data["text"]
-
- return cleaned_data
-
-
-class WarnTypoView(SingleContentFormViewMixin):
- modal_form = True
- form_class = WarnTypoForm
- must_be_author = False
-
- http_method_names = ["post"]
- object = None
-
- def get_form_kwargs(self):
- kwargs = super().get_form_kwargs()
-
- versioned = self.get_versioned_object()
- kwargs["content"] = versioned
- kwargs["targeted"] = versioned
-
- if "target" in self.request.POST and self.request.POST["target"] != "":
- kwargs["targeted"] = search_container_or_404(versioned, self.request.POST["target"])
-
- kwargs["public"] = True
-
- if versioned.is_beta:
- kwargs["public"] = False
- elif not versioned.is_public:
- raise PermissionDenied
-
- return kwargs
-
- def form_valid(self, form):
- user = self.request.user
- authors = list(Profile.objects.contactable_members().filter(user__in=self.object.authors.all()))
- authors = list(author.user for author in authors)
-
- # Check if the warning is done on a public or beta version
- is_public = False
- if form.content.is_public:
- is_public = True
- elif not form.content.is_beta:
- raise Http404("Le contenu n'est ni public, ni en bêta.")
-
- if not authors:
- if self.object.authors.count() > 1:
- messages.error(self.request, _("Les auteurs sont malheureusement injoignables."))
- else:
- messages.error(self.request, _("L'auteur est malheureusement injoignable."))
-
- elif user in authors: # Author is trying to PM himself
- messages.error(self.request, _("Impossible d'envoyer la proposition de correction : vous êtes auteur."))
-
- else: # Send correction
- text = "\n".join(["> " + line for line in form.cleaned_data["text"].split("\n")])
- pm_title = _("J'ai trouvé une faute dans « {} ».").format(form.content.title)
- msg = render_to_string(
- "tutorialv2/messages/warn_typo.md",
- {
- "user": user,
- "content": form.content,
- "target": form.targeted,
- "public": is_public,
- "text": text,
- },
- )
- send_mp(user, authors, pm_title, "", msg, leave=False)
- messages.success(self.request, _("Merci pour votre proposition de correction."))
-
- return redirect(form.previous_page_url)
diff --git a/zds/tutorialv2/views/warntypo.py b/zds/tutorialv2/views/warntypo.py
new file mode 100644
index 0000000000..4b0ef44037
--- /dev/null
+++ b/zds/tutorialv2/views/warntypo.py
@@ -0,0 +1,151 @@
+from crispy_forms.bootstrap import StrictButton
+from crispy_forms.helper import FormHelper
+from crispy_forms.layout import Layout, Field, HTML, Hidden, ButtonHolder
+from django import forms
+from django.contrib import messages
+
+from django.core.exceptions import PermissionDenied
+from django.http import Http404
+from django.shortcuts import redirect
+from django.template.loader import render_to_string
+from django.urls import reverse
+from django.utils.translation import gettext_lazy as _
+
+from zds.mp.models import filter_reachable
+from zds.mp.utils import send_mp
+from zds.tutorialv2.mixins import SingleContentFormViewMixin
+from zds.tutorialv2.utils import search_container_or_404
+
+
+class WarnTypoForm(forms.Form):
+ text = forms.CharField(
+ label="",
+ required=True,
+ widget=forms.Textarea(attrs={"placeholder": _("Expliquez la faute"), "rows": "3", "id": "warn_text"}),
+ )
+
+ target = forms.CharField(widget=forms.HiddenInput(), required=False)
+ version = forms.CharField(widget=forms.HiddenInput(), required=True)
+
+ def __init__(self, content, targeted, public=True, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ self.content = content
+ self.targeted = targeted
+
+ # Manage targeted version
+ self.previous_page_url = targeted.get_absolute_url_beta()
+ version = content.sha_beta
+ if public:
+ self.previous_page_url = targeted.get_absolute_url_online()
+ version = content.sha_public
+
+ # Create form
+ self.helper = FormHelper()
+ self.helper.form_action = reverse("content:warn-typo") + f"?pk={content.pk}"
+ self.helper.form_method = "post"
+ self.helper.form_class = "modal modal-flex"
+ self.helper.form_id = "warn-typo-modal"
+ self.helper.layout = Layout(
+ Field("target"),
+ Field("text"),
+ HTML(self.get_link_for_pm(content, targeted)),
+ Hidden("pk", "{{ content.pk }}"),
+ Hidden("version", version),
+ ButtonHolder(StrictButton(_("Envoyer"), type="submit", css_class="btn-submit")),
+ )
+
+ @staticmethod
+ def get_link_for_pm(content, targeted):
+ if targeted.get_tree_depth() == 0:
+ pm_title = _("J'ai trouvé une faute dans « {} ».").format(targeted.title)
+ else:
+ pm_title = _("J'ai trouvé une faute dans le chapitre « {} ».").format(targeted.title)
+ recipients = filter_reachable(content.authors.all())
+ usernames = "&".join([f"username={recipient.username}" for recipient in recipients])
+ plural = _("aux auteurs") if len(recipients) > 1 else _("à l'auteur")
+ msg = _(' Pas assez de place ? Envoyez un MP {} !').format(
+ reverse("mp:create"), pm_title, usernames, plural
+ )
+ return msg
+
+ def clean(self):
+ cleaned_data = super().clean()
+
+ text = cleaned_data.get("text")
+
+ if text is None or not text.strip():
+ self._errors["text"] = self.error_class([_("Vous devez indiquer la faute commise.")])
+ if "text" in cleaned_data:
+ del cleaned_data["text"]
+ elif len(text) < 3:
+ self._errors["text"] = self.error_class([_("Votre commentaire doit faire au moins 3 caractères.")])
+ if "text" in cleaned_data:
+ del cleaned_data["text"]
+
+ return cleaned_data
+
+
+class WarnTypoView(SingleContentFormViewMixin):
+ modal_form = True
+ form_class = WarnTypoForm
+ must_be_author = False
+
+ http_method_names = ["post"]
+
+ def get_form_kwargs(self):
+ kwargs = super().get_form_kwargs()
+
+ versioned = self.get_versioned_object()
+ kwargs["content"] = versioned
+ kwargs["targeted"] = versioned
+
+ if "target" in self.request.POST and self.request.POST["target"] != "":
+ kwargs["targeted"] = search_container_or_404(versioned, self.request.POST["target"])
+
+ kwargs["public"] = True
+
+ if versioned.is_beta:
+ kwargs["public"] = False
+ elif not versioned.is_public:
+ raise PermissionDenied
+
+ return kwargs
+
+ def form_valid(self, form):
+ # Check if the warning is done on a public or beta version
+ is_public = False
+ if form.content.is_public:
+ is_public = True
+ elif not form.content.is_beta:
+ raise Http404("Le contenu n'est ni public, ni en bêta.")
+
+ user = self.request.user
+ recipients = filter_reachable(self.object.authors.all())
+ if not recipients:
+ if self.object.authors.count() > 1:
+ messages.error(self.request, _("Les auteurs sont malheureusement injoignables."))
+ else:
+ messages.error(self.request, _("L'auteur est malheureusement injoignable."))
+ elif user in recipients:
+ messages.error(self.request, _("Impossible d'envoyer la proposition de correction : vous êtes auteur."))
+ else:
+ self.send_pm(form, is_public, recipients, user)
+ messages.success(self.request, _("Merci pour votre proposition de correction."))
+
+ return redirect(form.previous_page_url)
+
+ def send_pm(self, form, is_public, recipients, sender):
+ text = "\n".join(["> " + line for line in form.cleaned_data["text"].split("\n")])
+ title = _("J'ai trouvé une faute dans « {} ».").format(form.content.title)
+ body = render_to_string(
+ "tutorialv2/messages/warn_typo.md",
+ {
+ "user": sender,
+ "content": form.content,
+ "target": form.targeted,
+ "public": is_public,
+ "text": text,
+ },
+ )
+ send_mp(sender, recipients, title, "", body, leave=False)