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

[DO NOT MERGE] simplifier la gestion des catégories de documentation #775

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft
4 changes: 3 additions & 1 deletion clevercloud/collect_weekly_matomo_forum_stats.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ fi
# $APP_HOME is set by default by clever cloud.
cd $APP_HOME

python manage.py collect_matomo_forum_stats
# reactivate after documentation migration
# python manage.py collect_matomo_forum_stats
echo "Collecting weekly matomo stats for the forum is disabled for now."
1 change: 1 addition & 0 deletions config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"lacommunaute.search",
"lacommunaute.surveys",
"lacommunaute.partner",
"lacommunaute.documentation",
]

INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS + THIRD_PARTIES_APPS
Expand Down
2 changes: 2 additions & 0 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.urls import include, path, re_path
from machina.core.loading import get_class

from lacommunaute.documentation import urls as documentation_urls
from lacommunaute.event import urls as event_urls
from lacommunaute.forum import urls as forum_extension_urls
from lacommunaute.forum_conversation import urls as forum_conversation_extension_urls
Expand All @@ -30,6 +31,7 @@
path("inclusion_connect/", include(inclusion_connect_urls)),
# www.
path("", include(pages_urls)),
path("documentation/", include(documentation_urls)),
path("members/", include(forum_member_urls)),
path("", include(forum_conversation_extension_urls)),
path("", include(forum_extension_urls)),
Expand Down
Empty file.
38 changes: 38 additions & 0 deletions lacommunaute/documentation/abstract_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from django.conf import settings
from django.db import models
from django.utils.encoding import force_str
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from machina.models.fields import MarkupTextField
from storages.backends.s3boto3 import S3Boto3Storage

from lacommunaute.utils.validators import validate_image_size


class AbstractDatedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
abstract = True


class AbstractPublication(AbstractDatedModel):
name = models.CharField(max_length=100, verbose_name=_("Name"))
slug = models.SlugField(max_length=255, verbose_name=_("Slug"), unique=True)

description = MarkupTextField(verbose_name=_("Description"), null=True, blank=True)
short_description = models.CharField(max_length=400, verbose_name="Description courte (SEO)")
image = models.ImageField(
blank=True,
null=True,
storage=S3Boto3Storage(bucket_name=settings.AWS_STORAGE_BUCKET_NAME, file_overwrite=False),
validators=[validate_image_size],
)

class Meta:
abstract = True

def save(self, *args, **kwargs):
self.slug = slugify(force_str(self.name), allow_unicode=True)
super().save(*args, **kwargs)
40 changes: 40 additions & 0 deletions lacommunaute/documentation/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from django.contrib import admin

from lacommunaute.documentation.models import Category, Document, DocumentRating


class DocumentInlines(admin.TabularInline):
model = Document
extra = 0
fields = ("name", "short_description")
readonly_fields = ("name", "short_description")

def has_delete_permission(self, request, obj=None):
return False

def has_add_permission(self, request, obj=None):
return False


@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ("name",)
search_fields = ("name",)
fields = ("name", "short_description", "description", "image")
inlines = [DocumentInlines]


@admin.register(Document)
class DocumentAdmin(admin.ModelAdmin):
list_display = ("name", "category")
list_filter = ("category",)
search_fields = ("name",)
fields = ("name", "short_description", "description", "image")


@admin.register(DocumentRating)
class DocumentRatingAdmin(admin.ModelAdmin):
list_display = ("document", "rating", "created_at")
list_filter = ("document",)
list_display_links = ("rating",)
raw_id_fields = ("document", "user")
8 changes: 8 additions & 0 deletions lacommunaute/documentation/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.apps import AppConfig


class ForumUpVoteAppConfig(AppConfig):
label = "documentation"
name = "lacommunaute.documentation"
verbose_name = "Documentation"
verbose_name_plural = "Documentation"
48 changes: 48 additions & 0 deletions lacommunaute/documentation/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import factory
from faker import Faker

from lacommunaute.documentation.models import Category, Document


faker = Faker()


class AbstractDocumentationFactory(factory.django.DjangoModelFactory):
name = factory.Faker("name")
description = factory.Faker("sentence", nb_words=100)
short_description = factory.Faker("sentence", nb_words=10)
image = factory.django.ImageField(filename="banner.jpg")


class CategoryFactory(AbstractDocumentationFactory):
class Meta:
model = Category

class Params:
for_snapshot = factory.Trait(
name="Test Category", description="Test description", short_description="Test short description"
)


class DocumentFactory(AbstractDocumentationFactory):
category = factory.SubFactory(CategoryFactory)

class Meta:
model = Document

class Params:
for_snapshot = factory.Trait(
name="Test Document",
description="Test description",
short_description="Test short description",
category=factory.SubFactory(CategoryFactory, for_snapshot=True),
)

@factory.post_generation
def with_tags(self, create, extracted, **kwargs):
if not create or not extracted:
return

if isinstance(extracted, list):
for tag in extracted:
self.tags.add(tag)
81 changes: 81 additions & 0 deletions lacommunaute/documentation/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from django import forms
from django.conf import settings
from taggit.models import Tag

from lacommunaute.documentation.models import Category, Document
from lacommunaute.partner.models import Partner
from lacommunaute.utils.iframe import wrap_iframe_in_div_tag


class DocumentationFormMixin:
name = forms.CharField(required=True, label="Titre")
short_description = forms.CharField(
widget=forms.Textarea(attrs={"rows": 3}),
max_length=400,
required=True,
label="Sous-titre (400 caractères pour le SEO)",
)
description = forms.CharField(
widget=forms.Textarea(attrs={"rows": 20}), required=True, label="Contenu (markdown autorisé)"
)
image = forms.ImageField(
label="Banniere de couverture, format 1200 x 630 pixels recommandé",
widget=forms.FileInput(attrs={"accept": settings.SUPPORTED_IMAGE_FILE_TYPES.keys()}),
)

def save(self, commit=True):
instance = super().save(commit=False)
instance.description = wrap_iframe_in_div_tag(self.cleaned_data.get("description"))

if commit:
instance.save()
return instance


class CategoryForm(forms.ModelForm, DocumentationFormMixin):
class Meta:
model = Category
fields = ["name", "short_description", "description", "image"]


class DocumentForm(forms.ModelForm, DocumentationFormMixin):
certified = forms.BooleanField(required=False, label="Certifiée par la communauté de l'inclusion")
partner = forms.ModelChoiceField(
label="Sélectionner un partenaire",
queryset=Partner.objects.all(),
required=False,
)
category = forms.ModelChoiceField(
label="Sélectionner une catégorie documentaire",
queryset=Category.objects.all(),
required=False,
)
tags = forms.ModelMultipleChoiceField(
label="Sélectionner un ou plusieurs tags",
queryset=Tag.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
new_tags = forms.CharField(required=False, label="Ajouter un tag ou plusieurs tags (séparés par des virgules)")

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.pk:
self.fields["tags"].initial = self.instance.tags.all()

def save(self, commit=True):
instance = super().save(commit=False)

if commit:
instance.save()
instance.tags.set(self.cleaned_data["tags"])
(
instance.tags.add(*[tag.strip() for tag in self.cleaned_data["new_tags"].split(",")])
if self.cleaned_data.get("new_tags")
else None
)
return instance

class Meta:
model = Document
fields = ["name", "short_description", "description", "image", "certified", "partner", "category"]
Loading
Loading