From 0a37691af5a2a06b378b50f483bc339108e4d0ab Mon Sep 17 00:00:00 2001
From: Arnaud-D <35631001+Arnaud-D@users.noreply.github.com>
Date: Fri, 18 Oct 2024 19:58:16 +0200
Subject: [PATCH] Permet les suggestions sur les billets
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* autorise les suggestions sur les billets
* rend les messages génériques selon le type de publication
* préfère l'usage du mot "publication" à "contenu"
* corrige les tests
---
.../sidebar/editorialization.part.html | 2 +-
...lter_contentsuggestion_options_and_more.py | 28 +++++++++++++++
zds/tutorialv2/models/database.py | 8 ++---
zds/tutorialv2/models/events.py | 6 ++--
.../tests/tests_views/tests_addsuggestion.py | 10 +++---
.../tests_views/tests_removesuggestion.py | 2 +-
zds/tutorialv2/urls/urls_contents.py | 6 ++--
zds/tutorialv2/views/suggestions.py | 35 ++++++-------------
8 files changed, 55 insertions(+), 42 deletions(-)
create mode 100644 zds/tutorialv2/migrations/0042_alter_contentsuggestion_options_and_more.py
diff --git a/templates/tutorialv2/includes/sidebar/editorialization.part.html b/templates/tutorialv2/includes/sidebar/editorialization.part.html
index 11f02f9ec2..04e2e2e5cf 100644
--- a/templates/tutorialv2/includes/sidebar/editorialization.part.html
+++ b/templates/tutorialv2/includes/sidebar/editorialization.part.html
@@ -37,7 +37,7 @@
Éditorialisation
{% endif %}
- {% if perms.tutorialv2.change_publishablecontent and not content.is_opinion %}
+ {% if perms.tutorialv2.change_publishablecontent %}
{% trans "Ajouter une suggestion" %}
diff --git a/zds/tutorialv2/migrations/0042_alter_contentsuggestion_options_and_more.py b/zds/tutorialv2/migrations/0042_alter_contentsuggestion_options_and_more.py
new file mode 100644
index 0000000000..fea6eb9f21
--- /dev/null
+++ b/zds/tutorialv2/migrations/0042_alter_contentsuggestion_options_and_more.py
@@ -0,0 +1,28 @@
+# Generated by Django 4.2.16 on 2024-10-18 19:39
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("tutorialv2", "0041_remove_must_reindex"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="contentsuggestion",
+ options={"verbose_name": "Suggestion de publication", "verbose_name_plural": "Suggestions de publication"},
+ ),
+ migrations.AlterField(
+ model_name="contentsuggestion",
+ name="publication",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="publication",
+ to="tutorialv2.publishablecontent",
+ verbose_name="Publication",
+ ),
+ ),
+ ]
diff --git a/zds/tutorialv2/models/database.py b/zds/tutorialv2/models/database.py
index 8f0a50ddb2..5bbf03ad26 100644
--- a/zds/tutorialv2/models/database.py
+++ b/zds/tutorialv2/models/database.py
@@ -45,7 +45,7 @@
from zds.tutorialv2.models.goals import Goal
from zds.tutorialv2.models.labels import Label
from zds.tutorialv2.models.mixins import TemplatableContentModelMixin, OnlineLinkableContentMixin
-from zds.tutorialv2.models.versioned import NotAPublicVersion, VersionedContent
+from zds.tutorialv2.models.versioned import NotAPublicVersion
from zds.tutorialv2.utils import get_content_from_json, BadManifestError, get_blob
from zds.utils import get_current_user
from zds.utils.models import Category, SubCategory, Licence, Comment, Tag
@@ -1572,13 +1572,13 @@ def __str__(self):
class ContentSuggestion(models.Model):
class Meta:
- verbose_name = "Suggestion de contenu"
- verbose_name_plural = "Suggestions de contenu"
+ verbose_name = "Suggestion de publication"
+ verbose_name_plural = "Suggestions de publication"
publication = models.ForeignKey(
PublishableContent,
null=False,
- verbose_name="Contenu",
+ verbose_name="Publication",
db_index=True,
on_delete=models.CASCADE,
related_name="publication",
diff --git a/zds/tutorialv2/models/events.py b/zds/tutorialv2/models/events.py
index 8617d105c1..bdaabc0104 100644
--- a/zds/tutorialv2/models/events.py
+++ b/zds/tutorialv2/models/events.py
@@ -8,7 +8,7 @@
from zds.tutorialv2.views.beta import ManageBetaContent
from zds.tutorialv2.views.canonical import EditCanonicalLinkView
from zds.tutorialv2.views.contributors import AddContributorToContent, RemoveContributorFromContent
-from zds.tutorialv2.views.suggestions import AddSuggestion, RemoveSuggestion
+from zds.tutorialv2.views.suggestions import AddSuggestionView, RemoveSuggestionView
from zds.tutorialv2.views.tags import EditTags
from zds.tutorialv2.views.goals import EditGoals
from zds.tutorialv2.views.labels import EditLabels
@@ -164,8 +164,8 @@ def record_event_canonical_link_management(sender, performer, signal, content, *
).save()
-@receiver(signals.suggestions_management, sender=AddSuggestion)
-@receiver(signals.suggestions_management, sender=RemoveSuggestion)
+@receiver(signals.suggestions_management, sender=AddSuggestionView)
+@receiver(signals.suggestions_management, sender=RemoveSuggestionView)
def record_event_suggestion_management(sender, performer, signal, content, action, **_):
Event(
performer=performer,
diff --git a/zds/tutorialv2/tests/tests_views/tests_addsuggestion.py b/zds/tutorialv2/tests/tests_views/tests_addsuggestion.py
index 1634d68faf..581f6b27b6 100644
--- a/zds/tutorialv2/tests/tests_views/tests_addsuggestion.py
+++ b/zds/tutorialv2/tests/tests_views/tests_addsuggestion.py
@@ -71,7 +71,7 @@ def test_authenticated_staff_opinion(self):
self.content.type = "OPINION"
self.content.save()
response = self.client.post(self.form_url, self.form_data)
- self.assertEqual(response.status_code, 403)
+ self.assertRedirects(response, self.content_url)
class AddSuggestionWorkflowTests(TutorialTestMixin, TestCase):
@@ -94,10 +94,10 @@ def setUp(self):
# Get information to be reused in tests
self.form_url = reverse("content:add-suggestion", kwargs={"pk": self.content.pk})
- self.success_message_fragment = _("a été ajouté dans les suggestions")
- self.error_message_fragment_unpublished = _("un contenu qui n'a pas été publié")
- self.error_message_fragment_already_suggested = _("fait déjà partie des suggestions de")
- self.error_message_fragment_self = _("en tant que suggestion pour lui-même")
+ self.success_message_fragment = _("a été ajouté aux suggestions")
+ self.error_message_fragment_unpublished = _("pas suggérer une publication non publique")
+ self.error_message_fragment_already_suggested = _("déjà suggéré pour cette publication")
+ self.error_message_fragment_self = _("la publication pour elle-même")
self.error_messge_fragment_not_picked = _("un billet qui n'a pas été mis en avant")
# Log in with an authorized user to perform the tests
diff --git a/zds/tutorialv2/tests/tests_views/tests_removesuggestion.py b/zds/tutorialv2/tests/tests_views/tests_removesuggestion.py
index db324199e9..ebf6ffd558 100644
--- a/zds/tutorialv2/tests/tests_views/tests_removesuggestion.py
+++ b/zds/tutorialv2/tests/tests_views/tests_removesuggestion.py
@@ -74,7 +74,7 @@ def test_authenticated_staff_opinion(self):
self.content.type = "OPINION"
self.content.save()
response = self.client.post(self.form_url, self.form_data)
- self.assertEqual(response.status_code, 403)
+ self.assertRedirects(response, self.content_url)
class RemoveSuggestionWorkflowTests(TutorialTestMixin, TestCase):
diff --git a/zds/tutorialv2/urls/urls_contents.py b/zds/tutorialv2/urls/urls_contents.py
index 89da39e1e1..0f99c9e62c 100644
--- a/zds/tutorialv2/urls/urls_contents.py
+++ b/zds/tutorialv2/urls/urls_contents.py
@@ -46,7 +46,7 @@
RemoveContributorFromContent,
ContentOfContributors,
)
-from zds.tutorialv2.views.suggestions import RemoveSuggestion, AddSuggestion
+from zds.tutorialv2.views.suggestions import RemoveSuggestionView, AddSuggestionView
from zds.tutorialv2.views.tags import EditTags
from zds.tutorialv2.views.lists import TagsListView, ContentOfAuthor, ListContentReactions
@@ -233,8 +233,8 @@ def get_version_pages():
name="inactive-beta",
),
path("stats///", ContentStatisticsView.as_view(), name="stats-content"),
- path("ajouter-suggestion//", AddSuggestion.as_view(), name="add-suggestion"),
- path("enlever-suggestion//", RemoveSuggestion.as_view(), name="remove-suggestion"),
+ path("ajouter-suggestion//", AddSuggestionView.as_view(), name="add-suggestion"),
+ path("enlever-suggestion//", RemoveSuggestionView.as_view(), name="remove-suggestion"),
# jsfiddle support:
path("activer-js/", ActivateJSFiddleInContent.as_view(), name="activate-jsfiddle"),
# delete:
diff --git a/zds/tutorialv2/views/suggestions.py b/zds/tutorialv2/views/suggestions.py
index a7b92b5bc0..eafae1b996 100644
--- a/zds/tutorialv2/views/suggestions.py
+++ b/zds/tutorialv2/views/suggestions.py
@@ -5,7 +5,6 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import PermissionRequiredMixin
-from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.decorators import method_decorator
@@ -19,7 +18,7 @@
class SearchSuggestionForm(forms.Form):
suggestion_pk = forms.CharField(
- label="Contenu à suggérer",
+ label="Publication à suggérer",
required=False,
widget=forms.TextInput(),
)
@@ -64,7 +63,7 @@ def clean_pk_suggestion(self):
return pk_suggestion
-class RemoveSuggestion(PermissionRequiredMixin, SingleContentFormViewMixin):
+class RemoveSuggestionView(PermissionRequiredMixin, SingleContentFormViewMixin):
form_class = RemoveSuggestionForm
modal_form = True
permission_required = "tutorialv2.change_publishablecontent"
@@ -72,8 +71,6 @@ class RemoveSuggestion(PermissionRequiredMixin, SingleContentFormViewMixin):
@method_decorator(login_required)
@method_decorator(can_write_and_read_now)
def dispatch(self, *args, **kwargs):
- if self.get_object().is_opinion:
- raise PermissionDenied
return super().dispatch(*args, **kwargs)
def form_valid(self, form):
@@ -90,9 +87,8 @@ def form_invalid(self, form):
return super().form_invalid(form)
def get_success_message(self, content_suggestion):
- return _('Vous avez enlevé "{}" de la liste des suggestions de {}.').format(
- content_suggestion.suggestion.title,
- self.describe_type(),
+ return _('Vous avez enlevé "{}" de la liste des suggestions de cette publication.').format(
+ content_suggestion.suggestion.title
)
def get_success_url(self):
@@ -101,25 +97,14 @@ def get_success_url(self):
else:
return self.object.get_absolute_url()
- def describe_type(self):
- if self.object.is_tutorial:
- return _("ce tutoriel")
- return _("cet article")
-
-class AddSuggestion(LoggedWithReadWriteHability, PermissionRequiredMixin, SingleContentFormViewMixin):
+class AddSuggestionView(LoggedWithReadWriteHability, PermissionRequiredMixin, SingleContentFormViewMixin):
authorized_for_staff = True
permission_required = "tutorialv2.change_publishablecontent"
def post(self, request, *args, **kwargs):
publication = get_object_or_404(PublishableContent, pk=kwargs["pk"])
- _type = _("cet article")
- if publication.is_tutorial:
- _type = _("ce tutoriel")
- elif self.object.is_opinion:
- raise PermissionDenied
-
if "options" in request.POST:
options = request.POST.getlist("options")
for option in options:
@@ -127,22 +112,22 @@ def post(self, request, *args, **kwargs):
if ContentSuggestion.objects.filter(publication=publication, suggestion=suggestion).exists():
messages.error(
self.request,
- _(f'Le contenu "{suggestion.title}" fait déjà partie des suggestions de {_type}.'),
+ _(f'"{suggestion.title}" est déjà suggéré pour cette publication.'),
)
elif suggestion.pk == publication.pk:
messages.error(
self.request,
- _(f"Vous ne pouvez pas ajouter {_type} en tant que suggestion pour lui-même."),
+ _(f"Vous ne pouvez pas suggérer la publication pour elle-même."),
)
elif suggestion.is_opinion and suggestion.sha_picked != suggestion.sha_public:
messages.error(
self.request,
- _(f"Vous ne pouvez pas suggérer pour {_type} un billet qui n'a pas été mis en avant."),
+ _(f"Vous ne pouvez pas suggérer un billet qui n'a pas été mis en avant."),
)
elif not suggestion.sha_public:
messages.error(
self.request,
- _(f"Vous ne pouvez pas suggérer pour {_type} un contenu qui n'a pas été publié."),
+ _(f"Vous ne pouvez pas suggérer une publication non publique."),
)
else:
obj_suggestion = ContentSuggestion(publication=publication, suggestion=suggestion)
@@ -155,7 +140,7 @@ def post(self, request, *args, **kwargs):
)
messages.info(
self.request,
- _(f'Le contenu "{suggestion.title}" a été ajouté dans les suggestions de {_type}.'),
+ _(f'"{suggestion.title}" a été ajouté aux suggestions de la publication.'),
)
if self.object.public_version: