diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py index f8146cd797736fb48923df4190cead2d9133040c..d826f8e0ec559308507cdb2aa98fd1575f44cb01 100644 --- a/aleksis/apps/alsijil/models.py +++ b/aleksis/apps/alsijil/models.py @@ -30,7 +30,7 @@ from aleksis.apps.alsijil.managers import ( ) from aleksis.apps.chronos.managers import GroupPropertiesMixin from aleksis.apps.chronos.mixins import WeekRelatedMixin -from aleksis.apps.chronos.models import Event, ExtraLesson, LessonPeriod +from aleksis.apps.chronos.models import Event, ExtraLesson, LessonPeriod, TimePeriod from aleksis.core.mixins import ExtensibleModel from aleksis.core.models import SchoolTerm from aleksis.core.util.core_helpers import get_site_preferences @@ -155,6 +155,33 @@ class RegisterObjectRelatedMixin(WeekRelatedMixin): else f"{date_format(self.event.date_start)}–{date_format(self.event.date_end)}" ) + @property + def period(self: Union["LessonDocumentation", "PersonalNote"]) -> TimePeriod: + """Get the date of this lesson documentation or personal note. + + :: warning:: + + As events can be longer than one day, + this will return `None` for events. + """ + if self.event: + return self.event.period_from + else: + return self.register_object.period + + @property + def period_formatted(self: Union["LessonDocumentation", "PersonalNote"]) -> str: + """Get a formatted version of the period of this object. + + Lesson periods, extra lessons: formatted period + Events: formatted period range + """ + return ( + f"{self.period.period}." + if not self.event + else f"{self.event.period_from.period}.–{self.event.period_to.period}." + ) + def get_absolute_url(self: Union["LessonDocumentation", "PersonalNote"]) -> str: """Get the absolute url of the detail view for the related register object.""" return self.register_object.get_alsijil_url(self.calendar_week) diff --git a/aleksis/apps/alsijil/tables.py b/aleksis/apps/alsijil/tables.py index afa50cb154f85b1d57ce0c6cadf1208c65ab7cbb..47bd409ac60db055f9d88e33290bdb953a2f54a2 100644 --- a/aleksis/apps/alsijil/tables.py +++ b/aleksis/apps/alsijil/tables.py @@ -7,6 +7,7 @@ import django_tables2 as tables from django_tables2.utils import A from aleksis.core.tables import MaterializeCheckboxColumn +from aleksis.apps.chronos.models import Event, LessonPeriod from .models import PersonalNote @@ -85,31 +86,37 @@ class GroupRoleTable(tables.Table): if not request.user.has_perm("alsijil.delete_grouprole"): self.columns.hide("delete") class PersonalNoteTable(tables.Table): - selected = MaterializeCheckboxColumn(verbose_name=_("Gay"), attrs={"name": "selected_objects"}) - lesson_period_lesson = tables.Column(verbose_name=_("Lesson"), accessor=A("lesson_period")) - # lesson_period_teacher = tables.Column(verbose_name=_("Teacher"), accessor=A("lesson_period__get_teacher_names")) - personal_note_date = tables.Column(verbose_name=_("Date"), accessor=A("date")) - lesson_period_period = tables.Column(verbose_name=_("Period"), accessor=A("lesson_period__period__period")) - # lesson_period_subject = tables.Column(verbose_name=_("Subject"), accessor=A("lesson_period__get_subject__name")) - # absent = tables.Column(attrs={"td": {"class": "material-icons"}}) + selected = MaterializeCheckboxColumn( + attrs={"input": {"name": "selected_objects"}}, accessor=A("pk") + ) + date = tables.Column( + verbose_name=_("Date"), accessor=A("date_formatted"), order_by=A("day_start") + ) + period = tables.Column( + verbose_name=_("Period"), accessor=A("period_formatted"), order_by=A("period") + ) + groups = tables.Column(verbose_name=_("Groups"), accessor=A("register_object__group_names")) + teachers = tables.Column( + verbose_name=_("Teachers"), accessor=A("register_object__teacher_names") + ) + subject = tables.Column( + verbose_name=_("Subject"), accessor=A("register_object__get_subject__name") + ) + absent = tables.Column() excused = tables.Column(verbose_name=_("Excuse")) extra_marks = tables.Column(verbose_name="Extra marks", accessor=A("extra_marks__all")) - def render_lesson_period_period(self, value): - return str(value) + "." - - def render_lesson_period_lesson(self, value, record): - teachers = value.get_teacher_names() - subject = value.get_subject().name - pk = value.pk - week = record.week - year = record.year - - url = reverse("lesson_by_week_and_period", args=[year, week, pk]) - - context = dict(subject=subject, teachers=teachers, url=url) + def render_groups(self, value, record): + if isinstance(record.register_object, LessonPeriod): + return record.register_object.lesson.group_names + else: + return value - return render_to_string("alsijil/partials/personal_note_link.html", context) + def render_subject(self, value, record): + if isinstance(record.register_object, Event): + return _("Event") + else: + return value def render_absent(self, value): return render_to_string("components/materialize-chips.html", dict(content="Absent", classes="red white-text")) @@ -145,9 +152,5 @@ class PersonalNoteTable(tables.Table): class Meta: model = PersonalNote - sequence = ( - "selected", "year", "week", "personal_note_date", "lesson_period_period", - "lesson_period_lesson", "absent", "excused", "late", "extra_marks", "remarks" - ) - exclude = ("site", "id", "extended_data", "person", "lesson_period", "excuse_type") + fields = () template_name = "django_tables2/materialize.html" diff --git a/aleksis/apps/alsijil/templates/alsijil/class_register/person.html b/aleksis/apps/alsijil/templates/alsijil/class_register/person.html index be91e703b82718ccd96b2aa6aecaaefeb9b55c66..30a08ac0c228e67fa8c9fc6d6b743cfd83dd9c8b 100644 --- a/aleksis/apps/alsijil/templates/alsijil/class_register/person.html +++ b/aleksis/apps/alsijil/templates/alsijil/class_register/person.html @@ -51,84 +51,55 @@ <div class="col s12" id="statistics"> <h5>{% trans "Unexcused absences" %}</h5> - <ul class="collection"> - {% if unexcused_absences %} - <li class="collection-item row" id="title"> - <label class="col s12 xl2" id="select_all_container"> - <input type="checkbox" id="select_all_box" - form="excuse-multiple-form" class="filled-in"/> - <span id="select_all_span" class="secondary-color-text"> - <span id="select_all_box_text">Select all</span> - </span> - </label> - <div class="col s12 xl10"> - <form method="POST" id="excuse-multiple-form" class="right"> - {% csrf_token %} - {% trans "Mark selected as" %} - <span class="input-field inline"> - <select id="excuse-type-multiple" name="excuse_type"> - <option value="e" selected>{% trans "Excused" %}</option> - {% for excuse_type in excuse_types %} - <option value="{{ excuse_type.pk }}">{{ excuse_type.name }}</option> - {% endfor %} - </select> - <label for="excuse-type-multiple" class="hide">{% trans "Excuse type" %}</label> - </span> - <button type="submit" class="btn secondary-color" name="excuse_multiple" value="1"> - {% trans "Submit" %}<i class="material-icons right">send</i> - </button> - </form> - </div> - </li> - {% endif %} - {% for note in unexcused_absences %} - {% weekday_to_date note.calendar_week note.lesson_period.period.weekday as note_date %} - <li class="collection-item"> - {% has_perm "alsijil.edit_personalnote" user note as can_edit_personal_note %} - {% if can_edit_personal_note %} - <label class="left"> - <input type="checkbox" name="selected_notes" value="{{ note.pk }}" - form="excuse-multiple-form" class="filled-in"/> - <span></span> - </label> - <form action="" method="post" class="right hide-on-small-only"> - {% csrf_token %} - {% trans "Mark as" %} - <input type="hidden" value="{{ note.pk }}" name="personal_note"> - {% include "alsijil/partials/mark_as_buttons.html" %} - <a class="btn-flat red-text" title="{% trans "Delete note" %}" - href="{% url "delete_personal_note" note.pk %}"> - <i class="material-icons center">cancel</i> - </a> - </form> - {% endif %} - <i class="material-icons left red-text">warning</i> - <p class="no-margin"> - <a href="{% url "lesson_by_week_and_period" note.year note.week note.lesson_period.pk %}">{{ note_date }}, {{ note.lesson_period }}</a> - </p> - {% if note.remarks %} - <p class="no-margin"><em>{{ note.remarks }}</em></p> - {% endif %} - {% if can_edit_personal_note %} - <form action="" method="post" class="hide-on-med-and-up"> - {% csrf_token %} - {% trans "Mark as" %} - <input type="hidden" value="{{ note.pk }}" name="personal_note"> - {% include "alsijil/partials/mark_as_buttons.html" %} - <a class="btn-flat red-text" title="{% trans "Delete note" %}" - href="{% url "delete_personal_note" note.pk %}"> - <i class="material-icons center">cancel</i> - </a> - </form> - {% endif %} - </li> - {% empty %} - <li class="collection-item avatar valign-wrapper"> - <i class="material-icons left circle green white-text">check</i> - <span class="title">{% trans "There are no unexcused lessons." %}</span> - </li> - {% endfor %} - </ul> + + {# {% for note in unexcused_absences %}#} + {# {% weekday_to_date note.calendar_week note.lesson_period.period.weekday as note_date %}#} + {# <li class="collection-item">#} + {# {% has_perm "alsijil.edit_personalnote" user note as can_edit_personal_note %}#} + {# {% if can_edit_personal_note %}#} + {# <label class="left">#} + {# <input type="checkbox" name="selected_notes" value="{{ note.pk }}"#} + {# form="excuse-multiple-form" class="filled-in"/>#} + {# <span></span>#} + {# </label>#} + {# <form action="" method="post" class="right hide-on-small-only">#} + {# {% csrf_token %}#} + {# {% trans "Mark as" %}#} + {# <input type="hidden" value="{{ note.pk }}" name="personal_note">#} + {# {% include "alsijil/partials/mark_as_buttons.html" %}#} + {# <a class="btn-flat red-text" title="{% trans "Delete note" %}"#} + {# href="{% url "delete_personal_note" note.pk %}">#} + {# <i class="material-icons center">cancel</i>#} + {# </a>#} + {# </form>#} + {# {% endif %}#} + {# <i class="material-icons left red-text">warning</i>#} + {# <p class="no-margin">#} + {# <a href="{% url note.register_object.alsijil_url note.year note.week note.lesson_period.pk %}">{{ note_date }}, {{ note.lesson_period }}</a>#} + {# </p>#} + {# {% if note.remarks %}#} + {# <p class="no-margin"><em>{{ note.remarks }}</em></p>#} + {# {% endif %}#} + {# {% if can_edit_personal_note %}#} + {# <form action="" method="post" class="hide-on-med-and-up">#} + {# {% csrf_token %}#} + {# {% trans "Mark as" %}#} + {# <input type="hidden" value="{{ note.pk }}" name="personal_note">#} + {# {% include "alsijil/partials/mark_as_buttons.html" %}#} + {# <a class="btn-flat red-text" title="{% trans "Delete note" %}"#} + {# href="{% url "delete_personal_note" note.pk %}">#} + {# <i class="material-icons center">cancel</i>#} + {# </a>#} + {# </form>#} + {# {% endif %}#} + {# </li>#} + {# {% empty %}#} + {# <li class="collection-item avatar valign-wrapper">#} + {# <i class="material-icons left circle green white-text">check</i>#} + {# <span class="title">{% trans "There are no unexcused lessons." %}</span>#} + {# </li>#} + {# {% endfor %}#} + </ul> {% if stats %} <h5>{% trans "Statistics on absences, tardiness and remarks" %}</h5> <ul class="collapsible"> diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py index 5479745a4bd05ab01a805eb588b83e5d5b612e60..d25c08336fb332e84501ebe553b2ca475227cb61 100644 --- a/aleksis/apps/alsijil/views.py +++ b/aleksis/apps/alsijil/views.py @@ -725,10 +725,14 @@ def overview_person(request: HttpRequest, id_: Optional[int] = None) -> HttpResp ) context["person"] = person - person_personal_notes = person.personal_notes.all().prefetch_related( - "lesson_period__lesson__groups", - "lesson_period__lesson__teachers", - "lesson_period__substitutions", + person_personal_notes = ( + person.personal_notes.all() + .prefetch_related( + "lesson_period__lesson__groups", + "lesson_period__lesson__teachers", + "lesson_period__substitutions", + ) + .annotate_date_range() ) if request.user.has_perm("alsijil.view_person_overview_personalnote", person):