From 6c3ac4f05af19da442ea3d2742bad2912690b110 Mon Sep 17 00:00:00 2001 From: mikaelGusse Date: Tue, 12 Mar 2024 10:57:30 +0200 Subject: [PATCH] Add multilanguage news items --- course/api/serializers.py | 1 + locale/en/LC_MESSAGES/django.po | 4 ++ locale/fi/LC_MESSAGES/django.po | 4 ++ news/cache.py | 2 + news/forms.py | 1 + news/migrations/0005_news_language.py | 28 ++++++++++++++ news/models.py | 8 +++- news/templates/news/list.html | 30 ++++++++++---- news/templates/news/user_news.html | 56 +++++++++++++-------------- news/templatetags/news.py | 14 ++++++- news/urls.py | 4 ++ news/views.py | 24 +++++++++++- 12 files changed, 138 insertions(+), 38 deletions(-) create mode 100644 news/migrations/0005_news_language.py diff --git a/course/api/serializers.py b/course/api/serializers.py index 8bcf8b9a9..ced3ca3f5 100644 --- a/course/api/serializers.py +++ b/course/api/serializers.py @@ -129,6 +129,7 @@ class Meta(AplusModelSerializer.Meta): 'title', 'audience', 'publish', + 'language', 'body', 'pin', ) diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 02ef6a4c3..149f58109 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -5374,6 +5374,10 @@ msgstr "news items" msgid "ADD_NEWS_ITEM" msgstr "Add news item" +#: news/templates/news/edit.html news/templates/news/list.html +msgid "REMOVE_SELECTED_NEWS_ITEMS" +msgstr "Remove selected news items" + #: news/templates/news/list.html msgid "NEWS" msgstr "News" diff --git a/locale/fi/LC_MESSAGES/django.po b/locale/fi/LC_MESSAGES/django.po index 2d158b495..df79ebf48 100644 --- a/locale/fi/LC_MESSAGES/django.po +++ b/locale/fi/LC_MESSAGES/django.po @@ -5394,6 +5394,10 @@ msgstr "uutiset" msgid "ADD_NEWS_ITEM" msgstr "Lisää uutinen" +#: news/templates/news/edit.html news/templates/news/list.html +msgid "REMOVE_SELECTED_NEWS_ITEMS" +msgstr "Poista valitut uutiset" + #: news/templates/news/list.html msgid "NEWS" msgstr "Uutiset" diff --git a/news/cache.py b/news/cache.py index 31bbd1315..fad26e045 100644 --- a/news/cache.py +++ b/news/cache.py @@ -18,12 +18,14 @@ def _generate_data(self, instance, data=None): # pylint: disable=arguments-diffe 'id': item.id, 'audience': item.audience, 'publish': item.publish, + 'language': item.language, 'title': item.title, 'body': item.body, 'pin': item.pin, } for item in instance.news.all() ] + return { 'news': news, } diff --git a/news/forms.py b/news/forms.py index 7116d9c94..f4a07e02b 100644 --- a/news/forms.py +++ b/news/forms.py @@ -23,6 +23,7 @@ class Meta: 'pin', 'email_students', 'email_staff', + 'language', 'title', 'body', ] diff --git a/news/migrations/0005_news_language.py b/news/migrations/0005_news_language.py new file mode 100644 index 000000000..6b0593d89 --- /dev/null +++ b/news/migrations/0005_news_language.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.11 on 2024-03-20 07:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("news", "0004_auto_20210812_1536"), + ] + + operations = [ + migrations.AddField( + model_name="news", + name="language", + field=models.CharField( + choices=[ + ("-", "All"), + ("en", "English"), + ("fi", "Finnish"), + ("sv", "Swedish"), + ], + default="-", + max_length=30, + verbose_name="LANGUAGE", + ), + ), + ] diff --git a/news/models.py b/news/models.py index d99d16f28..713a58929 100644 --- a/news/models.py +++ b/news/models.py @@ -1,6 +1,7 @@ from django.db import models from django.utils.translation import gettext_lazy as _ from django.utils import timezone +from aplus import settings from course.models import CourseInstance from lib.models import UrlMixin @@ -21,6 +22,11 @@ class News(models.Model, UrlMixin): verbose_name=_('LABEL_PUBLISH'), default=timezone.now, ) + language = models.CharField( + verbose_name=_('LANGUAGE'), + max_length=30, + choices=([('-', 'All')] + settings.LANGUAGES), default='-', + ) title = models.CharField( verbose_name=_('LABEL_TITLE'), max_length=255, @@ -39,7 +45,7 @@ class Meta: ordering = ['course_instance', '-pin', '-publish'] def __str__(self): - return "{} {}".format(str(self.publish), self.title) + return "{} {} {}".format(str(self.publish), self.title, str(self.language)) def get_url_kwargs(self): return dict(news_id=self.id, **self.course_instance.get_url_kwargs()) # pylint: disable=use-dict-literal diff --git a/news/templates/news/list.html b/news/templates/news/list.html index 7cccc0546..7c81524df 100644 --- a/news/templates/news/list.html +++ b/news/templates/news/list.html @@ -15,14 +15,21 @@
+ + + {% for item in news %} + + + + {% endfor %} + {% csrf_token %} + + + +
{% translate "SELECT" %} {% translate "PUBLISH" %} {% translate "AUDIENCE" %} {% translate "TITLE" %}{% translate "LANGUAGE" %}
+ + {% if item.pin %} @@ -35,6 +42,10 @@ {{ item.title|safe }} + {{ item.language|safe }} + @@ -42,16 +53,21 @@ - - {% csrf_token %} - - + + + {% translate "REMOVE" %} +

