From f5529bc1a1a9044b7a8109ea0a9eabf09e6dcf50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <tomas@imaniti.org>
Date: Sun, 12 May 2024 12:15:17 +0200
Subject: [PATCH] update article timeline loading

---
 .../district/district_articles_page.html      |  16 +--
 shared/models/main.py                         | 115 ++++--------------
 .../articles/article_timeline_preview.html    |   3 +-
 .../articles/articles_timeline_list.html      |  19 +--
 .../articles/main_articles_timeline.html      |  12 +-
 5 files changed, 41 insertions(+), 124 deletions(-)

diff --git a/district/templates/district/district_articles_page.html b/district/templates/district/district_articles_page.html
index d67e17be..b3d0fdef 100644
--- a/district/templates/district/district_articles_page.html
+++ b/district/templates/district/district_articles_page.html
@@ -1,15 +1 @@
-{% extends "district/base.html" %}
-
-{% block content %}
-  <header>
-    <h1 itemprop="headline" class="head-alt-md md:head-alt-lg max-w-5xl mb-8">{{ page.title }}</h1>
-  </header>
-
-  <div class="article-card-list grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-8">
-    {% for a in articles %}
-      {% include "shared/article_preview.html" with article=a %}
-    {% endfor %}
-  </div>
-
-  {% include 'styleguide/2.3.x/pagination.html' with paginator=articles %}
-{% endblock %}
+{% extends "styleguide2/articles_page.html" %}
diff --git a/shared/models/main.py b/shared/models/main.py
index 5c209975..aee43fff 100644
--- a/shared/models/main.py
+++ b/shared/models/main.py
@@ -459,6 +459,8 @@ class MainArticlesPageMixin(
 
     ### OTHERS
 
+    ARTICLE_LIST_COUNT = 20
+
     class Meta:
         verbose_name = "Rozcestník článků"
         abstract = True
@@ -470,48 +472,6 @@ class MainArticlesPageMixin(
             ).order_by("-union_timestamp")
         )
 
-    def get_article_data_list(
-        self,
-        months_back: int = 1,
-        search_filter: models.Q | None = None,
-    ):
-        if search_filter is None:
-            search_filter = models.Q()
-
-        target_date_list = self.append_all_shared_articles_query(
-            self.root_page.article_page_model.objects.filter(search_filter).live()
-        ).order_by("-union_timestamp")
-
-        if not target_date_list:
-            return []
-
-        target_date = target_date_list[0]["union_timestamp"] - relativedelta(
-            months=months_back
-        )
-        first_day_of_target_month = target_date.replace(day=1)
-
-        filter = models.Q(timestamp__gte=first_day_of_target_month) & search_filter
-
-        sorted_article_qs = self.get_base_shared_articles_query(filter)
-
-        article_data_list = []
-
-        current_month_data = self.get_empty_month_data(timezone.now().date())
-
-        for article in sorted_article_qs:
-            if article.date.month != current_month_data["month_number"]:
-                if len(current_month_data["articles"]) != 0:
-                    # append completed month if it contains any articles
-                    article_data_list.append(current_month_data)
-
-                current_month_data = self.get_empty_month_data(article.date)
-
-            current_month_data["articles"].append(article)
-
-        article_data_list.append(current_month_data)  # last iteration
-
-        return article_data_list
-
     def get_search_filters(self, request):
         filter = models.Q()
 
