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

Merge branch '261-add-absence-management-to-course-book-student-dialog' into...

Merge branch '261-add-absence-management-to-course-book-student-dialog' into 264-add-absence-overview-page
parents 003f8836 dc851092
No related branches found
No related tags found
1 merge request!363Resolve "Add absence overview page"
Pipeline #189529 failed
<script>
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";
......@@ -15,6 +16,7 @@ export default {
components: {
AbsenceReasonChip,
AbsenceReasonGroupSelect,
AbsenceReasonButtons,
CancelButton,
LessonInformation,
MobileFullscreenDialog,
......@@ -25,6 +27,7 @@ export default {
return {
dialog: false,
search: "",
loadSelected: false,
selected: [],
isExpanded: false,
};
......@@ -42,29 +45,29 @@ export default {
},
},
methods: {
sendToServer(participation, field, value) {
sendToServer(participations, field, value) {
if (field !== "absenceReason") return;
this.mutate(
updateParticipationStatuses,
{
input: [
{
id: participation.id,
absenceReason: value === "present" ? null : value,
},
],
input: participations.map((participation) => ({
id: participation.id,
absenceReason: value === "present" ? null : value,
})),
},
(storedDocumentations, incomingStatuses) => {
const newStatus = incomingStatuses[0];
const documentation = storedDocumentations.find(
(doc) => doc.id === newStatus.relatedDocumentation.id,
(doc) => doc.id === this.documentation.id,
);
const participationStatus = documentation.participations.find(
(part) => part.id === newStatus.id,
);
participationStatus.absenceReason = newStatus.absenceReason;
participationStatus.isOptimistic = newStatus.isOptimistic;
incomingStatuses.forEach((newStatus) => {
const participationStatus = documentation.participations.find(
(part) => part.id === newStatus.id,
);
participationStatus.absenceReason = newStatus.absenceReason;
participationStatus.isOptimistic = newStatus.isOptimistic;
});
return storedDocumentations;
},
......@@ -94,6 +97,16 @@ export default {
// },
);
},
handleMultipleAction(absenceReasonId) {
this.loadSelected = true;
this.sendToServer(this.selected, "absenceReason", absenceReasonId);
this.$once("save", this.resetMultipleAction);
},
resetMultipleAction() {
this.loadSelected = false;
this.$set(this.selected, []);
this.$refs.iterator.selected = [];
},
},
};
</script>
......@@ -110,27 +123,36 @@ export default {
</template>
<template #title>
<lesson-information v-bind="documentationPartProps" />
<v-slide-x-transition leave-absolute>
<lesson-information v-bind="documentationPartProps" :compact="false" />
<v-scroll-x-transition leave-absolute>
<v-text-field
v-show="!isExpanded"
type="search"
v-model="search"
clearable
rounded
filled
hide-details
single-line
prepend-inner-icon="$search"
dense
outlined
:placeholder="$t('actions.search')"
class="pt-4"
class="pt-4 full-width"
/>
</v-slide-x-transition>
</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
ref="iterator"
v-model="selected"
:items="items"
:search="search"
......@@ -138,7 +160,9 @@ export default {
(item) => 'documentation-' + documentation.id + '-student-' + item.id
"
:is-expanded.sync="isExpanded"
:loading="loadingIndicator"
:loading="loadingIndicator || loadSelected"
:load-only-selected="loadSelected"
:disabled="loading"
>
<template #listItemContent="{ item }">
<v-list-item-title>
......@@ -167,7 +191,7 @@ export default {
empty-value="present"
:loadSelectedChip="loading"
:value="item.absenceReason?.id || 'present'"
@input="sendToServer(item, 'absenceReason', $event)"
@input="sendToServer([item], 'absenceReason', $event)"
/>
</v-card-text>
</template>
......
......@@ -12,6 +12,7 @@ mutation updateParticipationStatuses(
id
name
shortName
colour
}
}
}
......@@ -31,6 +32,7 @@ mutation touchDocumentation($documentationId: ID!) {
id
name
shortName
colour
}
isOptimistic
}
......
......@@ -76,6 +76,7 @@ query documentationsForCoursebook(
id
name
shortName
colour
}
isOptimistic
}
......
......@@ -61,7 +61,7 @@ import PersonChip from "aleksis.core/components/person/PersonChip.vue";
v-for="teacher in documentation.teachers"
:key="documentation.id + '-teacher-' + teacher.id"
:person="teacher"
no-link
:no-link="compact"
v-bind="compact ? dialogActivator.attrs : {}"
v-on="compact ? dialogActivator.on : {}"
/>
......@@ -69,7 +69,7 @@ import PersonChip from "aleksis.core/components/person/PersonChip.vue";
v-for="teacher in amendedTeachers"
:key="documentation.id + '-amendedTeacher-' + teacher.id"
:person="teacher"
no-link
:no-link="compact"
v-bind="compact ? dialogActivator.attrs : {}"
v-on="compact ? dialogActivator.on : {}"
class="text-decoration-line-through"
......
<script setup>
import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue";
</script>
<template>
<div
class="d-flex align-center justify-space-between justify-md-end flex-wrap gap"
>
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<v-chip dense color="success">
<v-chip small dense class="mr-2" color="green darken-3 white--text">
{{ documentation.participations.length }}
</v-chip>
Schüler
</v-chip>
<v-chip dense color="warning">
<v-chip small dense class="mr-2" color="orange darken-3 white--text"
>3</v-chip
>
entschuldigt
<v-chip dense color="success" outlined v-if="total > 0">
{{ $t("alsijil.coursebook.present_number", { present, total })}}
</v-chip>
<v-chip dense color="error">
<v-chip small dense class="mr-2" color="red darken-3 white--text"
>1</v-chip
>
unentschuldigt
</v-chip>
<v-chip dense color="grey lighten-1">
<v-chip small dense class="mr-2" color="grey darken-1 white--text"
>4</v-chip
>
Hausaufgaben vergessen
</v-chip>
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
<absence-reason-chip
v-for="participation in absences"
:absence-reason="participation.absenceReason"
dense
>
<template #prepend>
{{ participation.person.fullName }}:
</template>
</absence-reason-chip>
<manage-students-trigger v-bind="documentationPartProps" />
</div>
</template>
......@@ -40,6 +31,18 @@ export default {
name: "LessonNotes",
components: { ManageStudentsTrigger },
mixins: [documentationPartMixin],
computed: {
total() {
return this.documentation.participations.length;
},
present() {
return this.documentation.participations.filter(p => p.absenceReason === null).length;
},
absences() {
// Get all course attendants who have an absence reason
return this.documentation.participations.filter(p => p.absenceReason !== null);
},
},
};
</script>
......
......@@ -49,13 +49,27 @@
}
}
},
"title_plural": "Kursbuch"
"title_plural": "Kursbuch",
"present_number": "{present}/{total} anwesend"
},
"excuse_types": {
"menu_title": "Entschuldigungsarten"
},
"extra_marks": {
"menu_title": "Zusätzliche Markierungen"
"menu_title": "Zusätzliche Markierungen",
"create": "Markierung erstellen",
"name": "Markierung",
"short_name": "Abkürzung",
"colour_fg": "Schriftfarbe",
"colour_bg": "Hintergrundfarbe",
"show_in_coursebook": "In Kursbuch-Übersicht zeigen",
"show_in_coursebook_helptext": "Wenn aktiviert tauchen diese Markierungen in den Zeilen im Kursbuch auf."
},
"personal_notes": {
"note": "Notiz",
"create_personal_note": "Weitere Notiz",
"confirm_delete": "Notiz wirklich löschen?",
"confirm_delete_explanation": "Die Notiz \"{note}\" für {name} wird entfernt."
},
"group_roles": {
"menu_title_assign": "Gruppenrollen zuweisen",
......
......@@ -74,6 +74,7 @@
"courses": "Courses",
"filter_for_obj": "Filter for group and course"
},
"present_number": "{present}/{total} present",
"no_data": "No lessons for the selected groups and courses in this period",
"no_results": "No search results for {search}"
}
......
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