Skip to content

Commit

Permalink
feat(home): afficher les questions en attente de réponse sur la page …
Browse files Browse the repository at this point in the history
…d'accueil (#830)

## Description

🎸 Valoriser les questions en attente de réponse dès la page d'acceuil,
et permettre d'y répondre directement
🎸 Allègement de l'affichage, les questions en attente ne peuvent pas
avoir de réponse certifiée. Les `attachments` et les sondages sont
volontairement non affichés.

## Type de changement

🎢 Nouvelle fonctionnalité (changement non cassant qui ajoute une
fonctionnalité).
🎨 changement d'UI

### Points d'attention

🦺 ajout de la méthode `unanswered` dans `TopicQueryset`
🦺 duplication et simplification du gabarit `topic_list` en
`topic_simple_list`
🦺 enrichissement du contexte de `HomeView`
🦺 pas de pagination, seules les 4 plus récentes questions sont
affichées. La section est cachée si aucune question n'est en attente


### Captures d'écran (optionnel)

page d'accueil avec questions en attente


![image](https://github.com/user-attachments/assets/9363a5a7-6a80-46ff-a6fc-e54920da937b)

page d'accueil sans question en attente


![image](https://github.com/user-attachments/assets/1f1d4258-0a13-47f4-ba5c-02061066c8ad)

---------

Co-authored-by: hellodeloo <[email protected]>
Co-authored-by: François Freitag <[email protected]>
  • Loading branch information
3 people authored Dec 2, 2024
1 parent d86f0ee commit 300a7bd
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 1 deletion.
8 changes: 8 additions & 0 deletions lacommunaute/forum_conversation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ def unanswered(self):
.exclude(status=Topic.TOPIC_LOCKED)
.exclude(type=Topic.TOPIC_ANNOUNCE)
.filter(posts_count=1)
.select_related(
"forum",
"poster",
"poster__forum_profile",
"first_post",
"first_post__poster",
)
.order_by("-last_post_on")
)

def optimized_for_topics_list(self, user_id):
Expand Down
12 changes: 12 additions & 0 deletions lacommunaute/forum_conversation/tests/tests_models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from datetime import datetime, timezone

from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import IntegrityError
from django.test import TestCase
from django.urls import reverse
from factory import Iterator

from lacommunaute.forum.factories import ForumFactory
from lacommunaute.forum_conversation.factories import (
Expand Down Expand Up @@ -47,6 +50,15 @@ def test_unanswered(self):

self.assertEqual(Topic.objects.unanswered().get(), topic)

def test_unanswered_order(self):
forum = ForumFactory()
last_post_dates = [datetime(2025, 5, i, tzinfo=timezone.utc) for i in range(20, 24)]

TopicFactory.create_batch(
size=len(last_post_dates), forum=forum, posts_count=1, last_post_on=Iterator(last_post_dates)
)
assert list(Topic.objects.unanswered().values_list("last_post_on", flat=True)) == last_post_dates[::-1]

def test_optimized_for_topics_list_disapproved(self):
TopicFactory(approved=False)
self.assertEqual(Topic.objects.optimized_for_topics_list(1).count(), 0)
Expand Down
24 changes: 24 additions & 0 deletions lacommunaute/pages/tests/test_homepage.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import re

import pytest
from dateutil.relativedelta import relativedelta
from django.urls import reverse
from django.utils import timezone
from pytest_django.asserts import assertContains, assertNotContains

from lacommunaute.event.factories import EventFactory
from lacommunaute.forum.factories import ForumFactory
from lacommunaute.forum_conversation.factories import TopicFactory
from lacommunaute.utils.testing import parse_response_to_soup


Expand Down Expand Up @@ -49,3 +51,25 @@ def test_events(db, client):
assertContains(response, reverse("event:detail", kwargs={"pk": future_event.pk}))
assertNotContains(response, unvisible_future_event.name)
assertContains(response, reverse("event:current"))


@pytest.mark.parametrize("nb_topics,nb_expected", [(i, i) for i in range(5)] + [(i, 4) for i in range(5, 7)])
def test_unsanswered_topics(db, client, nb_topics, nb_expected, snapshot):
TopicFactory.create_batch(nb_topics, with_post=True, with_tags=["Pirmadienis", "Poniedziałek", "Lundi", "Montag"])
response = client.get(reverse("pages:home"))
assert len(response.context_data["unanswered_topics"]) == nb_expected
assert ('id="unanswered_topics"' in str(response.content)) == (nb_expected > 0)


def test_numqueries(db, client, django_assert_num_queries):
savepoint_queries = 4
session_queries = 2
with django_assert_num_queries(
savepoint_queries
+ session_queries
+ 1 # get first public forum
+ 1 # get most recent updated forums in documentation
+ 1 # get unanswered topics
+ 1 # get upcoming events
):
client.get(reverse("pages:home"))
4 changes: 4 additions & 0 deletions lacommunaute/pages/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

from lacommunaute.event.models import Event
from lacommunaute.forum.models import Forum
from lacommunaute.forum_conversation.forms import PostForm
from lacommunaute.forum_conversation.models import Topic


logger = logging.getLogger(__name__)
Expand All @@ -28,6 +30,8 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
context["forums_category"] = Forum.objects.filter(parent__type=1).order_by("-updated")[:4]
context["forum"] = Forum.objects.get_main_forum()
context["upcoming_events"] = Event.objects.filter(date__gte=timezone.now()).order_by("date")[:4]
context["unanswered_topics"] = Topic.objects.unanswered()[:4]
context["form"] = PostForm(user=self.request.user)
return context


Expand Down
4 changes: 3 additions & 1 deletion lacommunaute/partner/tests/tests_partner_listview.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest
from django.urls import reverse
from factory import Iterator

from lacommunaute.partner.factories import PartnerFactory
from lacommunaute.users.factories import UserFactory
Expand All @@ -21,7 +22,8 @@ def test_listview(client, db, snapshot, url):


def test_pagination(client, db, snapshot, url):
PartnerFactory.create_batch(8 * 3 + 1)
num_of_partners = 8 * 3 + 1
PartnerFactory.create_batch(num_of_partners, name=Iterator([f"Partner {i}" for i in range(num_of_partners)]))
response = client.get(url)
assert response.status_code == 200
assert str(parse_response_to_soup(response, selector="ul.pagination")) == snapshot(name="partner_pagination")
Expand Down
50 changes: 50 additions & 0 deletions lacommunaute/templates/forum_conversation/topic_simple_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{% load i18n %}
<div id="topicsarea">
{% if topics or not hide_if_empty %}
<ul class="list-group list-group-flush">
{% for topic in topics %}
<li class="list-group-item list-group-item-action">
<div id="{{ topic.pk }}" class="post">
<a href="{% url 'forum_conversation:topic' topic.forum.slug topic.forum.pk topic.slug topic.pk %}"
class="h4 text-tertiary d-block mb-1 matomo-event"
data-matomo-category="engagement"
data-matomo-action="view"
data-matomo-option="topic">{{ topic.subject }}</a>
<div class="mb-3">
{% include "forum_conversation/partials/poster.html" with post=topic.first_post topic=topic is_topic_head=True forum=forum %}
</div>
<div class="post-content">
<div id="showmoretopicsarea{{ topic.pk }}">
{% include 'partials/rendered_md.html' with content=topic.first_post.content truncatechars=1 only %}
{% if topic.first_post.content.rendered|length > 200 %}
<a hx-get="{% url 'forum_conversation_extension:showmore_topic' topic.forum.slug topic.forum.pk topic.slug topic.pk %}"
id="showmoretopic-button{{ topic.pk }}"
hx-target="#showmoretopicsarea{{ topic.pk }}"
hx-swap="outerHTML"
class="btn btn-link p-0 mb-3 mt-n3 matomo-event"
data-matomo-category="engagement"
data-matomo-action="showmore"
data-matomo-option="topic">{% trans "+ show more" %}</a>
{% endif %}
</div>
</div>
</div>
<div id="showmorepostsarea{{ topic.pk }}">
<div id="postinfeedarea{{ topic.pk }}">
{% include "forum_conversation/partials/post_feed_form_collapsable.html" with post_form=form %}
</div>
</div>
<div class="mb-3">
{% include "forum_conversation/partials/topic_detail_actions.html" with posts_count=topic.posts_count %}
</div>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
<script nonce="{{ request.csp_nonce }}">
var showmorepostsButtons = document.querySelectorAll('.showmoreposts-button')
showmorepostsButtons.forEach((button) => button.addEventListener('click', function() {
button.classList.add('d-none');
}));
</script>
14 changes: 14 additions & 0 deletions lacommunaute/templates/pages/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,20 @@ <h1 class="h1-hero">L’espace d’entraide des professionnels de l’inclusion<
</div>
</div>
</section>
{% if unanswered_topics %}
<section class="s-section my-5 my-md-9" id="unanswered_topics">
<div class="s-section__container container">
<div class="s-section__row row">
<div class="s-section__col col-12">
<p class="h1 text-tertiary">Des professionnels ont besoin de votre aide !</p>
{% with topics=unanswered_topics %}
{% include "forum_conversation/topic_simple_list.html" with active_tag=active_tag %}
{% endwith %}
</div>
</div>
</div>
</section>
{% endif %}
<section class="s-section my-5 my-md-10">
<div class="s-section__container container container-max-lg">
<div class="s-section__row row">
Expand Down

0 comments on commit 300a7bd

Please sign in to comment.