diff --git a/news/templates/news/user_news.html b/news/templates/news/user_news.html index 7f405096f..568a2bd83 100644 --- a/news/templates/news/user_news.html +++ b/news/templates/news/user_news.html @@ -1,6 +1,6 @@ {% load i18n %} {% load news %} - +{% load course %} {% if news %}

@@ -8,41 +8,41 @@

{% translate "COURSE_NEWS" %}

- {% for item in news %} -
- {% if item.pin %} - {% translate "NEWS_ITEM_PINNED_SR_TEXT" %} - {% endif %} -
-

- {{ item.title|safe }} -

-
- {% if not item|is_published:now %} - {% translate "PUBLISHED_ON" %}: - {% else %} - - {% endif %} - {% if is_course_staff %} - {{ item.audience|news_audience }} - {% endif %} - {% if item.pin %} - - {% endif %} + {% for item in language_news %} +
+ {% if item.pin %} + {% translate "NEWS_ITEM_PINNED_SR_TEXT" %} + {% endif %} +
+

+ {{ item.title|safe }} +

+
+ {% if not item|is_published:now %} + {% translate "PUBLISHED_ON" %}: + {% else %} + + {% endif %} + {% if is_course_staff %} + {{ item.audience|news_audience }} + {% endif %} + {% if item.pin %} + + {% endif %} +
+

+ {{ item.body|safe }} +

-

- {{ item.body|safe }} -

-
{# If a limit for folding news (more) is set, this creates the folding section #} - {% if forloop.counter == more and news|length > more and more > 0 %} + {% if forloop.counter == more and language_news|length > more and more > 0 %}
{# start of collapse.div #} {% endif %} - {% if forloop.last and news|length > more and more > 0 %} + {% if forloop.last and language_news|length > more and more > 0 %}
{# end of collapse.div #} {% endif %} {% endfor %} diff --git a/news/templatetags/news.py b/news/templatetags/news.py index 658c7d0ba..f4dbb8769 100644 --- a/news/templatetags/news.py +++ b/news/templatetags/news.py @@ -1,10 +1,13 @@ +from collections import defaultdict + from django import template from django.utils import timezone from lib.errors import TagUsageError from ..cache import CachedNews from ..models import News - +from ..models import CourseInstance +from django.utils.translation import get_language register = template.Library() @@ -28,10 +31,19 @@ def user_news(context, num, more=0): # pylint: disable=unused-argument or user.userprofile.is_external ) + language_to_news = defaultdict(list) + for item in news: + language_to_news[item['language']].append(item) + + # Get news of current chosen language AND news items with All language + language_dict = language_to_news['-'] + language_to_news[get_language()] + return { 'is_course_staff': context['is_course_staff'], 'now': context['now'], 'news': news, + 'language_news': language_dict, + 'instance_language': get_language(), 'more': more, } diff --git a/news/urls.py b/news/urls.py index 0a207ddbd..a02f8bcf4 100644 --- a/news/urls.py +++ b/news/urls.py @@ -17,4 +17,8 @@ re_path(EDIT_URL_PREFIX + r'news/(?P\d+)/remove/$', views.RemoveNewsView.as_view(), name="news-remove"), + re_path(EDIT_URL_PREFIX + r'news/remove-selected-news/$', + views.RemoveSelectedNewsView.as_view(), + name="remove-selected-news"), + ] diff --git a/news/views.py b/news/views.py index c5ce6dfdb..3ef79a529 100644 --- a/news/views.py +++ b/news/views.py @@ -15,11 +15,33 @@ class ListNewsView(CourseInstanceBaseView): access_mode = ACCESS.TEACHER template_name = "news/list.html" + def get_common_objects(self): + super().get_common_objects() + self.news = self.instance.news.all() + print(self.news) + + self.note("news") + + +class RemoveSelectedNewsView(CourseInstanceBaseView, BaseRedirectView): + access_mode = ACCESS.TEACHER + template_name = "news/list.html" + def get_common_objects(self): super().get_common_objects() self.news = self.instance.news.all() self.note("news") + def post(self, request, *args, **kwargs): + selected_news_ids = request.POST.getlist("selection") + + for new in self.news: + if str(new.id) in selected_news_ids: + print("Deleting ", new) + new.delete() + + return self.redirect(self.instance.get_url("news-list")) + class EditNewsView(CourseInstanceMixin, BaseFormView): access_mode = ACCESS.TEACHER @@ -76,6 +98,6 @@ def get_resource_objects(self): ) self.note("news_item") - def post(self, request, *args, **kwargs): + def get(self, request, *args, **kwargs): self.news_item.delete() return self.redirect(self.instance.get_url("news-list"))