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

Refactor build mechanism for timetables out from views and generalise it

parent b2a5dad4
No related branches found
No related tags found
1 merge request!47Advanced data in timetable views
......@@ -686,6 +686,14 @@ class Break(ExtensibleModel):
else self.before_period.weekday
)
@property
def after_period_number(self):
return (
self.after_period.period
if self.after_period
else self.before_period.period - 1
)
@property
def before_period_number(self):
return (
......@@ -694,6 +702,22 @@ class Break(ExtensibleModel):
else self.after_period.period + 1
)
@property
def time_start(self):
return self.after_period.time_end if self.after_period else None
@property
def time_end(self):
return self.before_period.time_start if self.before_period else None
@classmethod
def get_breaks_dict(cls) -> Dict[int, Tuple[datetime, datetime]]:
breaks = {}
for break_ in cls.objects.all():
breaks[break_.before_period_number] = break_
return breaks
class Meta:
ordering = ["after_period"]
indexes = [models.Index(fields=["after_period", "before_period"])]
......
......@@ -69,7 +69,8 @@
<select id="calendar-week-1">
{% for week in weeks %}
<option value="{{ week.week }}" {% if week == wanted_week %}
selected {% endif %}>{% trans "CW" %} {{ week.week }} ({{ week.0|date:"SHORT_DATE_FORMAT" }}–{{ week.6|date:"SHORT_DATE_FORMAT" }})
selected {% endif %}>{% trans "CW" %} {{ week.week }}
({{ week.0|date:"SHORT_DATE_FORMAT" }}–{{ week.6|date:"SHORT_DATE_FORMAT" }})
</option>
{% endfor %}
</select>
......@@ -79,7 +80,8 @@
<select id="calendar-week-2">
{% for week in weeks %}
<option value="{{ week.week }}" {% if week == wanted_week %}
selected {% endif %}>{% trans "CW" %} {{ week.week }} ({{ week.0|date:"j.n" }}–{{ week.6|date:"SHORT_DATE_FORMAT" }})
selected {% endif %}>{% trans "CW" %} {{ week.week }}
({{ week.0|date:"j.n" }}–{{ week.6|date:"SHORT_DATE_FORMAT" }})
</option>
{% endfor %}
</select>
......@@ -89,7 +91,8 @@
<select id="calendar-week-3">
{% for week in weeks %}
<option value="{{ week.week }}" {% if week == wanted_week %}
selected {% endif %}>{% trans "CW" %} {{ week.week }} ({{ week.0|date:"j.n" }}–{{ week.6|date:"j.n" }})
selected {% endif %}>{% trans "CW" %} {{ week.week }}
({{ week.0|date:"j.n" }}–{{ week.6|date:"j.n" }})
</option>
{% endfor %}
</select>
......@@ -159,17 +162,20 @@
</div>
{# Lessons #}
{% for period, lesson_periods_period in lesson_periods.items %}
{% for row in timetable %}
<div class="row">
<div class="col s2">
{% 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 %}
{% else %}
{% trans "Break" %}
{% endif %}
</div>
{% for weekday, lessons in lesson_periods_period.items %}
{% for col in row.cols %}
{# A lesson #}
<div class="col s2">
{% include "chronos/partials/lesson.html" with lessons=lessons %}
{% include "chronos/partials/lesson.html" with lessons=col %}
</div>
{% endfor %}
</div>
......
from collections import OrderedDict
from calendarweek import CalendarWeek
from aleksis.apps.chronos.models import LessonPeriod, TimePeriod, Break
def build_timetable(type_: str, pk: int, week: CalendarWeek):
needed_breaks = []
# Get matching lesson periods
lesson_periods = LessonPeriod.objects.in_week(week).filter_from_type(type_, pk)
# Sort lesson periods in a dict
lesson_periods_per_period = {}
for lesson_period in lesson_periods:
period = lesson_period.period.period
weekday = lesson_period.period.weekday
if period not in lesson_periods_per_period:
lesson_periods_per_period[period] = {}
if weekday not in lesson_periods_per_period[period]:
lesson_periods_per_period[period][weekday] = []
lesson_periods_per_period[period][weekday].append(lesson_period)
# Get ordered breaks
breaks = OrderedDict(sorted(Break.get_breaks_dict().items()))
rows = []
for period, break_ in breaks.items(): # period is period after break
# Break
if period in needed_breaks:
row = {
"type": "break",
"after_period": break_.after_period_number,
"before_period": break_.before_period_number,
"time_start": break_.time_start,
"time_end": break_.time_end,
}
cols = []
# ...
row["cols"] = cols
rows.append(row)
# Lesson
if period <= TimePeriod.period_max:
row = {
"type": "period",
"period": period,
"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):
col = []
if row["type"] == "period":
# 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
rows.append(row)
return rows
......@@ -18,6 +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.js import date_unix
from .util.date import CalendarWeek, get_weeks_for_year
from aleksis.core.util.core_helpers import has_person
......@@ -120,40 +121,11 @@ def timetable(
# TODO: On not used days show next week
wanted_week = CalendarWeek()
lesson_periods = LessonPeriod.objects.in_week(wanted_week)
lesson_periods = lesson_periods.filter_from_type(type_, pk)
# Regroup lesson periods per weekday
per_period = {}
for lesson_period in lesson_periods:
added = False
if lesson_period.period.period in per_period:
if lesson_period.period.weekday in per_period[lesson_period.period.period]:
per_period[lesson_period.period.period][
lesson_period.period.weekday
].append(lesson_period)
added = True
if not added:
per_period.setdefault(lesson_period.period.period, {})[
lesson_period.period.weekday
] = [lesson_period]
# Fill in empty lessons
for period_num in range(TimePeriod.period_min, TimePeriod.period_max + 1):
# Fill in empty weekdays
if period_num not in per_period.keys():
per_period[period_num] = {}
# Fill in empty lessons on this workday
for weekday_num in range(TimePeriod.weekday_min, TimePeriod.weekday_max + 1):
if weekday_num not in per_period[period_num].keys():
per_period[period_num][weekday_num] = []
# Order this weekday by periods
per_period[period_num] = OrderedDict(sorted(per_period[period_num].items()))
context["lesson_periods"] = OrderedDict(sorted(per_period.items()))
# Build timetable
timetable = build_timetable(type_, pk, wanted_week)
context["timetable"] = timetable
# Add time periods
context["periods"] = TimePeriod.get_times_dict()
# Build lists with weekdays and corresponding dates (long and short variant)
......
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