From 55d1b8821410540d0abd996bcccfc47b9c6f2728 Mon Sep 17 00:00:00 2001 From: Julian Leucker <leuckerj@gmail.com> Date: Sun, 29 Nov 2020 15:11:45 +0100 Subject: [PATCH] Implement multiple selection in person overview --- .../alsijil/static/css/alsijil/person.css | 11 ++ .../alsijil/class_register/person.html | 116 +++++++++++------- aleksis/apps/alsijil/views.py | 31 ++++- 3 files changed, 114 insertions(+), 44 deletions(-) create mode 100644 aleksis/apps/alsijil/static/css/alsijil/person.css diff --git a/aleksis/apps/alsijil/static/css/alsijil/person.css b/aleksis/apps/alsijil/static/css/alsijil/person.css new file mode 100644 index 000000000..bed4e7e3f --- /dev/null +++ b/aleksis/apps/alsijil/static/css/alsijil/person.css @@ -0,0 +1,11 @@ +span.input-field.inline > .select-wrapper > input { + color: red; + padding: 14px 0 0 0; + line-height: 2px; + height: 36px; + vertical-align: middle; +} + +span.input-field.inline > .select-wrapper .caret { + top: 12px !important; +} \ No newline at end of file diff --git a/aleksis/apps/alsijil/templates/alsijil/class_register/person.html b/aleksis/apps/alsijil/templates/alsijil/class_register/person.html index 7254e0e24..f4551ed96 100644 --- a/aleksis/apps/alsijil/templates/alsijil/class_register/person.html +++ b/aleksis/apps/alsijil/templates/alsijil/class_register/person.html @@ -4,6 +4,11 @@ {% load data_helpers %} {% load week_helpers %} {% load i18n %} +{% load static %} + +{% block extra_head %} + <link rel="stylesheet" href="{% static "css/alsijil/person.css" %}"> +{% endblock %} {% block browser_title %}{% blocktrans %}Class register: person{% endblocktrans %}{% endblock %} @@ -33,51 +38,76 @@ <div class="row"> <div class="col s12 m12 l6"> - <h5>{% trans "Unexcused absences" %}</h5> - <ul class="collection"> - {% for note in unexcused_absences %} - <li class="collection-item"> - {% has_perm "alsijil.edit_personalnote" user note as can_edit_personal_note %} - {% if can_edit_personal_note %} - <form action="" method="post" class="right hide-on-small-only" style="margin-top: -7px;"> + <h5>{% trans "Unexcused absences" %}</h5> + <h6> + <form method="POST" id="excuse-multiple-form"> {% 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="{{ note.get_absolute_url }}">{{ 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 materialize-circle green white-text">check</i> - <span class="title">{% trans "There are no unexcused lessons." %}</span> - </li> - {% endfor %} - </ul> + {% 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> + </h6> + + <ul class="collection"> + {% 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"/> + <span></span> + </label> + <form action="" method="post" class="right hide-on-small-only" style="margin-top: -7px;"> + {% 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> {% 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 75c07ebec..7f0cfbea3 100644 --- a/aleksis/apps/alsijil/views.py +++ b/aleksis/apps/alsijil/views.py @@ -1,5 +1,6 @@ from contextlib import nullcontext from copy import deepcopy +from contextlib import suppress from datetime import date, datetime, timedelta from typing import Any, Dict, Optional @@ -736,7 +737,35 @@ def overview_person(request: HttpRequest, id_: Optional[int] = None) -> HttpResp pass if found: - if request.POST.get("date"): + if request.POST.get("excuse_multiple") and request.POST.get("selected_notes"): + if not request.user.has_perm( + "alsijil.edit_person_overview_personalnote", person + ): + raise PermissionDenied() + + lesson_pks = request.POST.getlist("selected_notes") + + def convert_to_int_optional(x): + with suppress(ValueError): + return int(x) + + lesson_pks = [convert_to_int_optional(pk) for pk in lesson_pks] + + notes = person.personal_notes.filter( + pk__in=lesson_pks, + absent=True, + excused=False, + ) + for note in notes: + note.excused = True + note.excuse_type = excuse_type + with reversion.create_revision(): + reversion.set_user(request.user) + note.save() + + messages.success(request, _("The absences have been marked as excused.")) + + elif request.POST.get("date"): # Mark absences on date as excused try: date = datetime.strptime(request.POST["date"], "%Y-%m-%d").date() -- GitLab