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

feat: Afficher l'image du forum comme bannière #632

Merged
merged 5 commits into from
May 27, 2024
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
1 change: 1 addition & 0 deletions config/settings/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@
MEDIA_URL = f"{AWS_S3_ENDPOINT_URL}/" # noqa: F405

CSP_DEFAULT_SRC = ("*",)
CSP_IMG_SRC += ("localhost:9000",) # noqa: F405
5 changes: 4 additions & 1 deletion lacommunaute/forum/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ class ForumFactory(BaseForumFactory):
class Meta:
skip_postgeneration_save = True

class Params:
with_image = factory.Trait(image=factory.django.ImageField(filename="banner.jpg"))

@factory.post_generation
def with_public_perms(self, create, extracted, **kwargs):
if not create or not extracted:
Expand All @@ -41,4 +44,4 @@ def with_child(self, create, extracted, **kwargs):
if not create or not extracted:
return

ForumFactory(parent=self, with_public_perms=True)
ForumFactory(parent=self, with_public_perms=True, with_image=True)
27 changes: 27 additions & 0 deletions lacommunaute/forum/migrations/0013_alter_forum_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 5.0.6 on 2024-05-21 14:55

import storages.backends.s3
from django.conf import settings
from django.db import migrations, models

import lacommunaute.forum.models


class Migration(migrations.Migration):
dependencies = [
("forum", "0012_forum_short_description_alter_forum_kind"),
]

operations = [
migrations.AlterField(
model_name="forum",
name="image",
field=models.ImageField(
storage=storages.backends.s3.S3Storage(
bucket_name=settings.AWS_STORAGE_BUCKET_NAME, file_overwrite=False
),
upload_to="",
validators=[lacommunaute.forum.models.validate_image_size],
),
),
]
7 changes: 7 additions & 0 deletions lacommunaute/forum/models.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import uuid

from django.conf import settings
from django.contrib.auth.models import Group
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from django.urls import reverse
from django.utils.functional import cached_property
from machina.apps.forum.abstract_models import AbstractForum
from storages.backends.s3boto3 import S3Boto3Storage

from lacommunaute.forum.enums import Kind as Forum_Kind
from lacommunaute.forum_conversation.models import Topic
from lacommunaute.forum_upvote.models import UpVote
from lacommunaute.utils.validators import validate_image_size


class ForumQuerySet(models.QuerySet):
Expand All @@ -28,6 +31,10 @@ class Forum(AbstractForum):
short_description = models.CharField(
max_length=400, blank=True, null=True, verbose_name="Description courte (SEO)"
)
image = models.ImageField(
storage=S3Boto3Storage(bucket_name=settings.AWS_STORAGE_BUCKET_NAME, file_overwrite=False),
validators=[validate_image_size],
)

upvotes = GenericRelation(UpVote, related_query_name="forum")

Expand Down
11 changes: 10 additions & 1 deletion lacommunaute/forum/tests/test_categoryforum_listview.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pytest_django.asserts import assertContains, assertNotContains

from lacommunaute.forum.enums import Kind as ForumKind
from lacommunaute.forum.factories import ForumFactory
from lacommunaute.forum.factories import CategoryForumFactory, ForumFactory
from lacommunaute.forum.models import Forum
from lacommunaute.users.factories import UserFactory

Expand Down Expand Up @@ -45,3 +45,12 @@ def test_display_create_category_button(client, db):
user.save()
response = client.get(url)
assertContains(response, reverse("forum_extension:create_category"), status_code=200)


def test_display_banners(client, db):
forum = CategoryForumFactory(with_child=True, with_public_perms=True)
ForumFactory(parent=forum, with_public_perms=True, with_image=True)
url = reverse("forum_extension:forum", kwargs={"pk": forum.pk, "slug": forum.slug})
response = client.get(url)
for child in forum.get_children():
assertContains(response, child.image.url.split("=")[0])
12 changes: 12 additions & 0 deletions lacommunaute/forum/tests/tests_model.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.conf import settings
from django.db import IntegrityError
from django.test import TestCase

Expand Down Expand Up @@ -57,3 +58,14 @@ def test_upvotes_count(self):
self.assertEqual(forum.upvotes_count(), 0)
forum.upvotes.create(voter=UserFactory())
self.assertEqual(forum.upvotes_count(), 1)

def test_image_is_imagefield(self):
forum = ForumFactory()
self.assertEqual(forum.image.field.__class__.__name__, "ImageField")

def test_image_url(self):
forum = ForumFactory(image="test.jpg")
self.assertEqual(
forum.image.url.split("?")[0], f"{settings.MEDIA_URL}{settings.AWS_STORAGE_BUCKET_NAME}/{forum.image.name}"
)
self.assertIn("AWSAccessKeyId=", forum.image.url)
6 changes: 6 additions & 0 deletions lacommunaute/forum/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,9 @@ def test_filtered_queryset_on_tag(self):
)
self.assertContains(response, topic.subject)
self.assertNotContains(response, self.topic.subject)

