Skip to content

Commit 328ea8a

Browse files
committed
Added sorting tab to snippet list.
1 parent 8c3c764 commit 328ea8a

File tree

9 files changed

+102
-14
lines changed

9 files changed

+102
-14
lines changed

base/components/components.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django_components import Component, register
44
from pydantic import BaseModel
55

6+
from base.main import TAB_VAR, ObjectList
67
from base.pagination import PAGE_VAR, Pagination
78
from base.templatetags.base_templatetags import querystring
89

@@ -68,3 +69,35 @@ def get_template_data(self, args, kwargs, slots, context):
6869
"next_page_link": next_page_link,
6970
"page_elements": page_elements,
7071
}
72+
73+
74+
class TabItem(BaseModel):
75+
text: str
76+
is_current: bool
77+
attrs: Optional[dict]
78+
79+
80+
@register("sorting_tabs")
81+
class SortingTabs(Component):
82+
template_file = "sorting_tabs.html"
83+
84+
class Kwargs(BaseModel):
85+
object_list: ObjectList
86+
model_config = {"arbitrary_types_allowed": True}
87+
88+
def create_tab(self, object_list, tab):
89+
verbose_text = tab.replace("_", " ").capitalize()
90+
is_current = tab == object_list.current_tab
91+
link = querystring(None, {**object_list.params, TAB_VAR: tab})
92+
attrs = {"href": link}
93+
if is_current:
94+
attrs["aria-selected"] = "true"
95+
return TabItem(text=verbose_text, is_current=is_current, attrs=attrs)
96+
97+
def get_template_data(self, args, kwargs, slots, context):
98+
object_list = kwargs.object_list
99+
tabs = [self.create_tab(object_list, tab) for tab in object_list.sorting_tabs]
100+
return {
101+
"tabs": tabs,
102+
"object_list": object_list,
103+
}

base/components/sorting_tabs.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<nav aria-labelledby="sorting-tabs">
2+
<h2 id="sorting-tabs" class="sr-only">Sorting Tabs</h2>
3+
<ul class="m-0 inline-flex gap-2 p-2 border-2 border-base-green-400 rounded-lg font-common">
4+
{% for tab in tabs %}
5+
<li><a {% html_attrs tab.attrs %} class="inline-block px-4 py-2 rounded-md {% if tab.is_current %}bg-base-green-400 text-base-white-400 no-underline{% else %}underline duration-300 transition-colors hover:bg-base-green-400/30 hover:text-base-green-800{% endif %}">{{ tab.text }}</a></li>
6+
{% endfor %}
7+
</ul>
8+
</nav>

base/main.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,42 @@
11
from .pagination import PAGE_VAR, Pagination
22

3+
TAB_VAR = "tab"
4+
35

46
class ObjectList:
57
pagination_class = Pagination
8+
base_ordering = ()
9+
sorting_tabs = {}
610

711
def __init__(self, request, model, queryset, list_per_page):
812
self.model = model
13+
self.opts = model._meta
914
self.queryset = queryset
1015
self.list_per_page = list_per_page
11-
self.params = dict(request.GET.lists())
16+
self.params = dict(request.GET.dict())
17+
self.current_tab = self.params.get(TAB_VAR, None)
18+
if self.opts.ordering:
19+
self.base_ordering = self.opts.ordering
1220
if PAGE_VAR in self.params:
1321
del self.params[PAGE_VAR]
14-
self.result_objects = self.get_objects(request)
22+
self.result_objects = self.get_objects(request, queryset)
1523

1624
def __iter__(self):
1725
return iter(self.result_objects)
1826

