Implement category taxonomy and navigation (Issue #35) #36
@@ -79,7 +79,10 @@ class ArticleIndexPage(RoutablePageMixin, Page):
|
|||||||
available_categories = (
|
available_categories = (
|
||||||
Category.objects.filter(articles__in=all_articles).distinct().order_by("sort_order", "name")
|
Category.objects.filter(articles__in=all_articles).distinct().order_by("sort_order", "name")
|
||||||
)
|
)
|
||||||
category_links = [{"category": category, "url": self.get_category_url(category)} for category in available_categories]
|
category_links = [
|
||||||
|
{"category": category, "url": self.get_category_url(category)}
|
||||||
|
for category in available_categories
|
||||||
|
]
|
||||||
if active_category:
|
if active_category:
|
||||||
articles = articles.filter(category=active_category)
|
articles = articles.filter(category=active_category)
|
||||||
available_tags = (
|
available_tags = (
|
||||||
@@ -108,7 +111,8 @@ class ArticleIndexPage(RoutablePageMixin, Page):
|
|||||||
|
|
||||||
@route(r"^category/(?P<category_slug>[-\w]+)/$")
|
@route(r"^category/(?P<category_slug>[-\w]+)/$")
|
||||||
def category_listing(self, request, category_slug):
|
def category_listing(self, request, category_slug):
|
||||||
category = get_object_or_404(Category.objects.filter(articles__in=self.get_articles()).distinct(), slug=category_slug)
|
category_qs = Category.objects.filter(articles__in=self.get_articles()).distinct()
|
||||||
|
category = get_object_or_404(category_qs, slug=category_slug)
|
||||||
return self.render(request, context_overrides=self.get_listing_context(request, active_category=category))
|
return self.render(request, context_overrides=self.get_listing_context(request, active_category=category))
|
||||||
|
|
||||||
def get_context(self, request, *args, **kwargs):
|
def get_context(self, request, *args, **kwargs):
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ def get_categories_nav(context):
|
|||||||
index_page = index_qs.first()
|
index_page = index_qs.first()
|
||||||
if not index_page:
|
if not index_page:
|
||||||
return []
|
return []
|
||||||
categories = index_page.get_listing_context(request, active_category=None)["available_categories"].filter(show_in_nav=True)
|
categories = index_page.get_listing_context(
|
||||||
|
request, active_category=None
|
||||||
|
)["available_categories"].filter(show_in_nav=True)
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"name": category.name,
|
"name": category.name,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
<!-- Category Filters -->
|
<!-- Category Filters -->
|
||||||
<div class="flex flex-wrap gap-3 mb-4">
|
<div class="flex flex-wrap gap-3 mb-4">
|
||||||
<a href="/articles/{% if active_tag %}?tag={{ active_tag }}{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if not active_category %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if not active_category %}aria-current="page"{% endif %}>All Categories</a>
|
<a href="/articles/{% if active_tag %}?tag={{ active_tag }}{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if not active_category %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if not active_category %}aria-current="page"{% endif %}>Categories</a>
|
||||||
{% for category_link in category_links %}
|
{% for category_link in category_links %}
|
||||||
<a href="{{ category_link.url }}{% if active_tag %}?tag={{ active_tag }}{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if active_category and active_category.slug == category_link.category.slug %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if active_category and active_category.slug == category_link.category.slug %}aria-current="page"{% endif %}>{{ category_link.category.name }}</a>
|
<a href="{{ category_link.url }}{% if active_tag %}?tag={{ active_tag }}{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if active_category and active_category.slug == category_link.category.slug %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if active_category and active_category.slug == category_link.category.slug %}aria-current="page"{% endif %}>{{ category_link.category.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
<!-- Tag Filters -->
|
<!-- Tag Filters -->
|
||||||
<div class="flex flex-wrap gap-3">
|
<div class="flex flex-wrap gap-3">
|
||||||
<a href="{% if active_category %}{{ active_category_url }}{% else %}/articles/{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if not active_tag %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if not active_tag %}aria-current="page"{% endif %}>All Tags</a>
|
<a href="{% if active_category %}{{ active_category_url }}{% else %}/articles/{% endif %}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if not active_tag %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if not active_tag %}aria-current="page"{% endif %}>All</a>
|
||||||
{% for tag in available_tags %}
|
{% for tag in available_tags %}
|
||||||
<a href="{% if active_category %}{{ active_category_url }}{% else %}/articles/{% endif %}?tag={{ tag.slug }}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if active_tag == tag.slug %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if active_tag == tag.slug %}aria-current="page"{% endif %}>{{ tag.name }}</a>
|
<a href="{% if active_category %}{{ active_category_url }}{% else %}/articles/{% endif %}?tag={{ tag.slug }}" class="px-4 py-2 font-mono text-sm font-bold border transition-colors {% if active_tag == tag.slug %}bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark border-transparent{% else %}bg-transparent text-zinc-600 dark:text-zinc-400 border-zinc-300 dark:border-zinc-700 hover:text-brand-dark dark:hover:text-brand-light hover:border-brand-dark dark:hover:border-brand-light{% endif %}" {% if active_tag == tag.slug %}aria-current="page"{% endif %}>{{ tag.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
Reference in New Issue
Block a user