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
......@@ -6,16 +6,30 @@ MENUS = {
"name": _("Class register"),
"url": "#",
"svg_icon": "mdi:book-open-outline",
"vuetify_icon": "mdi-book-open-outline",
"root": True,
"validators": [
"menu_generator.validators.is_authenticated",
"aleksis.core.util.core_helpers.has_person",
],
"submenu": [
{
"name": _("Coursebook"),
"url": "select_coursebook",
"svg_icon": "mdi:book-education-outline",
"vuetify_icon": "mdi-book-education-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"alsijil.view_coursebook_rule",
),
],
},
{
"name": _("Current lesson"),
"url": "lesson_period",
"svg_icon": "mdi:alarm",
"vuetify_icon": "mdi-alarm",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -27,6 +41,7 @@ MENUS = {
"name": _("Current week"),
"url": "week_view",
"svg_icon": "mdi:view-week-outline",
"vuetify_icon": "mdi-view-week-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -38,6 +53,7 @@ MENUS = {
"name": _("My groups"),
"url": "my_groups",
"svg_icon": "mdi:account-multiple-outline",
"vuetify_icon": "mdi-account-multiple-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -49,6 +65,7 @@ MENUS = {
"name": _("My overview"),
"url": "overview_me",
"svg_icon": "mdi:chart-box-outline",
"vuetify_icon": "mdi-chart-box-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -60,6 +77,7 @@ MENUS = {
"name": _("My students"),
"url": "my_students",
"svg_icon": "mdi:account-school-outline",
"vuetify_icon": "mdi-account-school-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -71,6 +89,7 @@ MENUS = {
"name": _("Assign group role"),
"url": "assign_group_role_multiple",
"svg_icon": "mdi:clipboard-account-outline",
"vuetify_icon": "mdi-clipboard-account-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -82,6 +101,7 @@ MENUS = {
"name": _("All lessons"),
"url": "all_register_objects",
"svg_icon": "mdi:format-list-text",
"vuetify_icon": "mdi-format-list-text",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -92,7 +112,8 @@ MENUS = {
{
"name": _("Register absence"),
"url": "register_absence",
"icon": "rate_review",
"svg_icon": "mdi:message-draw",
"vuetify_icon": "mdi-message-draw",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -104,6 +125,7 @@ MENUS = {
"name": _("Excuse types"),
"url": "excuse_types",
"svg_icon": "mdi:label-outline",
"vuetify_icon": "mdi-label-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -115,6 +137,7 @@ MENUS = {
"name": _("Extra marks"),
"url": "extra_marks",
"svg_icon": "mdi:label-variant-outline",
"vuetify_icon": "mdi-label-variant-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......@@ -126,6 +149,7 @@ MENUS = {
"name": _("Manage group roles"),
"url": "group_roles",
"svg_icon": "mdi:clipboard-plus-outline",
"vuetify_icon": "mdi-clipboard-plus-outline",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
......
......@@ -461,7 +461,9 @@ def generate_person_list_with_class_register_statistics(
),
tardiness=Sum("filtered_personal_notes__tardiness"),
tardiness_count=Count(
"filtered_personal_notes", filter=Q(filtered_personal_notes__tardiness__gt=0), distinct=True
"filtered_personal_notes",
filter=Q(filtered_personal_notes__tardiness__gt=0),
distinct=True,
),
)
......
......@@ -347,11 +347,13 @@ class LessonDocumentation(RegisterObjectRelatedMixin, ExtensibleModel):
homework = models.CharField(verbose_name=_("Homework"), max_length=200, blank=True)
group_note = models.CharField(verbose_name=_("Group note"), max_length=200, blank=True)
def carry_over_data(self, all_periods_of_lesson: LessonPeriod):
"""Carry over data to given periods in this lesson if data is not already set.
def carry_over_data(self, all_periods_of_lesson: LessonPeriod, force: bool):
"""Carry over data to given periods in this lesson.
Does overwrite existing data in case ``force`` is set to ``True``.
Both forms of carrying over data can be deactivated using site preferences
``alsijil__carry_over_next_periods`` and ``alsijil__allow_carry_over_same_week``
``alsijil__carry_over_next_periods`` and ``alsijil__save_lesson_documentations_by_week``
respectively.
"""
for period in all_periods_of_lesson:
......@@ -361,15 +363,15 @@ class LessonDocumentation(RegisterObjectRelatedMixin, ExtensibleModel):
changed = False
if not lesson_documentation.topic:
if not lesson_documentation.topic or force:
lesson_documentation.topic = self.topic
changed = True
if not lesson_documentation.homework:
if not lesson_documentation.homework or force:
lesson_documentation.homework = self.homework
changed = True
if not lesson_documentation.group_note:
if not lesson_documentation.group_note or force:
lesson_documentation.group_note = self.group_note
changed = True
......@@ -390,7 +392,8 @@ class LessonDocumentation(RegisterObjectRelatedMixin, ExtensibleModel):
LessonPeriod.objects.filter(
lesson=self.lesson_period.lesson,
period__weekday=self.lesson_period.period.weekday,
)
),
False,
)
super().save(*args, **kwargs)
......
......@@ -67,17 +67,11 @@ class CarryOverDataToNextPeriods(BooleanPreference):
@site_preferences_registry.register
class AllowCarryOverLessonDocumentationToCurrentWeek(BooleanPreference):
class SaveLessonDocumentationsPerWeek(BooleanPreference):
section = alsijil
name = "allow_carry_over_same_week"
name = "save_lesson_documentations_by_week"
default = False
verbose_name = _(
"Allow carrying over data from any lesson period to all other lesson \
periods with the same lesson and in the same week"
)
help_text = _(
"This will carry over data only if the data in the aforementioned periods are empty."
)
verbose_name = _("Save lesson documentations per week instead of per lesson period")
@site_preferences_registry.register
......
......@@ -204,6 +204,11 @@ view_students_list_predicate = view_my_groups_predicate & (
)
add_perm("alsijil.view_students_list_rule", view_students_list_predicate)
# View CourseBook
view_coursebook_predicate = has_person & is_teacher
add_perm("alsijil.view_coursebook_rule", view_my_students_predicate)
# View person overview
view_person_overview_predicate = has_person & (
(is_current_person & is_site_preference_set("alsijil", "view_own_personal_notes"))
......
from datetime import datetime
from django.db.models import Q
import graphene
from calendarweek import CalendarWeek
from graphene_django import DjangoObjectType
from aleksis.apps.chronos.models import Lesson
from aleksis.apps.chronos.schema import LessonType
from aleksis.apps.chronos.util.date import get_current_year
from aleksis.core.models import Group, Person
from aleksis.core.util.core_helpers import get_site_preferences, has_person
from .models import (
Event,
ExcuseType,
ExtraLesson,
ExtraMark,
LessonDocumentation,
LessonPeriod,
PersonalNote,
)
class ExcuseTypeType(DjangoObjectType):
class Meta:
model = ExcuseType
class PersonalNoteType(DjangoObjectType):
class Meta:
model = PersonalNote
class LessonDocumentationType(DjangoObjectType):
class Meta:
model = LessonDocumentation
personal_notes = graphene.List(PersonalNoteType)
date = graphene.Field(graphene.Date)
period = graphene.Field(graphene.Int)
def resolve_personal_notes(root: LessonDocumentation, info, **kwargs):
persons = Person.objects.filter(
member_of__in=Group.objects.filter(pk__in=root.register_object.get_groups().all())
)
return PersonalNote.objects.filter(
week=root.week,
year=root.year,
lesson_period=root.lesson_period,
person__in=persons,
)
def resolve_period(root: LessonDocumentation, info, **kwargs):
return root.period.period
def resolve_date(root: LessonDocumentation, info, **kwargs):
return root.date
class ExtraMarkType(DjangoObjectType):
class Meta:
model = ExtraMark
class AlsijilSitePreferencesType(graphene.ObjectType):
save_lesson_documentations_by_week = graphene.Boolean()
def resolve_save_lesson_documentations_by_week(root, info, **kwargs):
return root["alsijil__save_lesson_documentations_by_week"]
class LessonDocumentationMutation(graphene.Mutation):
class Arguments:
year = graphene.Int(required=True)
week = graphene.Int(required=True)
lesson_period_id = graphene.ID(required=False)
event_id = graphene.ID(required=False)
extra_lesson_id = graphene.ID(required=False)
lesson_documentation_id = graphene.ID(required=False)
topic = graphene.String(required=False)
homework = graphene.String(required=False)
group_note = graphene.String(required=False)
lesson_documentation = graphene.Field(LessonDocumentationType)
@classmethod
def mutate(
cls,
root,
info,
year,
week,
lesson_period_id=None,
event_id=None,
extra_lesson_id=None,
lesson_documentation_id=None,
topic=None,
homework=None,
group_note=None,
):
lesson_period = LessonPeriod.objects.filter(pk=lesson_period_id).first()
event = Event.objects.filter(pk=event_id).first()
extra_lesson = ExtraLesson.objects.filter(pk=extra_lesson_id).first()
lesson_documentation, created = LessonDocumentation.objects.get_or_create(
year=year,
week=week,
lesson_period=lesson_period,
event=event,
extra_lesson=extra_lesson,
)
if topic is not None:
lesson_documentation.topic = topic
if homework is not None:
lesson_documentation.homework = homework
if group_note is not None:
lesson_documentation.group_note = group_note
lesson_documentation.save()
if (
get_site_preferences()["alsijil__save_lesson_documentations_by_week"]
and (
lesson_documentation.topic
or lesson_documentation.homework
or lesson_documentation.group_note
)
and lesson_documentation.lesson_period
):
lesson_documentation.carry_over_data(
LessonPeriod.objects.filter(lesson=lesson_documentation.lesson_period.lesson), True
)
return LessonDocumentationMutation(lesson_documentation=lesson_documentation)
class PersonalNoteMutation(graphene.Mutation):
class Arguments:
person_id = graphene.ID(required=True)
lesson_documentation = graphene.ID(required=True)
personal_note_id = graphene.ID(required=False) # Update or create personal note
late = graphene.Int(required=False)
absent = graphene.Boolean(required=False)
excused = graphene.Boolean(required=False)
excuse_type = graphene.ID(required=False)
remarks = graphene.String(required=False)
extra_marks = graphene.List(graphene.ID, required=False)
personal_note = graphene.Field(PersonalNoteType)
@classmethod
def mutate(
cls,
root,
info,
person_id,
lesson_documentation,
personal_note_id=None,
late=None,
absent=None,
excused=None,
excuse_type=None,
remarks=None,
extra_marks=None,
):
person = Person.objects.get(pk=person_id)
lesson_documentation = LessonDocumentation.objects.get(pk=lesson_documentation)
personal_note, created = PersonalNote.objects.get_or_create(
person=person,
event=lesson_documentation.event,
extra_lesson=lesson_documentation.extra_lesson,
lesson_period=lesson_documentation.lesson_period,
week=lesson_documentation.week,
year=lesson_documentation.year,
)
if late is not None:
personal_note.late = late
if absent is not None:
personal_note.absent = absent
if excused is not None:
personal_note.excused = excused
if excuse_type is not None:
personal_note.excuse_type = ExcuseType.objects.get(pk=excuse_type)
if remarks is not None:
personal_note.remarks = remarks
if created:
personal_note.groups_of_person.set(person.member_of.all())
personal_note.save()
if extra_marks is not None:
extra_marks = ExtraMark.objects.filter(pk__in=extra_marks)
personal_note.extra_marks.set(extra_marks)
personal_note.save()
return PersonalNoteMutation(personal_note=personal_note)
class Mutation(graphene.ObjectType):
update_or_create_lesson_documentation = LessonDocumentationMutation.Field()
update_or_create_personal_note = PersonalNoteMutation.Field()
# update_personal_note = PersonalNoteMutation.Field()
class Query(graphene.ObjectType):
excuse_types = graphene.List(ExcuseTypeType)
lesson_documentations = graphene.List(LessonDocumentationType)
lesson_documentation_by_id = graphene.Field(LessonDocumentationType, id=graphene.ID())
lesson_documentations_by_lesson_id = graphene.List(LessonDocumentationType, id=graphene.ID())
coursebook_lessons = graphene.List(LessonType)
personal_notes = graphene.List(PersonalNoteType)
extra_marks = graphene.List(ExtraMarkType)
alsijil_site_preferences = graphene.Field(AlsijilSitePreferencesType)
def resolve_excuse_types(root, info, **kwargs):
# FIXME do permission stuff
return ExcuseType.objects.all()
def resolve_lesson_documentations(root, info, **kwargs):
# FIXME do permission stuff
return LessonDocumentation.objects.all().order_by(
"-year", "-week", "-lesson_period__period__weekday", "-lesson_period__period__period"
)
def resolve_lesson_documentation_by_id(root, info, id, **kwargs): # noqa
return LessonDocumentation.objects.get(id=id)
def resolve_lesson_documentations_by_lesson_id(root, info, id, **kwargs): # noqa
lesson = Lesson.objects.get(id=id)
now = datetime.now()
for equal_lesson in lesson._equal_lessons:
for planned in equal_lesson.planned_lessonperiods_datetimes:
if planned["datetime_start"] <= now:
LessonDocumentation.objects.get_or_create(
week=planned["week"],
year=planned["year"],
lesson_period=planned["lesson_period"],
) # FIXME: Queries shouldn't alter data
return LessonDocumentation.objects.filter(
lesson_period_id__in=LessonPeriod.objects.filter(
lesson__in=lesson._equal_lessons
).values_list("id", flat=True)
).order_by(
"-year", "-week", "-lesson_period__period__weekday", "-lesson_period__period__period"
)
def resolve_coursebook_lessons(root, info, **kwargs): # noqa
current_week = CalendarWeek.current_week()
current_year = get_current_year()
# Show all future and the ones of last week
last_week, last_week_year = (
(current_week - 1, current_year)
if current_week >= 2
else (CalendarWeek.get_last_week_of_year(current_year - 1).week, current_year - 1)
)
last_week_query = Q(
lesson_periods__substitutions__week=last_week,
lesson_periods__substitutions__year=last_week_year,
)
this_week_query = Q(
lesson_periods__substitutions__week__gte=current_week,
lesson_periods__substitutions__year=current_year,
)
next_years_query = Q(lesson_periods__substitutions__year__gt=current_year)
return Lesson.objects.filter(
Q(teachers=info.context.user.person) | (Q(lesson_periods__substitutions__teachers=info.context.user.person)
& (last_week_query | this_week_query | next_years_query)
)
).for_current_or_all().distinct() if has_person(info.context.user) else None
def resolve_alsijil_site_preferences(root, info, **kwargs):
return info.context.site.preferences
def resolve_personal_notes(root, info, **kwargs):
# FIXME do permission stuff
return PersonalNote.objects.all()
def resolve_extra_marks(root, info, **kwargs):
return ExtraMark.objects.all()
......@@ -17,7 +17,7 @@ from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.translation import gettext as _
from django.views import View
from django.views.decorators.cache import never_cache
from django.views.generic import DetailView
from django.views.generic import DetailView, TemplateView
import reversion
from calendarweek import CalendarWeek
......@@ -28,9 +28,20 @@ from reversion.views import RevisionMixin
from rules.contrib.views import PermissionRequiredMixin, permission_required
from aleksis.apps.chronos.managers import TimetableType
from aleksis.apps.chronos.models import Event, ExtraLesson, Holiday, LessonPeriod, TimePeriod
from aleksis.apps.chronos.models import (
Event,
ExtraLesson,
Holiday,
Lesson,
LessonPeriod,
TimePeriod,
)
from aleksis.apps.chronos.util.build import build_weekdays
from aleksis.apps.chronos.util.date import get_weeks_for_year, week_weekday_to_date
from aleksis.apps.chronos.util.date import (
get_current_year,
get_weeks_for_year,
week_weekday_to_date,
)
from aleksis.core.mixins import (
AdvancedCreateView,
AdvancedDeleteView,
......@@ -1349,3 +1360,44 @@ class AllRegisterObjectsView(PermissionRequiredMixin, View):
if self.action_form.is_valid():
self.action_form.execute()
return render(request, "alsijil/class_register/all_objects.html", context)
class SelectCoursebookView(PermissionRequiredMixin, TemplateView):
template_name = "alsijil/class_register/select_coursebook.html"
permission_required = "alsijil.view_coursebook_rule" # FIXME
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
person = self.request.user.person
current_week = CalendarWeek.current_week()
current_year = get_current_year()
# Show all future and the ones of last week
last_week, last_week_year = (
(current_week - 1, current_year)
if current_week >= 2
else (CalendarWeek.get_last_week_of_year(current_year - 1).week, current_year - 1)
)
last_week_query = Q(
lesson_periods__substitutions__week=last_week,
lesson_periods__substitutions__year=last_week_year,
)
this_week_query = Q(
lesson_periods__substitutions__week__gte=current_week,
lesson_periods__substitutions__year=current_year,
)
next_year_query = Q(lesson_periods__substitutions__year__gt=current_year)
context["lessons"] = (
Lesson.objects.filter(
Q(teachers=person)
| (
Q(lesson_periods__substitutions__teachers=person)
& (last_week_query | this_week_query | next_year_query)
)
)
.for_current_or_all()
.distinct()
)
return context
......@@ -29,9 +29,9 @@ copyright = "2019-2022 The AlekSIS team"
author = "The AlekSIS Team"
# The short X.Y version
version = "2.1"
version = "3.0"
# The full version, including alpha/beta/rc tags
release = "2.2.dev0"
release = "3.0.dev2"
# -- General configuration ---------------------------------------------------
......
[tool.poetry]
name = "AlekSIS-App-Alsijil"
version = "2.2.dev0"
version = "3.0.dev2"
packages = [
{ include = "aleksis" }
]
......@@ -22,7 +22,8 @@ authors = [
"Hangzhi Yu <yuha@katharineum.de>",
"Lloyd Meins <meinsll@katharineum.de>",
"mirabilos <thorsten.glaser@teckids.org>",
"Tom Teichler <tom.teichler@teckids.org>"
"Tom Teichler <tom.teichler@teckids.org>",
"magicfelix <felix@felix-zauberer.de>"
]
maintainers = [
"Dominik George <dominik.george@teckids.org>",
......@@ -48,9 +49,9 @@ secondary = true
[tool.poetry.dependencies]
python = "^3.9"
aleksis-core = "^2.12"
aleksis-app-chronos = "^2.2"
aleksis-app-stoelindeling = { version = "^1.0", optional = true }
aleksis-core = "^3.0.dev3"
aleksis-app-chronos = "^3.0.0.dev1"
aleksis-app-stoelindeling = { version = "^2.0.0.dev0", optional = true }
[tool.poetry.dev-dependencies]
aleksis-builddeps = "*"
......