From b5c52a83d4c4e2b654c3b69499c25e7655d11572 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Thu, 9 Apr 2020 17:59:03 +0200 Subject: [PATCH] Create new build mechanism for substitution lists (in order to implement events etc. later) - Use new template for cancellation badge (badge.html) - Show more details like comment or specific cancellation types - Fix some rules in substitution templates - Fix cycle mechanism in substitutions_print.html --- aleksis/apps/chronos/models.py | 16 +++- .../templates/chronos/partials/lesson.html | 3 +- .../chronos/partials/subs/badge.html | 7 ++ .../templates/chronos/partials/subs/room.html | 79 ++++++++----------- .../chronos/partials/subs/subject.html | 46 +++++------ .../chronos/partials/subs/teachers.html | 27 +++---- .../templates/chronos/substitutions.html | 31 ++++---- .../chronos/substitutions_print.html | 35 ++++---- aleksis/apps/chronos/util/build.py | 28 ++++++- aleksis/apps/chronos/views.py | 6 +- 10 files changed, 155 insertions(+), 123 deletions(-) create mode 100644 aleksis/apps/chronos/templates/chronos/partials/subs/badge.html diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py index ebb3fb74..194b5fc9 100644 --- a/aleksis/apps/chronos/models.py +++ b/aleksis/apps/chronos/models.py @@ -4,6 +4,7 @@ from collections import OrderedDict from datetime import date, datetime, timedelta, time from typing import Dict, Optional, Tuple, Union +from constance import config from django.core import validators from django.core.exceptions import ValidationError from django.db import models @@ -442,6 +443,18 @@ class Lesson(ExtensibleModel): def group_names(self, sep: Optional[str] = ", ") -> str: return sep.join([group.short_name for group in self.groups.all()]) + @property + def groups_to_show(self) -> models.QuerySet: + groups = self.groups.all() + if groups.count() == 1 and groups[0].parent_groups.all() and config.CHRONOS_USE_PARENT_GROUPS: + return groups[0].parent_groups.all() + else: + return groups + + @property + def groups_to_show_names(self, sep: Optional[str] = ", ") -> str: + return sep.join([group.short_name for group in self.groups_to_show]) + def get_calendar_week(self, week: int): year = self.date_start.year if week < int(self.date_start.strftime("%V")): @@ -485,9 +498,10 @@ class LessonSubstitution(ExtensibleModel): @property def type_(self): - # TODO: Add cases events and supervisions if self.cancelled: return "cancellation" + elif self.cancelled_for_teachers: + return "cancellation_for_teachers" else: return "substitution" diff --git a/aleksis/apps/chronos/templates/chronos/partials/lesson.html b/aleksis/apps/chronos/templates/chronos/partials/lesson.html index 2c5bcd7b..66da0b62 100644 --- a/aleksis/apps/chronos/templates/chronos/partials/lesson.html +++ b/aleksis/apps/chronos/templates/chronos/partials/lesson.html @@ -34,8 +34,7 @@ {% endif %} {# Badge #} - <span class="badge new green darken-2">{% if sub.cancelled_for_teachers %} - {% trans "Cancelled for teachers" %}{% else %}{% trans "Cancelled" %}{% endif %}</span> + {% include "chronos/partials/subs/badge.html" with sub=sub %} {% else %} {# Display sub #} diff --git a/aleksis/apps/chronos/templates/chronos/partials/subs/badge.html b/aleksis/apps/chronos/templates/chronos/partials/subs/badge.html new file mode 100644 index 00000000..c04c9dd3 --- /dev/null +++ b/aleksis/apps/chronos/templates/chronos/partials/subs/badge.html @@ -0,0 +1,7 @@ +{% load i18n %} + +{% if sub.cancelled %} + <span class="badge new green">{% trans "Cancelled" %}</span> +{% elif item.el.cancelled_for_teachers %} + <span class="badge new green">{% trans "Cancelled for teachers" %}</span> +{% endif %} diff --git a/aleksis/apps/chronos/templates/chronos/partials/subs/room.html b/aleksis/apps/chronos/templates/chronos/partials/subs/room.html index cf637b92..e7535af9 100644 --- a/aleksis/apps/chronos/templates/chronos/partials/subs/room.html +++ b/aleksis/apps/chronos/templates/chronos/partials/subs/room.html @@ -1,47 +1,36 @@ -{% if not sub.is_event %} - {% if sub.sub.type == 3 %} - {# Supervisement #} - {{ sub.sub.corridor.name }} - {% elif sub.sub.type == 1 or sub.sub.type == 2 %} - {# Canceled lesson: no room #} - {% elif sub.room and sub.lesson_period.room %} - {# New and old room available #} - <span class="tooltipped" data-position="bottom" - data-tooltip="{{ sub.lesson_period.room.name }} → {{ sub.lesson_period.room.name }}"> - <a href="{% url "timetable" "room" sub.lesson_period.room.pk %}"> - <s>{{ sub.lesson_period.room.short_name }}</s> - </a> - → - <a href="{% url "timetable" "room" sub.room.pk %}"> - <strong>{{ sub.room.short_name }}</strong> - </a> - </span> - {% elif sub.room and not sub.lesson_period.room %} - {# Only new room available #} - <span class="tooltipped" data-position="bottom" - data-tooltip="{{ sub.room.name }}"> - <a href="{% url "timetable" "room" sub.room.pk %}"> - {{ sub.room.short_name }} - </a> - </span> - {% elif not sub.room and not sub.lesson_period.room %} - {# Nothing to view #} - {% else %} - {# Only old room available #} - <span class="tooltipped" data-position="bottom" - data-tooltip="{{ sub.lesson_period.room.name }}"> - <a href="{% url "timetable" "room" sub.lesson_period.room.pk %}"> - {{ sub.lesson_period.room.short_name }} - </a> - </span> - {% endif %} +{% if sub.cancelled or sub.cancelled_for_teachers %} + {# Canceled lesson: no room #} +{% elif sub.room and sub.lesson_period.room %} + {# New and old room available #} + <span class="tooltipped" data-position="bottom" + data-tooltip="{{ sub.lesson_period.room.name }} → {{ sub.lesson_period.room.name }}" + title="{{ sub.lesson_period.room.name }} → {{ sub.lesson_period.room.name }}"> + <a href="{% url "timetable" "room" sub.lesson_period.room.pk %}"> + <s>{{ sub.lesson_period.room.short_name }}</s> + </a> + → + <a href="{% url "timetable" "room" sub.room.pk %}"> + <strong>{{ sub.room.short_name }}</strong> + </a> + </span> +{% elif sub.room and not sub.lesson_period.room %} + {# Only new room available #} + <span class="tooltipped" data-position="bottom" + data-tooltip="{{ sub.room.name }}" + title="{{ sub.room.name }}"> + <a href="{% url "timetable" "room" sub.room.pk %}"> + {{ sub.room.short_name }} + </a> + </span> +{% elif not sub.room and not sub.lesson_period.room %} + {# Nothing to view #} {% else %} - {% for room in sub.rooms %} - <span class="tooltipped" data-position="bottom" - data-tooltip="{{ room.name }}"> - <a href="{% url "timetable_smart_plan" "room" room.id %}"> - <strong>{{ room.short_name }}{% if not forloop.last %},{% endif %}</strong> - </a> - </span> - {% endfor %} + {# Only old room available #} + <span class="tooltipped" data-position="bottom" + data-tooltip="{{ sub.lesson_period.room.name }}" + title="{{ sub.lesson_period.room.name }}"> + <a href="{% url "timetable" "room" sub.lesson_period.room.pk %}"> + {{ sub.lesson_period.room.short_name }} + </a> + </span> {% endif %} diff --git a/aleksis/apps/chronos/templates/chronos/partials/subs/subject.html b/aleksis/apps/chronos/templates/chronos/partials/subs/subject.html index 6fe8eb5a..2e61d415 100644 --- a/aleksis/apps/chronos/templates/chronos/partials/subs/subject.html +++ b/aleksis/apps/chronos/templates/chronos/partials/subs/subject.html @@ -1,28 +1,24 @@ {% load i18n %} -{% if not sub.sub.is_event %} - {% if sub.sub.type == 3 %} - <strong>{% trans "Supervision" %}</strong> - {% elif not sub.lesson_period.lesson.subject and not sub.subject %} - {% elif sub.sub.type == 1 or sub.sub.type == 2 %} - <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}"> - <s>{{ sub.lesson_period.lesson.subject.abbrev }}</s> - </span> - {% elif sub.subject and sub.lesson_period.lesson.subject %} - <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}"> - <s>{{ sub.lesson_period.lesson.subject.abbrev }}</s> - </span> - → - <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.subject.name }}"> - <strong>{{ sub.subject.abbrev }}</strong> - </span> - {% elif sub.subject and not sub.lesson_period.lesson.subject %} - <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.subject.name }}"> - <strong>{{ sub.subject.abbrev }}</strong> - </span> - {% else %} - <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}"> - <strong>{{ sub.lesson_period.lesson.subject.abbrev }}</strong> - </span> - {% endif %} +{% if not sub.lesson_period.lesson.subject and not sub.subject %} +{% elif sub.cancelled or sub.cancelled_for_teachers %} + <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}"> + <s>{{ sub.lesson_period.lesson.subject.abbrev }}</s> + </span> +{% elif sub.subject and sub.lesson_period.lesson.subject %} + <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}"> + <s>{{ sub.lesson_period.lesson.subject.abbrev }}</s> + </span> + → + <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.subject.name }}"> + <strong>{{ sub.subject.abbrev }}</strong> + </span> +{% elif sub.subject and not sub.lesson_period.lesson.subject %} + <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.subject.name }}"> + <strong>{{ sub.subject.abbrev }}</strong> + </span> +{% else %} + <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}"> + <strong>{{ sub.lesson_period.lesson.subject.abbrev }}</strong> + </span> {% endif %} diff --git a/aleksis/apps/chronos/templates/chronos/partials/subs/teachers.html b/aleksis/apps/chronos/templates/chronos/partials/subs/teachers.html index ec17d8b8..69002c5d 100644 --- a/aleksis/apps/chronos/templates/chronos/partials/subs/teachers.html +++ b/aleksis/apps/chronos/templates/chronos/partials/subs/teachers.html @@ -1,19 +1,16 @@ -{% if not sub.is_event %} - {% if sub.sub.type == 1 and sub.lesson_period.lesson.teachers.all %} +{% if sub.cancelled and sub.lesson_period.lesson.teachers.all %} + {% include "chronos/partials/teachers.html" with teachers=sub.lesson_period.lesson.teachers.all %} +{% elif sub.teachers.all and sub.lesson_period.lesson.teachers.all %} + <s> {% include "chronos/partials/teachers.html" with teachers=sub.lesson_period.lesson.teachers.all %} - {% elif sub.teachers.all and sub.lesson_period.lesson.teachers.all %} - <s> - {% include "chronos/partials/teachers.html" with teachers=sub.lesson_period.lesson.teachers.all %} - </s> - → - <strong> - {% include "chronos/partials/teachers.html" with teachers=sub.teachers.all %} - </strong> - {% elif sub.teachers.all and not sub.lesson_period.lesson.teachers.all %} + </s> + → + <strong> {% include "chronos/partials/teachers.html" with teachers=sub.teachers.all %} - {% elif sub.lesson_period.lesson.teachers.all %} - {% include "chronos/partials/teachers.html" with teachers=sub.lesson_period.lesson.teachers.all %} - {% endif %} -{% else %} + </strong> +{% elif sub.teachers.all and not sub.lesson_period.lesson.teachers.all %} {% include "chronos/partials/teachers.html" with teachers=sub.teachers.all %} +{% elif sub.lesson_period.lesson.teachers.all %} + {% include "chronos/partials/teachers.html" with teachers=sub.lesson_period.lesson.teachers.all %} {% endif %} + diff --git a/aleksis/apps/chronos/templates/chronos/substitutions.html b/aleksis/apps/chronos/templates/chronos/substitutions.html index febc6aeb..931eac1d 100644 --- a/aleksis/apps/chronos/templates/chronos/substitutions.html +++ b/aleksis/apps/chronos/templates/chronos/substitutions.html @@ -57,37 +57,38 @@ </p> </td> {% endif %} - {% for sub in substitutions %} - <tr class="{% if sub.type_ == "cancellation" %}green-text{% else %}black-text{% endif %}"> + {% for item in substitutions %} + <tr class=" + {% if item.type == "substitution" %} + {% if item.el.cancelled or item.el.cancelled_for_teachers %}green-text{% else %}black-text{% endif %} + {% endif %} + "> {# TODO: Extend support for blue and purple (supervisions and events) #} <td> - {% include "chronos/partials/groups.html" with groups=sub.lesson_period.lesson.groups.all %} + {% include "chronos/partials/groups.html" with groups=item.el.lesson_period.lesson.groups.all %} </td> <td> <strong> - {{ sub.lesson_period.period.period }}. + {{ item.el.lesson_period.period.period }}. </strong> </td> <td> - {% include "chronos/partials/subs/teachers.html" %} + {% include "chronos/partials/subs/teachers.html" with sub=item.el %} </td> <td> - {% include "chronos/partials/subs/subject.html" %} + {% include "chronos/partials/subs/subject.html" with sub=item.el %} </td> <td> - {% include "chronos/partials/subs/room.html" %} + {% include "chronos/partials/subs/room.html" with sub=item.el %} </td> <td> - {% if sub.cancelled %} - {# TODO: Support other cases#} - <span class="badge new green hide-on-med-and-up">{% trans "Cancelled" %}</span> - {% endif %} - {# <em>{{ sub.text|default:"" }}</em>#} + <span class="hide-on-med-and-up"> + {% include "chronos/partials/subs/badge.html" with sub=item.el %} + </span> + <em>{{ sub.comment|default:"" }}</em> </td> <td class="hide-on-small-and-down"> - {% if sub.cancelled %} - <span class="badge new green darken-2">{% trans "Cancelled" %}</span> - {% endif %} + {% include "chronos/partials/subs/badge.html" with sub=item.el %} </td> </tr> {% endfor %} diff --git a/aleksis/apps/chronos/templates/chronos/substitutions_print.html b/aleksis/apps/chronos/templates/chronos/substitutions_print.html index 400124f2..1692efe7 100644 --- a/aleksis/apps/chronos/templates/chronos/substitutions_print.html +++ b/aleksis/apps/chronos/templates/chronos/substitutions_print.html @@ -46,38 +46,39 @@ {% endif %} <tbody> - {% for sub in c.substitutions %} - <tr class="{% if sub.type_ == "cancellation" %}green-text{% else %}black-text{% endif %} "> + {% for item in c.substitutions %} + {% ifchanged item.el.lesson_period.lesson.groups_to_show_names %} + </tbody> + <tbody class="{% cycle "striped" "not-striped" %}"> + {% endifchanged %} + + <tr class=" + {% if item.type == "substitution" %} + {% if item.el.cancelled or item.el.cancelled_for_teachers %}green-text{% else %}black-text{% endif %} + {% endif %} + "> <td> - {% include "chronos/partials/groups.html" with groups=sub.lesson_period.lesson.groups.all %} + {% include "chronos/partials/groups.html" with groups=item.el.lesson_period.lesson.groups.all %} </td> <td> <strong> - {{ sub.lesson_period.period.period }}. + {{ item.el.lesson_period.period.period }}. </strong> </td> <td> - {% include "chronos/partials/subs/teachers.html" %} + {% include "chronos/partials/subs/teachers.html" with sub=item.el %} </td> <td> - {% include "chronos/partials/subs/subject.html" %} + {% include "chronos/partials/subs/subject.html" with sub=item.el %} </td> <td> - {% include "chronos/partials/subs/room.html" %} + {% include "chronos/partials/subs/room.html" with sub=item.el %} </td> <td> - {% if sub.cancelled %} - {# TODO: Support other cases#} - <span class="badge new green">{% trans "Cancelled" %}</span> - {% endif %} - {# <em>{{ sub.text|default:"" }}</em>#} + {% include "chronos/partials/subs/badge.html" with sub=item.el %} + <em>{{ sub.comment|default:"" }}</em> </td> </tr> - - {% ifchanged sub.lesson_period.lesson.groups %} - </tbody> - <tbody class="{% cycle "not-striped" "striped" %}"> - {% endifchanged %} {% endfor %} </tbody> </table> diff --git a/aleksis/apps/chronos/util/build.py b/aleksis/apps/chronos/util/build.py index b45b8510..57cd4707 100644 --- a/aleksis/apps/chronos/util/build.py +++ b/aleksis/apps/chronos/util/build.py @@ -1,6 +1,6 @@ from collections import OrderedDict from datetime import date -from typing import Union +from typing import Union, List from calendarweek import CalendarWeek from django.apps import apps @@ -11,6 +11,7 @@ LessonPeriod = apps.get_model("chronos", "LessonPeriod") TimePeriod = apps.get_model("chronos", "TimePeriod") Break = apps.get_model("chronos", "Break") Supervision = apps.get_model("chronos", "Supervision") +LessonSubstitution = apps.get_model("chronos", "LessonSubstitution") def build_timetable( @@ -155,3 +156,28 @@ def build_timetable( rows.append(row) return rows + + +def build_substitutions_list(wanted_day: date) -> List[dict]: + rows = [] + + subs = LessonSubstitution.objects.on_day(wanted_day).order_by( + "lesson_period__lesson__groups", "lesson_period__period" + ) + + for sub in subs: + if not sub.cancelled_for_teachers: + sort_a = sub.lesson_period.lesson.group_names + else: + sort_a = "Z.{}".format(sub.lesson_period.lesson.teacher_names) + + row = { + "type": "substitution", + "sort_a": sort_a, + "sort_b": "{}".format(sub.lesson_period.period.period), + "el": sub, + } + + rows.append(row) + + return rows diff --git a/aleksis/apps/chronos/views.py b/aleksis/apps/chronos/views.py index de931825..b59262ac 100644 --- a/aleksis/apps/chronos/views.py +++ b/aleksis/apps/chronos/views.py @@ -18,7 +18,7 @@ from aleksis.core.util import messages from .forms import LessonSubstitutionForm from .models import LessonPeriod, LessonSubstitution, TimePeriod, Room from .tables import LessonsTable -from .util.build import build_timetable +from .util.build import build_timetable, build_substitutions_list from .util.js import date_unix from .util.date import CalendarWeek, get_weeks_for_year from aleksis.core.util.core_helpers import has_person @@ -295,12 +295,14 @@ def substitutions( day_contexts = {wanted_day: {"day": wanted_day}} for day in day_contexts: - subs = LessonSubstitution.objects.on_day(day).order_by("lesson_period__lesson__groups", "lesson_period__period") + subs = build_substitutions_list(day) day_contexts[day]["substitutions"] = subs day_contexts[day]["announcements"] = Announcement.for_timetables().on_date(day).filter(show_in_timetables=True) if config.CHRONOS_SUBSTITUTIONS_SHOW_HEADER_BOX: + subs = LessonSubstitution.objects.on_day(day).order_by("lesson_period__lesson__groups", + "lesson_period__period") day_contexts[day]["affected_teachers"] = subs.affected_teachers() day_contexts[day]["affected_groups"] = subs.affected_groups() -- GitLab