Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AlekSIS/official/AlekSIS-App-Alsijil
  • sunweaver/AlekSIS-App-Alsijil
  • 8tincsoVluke/AlekSIS-App-Alsijil
  • perfreicpo/AlekSIS-App-Alsijil
  • noifobarep/AlekSIS-App-Alsijil
  • 7ingannisdo/AlekSIS-App-Alsijil
  • unmruntartpa/AlekSIS-App-Alsijil
  • balrorebta/AlekSIS-App-Alsijil
  • comliFdifwa/AlekSIS-App-Alsijil
  • 3ranaadza/AlekSIS-App-Alsijil
10 results
Show changes
Commits on Source (195)
Showing
with 3102 additions and 1115 deletions
......@@ -2,15 +2,18 @@ from datetime import datetime
from django import forms
from django.core.exceptions import ValidationError
from django.db.models import Count
from django.db.models import Count, Q
from django.utils.translation import gettext_lazy as _
from django_global_request.middleware import get_request
from django_select2.forms import Select2Widget
from guardian.shortcuts import get_objects_for_user
from material import Fieldset, Layout, Row
from aleksis.apps.chronos.managers import TimetableType
from aleksis.apps.chronos.models import TimePeriod
from aleksis.core.models import Group, Person
from aleksis.core.util.predicates import check_global_permission
from .models import ExcuseType, ExtraMark, LessonDocumentation, PersonalNote
......@@ -51,12 +54,7 @@ class SelectForm(forms.Form):
queryset=None, label=_("Group"), required=False, widget=Select2Widget,
)
teacher = forms.ModelChoiceField(
queryset=Person.objects.annotate(
lessons_count=Count("lessons_as_teacher")
).filter(lessons_count__gt=0),
label=_("Teacher"),
required=False,
widget=Select2Widget,
queryset=None, label=_("Teacher"), required=False, widget=Select2Widget,
)
def clean(self) -> dict:
......@@ -78,13 +76,41 @@ class SelectForm(forms.Form):
return data
def __init__(self, *args, **kwargs):
self.request = get_request()
super().__init__(*args, **kwargs)
self.fields["group"].queryset = (
Group.objects.for_current_school_term_or_all()
.annotate(lessons_count=Count("lessons"))
.filter(lessons_count__gt=0)
person = self.request.user.person
group_qs = Group.get_groups_with_lessons()
# Filter selectable groups by permissions
if not check_global_permission(self.request.user, "alsijil.view_week"):
# 1) All groups the user is allowed to see the week view by object permissions
# 2) All groups the user is a member of an owner of
group_qs = (
group_qs.filter(
pk__in=get_objects_for_user(
self.request.user, "core.view_week_class_register_group", Group
).values_list("pk", flat=True)
)
).union(group_qs.filter(Q(members=person) | Q(owners=person)))
# Flatten query by filtering groups by pk
self.fields["group"].queryset = Group.objects.filter(
pk__in=list(group_qs.values_list("pk", flat=True))
)
teacher_qs = Person.objects.annotate(
lessons_count=Count("lessons_as_teacher")
).filter(lessons_count__gt=0)
# Filter selectable teachers by permissions
if not check_global_permission(self.request.user, "alsijil.view_week"):
# If the user hasn't the global permission, the user is only allowed to see his own person
teacher_qs = teacher_qs.filter(pk=person.pk)
self.fields["teacher"].queryset = teacher_qs
PersonalNoteFormSet = forms.modelformset_factory(
PersonalNote, form=PersonalNoteForm, max_num=0, extra=0
......@@ -93,7 +119,6 @@ PersonalNoteFormSet = forms.modelformset_factory(
class RegisterAbsenceForm(forms.Form):
layout = Layout(
Fieldset("", "person"),
Fieldset("", Row("date_start", "date_end"), Row("from_period", "to_period")),
Fieldset("", Row("absent", "excused"), Row("excuse_type"), Row("remarks")),
)
......@@ -101,9 +126,6 @@ class RegisterAbsenceForm(forms.Form):
date_end = forms.DateField(label=_("End date"), initial=datetime.today)
from_period = forms.ChoiceField(label=_("Start period"))
to_period = forms.ChoiceField(label=_("End period"))
person = forms.ModelChoiceField(
label=_("Person"), queryset=Person.objects.all(), widget=Select2Widget
)
absent = forms.BooleanField(label=_("Absent"), initial=True, required=False)
excused = forms.BooleanField(label=_("Excused"), initial=True, required=False)
excuse_type = forms.ModelChoiceField(
......@@ -115,6 +137,7 @@ class RegisterAbsenceForm(forms.Form):
remarks = forms.CharField(label=_("Remarks"), max_length=30, required=False)
def __init__(self, *args, **kwargs):
self.request = get_request()
super().__init__(*args, **kwargs)
period_choices = TimePeriod.period_choices
......
from aleksis.core.managers import CurrentSiteManagerWithoutMigrations
class PersonalNoteManager(CurrentSiteManagerWithoutMigrations):
"""Manager adding specific methods to personal notes."""
def get_queryset(self):
"""Ensure all related lesson and person data are loaded as well."""
return (
super()
.get_queryset()
.select_related(
"person",
"excuse_type",
"lesson_period",
"lesson_period__lesson",
"lesson_period__lesson__subject",
"lesson_period__period",
"lesson_period__lesson__validity",
"lesson_period__lesson__validity__school_term",
)
.prefetch_related("extra_marks")
)
......@@ -16,49 +16,78 @@ MENUS = {
"name": _("Current lesson"),
"url": "lesson",
"icon": "alarm",
"validators": ["menu_generator.validators.is_authenticated"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"alsijil.view_lesson_menu",
),
],
},
{
"name": _("Current week"),
"url": "week_view",
"icon": "view_week",
"validators": ["menu_generator.validators.is_authenticated"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"alsijil.view_week_menu",
),
],
},
{
"name": _("My groups"),
"url": "my_groups",
"icon": "people",
"validators": ["menu_generator.validators.is_authenticated"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"alsijil.view_my_groups",
),
],
},
{
"name": _("My overview"),
"url": "overview_me",
"icon": "insert_chart",
"validators": ["menu_generator.validators.is_authenticated"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"alsijil.view_person_overview_menu",
),
],
},
{
"name": _("My students"),
"url": "my_students",
"icon": "people",
"validators": ["menu_generator.validators.is_authenticated"],
},
{
"name": _("Register absence"),
"url": "register_absence",
"icon": "rate_review",
"validators": ["menu_generator.validators.is_superuser"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"alsijil.view_my_students",
),
],
},
{
"name": _("Excuse types"),
"url": "excuse_types",
"icon": "label",
"validators": ["menu_generator.validators.is_superuser"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"alsijil.view_excusetypes",
),
],
},
{
"name": _("Extra marks"),
"url": "extra_marks",
"icon": "label",
"validators": ["menu_generator.validators.is_superuser"],
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"alsijil.view_extramarks",
),
],
},
],
}
......
from datetime import date
from typing import Dict, Optional, Union
from typing import Dict, Iterable, Iterator, Optional, Union
from django.db.models import Exists, OuterRef, QuerySet
from django.db.models import Exists, OuterRef, Q, QuerySet
from django.db.models.aggregates import Count, Sum
from django.utils.translation import gettext as _
import reversion
from calendarweek import CalendarWeek
......@@ -53,16 +55,20 @@ def mark_absent(
continue
with reversion.create_revision():
personal_note, created = PersonalNote.objects.update_or_create(
person=self,
lesson_period=lesson_period,
week=wanted_week.week,
year=wanted_week.year,
defaults={
"absent": absent,
"excused": excused,
"excuse_type": excuse_type,
},
personal_note, created = (
PersonalNote.objects.select_related(None)
.prefetch_related(None)
.update_or_create(
person=self,
lesson_period=lesson_period,
week=wanted_week.week,
year=wanted_week.year,
defaults={
"absent": absent,
"excused": excused,
"excuse_type": excuse_type,
},
)
)
personal_note.groups_of_person.set(self.member_of.all())
......@@ -75,7 +81,7 @@ def mark_absent(
@LessonPeriod.method
def get_personal_notes(self, wanted_week: CalendarWeek):
def get_personal_notes(self, persons: QuerySet, wanted_week: CalendarWeek):
"""Get all personal notes for that lesson in a specified week.
Returns all linked `PersonalNote` objects, filtered by the given weeek,
......@@ -88,7 +94,7 @@ def get_personal_notes(self, wanted_week: CalendarWeek):
- Dominik George <dominik.george@teckids.org>
"""
# Find all persons in the associated groups that do not yet have a personal note for this lesson
missing_persons = Person.objects.annotate(
missing_persons = persons.annotate(
no_personal_notes=~Exists(
PersonalNote.objects.filter(
week=wanted_week.week,
......@@ -118,11 +124,51 @@ def get_personal_notes(self, wanted_week: CalendarWeek):
for personal_note in new_personal_notes:
personal_note.groups_of_person.set(personal_note.person.member_of.all())
return PersonalNote.objects.select_related("person").filter(
lesson_period=self, week=wanted_week.week, year=wanted_week.year
return (
PersonalNote.objects.filter(
lesson_period=self,
week=wanted_week.week,
year=wanted_week.year,
person__in=persons,
)
.select_related(None)
.prefetch_related(None)
.select_related("person", "excuse_type")
.prefetch_related("extra_marks")
)
# Dynamically add extra permissions to Group and Person models in core
# Note: requires migrate afterwards
Group.add_permission(
"view_week_class_register_group",
_("Can view week overview of group class register"),
)
Group.add_permission(
"view_lesson_class_register_group",
_("Can view lesson overview of group class register"),
)
Group.add_permission(
"view_personalnote_group", _("Can view all personal notes of a group")
)
Group.add_permission(
"edit_personalnote_group", _("Can edit all personal notes of a group")
)
Group.add_permission(
"view_lessondocumentation_group", _("Can view all lesson documentation of a group")
)
Group.add_permission(
"edit_lessondocumentation_group", _("Can edit all lesson documentation of a group")
)
Group.add_permission("view_full_register_group", _("Can view full register of a group"))
Group.add_permission(
"register_absence_group", _("Can register an absence for all members of a group")
)
Person.add_permission(
"register_absence_person", _("Can register an absence for a person")
)
@LessonPeriod.method
def get_lesson_documentation(
self, week: Optional[CalendarWeek] = None
......@@ -130,11 +176,14 @@ def get_lesson_documentation(
"""Get lesson documentation object for this lesson."""
if not week:
week = self.week
# Use all to make effect of prefetched data
doc_filter = filter(
lambda d: d.week == week.week and d.year == week.year,
self.documentations.all(),
)
try:
return LessonDocumentation.objects.get(
lesson_period=self, week=week.week, year=week.year
)
except LessonDocumentation.DoesNotExist:
return next(doc_filter)
except StopIteration:
return None
......@@ -152,11 +201,15 @@ def get_or_create_lesson_documentation(
@LessonPeriod.method
def get_absences(self, week: Optional[CalendarWeek] = None) -> QuerySet:
def get_absences(self, week: Optional[CalendarWeek] = None) -> Iterator:
"""Get all personal notes of absent persons for this lesson."""
if not week:
week = self.week
return self.personal_notes.filter(week=week.week, year=week.year, absent=True)
return filter(
lambda p: p.week == week.week and p.year == week.year and p.absent,
self.personal_notes.all(),
)
@LessonPeriod.method
......@@ -204,3 +257,136 @@ def get_extra_marks(
stats[extra_mark] = qs
return stats
@Group.class_method
def get_groups_with_lessons(cls: Group):
"""Get all groups which have related lessons or child groups with related lessons."""
group_pks = (
cls.objects.for_current_school_term_or_all()
.annotate(lessons_count=Count("lessons"))
.filter(lessons_count__gt=0)
.values_list("pk", flat=True)
)
groups = cls.objects.filter(
Q(child_groups__pk__in=group_pks) | Q(pk__in=group_pks)
).distinct()
return groups
@Person.method
def get_owner_groups_with_lessons(self: Person):
"""Get all groups the person is an owner of and which have related lessons.
Groups which have child groups with related lessons are also included.
"""
return Group.get_groups_with_lessons().filter(owners=self).distinct()
@Group.method
def generate_person_list_with_class_register_statistics(
self: Group, persons: Optional[Iterable] = None
) -> QuerySet:
"""Get with class register statistics annotated list of all members."""
persons = persons or self.members.all()
persons = persons.filter(
personal_notes__groups_of_person=self,
personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
).annotate(
absences_count=Count(
"personal_notes__absent",
filter=Q(
personal_notes__absent=True,
personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
)
& (
Q(personal_notes__lesson_period__lesson__groups=self)
| Q(personal_notes__lesson_period__lesson__groups__parent_groups=self)
),
),
excused=Count(
"personal_notes__absent",
filter=Q(
personal_notes__absent=True,
personal_notes__excused=True,
personal_notes__excuse_type__isnull=True,
personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
)
& (
Q(personal_notes__lesson_period__lesson__groups=self)
| Q(personal_notes__lesson_period__lesson__groups__parent_groups=self)
),
),
unexcused=Count(
"personal_notes__absent",
filter=Q(
personal_notes__absent=True,
personal_notes__excused=False,
personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
)
& (
Q(personal_notes__lesson_period__lesson__groups=self)
| Q(personal_notes__lesson_period__lesson__groups__parent_groups=self)
),
),
tardiness=Sum(
"personal_notes__late",
filter=(
Q(personal_notes__lesson_period__lesson__groups=self)
| Q(personal_notes__lesson_period__lesson__groups__parent_groups=self)
),
),
tardiness_count=Count(
"personal_notes",
filter=~Q(personal_notes__late=0)
& Q(
personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
)
& (
Q(personal_notes__lesson_period__lesson__groups=self)
| Q(personal_notes__lesson_period__lesson__groups__parent_groups=self)
),
),
)
for extra_mark in ExtraMark.objects.all():
persons = persons.annotate(
**{
extra_mark.count_label: Count(
"personal_notes",
filter=Q(
personal_notes__extra_marks=extra_mark,
personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
)
& (
Q(personal_notes__lesson_period__lesson__groups=self)
| Q(
personal_notes__lesson_period__lesson__groups__parent_groups=self
)
),
)
}
)
for excuse_type in ExcuseType.objects.all():
persons = persons.annotate(
**{
excuse_type.count_label: Count(
"personal_notes__absent",
filter=Q(
personal_notes__absent=True,
personal_notes__excuse_type=excuse_type,
personal_notes__lesson_period__lesson__validity__school_term=self.school_term,
)
& (
Q(personal_notes__lesson_period__lesson__groups=self)
| Q(
personal_notes__lesson_period__lesson__groups__parent_groups=self
)
),
)
}
)
return persons
from django.db import models
from django.utils.formats import date_format
from django.utils.functional import classproperty
from django.utils.translation import gettext_lazy as _
from cache_memoize import cache_memoize
from calendarweek import CalendarWeek
from aleksis.apps.alsijil.managers import PersonalNoteManager
from aleksis.apps.chronos.mixins import WeekRelatedMixin
from aleksis.apps.chronos.models import LessonPeriod
from aleksis.apps.chronos.util.date import get_current_year
......@@ -46,6 +49,8 @@ class PersonalNote(ExtensibleModel, WeekRelatedMixin):
and remarks about a student in a single lesson period.
"""
objects = PersonalNoteManager()
person = models.ForeignKey(
"core.Person", models.CASCADE, related_name="personal_notes"
)
......@@ -208,3 +213,13 @@ class ExtraMark(ExtensibleModel):
ordering = ["short_name"]
verbose_name = _("Extra mark")
verbose_name_plural = _("Extra marks")
class AlsijilGlobalPermissions(ExtensibleModel):
class Meta:
managed = False
permissions = (
("view_week", _("Can view week overview")),
("register_absence", _("Can register absence")),
("list_personal_note_filters", _("Can list all personal note filters")),
)
......@@ -16,6 +16,24 @@ class BlockPersonalNotesForCancelled(BooleanPreference):
verbose_name = _("Block adding personal notes for cancelled lessons")
@site_preferences_registry.register
class ViewOwnPersonalNotes(BooleanPreference):
section = alsijil
name = "view_own_personal_notes"
default = True
verbose_name = _("Allow users to view their own personal notes")
@site_preferences_registry.register
class RegisterAbsenceAsPrimaryGroupOwner(BooleanPreference):
section = alsijil
name = "register_absence_as_primary_group_owner"
default = True
verbose_name = _(
"Allow primary group owners to register future absences for students in their groups"
)
@site_preferences_registry.register
class CarryOverDataToNextPeriods(BooleanPreference):
section = alsijil
......
from rules import add_perm
from aleksis.core.util.predicates import (
has_global_perm,
has_object_perm,
has_person,
is_current_person,
is_site_preference_set,
)
from .util.predicates import (
has_any_object_absence,
has_lesson_group_object_perm,
has_person_group_object_perm,
has_personal_note_group_perm,
is_group_member,
is_group_owner,
is_lesson_parent_group_owner,
is_lesson_participant,
is_lesson_teacher,
is_none,
is_own_personal_note,
is_person_group_owner,
is_person_primary_group_owner,
is_personal_note_lesson_parent_group_owner,
is_personal_note_lesson_teacher,
is_teacher,
)
# View lesson
view_lesson_predicate = has_person & (
is_none # View is opened as "Current lesson"
| is_lesson_teacher
| is_lesson_participant
| is_lesson_parent_group_owner
| has_global_perm("alsijil.view_lesson")
| has_lesson_group_object_perm("core.view_week_class_register_group")
)
add_perm("alsijil.view_lesson", view_lesson_predicate)
# View lesson in menu
add_perm("alsijil.view_lesson_menu", has_person)
# View lesson personal notes
view_lesson_personal_notes_predicate = view_lesson_predicate & (
~is_lesson_participant
| is_lesson_teacher
| has_global_perm("alsijil.view_personalnote")
| has_lesson_group_object_perm("core.view_personalnote_group")
)
add_perm("alsijil.view_lesson_personalnote", view_lesson_personal_notes_predicate)
# Edit personal note
edit_lesson_personal_note_predicate = view_lesson_personal_notes_predicate & (
is_lesson_teacher
| has_global_perm("alsijil.change_personalnote")
| has_lesson_group_object_perm("core.edit_personalnote_group")
)
add_perm("alsijil.edit_lesson_personalnote", edit_lesson_personal_note_predicate)
# View personal note
view_personal_note_predicate = has_person & (
(
is_own_personal_note
& is_site_preference_set("alsijil", "view_own_personal_notes")
)
| is_personal_note_lesson_teacher
| is_personal_note_lesson_parent_group_owner
| has_global_perm("alsijil.view_personalnote")
| has_personal_note_group_perm("core.view_personalnote_group")
)
add_perm("alsijil.view_personalnote", view_personal_note_predicate)
# Edit personal note
edit_personal_note_predicate = view_personal_note_predicate & (
~is_own_personal_note
| has_global_perm("alsijil.view_personalnote")
| has_personal_note_group_perm("core.edit_personalnote_group")
)
add_perm("alsijil.edit_personalnote", edit_personal_note_predicate)
# View lesson documentation
view_lesson_documentation_predicate = view_lesson_predicate
add_perm("alsijil.view_lessondocumentation", view_lesson_documentation_predicate)
# Edit lesson documentation
edit_lesson_documentation_predicate = view_lesson_predicate & (
is_lesson_teacher
| has_global_perm("alsijil.change_lessondocumentation")
| has_lesson_group_object_perm("core.edit_lessondocumentation_group")
)
add_perm("alsijil.edit_lessondocumentation", edit_lesson_documentation_predicate)
# View week overview
view_week_predicate = has_person & (
is_current_person
| is_group_member
| is_group_owner
| has_global_perm("alsijil.view_week")
| has_object_perm("core.view_week_class_register_group")
)
add_perm("alsijil.view_week", view_week_predicate)
# View week overview in menu
add_perm("alsijil.view_week_menu", has_person)
# View week personal notes
view_week_personal_notes_predicate = has_person & (
(is_current_person & is_teacher)
| is_group_owner
| has_global_perm("alsijil.view_personalnote")
| has_object_perm("core.view_personalnote_group")
)
add_perm("alsijil.view_week_personalnote", view_week_personal_notes_predicate)
# Register absence
register_absence_predicate = has_person & (
(
is_person_primary_group_owner
& is_site_preference_set("alsijil", "register_absence_as_primary_group_owner")
)
| has_global_perm("alsijil.register_absence")
| has_object_perm("core.register_absence_person")
| has_person_group_object_perm("core.register_absence_group")
)
add_perm("alsijil.register_absence", register_absence_predicate)
# View full register for group
view_full_register_predicate = has_person & (
is_group_owner
| has_global_perm("alsijil.view_full_register")
| has_object_perm("core.view_full_register_group")
)
add_perm("alsijil.view_full_register", view_full_register_predicate)
# View students list
view_my_students_predicate = has_person & is_teacher
add_perm("alsijil.view_my_students", view_my_students_predicate)
# View groups list
view_my_groups_predicate = has_person & is_teacher
add_perm("alsijil.view_my_groups", view_my_groups_predicate)
# View students list
view_students_list_predicate = view_my_groups_predicate & (
is_group_owner
| has_global_perm("alsijil.view_personalnote")
| has_object_perm("core.view_personalnote_group")
)
add_perm("alsijil.view_students_list", view_students_list_predicate)
# View person overview
view_person_overview_predicate = has_person & (
(is_current_person & is_site_preference_set("alsijil", "view_own_personal_notes"))
| is_person_group_owner
)
add_perm("alsijil.view_person_overview", view_person_overview_predicate)
# View person overview
view_person_overview_menu_predicate = has_person
add_perm("alsijil.view_person_overview_menu", view_person_overview_menu_predicate)
# View person overview personal notes
view_person_overview_personal_notes_predicate = view_person_overview_predicate & (
(is_current_person & is_site_preference_set("alsijil", "view_own_personal_notes"))
| is_person_primary_group_owner
| has_global_perm("alsijil.view_personalnote")
| has_person_group_object_perm("core.view_personalnote_group")
)
add_perm(
"alsijil.view_person_overview_personalnote",
view_person_overview_personal_notes_predicate,
)
# Edit person overview personal notes
edit_person_overview_personal_notes_predicate = (
view_person_overview_personal_notes_predicate
& (
~is_current_person
| has_global_perm("alsijil.edit_personalnote")
| has_person_group_object_perm("core.edit_personalnote_group")
)
)
add_perm(
"alsijil.edit_person_overview_personalnote",
edit_person_overview_personal_notes_predicate,
)
# View person statistics on personal notes
view_person_statistics_personal_notes_predicate = (
view_person_overview_personal_notes_predicate
)
add_perm(
"alsijil.view_person_statistics_personalnote",
view_person_statistics_personal_notes_predicate,
)
# View excuse type list
view_excusetypes_predicate = has_person & has_global_perm("alsijil.view_excusetype")
add_perm("alsijil.view_excusetypes", view_excusetypes_predicate)
# Add excuse type
add_excusetype_predicate = view_excusetypes_predicate & has_global_perm(
"alsijil.add_excusetype"
)
add_perm("alsijil.add_excusetype", add_excusetype_predicate)
# Edit excuse type
edit_excusetype_predicate = view_excusetypes_predicate & has_global_perm(
"alsijil.change_excusetype"
)
add_perm("alsijil.edit_excusetype", edit_excusetype_predicate)
# Delete excuse type
delete_excusetype_predicate = view_excusetypes_predicate & has_global_perm(
"alsijil.delete_excusetype"
)
add_perm("alsijil.delete_excusetype", delete_excusetype_predicate)
# View extra mark list
view_extramarks_predicate = has_person & has_global_perm("alsijil.view_extramark")
add_perm("alsijil.view_extramarks", view_extramarks_predicate)
# Add extra mark
add_extramark_predicate = view_extramarks_predicate & has_global_perm(
"alsijil.add_extramark"
)
add_perm("alsijil.add_extramark", add_extramark_predicate)
# Edit extra mark
edit_extramark_predicate = view_extramarks_predicate & has_global_perm(
"alsijil.change_extramark"
)
add_perm("alsijil.edit_extramark", edit_extramark_predicate)
# Delete extra mark
delete_extramark_predicate = view_extramarks_predicate & has_global_perm(
"alsijil.delete_extramark"
)
add_perm("alsijil.delete_extramark", delete_extramark_predicate)
......@@ -10,6 +10,11 @@
text-decoration: line-through;
}
.alsijil-tardiness-text{
vertical-align: super;
}
@media only screen and (max-width : 992px) {
table.responsive-table.alsijil-table th,
table.responsive-table.alsijil-table td {
......@@ -17,3 +22,7 @@
vertical-align: top;
height: 109px;}
}
.alsijil-top-button {
margin-top: -20px;
}
......@@ -42,3 +42,9 @@ class ExcuseTypeTable(tables.Table):
text=_("Delete"),
attrs={"a": {"class": "btn-flat waves-effect waves-red red-text"}},
)
def before_render(self, request):
if not request.user.has_perm("alsijil.edit_excusetype"):
self.columns.hide("edit")
if not request.user.has_perm("alsijil.delete_excusetype"):
self.columns.hide("delete")