Skip to content

Commit

Permalink
Merge pull request #1713 from digitalfabrik/bugfix/pnt-duplicate-lang…
Browse files Browse the repository at this point in the history
…uage

Fix sending Push Notifications
  • Loading branch information
timobrembeck authored Oct 17, 2022
2 parents 4d78059 + 25023d4 commit 146ad3a
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 67 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ UNRELEASED
* [ [#1434](https://github.com/digitalfabrik/integreat-cms/issues/1434) ] Add display of HIX values to nudge users to write easier texts
* [ [#1770](https://github.com/digitalfabrik/integreat-cms/issues/1770) ] Fix error in SUMM.AI translation if paragraph contains only special characters
* [ [#1710](https://github.com/digitalfabrik/integreat-cms/issues/1710) ] Add spacing to sidebar to improve view on small screens
* [ [#1526](https://github.com/digitalfabrik/integreat-cms/issues/1526)] Fix sending push notifications in one language
* [ [#1630](https://github.com/digitalfabrik/integreat-cms/issues/1630)] Fix not recognized sent status of push notifications


2022.10.0
Expand Down
4 changes: 2 additions & 2 deletions integreat_cms/api/v3/push_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ def transform_notification(pnt):
"""
return {
"id": str(pnt.pk),
"title": pnt.title,
"message": pnt.text,
"title": pnt.get_title(),
"message": pnt.get_text(),
"timestamp": pnt.last_updated, # deprecated field in the future
"last_updated": timezone.localtime(pnt.last_updated),
"channel": pnt.push_notification.channel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ class PushNotificationForm(CustomModelForm):
Form for creating and modifying push notification objects
"""

def __init__(self, **kwargs):
r"""
Initialize push notification form
:param \**kwargs: The supplied keyword arguments
:type \**kwargs: dict
"""
# Instantiate CustomModelForm
super().__init__(**kwargs)

# Make fields disabled when push notification was already sent
if self.instance.sent_date:
self.fields["channel"].disabled = True
self.fields["mode"].disabled = True

class Meta:
model = PushNotification
fields = ["channel", "mode"]
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.utils.translation import override, ugettext_lazy as _

from ..custom_model_form import CustomModelForm
from ...constants import push_notifications
from ...models import PushNotificationTranslation

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -50,3 +51,19 @@ def add_error_messages(self, request):
logger.debug(
"PushNotificationTranslationForm submitted with errors: %r", self.errors
)

def has_changed(self):
"""
Return ``True`` if submitted data differs from initial data.
If the main language should be used as fallback for missing translations, this always return ``True``.
:return: Whether the form has changed
:rtype: bool
"""
if (
hasattr(self.instance, "push_notification")
and self.instance.push_notification.mode
== push_notifications.USE_MAIN_LANGUAGE
):
return True
return super().has_changed()
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Make title for push notification translations optional
"""
# Generated by Django 3.2.15 on 2022-09-23 12:48

from django.db import migrations, models


class Migration(migrations.Migration):
"""
Make title for push notification translations optional
"""

dependencies = [
("cms", "0041_region_hix_enabled"),
]

operations = [
migrations.AlterField(
model_name="pushnotificationtranslation",
name="title",
field=models.CharField(blank=True, max_length=250, verbose_name="title"),
),
]
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""
The model for the push notificatiion
"""
from django.conf import settings
from django.db import models
from django.utils.functional import cached_property
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.conf import settings

from ..abstract_base_model import AbstractBaseModel
from ..languages.language import Language
from .push_notification import PushNotification
from ...constants import push_notifications as pnt_const


class PushNotificationTranslation(AbstractBaseModel):
"""
Data model representing a push notification translation
"""

title = models.CharField(
max_length=250,
verbose_name=_("title"),
)
title = models.CharField(max_length=250, blank=True, verbose_name=_("title"))
text = models.TextField(
max_length=250,
blank=True,
Expand Down Expand Up @@ -56,6 +55,43 @@ def search(cls, region, language_slug, query):
title__icontains=query,
)

def get_title(self):
"""
Get the title of the notification translation.
:return: A title for the push notification
:rtype: str
"""
if (
self.push_notification.mode == pnt_const.USE_MAIN_LANGUAGE
and self.title == ""
and self.push_notification.default_translation
):
return self.push_notification.default_translation.title
return self.title

def get_text(self):
"""
Get the text of the notification. Construct a fallback text if possible.
:return: A text for the push notification
:rtype: str
"""
if (
self.push_notification.mode == pnt_const.USE_MAIN_LANGUAGE
and self.text == ""
):
translations = "\n".join(
[
f"{translation.language.native_name}: {settings.WEBAPP_URL}{translation.get_absolute_url()}"
for translation in self.push_notification.translations.exclude(
text=""
)
]
)
return f"{self.language.message_content_not_available}\n{translations}"
return self.text

def get_absolute_url(self):
"""
Generates the absolute url to a news object in the app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured

from ...models import PushNotificationTranslation
from ...models import Region
from ...constants import push_notifications as pnt_const
from ..models import PushNotificationTranslation
from ..models import Region
from ..constants import push_notifications as pnt_const

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -71,7 +71,7 @@ def load_secondary_pnts(self):
secondary_pnt.title = self.primary_pnt.title
secondary_pnt.text = self.primary_pnt.text
self.prepared_pnts.append(secondary_pnt)
if len(secondary_pnt.title) > 0:
elif len(secondary_pnt.title) > 0:
self.prepared_pnts.append(secondary_pnt)

def is_valid(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import PermissionDenied, ImproperlyConfigured
from django.forms import inlineformset_factory
from django.shortcuts import render, redirect
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.views.generic import TemplateView
from django.forms import modelformset_factory

from .push_notification_sender import PushNotificationSender
from ...utils.push_notification_sender import PushNotificationSender
from ...decorators import permission_required
from ...forms import (
PushNotificationForm,
Expand Down Expand Up @@ -76,9 +76,6 @@ def get(self, request, *args, **kwargs):
push_notification = PushNotification.objects.filter(
id=kwargs.get("push_notification_id")
).first()
push_notification_translations = PushNotificationTranslation.objects.filter(
push_notification=push_notification
)

if push_notification and push_notification.sent_date:
messages.info(
Expand All @@ -96,24 +93,26 @@ def get(self, request, *args, **kwargs):
push_notification_form = PushNotificationForm(instance=push_notification)

num_languages = len(region.active_languages)
PNTFormset = modelformset_factory(
PushNotificationTranslation,
PushNotificationTranslationFormSet = inlineformset_factory(
parent_model=PushNotification,
model=PushNotificationTranslation,
form=PushNotificationTranslationForm,
min_num=1, # Require at least the first form to be valid
min_num=num_languages,
max_num=num_languages,
extra=num_languages - push_notification_translations.count(),
)
existing_languages = push_notification.languages if push_notification else []
pnt_formset = PNTFormset(
# Add queryset for all translations which exist already
queryset=push_notification_translations,
pnt_formset = PushNotificationTranslationFormSet(
# The push notification instance to which we want to create translations
instance=push_notification,
# Add initial data for all languages which do not yet have a translation
initial=[
{"language": language}
for language in region.active_languages
if language not in existing_languages
],
)
# Make title of default language required
pnt_formset[0].fields["title"].required = True

return render(
request,
Expand All @@ -127,7 +126,7 @@ def get(self, request, *args, **kwargs):
},
)

# pylint: disable=too-many-branches
# pylint: disable=too-many-branches,too-many-statements
def post(self, request, *args, **kwargs):
r"""
Save and show form for creating or editing a push notification. Send push notification
Expand All @@ -154,9 +153,6 @@ def post(self, request, *args, **kwargs):
push_notification_instance = PushNotification.objects.filter(
id=kwargs.get("push_notification_id")
).first()
push_notification_translations = PushNotificationTranslation.objects.filter(
push_notification=push_notification_instance
)

if not request.user.has_perm("cms.change_pushnotification"):
logger.warning(
Expand All @@ -175,27 +171,30 @@ def post(self, request, *args, **kwargs):
)

num_languages = len(region.active_languages)
PNTFormset = modelformset_factory(
PushNotificationTranslation,
PushNotificationTranslationFormSet = inlineformset_factory(
parent_model=PushNotification,
model=PushNotificationTranslation,
form=PushNotificationTranslationForm,
min_num=1, # Require at least the first form to be valid
min_num=num_languages,
max_num=num_languages,
extra=num_languages - push_notification_translations.count(),
)
existing_languages = (
push_notification_instance.languages if push_notification_instance else []
)
pnt_formset = PNTFormset(
pnt_formset = PushNotificationTranslationFormSet(
data=request.POST,
# Add queryset for all translations which exist already
queryset=push_notification_translations,
# The push notification instance to which we want to create translations
instance=push_notification_instance,
# Add initial data for all languages which do not yet have a translation
initial=[
{"language": language}
for language in region.active_languages
if language not in existing_languages
],
)
# Make title of default language required
pnt_formset[0].fields["title"].required = True

if not pn_form.is_valid():
# Add error messages
pn_form.add_error_messages(request)
Expand All @@ -212,9 +211,10 @@ def post(self, request, *args, **kwargs):
form.add_error_messages(request)
else:
# Save forms
pn_form.save()
for form in pnt_formset:
form.instance.push_notification = pn_form.instance
pnt_formset.instance = pn_form.save()
if not push_notification_instance:
for form in pnt_formset:
form.instance.push_notification = pnt_formset.instance
pnt_formset.save()

# Add the success message
Expand Down
2 changes: 1 addition & 1 deletion integreat_cms/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
IMPRINT_SLUG = "imprint"

#: The slug of the region "Testumgebung" - prevent sending PNs to actual users in development in
#: :func:`~integreat_cms.cms.views.push_notifications.push_notification_sender.PushNotificationSender.send_pn`
#: :func:`~integreat_cms.cms.utils.push_notification_sender.PushNotificationSender.send_pn`
TEST_REGION_SLUG = "testumgebung"

#: URL to the Integreat Website
Expand Down
Loading

0 comments on commit 146ad3a

Please sign in to comment.