diff --git a/aleksis/apps/chronos/migrations/0018_add_lessoneventalarm.py b/aleksis/apps/chronos/migrations/0018_add_lessoneventalarm.py index b813aa84d21b66d1d0706ea8198e077ca7139672..dd44633e5499d1dcaffd4fcd61042a4664f4f15b 100644 --- a/aleksis/apps/chronos/migrations/0018_add_lessoneventalarm.py +++ b/aleksis/apps/chronos/migrations/0018_add_lessoneventalarm.py @@ -8,7 +8,7 @@ class Migration(migrations.Migration): dependencies = [ ('chronos', '0017_optional_slot_number'), - ('core', '0066_alter_freebusy_options_and_more'), + ('core', '0066_add_calendar_alarm'), ] operations = [ @@ -16,6 +16,7 @@ class Migration(migrations.Migration): name='LessonEventAlarm', fields=[ ('calendaralarm_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.calendaralarm')), + ('status', models.CharField(choices=[('c', 'Created'), ('e', 'Edited'), ('d', 'Deleted')], default='c', max_length=1, verbose_name='Status')), ], options={ 'verbose_name': 'Lesson event alarm', diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py index 25a16143441c9cd8f5df3a5cde6d3df7e6e737d0..98a3ef9e0e813c2238e37b89281efb601ca5d746 100644 --- a/aleksis/apps/chronos/models.py +++ b/aleksis/apps/chronos/models.py @@ -1359,10 +1359,10 @@ class LessonEvent(CalendarEvent): @property def all_teachers(self: LessonEvent) -> list[Person]: """Get list of all teachers for this lesson event.""" - all_teachers = list(self.teachers.all()) + all_teachers = self.teachers.all() if self.amends: - all_teachers += list(self.amends.teachers.all()) - return all_teachers + all_teachers = all_teachers.union(self.amends.teachers.all()) + return list(all_teachers) @property def group_names(self: LessonEvent) -> str: @@ -1589,11 +1589,26 @@ class LessonEvent(CalendarEvent): return objs def save(self, *args, **kwargs): + adding_status = self._state.adding + super().save(*args, **kwargs) # Save alarm in lesson event alarm model if self.amends: - alarm, created = LessonEventAlarm.objects.get_or_create(event=self, defaults={"send_notifications": True}) + if adding_status: + # TODO: allow for generating multiple alarms for one event + alarm = LessonEventAlarm(event=self, send_notifications=True) + alarm.save() + else: + alarms = LessonEventAlarm.objects.filter(event=self, status="c") + for alarm in alarms: + if alarm.notifications.filter(sent=True).exists(): + follow_up_alarm = LessonEventAlarm( + event=self, send_notifications=True, status="e" + ) + follow_up_alarm.save() + else: + alarm.update_or_create_notifications() class Meta: verbose_name = _("Lesson Event") @@ -1603,11 +1618,16 @@ class LessonEvent(CalendarEvent): class LessonEventAlarm(CalendarAlarm): """Alarm model for lesson events.""" + STATUS_CHOICES = {"c": _("Created"), "e": _("Edited"), "d": _("Deleted")} + + status = models.CharField( + verbose_name=_("Status"), max_length=1, choices=STATUS_CHOICES, default="c" + ) + def value_description(self, request: HttpRequest | None = None) -> str: return LessonEvent.value_title(self.event) - def value_trigger(self, request: HttpRequest | None = None) -> Union[datetime, timedelta]: - # question: allow for generating multiple alarms for one event? + def value_trigger(self, request: HttpRequest | None = None) -> datetime | timedelta: if "fixed_time_relative" in get_site_preferences()["chronos__alarm_trigger_mode"]: return ( self.event.datetime_start @@ -1618,15 +1638,37 @@ class LessonEventAlarm(CalendarAlarm): ) elif "strictly_relative" in get_site_preferences()["chronos__alarm_trigger_mode"]: return get_site_preferences()["chronos__time_in_advance_alarms"] - + def value_notification_sender(self, request: HttpRequest | None = None) -> str: return _("Lesson notification") def value_notification_recipients(self, request: HttpRequest | None = None) -> [Person]: return self.event.all_teachers + def value_notification_title(self, request: HttpRequest | None = None) -> str: + return render_to_string( + "chronos/lesson_event_notification_title.txt", + { + "event": self.event, + "event_title": LessonEvent.value_title(self.event, request), + "status": self.STATUS_CHOICES[self.status].lower(), + }, + ) + def value_notification_description(self, request: HttpRequest | None = None) -> str: - return _("bliblablubb") + # FIXME: In some (?) cases, this is incomplete (e.g. room names are missing) + return render_to_string( + "chronos/lesson_event_notification_description.txt", + {"event": self.event, "status": self.STATUS_CHOICES[self.status].lower()}, + ) + + def value_notification_icon(self, request: HttpRequest | None = None) -> str: + return "calendar-remove-outline" if self.event.cancelled else "calendar-alert-outline" + + # TODO: how to get fitting link (from vue-router)? + # TODO: timetable overview page needs to be fitted so that CW is specified + # def value_notification_link(self, request: HttpRequest | None = None) -> str: + # raise NotImplementedError() class Meta: verbose_name = _("Lesson event alarm") diff --git a/aleksis/apps/chronos/templates/chronos/lesson_event_notification_description.txt b/aleksis/apps/chronos/templates/chronos/lesson_event_notification_description.txt new file mode 100644 index 0000000000000000000000000000000000000000..308e16778ad962851c9ba360e0200844a0208d81 --- /dev/null +++ b/aleksis/apps/chronos/templates/chronos/lesson_event_notification_description.txt @@ -0,0 +1 @@ +{% load i18n %}{% with rooms=event.room_names_with_amends comment=event.comment %}{% trans "Groups" %}: {{ event.group_names|default:"–" }}{% if event.subject or event.amends and event.amends.subject %} · {% trans "Subject" %}: {{ event.subject_name_with_amends }}{% endif %} · {% trans "Teachers" %}: {{ event.teacher_names_with_amends|default:"–" }}{% if rooms %} · {% trans "Rooms" %}: {{ rooms }}{% endif %}{% if comment %} · {{ comment }}{% endif %}{% endwith %} diff --git a/aleksis/apps/chronos/templates/chronos/lesson_event_notification_title.txt b/aleksis/apps/chronos/templates/chronos/lesson_event_notification_title.txt new file mode 100644 index 0000000000000000000000000000000000000000..298f4052ee8626fbf74eabfe3c506891981207f9 --- /dev/null +++ b/aleksis/apps/chronos/templates/chronos/lesson_event_notification_title.txt @@ -0,0 +1 @@ +{% load i18n %}{% trans "Lesson" %}{% if event.amends %} {% if event.cancelled %}{% trans "cancellation" %}{% else %}{% trans "substitution" %}{% endif %}{% endif %} {{ status }}: {{ event.datetime_start|date:"SHORT_DATETIME_FORMAT" }} - {{ event.datetime_end|date:"SHORT_DATETIME_FORMAT" }} · {{ event.group_names }}