Skip to content

Commit

Permalink
Merge pull request #287 from City-of-Turku/develop
Browse files Browse the repository at this point in the history
Release tku-v1.8
  • Loading branch information
SanttuA authored Sep 26, 2023
2 parents 3d49b50 + ffa7aa8 commit 1cd15d5
Show file tree
Hide file tree
Showing 46 changed files with 910 additions and 216 deletions.
11 changes: 10 additions & 1 deletion locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -1130,7 +1130,7 @@ msgid "Reserver name"
msgstr ""

#: resources/models/reservation.py:156
msgid "Reserver ID (business or person)"
msgid "Reserver ID (business)"
msgstr ""

#: resources/models/reservation.py:157
Expand Down Expand Up @@ -2800,3 +2800,12 @@ msgstr ""

msgid "Update HTML Templates"
msgstr ""

msgid "HTML Preview"
msgstr ""

msgid "Show Preview"
msgstr ""

msgid "Hide Preview"
msgstr ""
13 changes: 11 additions & 2 deletions locale/fi/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -810,8 +810,8 @@ msgstr "Varauksen lisäkysymykset"
msgid "Reserver name"
msgstr "Varaajan nimi"

msgid "Reserver ID (business or person)"
msgstr "Varaajan tunniste (yritys tai henkilö)"
msgid "Reserver ID (business)"
msgstr "Varaajan tunniste (yritys)"

msgid "Reserver email address"
msgstr "Varaajan sähköpostiosoite"
Expand Down Expand Up @@ -2177,3 +2177,12 @@ msgstr "sähköpostimalliprojekti"

msgid "Update HTML Templates"
msgstr "Päivitä HTML-pohjat"

msgid "HTML Preview"
msgstr "HTML:n esikatselu"

msgid "Show Preview"
msgstr "Näytä esikatselu"

msgid "Hide Preview"
msgstr "Piilota esikatselu"
13 changes: 11 additions & 2 deletions locale/sv/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -812,8 +812,8 @@ msgstr "Extra frågor för bokning"
msgid "Reserver name"
msgstr "Reservnamn"

msgid "Reserver ID (business or person)"
msgstr "Reserv ID (företag eller person)"
msgid "Reserver ID (business)"
msgstr "Reserv ID (företag)"

msgid "Reserver email address"
msgstr "Reserverares email adress"
Expand Down Expand Up @@ -2115,3 +2115,12 @@ msgstr "e-postmallprojekt"

msgid "Update HTML Templates"
msgstr "Uppdatera HTML-mallar"

msgid "HTML Preview"
msgstr "HTML-förhandsgranskning"

msgid "Show Preview"
msgstr "Visa förhandsgranskning"

msgid "Hide Preview"
msgstr "Dölj förhandsgranskningen"
Empty file added maintenance/__init__.py
Empty file.
55 changes: 55 additions & 0 deletions maintenance/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from django import forms
from django.contrib import admin
from django.db.models import Q
from django.contrib.admin import site as admin_site
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

from modeltranslation.admin import TranslationAdmin


from .models import MaintenanceMessage, MaintenanceMode


class MaintenanceModeAdmin(admin.ModelAdmin):
pass

class MaintenanceModeInline(admin.TabularInline):
model = MaintenanceMode
fields = ('start', 'end', )
verbose_name = _('maintenance mode')
verbose_name_plural = _('maintenance modes')
extra = 0


class MaintenanceMessageAdminForm(forms.ModelForm):
class Meta:
model = MaintenanceMessage
fields = ('start', 'end', 'message', )

def clean(self):
start = self.cleaned_data['start']
end = self.cleaned_data['end']
query = Q(end__gt=start, start__lt=end)
if self.instance and self.instance.pk:
query &= ~Q(pk=self.instance.pk)
collision = MaintenanceMessage.objects.filter(query)
if collision.exists():
raise ValidationError(_('maintenance message already exists.'))