def test_banner_display_on_subcategory_forum(self):
category_forum = CategoryForumFactory(with_child=True, with_public_perms=True)
forum = category_forum.get_children().first()
response = self.client.get(reverse("forum_extension:forum", kwargs={"pk": forum.pk, "slug": forum.slug}))
self.assertContains(response, forum.image.url.split("=")[0])
9 changes: 1 addition & 8 deletions lacommunaute/forum_file/models.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from machina.models.abstract_models import DatedModel
from storages.backends.s3boto3 import S3Boto3Storage

from lacommunaute.users.models import User


def validate_image_size(value):
max_size = 1024 * 1024 * 8

if value.size > max_size:
raise ValidationError("L'image ne doit pas dépasser 1 Mo")
from lacommunaute.utils.validators import validate_image_size


class PublicFile(DatedModel):
Expand Down
6 changes: 0 additions & 6 deletions lacommunaute/forum_file/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,5 @@ def test_get_file_url(db, public_file):
assert public_file.get_file_url() == expected_file_url


def test_size_validator(db, public_file):
with pytest.raises(Exception):
public_file.file.size = 1024 * 1024 * 8 + 1
public_file.save()


def test_file_field_is_imagefield(db):
assert isinstance(PublicFile._meta.get_field("file"), ImageField)
3 changes: 2 additions & 1 deletion lacommunaute/templates/forum/forum_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ <h1>{{ forum.name }}</h1>
{% include "partials/upvotes.html" with obj=forum kind="forum" %}
{% include "partials/social_share_buttons.html" with text=forum.name instance=forum id=forum.pk %}
</div>
<div class="col-12 col-sm-auto">
<div class="col-12 col-sm-auto">{% include "forum/partials/forum_banner.html" with forum=forum only %}</div>
<div class="col-12 col-sm-auto mt-3">
<div class="textarea_cms_md">{{ forum.description.rendered|urlizetrunc_target_blank:30 }}</div>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion lacommunaute/templates/forum/forum_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ <h3 class="h3 mb-0">
<p class="h3 lh-base">
<i class="ri-newspaper-line font-weight-normal"></i> {{ node.obj.name }}
</p>
{% if node.obj.short_description %}<div>{{ node.obj.short_description }}</div>{% endif %}
<div>{% include "forum/partials/forum_banner.html" with forum=node.obj only %}</div>
{% if node.obj.short_description %}<div class="mt-3">{{ node.obj.short_description }}</div>{% endif %}
</div>
<div class="card-footer text-end">
<a href="{% url 'forum_extension:forum' node.obj.slug node.obj.id %}"
Expand Down
5 changes: 5 additions & 0 deletions lacommunaute/templates/forum/partials/forum_banner.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% if forum.image %}
<div class="d-none d-md-block forum-image mt-3">
<img src="{{ forum.image.url }}" alt="{{ forum.name }}" class="rounded img-fluid" />
</div>
{% endif %}
15 changes: 15 additions & 0 deletions lacommunaute/utils/tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from datetime import datetime, timedelta
from unittest.mock import patch

import pytest
from bs4 import BeautifulSoup
from django.core.files.storage import default_storage
from django.core.files.uploadedfile import SimpleUploadedFile
Expand All @@ -19,6 +20,8 @@
from lacommunaute.forum.factories import ForumFactory
from lacommunaute.forum_conversation.factories import TopicFactory
from lacommunaute.forum_conversation.forum_attachments.factories import AttachmentFactory
from lacommunaute.forum_file.models import PublicFile
from lacommunaute.users.factories import UserFactory
from lacommunaute.utils.math import percent
from lacommunaute.utils.matomo import get_matomo_data, get_matomo_events_data, get_matomo_visits_data
from lacommunaute.utils.perms import add_public_perms_on_forum
Expand Down Expand Up @@ -502,3 +505,15 @@ def test_public_perms(self, db):
).count()
== 7
)


class TestImageSizeValidator:
def test_size_validator(self, db):
file = PublicFile.objects.create(
file="test.jpg",
user=UserFactory(),
keywords="test",
)
with pytest.raises(Exception):
file.file.size = 1024 * 1024 * 5 + 1
file.save()
8 changes: 8 additions & 0 deletions lacommunaute/utils/validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.core.exceptions import ValidationError


def validate_image_size(value):
max_size = 1024 * 1024 * 5

if value.size > max_size:
raise ValidationError("L'image ne doit pas dépasser 5 Mo")
Loading