feat: wraps self evaluation feedback request member side
This commit is contained in:
parent
3a519e2220
commit
412172515f
|
|
@ -28,8 +28,8 @@ import type {
|
||||||
import { useQuery } from "@urql/vue";
|
import { useQuery } from "@urql/vue";
|
||||||
import orderBy from "lodash/orderBy";
|
import orderBy from "lodash/orderBy";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import type { ComputedRef } from "vue";
|
import type { ComputedRef, Ref } from "vue";
|
||||||
import { computed, onMounted, ref, watchEffect } from "vue";
|
import { computed, onMounted, ref, toValue, watchEffect } from "vue";
|
||||||
|
|
||||||
export function useCurrentCourseSession() {
|
export function useCurrentCourseSession() {
|
||||||
/**
|
/**
|
||||||
|
|
@ -469,17 +469,52 @@ export function useFileUpload() {
|
||||||
export function useLearningMentors() {
|
export function useLearningMentors() {
|
||||||
const learningMentors = ref<LearningMentor[]>([]);
|
const learningMentors = ref<LearningMentor[]>([]);
|
||||||
const currentCourseSessionId = useCurrentCourseSession().value.id;
|
const currentCourseSessionId = useCurrentCourseSession().value.id;
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
const fetchMentors = async () => {
|
const fetchMentors = async () => {
|
||||||
|
loading.value = true;
|
||||||
const { data } = await useCSRFFetch(
|
const { data } = await useCSRFFetch(
|
||||||
`/api/mentor/${currentCourseSessionId}/mentors`
|
`/api/mentor/${currentCourseSessionId}/mentors`
|
||||||
).json();
|
).json();
|
||||||
learningMentors.value = data.value;
|
learningMentors.value = data.value;
|
||||||
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(fetchMentors);
|
onMounted(fetchMentors);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
learningMentors,
|
learningMentors,
|
||||||
|
loading,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSelfEvaluationFeedback(learningUnitId: Ref<string> | string) {
|
||||||
|
const feedback = ref({});
|
||||||
|
const loading = ref(false);
|
||||||
|
const exists = ref(false);
|
||||||
|
|
||||||
|
const url = `/api/self-evaluation-feedback/requester/${toValue(
|
||||||
|
learningUnitId
|
||||||
|
)}/feedback`;
|
||||||
|
|
||||||
|
const fetchSelfEvaluationFeedback = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const { data, statusCode } = await useCSRFFetch(url).json();
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
if (statusCode.value === 404) {
|
||||||
|
exists.value = false;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
exists.value = true;
|
||||||
|
feedback.value = data.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
onMounted(fetchSelfEvaluationFeedback);
|
||||||
|
|
||||||
|
return {
|
||||||
|
feedback,
|
||||||
|
exists,
|
||||||
|
loading,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { useRouteQuery } from "@vueuse/router";
|
||||||
import { computed, onUnmounted } from "vue";
|
import { computed, onUnmounted } from "vue";
|
||||||
import { getPreviousRoute } from "@/router/history";
|
import { getPreviousRoute } from "@/router/history";
|
||||||
import { getCompetenceNaviUrl } from "@/utils/utils";
|
import { getCompetenceNaviUrl } from "@/utils/utils";
|
||||||
import SelfEvaluationSubmit from "@/pages/learningPath/selfEvaluationPage/SelfEvaluationSubmit.vue";
|
import SelfEvaluationSubmit from "@/pages/learningPath/selfEvaluationPage/SelfEvaluationRequestFeedback.vue";
|
||||||
|
|
||||||
log.debug("LearningContent.vue setup");
|
log.debug("LearningContent.vue setup");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { LearningUnit, LearningUnitPerformanceCriteria } from "@/types";
|
||||||
|
import { useLearningMentors, useSelfEvaluationFeedback } from "@/composables";
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import ItButton from "@/components/ui/ItButton.vue";
|
||||||
|
import NoMentorInformationPanel from "@/components/mentor/NoMentorInformationPanel.vue";
|
||||||
|
import { useCSRFFetch } from "@/fetchHelpers";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
learningUnit: LearningUnit;
|
||||||
|
criteria: LearningUnitPerformanceCriteria[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const {
|
||||||
|
feedback: storedFeedback,
|
||||||
|
exists: isStoredFeedbackAvailable,
|
||||||
|
loading: isStoredFeedbackLoading,
|
||||||
|
} = useSelfEvaluationFeedback(props.learningUnit.id);
|
||||||
|
|
||||||
|
// if no feedback is stored "current session"
|
||||||
|
// state management (mentor selection etc.)
|
||||||
|
const { learningMentors, loading: isLearningMentorsLoading } = useLearningMentors();
|
||||||
|
const isCurrentSessionFeedbackRequested = ref(false);
|
||||||
|
const currentSessionRequestedMentor = ref();
|
||||||
|
|
||||||
|
const VisualState = {
|
||||||
|
LOADING: "LOADING",
|
||||||
|
NO_MENTOR: "NO_MENTOR",
|
||||||
|
HAS_REQUESTED_FEEDBACK: "HAS_REQUESTED_FEEDBACK",
|
||||||
|
HAS_NOT_REQUESTED_FEEDBACK: "HAS_NOT_REQUESTED_FEEDBACK",
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentVisualState = computed(() => {
|
||||||
|
if (isLearningMentorsLoading.value || isStoredFeedbackLoading.value) {
|
||||||
|
return VisualState.LOADING;
|
||||||
|
} else if (learningMentors.value.length == 0) {
|
||||||
|
return VisualState.NO_MENTOR;
|
||||||
|
} else if (
|
||||||
|
isStoredFeedbackAvailable.value ||
|
||||||
|
isCurrentSessionFeedbackRequested.value
|
||||||
|
) {
|
||||||
|
return VisualState.HAS_REQUESTED_FEEDBACK;
|
||||||
|
} else {
|
||||||
|
return VisualState.HAS_NOT_REQUESTED_FEEDBACK;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const feedbackMentorName = computed(() => {
|
||||||
|
const mentor = isStoredFeedbackAvailable.value
|
||||||
|
? (storedFeedback.value as any).feedback_provider_user
|
||||||
|
: isCurrentSessionFeedbackRequested.value
|
||||||
|
? currentSessionRequestedMentor.value
|
||||||
|
: null;
|
||||||
|
return mentor ? `${mentor.first_name} ${mentor.last_name}` : "";
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmitForMentorFeedback = async () => {
|
||||||
|
const url = `/api/self-evaluation-feedback/requester/${props.learningUnit.id}/feedback/start`;
|
||||||
|
const { error } = await useCSRFFetch(url).post({
|
||||||
|
feedback_provider_user_id: currentSessionRequestedMentor.value.id,
|
||||||
|
});
|
||||||
|
if (!error.value) {
|
||||||
|
isCurrentSessionFeedbackRequested.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="currentVisualState != VisualState.LOADING" class="mb-10 w-full pt-8">
|
||||||
|
<div class="w-full border border-gray-400">
|
||||||
|
<div class="m-6 space-y-6">
|
||||||
|
<h3 class="heading-3">
|
||||||
|
{{ $t("a.Selbsteinschätzung teilen") }}
|
||||||
|
</h3>
|
||||||
|
<div v-if="currentVisualState == VisualState.NO_MENTOR">
|
||||||
|
<NoMentorInformationPanel />
|
||||||
|
</div>
|
||||||
|
<div v-if="currentVisualState == VisualState.HAS_REQUESTED_FEEDBACK">
|
||||||
|
<div class="flex space-x-2 bg-green-200 p-4">
|
||||||
|
<it-icon-check class="it-icon h-6 w-6 text-green-700" />
|
||||||
|
<div>
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
"a.Du hast deine Selbsteinschätzung erfolgreich mit FULL_NAME geteilt.",
|
||||||
|
{
|
||||||
|
FULL_NAME: feedbackMentorName,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pt-6">
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
"a.FULL_NAME wird eine Fremdeinschätzung für dich vornehmen. Du wirst per Benachrichtigung informiert, sobald die Fremdeinschätzung für dich freigegeben wurde.",
|
||||||
|
{ FULL_NAME: feedbackMentorName }
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="currentVisualState == VisualState.HAS_NOT_REQUESTED_FEEDBACK">
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
"a.Du kannst deine Selbsteinschätzung mit deiner Lernbegleitung teilen, damit sie eine Fremdeinschätzung vornimmt."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<select
|
||||||
|
v-model="currentSessionRequestedMentor"
|
||||||
|
data-cy="select-learning-mentor"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="learningMentor in learningMentors"
|
||||||
|
:key="learningMentor.id"
|
||||||
|
:value="learningMentor.mentor"
|
||||||
|
>
|
||||||
|
{{ learningMentor.mentor.first_name }}
|
||||||
|
{{ learningMentor.mentor.last_name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<ItButton
|
||||||
|
class="mt-6"
|
||||||
|
variant="primary"
|
||||||
|
size="large"
|
||||||
|
:disabled="!currentSessionRequestedMentor"
|
||||||
|
data-cy="submit-assignment"
|
||||||
|
@click="onSubmitForMentorFeedback"
|
||||||
|
>
|
||||||
|
<p v-if="!currentSessionRequestedMentor">
|
||||||
|
{{ $t("a.Selbsteinschätzung teilen") }}
|
||||||
|
</p>
|
||||||
|
<p v-else>
|
||||||
|
{{
|
||||||
|
$t("a.Selbsteinschätzung mit MENTOR_NAME teilen", {
|
||||||
|
MENTOR_NAME: feedbackMentorName,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</ItButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(completion, index) in criteria"
|
||||||
|
:key="completion.id"
|
||||||
|
class="flex flex-col space-y-4 border-t border-gray-400 py-8"
|
||||||
|
>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<b>{{ completion.title }}</b>
|
||||||
|
<router-link :to="`${learningUnit.evaluate_url}?step=${index}`" class="underline">
|
||||||
|
{{ $t("a.Bearbeiten") }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="completion.completion_status == 'SUCCESS'"
|
||||||
|
class="flex flex-row items-center space-x-2"
|
||||||
|
>
|
||||||
|
<it-icon-smiley-happy class="h-6 w-6" />
|
||||||
|
<span>{{ $t("selfEvaluation.yes") }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else class="flex flex-row items-center space-x-2">
|
||||||
|
<it-icon-smiley-thinking class="h-6 w-6" />
|
||||||
|
<span>{{ $t("selfEvaluation.no") }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import type { LearningUnit, LearningUnitPerformanceCriteria } from "@/types";
|
|
||||||
import { useLearningMentors } from "@/composables";
|
|
||||||
import { ref } from "vue";
|
|
||||||
import ItButton from "@/components/ui/ItButton.vue";
|
|
||||||
import NoMentorInformationPanel from "@/components/mentor/NoMentorInformationPanel.vue";
|
|
||||||
|
|
||||||
defineProps<{
|
|
||||||
learningUnit: LearningUnit;
|
|
||||||
criteria: LearningUnitPerformanceCriteria[];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const selectedLearningMentor = ref();
|
|
||||||
const learningMentors = useLearningMentors().learningMentors;
|
|
||||||
const onSubmitForMentorFeedback = async () => {
|
|
||||||
try {
|
|
||||||
console.log("submit for mentor feedback");
|
|
||||||
} catch (error) {
|
|
||||||
console.log("Could not submit assignment", error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="mb-10 w-full pt-8">
|
|
||||||
<div class="w-full border border-gray-400">
|
|
||||||
<div class="m-6 space-y-6">
|
|
||||||
<h3 class="heading-3">
|
|
||||||
{{ $t("a.Selbsteinschätzung teilen") }}
|
|
||||||
</h3>
|
|
||||||
<div v-if="learningMentors?.length">
|
|
||||||
<p>
|
|
||||||
{{
|
|
||||||
$t(
|
|
||||||
"a.Du kannst deine Selbsteinschätzung mit deiner Lernbegleitung teilen, damit sie eine Fremdeinschätzung vornimmt."
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</p>
|
|
||||||
<select v-model="selectedLearningMentor" data-cy="select-learning-mentor">
|
|
||||||
<option
|
|
||||||
v-for="learningMentor in learningMentors"
|
|
||||||
:key="learningMentor.id"
|
|
||||||
:value="learningMentor.mentor"
|
|
||||||
>
|
|
||||||
{{ learningMentor.mentor.first_name }}
|
|
||||||
{{ learningMentor.mentor.last_name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<ItButton
|
|
||||||
class="mt-6"
|
|
||||||
variant="primary"
|
|
||||||
size="large"
|
|
||||||
:disabled="!selectedLearningMentor"
|
|
||||||
data-cy="submit-assignment"
|
|
||||||
@click="onSubmitForMentorFeedback"
|
|
||||||
>
|
|
||||||
<p v-if="!selectedLearningMentor">
|
|
||||||
{{ $t("a.Selbsteinschätzung teilen") }}
|
|
||||||
</p>
|
|
||||||
<p v-else>
|
|
||||||
{{
|
|
||||||
$t("a.Selbsteinschätzung mit MENTOR_NAME teilen", {
|
|
||||||
MENTOR_NAME: selectedLearningMentor.first_name,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
</p>
|
|
||||||
</ItButton>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<NoMentorInformationPanel />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-for="(pc, index) in criteria"
|
|
||||||
:key="pc.id"
|
|
||||||
class="flex flex-col space-y-4 border-t border-gray-400 py-8"
|
|
||||||
>
|
|
||||||
<div class="flex justify-between">
|
|
||||||
<b>{{ pc.title }}</b>
|
|
||||||
<router-link :to="`${learningUnit.evaluate_url}?step=${index}`" class="underline">
|
|
||||||
{{ $t("a.Bearbeiten") }}
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="pc.completion_status == 'SUCCESS'"
|
|
||||||
class="flex flex-row items-center space-x-2"
|
|
||||||
>
|
|
||||||
<it-icon-smiley-happy class="h-6 w-6" />
|
|
||||||
<span>{{ $t("selfEvaluation.yes") }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-else class="flex flex-row items-center space-x-2">
|
|
||||||
<it-icon-smiley-thinking class="h-6 w-6" />
|
|
||||||
<span>{{ $t("selfEvaluation.no") }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
|
|
@ -1,3 +1,49 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
# Register your models here.
|
from vbv_lernwelt.self_evaluation_feedback.models import (
|
||||||
|
CourseCompletionFeedback,
|
||||||
|
SelfEvaluationFeedback,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(SelfEvaluationFeedback)
|
||||||
|
class CourseSessionAdmin(admin.ModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
"id",
|
||||||
|
"feedback_submitted",
|
||||||
|
"feedback_requester_user",
|
||||||
|
"feedback_provider_user",
|
||||||
|
"learning_unit",
|
||||||
|
)
|
||||||
|
list_filter = (
|
||||||
|
"feedback_submitted",
|
||||||
|
"feedback_requester_user",
|
||||||
|
"feedback_provider_user",
|
||||||
|
"learning_unit",
|
||||||
|
)
|
||||||
|
search_fields = (
|
||||||
|
"feedback_submitted",
|
||||||
|
"feedback_requester_user",
|
||||||
|
"feedback_provider_user",
|
||||||
|
"learning_unit",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(CourseCompletionFeedback)
|
||||||
|
class CourseSessionAdmin(admin.ModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
"id",
|
||||||
|
"feedback",
|
||||||
|
"course_completion",
|
||||||
|
"feedback_assessment",
|
||||||
|
)
|
||||||
|
list_filter = (
|
||||||
|
"feedback",
|
||||||
|
"course_completion",
|
||||||
|
"feedback_assessment",
|
||||||
|
)
|
||||||
|
search_fields = (
|
||||||
|
"feedback",
|
||||||
|
"course_completion",
|
||||||
|
"feedback_assessment",
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue