From ef3e6a8f0dbbb71cd648a605894cb15a052371c0 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Thu, 29 Feb 2024 17:33:52 +0100 Subject: [PATCH 01/11] cherry-pick workaround for flaky test in CI --- cypress/e2e/circle.cy.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cypress/e2e/circle.cy.js b/cypress/e2e/circle.cy.js index 98d41b73..591d95f0 100644 --- a/cypress/e2e/circle.cy.js +++ b/cypress/e2e/circle.cy.js @@ -45,6 +45,12 @@ describe("circle.cy.js", () => { cy.get('[data-cy="complete-and-continue"]').click({ force: true }); cy.get('[data-cy="circle-title"]').should("contain", "Fahrzeug"); + // workaround for flaky test in CI: + // for some strange reason, locally we don't have to do this + // but in CI if we don't do this, the next click will not work... + // => it's not great but this workaround at least gives us a stable test + cy.visit("/course/test-lehrgang/learn/fahrzeug"); + cy.get('[data-cy="ls-continue-button"]').click(); cy.get('[data-cy="lc-title"]').should( "contain", From cfa34507043515cfa2d8a73040dd998474f20571 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Mon, 4 Mar 2024 17:59:50 +0100 Subject: [PATCH 02/11] feat: comp.navi. in cockpit profile page --- .../SelfEvaluationAndFeedbackOverview.vue | 132 ++++++++++++++++++ ...pitProfileCompetenceFeedbackEvaluation.vue | 14 ++ .../CockpitProfileCompetenceOverview.vue | 13 ++ .../profilePage/CockpitUserProfilePage.vue | 1 + .../profilePage/CompetenceProfilePage.vue | 55 ++++++++ .../pages/competence/CompetenceIndexPage.vue | 124 +--------------- .../SelfEvaluationAndFeedbackPage.vue | 4 +- client/src/router/index.ts | 7 + client/src/services/selfEvaluationFeedback.ts | 5 +- server/vbv_lernwelt/iam/permissions.py | 2 +- .../tests/test_api.py | 63 +++++++-- .../self_evaluation_feedback/urls.py | 14 +- .../self_evaluation_feedback/views.py | 19 ++- 13 files changed, 315 insertions(+), 138 deletions(-) create mode 100644 client/src/components/cockpit/SelfEvaluationAndFeedbackOverview.vue create mode 100644 client/src/components/cockpit/profile/CockpitProfileCompetenceFeedbackEvaluation.vue create mode 100644 client/src/components/cockpit/profile/CockpitProfileCompetenceOverview.vue create mode 100644 client/src/pages/cockpit/profilePage/CompetenceProfilePage.vue diff --git a/client/src/components/cockpit/SelfEvaluationAndFeedbackOverview.vue b/client/src/components/cockpit/SelfEvaluationAndFeedbackOverview.vue new file mode 100644 index 00000000..60051b54 --- /dev/null +++ b/client/src/components/cockpit/SelfEvaluationAndFeedbackOverview.vue @@ -0,0 +1,132 @@ + + + + + diff --git a/client/src/components/cockpit/profile/CockpitProfileCompetenceFeedbackEvaluation.vue b/client/src/components/cockpit/profile/CockpitProfileCompetenceFeedbackEvaluation.vue new file mode 100644 index 00000000..2f1bb0e3 --- /dev/null +++ b/client/src/components/cockpit/profile/CockpitProfileCompetenceFeedbackEvaluation.vue @@ -0,0 +1,14 @@ + + + + + diff --git a/client/src/components/cockpit/profile/CockpitProfileCompetenceOverview.vue b/client/src/components/cockpit/profile/CockpitProfileCompetenceOverview.vue new file mode 100644 index 00000000..8ee67a04 --- /dev/null +++ b/client/src/components/cockpit/profile/CockpitProfileCompetenceOverview.vue @@ -0,0 +1,13 @@ + + + + + diff --git a/client/src/pages/cockpit/profilePage/CockpitUserProfilePage.vue b/client/src/pages/cockpit/profilePage/CockpitUserProfilePage.vue index e06f7f96..fe9c24a6 100644 --- a/client/src/pages/cockpit/profilePage/CockpitUserProfilePage.vue +++ b/client/src/pages/cockpit/profilePage/CockpitUserProfilePage.vue @@ -14,6 +14,7 @@ const { t } = useTranslation(); const pages = ref([ { label: t("general.learningPath"), route: "cockpitProfileLearningPath" }, + { label: t("a.KompetenzNavi"), route: "cockpitProfileCompetence" }, ]); const courseSession = useCurrentCourseSession(); diff --git a/client/src/pages/cockpit/profilePage/CompetenceProfilePage.vue b/client/src/pages/cockpit/profilePage/CompetenceProfilePage.vue new file mode 100644 index 00000000..be9170f1 --- /dev/null +++ b/client/src/pages/cockpit/profilePage/CompetenceProfilePage.vue @@ -0,0 +1,55 @@ + + + diff --git a/client/src/pages/competence/CompetenceIndexPage.vue b/client/src/pages/competence/CompetenceIndexPage.vue index 34c5cd74..38605bbd 100644 --- a/client/src/pages/competence/CompetenceIndexPage.vue +++ b/client/src/pages/competence/CompetenceIndexPage.vue @@ -10,8 +10,9 @@ import { assignmentsUserPoints, competenceCertificateProgressStatusCount, } from "@/pages/competence/utils"; -import { useSelfEvaluationFeedbackSummaries } from "@/services/selfEvaluationFeedback"; import ItProgress from "@/components/ui/ItProgress.vue"; +import SelfEvaluationAndFeedbackOverview from "@/components/cockpit/SelfEvaluationAndFeedbackOverview.vue"; +import { useUserStore } from "@/stores/user"; const props = defineProps<{ courseSlug: string; @@ -48,24 +49,9 @@ const userPointsEvaluatedAssignments = computed(() => { return assignmentsUserPoints(allAssignments.value); }); -const selfEvaluationFeedbackSummaries = useSelfEvaluationFeedbackSummaries( - useCurrentCourseSession().value.id -); - -const selfAssessmentCounts = computed( - () => selfEvaluationFeedbackSummaries.aggregates.value?.self_assessment -); - -const feedbackEvaluationCounts = computed( - () => selfEvaluationFeedbackSummaries.aggregates.value?.feedback_assessment -); - const currentCourseSession = useCurrentCourseSession(); -const isLoaded = computed( - () => - !selfEvaluationFeedbackSummaries.loading.value && !certificatesQuery.fetching.value -); +const isLoaded = computed(() => !certificatesQuery.fetching.value); diff --git a/client/src/pages/competence/SelfEvaluationAndFeedbackPage.vue b/client/src/pages/competence/SelfEvaluationAndFeedbackPage.vue index 9e649a4d..6f210ff6 100644 --- a/client/src/pages/competence/SelfEvaluationAndFeedbackPage.vue +++ b/client/src/pages/competence/SelfEvaluationAndFeedbackPage.vue @@ -5,9 +5,11 @@ import { computed, ref } from "vue"; import FeedbackByLearningUnitSummary from "@/components/selfEvaluationFeedback/FeedbackByLearningUnitSummary.vue"; import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue"; import { t } from "i18next"; +import { useUserStore } from "@/stores/user"; const selfEvaluationFeedbackSummaries = useSelfEvaluationFeedbackSummaries( - useCurrentCourseSession().value.id + useCurrentCourseSession().value.id, + useUserStore().id ); const courseSession = useCurrentCourseSession(); diff --git a/client/src/router/index.ts b/client/src/router/index.ts index 3a46207c..7fdd3bac 100644 --- a/client/src/router/index.ts +++ b/client/src/router/index.ts @@ -257,6 +257,13 @@ const router = createRouter({ props: true, name: "cockpitProfileLearningPath", }, + { + path: "competence", + component: () => + import("@/pages/cockpit/profilePage/CompetenceProfilePage.vue"), + props: true, + name: "cockpitProfileCompetence", + }, ], }, { diff --git a/client/src/services/selfEvaluationFeedback.ts b/client/src/services/selfEvaluationFeedback.ts index 7908ca43..c2f4b8d6 100644 --- a/client/src/services/selfEvaluationFeedback.ts +++ b/client/src/services/selfEvaluationFeedback.ts @@ -165,7 +165,8 @@ export function useSelfEvaluationFeedback( } export function useSelfEvaluationFeedbackSummaries( - courseSessionId: Ref | string + courseSessionId: Ref | string, + userId: Ref | string ) { const summaries = ref([]); const aggregates = ref(); @@ -175,7 +176,7 @@ export function useSelfEvaluationFeedbackSummaries( const url = computed( () => - `/api/self-evaluation-feedback/requester/${courseSessionId}/feedbacks/summaries` + `/api/self-evaluation-feedback/feedbacks/summaries/course-session/${courseSessionId}/user/${userId}` ); const fetchFeedbackSummaries = async () => { diff --git a/server/vbv_lernwelt/iam/permissions.py b/server/vbv_lernwelt/iam/permissions.py index 69323f8b..bf4b136e 100644 --- a/server/vbv_lernwelt/iam/permissions.py +++ b/server/vbv_lernwelt/iam/permissions.py @@ -209,7 +209,7 @@ def can_view_course_completions( user: User, course_session_id: int, target_user_id: str ) -> bool: return ( - user.id == target_user_id + str(user.id) == target_user_id or is_course_session_expert(user=user, course_session_id=course_session_id) or is_user_mentor( mentor=user, diff --git a/server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py b/server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py index 526df344..5c9772d3 100644 --- a/server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py +++ b/server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py @@ -295,8 +295,8 @@ class SelfEvaluationFeedbackAPI(APITestCase): # WHEN response = self.client.get( reverse( - "get_self_evaluation_feedbacks_as_requester", - args=[self.course_session.id], + "get_course_session_user_feedback_summaries", + args=[self.course_session.id, self.member.id], ) ) @@ -358,8 +358,8 @@ class SelfEvaluationFeedbackAPI(APITestCase): # WHEN response = self.client.get( reverse( - "get_self_evaluation_feedbacks_as_requester", - args=[self.course_session.id], + "get_course_session_user_feedback_summaries", + args=[self.course_session.id, self.member.id], ) ) @@ -393,8 +393,8 @@ class SelfEvaluationFeedbackAPI(APITestCase): # WHEN response = self.client.get( reverse( - "get_self_evaluation_feedbacks_as_requester", - args=[self.course_session.id], + "get_course_session_user_feedback_summaries", + args=[self.course_session.id, self.member.id], ) ) @@ -406,6 +406,53 @@ class SelfEvaluationFeedbackAPI(APITestCase): self.assertEqual(result["self_assessment"]["counts"]["fail"], 0) self.assertEqual(result["self_assessment"]["counts"]["unknown"], 1) + def test_permission_feedback_summaries(self): + # GIVEN + learning_unit = create_learning_unit( # noqa + course=self.course, + circle=self.circle, + ) + + create_performance_criteria_page( + course=self.course, + course_page=self.course_page, + circle=self.circle, + learning_unit=learning_unit, + ) + + expert = create_user("expert") + add_course_session_user( + course_session=self.course_session, + user=expert, + role=CourseSessionUser.Role.EXPERT, + ) + + fellow_member = create_user("fellow_member") + add_course_session_user( + course_session=self.course_session, + user=fellow_member, + role=CourseSessionUser.Role.MEMBER, + ) + + # WHEN / THEN + test_cases = [ + (self.member, self.member, 200), + (self.mentor, self.member, 200), + (expert, self.member, 200), + (fellow_member, self.member, 403), + ] + + for principle_user, target_user, expected_status_code in test_cases: + with self.subTest(principle_user=principle_user, target_user=target_user): + self.client.force_login(principle_user) + response = self.client.get( + reverse( + "get_course_session_user_feedback_summaries", + args=[self.course_session.id, target_user.id], + ) + ) + self.assertEqual(response.status_code, expected_status_code) + def test_feedbacks_metadata(self): # GIVEN learning_unit = create_learning_unit( # noqa @@ -425,8 +472,8 @@ class SelfEvaluationFeedbackAPI(APITestCase): # WHEN response = self.client.get( reverse( - "get_self_evaluation_feedbacks_as_requester", - args=[self.course_session.id], + "get_course_session_user_feedback_summaries", + args=[self.course_session.id, self.member.id], ) ) diff --git a/server/vbv_lernwelt/self_evaluation_feedback/urls.py b/server/vbv_lernwelt/self_evaluation_feedback/urls.py index 856a802f..77b6d8ec 100644 --- a/server/vbv_lernwelt/self_evaluation_feedback/urls.py +++ b/server/vbv_lernwelt/self_evaluation_feedback/urls.py @@ -2,20 +2,15 @@ from django.urls import path from vbv_lernwelt.self_evaluation_feedback.views import ( add_provider_self_evaluation_feedback, + get_course_session_user_feedback_summaries, get_self_evaluation_feedback_as_provider, get_self_evaluation_feedback_as_requester, - get_self_evaluation_feedbacks_as_requester, release_provider_self_evaluation_feedback, start_self_evaluation_feedback, ) urlpatterns = [ # /requester/* URLs -> For the user who requests feedback - path( - "requester//feedbacks/summaries", - get_self_evaluation_feedbacks_as_requester, - name="get_self_evaluation_feedbacks_as_requester", - ), path( "requester//feedback/start", start_self_evaluation_feedback, @@ -42,4 +37,11 @@ urlpatterns = [ add_provider_self_evaluation_feedback, name="add_self_evaluation_feedback_assessment", ), + # route to get feedback summaries for a user in a course session + # used by different roles to retrieve feedback summaries for a user + path( + "feedbacks/summaries/course-session//user/", + get_course_session_user_feedback_summaries, + name="get_course_session_user_feedback_summaries", + ), ] diff --git a/server/vbv_lernwelt/self_evaluation_feedback/views.py b/server/vbv_lernwelt/self_evaluation_feedback/views.py index 78dbf2b9..5deea687 100644 --- a/server/vbv_lernwelt/self_evaluation_feedback/views.py +++ b/server/vbv_lernwelt/self_evaluation_feedback/views.py @@ -8,6 +8,7 @@ from rest_framework.response import Response from vbv_lernwelt.core.models import User from vbv_lernwelt.core.serializers import UserSerializer from vbv_lernwelt.course.models import CourseCompletion, CourseSession +from vbv_lernwelt.iam.permissions import can_view_course_completions from vbv_lernwelt.learning_mentor.models import LearningMentor from vbv_lernwelt.learnpath.models import Circle, LearningUnit from vbv_lernwelt.notify.services import NotificationService @@ -91,8 +92,18 @@ def get_self_evaluation_feedback_as_provider(request, learning_unit_id): @api_view(["GET"]) @permission_classes([IsAuthenticated]) -def get_self_evaluation_feedbacks_as_requester(request, course_session_id: int): +def get_course_session_user_feedback_summaries( + request, course_session_id: int, user_id: str +): course_session = get_object_or_404(CourseSession, id=course_session_id) + user_to_lookup = get_object_or_404(User, id=user_id) + + if not can_view_course_completions( + user=get_object_or_404(User, id=user_id), + course_session_id=course_session_id, + target_user_id=user_id, + ): + raise PermissionDenied() results = [] circle_ids = set() @@ -114,7 +125,7 @@ def get_self_evaluation_feedbacks_as_requester(request, course_session_id: int): feedback = SelfEvaluationFeedback.objects.filter( learning_unit=learning_unit, - feedback_requester_user=request.user, + feedback_requester_user=user_to_lookup, ).first() if not feedback: @@ -135,7 +146,9 @@ def get_self_evaluation_feedbacks_as_requester(request, course_session_id: int): }, } - self_assessment_counts = get_self_assessment_counts(learning_unit, request.user) + self_assessment_counts = get_self_assessment_counts( + learning_unit=learning_unit, user=user_to_lookup + ) all_self_assessment_counts.append(self_assessment_counts) results.append( From 61063d9604ffb7a4f17b5e66001516429a4c5dc0 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Tue, 5 Mar 2024 13:39:17 +0100 Subject: [PATCH 03/11] fix: user_id is uuid --- server/vbv_lernwelt/course/views.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/vbv_lernwelt/course/views.py b/server/vbv_lernwelt/course/views.py index a5b8ce2b..06e37ab5 100644 --- a/server/vbv_lernwelt/course/views.py +++ b/server/vbv_lernwelt/course/views.py @@ -1,3 +1,5 @@ +import uuid + import structlog from django.shortcuts import get_object_or_404 from rest_framework.decorators import api_view @@ -75,9 +77,13 @@ def request_course_completion(request, course_session_id): @api_view(["GET"]) -def request_course_completion_for_user(request, course_session_id, user_id): +def request_course_completion_for_user( + request, course_session_id: int, user_id: uuid.UUID +): if can_view_course_completions( - user=request.user, course_session_id=course_session_id, target_user_id=user_id + user=request.user, # noqa + course_session_id=course_session_id, + target_user_id=str(user_id), ): return _request_course_completion(course_session_id, user_id) raise PermissionDenied() From 8ee64d52ae920e39c2f5b132c661bc6c7c8f64e0 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Tue, 5 Mar 2024 14:36:14 +0100 Subject: [PATCH 04/11] fix: test case for principle_user accessing target_user --- server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py | 2 ++ server/vbv_lernwelt/self_evaluation_feedback/views.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py b/server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py index 5c9772d3..721d8fb3 100644 --- a/server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py +++ b/server/vbv_lernwelt/self_evaluation_feedback/tests/test_api.py @@ -436,6 +436,8 @@ class SelfEvaluationFeedbackAPI(APITestCase): # WHEN / THEN test_cases = [ + # principle_user wants to access target_user + # -> expected_status_code (self.member, self.member, 200), (self.mentor, self.member, 200), (expert, self.member, 200), diff --git a/server/vbv_lernwelt/self_evaluation_feedback/views.py b/server/vbv_lernwelt/self_evaluation_feedback/views.py index 5deea687..7d99cdb5 100644 --- a/server/vbv_lernwelt/self_evaluation_feedback/views.py +++ b/server/vbv_lernwelt/self_evaluation_feedback/views.py @@ -99,7 +99,7 @@ def get_course_session_user_feedback_summaries( user_to_lookup = get_object_or_404(User, id=user_id) if not can_view_course_completions( - user=get_object_or_404(User, id=user_id), + user=request.user, # noqa course_session_id=course_session_id, target_user_id=user_id, ): From 1ab656671637db4090138694055f694638830fd5 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Tue, 5 Mar 2024 16:58:52 +0100 Subject: [PATCH 05/11] fix: be more permissive on mark completion only let the request.user mark his completions... --- server/vbv_lernwelt/course/views.py | 6 +++++- server/vbv_lernwelt/iam/permissions.py | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/server/vbv_lernwelt/course/views.py b/server/vbv_lernwelt/course/views.py index 06e37ab5..abb1d6d6 100644 --- a/server/vbv_lernwelt/course/views.py +++ b/server/vbv_lernwelt/course/views.py @@ -25,6 +25,7 @@ from vbv_lernwelt.iam.permissions import ( has_course_access, has_course_access_by_page_request, is_circle_expert, + can_mark_course_completion, ) from vbv_lernwelt.learning_mentor.models import LearningMentor @@ -97,7 +98,10 @@ def mark_course_completion_view(request): course_session_id = request.data.get("course_session_id") page = Page.objects.get(id=page_id) - if not has_course_access_by_page_request(request, page): + if not can_mark_course_completion( + user=request.user, # noqa + course_session_id=course_session_id, + ): raise PermissionDenied() mark_course_completion( diff --git a/server/vbv_lernwelt/iam/permissions.py b/server/vbv_lernwelt/iam/permissions.py index bf4b136e..833fc197 100644 --- a/server/vbv_lernwelt/iam/permissions.py +++ b/server/vbv_lernwelt/iam/permissions.py @@ -9,6 +9,10 @@ def has_course_access_by_page_request(request, obj): return has_course_access(request.user, obj.specific.get_course().id) +def can_mark_course_completion(user: User, course_session_id: int) -> bool: + return is_course_session_member(user, course_session_id) + + def has_course_access(user, course_id): if user.is_superuser: return True From 7073beee490c0b4b818f3b352afc7ae830dcae7d Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Wed, 6 Mar 2024 10:00:36 +0100 Subject: [PATCH 06/11] fix: make SelfEvaluation.vue preview-friendly --- .../learningPath/SelfEvaluation.vue | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/client/src/components/learningPath/SelfEvaluation.vue b/client/src/components/learningPath/SelfEvaluation.vue index 6f5534a7..ca8f41cc 100644 --- a/client/src/components/learningPath/SelfEvaluation.vue +++ b/client/src/components/learningPath/SelfEvaluation.vue @@ -1,6 +1,11 @@ - - - - diff --git a/client/src/components/cockpit/profile/CockpitProfileCompetenceOverview.vue b/client/src/components/cockpit/profile/CockpitProfileCompetenceOverview.vue deleted file mode 100644 index 8ee67a04..00000000 --- a/client/src/components/cockpit/profile/CockpitProfileCompetenceOverview.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - - - diff --git a/client/src/components/selfEvaluationFeedback/FeedbackByLearningUnitSummary.vue b/client/src/components/selfEvaluationFeedback/FeedbackByLearningUnitSummary.vue index 7939e216..13a7d9ca 100644 --- a/client/src/components/selfEvaluationFeedback/FeedbackByLearningUnitSummary.vue +++ b/client/src/components/selfEvaluationFeedback/FeedbackByLearningUnitSummary.vue @@ -32,7 +32,7 @@ const feedbackProviderName = computed(() => { {{ props.summary.title }} Circle «{{ props.summary.circle_title }}» - + {
{{ $t("a.Deine Selbsteinschätzung") }}
-
+
-
-
-
-
{
-
+
-
-
-
-
{ diff --git a/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackList.vue b/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackList.vue new file mode 100644 index 00000000..00ad9135 --- /dev/null +++ b/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackList.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/client/src/components/cockpit/SelfEvaluationAndFeedbackOverview.vue b/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue similarity index 97% rename from client/src/components/cockpit/SelfEvaluationAndFeedbackOverview.vue rename to client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue index 60051b54..1dafa970 100644 --- a/client/src/components/cockpit/SelfEvaluationAndFeedbackOverview.vue +++ b/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue @@ -4,15 +4,15 @@ import { useSelfEvaluationFeedbackSummaries } from "@/services/selfEvaluationFee import { useCurrentCourseSession } from "@/composables"; const props = defineProps<{ - targetUserId: string; - detailUrl: string; + profileUserId: string; + detailUrl?: string; }>(); const courseSession = useCurrentCourseSession(); const selfEvaluationFeedbackSummaries = useSelfEvaluationFeedbackSummaries( useCurrentCourseSession().value.id, - props.targetUserId + props.profileUserId ); const selfAssessmentCounts = computed( @@ -78,7 +78,7 @@ const isLoaded = computed(() => !selfEvaluationFeedbackSummaries.loading.value);

{{ $t("a.Fremdeinschätzungen") }} @@ -116,7 +116,7 @@ const isLoaded = computed(() => !selfEvaluationFeedbackSummaries.loading.value);

-
+
import CockpitProfileContent from "@/components/cockpit/profile/CockpitProfileContent.vue"; import { ref } from "vue"; -import CockpitProfileCompetenceOverview from "@/components/cockpit/profile/CockpitProfileCompetenceOverview.vue"; -import CockpitProfileCompetenceFeedbackEvaluation from "@/components/cockpit/profile/CockpitProfileCompetenceFeedbackEvaluation.vue"; -import { useCurrentCourseSession } from "@/composables"; +import SelfEvaluationAndFeedbackList from "@/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackList.vue"; +import SelfEvaluationAndFeedbackOverview from "@/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue"; + +type SubMenuType = "OVERVIEW" | "DETAILS"; const props = defineProps<{ userId: string; courseSlug: string; }>(); -type SubMenuType = "OVERVIEW" | "EVALUATION"; - interface SubMenuItem { type: SubMenuType; label: string; @@ -19,11 +18,9 @@ interface SubMenuItem { const MENU_ENTRIES: SubMenuItem[] = [ { type: "OVERVIEW", label: "a.Übersicht" }, - { type: "EVALUATION", label: "a.Selbst- und Fremdeinschätzungen" }, + { type: "DETAILS", label: "a.Selbst- und Fremdeinschätzungen" }, ]; -const currentCourseSession = useCurrentCourseSession(); - const active = ref(MENU_ENTRIES[0]); @@ -41,13 +38,13 @@ const active = ref(MENU_ENTRIES[0]);
diff --git a/client/src/pages/competence/CompetenceIndexPage.vue b/client/src/pages/competence/CompetenceIndexPage.vue index 38605bbd..6823addd 100644 --- a/client/src/pages/competence/CompetenceIndexPage.vue +++ b/client/src/pages/competence/CompetenceIndexPage.vue @@ -11,7 +11,7 @@ import { competenceCertificateProgressStatusCount, } from "@/pages/competence/utils"; import ItProgress from "@/components/ui/ItProgress.vue"; -import SelfEvaluationAndFeedbackOverview from "@/components/cockpit/SelfEvaluationAndFeedbackOverview.vue"; +import SelfEvaluationAndFeedbackOverview from "@/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue"; import { useUserStore } from "@/stores/user"; const props = defineProps<{ @@ -132,7 +132,7 @@ const isLoaded = computed(() => !certificatesQuery.fetching.value);
diff --git a/client/src/pages/competence/SelfEvaluationAndFeedbackPage.vue b/client/src/pages/competence/SelfEvaluationAndFeedbackPage.vue index 6f210ff6..8d7b92d9 100644 --- a/client/src/pages/competence/SelfEvaluationAndFeedbackPage.vue +++ b/client/src/pages/competence/SelfEvaluationAndFeedbackPage.vue @@ -1,71 +1,12 @@ From 53b2b77472bb6bfd5627816f21252b0f11747bfd Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Wed, 6 Mar 2024 13:14:01 +0100 Subject: [PATCH 08/11] fix: format --- server/vbv_lernwelt/course/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/vbv_lernwelt/course/views.py b/server/vbv_lernwelt/course/views.py index abb1d6d6..80b7f238 100644 --- a/server/vbv_lernwelt/course/views.py +++ b/server/vbv_lernwelt/course/views.py @@ -20,12 +20,12 @@ from vbv_lernwelt.course_session_group.models import CourseSessionGroup from vbv_lernwelt.files.models import UploadFile from vbv_lernwelt.files.services import FileDirectUploadService from vbv_lernwelt.iam.permissions import ( + can_mark_course_completion, can_view_course_completions, course_sessions_for_user_qs, has_course_access, has_course_access_by_page_request, is_circle_expert, - can_mark_course_completion, ) from vbv_lernwelt.learning_mentor.models import LearningMentor From 84f27617951a853f27c0dbe1db40e3c5dd14ca8d Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Wed, 6 Mar 2024 13:36:52 +0100 Subject: [PATCH 09/11] chore: workaround to make show all clickable in competence profile page --- .../SelfEvaluationAndFeedbackOverview.vue | 19 +++++++++---------- .../profilePage/CompetenceProfilePage.vue | 12 +++++++++++- .../pages/competence/CompetenceIndexPage.vue | 9 ++++++++- client/src/router/index.ts | 1 + 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue b/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue index 1dafa970..fdf3d296 100644 --- a/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue +++ b/client/src/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue @@ -3,9 +3,10 @@ import { computed } from "vue"; import { useSelfEvaluationFeedbackSummaries } from "@/services/selfEvaluationFeedback"; import { useCurrentCourseSession } from "@/composables"; +const emit = defineEmits(["showAll"]); + const props = defineProps<{ profileUserId: string; - detailUrl?: string; }>(); const courseSession = useCurrentCourseSession(); @@ -116,15 +117,13 @@ const isLoaded = computed(() => !selfEvaluationFeedbackSummaries.loading.value);
-
- - {{ $t("general.showAll") }} - - -
+
diff --git a/client/src/pages/cockpit/profilePage/CompetenceProfilePage.vue b/client/src/pages/cockpit/profilePage/CompetenceProfilePage.vue index 6acf2684..8b71e58f 100644 --- a/client/src/pages/cockpit/profilePage/CompetenceProfilePage.vue +++ b/client/src/pages/cockpit/profilePage/CompetenceProfilePage.vue @@ -3,6 +3,7 @@ import CockpitProfileContent from "@/components/cockpit/profile/CockpitProfileCo import { ref } from "vue"; import SelfEvaluationAndFeedbackList from "@/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackList.vue"; import SelfEvaluationAndFeedbackOverview from "@/components/selfEvaluationFeedback/SelfEvaluationAndFeedbackOverview.vue"; +import { useCurrentCourseSession } from "@/composables"; type SubMenuType = "OVERVIEW" | "DETAILS"; @@ -18,10 +19,18 @@ interface SubMenuItem { const MENU_ENTRIES: SubMenuItem[] = [ { type: "OVERVIEW", label: "a.Übersicht" }, - { type: "DETAILS", label: "a.Selbst- und Fremdeinschätzungen" }, + { + type: "DETAILS", + label: useCurrentCourseSession().value.course.configuration.enable_learning_mentor + ? "a.Selbst- und Fremdeinschätzungen" + : "a.Selbsteinschätzungen", + }, ]; const active = ref(MENU_ENTRIES[0]); +const selectDetails = () => { + active.value = MENU_ENTRIES[1]; +};