Merged in VBV-518-trainer-cockpit-circle-auswahl (pull request #204)
Singe circle selection Approved-by: Daniel Egger
This commit is contained in:
commit
8c92b6664f
|
|
@ -22,8 +22,8 @@ onMounted(async () => {
|
|||
log.debug("CockpitParentPage mounted", props.courseSlug);
|
||||
|
||||
try {
|
||||
await cockpitStore.loadCourseSessionUsers(courseSession.value.id);
|
||||
cockpitStore.courseSessionUsers?.forEach((csu) => {
|
||||
const members = await cockpitStore.loadCourseSessionMembers(courseSession.value.id);
|
||||
members.forEach((csu) => {
|
||||
competenceStore.loadCompetenceProfilePage(
|
||||
props.courseSlug + "-competencenavi-competences",
|
||||
csu.user_id
|
||||
|
|
@ -31,7 +31,11 @@ onMounted(async () => {
|
|||
|
||||
learningPathStore.loadLearningPath(props.courseSlug + "-lp", csu.user_id);
|
||||
});
|
||||
learningPathStore.loadLearningPath(props.courseSlug + "-lp", useUserStore().id);
|
||||
await learningPathStore.loadLearningPath(
|
||||
props.courseSlug + "-lp",
|
||||
useUserStore().id
|
||||
);
|
||||
await cockpitStore.loadCircles(props.courseSlug, courseSession.value.id);
|
||||
} catch (error) {
|
||||
log.error(error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ onMounted(async () => {
|
|||
});
|
||||
|
||||
const user = computed(() => {
|
||||
return cockpitStore.courseSessionUsers?.find((csu) => csu.user_id === props.userId);
|
||||
return cockpitStore.courseSessionMembers?.find((csu) => csu.user_id === props.userId);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const learningPath = computed(() => {
|
|||
});
|
||||
|
||||
const user = computed(() => {
|
||||
return cockpitStore.courseSessionUsers?.find((csu) => csu.user_id === props.userId);
|
||||
return cockpitStore.courseSessionMembers?.find((csu) => csu.user_id === props.userId);
|
||||
});
|
||||
|
||||
function setActiveClasses(isActive: boolean) {
|
||||
|
|
|
|||
|
|
@ -85,10 +85,10 @@ const assignmentDetail = computed(() =>
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="cockpitStore.courseSessionUsers?.length" class="mt-6">
|
||||
<div v-if="cockpitStore.courseSessionMembers?.length" class="mt-6">
|
||||
<ul>
|
||||
<ItPersonRow
|
||||
v-for="csu in cockpitStore.courseSessionUsers"
|
||||
v-for="csu in cockpitStore.courseSessionMembers"
|
||||
:key="csu.user_id + csu.session_title"
|
||||
:name="`${csu.first_name} ${csu.last_name}`"
|
||||
:avatar-url="csu.avatar_url"
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ watch(
|
|||
|
||||
<div class="mt-4 flex flex-col bg-white p-6">
|
||||
<div
|
||||
v-for="(csu, index) in cockpitStore.courseSessionUsers"
|
||||
v-for="(csu, index) in cockpitStore.courseSessionMembers"
|
||||
:key="csu.user_id + csu.session_title"
|
||||
>
|
||||
<ItPersonRow
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ const courseSession = useCurrentCourseSession();
|
|||
|
||||
const circleDates = computed(() => {
|
||||
const dueDates = courseSession.value.due_dates.filter((dueDate) => {
|
||||
return cockpitStore.selectedCircles.includes(
|
||||
dueDate?.circle?.translation_key ?? ""
|
||||
if (!cockpitStore.selectedCircle) return false;
|
||||
return (
|
||||
cockpitStore.selectedCircle.translation_key == dueDate?.circle?.translation_key
|
||||
);
|
||||
});
|
||||
return dueDates.slice(0, 4);
|
||||
|
|
|
|||
|
|
@ -8,11 +8,9 @@ import SubmissionsOverview from "@/pages/cockpit/cockpitPage/SubmissionsOverview
|
|||
import { useCockpitStore } from "@/stores/cockpit";
|
||||
import { useCompetenceStore } from "@/stores/competence";
|
||||
import { useLearningPathStore } from "@/stores/learningPath";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import groupBy from "lodash/groupBy";
|
||||
import log from "loglevel";
|
||||
import { computed } from "vue";
|
||||
import CockpitDates from "@/pages/cockpit/cockpitPage/CockpitDates.vue";
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
|
|
@ -20,217 +18,165 @@ const props = defineProps<{
|
|||
|
||||
log.debug("CockpitIndexPage created", props.courseSlug);
|
||||
|
||||
const userStore = useUserStore();
|
||||
const cockpitStore = useCockpitStore();
|
||||
const competenceStore = useCompetenceStore();
|
||||
const learningPathStore = useLearningPathStore();
|
||||
const courseSession = useCurrentCourseSession();
|
||||
|
||||
function userCountStatusForCircle(userId: string, translationKey: string) {
|
||||
function userCountStatusForCircle(userId: string) {
|
||||
if (!cockpitStore.selectedCircle) return { FAIL: 0, SUCCESS: 0, UNKNOWN: 0 };
|
||||
const criteria = competenceStore.flatPerformanceCriteria(
|
||||
userId,
|
||||
cockpitStore.selectedCircles
|
||||
cockpitStore.selectedCircle.id
|
||||
);
|
||||
const grouped = groupBy(criteria, "circle.translation_key");
|
||||
|
||||
return competenceStore.calcStatusCount(grouped[translationKey] as []);
|
||||
}
|
||||
|
||||
const circles = computed(() => {
|
||||
const learningPathCircles = learningPathStore
|
||||
.learningPathForUser(props.courseSlug, userStore.id)
|
||||
?.circles.map((c) => {
|
||||
return {
|
||||
id: c.id,
|
||||
title: c.title,
|
||||
slug: c.slug,
|
||||
translation_key: c.translation_key,
|
||||
};
|
||||
});
|
||||
|
||||
if (cockpitStore.cockpitSessionUser?.circles?.length) {
|
||||
return cockpitStore.cockpitSessionUser.circles;
|
||||
} else if (learningPathCircles) {
|
||||
return learningPathCircles;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
const selectedCirclesTitles = computed(() => {
|
||||
return circles.value
|
||||
.filter((c) => cockpitStore.selectedCircles.includes(c.translation_key))
|
||||
.map((c) => c.title) as string[];
|
||||
});
|
||||
|
||||
function setActiveClasses(translationKey: string) {
|
||||
return cockpitStore.selectedCircles.indexOf(translationKey) > -1
|
||||
? ["bg-blue-900", "text-white"]
|
||||
: ["text-bg-900"];
|
||||
return competenceStore.calcStatusCount(criteria);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-gray-200">
|
||||
<div class="container-large">
|
||||
<div class="mb-9 flex items-end justify-between">
|
||||
<div class="mb-9 flex flex-col lg:flex-row lg:items-center lg:justify-between">
|
||||
<h1>Cockpit</h1>
|
||||
<div class="flex flex-row">
|
||||
<p class="text-base">{{ $t("general.circles") }}:</p>
|
||||
<ul class="ml-4 flex flex-row text-base font-bold leading-7">
|
||||
<li
|
||||
v-for="circle in circles"
|
||||
:key="circle.translation_key"
|
||||
class="mr-4 last:mr-0"
|
||||
>
|
||||
<button
|
||||
class="mr-4 rounded-full border-2 border-blue-900 px-4 last:mr-0"
|
||||
:class="setActiveClasses(circle.translation_key)"
|
||||
@click="cockpitStore.toggleCircleSelection(circle.translation_key)"
|
||||
<ItDropdownSelect
|
||||
v-model="cockpitStore.selectedCircle"
|
||||
class="mt-4 w-full lg:mt-0 lg:w-96"
|
||||
:items="cockpitStore.circles"
|
||||
></ItDropdownSelect>
|
||||
</div>
|
||||
<template v-if="cockpitStore.selectedCircle">
|
||||
<!-- Status -->
|
||||
<div class="mb-4 gap-4 lg:grid lg:grid-cols-3 lg:grid-rows-none">
|
||||
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
|
||||
<div>
|
||||
<h3 class="heading-3 mb-4 flex items-center gap-2">
|
||||
{{ $t("Trainerunterlagen") }}
|
||||
</h3>
|
||||
<div class="mb-4">
|
||||
{{ $t("cockpit.trainerFilesText") }}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
href="https://vbvbern.sharepoint.com/sites/myVBV-AFA_K-CI"
|
||||
class="btn-secondary min-w-min"
|
||||
target="_blank"
|
||||
>
|
||||
{{ circle.title }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Status -->
|
||||
<div class="mb-4 gap-4 lg:grid lg:grid-cols-3 lg:grid-rows-none">
|
||||
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
|
||||
<div>
|
||||
<h3 class="heading-3 mb-4 flex items-center gap-2">
|
||||
{{ $t("Trainerunterlagen") }}
|
||||
</h3>
|
||||
<div class="mb-4">
|
||||
{{ $t("cockpit.trainerFilesText") }}
|
||||
{{ $t("MS Teams öffnen") }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
href="https://vbvbern.sharepoint.com/sites/myVBV-AFA_K-CI"
|
||||
class="btn-secondary min-w-min"
|
||||
target="_blank"
|
||||
>
|
||||
{{ $t("MS Teams öffnen") }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
|
||||
<div>
|
||||
<h3 class="heading-3 mb-4 flex items-center gap-2">
|
||||
{{ $t("Anwesenheitskontrolle Präsenzkurse") }}
|
||||
</h3>
|
||||
<div class="mb-4">
|
||||
{{
|
||||
$t(
|
||||
"Hier überprüfst und bestätigst du die Anwesenheit deiner Teilnehmenden."
|
||||
)
|
||||
}}
|
||||
<div class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0">
|
||||
<div>
|
||||
<h3 class="heading-3 mb-4 flex items-center gap-2">
|
||||
{{ $t("Anwesenheitskontrolle Präsenzkurse") }}
|
||||
</h3>
|
||||
<div class="mb-4">
|
||||
{{
|
||||
$t(
|
||||
"Hier überprüfst und bestätigst du die Anwesenheit deiner Teilnehmenden."
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<router-link
|
||||
:to="`/course/${props.courseSlug}/cockpit/attendance`"
|
||||
class="btn-secondary min-w-min"
|
||||
>
|
||||
{{ $t("Anwesenheit prüfen") }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<router-link
|
||||
:to="`/course/${props.courseSlug}/cockpit/attendance`"
|
||||
class="btn-secondary min-w-min"
|
||||
>
|
||||
{{ $t("Anwesenheit prüfen") }}
|
||||
</router-link>
|
||||
<div class="bg-white p-6">
|
||||
<CockpitDates></CockpitDates>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white p-6">
|
||||
<CockpitDates></CockpitDates>
|
||||
</div>
|
||||
</div>
|
||||
<SubmissionsOverview
|
||||
:course-session="courseSession"
|
||||
:selected-circles="selectedCirclesTitles"
|
||||
></SubmissionsOverview>
|
||||
<div class="pt-4">
|
||||
<!-- progress -->
|
||||
<div v-if="cockpitStore.courseSessionUsers" class="bg-white p-6">
|
||||
<h1 class="heading-3 mb-5">{{ $t("cockpit.progress") }}</h1>
|
||||
<ul>
|
||||
<ItPersonRow
|
||||
v-for="csu in cockpitStore.courseSessionUsers"
|
||||
:key="csu.user_id + csu.session_title"
|
||||
:name="`${csu.first_name} ${csu.last_name}`"
|
||||
:avatar-url="csu.avatar_url"
|
||||
>
|
||||
<template #center>
|
||||
<div
|
||||
class="mt-2 flex w-full flex-col items-center justify-between lg:mt-0 lg:flex-row"
|
||||
>
|
||||
<ul class="w-full">
|
||||
<li
|
||||
v-for="(circle, i) of cockpitStore.selectedCircles"
|
||||
:key="i"
|
||||
class="flex flex-col justify-between lg:h-12 lg:flex-row lg:items-center"
|
||||
>
|
||||
<LearningPathDiagram
|
||||
v-if="
|
||||
learningPathStore.learningPathForUser(
|
||||
props.courseSlug,
|
||||
csu.user_id
|
||||
)
|
||||
"
|
||||
:learning-path="
|
||||
<SubmissionsOverview
|
||||
:course-session="courseSession"
|
||||
:selected-circle="cockpitStore.selectedCircle.id"
|
||||
></SubmissionsOverview>
|
||||
<div class="pt-4">
|
||||
<!-- progress -->
|
||||
<div v-if="cockpitStore.courseSessionMembers" class="bg-white p-6">
|
||||
<h1 class="heading-3 mb-5">{{ $t("cockpit.progress") }}</h1>
|
||||
<ul>
|
||||
<ItPersonRow
|
||||
v-for="csu in cockpitStore.courseSessionMembers"
|
||||
:key="csu.user_id + csu.session_title"
|
||||
:name="`${csu.first_name} ${csu.last_name}`"
|
||||
:avatar-url="csu.avatar_url"
|
||||
>
|
||||
<template #center>
|
||||
<div
|
||||
class="mt-2 flex w-full flex-col items-center justify-between lg:mt-0 lg:flex-row"
|
||||
>
|
||||
<LearningPathDiagram
|
||||
v-if="
|
||||
learningPathStore.learningPathForUser(
|
||||
props.courseSlug,
|
||||
csu.user_id
|
||||
)
|
||||
"
|
||||
:learning-path="
|
||||
learningPathStore.learningPathForUser(
|
||||
props.courseSlug,
|
||||
csu.user_id
|
||||
) as LearningPath
|
||||
"
|
||||
:postfix="`cockpit-${csu.user_id}-${i}`"
|
||||
:profile-user-id="`${csu.user_id}`"
|
||||
:show-circle-translation-keys="[circle]"
|
||||
:pull-up="false"
|
||||
diagram-type="singleSmall"
|
||||
class="mr-4"
|
||||
></LearningPathDiagram>
|
||||
<p class="lg:min-w-[150px]">
|
||||
{{ selectedCirclesTitles[i] }}
|
||||
</p>
|
||||
<div class="ml-4 flex flex-row items-center">
|
||||
<div class="mr-6 flex flex-row items-center">
|
||||
<it-icon-smiley-thinking
|
||||
class="mr-2 inline-block h-8 w-8"
|
||||
></it-icon-smiley-thinking>
|
||||
<p class="text-bold inline-block w-6">
|
||||
{{ userCountStatusForCircle(csu.user_id, circle).FAIL }}
|
||||
</p>
|
||||
</div>
|
||||
<li class="mr-6 flex flex-row items-center">
|
||||
<it-icon-smiley-happy
|
||||
class="mr-2 inline-block h-8 w-8"
|
||||
></it-icon-smiley-happy>
|
||||
<p class="text-bold inline-block w-6">
|
||||
{{ userCountStatusForCircle(csu.user_id, circle).SUCCESS }}
|
||||
</p>
|
||||
</li>
|
||||
<li class="flex flex-row items-center">
|
||||
<it-icon-smiley-neutral
|
||||
class="mr-2 inline-block h-8 w-8"
|
||||
></it-icon-smiley-neutral>
|
||||
<p class="text-bold inline-block w-6">
|
||||
{{ userCountStatusForCircle(csu.user_id, circle).UNKNOWN }}
|
||||
</p>
|
||||
</li>
|
||||
:show-circle-translation-keys="[
|
||||
cockpitStore.selectedCircle.translation_key,
|
||||
]"
|
||||
diagram-type="singleSmall"
|
||||
class="mr-4"
|
||||
></LearningPathDiagram>
|
||||
<p class="lg:min-w-[150px]">
|
||||
{{ cockpitStore.selectedCircle.name }}
|
||||
</p>
|
||||
<div class="ml-4 flex flex-row items-center">
|
||||
<div class="mr-6 flex flex-row items-center">
|
||||
<it-icon-smiley-thinking
|
||||
class="mr-2 inline-block h-8 w-8"
|
||||
></it-icon-smiley-thinking>
|
||||
<p class="text-bold inline-block w-6">
|
||||
{{ userCountStatusForCircle(csu.user_id).FAIL }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<template #link>
|
||||
<router-link
|
||||
:to="`/course/${props.courseSlug}/cockpit/profile/${csu.user_id}`"
|
||||
class="link w-full lg:text-right"
|
||||
>
|
||||
{{ $t("general.profileLink") }}
|
||||
</router-link>
|
||||
</template>
|
||||
</ItPersonRow>
|
||||
</ul>
|
||||
<li class="mr-6 flex flex-row items-center">
|
||||
<it-icon-smiley-happy
|
||||
class="mr-2 inline-block h-8 w-8"
|
||||
></it-icon-smiley-happy>
|
||||
<p class="text-bold inline-block w-6">
|
||||
{{ userCountStatusForCircle(csu.user_id).SUCCESS }}
|
||||
</p>
|
||||
</li>
|
||||
<li class="flex flex-row items-center">
|
||||
<it-icon-smiley-neutral
|
||||
class="mr-2 inline-block h-8 w-8"
|
||||
></it-icon-smiley-neutral>
|
||||
<p class="text-bold inline-block w-6">
|
||||
{{ userCountStatusForCircle(csu.user_id).UNKNOWN }}
|
||||
</p>
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #link>
|
||||
<router-link
|
||||
:to="`/course/${props.courseSlug}/cockpit/profile/${csu.user_id}`"
|
||||
class="link w-full lg:text-right"
|
||||
>
|
||||
{{ $t("general.profileLink") }}
|
||||
</router-link>
|
||||
</template>
|
||||
</ItPersonRow>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<span v-else class="text-lg text-orange-600">
|
||||
{{ $t("a.Kein Circle verfügbar oder ausgewählt.") }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const cockpitStore = useCockpitStore();
|
|||
const completeFeedbacks = ref(0);
|
||||
|
||||
const numFeedbacks = computed(() => {
|
||||
return cockpitStore.courseSessionUsers?.length ?? 0;
|
||||
return cockpitStore.courseSessionMembers?.length ?? 0;
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ interface Submittable {
|
|||
|
||||
const props = defineProps<{
|
||||
courseSession: CourseSession;
|
||||
selectedCircles: string[];
|
||||
selectedCircle: number;
|
||||
}>();
|
||||
|
||||
log.debug("SubmissionsOverview created", props.courseSession.id);
|
||||
|
|
@ -46,7 +46,7 @@ const submittables = computed(() => {
|
|||
return [];
|
||||
}
|
||||
return learningPath.circles
|
||||
.filter((circle) => props.selectedCircles.includes(circle.title))
|
||||
.filter((circle) => props.selectedCircle == circle.id)
|
||||
.flatMap((circle) => {
|
||||
const learningContents = circle.flatLearningContents.filter(
|
||||
(lc) =>
|
||||
|
|
@ -128,7 +128,7 @@ const getIconName = (lc: LearningContent) => {
|
|||
|
||||
<template>
|
||||
<div class="bg-white px-6 py-2">
|
||||
<div v-if="cockpitStore.courseSessionUsers" class="divide-y divide-gray-500">
|
||||
<div v-if="cockpitStore.courseSessionMembers" class="divide-y divide-gray-500">
|
||||
<div
|
||||
v-for="submittable in submittables"
|
||||
:key="submittable.id"
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ export async function loadAssignmentCompletionStatusData(
|
|||
`/api/assignment/${assignmentId}/${courseSessionId}/status/`
|
||||
)) as UserAssignmentCompletionStatus[];
|
||||
|
||||
const courseSessionUsers = await cockpitStore.loadCourseSessionUsers(courseSessionId);
|
||||
const courseSessionUsers = await cockpitStore.loadCourseSessionMembers(
|
||||
courseSessionId
|
||||
);
|
||||
|
||||
const gradedUsers: GradedUser[] = [];
|
||||
const assignmentSubmittedUsers: CourseSessionUser[] = [];
|
||||
|
|
|
|||
|
|
@ -2,27 +2,58 @@ import { itGetCached } from "@/fetchHelpers";
|
|||
import type { CourseSessionUser, ExpertSessionUser } from "@/types";
|
||||
import log from "loglevel";
|
||||
|
||||
import { useLearningPathStore } from "@/stores/learningPath";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export type CockpitStoreState = {
|
||||
courseSessionUsers: CourseSessionUser[] | undefined;
|
||||
cockpitSessionUser: ExpertSessionUser | undefined;
|
||||
selectedCircles: string[];
|
||||
courseSessionMembers: CourseSessionUser[] | undefined;
|
||||
selectedCircle:
|
||||
| {
|
||||
id: number;
|
||||
name: string;
|
||||
slug: string;
|
||||
translation_key: string;
|
||||
}
|
||||
| undefined;
|
||||
circles: {
|
||||
id: number;
|
||||
name: string;
|
||||
slug: string;
|
||||
translation_key: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const useCockpitStore = defineStore({
|
||||
id: "cockpit",
|
||||
state: () => {
|
||||
return {
|
||||
courseSessionUsers: undefined,
|
||||
cockpitSessionUser: undefined,
|
||||
selectedCircles: [],
|
||||
courseSessionMembers: undefined,
|
||||
selectedCircle: undefined,
|
||||
circles: [],
|
||||
} as CockpitStoreState;
|
||||
},
|
||||
actions: {
|
||||
async loadCourseSessionUsers(courseSessionId: number, reload = false) {
|
||||
log.debug("loadCockpitData called");
|
||||
async loadCircles(courseSlug: string, courseSessionId: number) {
|
||||
log.debug("loadCircles called");
|
||||
|
||||
const f = await courseCircles(courseSlug, courseSessionId);
|
||||
|
||||
this.circles = f.map((c) => {
|
||||
return {
|
||||
id: c.id,
|
||||
name: c.title,
|
||||
slug: c.slug,
|
||||
translation_key: c.translation_key,
|
||||
};
|
||||
});
|
||||
|
||||
if (this.circles.length > 0) {
|
||||
this.selectedCircle = this.circles[0];
|
||||
}
|
||||
},
|
||||
async loadCourseSessionMembers(courseSessionId: number, reload = false) {
|
||||
log.debug("loadCourseSessionMembers called");
|
||||
const users = (await itGetCached(
|
||||
`/api/course/sessions/${courseSessionId}/users/`,
|
||||
{
|
||||
|
|
@ -30,38 +61,42 @@ export const useCockpitStore = defineStore({
|
|||
}
|
||||
)) as CourseSessionUser[];
|
||||
|
||||
this.courseSessionUsers = users.filter((user) => user.role === "MEMBER");
|
||||
|
||||
const userStore = useUserStore();
|
||||
const currentUser = users.find((user) => user.user_id === userStore.id);
|
||||
|
||||
if (currentUser && currentUser.role === "EXPERT") {
|
||||
this.cockpitSessionUser = currentUser as ExpertSessionUser;
|
||||
}
|
||||
|
||||
if (this.selectedCircles.length === 0) {
|
||||
// workaround to select first circle by default, when nothing is selected...
|
||||
// TODO: is this the right place to do this?
|
||||
if (this.cockpitSessionUser && this.cockpitSessionUser.circles?.length > 0) {
|
||||
this.selectedCircles = [this.cockpitSessionUser.circles[0].translation_key];
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.courseSessionUsers) {
|
||||
throw `No courseSessionUsers data found for user`;
|
||||
}
|
||||
return this.courseSessionUsers;
|
||||
},
|
||||
toggleCircleSelection(translationKey: string) {
|
||||
if (this.selectedCircles.indexOf(translationKey) < 0) {
|
||||
this.selectedCircles.push(translationKey);
|
||||
} else {
|
||||
if (this.selectedCircles.length === 1) {
|
||||
return;
|
||||
}
|
||||
const index = this.selectedCircles.indexOf(translationKey);
|
||||
this.selectedCircles.splice(index, 1);
|
||||
}
|
||||
this.courseSessionMembers = users.filter((user) => user.role === "MEMBER");
|
||||
return this.courseSessionMembers;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
async function courseCircles(courseSlug: string, courseSessionId: number) {
|
||||
const userStore = useUserStore();
|
||||
const userId = userStore.id;
|
||||
|
||||
const users = (await itGetCached(`/api/course/sessions/${courseSessionId}/users/`, {
|
||||
reload: false,
|
||||
})) as CourseSessionUser[];
|
||||
|
||||
// First check if current user is an expert for this course session
|
||||
const currentUser = users.find((user) => user.user_id === userId);
|
||||
if (currentUser && currentUser.role === "EXPERT") {
|
||||
const expert = currentUser as ExpertSessionUser;
|
||||
return expert.circles;
|
||||
}
|
||||
|
||||
// Return all circles from learning path for admin users
|
||||
if (userStore.is_superuser) {
|
||||
const learningPathStore = useLearningPathStore();
|
||||
const learningPathCircles = learningPathStore
|
||||
.learningPathForUser(courseSlug, userId)
|
||||
?.circles.map((c) => {
|
||||
return {
|
||||
id: c.id,
|
||||
title: c.title,
|
||||
slug: c.slug,
|
||||
translation_key: c.translation_key,
|
||||
};
|
||||
});
|
||||
return learningPathCircles || [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export const useCompetenceStore = defineStore({
|
|||
},
|
||||
flatPerformanceCriteria(
|
||||
userId: string | undefined = undefined,
|
||||
circleTranslationKeys: string[] | undefined = undefined
|
||||
circleId: number | undefined = undefined
|
||||
) {
|
||||
if (!userId) {
|
||||
const userStore = useUserStore();
|
||||
|
|
@ -94,10 +94,8 @@ export const useCompetenceStore = defineStore({
|
|||
);
|
||||
}
|
||||
|
||||
if (circleTranslationKeys) {
|
||||
criteria = criteria.filter((c) =>
|
||||
circleTranslationKeys.includes(c.circle.translation_key)
|
||||
);
|
||||
if (circleId) {
|
||||
criteria = criteria.filter((c) => circleId === c.circle.id);
|
||||
}
|
||||
|
||||
return criteria;
|
||||
|
|
|
|||
Loading…
Reference in New Issue