feat: comp.navi. in cockpit profile page
This commit is contained in:
parent
ef3e6a8f0d
commit
cfa3450704
|
|
@ -0,0 +1,132 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useSelfEvaluationFeedbackSummaries } from "@/services/selfEvaluationFeedback";
|
||||
import { useCurrentCourseSession } from "@/composables";
|
||||
|
||||
const props = defineProps<{
|
||||
targetUserId: string;
|
||||
detailUrl: string;
|
||||
}>();
|
||||
|
||||
const courseSession = useCurrentCourseSession();
|
||||
|
||||
const selfEvaluationFeedbackSummaries = useSelfEvaluationFeedbackSummaries(
|
||||
useCurrentCourseSession().value.id,
|
||||
props.targetUserId
|
||||
);
|
||||
|
||||
const selfAssessmentCounts = computed(
|
||||
() => selfEvaluationFeedbackSummaries.aggregates.value?.self_assessment
|
||||
);
|
||||
|
||||
const feedbackEvaluationCounts = computed(
|
||||
() => selfEvaluationFeedbackSummaries.aggregates.value?.feedback_assessment
|
||||
);
|
||||
|
||||
const isLoaded = computed(() => !selfEvaluationFeedbackSummaries.loading.value);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="isLoaded">
|
||||
<!-- Self Evaluation -->
|
||||
<div class="bg-white px-8 py-4 lg:mb-8 lg:py-8">
|
||||
<div class="mb-8">
|
||||
<h3 class="mb-4 pb-4 lg:pb-0">
|
||||
{{ $t("a.Selbsteinschätzungen") }}
|
||||
</h3>
|
||||
<ul
|
||||
class="mb-6 flex flex-col lg:flex-row lg:items-center lg:justify-between lg:gap-8"
|
||||
>
|
||||
<li class="mb-4 inline-block flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">«{{ $t("selfEvaluation.no") }}»</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-thinking class="h-16 w-16"></it-icon-smiley-thinking>
|
||||
<p
|
||||
class="ml-4 inline-block text-7xl font-bold"
|
||||
data-cy="self-evaluation-fail"
|
||||
>
|
||||
{{ selfAssessmentCounts?.fail }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-4 inline-block flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">«{{ $t("selfEvaluation.yes") }}»</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-happy class="h-16 w-16"></it-icon-smiley-happy>
|
||||
<p
|
||||
class="ml-4 inline-block text-7xl font-bold"
|
||||
data-cy="self-evaluation-success"
|
||||
>
|
||||
{{ selfAssessmentCounts?.pass }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">{{ $t("competences.notAssessed") }}</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-neutral class="h-16 w-16"></it-icon-smiley-neutral>
|
||||
<p
|
||||
class="ml-4 inline-block text-7xl font-bold"
|
||||
data-cy="self-evaluation-unknown"
|
||||
>
|
||||
{{ selfAssessmentCounts?.unknown }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Feedback Evaluation -->
|
||||
<div
|
||||
v-if="courseSession.course.configuration.enable_learning_mentor"
|
||||
class="mb-8 border-t pt-8"
|
||||
>
|
||||
<h3 class="mb-4 pb-4 lg:pb-0">
|
||||
{{ $t("a.Fremdeinschätzungen") }}
|
||||
</h3>
|
||||
<ul
|
||||
class="mb-6 flex flex-col lg:flex-row lg:items-center lg:justify-between lg:gap-8"
|
||||
>
|
||||
<li class="mb-4 inline-block flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">«{{ $t("receivedEvaluation.no") }}»</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-thinking class="h-16 w-16"></it-icon-smiley-thinking>
|
||||
<p class="ml-4 inline-block text-7xl font-bold">
|
||||
{{ feedbackEvaluationCounts?.fail }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-4 inline-block flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">«{{ $t("receivedEvaluation.yes") }}»</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-happy class="h-16 w-16"></it-icon-smiley-happy>
|
||||
<p class="ml-4 inline-block text-7xl font-bold">
|
||||
{{ feedbackEvaluationCounts?.pass }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">{{ $t("competences.notAssessed") }}</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-neutral class="h-16 w-16"></it-icon-smiley-neutral>
|
||||
<p class="ml-4 inline-block text-7xl font-bold">
|
||||
{{ feedbackEvaluationCounts?.unknown }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Show All (always)-->
|
||||
<div>
|
||||
<router-link
|
||||
:to="detailUrl"
|
||||
class="btn-text inline-flex items-center py-2 pl-0"
|
||||
>
|
||||
<span>{{ $t("general.showAll") }}</span>
|
||||
<it-icon-arrow-right></it-icon-arrow-right>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
profileUserId: string;
|
||||
courseSessionId: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>COMPETENCE FEEDBACK EVALUATION</h1>
|
||||
<h2>{{ profileUserId }}</h2>
|
||||
<h2>{{ courseSessionId }}</h2>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import SelfEvaluationAndFeedbackOverview from "@/components/cockpit/SelfEvaluationAndFeedbackOverview.vue";
|
||||
|
||||
defineProps<{
|
||||
profileUserId: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelfEvaluationAndFeedbackOverview :target-user-id="profileUserId" detail-url="#" />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
<script setup lang="ts">
|
||||
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";
|
||||
|
||||
const props = defineProps<{
|
||||
userId: string;
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
type SubMenuType = "OVERVIEW" | "EVALUATION";
|
||||
|
||||
interface SubMenuItem {
|
||||
type: SubMenuType;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const MENU_ENTRIES: SubMenuItem[] = [
|
||||
{ type: "OVERVIEW", label: "a.Übersicht" },
|
||||
{ type: "EVALUATION", label: "a.Selbst- und Fremdeinschätzungen" },
|
||||
];
|
||||
|
||||
const currentCourseSession = useCurrentCourseSession();
|
||||
|
||||
const active = ref<SubMenuItem>(MENU_ENTRIES[0]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CockpitProfileContent>
|
||||
<template #side>
|
||||
<div v-for="(entry, index) in MENU_ENTRIES" :key="index" class="mb-4">
|
||||
<button
|
||||
class="flex w-full items-center space-x-2 p-2 pr-4 hover:bg-gray-200 lg:pr-8"
|
||||
:class="{ 'bg-gray-200': active.type === entry.type }"
|
||||
@click="active = entry"
|
||||
>
|
||||
<span>{{ $t(entry.label) }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template #main>
|
||||
<CockpitProfileCompetenceOverview
|
||||
v-if="active.type === 'OVERVIEW'"
|
||||
:profile-user-id="props.userId"
|
||||
/>
|
||||
<CockpitProfileCompetenceFeedbackEvaluation
|
||||
v-else-if="active.type === 'EVALUATION'"
|
||||
:course-session-id="currentCourseSession.id"
|
||||
:profile-user-id="props.userId"
|
||||
/>
|
||||
</template>
|
||||
</CockpitProfileContent>
|
||||
</template>
|
||||
|
|
@ -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);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -145,106 +131,10 @@ const isLoaded = computed(
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Self-evaluation -->
|
||||
<section class="mb-4 bg-white px-8 py-4 lg:mb-8 lg:py-8">
|
||||
<div class="mb-8">
|
||||
<h3 class="mb-4 pb-4 lg:pb-0">
|
||||
{{ $t("a.Selbsteinschätzungen") }}
|
||||
</h3>
|
||||
<ul
|
||||
class="mb-6 flex flex-col lg:flex-row lg:items-center lg:justify-between lg:gap-8"
|
||||
>
|
||||
<li class="mb-4 inline-block flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">«{{ $t("selfEvaluation.no") }}»</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-thinking class="h-16 w-16"></it-icon-smiley-thinking>
|
||||
<p
|
||||
class="ml-4 inline-block text-7xl font-bold"
|
||||
data-cy="self-evaluation-fail"
|
||||
>
|
||||
{{ selfAssessmentCounts?.fail }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-4 inline-block flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">«{{ $t("selfEvaluation.yes") }}»</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-happy class="h-16 w-16"></it-icon-smiley-happy>
|
||||
<p
|
||||
class="ml-4 inline-block text-7xl font-bold"
|
||||
data-cy="self-evaluation-success"
|
||||
>
|
||||
{{ selfAssessmentCounts?.pass }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">{{ $t("competences.notAssessed") }}</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-neutral class="h-16 w-16"></it-icon-smiley-neutral>
|
||||
<p
|
||||
class="ml-4 inline-block text-7xl font-bold"
|
||||
data-cy="self-evaluation-unknown"
|
||||
>
|
||||
{{ selfAssessmentCounts?.unknown }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Feedback evaluation -->
|
||||
<div
|
||||
v-if="courseSession.course.configuration.enable_learning_mentor"
|
||||
class="mb-8 border-t pt-8"
|
||||
>
|
||||
<h3 class="mb-4 pb-4 lg:pb-0">
|
||||
{{ $t("a.Fremdeinschätzungen") }}
|
||||
</h3>
|
||||
<ul
|
||||
class="mb-6 flex flex-col lg:flex-row lg:items-center lg:justify-between lg:gap-8"
|
||||
>
|
||||
<li class="mb-4 inline-block flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">«{{ $t("receivedEvaluation.no") }}»</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-thinking class="h-16 w-16"></it-icon-smiley-thinking>
|
||||
<p class="ml-4 inline-block text-7xl font-bold">
|
||||
{{ feedbackEvaluationCounts?.fail }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="mb-4 inline-block flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">«{{ $t("receivedEvaluation.yes") }}»</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-happy class="h-16 w-16"></it-icon-smiley-happy>
|
||||
<p class="ml-4 inline-block text-7xl font-bold">
|
||||
{{ feedbackEvaluationCounts?.pass }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex-1 pb-4 lg:mb-0 lg:w-1/3 lg:pb-0">
|
||||
<h5 class="mb-4 text-gray-700">{{ $t("competences.notAssessed") }}</h5>
|
||||
<div class="flex flex-row items-center">
|
||||
<it-icon-smiley-neutral class="h-16 w-16"></it-icon-smiley-neutral>
|
||||
<p class="ml-4 inline-block text-7xl font-bold">
|
||||
{{ feedbackEvaluationCounts?.unknown }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<router-link
|
||||
:to="`/course/${props.courseSlug}/competence/self-evaluation-and-feedback`"
|
||||
class="btn-text inline-flex items-center py-2 pl-0"
|
||||
>
|
||||
<span>{{ $t("general.showAll") }}</span>
|
||||
<it-icon-arrow-right></it-icon-arrow-right>
|
||||
</router-link>
|
||||
</div>
|
||||
</section>
|
||||
<SelfEvaluationAndFeedbackOverview
|
||||
:target-user-id="useUserStore().id"
|
||||
:detail-url="`/course/${props.courseSlug}/competence/self-evaluation-and-feedback`"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -257,6 +257,13 @@ const router = createRouter({
|
|||
props: true,
|
||||
name: "cockpitProfileLearningPath",
|
||||
},
|
||||
{
|
||||
path: "competence",
|
||||
component: () =>
|
||||
import("@/pages/cockpit/profilePage/CompetenceProfilePage.vue"),
|
||||
props: true,
|
||||
name: "cockpitProfileCompetence",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -165,7 +165,8 @@ export function useSelfEvaluationFeedback(
|
|||
}
|
||||
|
||||
export function useSelfEvaluationFeedbackSummaries(
|
||||
courseSessionId: Ref<string> | string
|
||||
courseSessionId: Ref<string> | string,
|
||||
userId: Ref<string> | string
|
||||
) {
|
||||
const summaries = ref<LearningUnitSummary[]>([]);
|
||||
const aggregates = ref<FeedbackSummaryAggregates>();
|
||||
|
|
@ -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 () => {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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/<signed_int:course_session_id>/feedbacks/summaries",
|
||||
get_self_evaluation_feedbacks_as_requester,
|
||||
name="get_self_evaluation_feedbacks_as_requester",
|
||||
),
|
||||
path(
|
||||
"requester/<int:learning_unit_id>/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/<signed_int:course_session_id>/user/<str:user_id>",
|
||||
get_course_session_user_feedback_summaries,
|
||||
name="get_course_session_user_feedback_summaries",
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Reference in New Issue