Skip to content

Commit 6b64e5a

Browse files
committed
Updated SnippetList new feature.
1 parent a72e876 commit 6b64e5a

File tree

17 files changed

+202
-177
lines changed

17 files changed

+202
-177
lines changed

base/components/components.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from typing import Literal, Optional
2+
3+
from django_components import Component, register
4+
from pydantic import BaseModel
5+
6+
from base.pagination import PAGE_VAR, Pagination
7+
from base.templatetags.base_templatetags import querystring
8+
9+
10+
class PaginationItem(BaseModel):
11+
kind: Literal["current", "ellipsis", "number"]
12+
text: Optional[str | int] = None
13+
attrs: Optional[dict] = None
14+
15+
16+
@register("pagination")
17+
class PaginationComponent(Component):
18+
template_file = "pagination.html"
19+
20+
class Kwargs(BaseModel):
21+
pagination_obj: Pagination
22+
model_config = {"arbitrary_types_allowed": True}
23+
24+
def pagination_number(self, pagination: Pagination, num: str | int) -> PaginationItem:
25+
"""
26+
Generates a list of `PaginatedItem`, each representing an individual page with
27+
its associated properties in a pagination navigation list.
28+
"""
29+
if num == pagination.paginator.ELLIPSIS:
30+
return PaginationItem(kind="ellipsis", text=str(pagination.paginator.ELLIPSIS))
31+
elif num == pagination.page_num:
32+
return PaginationItem(kind="current", text=num)
33+
else:
34+
link = querystring(None, {**pagination.params, PAGE_VAR: num})
35+
return PaginationItem(
36+
kind="number",
37+
text=num,
38+
attrs={"href": link},
39+
)
40+
41+
def get_template_data(self, args, kwargs, slots, context):
42+
pagination = kwargs.pagination_obj
43+
page_elements = [self.pagination_number(pagination, page_num) for page_num in pagination.page_range]
44+
previous_page_link = f"?{PAGE_VAR}={pagination.page_num - 1}" if pagination.page.has_previous() else ""
45+
next_page_link = f"?{PAGE_VAR}={pagination.page_num + 1}" if pagination.page.has_next() else ""
46+
return {
47+
"pagination": pagination,
48+
"previous_page_link": previous_page_link,
49+
"next_page_link": next_page_link,
50+
"page_elements": page_elements,
51+
}

base/components/pagination.html

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{% if pagination.multi_page %}
2+
<nav class="justify-center my-8" aria-labelledby="pagination">
3+
<h2 id="pagination" class="sr-only">Pagination {{ pagination.opts.verbose_name_plural }}</h2>
4+
<ul class="flex justify-center gap-2 transition-colors duration-200 ease-out ml-0">
5+
<li>
6+
<a class="py-[5px] px-[10px] mr-2 no-underline rounded-lg border-1 border-transparent text-base hover:border-base-orange-400 {% if previous_page_link == '' %}text-base-gray-400 hover:border-transparent cursor-default{% endif %}" href="{{ previous_page_link }}" rel="prev" aria-label="Previous page">
7+
<span class="arrow-left inline-flex items-center">Previous</span>
8+
</a>
9+
</li>
10+
{% with page_link_css="py-[5px] px-[10px] border-1 border-transparent rounded-lg no-underline hover:border-base-orange-400" %}
11+
{% for page_item in page_elements %}
12+
<li class="inline-block">
13+
{% if page_item.kind == 'ellipsis' %}
14+
{{ page_item.text }}
15+
{% elif page_item.kind == 'current' %}
16+
<a href="" class="{{ page_link_css }} bg-base-orange-400 text-base-white-400 cursor-default" aria-current="page">{{ page_item.text }}</a>
17+
{% else %}
18+
<a {% html_attrs page_item.attrs class=page_link_css %}>{{ page_item.text }}</a>
19+
{% endif %}
20+
</li>
21+
{% endfor %}
22+
{% endwith %}
23+
<li>
24+
<a class="py-[5px] px-[10px] ml-2 no-underline rounded-lg border-1 border-transparent text-base hover:border-base-orange-400 {% if next_page_link == '' %}text-base-gray-400 hover:border-transparent cursor-default{% endif %}" href="{{ next_page_link }}" rel="next" aria-label="Next page">
25+
<span class="arrow-right inline-flex items-center">Next</span>
26+
</a>
27+
</li>
28+
</ul>
29+
</nav>
30+
{% endif %}

