Skip to content
Snippets Groups Projects
Commit 1ae099f8 authored by Hangzhi Yu's avatar Hangzhi Yu
Browse files

Merge branch 'master' into 264-add-absence-overview-page

parents fe81ec8a bd54ca82
No related branches found
No related tags found
1 merge request!363Resolve "Add absence overview page"
Pipeline #191757 failed
<template>
<mobile-fullscreen-dialog v-model="popup" persistent>
<mobile-fullscreen-dialog v-model="popup" persistent :close-button="false">
<template #activator="activator">
<fab-button
color="secondary"
......@@ -167,7 +167,7 @@ export default {
},
handleSave() {
this.cancel();
this.$toastSuccess("alsijil.coursebook.absences.success");
this.$toastSuccess(this.$t("alsijil.coursebook.absences.success"));
},
},
};
......
......@@ -2,7 +2,7 @@
import AbsenceReasonButtons from "aleksis.apps.kolego/components/AbsenceReasonButtons.vue";
import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue";
import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue";
import CancelButton from "aleksis.core/components/generic/buttons/CancelButton.vue";
import DialogCloseButton from "aleksis.core/components/generic/buttons/DialogCloseButton.vue";
import MobileFullscreenDialog from "aleksis.core/components/generic/dialogs/MobileFullscreenDialog.vue";
import updateParticipationMixin from "./updateParticipationMixin.js";
import deepSearchMixin from "aleksis.core/mixins/deepSearchMixin.js";
......@@ -23,11 +23,11 @@ export default {
AbsenceReasonGroupSelect,
AbsenceReasonButtons,
PersonalNotes,
CancelButton,
LessonInformation,
MobileFullscreenDialog,
SlideIterator,
TardinessField,
DialogCloseButton,
},
mixins: [updateParticipationMixin, deepSearchMixin],
data() {
......@@ -77,13 +77,17 @@ export default {
v-bind="$attrs"
v-on="$listeners"
v-model="dialog"
:close-button="false"
>
<template #activator="activator">
<slot name="activator" v-bind="activator" />
</template>
<template #title>
<lesson-information v-bind="documentationPartProps" :compact="false" />
<div class="d-flex full-width">
<lesson-information v-bind="documentationPartProps" :compact="false" />
<dialog-close-button @click="dialog = false" class="ml-4" />
</div>
<v-scroll-x-transition leave-absolute>
<v-text-field
v-show="!isExpanded"
......@@ -100,15 +104,6 @@ export default {
class="pt-4 full-width"
/>
</v-scroll-x-transition>
<v-scroll-x-transition>
<div v-show="selected.length > 0" class="full-width mt-4">
<absence-reason-buttons
allow-empty
empty-value="present"
@input="handleMultipleAction"
/>
</div>
</v-scroll-x-transition>
</template>
<template #content>
<slide-iterator
......@@ -212,11 +207,15 @@ export default {
</template>
<template #actions>
<cancel-button
@click="dialog = false"
i18n-key="actions.close"
v-show="$vuetify.breakpoint.mobile"
/>
<v-scroll-y-reverse-transition>
<div v-show="selected.length > 0" class="full-width">
<absence-reason-buttons
allow-empty
empty-value="present"
@input="handleMultipleAction"
/>
</div>
</v-scroll-y-reverse-transition>
</template>
</mobile-fullscreen-dialog>
</template>
......
......@@ -2,8 +2,14 @@ from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from dynamic_preferences.preferences import Section
from dynamic_preferences.types import BooleanPreference, ChoicePreference, IntegerPreference
from dynamic_preferences.types import (
BooleanPreference,
ChoicePreference,
IntegerPreference,
ModelMultipleChoicePreference,
)
from aleksis.core.models import GroupType
from aleksis.core.registries import person_preferences_registry, site_preferences_registry
alsijil = Section("alsijil", verbose_name=_("Class register"))
......@@ -181,3 +187,19 @@ class AllowEditFutureDocumentations(ChoicePreference):
),
)
verbose_name = _("Set time range for which documentations may be edited")
@site_preferences_registry.register
class GroupTypesRegisterAbsence(ModelMultipleChoicePreference):
section = alsijil
name = "group_types_register_absence"
required = False
default = []
model = GroupType
verbose_name = _(
"User is allowed to register absences for members "
"of groups the user is an owner of with these group types"
)
help_text = _(
"If you leave it empty, all member of groups the user is an owner of will be shown."
)
......@@ -14,6 +14,8 @@ from .util.predicates import (
can_edit_documentation,
can_edit_participation_status,
can_edit_personal_note,
can_register_absence_for_at_least_one_group,
can_register_absence_for_person,
can_view_any_documentation,
can_view_documentation,
can_view_participation_status,
......@@ -171,12 +173,12 @@ add_perm("alsijil.view_week_personalnote_rule", view_week_personal_notes_predica
# Register absence
view_register_absence_predicate = has_person & (
is_person_group_owner | has_global_perm("alsijil.register_absence")
can_register_absence_for_at_least_one_group | has_global_perm("alsijil.register_absence")
)
add_perm("alsijil.view_register_absence_rule", view_register_absence_predicate)
register_absence_predicate = has_person & (
is_group_owner
can_register_absence_for_person
| has_global_perm("alsijil.register_absence")
| has_object_perm("core.register_absence_person")
| has_person_group_object_perm("core.register_absence_group")
......
......@@ -12,7 +12,7 @@ from aleksis.core.models import Group, Person
from aleksis.core.schema.base import FilterOrderList
from aleksis.core.schema.group import GroupType
from aleksis.core.schema.person import PersonType
from aleksis.core.util.core_helpers import has_person
from aleksis.core.util.core_helpers import get_site_preferences, has_person
from ..models import Documentation
from .absences import (
......@@ -177,7 +177,15 @@ class Query(graphene.ObjectType):
@staticmethod
def resolve_absence_creation_persons(root, info, **kwargs):
if not info.context.user.has_perm("alsijil.register_absence"):
return Person.objects.filter(member_of__owners=info.context.user.person)
group_types = get_site_preferences()["alsijil__group_types_register_absence"]
if group_types:
return Person.objects.filter(
member_of__in=Group.objects.filter(
owners=info.context.user.person, group_type__in=group_types
)
)
else:
return Person.objects.filter(member_of__owners=info.context.user.person)
return Person.objects.all()
@staticmethod
......
......@@ -103,6 +103,26 @@ def is_person_group_owner(user: User, obj) -> bool:
return Group.objects.filter(owners=user.person).exists()
@predicate
def can_register_absence_for_at_least_one_group(user: User, obj) -> bool:
"""Predicate for registering absence for at least one group."""
group_types = get_site_preferences()["alsijil__group_types_register_absence"]
qs = Group.objects.filter(owners=user.person)
if not group_types:
return qs.exists()
return qs.filter(group_type__in=group_types).exists()
@predicate
def can_register_absence_for_person(user: User, obj: Person) -> bool:
"""Predicate for registering absence for person."""
group_types = get_site_preferences()["alsijil__group_types_register_absence"]
qs = obj.member_of.filter(owners=user.person)
if not group_types:
return qs.exists()
return qs.filter(group_type__in=group_types).exists()
def use_prefetched(obj, attr):
prefetched_attr = f"{attr}_prefetched"
if hasattr(obj, prefetched_attr):
......
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