diff --git a/aleksis/apps/cursus/frontend/components/SubjectChip.vue b/aleksis/apps/cursus/frontend/components/SubjectChip.vue index d92ff834103440a48283f04119e5fa0db9e0c607..74634c810aa6a2cfb5d81dc4cf69add09c39ec98 100644 --- a/aleksis/apps/cursus/frontend/components/SubjectChip.vue +++ b/aleksis/apps/cursus/frontend/components/SubjectChip.vue @@ -12,6 +12,11 @@ export default { required: false, default: false, }, + prependIcon: { + type: String, + default: null, + required: false, + }, appendIcon: { type: String, default: null, @@ -28,6 +33,7 @@ export default { :color="subject.colourBg" :text-color="subject.colourFg" > + <v-icon left v-if="prependIcon">{{ prependIcon }}</v-icon> {{ shortName ? subject.shortName : subject.name }} <v-icon right v-if="appendIcon">{{ appendIcon }}</v-icon> </v-chip> diff --git a/aleksis/apps/cursus/frontend/components/TeacherField.vue b/aleksis/apps/cursus/frontend/components/TeacherField.vue new file mode 100644 index 0000000000000000000000000000000000000000..8331d02de390cd672677d362166374491df1e750 --- /dev/null +++ b/aleksis/apps/cursus/frontend/components/TeacherField.vue @@ -0,0 +1,100 @@ +<script setup> +import SubjectChip from "./SubjectChip.vue"; +</script> + +<template> + <v-autocomplete + v-bind="$attrs" + v-on="$listeners" + multiple + :items="teacherList" + item-text="fullName" + item-value="id" + :loading="$apollo.queries.persons.loading" + > + <template #item="data"> + <v-list-item-action> + <v-checkbox v-model="data.attrs.inputValue" /> + </v-list-item-action> + <v-list-item-content> + <v-list-item-title>{{ data.item.fullName }}</v-list-item-title> + <v-list-item-subtitle v-if="data.item.shortName" + >{{ data.item.shortName }} + </v-list-item-subtitle> + <v-list-item-subtitle + v-if="showSubjects && data.item.subjectsAsTeacher.length" + > + <subject-chip + v-for="subject in data.item.subjectsAsTeacher" + :key="subject.id" + :subject="subject" + :prepend-icon="subject.id === prioritySubject.id ? '$success' : ''" + :short-name="true" + x-small + class="mr-1" + /> + </v-list-item-subtitle> + </v-list-item-content> + </template> + <template #prepend-inner> + <slot name="prepend-inner" /> + </template> + <template #selection="data"> + <slot name="selection" v-bind="data" /> + </template> + </v-autocomplete> +</template> + +<script> +import { gqlTeachers } from "./helper.graphql"; + +export default { + name: "TeacherField", + data() { + return { + persons: [], + }; + }, + props: { + showSubjects: { + type: Boolean, + required: false, + default: false, + }, + prioritySubject: { + type: Object, + required: false, + default: null, + }, + }, + computed: { + teacherList() { + if (this.prioritySubject) { + let matching = []; + let nonMatching = []; + + this.persons.forEach((p) => { + if ( + p.subjectsAsTeacher.some((s) => s.id === this.prioritySubject.id) + ) { + matching.push(p); + } else { + nonMatching.push(p); + } + }); + + return matching.concat(nonMatching); + } else { + return this.persons; + } + }, + }, + apollo: { + persons: { + query: gqlTeachers, + }, + }, +}; +</script> + +<style scoped></style> diff --git a/aleksis/apps/cursus/frontend/components/helper.graphql b/aleksis/apps/cursus/frontend/components/helper.graphql index b849f56c578e3c04a4cc7d8b782ad7c55c4faa30..433ff5c0f2b8125d1cbee93a3ad7418a07b225af 100644 --- a/aleksis/apps/cursus/frontend/components/helper.graphql +++ b/aleksis/apps/cursus/frontend/components/helper.graphql @@ -12,3 +12,18 @@ query gqlGroups { name } } + +query gqlTeachers { + persons: teachers { + id + fullName + shortName + subjectsAsTeacher { + id + name + shortName + colourFg + colourBg + } + } +} diff --git a/aleksis/apps/cursus/schema.py b/aleksis/apps/cursus/schema.py index 711ddd0db21bd72c815dfd93ccfc05c27a678c7a..275ee67114e7527b40562e0999d879134fc0ecba 100644 --- a/aleksis/apps/cursus/schema.py +++ b/aleksis/apps/cursus/schema.py @@ -159,6 +159,22 @@ class CourseType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType): # return get_objects_for_user(info.context.user, "cursus.view_course", Course) +class TeacherType(GraphQLPersonType): + class Meta: + model = Person + + subjects_as_teacher = graphene.List(SubjectType) + courses_as_teacher = graphene.List(CourseType) + + @staticmethod + def resolve_subjects_as_teacher(root, info, **kwargs): + return root.subjects_as_teacher.all() + + @staticmethod + def resolve_courses_as_teacher(root, info, **kwargs): + return root.courses_as_teacher.all() + + class CourseBatchCreateMutation(DjangoBatchCreateMutation): class Meta: model = Course @@ -215,7 +231,7 @@ class Query(graphene.ObjectType): school_grades = FilterOrderList(GraphQLGroupType) school_grades_by_term = FilterOrderList(GraphQLGroupType, school_term=graphene.ID()) - teachers = FilterOrderList(GraphQLPersonType) + teachers = FilterOrderList(TeacherType) course_by_id = graphene.Field(CourseType, id=graphene.ID()) courses_of_teacher = FilterOrderList(CourseType, teacher=graphene.ID())