diff --git a/assets/scss/base/_base.scss b/assets/scss/base/_base.scss
index a5676bbc59..7af96dbb24 100644
--- a/assets/scss/base/_base.scss
+++ b/assets/scss/base/_base.scss
@@ -25,7 +25,7 @@ body {
}
// Elements with a dark background
-.flexpage-header, .write-tutorial, .page-footer, .header-menu, .header-right, .modal-title, .taglist, .hat, .linkbox-item.primary {
+.flexpage-header, .call-to-action, .page-footer, .header-menu, .header-right, .modal-title, .taglist, .hat, .linkbox-item.primary {
&::selection, *::selection {
@include negative-selection;
}
diff --git a/assets/scss/components/_content-item.scss b/assets/scss/components/_content-item.scss
index e807fa25db..43e3f01f1e 100644
--- a/assets/scss/components/_content-item.scss
+++ b/assets/scss/components/_content-item.scss
@@ -8,7 +8,7 @@ $content-item-padding-vertical: $length-14;
display: flex;
width: 100%;
- height: $content-item-height;
+ min-height: $content-item-height;
margin: $length-6 $length-10;
@@ -321,18 +321,15 @@ $content-item-padding-vertical: $length-14;
margin-bottom: $length-24;
}
-.write-tutorial {
+.call-to-action {
display: flex;
align-items: center;
-
- margin: $length-16 $length-10;
-
- &:not(:last-child) {
- margin-bottom: $length-20;
- }
+ flex-wrap: wrap;
+ box-sizing: border-box;
+ padding: $length-6 $length-20;
width: 100%;
- height: $content-item-height;
+ min-height: $content-item-height;
border-color: $color-primary;
background-color: $color-primary;
@@ -340,13 +337,13 @@ $content-item-padding-vertical: $length-14;
color: $grey-000;
&:hover {
- .btn-write-tutorial {
+ .btn-call-to-action {
background-color: $true-white;
transform: scale(1.05);
}
}
- .write-tutorial-text {
+ .call-to-action-text {
flex: 1;
text-align: center;
@@ -361,9 +358,8 @@ $content-item-padding-vertical: $length-14;
}
}
- .btn-write-tutorial {
+ .btn-call-to-action {
padding: $length-4 $length-20;
- margin-right: $length-24;
background-color: $grey-000;
color: $primary-900;
@@ -394,10 +390,6 @@ $content-item-padding-vertical: $length-14;
@include mobile {
.content-item {
- &.write-tutorial {
- display: none;
- }
-
.content-tags {
display: none;
}
diff --git a/templates/home.html b/templates/home.html
index fca74ce8c5..3e2c09d928 100644
--- a/templates/home.html
+++ b/templates/home.html
@@ -109,32 +109,54 @@
{% endfor %}
+
- {% trans "Derniers tutoriels" %}
- {% trans "Tous les tutoriels" %}
+ {% trans "Dernières pépites validées par l'équipe" %}
- {% include "tutorialv2/list_page_elements/list_of_online_contents.html" with public_contents=last_tutorials col_number=1 ignore_categories=True %}
+
+ {% for content in last_contents %}
+ {% include "tutorialv2/includes/content_item.part.html" with public_content=content show_description=True show_reactions=True ignore_categories=ignore_categories %}
+ {% endfor %}
+
+
+
+ {% blocktrans with plural=contents_count|pluralize_fr %}
+ Mais ce n'est pas tout...
+ {% endblocktrans %}
+
+
+ {% if validated_contents_count == 0 %}
+ {% blocktrans %}
+ Il y a {{ validated_contents_count }} publication validée par l'équipe.
+ {% endblocktrans %}
+ {% else %}
+ {% blocktrans %}
+ Il y a {{ validated_contents_count }} publications validées par l'équipe.
+ {% endblocktrans %}
+ {% endif %}
+
+
{% trans "Montre-les moi !" %}
+
+
+
+
-
- {% trans "Derniers articles" %}
- {% trans "Tous les articles" %}
+
+ {% trans "Dernières publications de la communauté" %}
- {% include "tutorialv2/list_page_elements/list_of_online_contents.html" with public_contents=last_articles col_number=1 ignore_categories=True %}
-
-
-
-
+
+
{% blocktrans with plural=contents_count|pluralize_fr %}
Il y a {{ contents_count }} publication{{ plural }} sur Zeste de Savoir.
@@ -142,34 +164,31 @@
{% trans "Pourquoi pas la vôtre ?" %}
-
{% trans "Commencer à rédiger" %}
+
{% trans "Commencer à rédiger" %}
-
-
-
-
-
-
-
-
-
-
-
{% for opinion in last_opinions %}
{% include 'tutorialv2/includes/content_item.part.html' with public_content=opinion show_description=True item_class=forloop.first|yesno:", mini" show_reactions=True ignore_categories=True %}
{% empty %}
{% trans "Aucun billet disponible." %}
{% endfor %}
+
+
+
+ {% blocktrans with plural=contents_count|pluralize_fr %}
+ D’autres publications de la communauté vous attendent.
+ {% endblocktrans %}
+
+
+
{% trans "Fais voir !" %}
+
+
+
- {% trans "Derniers sujets" %}
- {% trans "En voir plus" %}
+ {% trans "En direct du forum" %}
@@ -180,6 +199,16 @@
{% empty %}
{% trans "Aucun sujet disponible." %}
{% endfor %}
+
+
+
+ {% blocktrans with plural=contents_count|pluralize_fr %}
+ Entraide, débats, discussions : venez sur nos forums !
+ {% endblocktrans %}
+
+
+
{% trans "Je participe" %}
+
diff --git a/zds/featured/managers.py b/zds/featured/managers.py
index b33176892a..aec680f597 100644
--- a/zds/featured/managers.py
+++ b/zds/featured/managers.py
@@ -1,7 +1,6 @@
from datetime import datetime
from django.db import models
-from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
@@ -14,12 +13,8 @@ class FeaturedResourceManager(models.Manager):
Custom featured resource manager.
"""
- def get_last_featured(self):
- return (
- self.order_by("-pubdate")
- .exclude(pubdate__gt=datetime.now())
- .prefetch_related("authors__user")[: settings.ZDS_APP["featured_resource"]["home_number"]]
- )
+ def get_last_featured(self, count):
+ return self.order_by("-pubdate").exclude(pubdate__gt=datetime.now()).prefetch_related("authors__user")[:count]
class FeaturedMessageManager(models.Manager):
diff --git a/zds/forum/managers.py b/zds/forum/managers.py
index 9cf673207a..384c58f9cc 100644
--- a/zds/forum/managers.py
+++ b/zds/forum/managers.py
@@ -1,10 +1,8 @@
-from django.conf import settings
+import django.db.models
from django.db import models
from django.db.models import Q, F
from model_utils.managers import InheritanceManager
-from zds.utils import get_current_user
-
class ForumManager(models.Manager):
"""
@@ -65,17 +63,13 @@ class TopicManager(models.Manager):
"""
def visibility_check_query(self, current_user):
- """
- Build a subquery that checks if a topic is readable by current user
- :param current_user:
- :return:
- """
+ """Build a subquery that checks if a topic is readable by current user"""
if current_user.is_authenticated:
return Q(forum__groups__isnull=True) | Q(forum__groups__pk__in=current_user.profile.group_pks)
else:
return Q(forum__groups__isnull=True)
- def last_topics_of_a_member(self, author, user):
+ def last_topics_of_a_member(self, author, user, count):
"""
Gets last topics of a member but exclude all topics not accessible
for the request user.
@@ -86,24 +80,19 @@ def last_topics_of_a_member(self, author, user):
queryset = self.filter(author=author).prefetch_related("author")
queryset = queryset.filter(self.visibility_check_query(user)).distinct()
- return queryset.order_by("-pubdate").all()[: settings.ZDS_APP["forum"]["home_number"]]
+ return queryset.order_by("-pubdate").all()[:count]
def get_beta_topic_of(self, tutorial):
return self.filter(key=tutorial.pk, key__isnull=False).first()
- def get_last_topics(self):
- """
- Get last posted topics and prefetch some related properties.
- Depends on settings.ZDS_APP['topic']['home_number']
- :return:
- :rtype: django.models.Queryset
- """
+ def get_last_topics(self, count) -> django.db.models.QuerySet:
+ """Get last topics and prefetch some related properties."""
return (
self.filter(is_locked=False, forum__groups__isnull=True)
.select_related("forum", "author", "author__profile", "last_message")
.prefetch_related("tags")
.order_by("-pubdate")
- .all()[: settings.ZDS_APP["topic"]["home_number"]]
+ .all()[:count]
)
def get_all_topics_of_a_forum(self, forum_pk, is_sticky=False):
diff --git a/zds/forum/tests/tests.py b/zds/forum/tests/tests.py
index f67d27e7db..756904859f 100644
--- a/zds/forum/tests/tests.py
+++ b/zds/forum/tests/tests.py
@@ -13,7 +13,6 @@
TopicFactory,
PostFactory,
TagFactory,
- create_category_and_forum,
)
from zds.forum.models import Forum, TopicRead, Post, Topic
from zds.member.tests.factories import ProfileFactory, StaffProfileFactory
@@ -1182,7 +1181,7 @@ def setUp(self):
TopicFactory(forum=self.forum3, author=self.staff.user)
def test_get_last_topics(self):
- topics = Topic.objects.get_last_topics()
+ topics = Topic.objects.get_last_topics(5)
self.assertEqual(2, len(topics))
def test_get_unread_post(self):
diff --git a/zds/forum/tests/tests_views.py b/zds/forum/tests/tests_views.py
index b73889ec0a..0539c616ce 100644
--- a/zds/forum/tests/tests_views.py
+++ b/zds/forum/tests/tests_views.py
@@ -96,7 +96,8 @@ def test_topic_list_home_page(self):
_, forum = create_category_and_forum()
topic = create_topic_in_forum(forum, profile)
- topics_nb = len(Topic.objects.get_last_topics())
+ topics_count = 5
+ topics_nb = len(Topic.objects.get_last_topics(topics_count))
self.client.force_login(staff.user)
data = {"lock": "true", "topic": topic.pk}
@@ -105,7 +106,7 @@ def test_topic_list_home_page(self):
self.assertEqual(302, response.status_code)
self.assertTrue(Topic.objects.get(pk=topic.pk).is_locked)
- self.assertEqual(len(Topic.objects.get_last_topics()), topics_nb - 1)
+ self.assertEqual(len(Topic.objects.get_last_topics(topics_count)), topics_nb - 1)
class CategoryForumsDetailViewTest(TestCase):
diff --git a/zds/member/views/profile.py b/zds/member/views/profile.py
index eb8c5d263d..74b3d119c3 100644
--- a/zds/member/views/profile.py
+++ b/zds/member/views/profile.py
@@ -148,7 +148,8 @@ def get_context_data(self, **kwargs):
usr = context["usr"]
profile = usr.profile
context["profile"] = profile
- context["topics"] = list(Topic.objects.last_topics_of_a_member(usr, self.request.user))
+ topics_count = settings.ZDS_APP["member"]["topics_on_profile"]
+ context["topics"] = list(Topic.objects.last_topics_of_a_member(usr, self.request.user, count=topics_count))
followed_query_set = TopicAnswerSubscription.objects.get_objects_followed_by(self.request.user.id)
followed_topics = list(set(followed_query_set) & set(context["topics"]))
for topic in context["topics"]:
diff --git a/zds/pages/views.py b/zds/pages/views.py
index 1ec1797115..2c7682a268 100644
--- a/zds/pages/views.py
+++ b/zds/pages/views.py
@@ -31,28 +31,30 @@
def home(request):
- """Display the home page with last topics added."""
+ """Display the home page."""
- tutos = PublishableContent.objects.get_last_tutorials()
- articles = PublishableContent.objects.get_last_articles()
- opinions = PublishableContent.objects.get_last_opinions()
- quote = random.choice(QUOTES)
+ context = {
+ "featured_message": FeaturedMessage.objects.get_last_message(),
+ "contents_count": PublishedContent.objects.count_contents(),
+ "search_form": SearchForm(initial={}),
+ "validated_contents_count": PublishedContent.objects.count_validated_contents(),
+ }
- return render(
- request,
- "home.html",
- {
- "featured_message": FeaturedMessage.objects.get_last_message(),
- "last_tutorials": tutos,
- "last_articles": articles,
- "last_opinions": opinions,
- "last_featured_resources": FeaturedResource.objects.get_last_featured(),
- "last_topics": Topic.objects.get_last_topics(),
- "contents_count": PublishedContent.objects.get_contents_count(),
- "quote": quote.replace("\n", ""),
- "search_form": SearchForm(initial={}),
- },
- )
+ contents_count = settings.ZDS_APP["homepage"]["contents_count"]
+ context["last_contents"] = PublishableContent.objects.get_last_contents(contents_count)
+
+ opinions_count = settings.ZDS_APP["homepage"]["opinions_count"]
+ context["last_opinions"] = PublishableContent.objects.get_last_opinions(opinions_count)
+
+ features_count = settings.ZDS_APP["homepage"]["features_count"]
+ context["last_featured_resources"] = FeaturedResource.objects.get_last_featured(features_count)
+
+ topics_count = settings.ZDS_APP["homepage"]["topics_count"]
+ context["last_topics"] = Topic.objects.get_last_topics(topics_count)
+
+ context["quote"] = random.choice(QUOTES).replace("\n", "")
+
+ return render(request, "home.html", context)
def index(request):
@@ -60,7 +62,7 @@ def index(request):
def about(request):
- """Display many informations about the website."""
+ """Display many information about the website."""
return render(
request,
"pages/technologies.html",
diff --git a/zds/settings/abstract_base/zds.py b/zds/settings/abstract_base/zds.py
index a242c2a1d6..0a8ead2b98 100644
--- a/zds/settings/abstract_base/zds.py
+++ b/zds/settings/abstract_base/zds.py
@@ -145,6 +145,7 @@
"users_in_hats_list": 5,
"requested_hats_per_page": 100,
"update_last_visit_interval": 600, # seconds
+ "topics_on_profile": 5,
},
"hats": {
"moderation": "Staff",
@@ -156,12 +157,13 @@
"gallery_per_page": 21,
"images_per_page": 21,
},
- "tutorial": {
- "home_number": 4,
+ "homepage": {
+ "contents_count": 5,
+ "opinions_count": 4,
+ "topics_count": 5,
+ "features_count": 5,
},
- "article": {"home_number": 3},
"opinions": {
- "home_number": 5,
"allow_pdf": zds_config.get("opinions_allow_pdf", True),
"allow_epub": zds_config.get("opinions_allow_epub", True),
"allow_zip": zds_config.get("opinions_allow_zip", True),
@@ -210,7 +212,6 @@
"beta_forum_id": zds_config.get("publications_being_written_forum_id", 1),
"max_post_length": 1000000,
"top_tag_max": 5,
- "home_number": 6,
"old_post_limit_days": 90,
# Exclude tags from top tags list. Tags listed here should not be relevant for most of users.
# Be warned exclude too much tags can restrict performance
@@ -219,15 +220,11 @@
"description_size": 120,
"max_similar_topics": 10,
},
- "topic": {
- "home_number": 5,
- },
"comment": {
"max_pings": 15,
},
"featured_resource": {
"featured_per_page": 100,
- "home_number": 5,
"request_per_page": 50,
},
"notification": {
diff --git a/zds/tutorialv2/managers.py b/zds/tutorialv2/managers.py
index 381bb6403f..7a2e2a7fab 100644
--- a/zds/tutorialv2/managers.py
+++ b/zds/tutorialv2/managers.py
@@ -86,12 +86,12 @@ def last_articles_of_a_member_loaded(self, author):
def last_opinions_of_a_member_loaded(self, author):
return self.last_contents_of_a_member_loaded(author, _type="OPINION")
- def get_contents_count(self):
- """
- :rtype: int
- """
+ def count_contents(self) -> int:
return self.filter(must_redirect=False).count()
+ def count_validated_contents(self) -> int:
+ return self.filter(must_redirect=False, content_type__in=["ARTICLE", "TUTORIAL"]).count()
+
def get_top_tags(self, displayed_types, limit=-1):
"""
Retrieve all most rated tags.
@@ -203,32 +203,7 @@ def transfer_paternity(self, unregistered_user, replacement_author, gallery_clas
content.sha_draft = sha
content.save()
- def get_last_tutorials(self, number=0):
- """
- get list of last published tutorial
-
- :param number: number of tutorial you want. By default it is interpreted as \
- ``settings.ZDS_APP['tutorial']['home_number']``
- :return: list of last published content
- :rtype: list
- """
- number = number or settings.ZDS_APP["tutorial"]["home_number"]
- all_contents = (
- self.filter(type="TUTORIAL")
- .filter(public_version__isnull=False)
- .prefetch_related("authors")
- .select_related("public_version")
- .prefetch_related("subcategory")
- .prefetch_related("tags")
- .order_by("-public_version__publication_date")[:number]
- )
- published = []
- for content in all_contents:
- content.public_version.content = content
- published.append(content.public_version)
- return published
-
- def get_last_articles(self, number=0):
+ def get_last_contents(self, number):
"""
..attention:
this one uses a raw subquery for historical reasons. It will hopefully be replaced one day by an
@@ -244,9 +219,8 @@ def get_last_articles(self, number=0):
"utils_comment.id",
"tutorialv2_contentreaction.comment_ptr_id",
)
- number = number or settings.ZDS_APP["article"]["home_number"]
all_contents = (
- self.filter(type="ARTICLE")
+ self.filter(type__in=["ARTICLE", "TUTORIAL"])
.filter(public_version__isnull=False)
.prefetch_related("authors")
.select_related("last_note")
@@ -263,14 +237,13 @@ def get_last_articles(self, number=0):
published.append(content.public_version)
return published
- def get_last_opinions(self):
+ def get_last_opinions(self, count):
"""
This depends on settings.ZDS_APP['opinions']['home_number'] parameter.
:return: list of last opinions
:rtype: list
"""
- home_number = settings.ZDS_APP["opinions"]["home_number"]
all_contents = (
self.filter(type="OPINION")
.filter(public_version__isnull=False, sha_picked=F("sha_public"))
@@ -279,7 +252,7 @@ def get_last_opinions(self):
.select_related("public_version")
.prefetch_related("subcategory")
.prefetch_related("tags")
- .order_by("-public_version__publication_date")[:home_number]
+ .order_by("-public_version__publication_date")[:count]
)
published = []
for content in all_contents: