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: