diff --git a/com/static/com/css/news-list.scss b/com/static/com/css/news-list.scss
index bcbf8273..d073c4ac 100644
--- a/com/static/com/css/news-list.scss
+++ b/com/static/com/css/news-list.scss
@@ -36,6 +36,11 @@
&:not(:first-of-type) {
margin: 2em 0 1em 0;
}
+
+ .feed {
+ float: right;
+ color: #f26522;
+ }
}
@media screen and (max-width: $small-devices) {
diff --git a/com/templates/com/news_list.jinja b/com/templates/com/news_list.jinja
index 168a95b4..0f1f4301 100644
--- a/com/templates/com/news_list.jinja
+++ b/com/templates/com/news_list.jinja
@@ -8,6 +8,9 @@
{% block additional_css %}
+
+ {# Atom feed discovery, not really css but also goes there #}
+
{% endblock %}
{% block additional_js %}
@@ -19,7 +22,10 @@
{% 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 %}
+
+ {% trans %}Events today and the next few days{% endtrans %}
+
+
{% if user.is_authenticated and (user.is_com_admin or user.memberships.board().ongoing().exists()) %}
@@ -73,7 +79,10 @@
{% endif %}
-
{% trans %}All coming events{% endtrans %}
+
+ {% trans %}All coming events{% endtrans %}
+
+
diff --git a/com/tests/test_views.py b/com/tests/test_views.py
index 100a83ef..f80839ab 100644
--- a/com/tests/test_views.py
+++ b/com/tests/test_views.py
@@ -17,6 +17,7 @@ from unittest.mock import patch
import pytest
from django.conf import settings
+from django.contrib.sites.models import Site
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
from django.urls import reverse
@@ -24,7 +25,7 @@ from django.utils import html
from django.utils.timezone import localtime, now
from django.utils.translation import gettext as _
from model_bakery import baker
-from pytest_django.asserts import assertRedirects
+from pytest_django.asserts import assertNumQueries, assertRedirects
from club.models import Club, Membership
from com.models import News, NewsDate, Poster, Sith, Weekmail, WeekmailArticle
@@ -319,3 +320,15 @@ class TestNewsCreation(TestCase):
self.valid_payload,
)
mocked.assert_called()
+
+
+@pytest.mark.django_db
+def test_feed(client):
+ """Smoke test that checks that the atom feed is working"""
+ Site.objects.clear_cache()
+ with assertNumQueries(2):
+ # get sith domain with Site api: 1 request
+ # get all news and related info: 1 request
+ resp = client.get(reverse("com:news_feed"))
+ assert resp.status_code == 200
+ assert resp.headers["Content-Type"] == "application/rss+xml; charset=utf-8"
diff --git a/com/urls.py b/com/urls.py
index 592e653b..8afbfd12 100644
--- a/com/urls.py
+++ b/com/urls.py
@@ -25,6 +25,7 @@ from com.views import (
NewsCreateView,
NewsDeleteView,
NewsDetailView,
+ NewsFeed,
NewsListView,
NewsModerateView,
NewsUpdateView,
@@ -73,6 +74,7 @@ urlpatterns = [
name="weekmail_article_edit",
),
path("news/", NewsListView.as_view(), name="news_list"),
+ path("news/feed/", NewsFeed(), name="news_feed"),
path("news/admin/", NewsAdminListView.as_view(), name="news_admin_list"),
path("news/create/", NewsCreateView.as_view(), name="news_new"),
path("news//edit/", NewsUpdateView.as_view(), name="news_edit"),
diff --git a/com/views.py b/com/views.py
index a6faf214..0ab8fc1c 100644
--- a/com/views.py
+++ b/com/views.py
@@ -26,8 +26,10 @@ from datetime import timedelta
from smtplib import SMTPRecipientsRefused
from typing import Any
+from dateutil.relativedelta import relativedelta
from django.conf import settings
from django.contrib.auth.mixins import AccessMixin, PermissionRequiredMixin
+from django.contrib.syndication.views import Feed
from django.core.exceptions import PermissionDenied, ValidationError
from django.db.models import Max
from django.forms.models import modelform_factory
@@ -268,6 +270,34 @@ class NewsDetailView(CanViewMixin, DetailView):
return super().get_context_data(**kwargs) | {"date": self.object.dates.first()}
+class NewsFeed(Feed):
+ title = _("News")
+ link = reverse_lazy("com:news_list")
+ description = _("All incoming events")
+
+ def items(self):
+ return (
+ NewsDate.objects.filter(
+ news__is_moderated=True,
+ end_date__gte=timezone.now() - (relativedelta(months=6)),
+ )
+ .select_related("news", "news__author")
+ .order_by("-start_date")
+ )
+
+ def item_title(self, item: NewsDate):
+ return item.news.title
+
+ def item_description(self, item: NewsDate):
+ return item.news.summary
+
+ def item_link(self, item: NewsDate):
+ return item.news.get_absolute_url()
+
+ def item_author_name(self, item: NewsDate):
+ return item.news.author.get_display_name()
+
+
# Weekmail
diff --git a/core/management/commands/populate.py b/core/management/commands/populate.py
index 4d63bfb9..26bc6074 100644
--- a/core/management/commands/populate.py
+++ b/core/management/commands/populate.py
@@ -92,7 +92,12 @@ class Command(BaseCommand):
raise Exception("Never call this command in prod. Never.")
Sith.objects.create(weekmail_destinations="etudiants@git.an personnel@git.an")
- Site.objects.create(domain=settings.SITH_URL, name=settings.SITH_NAME)
+
+ site = Site.objects.get_current()
+ site.domain = settings.SITH_URL
+ site.name = settings.SITH_NAME
+ site.save()
+
groups = self._create_groups()
self._create_ban_groups()
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 07eede14..dc6b5ee6 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-01-10 14:52+0100\n"
+"POT-Creation-Date: 2025-01-19 18:12+0100\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Maréchal \n"
@@ -1447,7 +1447,7 @@ msgid "News admin"
msgstr "Administration des nouvelles"
#: com/templates/com/news_admin_list.jinja com/templates/com/news_detail.jinja
-#: com/templates/com/news_list.jinja
+#: com/templates/com/news_list.jinja com/views.py
msgid "News"
msgstr "Nouvelles"
@@ -1525,6 +1525,10 @@ msgstr "Éditer (sera soumise de nouveau à la modération)"
msgid "Edit news"
msgstr "Éditer la nouvelle"
+#: com/templates/com/news_list.jinja
+msgid "News feed"
+msgstr "Flux d'actualités"
+
#: com/templates/com/news_list.jinja
msgid "Events today and the next few days"
msgstr "Événements aujourd'hui et dans les prochains jours"
@@ -1767,6 +1771,10 @@ msgstr "Message d'alerte"
msgid "Screens list"
msgstr "Liste d'écrans"
+#: com/views.py
+msgid "All incoming events"
+msgstr "Tous les événements à venir"
+
#: com/views.py
msgid "Delete and save to regenerate"
msgstr "Supprimer et sauver pour régénérer"