diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue index 9bba651a8cae3cd9b2a59e63e72148e8b1155c94..9d88960352965f7436f2133e5c9fc24114e897cb 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue @@ -8,6 +8,10 @@ import MobileFullscreenDialog from "aleksis.core/components/generic/dialogs/Mobi import updateParticipationMixin from "./updateParticipationMixin.js"; import deepSearchMixin from "aleksis.core/mixins/deepSearchMixin.js"; import LessonInformation from "../documentation/LessonInformation.vue"; +import { + extendParticipationStatuses, + updateParticipationStatuses, +} from "./participationStatus.graphql"; import SlideIterator from "aleksis.core/components/generic/SlideIterator.vue"; import PersonalNotes from "../personal_notes/PersonalNotes.vue"; import ExtraMarkChip from "../../extra_marks/ExtraMarkChip.vue"; @@ -48,7 +52,8 @@ export default { num: 0, reason: "no reason", name: "nobody", - personIds: [], + participationIDs: [], + loading: false, }, }; }, @@ -70,6 +75,58 @@ export default { }, }, methods: { + sendToServer(participations, field, value) { + let fieldValue; + + if (field === "absenceReason") { + fieldValue = { + absenceReason: value === "present" ? null : value, + }; + } else if (field === "tardiness") { + fieldValue = { + tardiness: value, + }; + } else { + console.error(`Wrong field '${field}' for sendToServer`); + return; + } + + this.markAsAbsentDay.showAlert = false; + this.markAsAbsentDay.participationIDs = []; + + this.mutate( + updateParticipationStatuses, + { + input: participations.map((participation) => ({ + id: participation.id, + ...fieldValue, + })), + }, + (storedDocumentations, incomingStatuses) => { + const documentation = storedDocumentations.find( + (doc) => doc.id === this.documentation.id, + ); + + incomingStatuses.forEach((newStatus) => { + const participationStatus = documentation.participations.find( + (part) => part.id === newStatus.id, + ); + participationStatus.absenceReason = newStatus.absenceReason; + participationStatus.tardiness = newStatus.tardiness; + participationStatus.isOptimistic = newStatus.isOptimistic; + }); + + this.markAsAbsentDay.reason = incomingStatuses[0].absenceReason.name; + this.markAsAbsentDay.num = incomingStatuses.length; + + return storedDocumentations; + }, + ); + + if (field === "absenceReason" && value !== "present") { + this.$once("save", this.activateFullDayDialog); + } + }, handleMultipleAction(field, id) { this.loadSelected = true; this.sendToServer(this.selected, field, id); @@ -80,18 +137,57 @@ export default { this.$set(this.selected, []); this.$refs.iterator.selected = []; }, - activateFullDayDialog({ data: { updateParticipationStatuses: { items }}}) { - const itemIds = items.map(item => item.id); - const participations = this.documentation.participations.filter(part => itemIds.includes(part.id)); + activateFullDayDialog({ + data: { + updateParticipationStatuses: { items }, + }, + }) { + const itemIds = items.map((item) => item.id); + const participations = this.documentation.participations.filter((part) => + itemIds.includes(part.id), + ); if (this.markAsAbsentDay.num === 1) { this.markAsAbsentDay.name = participations[0].person.firstName; } - this.$set(this.markAsAbsentDay.personIds, itemIds); + this.$set(this.markAsAbsentDay, "participationIDs", itemIds); + this.markAsAbsentDay.loading = false; this.markAsAbsentDay.showAlert = true; - } + }, + markAsAbsentDayClick() { + this.markAsAbsentDay.loading = true; + + this.mutate( + extendParticipationStatuses, + { + input: this.markAsAbsentDay.participationIDs, + }, + (storedDocumentations, incomingStatuses) => { + const documentation = storedDocumentations.find( + (doc) => doc.id === this.documentation.id, + ); + + incomingStatuses.forEach((newStatus) => { + const participationStatus = documentation.participations.find( + (part) => part.id === newStatus.id, + ); + participationStatus.baseAbsence = newStatus.baseAbsence; + participationStatus.isOptimistic = newStatus.isOptimistic; + }); + + this.markAsAbsentDay.reason = "no reason"; + this.markAsAbsentDay.num = 0; + this.markAsAbsentDay.participationIDs = []; + this.markAsAbsentDay.loading = false; + + this.markAsAbsentDay.showAlert = false; + + return storedDocumentations; + }, + ); + }, }, }; </script> @@ -138,17 +234,29 @@ export default { class="mt-4 mb-0 full-width" > <div class="text-subtitle-2"> - {{ $tc("alsijil.coursebook.mark_as_absent_day.title", markAsAbsentDay.num, markAsAbsentDay) }} + {{ + $tc( + "alsijil.coursebook.mark_as_absent_day.title", + markAsAbsentDay.num, + markAsAbsentDay, + ) + }} </div> <p class="text-body-2 pa-0 ma-0" style="word-break: break-word"> - {{ $t("alsijil.coursebook.mark_as_absent_day.description", markAsAbsentDay) }} + {{ + $t( + "alsijil.coursebook.mark_as_absent_day.description", + markAsAbsentDay, + ) + }} </p> <secondary-action-button color="success" i18n-key="alsijil.coursebook.mark_as_absent_day.action_button" class="mt-2" - @click="markAsAbsentDay.showAlert = false" + :loading="markAsAbsentDay.loading" + @click="markAsAbsentDayClick" /> </message-box> </template> diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/participationStatus.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/absences/participationStatus.graphql index ce296d2b684c1f45928e1d94e8e584f7b845bb69..39eb59528c4f876eb2c75c20f187e5ded6fae2bc 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/participationStatus.graphql +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/participationStatus.graphql @@ -64,3 +64,14 @@ mutation touchDocumentation($documentationId: ID!) { } } } + +mutation extendParticipationStatuses($input: [ID]!) { + extendParticipationStatuses(input: $input) { + items: participations { + id + } + absences { + id + } + } +}