base/main.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from .pagination import PAGE_VAR, Pagination
2+
3+
4+
class ObjectList:
5+
pagination_class = Pagination
6+
7+
def __init__(self, request, model, queryset, list_per_page):
8+
self.model = model
9+
self.queryset = queryset
10+
self.list_per_page = list_per_page
11+
self.params = dict(request.GET.lists())
12+
if PAGE_VAR in self.params:
13+
del self.params[PAGE_VAR]
14+
self.result_objects = self.get_objects(request)
15+
16+
def paginate(self, request, queryset):
17+
pagination = self.pagination_class(
18+
request,
19+
self.model,
20+
queryset,
21+
self.list_per_page,
22+
)
23+
self.pagination = pagination
24+
return pagination.get_objects()
25+
26+
def get_objects(self, request):
27+
paginate_result = self.paginate(request, self.queryset)
28+
return paginate_result

base/templatetags/components.py

Lines changed: 0 additions & 40 deletions
This file was deleted.

cab/components/components.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from django_components import Component, register
2+
from pydantic import BaseModel
3+
4+
from base.main import ObjectList
5+
6+
7+
@register("snippet_list")
8+
class SnippetListComponent(Component):
9+
10+
template_file = "templates/snippet_list.html"
11+
12+
class Kwargs(BaseModel):
13+
snippet_list: ObjectList
14+
model_config = {"arbitrary_types_allowed": True}
15+
16+
def get_template_data(self, args, kwargs, slots, context):
17+
return {
18+
"snippet_list": kwargs.snippet_list.result_objects,
19+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<section class="border-2 border-base-green-400 rounded-sm" aria-labelledby="snippet-list-title">
2+
<h2 id="snippet-list-title" class="sr-only">Snippet List</h2>
3+
{% for snippet in snippet_list %}
4+
<article class="relative flex flex-col px-8 pt-4 pb-1 border-b-2 border-base-green-400 last:border-b-0 lg:flex-row">
5+
<div class="flex flex-row justify-start gap-3 text-sm md:text-base lg:my-6 lg:w-1/5 lg:flex-col">
6+
<span>{{ snippet.rating_score }} rating</span>
7+
<span>{{ snippet.bookmark_count }} bookmark</span>
8+
</div>
9+
<div class="flex flex-col lg:w-4/5">
10+
<h3 class="py-2 my-0 text-lg md:text-2xl">
11+
<a href="{{ snippet.get_absolute_url }}" class="text-base-green-400 hover:text-base-green-800 underline underline-offset-8 decoration-3 decoration-base-orange-400 hover:decoration-10 duration-500">{{ snippet.title|truncatechars:"80" }}</a>
12+
</h3>
13+
<p class="mb-0 py-4 min-h-[4rem] text-xs md:text-sm">{{ snippet.description|truncatechars:"250" }}</p>
14+
<footer class="flex flex-col flex-wrap py-2 text-xs md:text-sm">
15+
<div class="my-1">
16+
<strong class="text-sm md:text-base mr-2">Tags : </strong>
17+
<ul class="inline-flex gap-2 flex-wrap list-none m-0 text-xs md:text-sm">{% for tag in snippet.tags.all %}<li class="my-2 inline"><a href="{% url 'cab_snippet_matches_tag' tag.slug %}" class="py-1.5 px-2 text-white border-2 bg-base-green-400 border-base-green-400 rounded-lg hover:bg-base-white hover:text-base-green-400 duration-500 transition-colors no-underline">{{ tag.name }}</a></li>{% endfor %}</ul>
18+
</div>
19+
<p class="text-start">
20+
<strong class="text-sm md:text-base">Author : </strong>
21+
<a href="{{ snippet.author.get_absolute_url }}" class="text-base-green-400 underline underline-offset-4 hover:text-base-green-800">{{ snippet.author.username }}</a>
22+
<span class="mx-2" aria-hidden="true"> | </span>
23+
<strong class="text-sm md:text-base">Updated : </strong>
24+
<time>{{ snippet.updated_date }}</time>
25+
</p>
26+
</footer>
27+
</div>
28+
</article>
29+
{% endfor %}
30+
</section>

cab/utils.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.utils.safestring import mark_safe
88
from markdown import markdown as markdown_func
99

10+
from base.main import ObjectList
1011
from base.pagination import Pagination
1112

1213

@@ -35,23 +36,29 @@ def object_list(
3536
hits
3637
number of objects, total
3738
"""
39+
from cab.models import Snippet
40+
3841
if extra_context is None:
3942
extra_context = {}
4043
queryset = queryset._clone()
4144
model = queryset.model
4245
opts = model._meta
4346
if paginate_by:
44-
pagination = Pagination(request, model, queryset, paginate_by)
45-
object_list = pagination.get_objects()
47+
if queryset.model == Snippet:
48+
object_list = ObjectList(request, queryset.model, queryset, 15)
49+
pagination = object_list.pagination
50+
else:
51+
pagination = Pagination(request, model, queryset, paginate_by)
52+
object_list = pagination.get_objects()
4653

4754
context = {
48-
"%s_list" % template_object_name: object_list,
55+
"object_list": object_list,
4956
"pagination": pagination,
5057
"hits": pagination.result_count,
5158
}
5259
else:
5360
context = {
54-
"%s_list" % template_object_name: object_list,
61+
"object_list": queryset,
5562
}
5663
if not allow_empty and len(queryset) == 0:
5764
raise Http404

djangosnippets/templates/base.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
</ul>
3636
</nav>
3737
</div></header>
38-
<div id="main">
38+
<div id="main" class="container mb-auto mx-auto w-7/8">
3939
{% block secondary_nav %}
4040
<nav id="subnav">
4141
<ul>
@@ -59,14 +59,16 @@
5959

6060
<div id="base-container">
6161
<h1>{% block content_header %}{% endblock %}</h1>
62-
<div id="content">
62+
{% with current_url_name=request.resolver_match.url_name %}
63+
<div id="content" class="{% if current_url_name == 'home' %}w-1/2{% else %}w-full md:w-3/4{% endif %}">
6364
{% block content %}
6465
{% endblock %}
6566
</div>
66-
<div id="sidebar">
67+
<div id="sidebar" class="{% if current_url_name == 'home' %}w-1/2{% else %}hidden md:block md:w-1/4{% endif %}">
6768
{% block sidebar %}
6869
{% endblock %}
6970
</div>
71+
{% endwith %}
7072
{% block extra_content %}
7173
{% endblock %}
7274
</div>

djangosnippets/templates/cab/language_list.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{% extends "base.html" %}
2-
{% load core_tags components %}
2+
{% load core_tags %}
33

44
{% block head_title %}All languages{% endblock %}
55

@@ -12,6 +12,6 @@
1212
{% endfor %}
1313
</ul>
1414

15-
{% pagination pagination %}
15+
{% component "pagination" pagination_obj=pagination / %}
1616

1717
{% endblock %}

djangosnippets/templates/cab/partials/language_list.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{% load static components %}
1+
{% load static %}
22

33

44
<img class="bars" src="{% static 'img/bars.svg' %}"/>
@@ -10,5 +10,5 @@ <h1>All languages</h1>
1010
{% endfor %}
1111
</ul>
1212

13-
{% pagination pagination %}
13+
{% component "pagination" pagination_obj=pagination / %}
1414
</div>

0 commit comments

Comments
 (0)