Skip to content

Commit

Permalink
Permet d'écrire des billets ou articles avec une structure de tutoriel
Browse files Browse the repository at this point in the history
  • Loading branch information
Arnaud-D committed Oct 28, 2023
1 parent 0a733a7 commit 1f3ebae
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 44 deletions.
7 changes: 0 additions & 7 deletions zds/tutorialv2/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@
# verbose_name_plural User-friendly pluralized type name
# category_name User-friendly category name which contains this content
# requires_validation Boolean; whether this content has to be validated before publication
# single_container Boolean; True if the content is a single container
# beta Boolean; True if the content can be in beta
{
"name": "TUTORIAL",
"verbose_name": "tutoriel",
"verbose_name_plural": "tutoriels",
"category_name": "tutoriel",
"requires_validation": True,
"single_container": False,
"beta": True,
},
{
Expand All @@ -25,7 +23,6 @@
"verbose_name_plural": "articles",
"category_name": "article",
"requires_validation": True,
"single_container": True,
"beta": True,
},
{
Expand All @@ -34,7 +31,6 @@
"verbose_name_plural": "billets",
"category_name": "tribune",
"requires_validation": False,
"single_container": True,
"beta": False,
},
)
Expand All @@ -49,9 +45,6 @@
# a list of contents which have to be validated before publication
CONTENT_TYPES_REQUIRING_VALIDATION = [content["name"] for content in CONTENT_TYPES if content["requires_validation"]]

# a list of contents which have one big container containing at least one small container
SINGLE_CONTAINER_CONTENT_TYPES = [content["name"] for content in CONTENT_TYPES if content["single_container"]]

# a list of contents which can be in beta
CONTENT_TYPES_BETA = [content["name"] for content in CONTENT_TYPES if content["beta"]]

Expand Down
29 changes: 12 additions & 17 deletions zds/tutorialv2/models/versioned.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import contextlib
import copy
from pathlib import Path
from typing import List

from zds import json_handler
from git import Repo
Expand All @@ -15,7 +16,7 @@
from django.template.loader import render_to_string

from zds.tutorialv2.models.mixins import TemplatableContentModelMixin
from zds.tutorialv2.models import SINGLE_CONTAINER_CONTENT_TYPES, CONTENT_TYPES_REQUIRING_VALIDATION
from zds.tutorialv2.models import CONTENT_TYPES_REQUIRING_VALIDATION
from zds.tutorialv2.utils import default_slug_pool, export_content, get_commit_author, InvalidOperationError
from zds.tutorialv2.utils import get_blob
from zds.utils.validators import InvalidSlugError, check_slug
Expand Down Expand Up @@ -265,8 +266,7 @@ def can_add_container(self):
"""
if not self.has_extracts():
if self.get_tree_depth() < settings.ZDS_APP["content"]["max_tree_depth"] - 1:
if not self.top_container().type in SINGLE_CONTAINER_CONTENT_TYPES:
return True
return True
return False

def can_add_extract(self):
Expand Down Expand Up @@ -1331,21 +1331,16 @@ def get_prod_path(self, relative=False, file_ext="html"):

return path

def get_list_of_chapters(self):
"""
:return: a list of chapters (Container which contains Extracts) in the reading order
:rtype: list[Container]
"""
def get_list_of_chapters(self) -> list[Container]:
continuous_list = []
if self.type not in SINGLE_CONTAINER_CONTENT_TYPES: # cannot be paginated
if len(self.children) != 0 and isinstance(self.children[0], Container): # children must be Containers!
for child in self.children:
if len(child.children) != 0:
if isinstance(child.children[0], Extract):
continuous_list.append(child) # it contains Extract, this is a chapter, so paginated
else: # Container is a part
for sub_child in child.children:
continuous_list.append(sub_child) # even if empty `sub_child.childreen`, it's chapter
if len(self.children) != 0 and isinstance(self.children[0], Container): # children must be Containers!
for child in self.children:
if len(child.children) != 0:
if isinstance(child.children[0], Extract):
continuous_list.append(child) # it contains Extract, this is a chapter, so paginated
else: # Container is a part
for sub_child in child.children:
continuous_list.append(sub_child) # even if empty `sub_child.childreen`, it's chapter
return continuous_list

def get_json(self):
Expand Down
8 changes: 0 additions & 8 deletions zds/tutorialv2/tests/tests_opinion_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,6 @@ def test_accessible_ui_for_author(self):
self.assertNotContains(resp, "{}?subcategory=".format(reverse("publication:list")))
self.assertContains(resp, "{}?category=".format(reverse("opinion:list")))

def test_no_help_for_tribune(self):
self.client.force_login(self.user_author)

def test_help_for_article(self):
self.client.force_login(self.user_author)
resp = self.client.get(reverse("content:create-content", kwargs={"created_content_type": "ARTICLE"}))
self.assertEqual(200, resp.status_code)

def test_opinion_publication_staff(self):
"""
Test the publication of PublishableContent where type is OPINION (with staff).
Expand Down
96 changes: 96 additions & 0 deletions zds/tutorialv2/tests/tests_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from django.test import TestCase
from django.urls import reverse