class MaintenanceMessageAdmin(TranslationAdmin):
form = MaintenanceMessageAdminForm
inlines = ( MaintenanceModeInline, )
fieldsets = (
(_('General'), {
'fields': (
'start',
'end',
'message'
),
}),
)


admin_site.register(MaintenanceMessage, MaintenanceMessageAdmin)
admin_site.register(MaintenanceMode, MaintenanceModeAdmin)
1 change: 1 addition & 0 deletions maintenance/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .announcements import MaintenanceMessageViewSet
36 changes: 36 additions & 0 deletions maintenance/api/announcements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from django.utils import timezone
from rest_framework import viewsets, serializers
from resources.api.base import TranslatedModelSerializer, register_view
from maintenance.models import MaintenanceMessage



class MaintenanceMessageSerializer(TranslatedModelSerializer):
is_maintenance_mode_on = serializers.SerializerMethodField()

class Meta:
model = MaintenanceMessage
fields = ('message', 'is_maintenance_mode_on')

def get_is_maintenance_mode_on(self, obj):
maintenance_modes = obj.maintenancemode_set.all()
now = timezone.now()

for maintenance_mode in maintenance_modes:
if maintenance_mode.start <= now <= maintenance_mode.end:
return True

return False



class MaintenanceMessageViewSet(viewsets.ReadOnlyModelViewSet):
queryset = MaintenanceMessage.objects.all()
serializer_class = MaintenanceMessageSerializer


def get_queryset(self):
return self.queryset.active()


register_view(MaintenanceMessageViewSet, 'announcements', base_name='announcements')
6 changes: 6 additions & 0 deletions maintenance/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class MaintenanceConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'maintenance'
57 changes: 57 additions & 0 deletions maintenance/migrations/0001_create_maintenance_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Generated by Django 3.2.19 on 2023-09-04 06:19

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='MaintenanceMessage',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Time of creation')),
('modified_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Time of modification')),
('message', models.TextField(verbose_name='Message')),
('message_fi', models.TextField(null=True, verbose_name='Message')),
('message_en', models.TextField(null=True, verbose_name='Message')),
('message_sv', models.TextField(null=True, verbose_name='Message')),
('start', models.DateTimeField(verbose_name='Begin time')),
('end', models.DateTimeField(verbose_name='End time')),
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='maintenancemessage_created', to=settings.AUTH_USER_MODEL, verbose_name='Created by')),
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='maintenancemessage_modified', to=settings.AUTH_USER_MODEL, verbose_name='Modified by')),
],
options={
'verbose_name': 'maintenance message',
'verbose_name_plural': 'maintenance messages',
'ordering': ('start',),
},
),
migrations.CreateModel(
name='MaintenanceMode',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Time of creation')),
('modified_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Time of modification')),
('start', models.DateTimeField(verbose_name='Begin time')),
('end', models.DateTimeField(verbose_name='End time')),
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='maintenancemode_created', to=settings.AUTH_USER_MODEL, verbose_name='Created by')),
('maintenance_message', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maintenance.maintenancemessage')),
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='maintenancemode_modified', to=settings.AUTH_USER_MODEL, verbose_name='Modified by')),
],
options={
'verbose_name': 'maintenance mode',
'verbose_name_plural': 'maintenance modes',
'ordering': ('start',),
},
),
]
Empty file.
62 changes: 62 additions & 0 deletions maintenance/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import datetime


from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError


from resources.models.base import ModifiableModel


class MaintenanceMessageQuerySet(models.QuerySet):
def active(self):
return self.filter(start__lt=timezone.now(), end__gt=timezone.now())

class MaintenanceMessage(ModifiableModel):
message = models.TextField(verbose_name=_('Message'), null=False, blank=False)
start = models.DateTimeField(verbose_name=_('Begin time'), null=False, blank=False)
end = models.DateTimeField(verbose_name=_('End time'), null=False, blank=False)


objects = MaintenanceMessageQuerySet.as_manager()
class Meta:
verbose_name = _('maintenance message')
verbose_name_plural = _('maintenance messages')
ordering = ('start', )


