From 28445cf1a59584b9d6448ef870b1a44233508db8 Mon Sep 17 00:00:00 2001 From: Reto Aebersold Date: Tue, 9 Jan 2024 17:21:06 +0100 Subject: [PATCH 01/24] feat: add avatar upload --- .../src/pages/onboarding/AccountProfile.vue | 29 +++--- client/src/services/files.ts | 17 ++-- client/src/stores/user.ts | 5 ++ server/config/urls.py | 6 +- server/vbv_lernwelt/api/user.py | 16 +++- server/vbv_lernwelt/core/admin.py | 2 +- .../vbv_lernwelt/core/create_default_users.py | 89 +++++++++++-------- server/vbv_lernwelt/core/graphql/types.py | 3 + .../commands/create_default_users.py | 2 +- .../migrations/0004_auto_20240108_0943.py | 29 ++++++ server/vbv_lernwelt/core/models.py | 20 ++++- .../media_files/tests/test_user_images.py | 64 +++++++++++++ server/vbv_lernwelt/media_files/views.py | 39 ++++++++ 13 files changed, 260 insertions(+), 61 deletions(-) create mode 100644 server/vbv_lernwelt/core/migrations/0004_auto_20240108_0943.py create mode 100644 server/vbv_lernwelt/media_files/tests/test_user_images.py create mode 100644 server/vbv_lernwelt/media_files/views.py diff --git a/client/src/pages/onboarding/AccountProfile.vue b/client/src/pages/onboarding/AccountProfile.vue index 1eb9bb78..31b982b8 100644 --- a/client/src/pages/onboarding/AccountProfile.vue +++ b/client/src/pages/onboarding/AccountProfile.vue @@ -6,6 +6,7 @@ import { useUserStore } from "@/stores/user"; import { useRoute } from "vue-router"; import { useTranslation } from "i18next-vue"; import { profileNextRoute, useEntities } from "@/services/onboarding"; +import AvatarImage from "@/components/ui/AvatarImage.vue"; const { t } = useTranslation(); @@ -36,17 +37,23 @@ const validOrganisation = computed(() => { return selectedOrganisation.value.id !== 0; }); -/* TODO: We do this later (not in the first release) -const { - upload: avatarUpload, - loading: avatarLoading, - error: avatarError, - fileInfo: avatarFileInfo, -} = useFileUpload(); +const avatarError = ref(false); +const avatarLoading = ref(false); -watch(avatarFileInfo, (info) => { - console.log("fileInfo changed", info); -})*/ +async function avatarUpload(e: Event) { + const { files } = e.target as HTMLInputElement; + if (!files?.length) return; + avatarLoading.value = true; + avatarError.value = false; + + try { + await user.setUserAvatar(files[0]); + } catch (e) { + avatarError.value = true; + } finally { + avatarLoading.value = false; + } +} watch(selectedOrganisation, async (organisation) => { await user.setUserOrganisation(organisation.id); @@ -74,7 +81,6 @@ const nextRoute = computed(() => { - - - diff --git a/server/vbv_lernwelt/api/tests/test_profile.py b/server/vbv_lernwelt/api/tests/test_profile.py new file mode 100644 index 00000000..4c73b50e --- /dev/null +++ b/server/vbv_lernwelt/api/tests/test_profile.py @@ -0,0 +1,60 @@ +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APITestCase + +from vbv_lernwelt.course.creators.test_utils import ( + add_course_session_user, + create_course, + create_course_session, + create_user, +) +from vbv_lernwelt.course.models import CourseSessionUser + + +class ProfileViewTest(APITestCase): + def setUp(self) -> None: + self.course, _ = create_course("Test Course") + self.course_session = create_course_session( + course=self.course, title="Test Session" + ) + + self.user = create_user("user") + add_course_session_user( + self.course_session, + self.user, + role=CourseSessionUser.Role.MEMBER, + ) + + self.client.force_login(self.user) + + def test_user_profile(self) -> None: + # GIVEN + url = reverse( + "get_profile_view", + kwargs={ + "course_session_id": self.course_session.id, + "user_id": self.user.id, + }, + ) + + # WHEN + response = self.client.get(url) + + # THEN + self.assertEqual(response.status_code, status.HTTP_200_OK) + profile = response.data + self.assertEqual( + profile, + { + "id": str(self.user.id), + "first_name": self.user.first_name, + "last_name": self.user.last_name, + "email": self.user.email, + "username": self.user.username, + "avatar_url": "/static/avatars/myvbv-default-avatar.png", + "organisation": None, + "is_superuser": False, + "course_session_experts": [], + "language": "de", + }, + ) From f7aa5a35ca7ae2cad5cf5c8a6ba6a697000de961 Mon Sep 17 00:00:00 2001 From: Reto Aebersold Date: Mon, 15 Jan 2024 15:48:30 +0100 Subject: [PATCH 07/24] fix: wait for completion before nav --- .../learningContentPage/LearningContentParent.vue | 4 ++-- client/src/stores/circle.ts | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/client/src/pages/learningPath/learningContentPage/LearningContentParent.vue b/client/src/pages/learningPath/learningContentPage/LearningContentParent.vue index 012f966f..e33113fd 100644 --- a/client/src/pages/learningPath/learningContentPage/LearningContentParent.vue +++ b/client/src/pages/learningPath/learningContentPage/LearningContentParent.vue @@ -64,8 +64,8 @@ function handleFinishedLearningContent() { props.learningContent, props.circle, previousRoute, - (lc: LearningContentWithCompletion) => { - courseCompletionData.markCompletion(lc, "SUCCESS"); + async (lc: LearningContentWithCompletion) => { + await courseCompletionData.markCompletion(lc, "SUCCESS"); } ); } diff --git a/client/src/stores/circle.ts b/client/src/stores/circle.ts index 1bebc5db..5756c775 100644 --- a/client/src/stores/circle.ts +++ b/client/src/stores/circle.ts @@ -73,16 +73,18 @@ export const useCircleStore = defineStore({ }); } }, - continueFromLearningContent( + async continueFromLearningContent( currentLearningContent: LearningContentWithCompletion, circle: CircleType, returnRoute?: RouteLocationNormalized, - markCompletionFn?: (learningContent: LearningContentWithCompletion) => void + markCompletionFn?: ( + learningContent: LearningContentWithCompletion + ) => Promise ) { if (currentLearningContent) { if (currentLearningContent.can_user_self_toggle_course_completion) { if (markCompletionFn) { - markCompletionFn(currentLearningContent); + await markCompletionFn(currentLearningContent); } } this.closeLearningContent(currentLearningContent, circle, returnRoute); From 57f80ea1092ce50f91a7aff3b09d52693ef04cc3 Mon Sep 17 00:00:00 2001 From: Reto Aebersold Date: Thu, 18 Jan 2024 08:33:08 +0100 Subject: [PATCH 08/24] chore: format --- server/config/urls.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/config/urls.py b/server/config/urls.py index 1008ba73..56b9ad07 100644 --- a/server/config/urls.py +++ b/server/config/urls.py @@ -12,7 +12,12 @@ from django_ratelimit.exceptions import Ratelimited from graphene_django.views import GraphQLView from vbv_lernwelt.api.directory import list_entities -from vbv_lernwelt.api.user import get_cockpit_type, get_profile, me_user_view, post_avatar +from vbv_lernwelt.api.user import ( + get_cockpit_type, + get_profile, + me_user_view, + post_avatar, +) from vbv_lernwelt.assignment.views import request_assignment_completion_status from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt from vbv_lernwelt.core.schema import schema From 6de8d72e52c71c072f5a6992a4c4583b7f91a38c Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 18 Jan 2024 14:49:41 +0100 Subject: [PATCH 09/24] Fix assignment reminder user group --- server/vbv_lernwelt/notify/email/reminders/assigment.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/vbv_lernwelt/notify/email/reminders/assigment.py b/server/vbv_lernwelt/notify/email/reminders/assigment.py index 50a030c3..e3d0439e 100644 --- a/server/vbv_lernwelt/notify/email/reminders/assigment.py +++ b/server/vbv_lernwelt/notify/email/reminders/assigment.py @@ -9,6 +9,7 @@ from vbv_lernwelt.course_session.models import ( CourseSessionAssignment, CourseSessionEdoniqTest, ) +from vbv_lernwelt.learnpath.models import Circle from vbv_lernwelt.notify.services import NotificationService logger = structlog.get_logger(__name__) @@ -63,9 +64,12 @@ def send_assignment_reminder_notifications(): AssignmentType.CASEWORK.value, ], ): + circle_page = assignment.learning_content.get_parent_circle() + circle = Circle.objects.get(page_ptr=circle_page.id) for expert in CourseSessionUser.objects.filter( course_session_id=assignment.course_session.id, role=CourseSessionUser.Role.EXPERT, + expert=circle, ): sent.append( NotificationService.send_casework_expert_evaluation_reminder( From 278b6e6b64dcf3fe8f293a69bd63e38263a82063 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Wed, 10 Jan 2024 14:45:46 +0100 Subject: [PATCH 10/24] wip: mentor feedback (praxisauftrag) --- client/src/gql/gql.ts | 4 ++-- client/src/gql/graphql.ts | 4 ++-- client/src/graphql/queries.ts | 3 +++ .../AssignmentEvaluationPage.vue | 21 +++++++++---------- .../mentor/MentorPraxisAssignment.vue | 17 ++++++++++++++- .../assignment/AssignmentView.vue | 1 - client/src/services/mentorCockpit.ts | 1 + .../content/praxis_assignment.py | 1 + .../vbv_lernwelt/learning_mentor/entities.py | 1 + .../learning_mentor/serializers.py | 1 + .../learning_mentor/tests/test_assignments.py | 4 ++++ 11 files changed, 41 insertions(+), 17 deletions(-) diff --git a/client/src/gql/gql.ts b/client/src/gql/gql.ts index 2fbc4386..25a201a6 100644 --- a/client/src/gql/gql.ts +++ b/client/src/gql/gql.ts @@ -17,7 +17,7 @@ const documents = { "\n mutation UpsertAssignmentCompletion(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n $completionStatus: AssignmentCompletionStatus!\n $completionDataString: String!\n $evaluationPoints: Float\n $initializeCompletion: Boolean\n $evaluationUserId: ID\n ) {\n upsert_assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n assignment_user_id: $assignmentUserId\n completion_status: $completionStatus\n completion_data_string: $completionDataString\n evaluation_points: $evaluationPoints\n initialize_completion: $initializeCompletion\n evaluation_user_id: $evaluationUserId\n ) {\n assignment_completion {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_points\n completion_data\n task_completion_data\n }\n }\n }\n": types.UpsertAssignmentCompletionDocument, "\n fragment CoursePageFields on CoursePageInterface {\n title\n id\n slug\n content_type\n frontend_url\n }\n": types.CoursePageFieldsFragmentDoc, "\n query attendanceCheckQuery($courseSessionId: ID!) {\n course_session_attendance_course(id: $courseSessionId) {\n id\n attendance_user_list {\n user_id\n status\n }\n }\n }\n": types.AttendanceCheckQueryDocument, - "\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n }\n assignment_user {\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n": types.AssignmentCompletionQueryDocument, + "\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n }\n assignment_user {\n avatar_url\n first_name\n last_name\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n": types.AssignmentCompletionQueryDocument, "\n query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {\n competence_certificate_list(course_slug: $courseSlug) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n": types.CompetenceCertificateQueryDocument, "\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n enable_circle_documents\n circle_contact_type\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n }\n }\n": types.CourseSessionDetailDocument, "\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n enable_circle_documents\n circle_contact_type\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n evaluate_url\n ...CoursePageFields\n performance_criteria {\n ...CoursePageFields\n }\n learning_contents {\n can_user_self_toggle_course_completion\n content_url\n minutes\n description\n ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument, @@ -60,7 +60,7 @@ export function graphql(source: "\n query attendanceCheckQuery($courseSessionId /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n }\n assignment_user {\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n"): (typeof documents)["\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n }\n assignment_user {\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n"]; +export function graphql(source: "\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n }\n assignment_user {\n avatar_url\n first_name\n last_name\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n"): (typeof documents)["\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n }\n assignment_user {\n avatar_url\n first_name\n last_name\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/client/src/gql/graphql.ts b/client/src/gql/graphql.ts index f2523e64..99c7abd1 100644 --- a/client/src/gql/graphql.ts +++ b/client/src/gql/graphql.ts @@ -1131,7 +1131,7 @@ export type AssignmentCompletionQueryQueryVariables = Exact<{ export type AssignmentCompletionQueryQuery = { __typename?: 'Query', assignment?: { __typename?: 'AssignmentObjectType', assignment_type: AssignmentAssignmentAssignmentTypeChoices, needs_expert_evaluation: boolean, max_points?: number | null, content_type: string, effort_required: string, evaluation_description: string, evaluation_document_url: string, evaluation_tasks?: any | null, id: string, intro_text: string, performance_objectives?: any | null, slug: string, tasks?: any | null, title: string, translation_key: string, solution_sample?: { __typename?: 'ContentDocumentObjectType', id: string, url?: string | null } | null, competence_certificate?: ( { __typename?: 'CompetenceCertificateObjectType' } & { ' $fragmentRefs'?: { 'CoursePageFieldsCompetenceCertificateObjectTypeFragment': CoursePageFieldsCompetenceCertificateObjectTypeFragment } } - ) | null } | null, assignment_completion?: { __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: string | null, evaluation_submitted_at?: string | null, evaluation_points?: number | null, evaluation_max_points?: number | null, evaluation_passed?: boolean | null, edoniq_extended_time_flag: boolean, completion_data?: any | null, task_completion_data?: any | null, evaluation_user?: { __typename?: 'UserObjectType', id: string } | null, assignment_user: { __typename?: 'UserObjectType', id: string } } | null }; + ) | null } | null, assignment_completion?: { __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: string | null, evaluation_submitted_at?: string | null, evaluation_points?: number | null, evaluation_max_points?: number | null, evaluation_passed?: boolean | null, edoniq_extended_time_flag: boolean, completion_data?: any | null, task_completion_data?: any | null, evaluation_user?: { __typename?: 'UserObjectType', id: string } | null, assignment_user: { __typename?: 'UserObjectType', avatar_url: string, first_name: string, last_name: string, id: string } } | null }; export type CompetenceCertificateQueryQueryVariables = Exact<{ courseSlug: Scalars['String']['input']; @@ -1300,7 +1300,7 @@ export const CoursePageFieldsFragmentDoc = {"kind":"Document","definitions":[{"k export const AttendanceCheckMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AttendanceCheckMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"attendanceCourseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"attendanceUserList"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AttendanceUserInputType"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update_course_session_attendance_course_users"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"attendanceCourseId"}}},{"kind":"Argument","name":{"kind":"Name","value":"attendance_user_list"},"value":{"kind":"Variable","name":{"kind":"Name","value":"attendanceUserList"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_session_attendance_course"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attendance_user_list"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user_id"}},{"kind":"Field","name":{"kind":"Name","value":"first_name"}},{"kind":"Field","name":{"kind":"Name","value":"last_name"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const UpsertAssignmentCompletionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpsertAssignmentCompletion"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"completionStatus"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AssignmentCompletionStatus"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"completionDataString"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"evaluationPoints"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"initializeCompletion"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"evaluationUserId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"upsert_assignment_completion"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"assignment_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"assignment_user_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}}},{"kind":"Argument","name":{"kind":"Name","value":"completion_status"},"value":{"kind":"Variable","name":{"kind":"Name","value":"completionStatus"}}},{"kind":"Argument","name":{"kind":"Name","value":"completion_data_string"},"value":{"kind":"Variable","name":{"kind":"Name","value":"completionDataString"}}},{"kind":"Argument","name":{"kind":"Name","value":"evaluation_points"},"value":{"kind":"Variable","name":{"kind":"Name","value":"evaluationPoints"}}},{"kind":"Argument","name":{"kind":"Name","value":"initialize_completion"},"value":{"kind":"Variable","name":{"kind":"Name","value":"initializeCompletion"}}},{"kind":"Argument","name":{"kind":"Name","value":"evaluation_user_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"evaluationUserId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_completion"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"completion_data"}},{"kind":"Field","name":{"kind":"Name","value":"task_completion_data"}}]}}]}}]}}]} as unknown as DocumentNode; export const AttendanceCheckQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"attendanceCheckQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_session_attendance_course"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attendance_user_list"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user_id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}}]} as unknown as DocumentNode; -export const AssignmentCompletionQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"assignmentCompletionQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"needs_expert_evaluation"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"effort_required"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_description"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_document_url"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_tasks"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"intro_text"}},{"kind":"Field","name":{"kind":"Name","value":"performance_objectives"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"tasks"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"translation_key"}},{"kind":"Field","name":{"kind":"Name","value":"solution_sample"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment_completion"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"assignment_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"assignment_user_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_max_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_passed"}},{"kind":"Field","name":{"kind":"Name","value":"edoniq_extended_time_flag"}},{"kind":"Field","name":{"kind":"Name","value":"completion_data"}},{"kind":"Field","name":{"kind":"Name","value":"task_completion_data"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode; +export const AssignmentCompletionQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"assignmentCompletionQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"needs_expert_evaluation"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"effort_required"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_description"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_document_url"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_tasks"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"intro_text"}},{"kind":"Field","name":{"kind":"Name","value":"performance_objectives"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"tasks"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"translation_key"}},{"kind":"Field","name":{"kind":"Name","value":"solution_sample"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment_completion"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"assignment_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"assignment_user_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar_url"}},{"kind":"Field","name":{"kind":"Name","value":"first_name"}},{"kind":"Field","name":{"kind":"Name","value":"last_name"}},{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_max_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_passed"}},{"kind":"Field","name":{"kind":"Name","value":"edoniq_extended_time_flag"}},{"kind":"Field","name":{"kind":"Name","value":"completion_data"}},{"kind":"Field","name":{"kind":"Name","value":"task_completion_data"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode; export const CompetenceCertificateQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"competenceCertificateQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_certificate_list"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificates"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"completion"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_max_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_passed"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"circle"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode; export const CourseSessionDetailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"courseSessionDetail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_session"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"course"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"enable_circle_documents"}},{"kind":"Field","name":{"kind":"Name","value":"circle_contact_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"users"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"user_id"}},{"kind":"Field","name":{"kind":"Name","value":"first_name"}},{"kind":"Field","name":{"kind":"Name","value":"last_name"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"avatar_url"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"circles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"attendance_courses"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"location"}},{"kind":"Field","name":{"kind":"Name","value":"trainer"}},{"kind":"Field","name":{"kind":"Name","value":"due_date"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"start"}},{"kind":"Field","name":{"kind":"Name","value":"end"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content_id"}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"circle"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"submission_deadline"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"start"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_deadline"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"start"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"edoniq_tests"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"deadline"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"start"}},{"kind":"Field","name":{"kind":"Name","value":"end"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const CourseQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"courseQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"slug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"slug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"category_name"}},{"kind":"Field","name":{"kind":"Name","value":"enable_circle_documents"}},{"kind":"Field","name":{"kind":"Name","value":"circle_contact_type"}},{"kind":"Field","name":{"kind":"Name","value":"action_competences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"performance_criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_id"}},{"kind":"Field","name":{"kind":"Name","value":"learning_unit"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"evaluate_url"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_path"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"topics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"is_visible"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"circles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"goals"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"learning_sequences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"learning_units"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evaluate_url"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"performance_criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_contents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"can_user_self_toggle_course_completion"}},{"kind":"Field","name":{"kind":"Name","value":"content_url"}},{"kind":"Field","name":{"kind":"Name","value":"minutes"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentAssignmentObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentEdoniqTestObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"checkbox_text"}},{"kind":"Field","name":{"kind":"Name","value":"has_extended_time_test"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentRichTextObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"}}]}}]}}]}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode; diff --git a/client/src/graphql/queries.ts b/client/src/graphql/queries.ts index e8b6fc29..a37fc3b5 100644 --- a/client/src/graphql/queries.ts +++ b/client/src/graphql/queries.ts @@ -68,6 +68,9 @@ export const ASSIGNMENT_COMPLETION_QUERY = graphql(` id } assignment_user { + avatar_url + first_name + last_name id } evaluation_points diff --git a/client/src/pages/cockpit/assignmentEvaluationPage/AssignmentEvaluationPage.vue b/client/src/pages/cockpit/assignmentEvaluationPage/AssignmentEvaluationPage.vue index 513a66a3..08268d60 100644 --- a/client/src/pages/cockpit/assignmentEvaluationPage/AssignmentEvaluationPage.vue +++ b/client/src/pages/cockpit/assignmentEvaluationPage/AssignmentEvaluationPage.vue @@ -1,16 +1,15 @@ -
+
+ + {{ $t("a.Ergebnis bewerten") }} + + + {{ $t("a.Bewertung anzeigen") }} + +
diff --git a/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue b/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue index e6933ce8..e6a7c029 100644 --- a/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue +++ b/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue @@ -18,7 +18,6 @@ import { useRouteQuery } from "@vueuse/router"; import * as log from "loglevel"; import { computed, onMounted, ref, watchEffect } from "vue"; import { useTranslation } from "i18next-vue"; -import { bustItGetCache } from "@/fetchHelpers"; import { learningContentTypeData } from "@/utils/typeMaps"; import EvaluationSummary from "@/pages/cockpit/assignmentEvaluationPage/EvaluationSummary.vue"; diff --git a/client/src/services/mentorCockpit.ts b/client/src/services/mentorCockpit.ts index 3c6bdc76..213caa34 100644 --- a/client/src/services/mentorCockpit.ts +++ b/client/src/services/mentorCockpit.ts @@ -27,6 +27,7 @@ interface Completion { status: CompletionStatus; user_id: string; last_name: string; + url: string; } export interface PraxisAssignment { diff --git a/server/vbv_lernwelt/learning_mentor/content/praxis_assignment.py b/server/vbv_lernwelt/learning_mentor/content/praxis_assignment.py index 0e8298a8..b1746f5f 100644 --- a/server/vbv_lernwelt/learning_mentor/content/praxis_assignment.py +++ b/server/vbv_lernwelt/learning_mentor/content/praxis_assignment.py @@ -71,6 +71,7 @@ def get_assignment_completions( )[0], user_id=user.id, last_name=user.last_name, + url=f"/course/{course_session.course.slug}/cockpit/assignment/{assignment.id}/{user.id}", ) for user in sorted_participants ] diff --git a/server/vbv_lernwelt/learning_mentor/entities.py b/server/vbv_lernwelt/learning_mentor/entities.py index 6dabcc26..2b4a9a04 100644 --- a/server/vbv_lernwelt/learning_mentor/entities.py +++ b/server/vbv_lernwelt/learning_mentor/entities.py @@ -14,6 +14,7 @@ class PraxisAssignmentCompletion: status: CompletionStatus user_id: str last_name: str + url: str @dataclass diff --git a/server/vbv_lernwelt/learning_mentor/serializers.py b/server/vbv_lernwelt/learning_mentor/serializers.py index e9cb7555..20333aaf 100644 --- a/server/vbv_lernwelt/learning_mentor/serializers.py +++ b/server/vbv_lernwelt/learning_mentor/serializers.py @@ -8,6 +8,7 @@ class PraxisAssignmentCompletionSerializer(serializers.Serializer): status = serializers.SerializerMethodField() user_id = serializers.CharField() last_name = serializers.CharField() + url = serializers.CharField() @staticmethod def get_status(obj): diff --git a/server/vbv_lernwelt/learning_mentor/tests/test_assignments.py b/server/vbv_lernwelt/learning_mentor/tests/test_assignments.py index 8b096c64..b60d78cc 100644 --- a/server/vbv_lernwelt/learning_mentor/tests/test_assignments.py +++ b/server/vbv_lernwelt/learning_mentor/tests/test_assignments.py @@ -84,6 +84,10 @@ class AttendanceServicesTestCase(TestCase): for i, result in enumerate(results): self.assertEqual(result.last_name, expected_order[i]) self.assertEqual(result.status, expected_statuses[result.last_name]) + self.assertEqual( + result.url, + f"/course/test-lehrgang/cockpit/assignment/{self.assignment.id}/{result.user_id}", + ) def test_praxis_assignment_status(self): # GIVEN From 51ad79d986829bebaaed9508c0f732db3b2a6c3e Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Thu, 11 Jan 2024 14:47:50 +0100 Subject: [PATCH 11/24] wip: mentor feedback (praxisauftrag) --- .../EvaluationIntro.vue | 2 +- .../EvaluationSummary.vue | 2 +- .../EvaluationTask.vue | 2 +- .../assignment/graphql/mutations.py | 6 ++- .../vbv_lernwelt/assignment/graphql/types.py | 2 +- server/vbv_lernwelt/iam/permissions.py | 34 ++++++++++-- server/vbv_lernwelt/iam/tests/test_roles.py | 54 ++++++++++++++++++- 7 files changed, 91 insertions(+), 11 deletions(-) diff --git a/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationIntro.vue b/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationIntro.vue index 6d293307..931fb4ba 100644 --- a/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationIntro.vue +++ b/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationIntro.vue @@ -58,7 +58,7 @@ async function startEvaluation() { upsertAssignmentCompletionMutation.executeMutation({ assignmentId: props.assignment.id, courseSessionId: courseSession.value.id, - assignmentUserId: props.assignmentUser.user_id, + assignmentUserId: props.assignmentUser.id, completionStatus: "EVALUATION_IN_PROGRESS", completionDataString: JSON.stringify({}), // next line used for urql diff --git a/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationSummary.vue b/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationSummary.vue index 9f29e01a..6e7a905e 100644 --- a/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationSummary.vue +++ b/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationSummary.vue @@ -75,7 +75,7 @@ async function submitEvaluation() { upsertAssignmentCompletionMutation.executeMutation({ assignmentId: props.assignment.id, courseSessionId: courseSession.value.id, - assignmentUserId: props.assignmentUser.user_id, + assignmentUserId: props.assignmentUser.id, completionStatus: "EVALUATION_SUBMITTED", completionDataString: JSON.stringify({}), evaluationPoints: userPoints.value, diff --git a/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationTask.vue b/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationTask.vue index 1ccb03e0..e6750d3b 100644 --- a/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationTask.vue +++ b/client/src/pages/cockpit/assignmentEvaluationPage/EvaluationTask.vue @@ -91,7 +91,7 @@ async function evaluateAssignmentCompletion(completionData: AssignmentCompletion upsertAssignmentCompletionMutation.executeMutation({ assignmentId: props.assignment.id, courseSessionId: courseSession.value.id, - assignmentUserId: props.assignmentUser.user_id, + assignmentUserId: props.assignmentUser.id, completionStatus: "EVALUATION_IN_PROGRESS", completionDataString: JSON.stringify(completionData), // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/server/vbv_lernwelt/assignment/graphql/mutations.py b/server/vbv_lernwelt/assignment/graphql/mutations.py index 1e6b2ac2..7071876d 100644 --- a/server/vbv_lernwelt/assignment/graphql/mutations.py +++ b/server/vbv_lernwelt/assignment/graphql/mutations.py @@ -99,7 +99,11 @@ class AssignmentCompletionMutation(graphene.Mutation): AssignmentCompletionStatus.EVALUATION_SUBMITTED, AssignmentCompletionStatus.EVALUATION_IN_PROGRESS, ): - if not can_evaluate_assignments(info.context.user, course_session_id): + if not can_evaluate_assignments( + evaluation_user=info.context.user, + assignment_user_id=assignment_user_id, + course_session_id=course_session_id, + ): raise PermissionDenied() evaluation_data = { diff --git a/server/vbv_lernwelt/assignment/graphql/types.py b/server/vbv_lernwelt/assignment/graphql/types.py index 70efc5b6..a0dfdb8a 100644 --- a/server/vbv_lernwelt/assignment/graphql/types.py +++ b/server/vbv_lernwelt/assignment/graphql/types.py @@ -109,7 +109,7 @@ def resolve_assignment_completion( assignment_user_id = info.context.user.id if str(assignment_user_id) == str(info.context.user.id) or can_evaluate_assignments( - info.context.user, course_session_id + evaluation_user=info.context.user, assignment_user_id=assignment_user_id, course_session_id=course_session_id ): course_id = CourseSession.objects.get(id=course_session_id).course_id if has_course_access(info.context.user, course_id): diff --git a/server/vbv_lernwelt/iam/permissions.py b/server/vbv_lernwelt/iam/permissions.py index e0b0fd92..01164834 100644 --- a/server/vbv_lernwelt/iam/permissions.py +++ b/server/vbv_lernwelt/iam/permissions.py @@ -18,6 +18,9 @@ def has_course_access(user, course_id): ).exists(): return True + if LearningMentor.objects.filter(course_id=course_id, mentor=user).exists(): + return True + return CourseSessionUser.objects.filter( course_session__course_id=course_id, user=user ).exists() @@ -32,6 +35,19 @@ def has_course_session_access(user, course_session_id: int): ).exists() +def is_user_mentor(mentor: User, participant_user_id: str, course_session_id: int): + csu = CourseSessionUser.objects.filter( + course_session_id=course_session_id, user_id=participant_user_id + ).first() + + if csu is None: + return False + + return LearningMentor.objects.filter( + course_id=csu.course_session.course_id, mentor=mentor, participants=csu + ).exists() + + def is_course_session_expert(user, course_session_id: int): if user.is_superuser: return True @@ -60,21 +76,29 @@ def is_course_session_member(user, course_session_id: int | None = None): ).exists() -def can_evaluate_assignments(user, course_session_id: int): - if user.is_superuser: +def can_evaluate_assignments( + evaluation_user: User, course_session_id: int, assignment_user_id: str | None = None +): + if evaluation_user.is_superuser: return True is_supervisor = CourseSessionGroup.objects.filter( - supervisor=user, course_session__id=course_session_id + supervisor=evaluation_user, course_session__id=course_session_id ).exists() is_expert = CourseSessionUser.objects.filter( course_session_id=course_session_id, - user=user, + user=evaluation_user, role=CourseSessionUser.Role.EXPERT, ).exists() - return is_supervisor or is_expert + is_mentor = is_user_mentor( + mentor=evaluation_user, + participant_user_id=assignment_user_id, + course_session_id=course_session_id, + ) + + return is_supervisor or is_expert or is_mentor def course_sessions_for_user_qs(user): diff --git a/server/vbv_lernwelt/iam/tests/test_roles.py b/server/vbv_lernwelt/iam/tests/test_roles.py index 2cb221c6..6f77888e 100644 --- a/server/vbv_lernwelt/iam/tests/test_roles.py +++ b/server/vbv_lernwelt/iam/tests/test_roles.py @@ -8,7 +8,7 @@ from vbv_lernwelt.course.creators.test_utils import ( ) from vbv_lernwelt.course.models import CourseSessionUser from vbv_lernwelt.course_session_group.models import CourseSessionGroup -from vbv_lernwelt.iam.permissions import has_role_in_course +from vbv_lernwelt.iam.permissions import has_role_in_course, is_user_mentor from vbv_lernwelt.learning_mentor.models import LearningMentor @@ -59,6 +59,58 @@ class RoleTestCase(TestCase): # THEN self.assertTrue(has_role) + def test_is_user_mentor(self): + # GIVEN + member = create_user("member") + mentor = create_user("mentor") + + course, course_page = create_course("Test Course") + course_session = create_course_session(course=course, title=":)") + + member_csu = add_course_session_user( + course_session=course_session, + user=member, + role=CourseSessionUser.Role.MEMBER, + ) + + learning_mentor = LearningMentor.objects.create( + mentor=mentor, + course=course, + ) + + learning_mentor.participants.add(member_csu) + learning_mentor.save() + + # WHEN + is_mentor = is_user_mentor( + mentor=mentor, participant_user_id=member.id, course_id=course.id + ) + + # THEN + self.assertTrue(is_mentor) + + def test_not_is_user_mentor(self): + # GIVEN + member = create_user("member") + wanna_be_mentor = create_user("wanna_be_mentor") + + course, course_page = create_course("Test Course") + course_session = create_course_session(course=course, title=":)") + + add_course_session_user( + course_session=course_session, + user=member, + role=CourseSessionUser.Role.MEMBER, + ) + + # WHEN + is_mentor = is_user_mentor( + mentor=wanna_be_mentor, participant_user_id=member.id, course_id=course.id + ) + + # THEN + self.assertFalse(is_mentor) + def test_no_role(self): # GIVEN other_course, _ = create_course("Other Test Course") From fa2e96d220357cc6d5073bcab1f95a96279d2834 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Thu, 11 Jan 2024 14:47:55 +0100 Subject: [PATCH 12/24] wip: mentor feedback (praxisauftrag) --- .../learningContentPage/assignment/AssignmentView.vue | 1 + server/vbv_lernwelt/assignment/graphql/types.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue b/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue index e6a7c029..d24ca582 100644 --- a/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue +++ b/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue @@ -20,6 +20,7 @@ import { computed, onMounted, ref, watchEffect } from "vue"; import { useTranslation } from "i18next-vue"; import { learningContentTypeData } from "@/utils/typeMaps"; import EvaluationSummary from "@/pages/cockpit/assignmentEvaluationPage/EvaluationSummary.vue"; +import { bustItGetCache } from "@/fetchHelpers"; const { t } = useTranslation(); const courseSession = useCurrentCourseSession(); diff --git a/server/vbv_lernwelt/assignment/graphql/types.py b/server/vbv_lernwelt/assignment/graphql/types.py index a0dfdb8a..cf0267ca 100644 --- a/server/vbv_lernwelt/assignment/graphql/types.py +++ b/server/vbv_lernwelt/assignment/graphql/types.py @@ -109,7 +109,9 @@ def resolve_assignment_completion( assignment_user_id = info.context.user.id if str(assignment_user_id) == str(info.context.user.id) or can_evaluate_assignments( - evaluation_user=info.context.user, assignment_user_id=assignment_user_id, course_session_id=course_session_id + evaluation_user=info.context.user, + assignment_user_id=assignment_user_id, + course_session_id=course_session_id, ): course_id = CourseSession.objects.get(id=course_session_id).course_id if has_course_access(info.context.user, course_id): From a97ac4ec97c5f2a15bbfc340d54c5f772c389422 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Mon, 15 Jan 2024 14:06:28 +0100 Subject: [PATCH 13/24] fix: refresh mentor completions on submission --- .../mentor/MentorPraxisAssignment.vue | 19 ++++++++++--------- client/src/services/mentorCockpit.ts | 5 +++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/client/src/pages/cockpit/cockpitPage/mentor/MentorPraxisAssignment.vue b/client/src/pages/cockpit/cockpitPage/mentor/MentorPraxisAssignment.vue index ae5b75c3..12119397 100644 --- a/client/src/pages/cockpit/cockpitPage/mentor/MentorPraxisAssignment.vue +++ b/client/src/pages/cockpit/cockpitPage/mentor/MentorPraxisAssignment.vue @@ -1,8 +1,9 @@