from zds.tutorialv2.models.database import PublishableContent
from zds.tutorialv2.publication_utils import publish_content
from zds.tutorialv2.tests import override_for_contents, TutorialTestMixin
from zds.tutorialv2.tests.factories import PublishableContentFactory, ContainerFactory


@override_for_contents()
class BasicRouteTests(TestCase, TutorialTestMixin):
def setUp(self):
self.build_content(self.content_type)
self.mock_publication_process(self.content)

def build_content(self, type):
self.content = PublishableContentFactory()
self.content.type = type
self.content.save()
content_versioned = self.content.load_version()
self.container = ContainerFactory(parent=content_versioned, db_object=self.content)
self.subcontainer = ContainerFactory(parent=self.container, db_object=self.content)

def assert_can_be_reached(self, route, route_args):
url = reverse(route, kwargs=route_args)
response = self.client.get(url)
self.assertEqual(response.status_code, 200)

def mock_publication_process(self, content: PublishableContent):
published = publish_content(content, content.load_version())
content.sha_public = content.sha_draft
content.public_version = published
content.save()


class OpinionDisplayRoutesTests(BasicRouteTests):
content_type = "OPINION"

def test_view(self):
route = "opinion:view"
route_args = {
"pk": self.content.pk,
"slug": self.content.slug,
}
self.assert_can_be_reached(route, route_args)

def test_view_container_one_level_deep(self):
route = "opinion:view-container"
route_args = {
"pk": self.content.pk,
"slug": self.content.slug,
"container_slug": self.container.slug,
}
self.assert_can_be_reached(route, route_args)

def test_view_container_two_level_deep(self):
route = "opinion:view-container"
route_args = {
"pk": self.content.pk,
"slug": self.content.slug,
"parent_container_slug": self.container.slug,
"container_slug": self.subcontainer.slug,
}
self.assert_can_be_reached(route, route_args)


@override_for_contents()
class ArticlesDisplayRoutesTests(BasicRouteTests):
content_type = "ARTICLE"

def test_view(self):
route = "article:view"
route_args = {
"pk": self.content.pk,
"slug": self.content.slug,
}
self.assert_can_be_reached(route, route_args)

def test_view_container_one_level_deep(self):
route = "article:view-container"
route_args = {
"pk": self.content.pk,
"slug": self.content.slug,
"container_slug": self.container.slug,
}
self.assert_can_be_reached(route, route_args)

def test_view_container_two_level_deep(self):
route = "article:view-container"
route_args = {
"pk": self.content.pk,
"slug": self.content.slug,
"parent_container_slug": self.container.slug,
"container_slug": self.subcontainer.slug,
}
self.assert_can_be_reached(route, route_args)
25 changes: 19 additions & 6 deletions zds/tutorialv2/urls/urls_articles.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,33 @@
from zds.tutorialv2.views.contributors import ContentOfContributors
from zds.tutorialv2.views.lists import TagsListView, ContentOfAuthor
from zds.tutorialv2.views.download_online import DownloadOnlineArticle
from zds.tutorialv2.views.display import ArticleOnlineView
from zds.tutorialv2.views.display import ArticleOnlineView, ContainerOnlineView
from zds.tutorialv2.feeds import LastArticlesFeedRSS, LastArticlesFeedATOM