def __str__(self):
return f"{_('maintenance message')} \
{timezone.localtime(self.start).replace(tzinfo=None)} - \
{timezone.localtime(self.end).replace(tzinfo=None)}" \
.capitalize()


def clean(self):
super().clean()
if self.end <= self.start:
raise ValidationError(_("Invalid start or end time"))

class MaintenanceModeQuerySet(models.QuerySet):
def active(self):
return self.filter(start__lt=timezone.now(), end__gt=timezone.now())


class MaintenanceMode(ModifiableModel):
start = models.DateTimeField(verbose_name=_('Begin time'), null=False, blank=False)
end = models.DateTimeField(verbose_name=_('End time'), null=False, blank=False)
maintenance_message = models.ForeignKey(MaintenanceMessage, on_delete=models.CASCADE, null=True, blank=True)

objects = MaintenanceModeQuerySet.as_manager()

class Meta:
verbose_name = _('maintenance mode')
verbose_name_plural = _('maintenance modes')
ordering = ('start', )

def clean(self):
super().clean()
if self.end <= self.start:
raise ValidationError(_("Invalid start or end time"))
3 changes: 3 additions & 0 deletions maintenance/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
8 changes: 8 additions & 0 deletions maintenance/translation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from modeltranslation.translator import TranslationOptions, register
from .models import MaintenanceMessage


@register(MaintenanceMessage)
class MaintenanceMessageTranslationOptions(TranslationOptions):
fields = ('message', )
required_languages = ('fi', 'en', 'sv', )
3 changes: 3 additions & 0 deletions maintenance/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.shortcuts import render

# Create your views here.
1 change: 1 addition & 0 deletions notifications/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class NotificationTemplateAdmin(TranslatableAdmin):
# variables are accessed?
#
form = NotificationTemplateForm
change_form_template = 'admin/html_preview.html'
actions = ['update_notification_html_templates']

def get_urls(self):
Expand Down
24 changes: 21 additions & 3 deletions notifications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from django.utils.translation import gettext_lazy as _
from django.utils.formats import date_format
from jinja2 import StrictUndefined
from jinja2.exceptions import TemplateError
from jinja2.exceptions import TemplateError, UndefinedError
from jinja2.sandbox import SandboxedEnvironment
from parler.models import TranslatableModel, TranslatedFields
from parler.utils.context import switch_language
Expand Down Expand Up @@ -183,6 +183,25 @@ def clean(self, **kwargs):
elif NotificationTemplate.objects.filter(type=self.type, is_default_template=False).exists():
logger.info("New default template of type {} was created.".format(self.type))

self.validate_templates()

def validate_templates(self):
context = {}
env = SandboxedEnvironment(trim_blocks=True, lstrip_blocks=True, undefined=StrictUndefined)
env.filters['reservation_time'] = reservation_time
env.filters['format_datetime'] = format_datetime
env.filters['format_datetime_tz'] = format_datetime_tz
templates = ['short_message', 'body', 'html_body']
for template in templates:
try:
env.from_string(getattr(self, template)).render(context)
except UndefinedError as e:
# context can have various variables that are hard to test without actual data
# so we just skip validation for them
continue
except TemplateError as e:
raise ValidationError({template: e})


def reservation_time(res):
if isinstance(res, dict):
Expand Down Expand Up @@ -218,7 +237,7 @@ def render_notification_template(notification_type, context, language_code=DEFAU
class NotificationTemplateGroup(ModifiableModel):
identifier = models.CharField(verbose_name=_('Identifier'), max_length=100)
name = models.CharField(verbose_name=_('Name'), max_length=200)
templates = models.ManyToManyField(NotificationTemplate,
templates = models.ManyToManyField(NotificationTemplate,
verbose_name=_('Notification templates'),
related_name='groups',
blank=True,
Expand All @@ -232,4 +251,3 @@ class Meta:
def __str__(self):
return self.name


Loading

0 comments on commit 1cd15d5

Please sign in to comment.