@@ -555,23 +515,15 @@ class MainArticlesPageMixin(
 
             search_filter = self.get_search_filters(request)
 
-            article_timeline_list = self.get_article_data_list(1, search_filter)
+            articles = self.get_base_shared_articles_query(search_filter)[:self.ARTICLE_LIST_COUNT + 1]
 
-            ctx["article_timeline_list"] = article_timeline_list
-            ctx["show_next_timeline_articles"] = len(
-                self.get_base_shared_articles_query(search_filter)
-            ) != 0 and (
-                self.materialize_shared_articles_query(
-                    self.append_all_shared_articles_query(
-                        self.root_page.article_page_model.objects.filter(search_filter)
-                        .live()
-                        .all()
-                    ).order_by("union_timestamp")[
-                        :2
-                    ]  # LIMIT 2
-                )[0]
-                not in article_timeline_list[-1]["articles"]
-            )
+            more_articles_exist = len(articles) > self.ARTICLE_LIST_COUNT
+
+            articles = articles[:self.ARTICLE_LIST_COUNT]
+
+            ctx["articles"] = articles
+            ctx["show_next_timeline_articles"] = more_articles_exist
+            ctx["article_count"] = len(articles)
 
             tags = []
 
@@ -589,15 +541,22 @@ class MainArticlesPageMixin(
         return ctx
 
     def get_timeline_articles_response(self, request):
-        try:
-            months = int(request.GET.get("months", None))
-        except ValueError:
-            months = 1
+        article_count = request.GET.get("article_count", "")
 
         search_filter = self.get_search_filters(request)
-        article_timeline_list = self.get_article_data_list(months, search_filter)
 
-        context = {"article_timeline_list": article_timeline_list}
+        if article_count.isnumeric():
+            article_count = int(article_count)
+        else:
+            article_count = self.ARTICLE_LIST_COUNT
+
+        articles = self.get_base_shared_articles_query(search_filter)[:article_count + 1]
+
+        more_articles_exist = len(articles) > article_count
+
+        articles = articles[:article_count]
+
+        context = {"articles": articles}
 
         data = {
             "html": render(
@@ -605,23 +564,7 @@ class MainArticlesPageMixin(
                 "styleguide2/includes/organisms/articles/articles_timeline_list.html",
                 context,
             ).content.decode("utf-8"),
-            "has_next": (
-                len(self.get_base_shared_articles_query(search_filter)) != 0
-                and (
-                    self.materialize_shared_articles_query(
-                        self.append_all_shared_articles_query(
-                            self.root_page.article_page_model.objects.filter(
-                                search_filter
-                            )
-                            .live()
-                            .all()
-                        ).order_by("union_timestamp")[
-                            :2
-                        ]  # LIMIT 2
-                    )[0]
-                    not in article_timeline_list[-1]["articles"]
-                )
-            ),
+            "has_next": more_articles_exist,
         }
 
         return JsonResponse(data=data, safe=False)
@@ -632,19 +575,11 @@ class MainArticlesPageMixin(
 
     def serve(self, request, *args, **kwargs):
         if request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest":
-            if "months" in request.GET:
+            if "article_count" in request.GET:
                 return self.get_timeline_articles_response(request)
 
         return super().serve(request, *args, **kwargs)
 
-    @staticmethod
-    def get_empty_month_data(date_obj):
-        return {
-            "month_number": date_obj.month,
-            "month_text": MONTH_NAMES[date_obj.month - 1],
-            "articles": [],
-        }
-
 
 class MainArticlePageMixin(
     ArticleMixin,
diff --git a/shared/templates/styleguide2/includes/molecules/articles/article_timeline_preview.html b/shared/templates/styleguide2/includes/molecules/articles/article_timeline_preview.html
index dd1be472..8cc24ace 100644
--- a/shared/templates/styleguide2/includes/molecules/articles/article_timeline_preview.html
+++ b/shared/templates/styleguide2/includes/molecules/articles/article_timeline_preview.html
@@ -2,10 +2,11 @@
 
 <div
   class="
-    flex flex-col mb-8 bg-grey-180 drop-shadow
+    __article flex flex-col mb-8 bg-grey-180 drop-shadow
 
     {{ classes }}
   "
+  data-id="{{ article.id }}"
 >
   <a href="{{ article.url }}">
     {% image article.image width-1024 as image %}
diff --git a/shared/templates/styleguide2/includes/organisms/articles/articles_timeline_list.html b/shared/templates/styleguide2/includes/organisms/articles/articles_timeline_list.html
index 6de74450..1a57c08f 100644
--- a/shared/templates/styleguide2/includes/organisms/articles/articles_timeline_list.html
+++ b/shared/templates/styleguide2/includes/organisms/articles/articles_timeline_list.html
@@ -1,16 +1,9 @@
-{% if article_timeline_list|length != 0 %}
-  {% for timeline_item in article_timeline_list %}
-    <div class="text-center">
-      <h2 class="head-9xl">{{ timeline_item.month_text }}</h2>
-    </div>
-    <div
-      class="grid grid-cols-1 md:grid-cols-2 gap-12"
-    >
-      {% for article in timeline_item.articles %}
-        {% include 'styleguide2/includes/molecules/articles/article_timeline_preview.html' %}
-      {% endfor %}
-    </div>
-  {% endfor %}
+{% 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_timeline_preview.html' %}
+    {% endfor %}
+  </div>
 {% else %}
   <div class="mb-10">
     Žádné výsledky.
diff --git a/shared/templates/styleguide2/includes/organisms/articles/main_articles_timeline.html b/shared/templates/styleguide2/includes/organisms/articles/main_articles_timeline.html
index 42742c7c..5de4ddaf 100644
--- a/shared/templates/styleguide2/includes/organisms/articles/main_articles_timeline.html
+++ b/shared/templates/styleguide2/includes/organisms/articles/main_articles_timeline.html
@@ -11,8 +11,8 @@
       <div class="flex justify-center mb-16">
         <div
           onclick="showMoreTimelineArticles(event, this)"
-          data-url="{{ page_url }}{% if filtered_tag %}?tag_id={{ filtered_tag.id }}&amp;{% else %}?{% endif %}months="
-          data-months="2"
+          data-url="{{ page_url }}{% if filtered_tag %}?tag_id={{ filtered_tag.id }}&amp;{% else %}?{% endif %}article_count="
+          data-count="{{ article_count }}"
         >
           {% include 'styleguide2/includes/atoms/buttons/round_button.html' with button_text='Další články' %}
         </div>
@@ -25,8 +25,12 @@
   async function showMoreTimelineArticles(event, btn) {
     event.preventDefault()
 
+    let count = parseInt(btn.dataset.count)
+    count += 20
+    btn.setAttribute("data-count", count)
+
     const showMoreTimelineResultsWrapper = document.getElementById('showMoreTimelineResultsWrapper')
-    const url = btn.getAttribute('data-url') + btn.getAttribute('data-months')
+    const url = btn.dataset.url + btn.dataset.count
 
     const response = await fetch(url, {
       method: "GET",
@@ -36,8 +40,6 @@
 
     showMoreTimelineResultsWrapper.innerHTML = data.html
 
-    btn.setAttribute('data-months', parseInt(btn.getAttribute('data-months')) + 1)
-
     if (!data.has_next) {
       btn.style.display = 'none';
     }
-- 
GitLab