urlpatterns = [
# Flux
feed_patterns = [
path("flux/rss/", LastArticlesFeedRSS(), name="feed-rss"),
path("flux/atom/", LastArticlesFeedATOM(), name="feed-atom"),
# View
]

display_patterns = [
path("<int:pk>/<slug:slug>/", ArticleOnlineView.as_view(), name="view"),
# Downloads
path(
"<int:pk>/<slug:slug>/<slug:parent_container_slug>/<slug:container_slug>/",
ContainerOnlineView.as_view(),
name="view-container",
),
path("<int:pk>/<slug:slug>/<slug:container_slug>/", ContainerOnlineView.as_view(), name="view-container"),
]

download_patterns = [
path("md/<int:pk>/<slug:slug>.md", DownloadOnlineArticle.as_view(requested_file="md"), name="download-md"),
path("pdf/<int:pk>/<slug:slug>.pdf", DownloadOnlineArticle.as_view(requested_file="pdf"), name="download-pdf"),
path("tex/<int:pk>/<slug:slug>.tex", DownloadOnlineArticle.as_view(requested_file="tex"), name="download-tex"),
path("epub/<int:pk>/<slug:slug>.epub", DownloadOnlineArticle.as_view(requested_file="epub"), name="download-epub"),
path("zip/<int:pk>/<slug:slug>.zip", DownloadOnlineArticle.as_view(requested_file="zip"), name="download-zip"),
# Listing
]

listing_patterns = [
path("", RedirectView.as_view(pattern_name="publication:list", permanent=True)),
re_path(r"tags/*", TagsListView.as_view(displayed_types=["ARTICLE"]), name="tags"),
path(
Expand All @@ -33,3 +44,5 @@
name="find-contributions-article",
),
]

urlpatterns = feed_patterns + display_patterns + download_patterns + listing_patterns
25 changes: 19 additions & 6 deletions zds/tutorialv2/urls/urls_opinions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,38 @@
from zds.tutorialv2.feeds import LastOpinionsFeedRSS, LastOpinionsFeedATOM
from zds.tutorialv2.views.lists import ListOpinions, ContentOfAuthor
from zds.tutorialv2.views.download_online import DownloadOnlineOpinion
from zds.tutorialv2.views.display import OpinionOnlineView
from zds.tutorialv2.views.display import OpinionOnlineView, ContainerOnlineView

urlpatterns = [
# Flux
feed_patterns = [
path("flux/rss/", LastOpinionsFeedRSS(), name="feed-rss"),
path("flux/atom/", LastOpinionsFeedATOM(), name="feed-atom"),
# View
]

display_patterns = [
path("<int:pk>/<slug:slug>/", OpinionOnlineView.as_view(), name="view"),
# downloads:
path(
"<int:pk>/<slug:slug>/<slug:parent_container_slug>/<slug:container_slug>/",
ContainerOnlineView.as_view(),
name="view-container",
),
path("<int:pk>/<slug:slug>/<slug:container_slug>/", ContainerOnlineView.as_view(), name="view-container"),
]

download_patterns = [
path("md/<int:pk>/<slug:slug>.md", DownloadOnlineOpinion.as_view(requested_file="md"), name="download-md"),
path("pdf/<int:pk>/<slug:slug>.pdf", DownloadOnlineOpinion.as_view(requested_file="pdf"), name="download-pdf"),
path("epub/<int:pk>/<slug:slug>.epub", DownloadOnlineOpinion.as_view(requested_file="epub"), name="download-epub"),
path("zip/<int:pk>/<slug:slug>.zip", DownloadOnlineOpinion.as_view(requested_file="zip"), name="download-zip"),
path("tex/<int:pk>/<slug:slug>.tex", DownloadOnlineOpinion.as_view(requested_file="tex"), name="download-tex"),
# Listing
]

listing_patterns = [
path("", ListOpinions.as_view(), name="list"),
path(
"voir/<str:username>/",
ContentOfAuthor.as_view(type="OPINION", context_object_name="opinions"),
name="find-opinion",
),
]

urlpatterns = feed_patterns + display_patterns + download_patterns + listing_patterns

0 comments on commit 1f3ebae

Please sign in to comment.