Skip to content
Snippets Groups Projects
Verified Commit 75088d27 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Use new build mechanism for timetables for my timetable and dashboard timetable widget, too

- Refactor build_timetable to return data for a single day
- Use lazy model imports
- Refactor lessons_col.html
parent e53b68e4
No related branches found
No related tags found
1 merge request!47Advanced data in timetable views
...@@ -569,21 +569,24 @@ class TimetableWidget(DashboardWidget): ...@@ -569,21 +569,24 @@ class TimetableWidget(DashboardWidget):
template = "chronos/widget.html" template = "chronos/widget.html"
def get_context(self): def get_context(self):
from aleksis.apps.chronos.util.build import build_timetable # noqa
request = get_request() request = get_request()
context = {"has_plan": True} context = {"has_plan": True}
wanted_day = TimePeriod.get_next_relevant_day(timezone.now().date(), datetime.now().time()) wanted_day = TimePeriod.get_next_relevant_day(timezone.now().date(), datetime.now().time())
if has_person(request.user): if has_person(request.user):
person = request.user.person person = request.user.person
lesson_periods = LessonPeriod.objects.daily_lessons_for_person(person, wanted_day)
type_ = person.timetable_type type_ = person.timetable_type
# Build timetable
timetable = build_timetable("person", person, wanted_day)
if type_ is None: if type_ is None:
# If no student or teacher, redirect to all timetables # If no student or teacher, redirect to all timetables
context["has_plan"] = False context["has_plan"] = False
else: else:
context["lesson_periods"] = lesson_periods.per_period_one_day() context["timetable"] = timetable
context["type"] = type_ context["type"] = type_
context["day"] = wanted_day context["day"] = wanted_day
context["periods"] = TimePeriod.get_times_dict() context["periods"] = TimePeriod.get_times_dict()
...@@ -738,6 +741,12 @@ class SupervisionQuerySet(models.QuerySet): ...@@ -738,6 +741,12 @@ class SupervisionQuerySet(models.QuerySet):
return self.annotate(_week=models.Value(week_num, models.IntegerField())) return self.annotate(_week=models.Value(week_num, models.IntegerField()))
def filter_by_weekday(self, weekday: int):
self.filter(
Q(break_item__before_period__weekday=weekday)
| Q(break_item__after_period__weekday=weekday)
)
class Supervision(ExtensibleModel): class Supervision(ExtensibleModel):
objects = models.Manager.from_queryset(SupervisionQuerySet)() objects = models.Manager.from_queryset(SupervisionQuerySet)()
......
{% for period, lessons in lesson_periods.items %} {% for row in timetable %}
<div class="row"> <div class="row">
<div class="col s4"> <div class="col s4">
{% include "chronos/partials/period_time.html" with period=period periods=periods %} {% if row.type == "period" %}
{% include "chronos/partials/period_time.html" with period=row.period periods=periods %}
{% endif %}
</div> </div>
<div class="col s8"> <div class="col s8">
{% include "chronos/partials/elements.html" with elements=lessons %} {% if row.type == "period" %}
{% include "chronos/partials/elements.html" with elements=row.col %}
{% else %}
{% include "chronos/partials/supervision.html" with supervision=row.col %}
{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
from collections import OrderedDict from collections import OrderedDict
from datetime import date
from typing import Union
from calendarweek import CalendarWeek from calendarweek import CalendarWeek
from django.apps import apps
from aleksis.apps.chronos.models import LessonPeriod, TimePeriod, Break, Supervision from aleksis.core.models import Person
LessonPeriod = apps.get_model("chronos", "LessonPeriod")
TimePeriod = apps.get_model("chronos", "TimePeriod")
Break = apps.get_model("chronos", "Break")
Supervision = apps.get_model("chronos", "Supervision")
def build_timetable(type_: str, pk: int, week: CalendarWeek):
def build_timetable(
type_: str, obj: Union[int, Person], date_ref: Union[CalendarWeek, date]
):
needed_breaks = [] needed_breaks = []
if not isinstance(obj, int):
pk = obj.pk
else:
pk = obj
is_person = False
if type_ == "person":
is_person = True
type_ = obj.timetable_type
# Get matching lesson periods # Get matching lesson periods
lesson_periods = LessonPeriod.objects.in_week(week).filter_from_type(type_, pk) if is_person:
lesson_periods = LessonPeriod.objects.daily_lessons_for_person(obj, date_ref)
else:
lesson_periods = LessonPeriod.objects.in_week(date_ref).filter_from_type(
type_, obj
)
# Sort lesson periods in a dict # Sort lesson periods in a dict
lesson_periods_per_period = {} lesson_periods_per_period = {}
...@@ -18,16 +43,26 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek): ...@@ -18,16 +43,26 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek):
weekday = lesson_period.period.weekday weekday = lesson_period.period.weekday
if period not in lesson_periods_per_period: if period not in lesson_periods_per_period:
lesson_periods_per_period[period] = {} lesson_periods_per_period[period] = [] if is_person else {}
if weekday not in lesson_periods_per_period[period]: if not is_person and weekday not in lesson_periods_per_period[period]:
lesson_periods_per_period[period][weekday] = [] lesson_periods_per_period[period][weekday] = []
lesson_periods_per_period[period][weekday].append(lesson_period) if is_person:
lesson_periods_per_period[period].append(lesson_period)
else:
lesson_periods_per_period[period][weekday].append(lesson_period)
if type_ == "teacher": if type_ == "teacher":
# Get matching supervisions # Get matching supervisions
supervisions = Supervision.objects.filter(teacher=pk).annotate_week(week) if is_person:
week = CalendarWeek.from_date(date_ref)
else:
week = date_ref
supervisions = Supervision.objects.filter(teacher=obj).annotate_week(week)
if is_person:
supervisions.filter_by_weekday(date_ref.weekday())
supervisions_per_period_after = {} supervisions_per_period_after = {}
for supervision in supervisions: for supervision in supervisions:
...@@ -38,10 +73,16 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek): ...@@ -38,10 +73,16 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek):
if period_after_break not in needed_breaks: if period_after_break not in needed_breaks:
needed_breaks.append(period_after_break) needed_breaks.append(period_after_break)
if period_after_break not in supervisions_per_period_after: if (
not is_person
and period_after_break not in supervisions_per_period_after
):
supervisions_per_period_after[period_after_break] = {} supervisions_per_period_after[period_after_break] = {}
supervisions_per_period_after[period_after_break][weekday] = supervision if is_person:
supervisions_per_period_after[period_after_break] = supervision
else:
supervisions_per_period_after[period_after_break][weekday] = supervision
# Get ordered breaks # Get ordered breaks
breaks = OrderedDict(sorted(Break.get_breaks_dict().items())) breaks = OrderedDict(sorted(Break.get_breaks_dict().items()))
...@@ -58,16 +99,24 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek): ...@@ -58,16 +99,24 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek):
"time_end": break_.time_end, "time_end": break_.time_end,
} }
cols = [] if not is_person:
cols = []
for weekday in range(
TimePeriod.weekday_min, TimePeriod.weekday_max + 1
):
col = None
if period in supervisions_per_period_after:
if weekday in supervisions_per_period_after[period]:
col = supervisions_per_period_after[period][weekday]
cols.append(col)
for weekday in range(TimePeriod.weekday_min, TimePeriod.weekday_max + 1): row["cols"] = cols
else:
col = None col = None
if period in supervisions_per_period_after: if period in supervisions_per_period_after:
if weekday in supervisions_per_period_after[period]: col = supervisions_per_period_after[period]
col = supervisions_per_period_after[period][weekday] row["col"] = col
cols.append(col)
row["cols"] = cols
rows.append(row) rows.append(row)
# Lesson # Lesson
...@@ -78,18 +127,31 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek): ...@@ -78,18 +127,31 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek):
"time_start": break_.before_period.time_start, "time_start": break_.before_period.time_start,
"time_end": break_.before_period.time_end, "time_end": break_.before_period.time_end,
} }
cols = []
for weekday in range(TimePeriod.weekday_min, TimePeriod.weekday_max + 1): if not is_person:
cols = []
for weekday in range(
TimePeriod.weekday_min, TimePeriod.weekday_max + 1
):
col = []
# Add lesson periods
if period in lesson_periods_per_period:
if weekday in lesson_periods_per_period[period]:
col += lesson_periods_per_period[period][weekday]
cols.append(col)
row["cols"] = cols
else:
col = [] col = []
# Add lesson periods # Add lesson periods
if period in lesson_periods_per_period: if period in lesson_periods_per_period:
if weekday in lesson_periods_per_period[period]: col += lesson_periods_per_period[period]
col += lesson_periods_per_period[period][weekday]
cols.append(col) row["col"] = col
row["cols"] = cols
rows.append(row) rows.append(row)
return rows return rows
...@@ -66,17 +66,18 @@ def my_timetable( ...@@ -66,17 +66,18 @@ def my_timetable(
if has_person(request.user): if has_person(request.user):
person = request.user.person person = request.user.person
type_ = person.timetable_type
lesson_periods = LessonPeriod.objects.daily_lessons_for_person(person, wanted_day) # Build timetable
timetable = build_timetable("person", person, wanted_day)
if lesson_periods is None: if type_ is None:
# If no student or teacher, redirect to all timetables # If no student or teacher, redirect to all timetables
return redirect("all_timetables") return redirect("all_timetables")
type_ = person.timetable_type
super_el = person.timetable_object super_el = person.timetable_object
context["lesson_periods"] = lesson_periods.per_period_one_day() context["timetable"] = timetable
context["super"] = {"type": type_, "el": super_el} context["super"] = {"type": type_, "el": super_el}
context["type"] = type_ context["type"] = type_
context["day"] = wanted_day context["day"] = wanted_day
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment