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 89da39e1e1..466b528482 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//", SendContentAlert.as_view(), name="alert-content"), path("resoudre//", SolveContentAlert.as_view(), name="resolve-content"), # typo: - path("reactions/typo/", WarnTypo.as_view(), name="warn-typo"), + path("reactions/typo/", WarnTypoView.as_view(), name="warn-typo"), # create: path("nouveau-contenu//", CreateContentView.as_view(), name="create-content"), path( diff --git a/zds/tutorialv2/views/display/container.py b/zds/tutorialv2/views/display/container.py index f1fececbc4..cb313bbdef 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.forms import WarnTypoForm +from zds.tutorialv2.views.misc 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 7f2ab0e384..be1f12c47d 100644 --- a/zds/tutorialv2/views/display/content.py +++ b/zds/tutorialv2/views/display/content.py @@ -18,13 +18,13 @@ CancelValidationForm, RevokeValidationForm, UnpublicationForm, - WarnTypoForm, JsFiddleActivationForm, PublicationForm, PickOpinionForm, UnpickOpinionForm, PromoteOpinionToArticleForm, ) +from zds.tutorialv2.views.misc 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 657e712c1b..7b4325517e 100644 --- a/zds/tutorialv2/views/misc.py +++ b/zds/tutorialv2/views/misc.py @@ -1,3 +1,7 @@ +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 @@ -5,6 +9,7 @@ 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 @@ -13,7 +18,6 @@ from zds.member.decorator import LoggedWithReadWriteHability from zds.member.models import Profile from zds.notification.models import NewPublicationSubscription -from zds.tutorialv2.forms import WarnTypoForm from zds.tutorialv2.mixins import SingleOnlineContentViewMixin, SingleContentFormViewMixin from zds.tutorialv2.utils import search_container_or_404 from zds.mp.utils import send_mp @@ -74,7 +78,82 @@ def post(self, request, *args, **kwargs): return redirect(request.META.get("HTTP_REFERER")) -class WarnTypo(SingleContentFormViewMixin): +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 @@ -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)