Coverage for src / ptf_tools / views / components / breadcrumb.py: 29%
63 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-08-03 13:45 +0000
« prev ^ index » next coverage.py v7.13.2, created at 2026-08-03 13:45 +0000
1from __future__ import annotations
3from typing import TYPE_CHECKING
5from django.urls import reverse
6from django.utils.translation import gettext as translate_text
7from django.utils.translation import gettext_lazy as _
8from ptf.models import ResourceVisitor
9from ptf.views.components.breadcrumb import (
10 Breadcrumb,
11 BreadcrumbItem,
12 get_next_article,
13 get_previous_article,
14)
16if TYPE_CHECKING:
17 from ptf.models import Article, Collection, Container, Resource
20def get_trammel_base_breadcrumb() -> Breadcrumb:
21 return Breadcrumb(
22 items=[
23 BreadcrumbItem(
24 title=_("Home"),
25 url=reverse("home"),
26 icon_class="bi-house",
27 )
28 ]
29 )
32def get_trammel_breadcrumb(resource: Resource) -> Breadcrumb:
33 visitor = TrammelBreadcrumbVisitor()
34 return resource.accept(visitor)
37class TrammelBreadcrumbVisitor(ResourceVisitor):
38 def __init__(self):
39 super().__init__()
40 self.crumb = get_trammel_base_breadcrumb()
42 def visit(self, resource):
43 method = getattr(self, f"visit_{resource.classname.lower()}")
44 return method(resource)
46 def visit_collection(self, collection: Collection) -> Breadcrumb:
47 self._add_collection_item(collection)
48 return self.crumb
50 def visit_container(self, container: Container) -> Breadcrumb:
51 collection = container.get_top_collection()
53 self._add_collection_item(collection)
54 self._add_container_item(container)
56 return self.crumb
58 def visit_article(self, article: Article) -> Breadcrumb:
59 collection = article.get_top_collection()
60 container = article.get_container()
62 self._add_collection_item(collection)
64 if container is not None:
65 self._add_container_item(container)
67 self._add_article_item(article)
68 self._set_next_previous_article_items(article)
70 return self.crumb
72 def _add_collection_item(self, collection: Collection) -> None:
73 self.crumb.add_item(
74 title=collection.title_html or collection.title_tex or collection.pid,
75 url=self._collection_url(collection),
76 html=True,
77 )
79 def _add_container_item(self, container: Container) -> None:
80 self.crumb.add_item(
81 title=self._container_title(container),
82 url=self._container_url(container),
83 html=True,
84 )
86 def _add_article_item(self, article: Article) -> None:
87 self.crumb.add_item(
88 title=article.get_breadcrumb_page_text(),
89 url=article.get_absolute_url(),
90 html=True,
91 )
93 def _set_next_previous_article_items(self, article: Article) -> None:
94 next_article = get_next_article(article)
95 if next_article is not None:
96 self.crumb.nextItem = BreadcrumbItem(
97 title=translate_text("Suivant"),
98 url=next_article.get_absolute_url(),
99 )
101 previous_article = get_previous_article(article)
102 if previous_article is not None:
103 self.crumb.previousItem = BreadcrumbItem(
104 title=translate_text("Précédent"),
105 url=previous_article.get_absolute_url(),
106 )
108 def _collection_url(self, collection: Collection) -> str:
109 return reverse("collection-detail", kwargs={"pid": collection.pid})
111 def _container_url(self, container: Container) -> str:
112 return reverse("issue-items", kwargs={"pid": container.pid})
114 def _container_title(self, container: Container) -> str:
115 if container.title_html:
116 return container.title_html
118 if container.number:
119 return f"no. {container.number}"
121 if container.volume:
122 return f"Volume {container.volume}"
124 if container.year_str:
125 return container.year_str
127 return container.pid