diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonInformation.vue b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonInformation.vue index a104d84425d8317091d649ce7b0b88919fdf9c52..d0675ddca80e3909ee4992f68b5dba6a2a140def 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonInformation.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/documentation/LessonInformation.vue @@ -10,25 +10,16 @@ import SubjectChipSelectField from "aleksis.apps.cursus/components/SubjectChipSe <div class="d-flex"> <documentation-status v-if="compact" v-bind="documentationPartProps" /> <div - v-if="documentation.amends?.slotNumberStart" + v-if="slotNumberStart" :class="{ 'text-h5 mr-3 d-flex flex-column justify-center slot-number': true, 'ml-2 slot-number-mobile': !largeGrid, }" > - <span - v-if=" - documentation.amends?.slotNumberStart == - documentation.amends?.slotNumberEnd - " - > - {{ documentation.amends?.slotNumberStart }}. - </span> - <span v-else> - {{ documentation.amends?.slotNumberStart }}.–{{ - documentation.amends?.slotNumberEnd - }}. + <span v-if="slotNumberStart == slotNumberEnd"> + {{ slotNumberStart }}. </span> + <span v-else> {{ slotNumberStart }}.–{{ slotNumberEnd }}. </span> </div> <div :class="{ 'text-right d-flex flex-column fit-content': largeGrid }"> <time :datetime="documentation.datetimeStart" class="text-no-wrap"> @@ -94,22 +85,14 @@ import SubjectChipSelectField from "aleksis.apps.cursus/components/SubjectChipSe }" > <person-chip - v-for="teacher in documentation.teachers" + v-for="teacher in teachersWithStatus" :key="documentation.id + '-teacher-' + teacher.id" :person="teacher" :no-link="compact" v-bind="compact ? dialogActivator.attrs : {}" v-on="compact ? dialogActivator.on : {}" - /> - <person-chip - v-for="teacher in amendedTeachers" - :key="documentation.id + '-amendedTeacher-' + teacher.id" - :person="teacher" - :no-link="compact" - v-bind="compact ? dialogActivator.attrs : {}" - v-on="compact ? dialogActivator.on : {}" - class="text-decoration-line-through" - disabled + :class="{ 'text-decoration-line-through': teacher?.removed }" + :disabled="teacher?.removed" /> </div> </div> @@ -147,16 +130,50 @@ export default { largeGrid() { return this.compact && !this.$vuetify.breakpoint.mobile; }, - amendedTeachers() { - if ( - this.documentation?.amends?.amends?.teachers && - this.documentation.amends.amends.teachers.length - ) { - return this.documentation.amends.amends.teachers.filter( - (at) => !this.documentation.teachers.includes((t) => t.id === at.id), - ); + // Group teachers by their substitution status (regular, removed) + teachersWithStatus() { + if (this.documentation?.amends?.amends) { + // Only do grouping if documentation is based on substitution and substitution + // has teachers linked with it. + if (this.documentation.teachers.length > 0) { + // IDs of teachers of amended lesson + const oldIds = this.documentation.amends.amends.teachers.map( + (teacher) => teacher.id, + ); + // IDs of teachers of new substitution lesson + const newIds = this.documentation.teachers.map( + (teacher) => teacher.id, + ); + const allTeachers = new Set( + this.documentation.amends.amends.teachers.concat( + this.documentation.teachers, + ), + ); + let teachersWithStatus = Array.from(allTeachers).map((teacher) => { + let removed = false; + if (!newIds.includes(teacher.id) && oldIds.includes(teacher.id)) { + // Mark teacher as being removed if they are only linked to the amended lesson + removed = true; + } + return { ...teacher, removed: removed }; + }); + return teachersWithStatus; + } + return this.documentation.amends.amends.teachers; + } + return this.documentation.teachers; + }, + slotNumberStart() { + if (this.documentation?.amends?.amends?.slotNumberStart) { + return this.documentation.amends.amends.slotNumberStart; + } + return this.documentation.amends?.slotNumberStart; + }, + slotNumberEnd() { + if (this.documentation?.amends?.amends?.slotNumberEnd) { + return this.documentation.amends.amends.slotNumberEnd; } - return []; + return this.documentation.amends?.slotNumberEnd; }, }, }; diff --git a/aleksis/apps/alsijil/util/predicates.py b/aleksis/apps/alsijil/util/predicates.py index 0afb920046c24e03e431950d610b2687467eb16c..41f8dbe0249bf9d27c0fd2d0231c6739e9ef0fbe 100644 --- a/aleksis/apps/alsijil/util/predicates.py +++ b/aleksis/apps/alsijil/util/predicates.py @@ -193,6 +193,7 @@ def is_lesson_event_group_owner(user: User, obj: LessonEvent): Checks whether the person linked to the user is a owner of any group (or their respective parent groups) linked to the lesson event, or a owner of any group linked to the course, if the lesson event has one. + Also checks for groups linked to the lesson being amended, if one exists. """ if obj: for g in obj.groups.all(): @@ -201,6 +202,13 @@ def is_lesson_event_group_owner(user: User, obj: LessonEvent): for pg in g.parent_groups.all(): if user.person in pg.owners.all(): return True + if obj.amends: + for g in obj.amends.groups.all(): + if user.person in g.owners.all(): + return True + for pg in g.parent_groups.all(): + if user.person in pg.owners.all(): + return True return False