From bba02fb8dc7c1154c2ef5f8624dfcb191a084249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexa=20Valentov=C3=A1?= <git@imaniti.org> Date: Fri, 9 May 2025 16:55:09 +0200 Subject: [PATCH] Add "more articles" button --- .../commands/octopus_people_import.py | 5 +- .../migrations/0319_auto_20250508_1642.py | 14 ++- shared/models/main.py | 89 ++++++++++++++++++- .../templates/styleguide2/article_page.html | 41 ++++++++- .../articles/article_links_block.html | 11 +++ uniweb/migrations/0138_auto_20250508_1752.py | 14 ++- 6 files changed, 148 insertions(+), 26 deletions(-) diff --git a/district/management/commands/octopus_people_import.py b/district/management/commands/octopus_people_import.py index 48ee4ca9c..330a0613d 100644 --- a/district/management/commands/octopus_people_import.py +++ b/district/management/commands/octopus_people_import.py @@ -52,9 +52,10 @@ class Command(BaseCommand): for person_page in DistrictManualOctopusPersonPage.objects.all(): import_manual_person.delay( - person_page.id, ( + person_page.id, + ( person_page.root_page.image_collection_id if hasattr(person_page.root_page, "image_collection_id") else 0 - ) + ), ) diff --git a/district/migrations/0319_auto_20250508_1642.py b/district/migrations/0319_auto_20250508_1642.py index 3a9cbf538..2d5382061 100644 --- a/district/migrations/0319_auto_20250508_1642.py +++ b/district/migrations/0319_auto_20250508_1642.py @@ -4,13 +4,12 @@ from django.db import migrations def add_district_search_pages(apps, schema_editor): - from district.models import DistrictHomePage - from district.models import DistrictSearchPage + from district.models import DistrictHomePage, DistrictSearchPage for home_page in DistrictHomePage.objects.all(): if DistrictSearchPage.objects.descendant_of(home_page).exists(): unlive_page = DistrictSearchPage.objects.descendant_of(home_page).first() - + if unlive_page is None: continue @@ -18,7 +17,7 @@ def add_district_search_pages(apps, schema_editor): unlive_page.save_revision().publish() continue - + search_page = DistrictSearchPage( title="Vyhledávací stránka", slug="search", @@ -31,11 +30,8 @@ def add_district_search_pages(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ - ('district', '0318_districthomepage_ecomail_newsletter_list_source'), + ("district", "0318_districthomepage_ecomail_newsletter_list_source"), ] - operations = [ - migrations.RunPython(add_district_search_pages) - ] + operations = [migrations.RunPython(add_district_search_pages)] diff --git a/shared/models/main.py b/shared/models/main.py index 817293eff..a9e5279d3 100644 --- a/shared/models/main.py +++ b/shared/models/main.py @@ -1,5 +1,6 @@ import datetime import logging +import random from collections import namedtuple from enum import Enum from functools import cached_property, reduce @@ -321,10 +322,9 @@ class PageInMenuMixin(Page): def get_menu_title(self, parent_instance=None) -> str: instance = self if parent_instance is None else parent_instance - menu_iterator = ( - getattr(getattr(instance, "root_page", None), "menu", None) - or getattr(instance, "menu", []) - ) + menu_iterator = getattr( + getattr(instance, "root_page", None), "menu", None + ) or getattr(instance, "menu", []) for menu in menu_iterator: if menu.block_type == "menu_item": @@ -1723,6 +1723,87 @@ class MainArticlePageMixin( ### END Relations + ### BEGIN Custom serving + + def serve(self, request, *args, **kwargs): + NUM_ARTICLES = 4 + + get_related_articles = request.GET.get("get_related_articles") + + all_articles_in_same_web = ( + type(self.specific) + .objects.filter(~Q(id=self.specific.id)) + .live() + .descendant_of(self.root_page.articles_page) + ) + + if get_related_articles: + # Make a while True loop here so we can break whenever + # instead of making nested if-else statements. + + while True: + ### Enough with same tag in this web + articles_with_same_tags = list( + all_articles_in_same_web.filter( + tags__in=self.get_tags, + ).all() + ) + + picked_articles = [] + + if len(articles_with_same_tags) == NUM_ARTICLES: + picked_articles = random.sample( + articles_with_same_tags, + min(NUM_ARTICLES, len(articles_with_same_tags)), + ) + break + + ### Enough in this web, just without same tags + needed_extra_articles_num = NUM_ARTICLES - len(articles_with_same_tags) + + articles_without_same_tags = list(all_articles_in_same_web.all()) + picked_articles_without_same_tags = random.sample( + articles_without_same_tags, + min(needed_extra_articles_num, len(articles_without_same_tags)), + ) + + picked_articles = ( + articles_with_same_tags + picked_articles_without_same_tags + ) + + if len(picked_articles) == NUM_ARTICLES: + break + else: + ### Use MainArticlePages to supplement if there aren't even enough articles + ### in this web. If there are no MainArticlePages, we're in a testing env + ### where it doesn't matter much. + from main.models import MainArticlePage + + needed_supplementary_articles_num = NUM_ARTICLES - len( + picked_articles + ) + main_web_articles = list( + MainArticlePage.objects.all()[ + : needed_supplementary_articles_num - 1 + ] + ) + + picked_articles += main_web_articles + + # Always break here so this only loops once no matter what, + # even if for some reason conditions aren't met. + break + + return render( + request, + "styleguide2/includes/organisms/articles/article_links_block.html", + {"articles": picked_articles}, + ) + + return super().serve(request, *args, **kwargs) + + ### END Custom serving + ### BEGIN Pages @property diff --git a/shared/templates/styleguide2/article_page.html b/shared/templates/styleguide2/article_page.html index b69c07599..5608a4fbd 100644 --- a/shared/templates/styleguide2/article_page.html +++ b/shared/templates/styleguide2/article_page.html @@ -28,12 +28,49 @@ {% include_block block %} {% endfor %} - <div class="flex justify-start"> - {% include 'styleguide2/includes/atoms/buttons/round_button.html' with url=page.root_page.articles_page.url text='Zpět na aktuality' show_arrow_on_hover=True %} + <div class="flex justify-start gap-4"> + {% include 'styleguide2/includes/atoms/buttons/round_button.html' with classes="bg-pirati-yellow text-black" fill="black" id="similar-articles" text='Související články' show_arrow_on_hover=True %} + {% include 'styleguide2/includes/atoms/buttons/round_button.html' with url=page.root_page.articles_page.url text='Zpět na seznam aktualit' show_arrow_on_hover=True %} </div> + + <div id="similar-articles-container"></div> </div> </main> +<script> + let similarArticlesOpen = false; + + document.getElementById("similar-articles").addEventListener( + "click", + async function (event) { + const container = document.getElementById("similar-articles-container"); + + if (!similarArticlesOpen) { + this.disabled = true; + + const articlesResponse = await fetch("./?get_related_articles=1") + + if (!articlesResponse.ok) { + throw new Error(`Could not get articles: status ${articlesResponse.status}. Check network logs`); + similarArticlesOpen = !similarArticlesOpen; + } + + container.innerHTML = await articlesResponse.text(); + container.style.display = "block"; + + this.disabled = false; + document.getElementById(`${this.id}-inner-text`).innerHTML = "Zavřít související články"; + this.scrollIntoView(); + } else { + container.style.display = "none"; + document.getElementById(`${this.id}-inner-text`).innerHTML = "Související články"; + } + + similarArticlesOpen = !similarArticlesOpen; + } + ) +</script> + {% include 'styleguide2/includes/organisms/main_section/newsletter_section.html' %} {% endblock %} diff --git a/shared/templates/styleguide2/includes/organisms/articles/article_links_block.html b/shared/templates/styleguide2/includes/organisms/articles/article_links_block.html index aeb85444f..3627f97fa 100644 --- a/shared/templates/styleguide2/includes/organisms/articles/article_links_block.html +++ b/shared/templates/styleguide2/includes/organisms/articles/article_links_block.html @@ -1,3 +1,14 @@ +{# Allow either "articles" or "self.articles" to be used in the same way. #} +{# TODO Make this cleaner #} + +{% if articles|length != 0 %} + <div class="grid grid-cols-1 md:grid-cols-2 gap-12"> + {% for article in articles %} + {% include 'styleguide2/includes/molecules/articles/article_title_preview.html' %} + {% endfor %} + </div> +{% endif %} + {% if self.articles|length != 0 %} <div class="grid grid-cols-1 md:grid-cols-2 gap-12"> {% for article in self.articles %} diff --git a/uniweb/migrations/0138_auto_20250508_1752.py b/uniweb/migrations/0138_auto_20250508_1752.py index 2fefb91de..953f53caf 100644 --- a/uniweb/migrations/0138_auto_20250508_1752.py +++ b/uniweb/migrations/0138_auto_20250508_1752.py @@ -4,13 +4,12 @@ from django.db import migrations def add_uniweb_search_pages(apps, schema_editor): - from uniweb.models import UniwebHomePage - from uniweb.models import UniwebSearchPage + from uniweb.models import UniwebHomePage, UniwebSearchPage for home_page in UniwebHomePage.objects.all(): if UniwebSearchPage.objects.descendant_of(home_page).exists(): unlive_page = UniwebSearchPage.objects.descendant_of(home_page).first() - + if unlive_page is None: continue @@ -18,7 +17,7 @@ def add_uniweb_search_pages(apps, schema_editor): unlive_page.save_revision().publish() continue - + search_page = UniwebSearchPage( title="Vyhledávací stránka", slug="search", @@ -31,11 +30,8 @@ def add_uniweb_search_pages(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ - ('uniweb', '0137_uniwebformpage_submission_button_text'), + ("uniweb", "0137_uniwebformpage_submission_button_text"), ] - operations = [ - migrations.RunPython(add_uniweb_search_pages) - ] + operations = [migrations.RunPython(add_uniweb_search_pages)] -- GitLab