Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corrige l'affichage des suggestions quand certaines ne sont pas publiques #6439

Merged
merged 4 commits into from
Jan 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions zds/tutorialv2/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ContentRead,
PublicationEvent,
ContentContributionRole,
ContentSuggestion,
)
from zds.tutorialv2.models.events import Event
from zds.tutorialv2.models.goals import Goal
Expand Down Expand Up @@ -129,3 +130,4 @@ class GoalAdmin(admin.ModelAdmin):
admin.site.register(HelpWriting)
admin.site.register(Event)
admin.site.register(Goal, GoalAdmin)
admin.site.register(ContentSuggestion)
17 changes: 17 additions & 0 deletions zds/tutorialv2/migrations/0036_alter_contentsuggestion_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 3.2.15 on 2022-12-21 12:42

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("tutorialv2", "0035_alter_publishablecontent_goals"),
]

operations = [
migrations.AlterModelOptions(
name="contentsuggestion",
options={"verbose_name": "Suggestion de contenu", "verbose_name_plural": "Suggestions de contenu"},
),
]
78 changes: 28 additions & 50 deletions zds/tutorialv2/models/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,64 +250,32 @@ def ensure_author_gallery(self):
user_gallery.user = author
user_gallery.save()

def in_beta(self):
"""A tutorial is not in beta if sha_beta is ``None`` or empty


:return: ``True`` if the tutorial is in beta, ``False`` otherwise
:rtype: bool
"""
def in_beta(self) -> bool:
"""Return True if a beta version of the content exists, and False otherwise."""
return (self.sha_beta is not None) and (self.sha_beta.strip() != "")

def in_validation(self):
"""A tutorial is not in validation if sha_validation is ``None`` or empty

:return: ``True`` if the tutorial is in validation, ``False`` otherwise
:rtype: bool
"""
def in_validation(self) -> bool:
"""Return True if a version of the content is in validation, and False otherwise."""
return (self.sha_validation is not None) and (self.sha_validation.strip() != "")

def in_drafting(self):
"""A tutorial is not in draft if sha_draft is ``None`` or empty

:return: ``True`` if the tutorial is in draft, ``False`` otherwise
:rtype: bool
"""
def in_drafting(self) -> bool:
"""Return True if a draft version of the content exists, and False otherwise."""
return (self.sha_draft is not None) and (self.sha_draft.strip() != "")

def in_public(self):
"""A tutorial is not in on line if sha_public is ``None`` or empty

:return: ``True`` if the tutorial is on line, ``False`` otherwise
:rtype: bool
"""
def in_public(self) -> bool:
"""Return True if a public version of the content exists, and False otherwise."""
return (self.sha_public is not None) and (self.sha_public.strip() != "")

def is_beta(self, sha):
"""Is this version of the content the beta version ?

:param sha: version
:return: ``True`` if the tutorial is in beta, ``False`` otherwise
:rtype: bool
"""
def is_beta(self, sha: str) -> bool:
"""Return True if the given sha corresponds to the beta version, and False otherwise."""
return self.in_beta() and sha == self.sha_beta

def is_validation(self, sha):
"""Is this version of the content the validation version ?

:param sha: version
:return: ``True`` if the tutorial is in validation, ``False`` otherwise
:rtype: bool
"""
def is_validation(self, sha: str) -> bool:
"""Return True if the given sha corresponds to the version in validation, and False otherwise."""
return self.in_validation() and sha == self.sha_validation

def is_public(self, sha):
"""Is this version of the content the published version ?

:param sha: version
:return: ``True`` if the tutorial is in public, ``False`` otherwise
:rtype: bool
"""
def is_public(self, sha: str) -> bool:
"""Return True if the given sha corresponds to the public version, and False otherwise."""
return self.in_public() and sha == self.sha_public

def is_permanently_unpublished(self):
Expand Down Expand Up @@ -1483,9 +1451,9 @@ def __str__(self):


class ContentSuggestion(models.Model):
"""
Content suggestion
"""
class Meta:
verbose_name = "Suggestion de contenu"
verbose_name_plural = "Suggestions de contenu"

publication = models.ForeignKey(
PublishableContent,
Expand All @@ -1505,7 +1473,17 @@ class ContentSuggestion(models.Model):
)

def __str__(self):
return f"<Suggest '{self.suggestion.title}' for content {self.publication.title}, #{self.pk}>"
return f"<Suggest '{self.suggestion.title}' for content '{self.publication.title}', #{self.pk}>"

@staticmethod
def get_random_public_suggestions(publication: PublishableContent, count: int):
"""
Get random public suggestions for the given publication.
At most `count` suggestions are returned.
"""
all_suggestions = ContentSuggestion.objects.filter(publication=publication).order_by("?")
public_suggestions = [suggestion for suggestion in all_suggestions if suggestion.suggestion.in_public()]
return public_suggestions[:count]


@receiver(models.signals.pre_delete, sender=User)
Expand Down
45 changes: 45 additions & 0 deletions zds/tutorialv2/tests/models/tests_contentsuggestion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from django.test import TestCase

from zds.tutorialv2.models.database import ContentSuggestion, PublishableContent
from zds.tutorialv2.tests import TutorialTestMixin, override_for_contents
from zds.tutorialv2.tests.factories import PublishableContentFactory


@override_for_contents()
class ContentSuggestionTests(TutorialTestMixin, TestCase):
def setUp(self):
self.publication = PublishableContentFactory()
self.suggested_publications = [
PublishableContentFactory(),
PublishableContentFactory(),
PublishableContentFactory(),
PublishableContentFactory(),
]

# Make some suggested publications public, but not all.
for publication in self.suggested_publications[:-1]:
self.mock_publication_process(publication)

ContentSuggestion(publication=self.publication, suggestion=self.suggested_publications[0]).save()
ContentSuggestion(publication=self.publication, suggestion=self.suggested_publications[1]).save()
ContentSuggestion(publication=self.publication, suggestion=self.suggested_publications[2]).save()

def test_random_public_suggestions(self):
all_suggestions = ContentSuggestion.objects.filter(publication=self.publication)
all_suggestions_count = all_suggestions.count()
public_suggestions = [suggestion for suggestion in all_suggestions if suggestion.suggestion.in_public()]
public_suggestions_count = len(public_suggestions)
for count in range(all_suggestions_count):
suggestions = ContentSuggestion.get_random_public_suggestions(self.publication, count)
self.assertEqual(len(suggestions), min(count, public_suggestions_count))
for suggestion in suggestions:
self.assertTrue(suggestion.suggestion.in_public())

def mock_publication_process(self, publication: PublishableContent) -> ():
"""
Make the publication behave, for the purpose of the test, as if it had been published.
This is not extremely robust, but better than not testing.
"""
publication.sha_public = "123456"
publication.save()
self.assertTrue(publication.in_public())
7 changes: 4 additions & 3 deletions zds/tutorialv2/views/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,10 @@ def get_context_data(self, **kwargs):
context["contributions"] = ContentContribution.objects.filter(content=self.object).order_by(
"contribution_role__position"
)
context["content_suggestions_random"] = ContentSuggestion.objects.filter(publication=self.object).order_by("?")[
: settings.ZDS_APP["content"]["suggestions_per_page"]
]

context["content_suggestions_random"] = ContentSuggestion.get_random_public_suggestions(
self.object, count=settings.ZDS_APP["content"]["suggestions_per_page"]
)

return context

Expand Down