WIP: Adding courseId to statistics page
This commit is contained in:
parent
1e5db1f0f7
commit
b58bceb14d
|
|
@ -6,6 +6,7 @@ import BaseBox from "@/components/dashboard/BaseBox.vue";
|
|||
const props = defineProps<{
|
||||
assignmentsCompleted: number;
|
||||
avgPassed: number;
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
const progress = computed(() => {
|
||||
|
|
@ -19,7 +20,7 @@ const progress = computed(() => {
|
|||
|
||||
<template>
|
||||
<BaseBox
|
||||
:details-link="'/statistic/assignment'"
|
||||
:details-link="`/statistic/${courseSlug}/assignment`"
|
||||
data-cy="dashboard.stats.assignments"
|
||||
>
|
||||
<template #title>{{ $t("a.Kompetenznachweis-Elemente") }}</template>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import BaseBox from "@/components/dashboard/BaseBox.vue";
|
|||
const props = defineProps<{
|
||||
daysCompleted: number;
|
||||
avgParticipantsPresent: number;
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
const progressRecord = computed(() => {
|
||||
|
|
@ -18,7 +19,10 @@ const progressRecord = computed(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<BaseBox :details-link="'/statistic/attendance'" data-cy="dashboard.stats.attendance">
|
||||
<BaseBox
|
||||
:details-link="`/statistic/${props.courseSlug}/attendance`"
|
||||
data-cy="dashboard.stats.attendance"
|
||||
>
|
||||
<template #title>{{ $t("a.Anwesenheit") }}</template>
|
||||
<template #content>
|
||||
<div class="flex items-center">
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ function hasActionButton(): boolean {
|
|||
v-if="hasWidget('UKStatisticsWidget')"
|
||||
class="flex flex-col flex-wrap gap-x-[60px] border-b border-gray-300 pb-8 last:border-0 md:flex-row"
|
||||
>
|
||||
<UkStatistics :course-id="courseConfig.course_id" />
|
||||
<UkStatistics :course-slug="courseSlug" :course-id="courseConfig.course_id" />
|
||||
</div>
|
||||
<div v-if="numberOfMentorWidgets > 0" class="flex flex-col flex-wrap md:flex-row">
|
||||
<MentorOpenTasksCount
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { useDashboardStore } from "@/stores/dashboard";
|
||||
import { computed, onMounted } from "vue";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import AttendanceSummaryBox from "@/components/dashboard/AttendanceSummaryBox.vue";
|
||||
import type { CourseStatisticsType } from "@/gql/graphql";
|
||||
import AssignmentSummaryBox from "@/components/dashboard/AssignmentSummaryBox.vue";
|
||||
|
|
@ -9,12 +9,12 @@ import CompetenceSummaryBox from "@/components/dashboard/CompetenceSummaryBox.vu
|
|||
|
||||
const props = defineProps<{
|
||||
courseId: string;
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
const statistics = ref<CourseStatisticsType | null>(null);
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
const statistics = computed(() => {
|
||||
return dashboardStore.currentDashBoardData as CourseStatisticsType;
|
||||
});
|
||||
|
||||
const attendanceDayPresences = computed(() => {
|
||||
return statistics.value.attendance_day_presences.summary;
|
||||
|
|
@ -33,7 +33,8 @@ const feebackSummary = computed(() => {
|
|||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await dashboardStore.loadStatisticsData(props.courseId);
|
||||
statistics.value = await dashboardStore.loadStatisticsDatav2(props.courseId);
|
||||
//await dashboardStore.loadStatisticsData(props.courseId);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -46,11 +47,13 @@ onMounted(async () => {
|
|||
class="flex-grow"
|
||||
:days-completed="attendanceDayPresences.days_completed"
|
||||
:avg-participants-present="attendanceDayPresences.participants_present"
|
||||
:course-slug="props.courseSlug"
|
||||
/>
|
||||
<AssignmentSummaryBox
|
||||
class="flex-grow"
|
||||
:assignments-completed="assigmentSummary.completed_count"
|
||||
:avg-passed="assigmentSummary.average_passed"
|
||||
:course-slug="props.courseSlug"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -60,11 +63,13 @@ onMounted(async () => {
|
|||
:feedback-count="feebackSummary.total_responses"
|
||||
:statisfaction-max="feebackSummary.satisfaction_max"
|
||||
:statisfaction-avg="feebackSummary.satisfaction_average"
|
||||
:course-slug="props.courseSlug"
|
||||
/>
|
||||
<CompetenceSummaryBox
|
||||
:fail-count="competenceSummary.fail_total"
|
||||
:success-count="competenceSummary.success_total"
|
||||
details-link="/statistic/competence"
|
||||
:details-link="`/statistic/${courseSlug}/competence`"
|
||||
:course-slug="props.courseSlug"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
someFinishedInLearningSequence,
|
||||
} from "@/services/circle";
|
||||
import type { DashboardPersonType } from "@/services/dashboard";
|
||||
import { fetchDashboardPersons } from "@/services/dashboard";
|
||||
import { fetchDashboardPersons, fetchStatisticData } from "@/services/dashboard";
|
||||
import { presignUpload, uploadFile } from "@/services/files";
|
||||
import { useCompletionStore } from "@/stores/completion";
|
||||
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||
|
|
@ -573,3 +573,24 @@ export function useCourseCircleProgress(circles: Ref<CircleType[] | undefined>)
|
|||
|
||||
return { inProgressCirclesCount, circlesCount };
|
||||
}
|
||||
|
||||
export function useCourseStatisticsv2(courseId: string) {
|
||||
const courseStatistics = ref<CourseStatisticsType[] | null>(null);
|
||||
const loading = ref(false);
|
||||
|
||||
const fetchData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
courseStatistics.value = await fetchStatisticData(courseId);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(fetchData);
|
||||
|
||||
return {
|
||||
courseStatistics,
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { Component, Ref } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import type { Component } from "vue";
|
||||
import { onMounted } from "vue";
|
||||
import StatisticPage from "@/pages/dashboard/StatisticPage.vue";
|
||||
import ProgressPage from "@/pages/dashboard/ProgressPage.vue";
|
||||
import SimpleDates from "@/components/dashboard/SimpleDates.vue";
|
||||
|
|
@ -8,7 +8,6 @@ import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
|||
import { useDashboardStore } from "@/stores/dashboard";
|
||||
import type { DashboardType } from "@/gql/graphql";
|
||||
import type { DashboardCourseConfigType } from "@/services/dashboard";
|
||||
import { fetchDashboardConfigv2 } from "@/services/dashboard";
|
||||
import SimpleCoursePage from "@/pages/dashboard/SimpleCoursePage.vue";
|
||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||
import CourseDetailDates from "@/components/dashboard/CourseDetailDates.vue";
|
||||
|
|
@ -31,15 +30,12 @@ const boards: Record<DashboardType, DashboardPage> = {
|
|||
PRAXISBILDNER_DASHBOARD: { main: CoursePanel, aside: SimpleDates },
|
||||
};
|
||||
|
||||
const dashboardConfigv2: Ref<DashboardCourseConfigType[]> = ref([]);
|
||||
|
||||
onMounted(async () => {
|
||||
dashboardConfigv2.value = await fetchDashboardConfigv2();
|
||||
await dashboardStore.loadDashboardDetails();
|
||||
});
|
||||
|
||||
function newDashboardConfigForId(id: string): DashboardCourseConfigType | undefined {
|
||||
return dashboardConfigv2.value.find((config) => config.course_id == id);
|
||||
return dashboardStore.dashboardConfigsv2.find((config) => config.course_id == id);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -64,8 +60,11 @@ function newDashboardConfigForId(id: string): DashboardCourseConfigType | undefi
|
|||
</div>
|
||||
<!-- new way of dashboard -->
|
||||
<ul>
|
||||
<li v-for="config in dashboardStore.dashboardConfigs" :key="config.id">
|
||||
<CoursePanel :course-config="newDashboardConfigForId(config.id)" />
|
||||
<li
|
||||
v-for="config in dashboardStore.dashboardConfigsv2"
|
||||
:key="config.course_id"
|
||||
>
|
||||
<CoursePanel :course-config="newDashboardConfigForId(config.course_id)" />
|
||||
</li>
|
||||
</ul>
|
||||
<!-- end of new way of dashboard -->
|
||||
|
|
|
|||
|
|
@ -1,23 +1,39 @@
|
|||
<script setup lang="ts">
|
||||
import { useDashboardStore } from "@/stores/dashboard";
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import { computed } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import type {
|
||||
AssignmentCompletionMetricsType,
|
||||
AssignmentStatisticsRecordType,
|
||||
CourseStatisticsType,
|
||||
} from "@/gql/graphql";
|
||||
import StatisticFilterList from "@/components/dashboard/StatisticFilterList.vue";
|
||||
import { useCourseStatistics } from "@/composables";
|
||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||
import { useCourseStatistics, useCourseStatisticsv2 } from "@/composables";
|
||||
import { getDateString } from "@/components/dueDates/dueDatesUtils";
|
||||
import dayjs from "dayjs";
|
||||
import { courseIdForCourseSlug } from "@/services/dashboard";
|
||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
||||
const statistics = computed(() => {
|
||||
return dashboardStore.currentDashBoardData as CourseStatisticsType;
|
||||
});
|
||||
const statistics = ref<CourseStatisticsType | null>(null);
|
||||
// const statistics = reactive<CourseStatisticsType>({
|
||||
// course_session_properties: {
|
||||
// sessions: [],
|
||||
// generations: [],
|
||||
// circles: [],
|
||||
// },
|
||||
// assignments: { records: [] },
|
||||
// });
|
||||
|
||||
const courseId = courseIdForCourseSlug(
|
||||
dashboardStore.dashboardConfigsv2,
|
||||
props.courseSlug
|
||||
);
|
||||
const { courseStatistics, loading } = useCourseStatisticsv2(courseId);
|
||||
|
||||
const { courseSessionName, circleMeta } = useCourseStatistics();
|
||||
|
||||
|
|
@ -40,23 +56,34 @@ const assignmentStats = (metrics: AssignmentCompletionMetricsType) => {
|
|||
const total = (metrics: AssignmentCompletionMetricsType) => {
|
||||
return metrics.passed_count + metrics.failed_count + metrics.unranked_count;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
console.log("onMount AssignmentList", courseId, props.courseSlug, statistics);
|
||||
if (!courseId) {
|
||||
return;
|
||||
}
|
||||
// statistics.value = await dashboardStore.loadStatisticsDatav2(courseId);
|
||||
// const some = await courseStatistics.loadStatisticsDatav2(courseId);
|
||||
// console.log("some", some.course_session_properties);
|
||||
// statistics.value = some;
|
||||
// console.log("other", statistics.value.course_session_properties);
|
||||
// statistics.course_session_properties = some.course_session_properties;
|
||||
// statistics.assignments = some.assignments;
|
||||
// statistics.console.log(statistics.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main v-if="statistics">
|
||||
{{ loading }}
|
||||
<main v-if="!loading">
|
||||
<div class="mb-10 flex items-center justify-between">
|
||||
<h3>{{ $t("a.Kompetenznachweis-Elemente") }}</h3>
|
||||
<ItDropdownSelect
|
||||
:model-value="dashboardStore.currentDashboardConfig"
|
||||
class="mt-4 w-full lg:mt-0 lg:w-96"
|
||||
:items="dashboardStore.dashboardConfigs"
|
||||
@update:model-value="dashboardStore.switchAndLoadDashboardConfig"
|
||||
></ItDropdownSelect>
|
||||
</div>
|
||||
<div v-if="statistics.assignments.records" class="mt-8 bg-white">
|
||||
<div v-if="courseStatistics?.assignments.records" class="mt-8 bg-white">
|
||||
<StatisticFilterList
|
||||
:course-session-properties="statistics.course_session_properties"
|
||||
:items="statistics.assignments.records"
|
||||
v-if="courseStatistics?.course_session_properties"
|
||||
:course-session-properties="courseStatistics.course_session_properties"
|
||||
:items="courseStatistics.assignments.records"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<div class="flex justify-between">
|
||||
|
|
@ -89,8 +116,8 @@ const total = (metrics: AssignmentCompletionMetricsType) => {
|
|||
<div v-else>Noch nicht bestätigt</div>
|
||||
<ItProgress
|
||||
:status-count="
|
||||
assignmentStats((item as AssignmentStatisticsRecordType).metrics)
|
||||
"
|
||||
assignmentStats((item as AssignmentStatisticsRecordType).metrics)
|
||||
"
|
||||
></ItProgress>
|
||||
<router-link
|
||||
class="underline"
|
||||
|
|
|
|||
|
|
@ -1,19 +1,26 @@
|
|||
<script setup lang="ts">
|
||||
import { useDashboardStore } from "@/stores/dashboard";
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import { computed } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import type { CourseStatisticsType, PresenceRecordStatisticsType } from "@/gql/graphql";
|
||||
import StatisticFilterList from "@/components/dashboard/StatisticFilterList.vue";
|
||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||
import { useCourseStatistics } from "@/composables";
|
||||
import { getDateString } from "@/components/dueDates/dueDatesUtils";
|
||||
import dayjs from "dayjs";
|
||||
import { courseIdForCourseSlug } from "@/services/dashboard";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
||||
const statistics = computed(() => {
|
||||
return dashboardStore.currentDashBoardData as CourseStatisticsType;
|
||||
});
|
||||
const statistics = ref<CourseStatisticsType | null>(null);
|
||||
|
||||
const courseId = courseIdForCourseSlug(
|
||||
dashboardStore.dashboardConfigsv2,
|
||||
props.courseSlug
|
||||
);
|
||||
|
||||
const { courseSessionName, circleMeta } = useCourseStatistics();
|
||||
|
||||
|
|
@ -24,18 +31,17 @@ const attendanceStats = (present: number, total: number) => {
|
|||
UNKNOWN: 0,
|
||||
};
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
console.log("onMount AttendanceList", courseId, props.courseSlug, statistics);
|
||||
statistics.value = await dashboardStore.loadStatisticsDatav2(courseId);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main v-if="statistics">
|
||||
<div class="mb-10 flex items-center justify-between">
|
||||
<h3>{{ $t("Anwesenheit") }}</h3>
|
||||
<ItDropdownSelect
|
||||
:model-value="dashboardStore.currentDashboardConfig"
|
||||
class="mt-4 w-full lg:mt-0 lg:w-96"
|
||||
:items="dashboardStore.dashboardConfigs"
|
||||
@update:model-value="dashboardStore.switchAndLoadDashboardConfig"
|
||||
></ItDropdownSelect>
|
||||
</div>
|
||||
<div v-if="statistics.attendance_day_presences.records" class="mt-8 bg-white">
|
||||
<StatisticFilterList
|
||||
|
|
|
|||
|
|
@ -1,21 +1,30 @@
|
|||
<script setup lang="ts">
|
||||
import { useDashboardStore } from "@/stores/dashboard";
|
||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import { computed } from "vue";
|
||||
import type {
|
||||
CompetenceRecordStatisticsType,
|
||||
CourseStatisticsType,
|
||||
} from "@/gql/graphql";
|
||||
import { onMounted, ref } from "vue";
|
||||
import type { CompetenceRecordStatisticsType } from "@/gql/graphql";
|
||||
import { CourseStatisticsType } from "@/gql/graphql";
|
||||
import StatisticFilterList from "@/components/dashboard/StatisticFilterList.vue";
|
||||
import { useCourseStatistics } from "@/composables";
|
||||
import { courseIdForCourseSlug } from "@/services/dashboard";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
const statistics = ref<CourseStatisticsType | null>(null);
|
||||
|
||||
const statistics = computed(() => {
|
||||
return dashboardStore.currentDashBoardData as CourseStatisticsType;
|
||||
});
|
||||
const courseId = courseIdForCourseSlug(
|
||||
dashboardStore.dashboardConfigsv2,
|
||||
props.courseSlug
|
||||
);
|
||||
|
||||
const { courseSessionName, circleMeta } = useCourseStatistics();
|
||||
|
||||
onMounted(async () => {
|
||||
statistics.value = await dashboardStore.loadStatisticsDatav2(courseId);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { useDashboardStore } from "@/stores/dashboard";
|
||||
import { onMounted } from "vue";
|
||||
import { computed, onMounted, watch } from "vue";
|
||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
onMounted(dashboardStore.loadDashboardDetails);
|
||||
dashboardStore.loading = true;
|
||||
|
||||
const some = computed(() => {
|
||||
return dashboardStore.loading;
|
||||
});
|
||||
|
||||
watch(some, () => {
|
||||
console.log("watch loading", dashboardStore.loading);
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
console.log("onMount StatisticParentPage", dashboardStore.loading);
|
||||
await dashboardStore.loadDashboardDetails();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ const router = createRouter({
|
|||
],
|
||||
},
|
||||
{
|
||||
path: "/statistic",
|
||||
path: "/statistic/:courseSlug",
|
||||
props: true,
|
||||
component: () => import("@/pages/dashboard/statistic/StatisticParentPage.vue"),
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -159,3 +159,11 @@ export async function fetchOpenTasksCount(courseId: string) {
|
|||
`/api/dashboard/course/${courseId}/open_tasks/`
|
||||
);
|
||||
}
|
||||
|
||||
export function courseIdForCourseSlug(
|
||||
dashboardConfigs: DashboardCourseConfigType[],
|
||||
courseSlug: string
|
||||
) {
|
||||
const config = dashboardConfigs.find((config) => config.course_slug === courseSlug);
|
||||
return config?.course_id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ import type {
|
|||
DashboardConfigType,
|
||||
DashboardType,
|
||||
} from "@/gql/graphql";
|
||||
import type { DashboardCourseConfigType } from "@/services/dashboard";
|
||||
import {
|
||||
fetchDashboardConfig,
|
||||
fetchDashboardConfigv2,
|
||||
fetchProgressData,
|
||||
fetchStatisticData,
|
||||
} from "@/services/dashboard";
|
||||
|
|
@ -15,6 +17,7 @@ import { ref } from "vue";
|
|||
|
||||
export const useDashboardStore = defineStore("dashboard", () => {
|
||||
const dashboardConfigs: Ref<DashboardConfigType[]> = ref([]);
|
||||
const dashboardConfigsv2: Ref<DashboardCourseConfigType[]> = ref([]);
|
||||
const currentDashboardConfig: Ref<DashboardConfigType | undefined> = ref();
|
||||
const dashBoardDataCache: Record<
|
||||
string,
|
||||
|
|
@ -56,6 +59,8 @@ export const useDashboardStore = defineStore("dashboard", () => {
|
|||
|
||||
const loadDashboardDetails = async () => {
|
||||
loading.value = true;
|
||||
dashboardConfigsv2.value = await fetchDashboardConfigv2();
|
||||
console.log("got dashboard config v2: ", dashboardConfigsv2.value);
|
||||
try {
|
||||
if (!currentDashboardConfig.value) {
|
||||
await loadDashboardConfig();
|
||||
|
|
@ -66,8 +71,9 @@ export const useDashboardStore = defineStore("dashboard", () => {
|
|||
currentDashBoardData.value = dashBoardDataCache[id];
|
||||
return;
|
||||
}
|
||||
await loadDashboardData(dashboard_type, id);
|
||||
// await loadDashboardData(dashboard_type, id);
|
||||
} finally {
|
||||
console.log("done loading dashboard details");
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
|
@ -78,8 +84,16 @@ export const useDashboardStore = defineStore("dashboard", () => {
|
|||
currentDashBoardData.value = data;
|
||||
};
|
||||
|
||||
const loadStatisticsDatav2 = async (id: string) => {
|
||||
console.log("fetching statistics v2 for course ID: ", id);
|
||||
const data = await fetchStatisticData(id);
|
||||
dashBoardDataCache[id] = data;
|
||||
return data;
|
||||
};
|
||||
|
||||
return {
|
||||
dashboardConfigs,
|
||||
dashboardConfigsv2,
|
||||
currentDashboardConfig,
|
||||
switchAndLoadDashboardConfig,
|
||||
loadDashboardConfig,
|
||||
|
|
@ -87,5 +101,6 @@ export const useDashboardStore = defineStore("dashboard", () => {
|
|||
currentDashBoardData,
|
||||
loading,
|
||||
loadStatisticsData,
|
||||
loadStatisticsDatav2,
|
||||
};
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue