Skip to content
Snippets Groups Projects
Commit fbada802 authored by Tomáš Valenta's avatar Tomáš Valenta Committed by josef.bouse
Browse files

tag filtering

parent 3adcf582
Branches
No related tags found
2 merge requests!861Release: New homepage design,!841Feat/new homepage
Showing
with 135 additions and 207 deletions
# Generated by Django 4.1.10 on 2023-12-19 20:40
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('main', '0088_alter_mainhomepage_europarl_section_tag'),
]
operations = [
migrations.RemoveField(
model_name='mainarticlepage',
name='section_tags',
),
migrations.RemoveField(
model_name='mainhomepage',
name='europarl_section_tag',
),
migrations.RemoveField(
model_name='mainhomepage',
name='main_section_tag',
),
migrations.DeleteModel(
name='MainArticleSectionTagged',
),
migrations.DeleteModel(
name='SectionTag',
),
]
......@@ -10,7 +10,7 @@ from django.shortcuts import render
from django.utils import timezone
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
from taggit.models import TagBase, TaggedItemBase
from taggit.models import Tag, TaggedItemBase
from wagtail.admin.panels import (
FieldPanel,
HelpPanel,
......@@ -124,24 +124,6 @@ class MainHomePage(
null=True,
)
main_section_tag = models.ForeignKey(
"main.SectionTag",
verbose_name="Tag pro rozdělení - Hlavní stránka",
on_delete=models.PROTECT,
related_name="+",
blank=True,
null=True,
)
europarl_section_tag = models.ForeignKey(
"main.SectionTag",
verbose_name="Tag pro rozdělení - Eurovolby",
on_delete=models.PROTECT,
related_name="+",
blank=True,
null=True,
)
matomo_id = models.IntegerField(
"Matomo ID pro sledování návštěvnosti", blank=True, null=True
)
......@@ -171,13 +153,6 @@ class MainHomePage(
FieldPanel("donation_page_text"),
FieldPanel("social_links"),
FieldPanel("matomo_id"),
MultiFieldPanel(
[
FieldPanel("europarl_section_tag"),
FieldPanel("main_section_tag"),
],
heading="Tagy",
),
]
### EDIT HANDLERS
......@@ -223,10 +198,7 @@ class MainHomePage(
context = super().get_context(request, args, kwargs)
context["article_data_list"] = (
MainArticlePage.objects.filter(
models.Q(section_tags__isnull=True)
| models.Q(section_tags=self.main_section_tag)
)
MainArticlePage.objects
.live()
.order_by("-date")[:3]
)
......@@ -404,9 +376,18 @@ class MainArticlesPage(
class Meta:
verbose_name = "Rozcestník článků"
def get_article_data_list(self, months_back: int = 1):
def get_article_data_list(
self,
months_back: int = 1,
filtered_tag: Tag|None = None,
):
tag_filter = models.Q()
if filtered_tag is not None:
tag_filter = tag_filter & models.Q(tags=filtered_tag)
target_date_list = (
MainArticlePage.objects.order_by("-date")
MainArticlePage.objects.filter(tag_filter).order_by("-date")
.live()
.values_list("date", flat=True)
)
......@@ -417,10 +398,10 @@ class MainArticlesPage(
target_date = target_date_list[0] - relativedelta(months=months_back)
first_day_of_target_month = target_date.replace(day=1)
filter = models.Q(date__gt=first_day_of_target_month) & tag_filter
sorted_article_qs = (
MainArticlePage.objects.filter(
date__gt=first_day_of_target_month,
)
MainArticlePage.objects.filter(filter)
.live()
.order_by("-date")
)
......@@ -440,11 +421,29 @@ class MainArticlesPage(
return article_data_list
def get_filtered_tag(self, request):
if "tag_id" in request.GET:
try:
tag = Tag.objects.filter(id=int(request.GET["tag_id"])).first()
except Exception:
tag = None
if tag is not None:
return tag
return None
def get_context(self, request, get_articles: bool = True, *args, **kwargs):
ctx = super().get_context(request, args, kwargs)
if get_articles:
article_timeline_list = self.get_article_data_list(1)
filtered_tag = self.get_filtered_tag(request)
if filtered_tag is not None:
ctx["filtered_tag"] = filtered_tag
article_timeline_list = self.get_article_data_list(1, filtered_tag)
ctx["article_timeline_list"] = article_timeline_list
ctx[
"show_next_timeline_articles"
......@@ -463,7 +462,7 @@ class MainArticlesPage(
tags = []
for article in MainArticlePage.objects.all()[:50]:
for tag in article.tags.names():
for tag in article.tags.all():
if tag in tags:
continue
......@@ -471,6 +470,8 @@ class MainArticlesPage(
ctx["tags"] = tags
# meow
return ctx
def get_timeline_articles_response(self, request):
......@@ -479,7 +480,9 @@ class MainArticlesPage(
except ValueError:
months = 1
article_list = self.get_article_data_list(months)
filtered_tag = self.get_filtered_tag(request)
article_list = self.get_article_data_list(months, filtered_tag)
context = {"article_timeline_list": article_list}
data = {
"html": render(
......@@ -570,26 +573,6 @@ class MainArticleTag(TaggedItemBase):
)
class SectionTag(TagBase):
class Meta:
verbose_name = "Tag pro rozdělení do sekcí"
verbose_name_plural = "Tagy pro rozdělení do sekcí"
class MainArticleSectionTagged(TaggedItemBase):
tag = models.ForeignKey(
SectionTag,
on_delete=models.CASCADE,
related_name="%(app_label)s_%(class)s_items",
)
content_object = ParentalKey(
"main.MainArticlePage",
on_delete=models.CASCADE,
related_name="section_tagged_items",
)
class MainArticlePage(
ArticleMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
):
......@@ -624,14 +607,6 @@ class MainArticlePage(
blank=True,
)
section_tags = ClusterTaggableManager(
through=MainArticleSectionTagged,
verbose_name="Tagy pro rozdělení do sekcí",
help_text="Používá se například pro oddělení článků do sekce pro eurovolby. Pokud chceš, aby se články zobrazovaly pouze na hlavní stránce, nepřidávej žádné tagy.",
related_name="sectioned_articles",
blank=True,
)
search_fields = ArticleMixin.search_fields + [
index.SearchField("author_page"),
index.FilterField("slug"),
......@@ -642,7 +617,6 @@ class MainArticlePage(
content_panels = ArticleMixin.content_panels + [
FieldPanel("author_page"),
FieldPanel("tags"),
FieldPanel("section_tags"),
FieldPanel("shared_tags"),
]
......
This diff is collapsed.
This diff is collapsed.
<a href="#" class="text px-4 py-2 text-black bg-yellow-500 duration-200 hover:bg-yellow-600 hover:no-underline">
<a
href="{% if tags_are_selectable %}?tag_id={{ id }}{% endif %}"
class="text px-4 py-2 text-black bg-yellow-500 duration-200 hover:bg-yellow-600 hover:no-underline"
style="
{% if filtered_tag.id == id %}
background:white!important;
text-color:black
{% endif %}
"
>
{{ text }}
</a>
<div class="flex grow flex-col gap-0 md:flex-row md:gap-8">
<div class="md:shrink-0">
<a href="#">
<a href="{{ url }}">
<img
class="h-full w-36 object-cover rounded-full"
src="../../../../static/images/person-table.png"
class="h-36 w-36 object-cover rounded-full"
src="{{ image.url }}"
alt="{{ name }}"
>
</a>
......@@ -17,24 +17,30 @@
md:text-2xl
xl:text-3xl
"
href="#"
href="{{ url }}"
><h4>{{ name }}</h4></a>
{% if function %}
<span class="leading-6 mb-4 md:mb-6 w-10/12 text-grey-200">
{{ function }}
</span>
{% endif %}
</div>
<div class="flex flex-col items-start">
{% if telephone %}
<a
class="mb-2"
href="tel:{{ telephone }}"
>{{ telephone }}</a>
{% endif %}
{% if mail %}
<a
class="text-pirati-yellow"
href="mailto:{{ mail }}"
>{{ mail }}</a>
{% endif %}
</div>
</div>
</div>
......
......@@ -4,6 +4,7 @@
<div class="header-carousel">
<div class="h-[700px] xl:h-screen relative">
<img
class="header-carousel--image"
src="{% static 'main/images/background-images/bg-flag.webp' %}"
draggable="false"
>
......
<div class="flex gap-4 flex-wrap max-w-[550px] {{ classes }}">
{% for tag in tags %}
{% include 'main/includes/atoms/tags/tag.html' with text=tag %}
{% include 'main/includes/atoms/tags/tag.html' with text=tag id=tag.id %}
{% endfor %}
</div>
{% if filtered_tag %}
<a href="?tag_id=" class="text-white pb-6 underline">
Resetovat tagy
</a>
{% endif %}
{% extends 'main/includes/organisms/header/simple_header_with_tags.html' %}
{% block after_heading %}
{% include 'main/includes/molecules/tags/tags.html' with classes='mb-4' %}
{% include 'main/includes/molecules/tags/tags.html' with classes='mb-4' tags_are_selectable=True %}
<div class="flex justify-start">
<input
......
......@@ -3,7 +3,7 @@
{% block after_description %}
<div
class="
container--medium flex justify-start pl-[unset] pr-[unset] ml-[unset] mr-[unset]
container--medium flex justify-start !pl-[unset] !pr-[unset] !ml-[unset] !mr-[unset]
xl:mb-12 mb-4
"
>
......
{% load wagtailimages_tags %}
<footer class="bg-black text-white __js-root py-4 xl:py-24 pb-8 xl:pb-24">
<ui-app inline-template>
<div
......@@ -30,8 +32,15 @@
<section class="flex flex-col xl:items-end">
<div class="flex flex-col gap-12">
{% include 'main/includes/molecules/contact/contact_footer_box.html' %}
{% include 'main/includes/molecules/contact/contact_footer_box.html' %}
{% if page.root_page.footer_person_list %}
{% for person in page.root_page.footer_person_list %}
{% image person.value.person.profile_image fill-256x256 as person_profile_image %}
{% firstof person.value.position person.value.person.position as position %}
{% include 'main/includes/molecules/contact/contact_footer_box.html' with image=person_profile_image url=person.value.person.url name=person.value.person.title function=position telephone=person.value.person.phone mail=person.value.person.email %}
{% endfor %}
{% endif %}
</div>
</section>
</div>
......
......@@ -130,7 +130,7 @@
<div class="grid-left-side">
<img
class="w-[150px] mt-3"
src="../../../../static/images/logo-full-black.svg"
src="{% static 'main/images/logo-full-black.svg' %}"
alt=""
>
</div>
......@@ -166,7 +166,7 @@
href="{{ target }}"
class="
decoration-1 underline-offset-4
{% if item == selected_item %}navbar__menu-item--selected{% endif %}
{% if menu_item.value.title == selected_item %}navbar__menu-item--selected{% endif %}
"
>{{ menu_item.value.title }}</a>
{% endfor %}
......
{% extends "main/base.html" %}
{% load wagtailcore_tags wagtailimages_tags shared_filters %}
{% block content %}
{% include 'main/includes/layout/simple_page_header.html' with sub_heading=sub_heading %}
<main role="main">
<div class="__js-root">
<div class="grid-container article-section mb-8">
<div class="grid-full">
<div class="flex justify-center">
<div class="flex flex-col items-end gap-3">
<form
class="flex flex-row"
method="get"
action="{{ page.search_url }}"
>
<input
class="bg-grey-150 w-56 h-10 px-4 text-lg xl:h-14 xl:px-5"
type="text"
id="q"
name="q"
value="{{ query }}"
placeholder="Hledat články..."
aria-label="Vyhledávací box"
>
<button
class="btn btn--yellow-500 btn--to-yellow-600 btn--hoveractive"
aria-label="Vyhledat"
type="submit"
>
<div class="btn__body-wrap h-10 w-12 min-h-0 min-w-0 xl:h-14 xl:w-14">
<div class="btn__body p-0">
<i class="ico--search"></i>
</div>
</div>
</button>
</form>
<a href="{{ page.url }}" class="btn btn--black btn--to-yellow-500 btn--hoveractive uppercase">
<span class="btn__body-wrap">
<span class="btn__body text-lg lg:text-base">
Zpět na seznam
</span>
</span>
</a>
</div>
</div>
</div>
</div>
<section class="mb-3 xl:mb-14">
{% if article_results %}
<div id="searchArticleResultWrapper">
{% include 'main/includes/person_article_preview.html' with article_data_list=article_results %}
</div>
{% if show_more_articles %}
<div class="grid-container">
<div class="grid-content-with-right-side">
<a
onclick="showMoreArticles(event, this)"
href="#"
data-url="{{ page_url }}"
data-page="2"
data-query="{{ query }}"
class="btn btn--black btn--to-yellow-500 btn--hoveractive uppercase"
>
<span class="btn__body-wrap">
<span class="btn__body text-lg lg:text-base">
Zobrazit další
</span>
</span>
</a>
</div>
</div>
{% endif %}
{% else %}
<div class="grid-container article-section mb-8">
<div class="grid-full">
<p class="text-grey-300 text-center">Žádné výsledky.</p>
</div>
</div>
{% endif %}
</section>
{% include "main/includes/newsletter_section.html" %}
</div>
</main>
<script type="text/javascript">
async function showMoreArticles(event, btn) {
event.preventDefault()
let searchArticleResultWrapper = document.getElementById('searchArticleResultWrapper')
let url = (
btn.getAttribute('data-url')
+ `?page=${btn.getAttribute('data-page')}`
+ `&q=${btn.getAttribute('data-query')}`
)
const response = await fetch(url, {
method: "GET",
headers: {"X-Requested-With": "XMLHttpRequest"},
})
const data = await response.json()
searchArticleResultWrapper.innerHTML += data.html;
if (!data.has_next) { btn.style.display = 'none'; }
btn.setAttribute('data-page', parseInt(btn.getAttribute('data-page')) + 1)
}
</script>
{% endblock content %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment