Merged in feature/VBV-341-feedback-rebase (pull request #75)
Feature/VBV-341 feedback rebase Approved-by: Christian Cueni Approved-by: Elia Bieri
This commit is contained in:
commit
aab9373c3e
|
|
@ -1,3 +1,133 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ItRadioGroup from "@/components/ui/ItRadioGroup.vue";
|
||||||
|
import ItTextarea from "@/components/ui/ItTextarea.vue";
|
||||||
|
import { graphql } from "@/gql/";
|
||||||
|
import type { SendFeedbackInput } from "@/gql/graphql";
|
||||||
|
import FeedbackCompletition from "@/pages/learningPath/learningContentPage/feedback/FeedbackCompletition.vue";
|
||||||
|
import {
|
||||||
|
PERCENTAGES,
|
||||||
|
RATINGS,
|
||||||
|
YES_NO,
|
||||||
|
} from "@/pages/learningPath/learningContentPage/feedback/feedback.constants";
|
||||||
|
import LearningContentMultiLayout from "@/pages/learningPath/learningContentPage/layouts/LearningContentMultiLayout.vue";
|
||||||
|
import { useCircleStore } from "@/stores/circle";
|
||||||
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||||
|
import type { LearningContent } from "@/types";
|
||||||
|
import { useMutation } from "@urql/vue";
|
||||||
|
import { useRouteQuery } from "@vueuse/router";
|
||||||
|
import log from "loglevel";
|
||||||
|
import { computed, onMounted, reactive, ref } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
const props = defineProps<{ page: LearningContent }>();
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
const circleStore = useCircleStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
log.debug("Feedback mounted");
|
||||||
|
});
|
||||||
|
|
||||||
|
const stepNo = useRouteQuery("step", "0", { transform: Number, mode: "push" });
|
||||||
|
|
||||||
|
const title = computed(
|
||||||
|
() => `«${circleStore.circle?.title}»: ${t("feedback.areYouSatisfied")}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const stepLabels = [
|
||||||
|
t("general.introduction"),
|
||||||
|
t("feedback.satisfactionLabel"),
|
||||||
|
t("feedback.goalAttainmentLabel"),
|
||||||
|
t("feedback.proficiencyLabel"),
|
||||||
|
t("feedback.preparationTaskClarityLabel"),
|
||||||
|
t("feedback.instructorCompetenceLabel"),
|
||||||
|
t("feedback.instructorRespectLabel"),
|
||||||
|
t("feedback.instructorOpenFeedbackLabel"),
|
||||||
|
t("feedback.recommendLabel"),
|
||||||
|
t("feedback.courseNegativeFeedbackLabel"),
|
||||||
|
t("feedback.coursePositiveFeedbackLabel"),
|
||||||
|
t("general.submission"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const numSteps = stepLabels.length;
|
||||||
|
|
||||||
|
const sendFeedbackMutation = graphql(`
|
||||||
|
mutation SendFeedbackMutation($input: SendFeedbackInput!) {
|
||||||
|
sendFeedback(input: $input) {
|
||||||
|
feedbackResponse {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
field
|
||||||
|
messages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const { executeMutation } = useMutation(sendFeedbackMutation);
|
||||||
|
|
||||||
|
const satisfaction = ref(null);
|
||||||
|
const goalAttainment = ref(null);
|
||||||
|
const proficiency = ref(null);
|
||||||
|
const preparationTaskClarity = ref(null);
|
||||||
|
const instructorCompetence = ref(null);
|
||||||
|
const instructorRespect = ref(null);
|
||||||
|
const instructorOpenFeedback = ref("");
|
||||||
|
const wouldRecommend = ref(null);
|
||||||
|
const courseNegativeFeedback = ref("");
|
||||||
|
const coursePositiveFeedback = ref("");
|
||||||
|
|
||||||
|
const mutationResult = ref<any>(null);
|
||||||
|
|
||||||
|
const previousStep = () => {
|
||||||
|
if (stepNo.value > 0) {
|
||||||
|
stepNo.value -= 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const nextStep = () => {
|
||||||
|
if (stepNo.value < numSteps) {
|
||||||
|
stepNo.value += 1;
|
||||||
|
}
|
||||||
|
log.info(`next step ${stepNo.value} of ${numSteps}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendFeedback = () => {
|
||||||
|
log.info("sending feedback");
|
||||||
|
const courseSession = courseSessionsStore.currentCourseSession;
|
||||||
|
if (!courseSession || !courseSession.id) {
|
||||||
|
log.error("no course session set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const input: SendFeedbackInput = reactive({
|
||||||
|
data: {
|
||||||
|
preparation_task_clarity: preparationTaskClarity,
|
||||||
|
course_negative_feedback: courseNegativeFeedback,
|
||||||
|
course_positive_feedback: coursePositiveFeedback,
|
||||||
|
goald_attainment: goalAttainment,
|
||||||
|
instructor_competence: instructorCompetence,
|
||||||
|
instructor_respect: instructorRespect,
|
||||||
|
instructor_open_feedback: instructorOpenFeedback,
|
||||||
|
satisfaction,
|
||||||
|
proficiency,
|
||||||
|
would_recommend: wouldRecommend,
|
||||||
|
},
|
||||||
|
page: props.page.translation_key,
|
||||||
|
courseSession: courseSession.id,
|
||||||
|
});
|
||||||
|
const variables = reactive({
|
||||||
|
input,
|
||||||
|
});
|
||||||
|
log.debug(variables);
|
||||||
|
executeMutation(variables)
|
||||||
|
.then(({ data, error }) => {
|
||||||
|
log.debug(data);
|
||||||
|
log.error(error);
|
||||||
|
mutationResult.value = data;
|
||||||
|
})
|
||||||
|
.catch((e) => log.error(e));
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LearningContentMultiLayout
|
<LearningContentMultiLayout
|
||||||
:title="title"
|
:title="title"
|
||||||
|
|
@ -11,10 +141,11 @@
|
||||||
:steps-count="numSteps"
|
:steps-count="numSteps"
|
||||||
:start-badge-text="$t('general.introduction')"
|
:start-badge-text="$t('general.introduction')"
|
||||||
:end-badge-text="$t('general.submission')"
|
:end-badge-text="$t('general.submission')"
|
||||||
|
:base-url="props.page.frontend_url"
|
||||||
@previous="previousStep()"
|
@previous="previousStep()"
|
||||||
@next="nextStep()"
|
@next="nextStep()"
|
||||||
>
|
>
|
||||||
<div class="container-medium">
|
<div>
|
||||||
<p v-if="stepNo === 0" class="mt-10">
|
<p v-if="stepNo === 0" class="mt-10">
|
||||||
{{
|
{{
|
||||||
$t("feedback.intro", {
|
$t("feedback.intro", {
|
||||||
|
|
@ -27,51 +158,47 @@
|
||||||
</p>
|
</p>
|
||||||
<ItRadioGroup
|
<ItRadioGroup
|
||||||
v-if="stepNo === 1"
|
v-if="stepNo === 1"
|
||||||
v-model="wouldRecommend"
|
|
||||||
class="mb-8"
|
|
||||||
:items="YES_NO"
|
|
||||||
/>
|
|
||||||
<ItRadioGroup
|
|
||||||
v-if="stepNo === 2"
|
|
||||||
v-model="satisfaction"
|
v-model="satisfaction"
|
||||||
class="mb-8"
|
class="mb-8"
|
||||||
:items="RATINGS"
|
:items="RATINGS"
|
||||||
/>
|
/>
|
||||||
<ItRadioGroup
|
<ItRadioGroup
|
||||||
v-if="stepNo === 3"
|
v-if="stepNo === 2"
|
||||||
v-model="goalAttainment"
|
v-model="goalAttainment"
|
||||||
class="mb-8"
|
class="mb-8"
|
||||||
:items="RATINGS"
|
:items="RATINGS"
|
||||||
/>
|
/>
|
||||||
<ItRadioGroup
|
<ItRadioGroup
|
||||||
v-if="stepNo === 4"
|
v-if="stepNo === 3"
|
||||||
v-model="proficiency"
|
v-model="proficiency"
|
||||||
class="mb-8"
|
class="mb-8"
|
||||||
:items="PERCENTAGES"
|
:items="PERCENTAGES"
|
||||||
/>
|
/>
|
||||||
<ItRadioGroup
|
<ItRadioGroup
|
||||||
v-if="stepNo === 5"
|
v-if="stepNo === 4"
|
||||||
v-model="receivedMaterials"
|
v-model="preparationTaskClarity"
|
||||||
class="mb-8"
|
class="mb-8"
|
||||||
:items="YES_NO"
|
:items="YES_NO"
|
||||||
/>
|
/>
|
||||||
<div v-if="stepNo === 5 && receivedMaterials">
|
|
||||||
<p class="pb-2">{{ t("feedback.materialsRatingLabel") }}</p>
|
|
||||||
<ItRadioGroup v-model="materialsRating" class="mb-8" :items="RATINGS" />
|
|
||||||
</div>
|
|
||||||
<ItRadioGroup
|
<ItRadioGroup
|
||||||
v-if="stepNo === 6"
|
v-if="stepNo === 5"
|
||||||
v-model="instructorCompetence"
|
v-model="instructorCompetence"
|
||||||
class="mb-8"
|
class="mb-8"
|
||||||
:items="RATINGS"
|
:items="RATINGS"
|
||||||
/>
|
/>
|
||||||
<ItRadioGroup
|
<ItRadioGroup
|
||||||
v-if="stepNo === 7"
|
v-if="stepNo === 6"
|
||||||
v-model="instructorRespect"
|
v-model="instructorRespect"
|
||||||
class="mb-8"
|
class="mb-8"
|
||||||
:items="RATINGS"
|
:items="RATINGS"
|
||||||
/>
|
/>
|
||||||
<ItTextarea v-if="stepNo === 8" v-model="instructorOpenFeedback" class="mb-8" />
|
<ItTextarea v-if="stepNo === 7" v-model="instructorOpenFeedback" class="mb-8" />
|
||||||
|
<ItRadioGroup
|
||||||
|
v-if="stepNo === 8"
|
||||||
|
v-model="wouldRecommend"
|
||||||
|
class="mb-8"
|
||||||
|
:items="YES_NO"
|
||||||
|
/>
|
||||||
<ItTextarea v-if="stepNo === 9" v-model="courseNegativeFeedback" class="mb-8" />
|
<ItTextarea v-if="stepNo === 9" v-model="courseNegativeFeedback" class="mb-8" />
|
||||||
<ItTextarea v-if="stepNo === 10" v-model="coursePositiveFeedback" class="mb-8" />
|
<ItTextarea v-if="stepNo === 10" v-model="coursePositiveFeedback" class="mb-8" />
|
||||||
<FeedbackCompletition
|
<FeedbackCompletition
|
||||||
|
|
@ -104,134 +231,3 @@
|
||||||
mutationResult: {{ mutationResult }}
|
mutationResult: {{ mutationResult }}
|
||||||
</pre> -->
|
</pre> -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import ItRadioGroup from "@/components/ui/ItRadioGroup.vue";
|
|
||||||
import ItTextarea from "@/components/ui/ItTextarea.vue";
|
|
||||||
import { graphql } from "@/gql/";
|
|
||||||
import type { SendFeedbackInput } from "@/gql/graphql";
|
|
||||||
import FeedbackCompletition from "@/pages/learningPath/learningContentPage/feedback/FeedbackCompletition.vue";
|
|
||||||
import {
|
|
||||||
PERCENTAGES,
|
|
||||||
RATINGS,
|
|
||||||
YES_NO,
|
|
||||||
} from "@/pages/learningPath/learningContentPage/feedback/feedback.constants";
|
|
||||||
import LearningContentMultiLayout from "@/pages/learningPath/learningContentPage/layouts/LearningContentMultiLayout.vue";
|
|
||||||
import { useCircleStore } from "@/stores/circle";
|
|
||||||
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
|
||||||
import type { LearningContent } from "@/types";
|
|
||||||
import { useMutation } from "@urql/vue";
|
|
||||||
import log from "loglevel";
|
|
||||||
import { computed, onMounted, reactive, ref } from "vue";
|
|
||||||
import { useI18n } from "vue-i18n";
|
|
||||||
|
|
||||||
const props = defineProps<{ page: LearningContent }>();
|
|
||||||
const courseSessionsStore = useCourseSessionsStore();
|
|
||||||
const circleStore = useCircleStore();
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
log.debug("Feedback mounted");
|
|
||||||
});
|
|
||||||
|
|
||||||
const stepNo = ref(0);
|
|
||||||
|
|
||||||
const title = computed(
|
|
||||||
() => `«${circleStore.circle?.title}»: ${t("feedback.areYouSatisfied")}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const stepLabels = [
|
|
||||||
t("general.introduction"),
|
|
||||||
t("feedback.recommendLabel"),
|
|
||||||
t("feedback.satisfactionLabel"),
|
|
||||||
t("feedback.goalAttainmentLabel"),
|
|
||||||
t("feedback.proficiencyLabel"),
|
|
||||||
t("feedback.receivedMaterialsLabel"),
|
|
||||||
t("feedback.instructorCompetenceLabel"),
|
|
||||||
t("feedback.instructorRespectLabel"),
|
|
||||||
t("feedback.instructorOpenFeedbackLabel"),
|
|
||||||
t("feedback.courseNegativeFeedbackLabel"),
|
|
||||||
t("feedback.coursePositiveFeedbackLabel"),
|
|
||||||
t("general.submission"),
|
|
||||||
];
|
|
||||||
|
|
||||||
const numSteps = stepLabels.length;
|
|
||||||
|
|
||||||
const sendFeedbackMutation = graphql(`
|
|
||||||
mutation SendFeedbackMutation($input: SendFeedbackInput!) {
|
|
||||||
sendFeedback(input: $input) {
|
|
||||||
feedbackResponse {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
errors {
|
|
||||||
field
|
|
||||||
messages
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
const { executeMutation } = useMutation(sendFeedbackMutation);
|
|
||||||
|
|
||||||
const satisfaction = ref(null);
|
|
||||||
const goalAttainment = ref(null);
|
|
||||||
const wouldRecommend = ref(null);
|
|
||||||
const proficiency = ref(null);
|
|
||||||
const receivedMaterials = ref(null);
|
|
||||||
const materialsRating = ref(null);
|
|
||||||
const instructorCompetence = ref(null);
|
|
||||||
const instructorRespect = ref(null);
|
|
||||||
const coursePositiveFeedback = ref("");
|
|
||||||
const courseNegativeFeedback = ref("");
|
|
||||||
const instructorOpenFeedback = ref("");
|
|
||||||
|
|
||||||
const mutationResult = ref<any>(null);
|
|
||||||
|
|
||||||
const previousStep = () => {
|
|
||||||
if (stepNo.value > 0) {
|
|
||||||
stepNo.value -= 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const nextStep = () => {
|
|
||||||
if (stepNo.value < numSteps) {
|
|
||||||
stepNo.value += 1;
|
|
||||||
}
|
|
||||||
log.info(`next step ${stepNo.value} of ${numSteps}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendFeedback = () => {
|
|
||||||
log.info("sending feedback");
|
|
||||||
const courseSession = courseSessionsStore.currentCourseSession;
|
|
||||||
if (!courseSession || !courseSession.id) {
|
|
||||||
log.error("no course session set");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const input: SendFeedbackInput = reactive({
|
|
||||||
data: {
|
|
||||||
materials_rating: materialsRating,
|
|
||||||
course_negative_feedback: courseNegativeFeedback,
|
|
||||||
course_positive_feedback: coursePositiveFeedback,
|
|
||||||
goald_attainment: goalAttainment,
|
|
||||||
instructor_competence: instructorCompetence,
|
|
||||||
instructor_respect: instructorRespect,
|
|
||||||
instructor_open_feedback: instructorOpenFeedback,
|
|
||||||
satisfaction,
|
|
||||||
proficiency,
|
|
||||||
received_materials: receivedMaterials,
|
|
||||||
would_recommend: wouldRecommend,
|
|
||||||
},
|
|
||||||
page: props.page.translation_key,
|
|
||||||
courseSession: courseSession.id,
|
|
||||||
});
|
|
||||||
const variables = reactive({
|
|
||||||
input,
|
|
||||||
});
|
|
||||||
log.debug(variables);
|
|
||||||
executeMutation(variables)
|
|
||||||
.then(({ data, error }) => {
|
|
||||||
log.debug(data);
|
|
||||||
log.error(error);
|
|
||||||
mutationResult.value = data;
|
|
||||||
})
|
|
||||||
.catch((e) => log.error(e));
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@ export interface Props {
|
||||||
startBadgeText?: string;
|
startBadgeText?: string;
|
||||||
endBadgeText?: string;
|
endBadgeText?: string;
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
queryParam?: string;
|
stepQueryParam?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
startBadgeText: undefined,
|
startBadgeText: undefined,
|
||||||
endBadgeText: undefined,
|
endBadgeText: undefined,
|
||||||
baseUrl: undefined,
|
baseUrl: undefined,
|
||||||
queryParam: "page",
|
stepQueryParam: "step",
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasStartBadge = computed(() => typeof props.startBadgeText !== "undefined");
|
const hasStartBadge = computed(() => typeof props.startBadgeText !== "undefined");
|
||||||
|
|
@ -67,7 +67,10 @@ function calcStepIndex(step: number) {
|
||||||
:class="startBadgeClasses"
|
:class="startBadgeClasses"
|
||||||
data-cy="nav-progress-step-start"
|
data-cy="nav-progress-step-start"
|
||||||
>
|
>
|
||||||
<router-link v-if="props.baseUrl" :to="`${props.baseUrl}?${props.queryParam}=0`">
|
<router-link
|
||||||
|
v-if="props.baseUrl"
|
||||||
|
:to="`${props.baseUrl}?${props.stepQueryParam}=0`"
|
||||||
|
>
|
||||||
{{ props.startBadgeText }}
|
{{ props.startBadgeText }}
|
||||||
</router-link>
|
</router-link>
|
||||||
<span v-else>{{ props.startBadgeText }}</span>
|
<span v-else>{{ props.startBadgeText }}</span>
|
||||||
|
|
@ -84,7 +87,7 @@ function calcStepIndex(step: number) {
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
v-if="props.baseUrl"
|
v-if="props.baseUrl"
|
||||||
:to="`${props.baseUrl}?${props.queryParam}=${calcStepIndex(step)}`"
|
:to="`${props.baseUrl}?${props.stepQueryParam}=${calcStepIndex(step)}`"
|
||||||
>
|
>
|
||||||
{{ step + 1 }}
|
{{ step + 1 }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
@ -100,7 +103,7 @@ function calcStepIndex(step: number) {
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
v-if="props.baseUrl"
|
v-if="props.baseUrl"
|
||||||
:to="`${props.baseUrl}?${props.queryParam}=${steps - 1}`"
|
:to="`${props.baseUrl}?${props.stepQueryParam}=${steps - 1}`"
|
||||||
>
|
>
|
||||||
{{ props.endBadgeText }}
|
{{ props.endBadgeText }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
|
||||||
|
|
@ -87,23 +87,23 @@
|
||||||
"circleFeedback": "Feedback zum Circle",
|
"circleFeedback": "Feedback zum Circle",
|
||||||
"completionDescription": "Dein Feedback ist anonym. Dein Vor- und Nachname werden bei deiner Trainer/-in nicht angezeigt.",
|
"completionDescription": "Dein Feedback ist anonym. Dein Vor- und Nachname werden bei deiner Trainer/-in nicht angezeigt.",
|
||||||
"completionTitle": "Schicke dein Feedback an {name}",
|
"completionTitle": "Schicke dein Feedback an {name}",
|
||||||
"courseNegativeFeedbackLabel": "Wo sehen Sie Verbesserungspotenzial?",
|
"courseNegativeFeedbackLabel": "Wo siehst du Verbesserungspotential?",
|
||||||
"coursePositiveFeedbackLabel": "Was hat Ihnen besonders gut gefallen?",
|
"coursePositiveFeedbackLabel": "Was hat dir besonders gut gefallen?",
|
||||||
"feedbackPageInfo": "Teilnehmer haben das Feedback ausgefüllt",
|
"feedbackPageInfo": "Teilnehmer haben das Feedback ausgefüllt",
|
||||||
"feedbackPageTitle": "Feedback zum Lehrgang",
|
"feedbackPageTitle": "Feedback zum Lehrgang",
|
||||||
"feedbackSent": "Dein Feedback wurde abgeschickt",
|
"feedbackSent": "Dein Feedback wurde abgeschickt",
|
||||||
"goalAttainmentLabel": "Zielerreichung insgesamt",
|
"goalAttainmentLabel": "Zielerreichung insgesamt",
|
||||||
"happy": "Zufrieden",
|
"happy": "Zufrieden",
|
||||||
"instructorCompetenceLabel": "Der Kursleiter war themenstark, fachkompetent.",
|
"instructorCompetenceLabel": "Wie beurteilst du die Themensicherheit und Fachkompetenz des Kursleiters/der Kursleiterin?",
|
||||||
"instructorOpenFeedbackLabel": "Was ich dem Kursleiter sonst noch sagen wollte:",
|
"instructorOpenFeedbackLabel": "Was möchtest du dem Kursleiter/der Kursleiterin sonst noch sagen?",
|
||||||
"instructorRespectLabel": "Fragen und Anregungen der Kursteilnehmenden wurden ernst genommen und aufgegriffen.",
|
"instructorRespectLabel": "Wurden Fragen und Anregungen der Kursteilnehmenden ernst genommen und aufgegriffen?",
|
||||||
"intro": "{name}, dein/e Trainer/-in, bittet dich, ihm/ihr Feedback zu geben. Das ist freiwillig, würde aber ihm/ihr helfen, deine Lernerlebniss zu verbessern.",
|
"intro": "{name}, dein/e Trainer/-in, bittet dich, ihm/ihr Feedback zu geben. Das ist freiwillig, würde aber ihm/ihr helfen, deine Lernerlebniss zu verbessern.",
|
||||||
"materialsRatingLabel": "Falls ja: Wie beurteilen Sie die Vorbereitungsunterlagen (z.B. eLearning)?",
|
"materialsRatingLabel": "Falls ja: Wie beurteilen Sie die Vorbereitungsunterlagen (z.B. eLearning)?",
|
||||||
"noFeedbacks": "Es wurden noch keine Feedbacks abgegeben",
|
"noFeedbacks": "Es wurden noch keine Feedbacks abgegeben",
|
||||||
"proficiencyLabel": "Wie beurteilen Sie Ihre Sicherheit bezüglichen den Themen nach dem Kurs?",
|
"preparationTaskClarityLabel": "Waren die Vorbereitungsaufträge klar und verständlich?",
|
||||||
|
"proficiencyLabel": "Wie beurteilst du deine Sicherheit bezüglichen den Themen nach dem Kurs?",
|
||||||
"questionTitle": "Frage",
|
"questionTitle": "Frage",
|
||||||
"receivedMaterialsLabel": "Haben Sie Vorbereitungsunterlagen (z.B. eLearning) erhalten?",
|
"recommendLabel": "Würdest du den Kurs weiterempfehlen?",
|
||||||
"recommendLabel": "Würden Sie den Kurs weiterempfehlen?",
|
|
||||||
"satisfactionLabel": "Zufriedenheit insgesamt",
|
"satisfactionLabel": "Zufriedenheit insgesamt",
|
||||||
"sendFeedback": "Feedback abschicken",
|
"sendFeedback": "Feedback abschicken",
|
||||||
"sentByUsers": "Von {count} Teilnehmern ausgefüllt",
|
"sentByUsers": "Von {count} Teilnehmern ausgefüllt",
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,6 @@ const courseSessionsStore = useCourseSessionsStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const orderedQuestions = [
|
const orderedQuestions = [
|
||||||
{
|
|
||||||
key: "would_recommend",
|
|
||||||
question: t("feedback.recommendLabel"),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: "satisfaction",
|
key: "satisfaction",
|
||||||
question: t("feedback.satisfactionLabel"),
|
question: t("feedback.satisfactionLabel"),
|
||||||
|
|
@ -100,12 +96,8 @@ const orderedQuestions = [
|
||||||
question: t("feedback.proficiencyLabel"),
|
question: t("feedback.proficiencyLabel"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "received_materials",
|
key: "preparation_task_clarity",
|
||||||
question: t("feedback.receivedMaterialsLabel"),
|
question: t("feedback.preparationTaskClarityLabel"),
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "materials_rating",
|
|
||||||
question: t("feedback.materialsRatingLabel"),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "instructor_competence",
|
key: "instructor_competence",
|
||||||
|
|
@ -119,6 +111,10 @@ const orderedQuestions = [
|
||||||
key: "instructor_open_feedback",
|
key: "instructor_open_feedback",
|
||||||
question: t("feedback.instructorOpenFeedbackLabel"),
|
question: t("feedback.instructorOpenFeedbackLabel"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "would_recommend",
|
||||||
|
question: t("feedback.recommendLabel"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "course_negative_feedback",
|
key: "course_negative_feedback",
|
||||||
question: t("feedback.courseNegativeFeedbackLabel"),
|
question: t("feedback.courseNegativeFeedbackLabel"),
|
||||||
|
|
@ -132,11 +128,10 @@ const orderedQuestions = [
|
||||||
const ratingKeys = [
|
const ratingKeys = [
|
||||||
"satisfaction",
|
"satisfaction",
|
||||||
"goal_attainment",
|
"goal_attainment",
|
||||||
"materials_rating",
|
|
||||||
"instructor_competence",
|
"instructor_competence",
|
||||||
"instructor_respect",
|
"instructor_respect",
|
||||||
];
|
];
|
||||||
const verticalChartKyes = ["received_materials", "would_recommend"];
|
const verticalChartKyes = ["preparation_task_clarity", "would_recommend"];
|
||||||
const horizontalChartKeys = ["proficiency"];
|
const horizontalChartKeys = ["proficiency"];
|
||||||
const openKeys = [
|
const openKeys = [
|
||||||
"course_negative_feedback",
|
"course_negative_feedback",
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,11 @@ import type {
|
||||||
AssignmentEvaluationTask,
|
AssignmentEvaluationTask,
|
||||||
CourseSessionUser,
|
CourseSessionUser,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
|
import { useRouteQuery } from "@vueuse/router";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { findIndex } from "lodash";
|
import { findIndex } from "lodash";
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
import { computed, onMounted, reactive } from "vue";
|
import { computed, onMounted } from "vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
assignmentUser: CourseSessionUser;
|
assignmentUser: CourseSessionUser;
|
||||||
|
|
@ -24,14 +25,8 @@ const emit = defineEmits(["close"]);
|
||||||
|
|
||||||
log.debug("UserEvaluation setup");
|
log.debug("UserEvaluation setup");
|
||||||
|
|
||||||
interface StateInterface {
|
// 0 = introduction, 1 - n = tasks, n+1 = submission
|
||||||
// 0 = introduction, 1 - n = tasks, n+1 = submission
|
const stepIndex = useRouteQuery("step", "0", { transform: Number, mode: "push" });
|
||||||
pageIndex: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const state: StateInterface = reactive({
|
|
||||||
pageIndex: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const assignmentStore = useAssignmentStore();
|
const assignmentStore = useAssignmentStore();
|
||||||
|
|
||||||
|
|
@ -41,21 +36,19 @@ const evaluationSubmitted = computed(
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (evaluationSubmitted.value) {
|
if (stepIndex.value === 0 && evaluationSubmitted.value) {
|
||||||
state.pageIndex = props.assignment.evaluation_tasks?.length + 1 ?? 0;
|
stepIndex.value = props.assignment.evaluation_tasks?.length + 1 ?? 0;
|
||||||
} else {
|
|
||||||
state.pageIndex = 0;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function previousPage() {
|
function previousPage() {
|
||||||
log.debug("previousTask");
|
log.debug("previousTask");
|
||||||
state.pageIndex = Math.max(0, state.pageIndex - 1);
|
stepIndex.value = Math.max(0, stepIndex.value - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextPage() {
|
function nextPage() {
|
||||||
log.debug("nextTask");
|
log.debug("nextTask");
|
||||||
state.pageIndex = Math.min(numTasks.value + 1, state.pageIndex + 1);
|
stepIndex.value = Math.min(numTasks.value + 1, stepIndex.value + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function editTask(task: AssignmentEvaluationTask) {
|
function editTask(task: AssignmentEvaluationTask) {
|
||||||
|
|
@ -64,7 +57,7 @@ function editTask(task: AssignmentEvaluationTask) {
|
||||||
findIndex(props.assignment.evaluation_tasks, {
|
findIndex(props.assignment.evaluation_tasks, {
|
||||||
id: task.id,
|
id: task.id,
|
||||||
}) ?? 0;
|
}) ?? 0;
|
||||||
state.pageIndex = taskIndex + 1;
|
stepIndex.value = taskIndex + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const assignmentDetail = computed(() =>
|
const assignmentDetail = computed(() =>
|
||||||
|
|
@ -76,9 +69,9 @@ const dueDate = computed(() =>
|
||||||
);
|
);
|
||||||
|
|
||||||
const inEvaluationTask = computed(
|
const inEvaluationTask = computed(
|
||||||
() => state.pageIndex >= 1 && state.pageIndex <= numTasks.value
|
() => stepIndex.value >= 1 && stepIndex.value <= numTasks.value
|
||||||
);
|
);
|
||||||
const taskIndex = computed(() => state.pageIndex - 1);
|
const taskIndex = computed(() => stepIndex.value - 1);
|
||||||
const task = computed(() => props.assignment.evaluation_tasks[taskIndex.value]);
|
const task = computed(() => props.assignment.evaluation_tasks[taskIndex.value]);
|
||||||
|
|
||||||
const taskExpertDataText = computed(() => {
|
const taskExpertDataText = computed(() => {
|
||||||
|
|
@ -108,7 +101,7 @@ function finishButtonEnabled() {
|
||||||
<div class="flex-1 overflow-y-auto">
|
<div class="flex-1 overflow-y-auto">
|
||||||
<section class="p-10">
|
<section class="p-10">
|
||||||
<EvaluationIntro
|
<EvaluationIntro
|
||||||
v-if="state.pageIndex === 0"
|
v-if="stepIndex === 0"
|
||||||
:assignment-user="props.assignmentUser"
|
:assignment-user="props.assignmentUser"
|
||||||
:assignment="props.assignment"
|
:assignment="props.assignment"
|
||||||
:assignment-completion="props.assignmentCompletion"
|
:assignment-completion="props.assignmentCompletion"
|
||||||
|
|
@ -119,7 +112,7 @@ function finishButtonEnabled() {
|
||||||
v-else-if="inEvaluationTask"
|
v-else-if="inEvaluationTask"
|
||||||
:assignment-user="props.assignmentUser"
|
:assignment-user="props.assignmentUser"
|
||||||
:assignment="props.assignment"
|
:assignment="props.assignment"
|
||||||
:task-index="state.pageIndex - 1"
|
:task-index="stepIndex - 1"
|
||||||
:allow-edit="
|
:allow-edit="
|
||||||
props.assignmentCompletion.completion_status !== 'evaluation_submitted'
|
props.assignmentCompletion.completion_status !== 'evaluation_submitted'
|
||||||
"
|
"
|
||||||
|
|
@ -135,7 +128,7 @@ function finishButtonEnabled() {
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav v-if="state.pageIndex > 0" class="sticky bottom-0 border-t bg-gray-200 p-6">
|
<nav v-if="stepIndex > 0" class="sticky bottom-0 border-t bg-gray-200 p-6">
|
||||||
<div class="relative flex flex-row place-content-end">
|
<div class="relative flex flex-row place-content-end">
|
||||||
<button
|
<button
|
||||||
v-if="true"
|
v-if="true"
|
||||||
|
|
@ -147,7 +140,7 @@ function finishButtonEnabled() {
|
||||||
{{ $t("general.backCapitalized") }}
|
{{ $t("general.backCapitalized") }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="state.pageIndex <= numTasks"
|
v-if="stepIndex <= numTasks"
|
||||||
:disabled="!nextButtonEnabled()"
|
:disabled="!nextButtonEnabled()"
|
||||||
class="btn-secondary z-10 flex items-center"
|
class="btn-secondary z-10 flex items-center"
|
||||||
data-cy="next-step"
|
data-cy="next-step"
|
||||||
|
|
@ -158,7 +151,7 @@ function finishButtonEnabled() {
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
v-if="state.pageIndex > numTasks"
|
v-if="stepIndex > numTasks"
|
||||||
:disabled="!finishButtonEnabled()"
|
:disabled="!finishButtonEnabled()"
|
||||||
class="btn-secondary z-10"
|
class="btn-secondary z-10"
|
||||||
data-cy="next-step"
|
data-cy="next-step"
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 0 = introduction, 1 - n = tasks, n+1 = submission
|
// 0 = introduction, 1 - n = tasks, n+1 = submission
|
||||||
const pageIndex = useRouteQuery("page", "0", { transform: Number, mode: "push" });
|
const stepIndex = useRouteQuery("step", "0", { transform: Number, mode: "push" });
|
||||||
|
|
||||||
const assignmentCompletion = computed(() => assignmentStore.assignmentCompletion);
|
const assignmentCompletion = computed(() => assignmentStore.assignmentCompletion);
|
||||||
const completionStatus = computed(() => {
|
const completionStatus = computed(() => {
|
||||||
|
|
@ -64,10 +64,10 @@ onMounted(async () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
pageIndex.value === 0 &&
|
stepIndex.value === 0 &&
|
||||||
(completionStatus.value ?? "in_progress") !== "in_progress"
|
(completionStatus.value ?? "in_progress") !== "in_progress"
|
||||||
) {
|
) {
|
||||||
pageIndex.value = numPages.value - 1;
|
stepIndex.value = numPages.value - 1;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(error);
|
log.error(error);
|
||||||
|
|
@ -76,9 +76,9 @@ onMounted(async () => {
|
||||||
|
|
||||||
const numTasks = computed(() => state.assignment?.tasks?.length ?? 0);
|
const numTasks = computed(() => state.assignment?.tasks?.length ?? 0);
|
||||||
const numPages = computed(() => numTasks.value + 2);
|
const numPages = computed(() => numTasks.value + 2);
|
||||||
const showPreviousButton = computed(() => pageIndex.value != 0);
|
const showPreviousButton = computed(() => stepIndex.value != 0);
|
||||||
const showNextButton = computed(() => pageIndex.value + 1 < numPages.value);
|
const showNextButton = computed(() => stepIndex.value + 1 < numPages.value);
|
||||||
const showExitButton = computed(() => numPages.value === pageIndex.value + 1);
|
const showExitButton = computed(() => numPages.value === stepIndex.value + 1);
|
||||||
const dueDate = computed(() =>
|
const dueDate = computed(() =>
|
||||||
dayjs(state.courseSessionAssignmentDetails?.submissionDeadlineDateTimeUtc)
|
dayjs(state.courseSessionAssignmentDetails?.submissionDeadlineDateTimeUtc)
|
||||||
);
|
);
|
||||||
|
|
@ -86,41 +86,41 @@ const courseSessionId = computed(
|
||||||
() => courseSessionsStore.currentCourseSession?.id ?? 0
|
() => courseSessionsStore.currentCourseSession?.id ?? 0
|
||||||
);
|
);
|
||||||
const currentTask = computed(() => {
|
const currentTask = computed(() => {
|
||||||
if (pageIndex.value > 0 && pageIndex.value <= numTasks.value) {
|
if (stepIndex.value > 0 && stepIndex.value <= numTasks.value) {
|
||||||
return state.assignment?.tasks[pageIndex.value - 1];
|
return state.assignment?.tasks[stepIndex.value - 1];
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
log.debug("handleBack");
|
log.debug("handleBack");
|
||||||
if (pageIndex.value > 0) {
|
if (stepIndex.value > 0) {
|
||||||
pageIndex.value -= 1;
|
stepIndex.value -= 1;
|
||||||
}
|
}
|
||||||
log.debug(`pageIndex: ${pageIndex.value}`);
|
log.debug(`pageIndex: ${stepIndex.value}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleContinue = () => {
|
const handleContinue = () => {
|
||||||
log.debug("handleContinue");
|
log.debug("handleContinue");
|
||||||
if (pageIndex.value + 1 < numPages.value) {
|
if (stepIndex.value + 1 < numPages.value) {
|
||||||
pageIndex.value += 1;
|
stepIndex.value += 1;
|
||||||
}
|
}
|
||||||
log.debug(`pageIndex: ${pageIndex.value}`);
|
log.debug(`pageIndex: ${stepIndex.value}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const jumpToTask = (task: AssignmentTask) => {
|
const jumpToTask = (task: AssignmentTask) => {
|
||||||
log.debug("jumpToTask", task);
|
log.debug("jumpToTask", task);
|
||||||
const index = state.assignment?.tasks.findIndex((t) => t.id === task.id);
|
const index = state.assignment?.tasks.findIndex((t) => t.id === task.id);
|
||||||
if (index && index >= 0) {
|
if (index && index >= 0) {
|
||||||
pageIndex.value = index + 1;
|
stepIndex.value = index + 1;
|
||||||
}
|
}
|
||||||
log.debug(`pageIndex: ${pageIndex.value}`);
|
log.debug(`pageIndex: ${stepIndex.value}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTitle = () => {
|
const getTitle = () => {
|
||||||
if (0 === pageIndex.value) {
|
if (0 === stepIndex.value) {
|
||||||
return t("general.introduction");
|
return t("general.introduction");
|
||||||
} else if (pageIndex.value === numPages.value - 1) {
|
} else if (stepIndex.value === numPages.value - 1) {
|
||||||
return t("general.submission");
|
return t("general.submission");
|
||||||
}
|
}
|
||||||
return currentTask?.value?.value.title ?? "Unknown";
|
return currentTask?.value?.value.title ?? "Unknown";
|
||||||
|
|
@ -137,7 +137,7 @@ const assignmentUser = computed(() => {
|
||||||
<div v-if="state.assignment">
|
<div v-if="state.assignment">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<LearningContentMultiLayout
|
<LearningContentMultiLayout
|
||||||
:current-step="pageIndex"
|
:current-step="stepIndex"
|
||||||
:subtitle="state.assignment?.title ?? ''"
|
:subtitle="state.assignment?.title ?? ''"
|
||||||
:title="getTitle()"
|
:title="getTitle()"
|
||||||
learning-content-type="assignment"
|
learning-content-type="assignment"
|
||||||
|
|
@ -147,7 +147,7 @@ const assignmentUser = computed(() => {
|
||||||
:show-start-button="false"
|
:show-start-button="false"
|
||||||
:show-previous-button="showPreviousButton"
|
:show-previous-button="showPreviousButton"
|
||||||
:base-url="props.learningContent.frontend_url"
|
:base-url="props.learningContent.frontend_url"
|
||||||
query-param="page"
|
step-query-param="step"
|
||||||
start-badge-text="Einleitung"
|
start-badge-text="Einleitung"
|
||||||
end-badge-text="Abgabe"
|
end-badge-text="Abgabe"
|
||||||
close-button-variant="close"
|
close-button-variant="close"
|
||||||
|
|
@ -157,7 +157,7 @@ const assignmentUser = computed(() => {
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div>
|
<div>
|
||||||
<AssignmentIntroductionView
|
<AssignmentIntroductionView
|
||||||
v-if="pageIndex === 0 && state.assignment"
|
v-if="stepIndex === 0 && state.assignment"
|
||||||
:due-date="dueDate"
|
:due-date="dueDate"
|
||||||
:assignment="state.assignment!"
|
:assignment="state.assignment!"
|
||||||
></AssignmentIntroductionView>
|
></AssignmentIntroductionView>
|
||||||
|
|
@ -167,7 +167,7 @@ const assignmentUser = computed(() => {
|
||||||
:assignment-id="props.assignmentId"
|
:assignment-id="props.assignmentId"
|
||||||
></AssignmentTaskView>
|
></AssignmentTaskView>
|
||||||
<AssignmentSubmissionView
|
<AssignmentSubmissionView
|
||||||
v-if="pageIndex + 1 === numPages && state.assignment && courseSessionId"
|
v-if="stepIndex + 1 === numPages && state.assignment && courseSessionId"
|
||||||
:due-date="dueDate"
|
:due-date="dueDate"
|
||||||
:assignment="state.assignment!"
|
:assignment="state.assignment!"
|
||||||
:assignment-completion-data="assignmentCompletion?.completion_data ?? {}"
|
:assignment-completion-data="assignmentCompletion?.completion_data ?? {}"
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ interface Props {
|
||||||
endBadgeText?: string;
|
endBadgeText?: string;
|
||||||
closeButtonVariant?: ClosingButtonVariant;
|
closeButtonVariant?: ClosingButtonVariant;
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
queryParam?: string;
|
stepQueryParam?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
@ -58,7 +58,7 @@ const emit = defineEmits(["previous", "next", "exit"]);
|
||||||
:steps="stepsCount"
|
:steps="stepsCount"
|
||||||
:end-badge-text="props.endBadgeText"
|
:end-badge-text="props.endBadgeText"
|
||||||
:base-url="props.baseUrl"
|
:base-url="props.baseUrl"
|
||||||
:query-param="props.queryParam"
|
:query-param="props.stepQueryParam"
|
||||||
class="overflow-hidden pb-12"
|
class="overflow-hidden pb-12"
|
||||||
></ItNavigationProgress>
|
></ItNavigationProgress>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
|
|
||||||
|
|
@ -8,37 +8,36 @@ import LearningContentContainer from "@/pages/learningPath/learningContentPage/L
|
||||||
import LearningContentMultiLayout from "@/pages/learningPath/learningContentPage/layouts/LearningContentMultiLayout.vue";
|
import LearningContentMultiLayout from "@/pages/learningPath/learningContentPage/layouts/LearningContentMultiLayout.vue";
|
||||||
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||||
import eventBus from "@/utils/eventBus";
|
import eventBus from "@/utils/eventBus";
|
||||||
import { computed, onUnmounted, reactive } from "vue";
|
import { useRouteQuery } from "@vueuse/router";
|
||||||
|
import { computed, onUnmounted } from "vue";
|
||||||
|
|
||||||
log.debug("LearningContent.vue setup");
|
log.debug("LearningContent.vue setup");
|
||||||
|
|
||||||
const circleStore = useCircleStore();
|
const circleStore = useCircleStore();
|
||||||
const courseSession = useCourseSessionsStore();
|
const courseSession = useCourseSessionsStore();
|
||||||
|
|
||||||
const state = reactive({
|
const questionIndex = useRouteQuery("step", "0", { transform: Number, mode: "push" });
|
||||||
questionIndex: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
learningUnit: LearningUnit;
|
learningUnit: LearningUnit;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const questions = computed(() => props.learningUnit?.children);
|
const questions = computed(() => props.learningUnit?.children);
|
||||||
const currentQuestion = computed(() => questions.value[state.questionIndex]);
|
const currentQuestion = computed(() => questions.value[questionIndex.value]);
|
||||||
const showPreviousButton = computed(() => state.questionIndex != 0);
|
const showPreviousButton = computed(() => questionIndex.value != 0);
|
||||||
const showNextButton = computed(
|
const showNextButton = computed(
|
||||||
() => state.questionIndex + 1 < questions.value?.length && questions.value?.length > 1
|
() => questionIndex.value + 1 < questions.value?.length && questions.value?.length > 1
|
||||||
);
|
);
|
||||||
const showExitButton = computed(
|
const showExitButton = computed(
|
||||||
() =>
|
() =>
|
||||||
questions.value?.length === 1 || questions.value?.length === state.questionIndex + 1
|
questions.value?.length === 1 || questions.value?.length === questionIndex.value + 1
|
||||||
);
|
);
|
||||||
|
|
||||||
function handleContinue() {
|
function handleContinue() {
|
||||||
log.debug("handleContinue");
|
log.debug("handleContinue");
|
||||||
if (state.questionIndex + 1 < questions.value.length) {
|
if (questionIndex.value + 1 < questions.value.length) {
|
||||||
log.debug("increment questionIndex", state.questionIndex);
|
log.debug("increment questionIndex", questionIndex.value);
|
||||||
state.questionIndex += 1;
|
questionIndex.value += 1;
|
||||||
} else {
|
} else {
|
||||||
log.debug("continue to next learning content");
|
log.debug("continue to next learning content");
|
||||||
circleStore.continueFromSelfEvaluation(props.learningUnit);
|
circleStore.continueFromSelfEvaluation(props.learningUnit);
|
||||||
|
|
@ -47,8 +46,8 @@ function handleContinue() {
|
||||||
|
|
||||||
function handleBack() {
|
function handleBack() {
|
||||||
log.debug("handleBack");
|
log.debug("handleBack");
|
||||||
if (state.questionIndex > 0 && state.questionIndex < questions.value.length) {
|
if (questionIndex.value > 0 && questionIndex.value < questions.value.length) {
|
||||||
state.questionIndex -= 1;
|
questionIndex.value -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +68,7 @@ onUnmounted(() => {
|
||||||
@exit="circleStore.closeSelfEvaluation(props.learningUnit)"
|
@exit="circleStore.closeSelfEvaluation(props.learningUnit)"
|
||||||
>
|
>
|
||||||
<LearningContentMultiLayout
|
<LearningContentMultiLayout
|
||||||
:current-step="state.questionIndex"
|
:current-step="questionIndex"
|
||||||
:subtitle="$t('selfEvaluation.title')"
|
:subtitle="$t('selfEvaluation.title')"
|
||||||
:title="$t('selfEvaluation.title', { title: learningUnit.title })"
|
:title="$t('selfEvaluation.title', { title: learningUnit.title })"
|
||||||
learning-content-type="learningmodule"
|
learning-content-type="learningmodule"
|
||||||
|
|
@ -78,6 +77,7 @@ onUnmounted(() => {
|
||||||
:show-exit-button="showExitButton"
|
:show-exit-button="showExitButton"
|
||||||
:show-start-button="false"
|
:show-start-button="false"
|
||||||
:show-previous-button="showPreviousButton"
|
:show-previous-button="showPreviousButton"
|
||||||
|
:base-url="props.learningUnit.evaluate_url"
|
||||||
@previous="handleBack()"
|
@previous="handleBack()"
|
||||||
@next="handleContinue()"
|
@next="handleContinue()"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@ class FeedbackFactory(DjangoModelFactory):
|
||||||
"satisfaction": FuzzyInteger(2, 4),
|
"satisfaction": FuzzyInteger(2, 4),
|
||||||
"goal_attainment": FuzzyInteger(3, 4),
|
"goal_attainment": FuzzyInteger(3, 4),
|
||||||
"proficiency": FuzzyChoice([20, 40, 60, 80]),
|
"proficiency": FuzzyChoice([20, 40, 60, 80]),
|
||||||
"received_materials": FuzzyChoice([True, False]),
|
"preparation_task_clarity": FuzzyChoice([True, False]),
|
||||||
"materials_rating": FuzzyInteger(2, 4),
|
|
||||||
"instructor_competence": FuzzyInteger(3, 4),
|
"instructor_competence": FuzzyInteger(3, 4),
|
||||||
"instructor_respect": FuzzyInteger(3, 4),
|
"instructor_respect": FuzzyInteger(3, 4),
|
||||||
"instructor_open_feedback": FuzzyChoice(
|
"instructor_open_feedback": FuzzyChoice(
|
||||||
|
|
@ -23,18 +22,18 @@ class FeedbackFactory(DjangoModelFactory):
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
"would_recommend": FuzzyChoice([True, False]),
|
"would_recommend": FuzzyChoice([True, False]),
|
||||||
"course_positive_feedback": FuzzyChoice(
|
|
||||||
[
|
|
||||||
"Die Präsentation war super",
|
|
||||||
"Das Beispiel mit der Katze fand ich sehr gut veranschaulicht!",
|
|
||||||
]
|
|
||||||
),
|
|
||||||
"course_negative_feedback": FuzzyChoice(
|
"course_negative_feedback": FuzzyChoice(
|
||||||
[
|
[
|
||||||
"Es wäre praktisch, Zugang zu einer FAQ zu haben.",
|
"Es wäre praktisch, Zugang zu einer FAQ zu haben.",
|
||||||
"Es wäre schön, mehr Videos hinzuzufügen.",
|
"Es wäre schön, mehr Videos hinzuzufügen.",
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
"course_positive_feedback": FuzzyChoice(
|
||||||
|
[
|
||||||
|
"Die Präsentation war super",
|
||||||
|
"Das Beispiel mit der Katze fand ich sehr gut veranschaulicht!",
|
||||||
|
]
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,18 +53,6 @@ class FeedbackResponse(models.Model):
|
||||||
)
|
)
|
||||||
super(FeedbackResponse, self).save(*args, **kwargs)
|
super(FeedbackResponse, self).save(*args, **kwargs)
|
||||||
|
|
||||||
# satisfaction = FeedbackIntegerField()
|
|
||||||
# goal_attainment = FeedbackIntegerField()
|
|
||||||
# proficiency = models.IntegerField(null=True)
|
|
||||||
# received_materials = models.BooleanField(null=True)
|
|
||||||
# materials_rating = FeedbackIntegerField()
|
|
||||||
# instructor_competence = FeedbackIntegerField()
|
|
||||||
# instructor_respect = FeedbackIntegerField()
|
|
||||||
# instructor_open_feedback = models.TextField(blank=True)
|
|
||||||
# would_recommend = models.BooleanField(null=True)
|
|
||||||
# course_positive_feedback = models.TextField(blank=True)
|
|
||||||
# course_negative_feedback = models.TextField(blank=True)
|
|
||||||
|
|
||||||
data = models.JSONField(default=dict)
|
data = models.JSONField(default=dict)
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class CourseFeedbackSerializer(serializers.Serializer):
|
||||||
satisfaction = FeedbackIntegerField()
|
satisfaction = FeedbackIntegerField()
|
||||||
goal_attainment = FeedbackIntegerField()
|
goal_attainment = FeedbackIntegerField()
|
||||||
proficiency = serializers.IntegerField(required=False, allow_null=True)
|
proficiency = serializers.IntegerField(required=False, allow_null=True)
|
||||||
received_materials = serializers.BooleanField(required=False, allow_null=True)
|
preparation_task_clarity = serializers.BooleanField()
|
||||||
materials_rating = FeedbackIntegerField()
|
materials_rating = FeedbackIntegerField()
|
||||||
instructor_competence = FeedbackIntegerField()
|
instructor_competence = FeedbackIntegerField()
|
||||||
instructor_respect = FeedbackIntegerField()
|
instructor_respect = FeedbackIntegerField()
|
||||||
|
|
|
||||||
|
|
@ -190,8 +190,7 @@ class FeedbackDetailApiTestCase(FeedbackApiBaseTestCase):
|
||||||
"satisfaction": [1, 4, 2],
|
"satisfaction": [1, 4, 2],
|
||||||
"goal_attainment": [2, 4, 3],
|
"goal_attainment": [2, 4, 3],
|
||||||
"proficiency": [20, 60, 80],
|
"proficiency": [20, 60, 80],
|
||||||
"received_materials": [True, False, True],
|
"preparation_task_clarity": [True, False, True],
|
||||||
"materials_rating": [3, 2, 1],
|
|
||||||
"instructor_competence": [1, 2, 3],
|
"instructor_competence": [1, 2, 3],
|
||||||
"instructor_respect": [40, 80, 100],
|
"instructor_respect": [40, 80, 100],
|
||||||
"instructor_open_feedback": ["super", "ok", "naja"],
|
"instructor_open_feedback": ["super", "ok", "naja"],
|
||||||
|
|
@ -214,14 +213,15 @@ class FeedbackDetailApiTestCase(FeedbackApiBaseTestCase):
|
||||||
"satisfaction": feedback_data["satisfaction"][i],
|
"satisfaction": feedback_data["satisfaction"][i],
|
||||||
"goal_attainment": feedback_data["goal_attainment"][i],
|
"goal_attainment": feedback_data["goal_attainment"][i],
|
||||||
"proficiency": feedback_data["proficiency"][i],
|
"proficiency": feedback_data["proficiency"][i],
|
||||||
"received_materials": feedback_data["received_materials"][i],
|
"preparation_task_clarity": feedback_data[
|
||||||
"materials_rating": feedback_data["materials_rating"][i],
|
"preparation_task_clarity"
|
||||||
|
][i],
|
||||||
"instructor_competence": feedback_data["instructor_competence"][i],
|
"instructor_competence": feedback_data["instructor_competence"][i],
|
||||||
"instructor_open_feedback": feedback_data[
|
"instructor_open_feedback": feedback_data[
|
||||||
"instructor_open_feedback"
|
"instructor_open_feedback"
|
||||||
][i],
|
][i],
|
||||||
"instructor_respect": feedback_data["instructor_respect"][i],
|
|
||||||
"would_recommend": feedback_data["would_recommend"][i],
|
"would_recommend": feedback_data["would_recommend"][i],
|
||||||
|
"instructor_respect": feedback_data["instructor_respect"][i],
|
||||||
"course_positive_feedback": feedback_data[
|
"course_positive_feedback": feedback_data[
|
||||||
"course_positive_feedback"
|
"course_positive_feedback"
|
||||||
][i],
|
][i],
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,13 @@ FEEDBACK_FIELDS = [
|
||||||
"satisfaction",
|
"satisfaction",
|
||||||
"goal_attainment",
|
"goal_attainment",
|
||||||
"proficiency",
|
"proficiency",
|
||||||
"received_materials",
|
|
||||||
"materials_rating",
|
|
||||||
"instructor_competence",
|
"instructor_competence",
|
||||||
"instructor_respect",
|
"instructor_respect",
|
||||||
"instructor_open_feedback",
|
"instructor_open_feedback",
|
||||||
"would_recommend",
|
"would_recommend",
|
||||||
"course_positive_feedback",
|
"course_positive_feedback",
|
||||||
"course_negative_feedback",
|
"course_negative_feedback",
|
||||||
|
"preparation_task_clarity",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue