WIP: Adding courseId to statistics page

This commit is contained in:
Christian Cueni 2024-04-18 15:43:19 +02:00
parent 1e5db1f0f7
commit b58bceb14d
13 changed files with 169 additions and 61 deletions

View File

@ -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>

View File

@ -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">

View File

@ -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

View File

@ -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>

View File

@ -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,
};
}

View File

@ -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 -->

View File

@ -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">

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -269,7 +269,7 @@ const router = createRouter({
],
},
{
path: "/statistic",
path: "/statistic/:courseSlug",
props: true,
component: () => import("@/pages/dashboard/statistic/StatisticParentPage.vue"),
children: [

View File

@ -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;
}

View File

@ -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,
};
});