Skip to content
Snippets Groups Projects
Unverified Commit 379b37be authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Merge branch 'master' of edugit.org:Teckids/BiscuIT/BiscuIT-App-Chronos

parents 8e422355 3554008c
No related branches found
No related tags found
No related merge requests found
from django import forms
from django.db.models import Count
from django.utils.translation import ugettext_lazy as _
from biscuit.core.models import Person, Group
from .models import Room
class SelectForm(forms.Form):
group = forms.ModelChoiceField(
queryset=Group.objects.annotate(lessons_count=Count('lessons')).filter(lessons_count__gt=0),
label=_('Group'), required=False)
teacher = forms.ModelChoiceField(
queryset=Person.objects.annotate(lessons_count=Count('lessons')).filter(lessons_count__gt=0),
label=_('Teacher'), required=False)
room = forms.ModelChoiceField(
queryset=Room.objects.annotate(lessons_count=Count('lesson_periods')).filter(lessons_count__gt=0),
label=_('Room'), required=False)
......@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-08-18 21:36+0200\n"
"PO-Revision-Date: 2019-08-17 13:37+0200\n"
"POT-Creation-Date: 2019-08-24 13:55+0200\n"
"PO-Revision-Date: 2019-08-24 13:55+0200\n"
"Last-Translator: Tom Teichler <tom.teichler@teckids.org>\n"
"Language-Team: \n"
"Language: de_DE\n"
......@@ -21,6 +21,18 @@ msgstr ""
msgid "BiscuIT - Chronos (Timetables)"
msgstr "BiscuIT - Chronos (Stundenpläne)"
#: forms.py:13
msgid "Group"
msgstr "Gruppe"
#: forms.py:16
msgid "Teacher"
msgstr "Lehrer"
#: forms.py:19
msgid "Room"
msgstr "Raum"
#: menus.py:6
msgid "Timetables"
msgstr "Stundenpläne"
......@@ -29,97 +41,86 @@ msgstr "Stundenpläne"
msgid "Timetable"
msgstr "Stundenplan"
#: models.py:8
#: models.py:15
msgid "Sunday"
msgstr "Sonntag"
#: models.py:9
#: models.py:16
msgid "Monday"
msgstr "Montag"
#: models.py:10
#: models.py:17
msgid "Tuesday"
msgstr "Dienstag"
#: models.py:11
#: models.py:18
msgid "Wednesday"
msgstr "Mittwoch"
#: models.py:12
#: models.py:19
msgid "Thursday"
msgstr "Donnerstag"
#: models.py:13
#: models.py:20
msgid "Friday"
msgstr "Freitag"
#: models.py:14
#: models.py:21
msgid "Saturday"
msgstr "Samstag"
#: models.py:18
#: models.py:25
msgid "Week day"
msgstr "Wochentag"
#: models.py:20
#: models.py:27
msgid "Number of period"
msgstr "Nummer der Stunde"
#: models.py:22
#: models.py:29
msgid "Time the period starts"
msgstr "Anfangszeit der Stunde"
#: models.py:23
#: models.py:30
msgid "Time the period ends"
msgstr "Endzeit der Stunde"
#: models.py:42
#: models.py:49
msgid "Abbreviation of subject in timetable"
msgstr "Kürzel des Faches im Stundenplan"
#: models.py:44
#: models.py:51
msgid "Long name of subject"
msgstr "Name des Faches"
#: models.py:46
#: models.py:53
msgid "Foreground colour in timetable"
msgstr "Vordergrundfarbe im Stundenplan"
#: models.py:48
#: models.py:55
msgid "Background colour in timetable"
msgstr "Hintergrundfarbe im Stundenplan"
#: models.py:57
#: models.py:64
msgid "Short name, e.g. room number"
msgstr "Kurzer Name, z.B. Raumnummer"
#: models.py:58
#: models.py:65
msgid "Long name"
msgstr "Langer Name"
#: models.py:73
#: models.py:81
msgid "Effective start date of lesson"
msgstr "Effektives Startdatum des Unterrichts"
#: models.py:75
#: models.py:83
msgid "Effective end date of lesson"
msgstr "Effektives Enddatum des Unterrichts"
#: templates/chronos/tt_week.html:24
#: models.py:86
msgid "Week"
msgstr "Kalenderwoche"
#: templates/chronos/tt_week.html:28
msgid "Times"
msgstr "Zeiten"
#: views.py:24
#, python-format
msgid "Group: %s"
msgstr "Gruppen: %s"
#: views.py:29
#, python-format
msgid "Teacher: %s"
msgstr "Lehrer: %s"
#: views.py:34
#, python-format
msgid "Room: %s"
msgstr "Raum: %s"
......@@ -6,11 +6,12 @@ MENUS = {
'name': _('Timetables'),
'url': '#',
'root': True,
'validators': ['menu_generator.validators.is_authenticated'],
'submenu': [
{
'name': _('Timetable'),
'url': 'timetable',
'validators': ['menu_generator.validators.is_authenticated', 'menu_generator.validators.is_superuser']
'validators': ['menu_generator.validators.is_authenticated']
}
]
}
......
from datetime import datetime
from typing import List, Tuple, Optional
from typing import Dict, Optional, List, Tuple
from django.core import validators
from django.db import models
......@@ -29,7 +29,7 @@ class TimePeriod(models.Model):
time_start = models.TimeField(verbose_name=_('Time the period starts'))
time_end = models.TimeField(verbose_name=_('Time the period ends'))
def __str__(self): str:
def __str__(self) -> str:
return '%s, %d. period (%s - %s)' % (self.weekday, self.period, self.time_start, self.time_end)
@classmethod
......@@ -82,12 +82,26 @@ class Lesson(models.Model):
date_end = models.DateField(verbose_name=_(
'Effective end date of lesson'), null=True)
class LessonSubstitution(models.Model):
week = models.IntegerField(verbose_name=_('Week'),
default=current_week)
lesson_period = models.ForeignKey(
'LessonPeriod', models.CASCADE, 'substitutions')
subject = models.ForeignKey(
'Subject', on_delete=models.CASCADE,
related_name='lesson_substitutions', null=True)
teachers = models.ManyToManyField('core.Person',
related_name='lesson_substitutions')
room = models.ForeignKey('Room', models.CASCADE, null=True)
class LessonPeriod(models.Model):
lesson = models.ForeignKey('Lesson', models.CASCADE, related_name='lesson_periods')
period = models.ForeignKey('TimePeriod', models.CASCADE, related_name='lesson_periods')
room = models.ForeignKey('Room', models.CASCADE, null=True)
room = models.ForeignKey('Room', models.CASCADE, null=True, related_name='lesson_periods')
def get_substitution(self, week: Optional[int] = None) -> LessonSubstitution:
wanted_week = week or current_week()
......@@ -113,18 +127,3 @@ class LessonPeriod(models.Model):
def get_groups(self) -> models.query.QuerySet:
return self.lesson.groups
class LessonSubstitution(models.Model):
week = models.IntegerField(verbose_name=_('Kalenderwoche'),
default=current_week)
lesson_period = models.ForeignKey(
'LessonPeriod', models.CASCADE, 'substitutions')
subject = models.ForeignKey(
'Subject', on_delete=models.CASCADE,
related_name='lesson_substitutions', null=True)
teachers = models.ManyToManyField('core.Person',
related_name='lesson_substitutions')
room = models.ForeignKey('Room', models.CASCADE, null=True)
.chronos-lesson {
height: 6em;
}
ul#timetable_select_form li {
dispaly: inline;
}
\ No newline at end of file
......@@ -10,9 +10,13 @@
{% block page_title %}Timetable{% endblock %}
{% block content %}
<p>
{{ filter_descs }}
</p>
<form method="get">
{% csrf_token %}
<ul id="timetable_select_form">
{{ select_form.as_ul }}
</ul>
<input type="submit" value="Select" />
</form>
<div class="row">
<div class="col-sm px-0">
......
from datetime import date
from django import template
from ..util import week_days
register = template.Library()
@register.filter
def week_start(week: int) -> date:
return week_days(week)[0]
@register.filter
def week_end(week: int) -> date:
return week_days(week)[-1]
from datetime import datetime
from typing import Optional
from datetime import date, datetime, timedelta
from typing import Optional, Sequence
from django.apps import apps
from django.db import models
from .models import LessonPeriod
def current_week() -> int:
return int(datetime.now().strftime('%V'))
def week_days(week: Optional[int]) -> Sequence[date]:
# FIXME Make this aware of the school term concept
# cf. BiscuIT-ng#40
year = date.today().year
wanted_week = week or current_week()
first_day = datetime.strptime('%d-%d-1' % (year, wanted_week), '%Y-%W-%w')
return [(first_day + timedelta(days=offset)).date() for offset in range(0, 7)]
def current_lesson_periods(when: Optional[datetime] = None) -> models.query.QuerySet:
now = when or datetime.now()
LessonPeriod = apps.get_model('chronos.LessonPeriod')
return LessonPeriod.objects.filter(lesson__date_start__lte=now.date(),
lesson__date_end__gte=now.date(),
period__weekday=now.isoweekday(),
......
from collections import OrderedDict
from django.contrib.auth.decorators import login_required
from django.db.models import Max, Min
from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect, render
from django.urls import reverse
......@@ -9,6 +10,7 @@ from django.utils.translation import ugettext as _
from biscuit.core.decorators import admin_required
from biscuit.core.models import Group, Person
from .forms import SelectForm
from .models import LessonPeriod, TimePeriod, Room
from .util import current_week
......@@ -19,51 +21,47 @@ def timetable(request: HttpRequest) -> HttpResponse:
context = {}
lesson_periods = LessonPeriod.objects.all()
filter_descs = []
if 'group' in request.GET:
lesson_periods = lesson_periods.filter(
lesson__groups__pk=int(request.GET['group']))
filter_descs.append(_('Group: %s') % Group.objects.get(
pk=int(request.GET['group'])))
elif 'teacher' in request.GET:
lesson_periods = lesson_periods.filter(
lesson__teachers__pk=int(request.GET['teacher']))
filter_descs.append(_('Teacher: %s') % Person.objects.get(
pk=int(request.GET['teacher'])))
elif 'room' in request.GET:
lesson_periods = lesson_periods.filter(
room__pk=int(request.GET['room']))
filter_descs.append(_('Room: %s') % Room.objects.get(
pk=int(request.GET['room'])))
if request.GET.get('group', None) or request.GET.get('teacher', None) or request.GET.get('room', None):
# Incrementally filter lesson periods by GET parameters
if 'group' in request.GET and request.GET['group']:
lesson_periods = lesson_periods.filter(
lesson__groups__pk=int(request.GET['group']))
if 'teacher' in request.GET and request.GET['teacher']:
lesson_periods = lesson_periods.filter(
lesson__teachers__pk=int(request.GET['teacher']))
if 'room' in request.GET and request.GET['room']:
lesson_periods = lesson_periods.filter(
room__pk=int(request.GET['room']))
else:
# Redirect to a selected view if no filter provided
if request.user.person:
if request.user.person.primary_group:
return redirect(reverse('timetable') + '?group=%d' % request.user.person.primary_group.pk)
elif lesson_periods.filter(lesson__teachers=request.user.person).exists():
return redirect(reverse('timetable') + '?teacher=%d' % request.user.person.pk)
# Regroup lesson periods per weekday
per_day = {}
period_min, period_max = None, None
for lesson_period in lesson_periods:
per_day.setdefault(lesson_period.period.weekday,
{})[lesson_period.period.period] = lesson_period
# Expand min and max lesson to later fill in empty lessons
if period_min is None or period_min > lesson_period.period.period:
period_min = lesson_period.period.period
if period_max is None or period_max < lesson_period.period.period:
period_max = lesson_period.period.period
# Determine overall first and last day and period
min_max = TimePeriod.objects.aggregate(
Min('period'), Max('period'),
Min('weekday'), Max('weekday'))
# Fill in empty lessons
for weekday_num in range(min(per_day.keys() or [0]),
max(per_day.keys() or [6]) + 1):
for weekday_num in range(min_max.get('weekday__min', 0),
min_max.get('weekday__max', 6) + 1):
# Fill in empty weekdays
if weekday_num not in per_day.keys():
per_day[weekday_num] = {}
# Fill in empty lessons on this workday
for period_num in range(period_min, period_max + 1):
for period_num in range(min_max.get('period__min', 1),
min_max.get('period__max', 7) + 1):
if period_num not in per_day[weekday_num].keys():
per_day[weekday_num][period_num] = None
......@@ -71,10 +69,13 @@ def timetable(request: HttpRequest) -> HttpResponse:
per_day[weekday_num] = OrderedDict(
sorted(per_day[weekday_num].items()))
# Add a form to filter the view
select_form = SelectForm(request.GET or None)
context['lesson_periods'] = OrderedDict(sorted(per_day.items()))
context['filter_descs'] = ', '.join(filter_descs)
context['periods'] = TimePeriod.get_times_dict()
context['weekdays'] = dict(TimePeriod.WEEKDAY_CHOICES)
context['current_week'] = current_week()
context['select_form'] = select_form
return render(request, 'chronos/tt_week.html', context)
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