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):
template = "chronos/widget.html"
def get_context(self):
from aleksis.apps.chronos.util.build import build_timetable # noqa
request = get_request()
context = {"has_plan": True}
wanted_day = TimePeriod.get_next_relevant_day(timezone.now().date(), datetime.now().time())
if has_person(request.user):
person = request.user.person
lesson_periods = LessonPeriod.objects.daily_lessons_for_person(person, wanted_day)
type_ = person.timetable_type
# Build timetable
timetable = build_timetable("person", person, wanted_day)
if type_ is None:
# If no student or teacher, redirect to all timetables
context["has_plan"] = False
else:
context["lesson_periods"] = lesson_periods.per_period_one_day()
context["timetable"] = timetable
context["type"] = type_
context["day"] = wanted_day
context["periods"] = TimePeriod.get_times_dict()
......@@ -738,6 +741,12 @@ class SupervisionQuerySet(models.QuerySet):
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):
objects = models.Manager.from_queryset(SupervisionQuerySet)()
......
{% for period, lessons in lesson_periods.items %}
{% for row in timetable %}
<div class="row">
<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 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>
{% endfor %}
from collections import OrderedDict
from datetime import date
from typing import Union
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 = []
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
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
lesson_periods_per_period = {}
......@@ -18,16 +43,26 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek):
weekday = lesson_period.period.weekday
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].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":
# 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 = {}
for supervision in supervisions:
......@@ -38,10 +73,16 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek):
if period_after_break not in needed_breaks:
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][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
breaks = OrderedDict(sorted(Break.get_breaks_dict().items()))
......@@ -58,16 +99,24 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek):
"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
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)
row["cols"] = cols
col = supervisions_per_period_after[period]
row["col"] = col
rows.append(row)
# Lesson
......@@ -78,18 +127,31 @@ def build_timetable(type_: str, pk: int, week: CalendarWeek):
"time_start": break_.before_period.time_start,
"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 = []
# 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]
col += lesson_periods_per_period[period]
cols.append(col)
row["col"] = col
row["cols"] = cols
rows.append(row)
return rows
......@@ -66,17 +66,18 @@ def my_timetable(
if has_person(request.user):
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
return redirect("all_timetables")
type_ = person.timetable_type
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["type"] = type_
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