Improve news list display

This commit is contained in:
imperosol 2025-01-20 17:27:00 +01:00
parent 3a06cefea8
commit 185fb70dda
5 changed files with 116 additions and 176 deletions

View File

@ -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")

View File

@ -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;
}

View File

@ -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 %}
<div id="news">
<div id="left_column" class="news_column">
{% 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') %}
<h3>
{% trans %}Events today and the next few days{% endtrans %}
<a target="#" href="{{ url("com:news_feed") }}"><i class="fa fa-rss feed"></i></a>
@ -33,51 +30,58 @@
</a>
{% endif %}
{% if user.is_com_admin %}
<a class="btn btn-blue" href="{{ url('com:news_admin_list') }}">{% trans %}Administrate news{% endtrans %}</a>
<a class="btn btn-blue" href="{{ url('com:news_admin_list') }}">
{% trans %}Administrate news{% endtrans %}
</a>
<br>
{% endif %}
{% if events_dates %}
{% for d in events_dates %}
<div class="news_events_group">
<div class="news_events_group_date">
<div>
<div>{{ d|localtime|date('D') }}</div>
<div class="day">{{ d|localtime|date('d') }}</div>
<div>{{ d|localtime|date('b') }}</div>
</div>
</div>
<div class="news_events_group_items">
{% 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') %}
<section class="news_event">
<div class="club_logo">
{% if news.club.logo %}
<img src="{{ news.club.logo.url }}" alt="{{ news.club }}" />
{% else %}
<img src="{{ static("com/img/news.png") }}" alt="{{ news.club }}" />
{% endif %}
</div>
<h4> <a href="{{ url('com:news_detail', news_id=news.id) }}">{{ news.title }}</a></h4>
<div><a href="{{ news.club.get_absolute_url() }}">{{ news.club }}</a></div>
<div class="news_date">
<span>{{ news.dates.first().start_date|localtime|time(DATETIME_FORMAT) }}</span> -
<span>{{ news.dates.first().end_date|localtime|time(DATETIME_FORMAT) }}</span>
</div>
<div class="news_content">{{ news.summary|markdown }}
<div class="button_bar">
{{ fb_quick(news) }}
{{ tweet_quick(news) }}
</div>
</div>
</section>
{% endfor %}
{% endif %}
{% for day, dates_group in news_dates %}
<div class="news_events_group">
<div class="news_events_group_date">
<div>
<div>{{ day|date('D') }}</div>
<div class="day">{{ day|date('d') }}</div>
<div>{{ day|date('b') }}</div>
</div>
</div>
{% endfor %}
<div class="news_events_group_items">
{% for date in dates_group %}
<article class="news_event">
<header class="row gap">
{% if date.news.club.logo %}
<img src="{{ date.news.club.logo.url }}" alt="{{ date.news.club }}"/>
{% else %}
<img src="{{ static("com/img/news.png") }}" alt="{{ date.news.club }}"/>
{% endif %}
<div class="header_content">
<h4>
<a href="{{ url('com:news_detail', news_id=date.news_id) }}">
{{ date.news.title }}
</a>
</h4>
<a href="{{ date.news.club.get_absolute_url() }}">{{ date.news.club }}</a>
<div class="news_date">
<time datetime="{{ date.start_date.isoformat(timespec="seconds") }}">
{{ date.start_date|localtime|time(DATETIME_FORMAT) }}
</time> -
<time datetime="{{ date.end_date.isoformat(timespec="seconds") }}">
{{ date.end_date|localtime|time(DATETIME_FORMAT) }}
</time>
</div>
</div>
</header>
<div class="news_content markdown">
{{ date.news.summary|markdown }}
</div>
</article>
{% endfor %}
</div>
</div>
{% else %}
<div class="news_empty">
<em>{% trans %}Nothing to come...{% endtrans %}</em>
</div>
{% endif %}
{% endfor %}
<h3>
{% trans %}All coming events{% endtrans %}
@ -110,18 +114,26 @@
<ul>
<li>
<i class="fa-brands fa-discord fa-xl"></i>
<a rel="nofollow" target="#" href="https://discord.gg/QvTm3XJrHR">{% trans %}Discord AE{% endtrans %}</a>
<a rel="nofollow" target="#" href="https://discord.gg/QvTm3XJrHR">
{% trans %}Discord AE{% endtrans %}
</a>
{% if user.was_subscribed %}
- <a rel="nofollow" target="#" href="https://discord.gg/u6EuMfyGaJ">{% trans %}Dev Team{% endtrans %}</a>
- <a rel="nofollow" target="#" href="https://discord.gg/u6EuMfyGaJ">
{% trans %}Dev Team{% endtrans %}
</a>
{% endif %}
</li>
<li>
<i class="fa-brands fa-facebook fa-xl"></i>
<a rel="nofollow" target="#" href="https://www.facebook.com/@AEUTBM/">{% trans %}Facebook{% endtrans %}</a>
<a rel="nofollow" target="#" href="https://www.facebook.com/@AEUTBM/">
Facebook
</a>
</li>
<li>
<i class="fa-brands fa-square-instagram fa-xl"></i>
<a rel="nofollow" target="#" href="https://www.instagram.com/ae_utbm">{% trans %}Instagram{% endtrans %}</a>
<a rel="nofollow" target="#" href="https://www.instagram.com/ae_utbm">
Instagram
</a>
</li>
</ul>
</div>
@ -130,7 +142,7 @@
<div id="birthdays">
<h3>{% trans %}Birthdays{% endtrans %}</h3>
<div id="birthdays_content">
{%- if user.was_subscribed -%}
{%- if user.has_perm("core.view_user") -%}
<ul class="birthdays_year">
{%- for year, users in birthdays -%}
<li>
@ -143,8 +155,13 @@
</li>
{%- endfor -%}
</ul>
{%- else -%}
{%- elif not user.was_subscribed -%}
{# The user cannot view birthdays, because he never subscribed #}
<p>{% trans %}You need to subscribe to access this content{% endtrans %}</p>
{%- else -%}
{# There is another reason why user cannot view birthdays (maybe he is banned)
but we cannot know exactly what is this reason #}
<p>{% trans %}You cannot access this content{% endtrans %}</p>
{%- endif -%}
</div>
</div>

View File

@ -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):

View File

@ -39,14 +39,6 @@
<a rel="nofollow" target="#" class="share_button twitter" href="https://twitter.com/intent/tweet?text={{ news.get_full_url() }}">{% trans %}Tweet{% endtrans %}</a>
{%- endmacro %}
{% macro fb_quick(news) -%}
<a rel="nofollow" target="#" href="https://www.facebook.com/sharer/sharer.php?u={{ news.get_full_url() }}" class="fb fa-brands fa-facebook fa-2x"></a>
{%- endmacro %}
{% macro tweet_quick(news) -%}
<a rel="nofollow" target="#" href="https://twitter.com/intent/tweet?text={{ news.get_full_url() }}" class="twitter fa-brands fa-twitter-square fa-2x"></a>
{%- endmacro %}
{% macro user_mini_profile(user) %}
<div class="user_mini_profile">
<div class="user_mini_profile_infos">