From 185fb70dda9fa2ec7262d7f9bdaa9b962d533bc6 Mon Sep 17 00:00:00 2001 From: imperosol Date: Mon, 20 Jan 2025 17:27:00 +0100 Subject: [PATCH] Improve news list display --- com/models.py | 18 +++++ com/static/com/css/news-list.scss | 118 +++--------------------------- com/templates/com/news_list.jinja | 111 ++++++++++++++++------------ com/views.py | 37 ++++++---- core/templates/core/macros.jinja | 8 -- 5 files changed, 116 insertions(+), 176 deletions(-) diff --git a/com/models.py b/com/models.py index 1219410a..229d83c8 100644 --- a/com/models.py +++ b/com/models.py @@ -172,6 +172,22 @@ def news_notification_callback(notif): notif.viewed = True +class NewsDateQuerySet(models.QuerySet): + def viewable_by(self, user: User) -> Self: + """Filter the event dates that the given user can view. + + - If the can view non moderated news, he can view all news dates + - else, he can view the dates of news that are either + authored by him or moderated. + """ + if user.has_perm("com.view_unmoderated_news"): + return self + q_filter = Q(news__is_moderated=True) + if user.is_authenticated: + q_filter |= Q(news__author_id=user.id) + return self.filter(q_filter) + + class NewsDate(models.Model): """A date associated with news. @@ -187,6 +203,8 @@ class NewsDate(models.Model): start_date = models.DateTimeField(_("start_date")) end_date = models.DateTimeField(_("end_date")) + objects = NewsDateQuerySet.as_manager() + class Meta: verbose_name = _("news date") verbose_name_plural = _("news dates") diff --git a/com/static/com/css/news-list.scss b/com/static/com/css/news-list.scss index d073c4ac..b068fb45 100644 --- a/com/static/com/css/news-list.scss +++ b/com/static/com/css/news-list.scss @@ -172,53 +172,21 @@ .news_event { display: block; - padding: 0.4em; - - &:not(:last-child) { - border-bottom: 1px solid grey; - } - - div { - margin: 0.2em; - } - - h4 { - margin-top: 1em; - text-transform: uppercase; - } - - .club_logo { - float: left; - min-width: 7em; - max-width: 9em; - margin: 0; - margin-right: 1em; - margin-top: 0.8em; + padding: 1em; + header { img { - max-height: 6em; - max-width: 8em; - display: block; - margin: 0 auto; + height: 75px; } - } + .header_content { + display: flex; + flex-direction: column; + justify-content: center; + gap: .2rem; - .news_date { - font-size: 100%; - } - - .news_content { - clear: left; - - .button_bar { - text-align: right; - - .fb { - color: $faceblue; - } - - .twitter { - color: $twitblue; + h4 { + margin-top: 0; + text-transform: uppercase; } } } @@ -228,70 +196,6 @@ /* END EVENTS TODAY AND NEXT FEW DAYS */ - /* COMING SOON */ - .news_coming_soon { - display: list-item; - list-style-type: square; - list-style-position: inside; - margin-left: 1em; - padding-left: 0; - - a { - font-weight: bold; - text-transform: uppercase; - } - - .news_date { - font-size: 0.9em; - } - } - - /* END COMING SOON */ - - /* NOTICES */ - .news_notice { - margin: 0 0 1em 1em; - padding: 0.4em; - padding-left: 1em; - background: $secondary-neutral-light-color; - box-shadow: $shadow-color 0 0 2px; - border-radius: 18px 5px 18px 5px; - - h4 { - margin: 0; - } - - .news_content { - margin-left: 1em; - } - } - - /* END NOTICES */ - - /* CALLS */ - .news_call { - margin: 0 0 1em 1em; - padding: 0.4em; - padding-left: 1em; - background: $secondary-neutral-light-color; - border: 1px solid grey; - box-shadow: $shadow-color 1px 1px 1px; - - h4 { - margin: 0; - } - - .news_date { - font-size: 0.9em; - } - - .news_content { - margin-left: 1em; - } - } - - /* END CALLS */ - .news_empty { margin-left: 1em; } diff --git a/com/templates/com/news_list.jinja b/com/templates/com/news_list.jinja index 0f1f4301..560eb569 100644 --- a/com/templates/com/news_list.jinja +++ b/com/templates/com/news_list.jinja @@ -1,5 +1,4 @@ {% extends "core/base.jinja" %} -{% from 'core/macros.jinja' import tweet_quick, fb_quick %} {% block title %} {% trans %}News{% endtrans %} @@ -18,10 +17,8 @@ {% endblock %} {% block content %} -
- {% set events_dates = NewsDate.objects.filter(end_date__gte=timezone.now(), start_date__lte=timezone.now()+timedelta(days=5), news__is_moderated=True).datetimes('start_date', 'day') %}

{% trans %}Events today and the next few days{% endtrans %} @@ -33,51 +30,58 @@ {% endif %} {% if user.is_com_admin %} - {% trans %}Administrate news{% endtrans %} + + {% trans %}Administrate news{% endtrans %} +
- {% endif %} - {% if events_dates %} - {% for d in events_dates %} -
-
-
-
{{ d|localtime|date('D') }}
-
{{ d|localtime|date('d') }}
-
{{ d|localtime|date('b') }}
-
-
-
- {% for news in object_list.filter(dates__start_date__gte=d,dates__start_date__lte=d+timedelta(days=1)).exclude(dates__end_date__lt=timezone.now()).order_by('dates__start_date') %} -
- -

{{ news.title }}

- -
- {{ news.dates.first().start_date|localtime|time(DATETIME_FORMAT) }} - - {{ news.dates.first().end_date|localtime|time(DATETIME_FORMAT) }} -
-
{{ news.summary|markdown }} -
- {{ fb_quick(news) }} - {{ tweet_quick(news) }} -
-
-
- {% endfor %} + {% endif %} + {% for day, dates_group in news_dates %} +
+
+
+
{{ day|date('D') }}
+
{{ day|date('d') }}
+
{{ day|date('b') }}
- {% endfor %} +
+ {% for date in dates_group %} +
+
+ {% if date.news.club.logo %} + {{ date.news.club }} + {% else %} + {{ date.news.club }} + {% endif %} +
+

+ + {{ date.news.title }} + +

+ {{ date.news.club }} +
+ - + +
+
+
+
+ {{ date.news.summary|markdown }} +
+
+ {% endfor %} +
+
{% else %}
{% trans %}Nothing to come...{% endtrans %}
- {% endif %} + {% endfor %}

{% trans %}All coming events{% endtrans %} @@ -110,18 +114,26 @@

@@ -130,7 +142,7 @@

{% trans %}Birthdays{% endtrans %}

- {%- if user.was_subscribed -%} + {%- if user.has_perm("core.view_user") -%}
    {%- for year, users in birthdays -%}
  • @@ -143,8 +155,13 @@
  • {%- endfor -%}
- {%- else -%} + {%- elif not user.was_subscribed -%} + {# The user cannot view birthdays, because he never subscribed #}

{% trans %}You need to subscribe to access this content{% endtrans %}

+ {%- else -%} + {# There is another reason why user cannot view birthdays (maybe he is banned) + but we cannot know exactly what is this reason #} +

{% trans %}You cannot access this content{% endtrans %}

{%- endif -%}
diff --git a/com/views.py b/com/views.py index 0ab8fc1c..3990fe9b 100644 --- a/com/views.py +++ b/com/views.py @@ -37,9 +37,9 @@ from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, redirect from django.urls import reverse, reverse_lazy from django.utils import timezone -from django.utils.timezone import localdate +from django.utils.timezone import localdate, now from django.utils.translation import gettext_lazy as _ -from django.views.generic import DetailView, ListView, View +from django.views.generic import DetailView, ListView, TemplateView, View from django.views.generic.edit import CreateView, DeleteView, UpdateView from club.models import Club, Mailing @@ -236,28 +236,37 @@ class NewsAdminListView(PermissionRequiredMixin, ListView): permission_required = ["com.moderate_news", "com.delete_news"] -class NewsListView(ListView): - model = News +class NewsListView(TemplateView): template_name = "com/news_list.jinja" - queryset = News.objects.filter(is_moderated=True) - def get_queryset(self): - return super().get_queryset().viewable_by(self.request.user) - - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - kwargs["NewsDate"] = NewsDate - kwargs["timedelta"] = timedelta - kwargs["birthdays"] = itertools.groupby( + def get_birthdays(self): + if not self.request.user.has_perm("core.view_user"): + return [] + return itertools.groupby( User.objects.filter( date_of_birth__month=localdate().month, date_of_birth__day=localdate().day, + is_subscriber_viewable=True, ) .filter(role__in=["STUDENT", "FORMER STUDENT"]) .order_by("-date_of_birth"), key=lambda u: u.date_of_birth.year, ) - return kwargs + + def get_news_dates(self): + return itertools.groupby( + NewsDate.objects.viewable_by(self.request.user) + .filter(end_date__gt=now(), start_date__lt=now() + timedelta(days=6)) + .order_by("start_date") + .select_related("news", "news__club"), + key=lambda d: d.start_date.date(), + ) + + def get_context_data(self, **kwargs): + return super().get_context_data(**kwargs) | { + "news_dates": self.get_news_dates(), + "birthdays": self.get_birthdays(), + } class NewsDetailView(CanViewMixin, DetailView): diff --git a/core/templates/core/macros.jinja b/core/templates/core/macros.jinja index 84c5b05a..b43ba844 100644 --- a/core/templates/core/macros.jinja +++ b/core/templates/core/macros.jinja @@ -39,14 +39,6 @@ {%- endmacro %} -{% macro fb_quick(news) -%} - -{%- endmacro %} - -{% macro tweet_quick(news) -%} - -{%- endmacro %} - {% macro user_mini_profile(user) %}