27+
def tab_sort(self, queryset):
28+
result_queryset = queryset
29+
if self.current_tab:
30+
sort_value = self.sorting_tabs[self.current_tab]
31+
result_queryset = result_queryset.order_by(*sort_value, *self.base_ordering)
32+
else:
33+
for tab_name, tab_order in self.sorting_tabs.items():
34+
if tab_order == self.base_ordering:
35+
self.current_tab = tab_name
36+
break
37+
38+
return result_queryset
39+
1940
def paginate(self, request, queryset):
2041
pagination = self.pagination_class(
2142
request,
@@ -26,6 +47,7 @@ def paginate(self, request, queryset):
2647
self.pagination = pagination
2748
return pagination.get_objects()
2849

29-
def get_objects(self, request):
30-
paginate_result = self.paginate(request, self.queryset)
50+
def get_objects(self, request, queryset):
51+
tab_result = self.tab_sort(queryset)
52+
paginate_result = self.paginate(request, tab_result)
3153
return paginate_result

cab/main.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from base.main import ObjectList
2+
3+
4+
class SnippetList(ObjectList):
5+
sorting_tabs = {
6+
"newest": ("-pub_date",),
7+
"latest_updated": ("-updated_date",),
8+
"highest_rated": ("-rating_score",),
9+
"most_bookmarked": ("-bookmark_count",),
10+
}

cab/utils.py

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

10-
from base.main import ObjectList
1110
from base.pagination import Pagination
1211

12+
from .main import SnippetList
13+
1314

1415
def object_list(
1516
request,
@@ -45,7 +46,7 @@ def object_list(
4546
opts = model._meta
4647
if paginate_by:
4748
if queryset.model == Snippet:
48-
object_list = ObjectList(request, queryset.model, queryset, 15)
49+
object_list = SnippetList(request, queryset.model, queryset, 15)
4950
pagination = object_list.pagination
5051
else:
5152
pagination = Pagination(request, model, queryset, paginate_by)

djangosnippets/templates/base.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/themes/smoothness/jquery-ui.css" />
99
<link rel="preconnect" href="https://fonts.googleapis.com">
1010
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11-
<link href="https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Raleway:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
11+
<link href="https://fonts.googleapis.com/css2?family=Libertinus+Sans:ital,wght@0,400;0,700;1,400&family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Raleway:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
1212
<link rel="alternate" href="{% url 'cab_feed_latest' %}" type="application/atom+xml" title="Feed of latest snippets" />
1313
<link rel="stylesheet" href="{% static "css/main.css" %}" type="text/css" />
1414
{% block feeds %}{% endblock %}
@@ -62,6 +62,7 @@
6262

6363
<div id="base-container">
6464
<h1>{% block content_header %}{% endblock %}</h1>
65+
{% block new_content_header %}{% endblock %}
6566
{% with current_url_name=request.resolver_match.url_name %}
6667
<div id="content" class="{% if current_url_name == 'home' %}w-1/2{% else %}w-full{% endif %}">
6768
{% block content %}

djangosnippets/templates/cab/snippet_list.html

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@
22
{% load core_tags %}
33
{% load static %}
44
{% block bodyclass %}snippet-list{% endblock %}
5-
{% block head_title %}All snippets{% if months %} last {{ months }} months{% endif %}{% endblock %}
5+
{% block head_title %}Snippet list{% endblock %}
66

7-
{% block content_header %}All snippets{% if months %} last {{ months }} months{% endif %}{% endblock %}
7+
{% block new_content_header %}
8+
<header class="bg-transparent">
9+
<h1 class="my-20 text-center float-none font-header text-8xl md:text-left">{{ hits }} snippet{{ hits|pluralize }}</h1>
10+
<div class="my-4 flex justify-between px-4">
11+
<div></div>
12+
{% component 'sorting_tabs' object_list=object_list / %}
13+
</div>
14+
</header>
15+
{% endblock %}
816

917
{% block content %}
1018
{% if object_list %}
1119
{% component 'snippet_list' snippet_list=object_list / %}
1220
{% component 'pagination' pagination_obj=pagination / %}
13-
<p class="count">{{ hits }} snippet{{ hits|pluralize }} posted so far.</p>
14-
{% else %}
15-
<p class="empty">No snippets posted yet.</p>
1621
{% endif %}
1722
{% endblock %}
1823

djangosnippets/templates/cab/user_detail.html

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@
77

88
{% block head_title %}Snippets by {{ author.username }}{% if months %}, last {{ months }} months{% endif %}{% endblock %}
99

10-
{% block content_header %}Snippets by {{ author.username }}{% if months %}, last {{ months }} months{% endif %}{% endblock %}
10+
{% block new_content_header %}
11+
<header class="bg-transparent">
12+
<h1 class="my-20 text-center float-none font-header text-8xl md:text-left">Snippet{{ hits|pluralize }} by {{ author.username }}</h1>
13+
<div class="my-4 flex justify-between px-4">
14+
<div></div>
15+
{% component 'sorting_tabs' object_list=object_list / %}
16+
</div>
17+
</header>
18+
{% endblock %}
1119

1220

1321
{% block content %}
1422
{% if object_list %}
1523
{% component 'snippet_list' snippet_list=object_list / %}
1624
{% cache 600 author_detail_sidebar author.username %}
17-
<p class="count">{% if request.user.username == author.username %}You've{% else %}{{ author.username }} has{% endif %} posted {{ author.snippet_set.count }} snippet{{ author.snippet_set.count|pluralize }}.</p>
1825
{% endcache %}
1926
{% component "pagination" pagination_obj=pagination / %}
2027
{% else %}

theme/static_src/src/styles.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
--color-base-gray-400: #7a7a7a;
88
--color-base-green-400: #256918;
99
--color-base-green-800: #12330c;
10+
--font-header: "Libertinus Sans", sans-serif;
1011
--font-title: "Playfair Display", sans-serif;
1112
--font-text: "Nunito", sans-serif;
1213
--font-common: "Raleway", sans-serif;

0 commit comments

Comments
 (0)