Filter for list, add average grade
This commit is contained in:
parent
b7231fb1b7
commit
29c42f3512
|
|
@ -4,27 +4,53 @@ import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
|||
import { useTranslation } from "i18next-vue";
|
||||
import type { StatisticsCourseSessionPropertiesType } from "@/gql/graphql";
|
||||
import type { StatisticsFilterItem } from "@/types";
|
||||
import _ from "lodash";
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const props = defineProps<{
|
||||
items: StatisticsFilterItem[];
|
||||
courseSessionProperties: StatisticsCourseSessionPropertiesType;
|
||||
hideCircleFilter?: boolean;
|
||||
}>();
|
||||
|
||||
defineExpose({ getFilteredItems });
|
||||
|
||||
const regionFilter = computed(() => {
|
||||
const regions = _.uniq(
|
||||
props.courseSessionProperties.sessions.map((session) => session.region)
|
||||
);
|
||||
const f = regions.map((region) => ({
|
||||
name: `Region: ${region}`,
|
||||
id: region,
|
||||
}));
|
||||
return [
|
||||
{
|
||||
name: `${t("Region")}: ${t("a.Alle")}`,
|
||||
id: "_all",
|
||||
},
|
||||
...f,
|
||||
];
|
||||
});
|
||||
|
||||
const sessionFilter = computed(() => {
|
||||
const f = props.courseSessionProperties.sessions.map((session) => ({
|
||||
name: `${t("a.Durchfuehrung")}: ${session.name}`,
|
||||
let values = props.courseSessionProperties.sessions.map((session) => ({
|
||||
name: session.name,
|
||||
region: session.region,
|
||||
id: session.id,
|
||||
}));
|
||||
return [{ name: t("a.AlleDurchführungen"), id: "_all" }, ...f];
|
||||
|
||||
// filter by selected region
|
||||
if (regionFilterValue.value.id !== "_all") {
|
||||
values = values.filter((cs) => cs.region === regionFilterValue.value.id);
|
||||
}
|
||||
|
||||
return [{ name: t("a.AlleDurchführungen"), id: "_all" }, ...values];
|
||||
});
|
||||
|
||||
const generationFilter = computed(() => {
|
||||
const f = props.courseSessionProperties.generations.map((generation) => ({
|
||||
name: `${t("a.Generation")}: ${generation}`,
|
||||
name: generation,
|
||||
id: generation,
|
||||
}));
|
||||
return [{ name: t("a.AlleGenerationen"), id: "_all" }, ...f];
|
||||
|
|
@ -32,12 +58,13 @@ const generationFilter = computed(() => {
|
|||
|
||||
const circleFilter = computed(() => {
|
||||
const f = props.courseSessionProperties.circles.map((circle) => ({
|
||||
name: `Circle: ${circle.name}`,
|
||||
name: circle.name,
|
||||
id: circle.id,
|
||||
}));
|
||||
return [{ name: t("a.AlleCircle"), id: "_all" }, ...f];
|
||||
});
|
||||
|
||||
const regionFilterValue = ref(regionFilter.value[0]);
|
||||
const sessionFilterValue = ref(sessionFilter.value[0]);
|
||||
const generationFilterValue = ref(generationFilter.value[0]);
|
||||
const circleFilterValue = ref(circleFilter.value[0]);
|
||||
|
|
@ -48,12 +75,21 @@ watch(
|
|||
sessionFilterValue.value = sessionFilter.value[0];
|
||||
generationFilterValue.value = generationFilter.value[0];
|
||||
circleFilterValue.value = circleFilter.value[0];
|
||||
regionFilterValue.value = regionFilter.value[0];
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
watch(regionFilterValue, () => {
|
||||
console.log("regionFilterValue", regionFilterValue.value);
|
||||
sessionFilterValue.value = sessionFilter.value[0];
|
||||
});
|
||||
|
||||
const filteredItems = computed(() => {
|
||||
return props.items.filter((item) => {
|
||||
const regionMatch =
|
||||
regionFilterValue.value.id === "_all" ||
|
||||
item.region === regionFilterValue.value.id;
|
||||
const sessionMatch =
|
||||
sessionFilterValue.value.id === "_all" ||
|
||||
item.course_session_id === sessionFilterValue.value.id;
|
||||
|
|
@ -64,7 +100,7 @@ const filteredItems = computed(() => {
|
|||
circleFilterValue.value.id === "_all" ||
|
||||
item.circle_id === circleFilterValue.value.id;
|
||||
|
||||
return sessionMatch && generationMatch && circleMatch;
|
||||
return regionMatch && sessionMatch && generationMatch && circleMatch;
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -75,30 +111,45 @@ function getFilteredItems() {
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex flex-col space-x-2 lg:flex-row">
|
||||
<div class="flex flex-col space-x-2 lg:flex-row border-b">
|
||||
<ItDropdownSelect
|
||||
v-if="regionFilter.length > 2"
|
||||
v-model="regionFilterValue"
|
||||
class="min-w-[12rem]"
|
||||
:items="regionFilter"
|
||||
borderless
|
||||
></ItDropdownSelect>
|
||||
<ItDropdownSelect
|
||||
v-model="sessionFilterValue"
|
||||
class="min-w-[18rem]"
|
||||
class="min-w-[12rem]"
|
||||
:items="sessionFilter"
|
||||
borderless
|
||||
></ItDropdownSelect>
|
||||
<ItDropdownSelect
|
||||
v-model="generationFilterValue"
|
||||
class="min-w-[18rem]"
|
||||
class="min-w-[12rem]"
|
||||
:items="generationFilter"
|
||||
borderless
|
||||
></ItDropdownSelect>
|
||||
<ItDropdownSelect
|
||||
v-if="!props.hideCircleFilter"
|
||||
v-model="circleFilterValue"
|
||||
class="min-w-[18rem]"
|
||||
class="min-w-[12rem]"
|
||||
:items="circleFilter"
|
||||
borderless
|
||||
></ItDropdownSelect>
|
||||
</div>
|
||||
<div v-for="item in filteredItems" :key="item._id" class="px-5">
|
||||
<div class="border-t border-gray-500 py-4">
|
||||
<slot :item="item"></slot>
|
||||
<slot name="header"></slot>
|
||||
<section>
|
||||
<div
|
||||
v-for="item in filteredItems"
|
||||
:key="item._id"
|
||||
class="mx-6 border-t border-gray-500 first:border-t-0"
|
||||
>
|
||||
<div class="py-4">
|
||||
<slot :item="item"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -52,9 +52,11 @@ type AssignmentStatisticsRecordType {
|
|||
course_session_assignment_id: ID!
|
||||
circle_id: ID!
|
||||
generation: String!
|
||||
region: String!
|
||||
assignment_type_translation_key: String!
|
||||
assignment_title: String!
|
||||
deadline: DateTime!
|
||||
course_session_title: String
|
||||
competence_certificate_id: ID
|
||||
competence_certificate_title: String
|
||||
metrics: AssignmentCompletionMetricsType!
|
||||
|
|
@ -98,6 +100,7 @@ type StatisticsCourseSessionPropertiesType {
|
|||
type StatisticsCourseSessionDataType {
|
||||
id: ID!
|
||||
name: String!
|
||||
region: String!
|
||||
}
|
||||
|
||||
type StatisticsCircleDataType {
|
||||
|
|
@ -122,6 +125,7 @@ type PresenceRecordStatisticsType {
|
|||
_id: ID!
|
||||
course_session_id: ID!
|
||||
generation: String!
|
||||
region: String!
|
||||
circle_id: ID!
|
||||
due_date: DateTime!
|
||||
participants_present: Int!
|
||||
|
|
@ -145,6 +149,7 @@ type FeedbackStatisticsRecordType {
|
|||
_id: ID!
|
||||
course_session_id: ID!
|
||||
generation: String!
|
||||
region: String!
|
||||
circle_id: ID!
|
||||
satisfaction_average: Float!
|
||||
satisfaction_max: Int!
|
||||
|
|
@ -175,6 +180,7 @@ type CompetenceRecordStatisticsType {
|
|||
_id: ID!
|
||||
course_session_id: ID!
|
||||
generation: String!
|
||||
region: String!
|
||||
title: String!
|
||||
circle_id: ID!
|
||||
success_count: Int!
|
||||
|
|
|
|||
|
|
@ -370,6 +370,7 @@ export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
|||
sessions {
|
||||
id
|
||||
name
|
||||
region
|
||||
}
|
||||
generations
|
||||
circles {
|
||||
|
|
@ -390,6 +391,7 @@ export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
|||
_id
|
||||
course_session_id
|
||||
generation
|
||||
region
|
||||
circle_id
|
||||
due_date
|
||||
participants_present
|
||||
|
|
@ -408,6 +410,7 @@ export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
|||
_id
|
||||
course_session_id
|
||||
generation
|
||||
region
|
||||
circle_id
|
||||
experts
|
||||
satisfaction_average
|
||||
|
|
@ -436,6 +439,7 @@ export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
|||
course_session_assignment_id
|
||||
circle_id
|
||||
generation
|
||||
region
|
||||
assignment_title
|
||||
assignment_type_translation_key
|
||||
competence_certificate_title
|
||||
|
|
@ -465,6 +469,7 @@ export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
|||
_id
|
||||
course_session_id
|
||||
generation
|
||||
region
|
||||
circle_id
|
||||
title
|
||||
success_count
|
||||
|
|
@ -490,6 +495,7 @@ export const DASHBOARD_MENTOR_COMPETENCE_SUMMARY = graphql(`
|
|||
sessions {
|
||||
id
|
||||
name
|
||||
region
|
||||
}
|
||||
generations
|
||||
circles {
|
||||
|
|
@ -510,8 +516,10 @@ export const DASHBOARD_MENTOR_COMPETENCE_SUMMARY = graphql(`
|
|||
_id
|
||||
course_session_id
|
||||
course_session_assignment_id
|
||||
course_session_title
|
||||
circle_id
|
||||
generation
|
||||
region
|
||||
assignment_title
|
||||
assignment_type_translation_key
|
||||
competence_certificate_id
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import log from "loglevel";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { computed, onMounted, type Ref, ref } from "vue";
|
||||
import {
|
||||
courseIdForCourseSlug,
|
||||
fetchMentorCompetenceSummary,
|
||||
|
|
@ -10,6 +10,8 @@ import { useDashboardStore } from "@/stores/dashboard";
|
|||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||
import _ from "lodash";
|
||||
import { percentToRoundedGrade } from "@/services/assignmentService";
|
||||
import StatisticFilterList from "@/components/dashboard/StatisticFilterList.vue";
|
||||
import type { StatisticsFilterItem } from "@/types";
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
||||
|
|
@ -32,6 +34,22 @@ const courseSessionName = (courseSessionId: string) => {
|
|||
);
|
||||
};
|
||||
|
||||
const statisticFilter: Ref<typeof StatisticFilterList | null> = ref(null);
|
||||
const filteredItems = computed(() => {
|
||||
if (!statisticFilter.value) {
|
||||
return [];
|
||||
}
|
||||
return statisticFilter.value.getFilteredItems();
|
||||
});
|
||||
const totalAverageGrade = computed(() => {
|
||||
return percentToRoundedGrade(
|
||||
_.sumBy(filteredItems.value, (i) => {
|
||||
return (i as GroupedAssignmentEntry).averageEvaluationPercent ?? 0;
|
||||
}) / filteredItems.value.length,
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await dashboardStore.loadDashboardDetails();
|
||||
courseId.value = courseIdForCourseSlug(
|
||||
|
|
@ -53,26 +71,31 @@ onMounted(async () => {
|
|||
loading.value = false;
|
||||
});
|
||||
|
||||
type GroupedAssignments = {
|
||||
interface GroupedAssignmentEntry extends StatisticsFilterItem {
|
||||
competenceCertificateId: string;
|
||||
competenceCertificateTitle: string;
|
||||
generation: string;
|
||||
courseSessionId: string;
|
||||
course_session_title: string;
|
||||
assignments: AssignmentStatisticsRecordType[];
|
||||
sumAverageEvaluationPercent: number;
|
||||
averageEvaluationPercent: number | null;
|
||||
averageGrade: number | null;
|
||||
};
|
||||
}
|
||||
|
||||
function isGroupedAssignmentEntry(
|
||||
item: StatisticsFilterItem
|
||||
): item is GroupedAssignmentEntry {
|
||||
return (item as GroupedAssignmentEntry).competenceCertificateId !== undefined;
|
||||
}
|
||||
|
||||
const courseSessionCompetenceAssignments = computed(() => {
|
||||
let resultArray = [] as GroupedAssignments[];
|
||||
let resultArray = [] as GroupedAssignmentEntry[];
|
||||
|
||||
// group assignments by competence and course session
|
||||
for (const assignment of agentAssignmentData.value?.assignments.records ?? []) {
|
||||
const entry = resultArray.find(
|
||||
(r) =>
|
||||
r.competenceCertificateId === assignment.competence_certificate_id &&
|
||||
r.courseSessionId === assignment.course_session_id
|
||||
r.course_session_id === assignment.course_session_id
|
||||
);
|
||||
if (entry) {
|
||||
if (assignment.metrics.ranking_completed) {
|
||||
|
|
@ -80,14 +103,18 @@ const courseSessionCompetenceAssignments = computed(() => {
|
|||
}
|
||||
} else {
|
||||
const newEntry = {
|
||||
_id: `${assignment.competence_certificate_id}-${assignment.course_session_id}`,
|
||||
competenceCertificateId: assignment.competence_certificate_id ?? "",
|
||||
competenceCertificateTitle: assignment.competence_certificate_title ?? "",
|
||||
generation: assignment.generation ?? "",
|
||||
courseSessionId: assignment.course_session_id ?? "",
|
||||
region: assignment.region ?? "",
|
||||
course_session_id: assignment.course_session_id ?? "",
|
||||
course_session_title: assignment.course_session_title ?? "",
|
||||
assignments: [] as AssignmentStatisticsRecordType[],
|
||||
sumAverageEvaluationPercent: 0,
|
||||
averageEvaluationPercent: null,
|
||||
averageGrade: null,
|
||||
circle_id: assignment.circle_id ?? "",
|
||||
};
|
||||
if (assignment && assignment.metrics.ranking_completed) {
|
||||
newEntry.assignments.push(assignment);
|
||||
|
|
@ -114,7 +141,11 @@ const courseSessionCompetenceAssignments = computed(() => {
|
|||
});
|
||||
entry.averageGrade = percentToRoundedGrade(entry.averageEvaluationPercent, false);
|
||||
}
|
||||
return resultArray;
|
||||
return _.orderBy(
|
||||
resultArray,
|
||||
["course_session_title", "competenceCertificateTitle"],
|
||||
["asc", "asc"]
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -129,48 +160,61 @@ const courseSessionCompetenceAssignments = computed(() => {
|
|||
<span>{{ $t("general.back") }}</span>
|
||||
</router-link>
|
||||
<div>
|
||||
<h2>{{ $t("a.Kompetenznachweise") }}</h2>
|
||||
<h2 class="mb-8">{{ $t("a.Kompetenznachweise") }}</h2>
|
||||
|
||||
<div class="bg-white px-4 py-2">
|
||||
<section
|
||||
class="flex flex-col space-x-0 border-b bg-white lg:flex-row lg:space-x-3"
|
||||
></section>
|
||||
<div
|
||||
v-for="entry in courseSessionCompetenceAssignments"
|
||||
:key="entry.courseSessionId"
|
||||
:data-cy="`entry-${entry.courseSessionId}`"
|
||||
class="flex flex-col justify-between gap-4 border-b p-2 last:border-b-0 md:flex-row md:items-center md:justify-between md:gap-16"
|
||||
<div class="bg-white py-2">
|
||||
<StatisticFilterList
|
||||
v-if="
|
||||
agentAssignmentData?.course_session_properties &&
|
||||
courseSessionCompetenceAssignments?.length
|
||||
"
|
||||
ref="statisticFilter"
|
||||
:course-session-properties="agentAssignmentData?.course_session_properties"
|
||||
:items="courseSessionCompetenceAssignments"
|
||||
:hide-circle-filter="true"
|
||||
>
|
||||
<div class="w-full flex-auto md:w-1/2">
|
||||
{{ entry.competenceCertificateTitle }}
|
||||
<br />
|
||||
{{ $t("a.Durchführung") }} «{{
|
||||
courseSessionName(entry.courseSessionId)
|
||||
}}»
|
||||
</div>
|
||||
|
||||
<div class="flex flex-auto items-center gap-2 md:w-1/4">
|
||||
<div>{{ $t("a.Durchschnittsnote") }}:</div>
|
||||
<div class="min-w-12 text-center">
|
||||
<div
|
||||
class="rounded px-2 py-1 font-bold"
|
||||
:class="{ 'bg-red-400': (entry.averageGrade ?? 4) < 4 }"
|
||||
>
|
||||
{{ entry.averageGrade }}
|
||||
<template #header>
|
||||
<div class="heading-3 border-b px-6 py-4">
|
||||
{{ $t("a.Durchschnittsnote") }}: {{ totalAverageGrade }}
|
||||
</div>
|
||||
</template>
|
||||
<template #default="{ item: item }">
|
||||
<div
|
||||
v-if="isGroupedAssignmentEntry(item)"
|
||||
class="flex flex-col justify-between gap-4 border-b last:border-b-0 md:flex-row md:items-center md:justify-between md:gap-16"
|
||||
>
|
||||
<div class="w-full flex-auto md:w-1/2">
|
||||
<span class="text-bold">
|
||||
{{ item.competenceCertificateTitle }}
|
||||
</span>
|
||||
<br />
|
||||
{{ $t("a.Durchführung") }} «{{
|
||||
courseSessionName(item.course_session_id)
|
||||
}}»
|
||||
</div>
|
||||
<div class="flex flex-auto items-center gap-2 md:w-1/4">
|
||||
<div>{{ $t("a.Durchschnittsnote") }}:</div>
|
||||
<div class="min-w-12 text-center">
|
||||
<div
|
||||
class="rounded px-2 py-1 font-bold"
|
||||
:class="{ 'bg-red-400': (item.averageGrade ?? 4) < 4 }"
|
||||
>
|
||||
{{ item.averageGrade }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full flex-auto items-end md:w-1/4 md:text-end">
|
||||
<router-link
|
||||
class="underline"
|
||||
:to="`/statistic/${props.agentRole}/${props.courseSlug}/competence-grade/${item.course_session_id}/${item.competenceCertificateId}`"
|
||||
data-cy="basebox.detailsLink"
|
||||
>
|
||||
{{ $t("a.Details anschauen") }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full flex-auto items-end md:w-1/4 md:text-end">
|
||||
<router-link
|
||||
class="underline"
|
||||
:to="`/statistic/${props.agentRole}/${props.courseSlug}/competence-grade/${entry.courseSessionId}/${entry.competenceCertificateId}`"
|
||||
data-cy="basebox.detailsLink"
|
||||
>
|
||||
{{ $t("a.Details anschauen") }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</StatisticFilterList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -623,6 +623,7 @@ export type DashboardPersonsPageMode = "default" | "competenceMetrics";
|
|||
export interface StatisticsFilterItem {
|
||||
_id: string;
|
||||
course_session_id: string;
|
||||
region: string;
|
||||
generation: string;
|
||||
circle_id: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,9 +36,11 @@ class AssignmentStatisticsRecordType(graphene.ObjectType):
|
|||
course_session_assignment_id = graphene.ID(required=True)
|
||||
circle_id = graphene.ID(required=True)
|
||||
generation = graphene.String(required=True)
|
||||
region = graphene.String(required=True)
|
||||
assignment_type_translation_key = graphene.String(required=True)
|
||||
assignment_title = graphene.String(required=True)
|
||||
deadline = graphene.DateTime(required=True)
|
||||
course_session_title = graphene.String()
|
||||
competence_certificate_id = graphene.ID()
|
||||
competence_certificate_title = graphene.String()
|
||||
metrics = graphene.Field(AssignmentCompletionMetricsType, required=True)
|
||||
|
|
@ -171,9 +173,11 @@ def create_record(
|
|||
# make sure it's unique, across all types of assignments!
|
||||
_id=f"{course_session_assignment._meta.model_name}#{course_session_assignment.id}@{urql_id_postfix}", # noqa
|
||||
course_session_id=str(course_session_assignment.course_session.id), # noqa
|
||||
course_session_title=course_session_assignment.course_session.title, # noqa
|
||||
circle_id=learning_content.get_circle().id, # noqa
|
||||
course_session_assignment_id=str(course_session_assignment.id), # noqa
|
||||
generation=course_session_assignment.course_session.generation, # noqa
|
||||
region=course_session_assignment.course_session.region, # noqa
|
||||
assignment_type_translation_key=due_date.assignment_type_translation_key, # noqa
|
||||
competence_certificate_id=str(competence_certificate.id), # noqa
|
||||
competence_certificate_title=competence_certificate.title, # noqa
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class PresenceRecordStatisticsType(graphene.ObjectType):
|
|||
_id = graphene.ID(required=True)
|
||||
course_session_id = graphene.ID(required=True)
|
||||
generation = graphene.String(required=True)
|
||||
region = graphene.String(required=True)
|
||||
circle_id = graphene.ID(required=True)
|
||||
due_date = graphene.DateTime(required=True)
|
||||
participants_present = graphene.Int(required=True)
|
||||
|
|
@ -83,6 +84,7 @@ def attendance_day_presences(
|
|||
_id=f"{urql_id}:attendance_day:{attendance_day.id}", # noqa
|
||||
course_session_id=course_session.id, # noqa
|
||||
generation=course_session.generation, # noqa
|
||||
region=course_session.region, # noqa
|
||||
circle_id=circle.id, # noqa
|
||||
due_date=attendance_day.due_date.end, # noqa
|
||||
participants_present=participants_present, # noqa
|
||||
|
|
@ -98,7 +100,9 @@ def attendance_day_presences(
|
|||
)
|
||||
|
||||
return AttendanceDayPresencesStatisticsType(
|
||||
summary=summary, records=records, _id=course_id # noqa
|
||||
summary=summary,
|
||||
records=records,
|
||||
_id=course_id, # noqa
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class CompetenceRecordStatisticsType(graphene.ObjectType):
|
|||
_id = graphene.ID(required=True)
|
||||
course_session_id = graphene.ID(required=True)
|
||||
generation = graphene.String(required=True)
|
||||
region = graphene.String(required=True)
|
||||
title = graphene.String(required=True)
|
||||
circle_id = graphene.ID(required=True)
|
||||
success_count = graphene.Int(required=True)
|
||||
|
|
@ -80,6 +81,7 @@ def competences(
|
|||
title=learning_unit.title, # noqa
|
||||
course_session_id=completion.course_session.id, # noqa
|
||||
generation=completion.course_session.generation, # noqa
|
||||
region=completion.course_session.region, # noqa
|
||||
circle_id=circle.id, # noqa
|
||||
success_count=0, # noqa
|
||||
fail_count=0, # noqa
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ from vbv_lernwelt.learnpath.models import Circle
|
|||
class StatisticsCourseSessionDataType(graphene.ObjectType):
|
||||
id = graphene.ID(required=True)
|
||||
name = graphene.String(required=True)
|
||||
region = graphene.String(required=True)
|
||||
|
||||
|
||||
class StatisticsCircleDataType(graphene.ObjectType):
|
||||
|
|
@ -129,6 +130,7 @@ class BaseStatisticsType(graphene.ObjectType):
|
|||
StatisticsCourseSessionDataType(
|
||||
id=course_session.id, # noqa
|
||||
name=course_session.title, # noqa
|
||||
region=course_session.region, # noqa
|
||||
)
|
||||
)
|
||||
generations.add(course_session.generation)
|
||||
|
|
@ -199,7 +201,8 @@ class CourseStatisticsType(BaseStatisticsType):
|
|||
records, success_total, fail_total = competences(
|
||||
course_slug=str(root.course_slug),
|
||||
course_session_selection_ids=[
|
||||
str(cs) for cs in root.course_session_selection_ids # noqa
|
||||
str(cs)
|
||||
for cs in root.course_session_selection_ids # noqa
|
||||
],
|
||||
user_selection_ids=user_selection_ids, # noqa
|
||||
circle_ids=root.get_circle_ids(info), # noqa
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class FeedbackStatisticsRecordType(graphene.ObjectType):
|
|||
_id = graphene.ID(required=True)
|
||||
course_session_id = graphene.ID(required=True)
|
||||
generation = graphene.String(required=True)
|
||||
region = graphene.String(required=True)
|
||||
circle_id = graphene.ID(required=True)
|
||||
satisfaction_average = graphene.Float(required=True)
|
||||
satisfaction_max = graphene.Int(required=True)
|
||||
|
|
@ -68,6 +69,7 @@ def feedback_responses(
|
|||
feedbacks=fbs,
|
||||
course_session_id=course_session.id,
|
||||
generation=course_session.generation,
|
||||
region=course_session.region,
|
||||
course_slug=str(course_slug),
|
||||
urql_id_postfix=urql_id,
|
||||
)
|
||||
|
|
@ -96,6 +98,7 @@ def circle_feedback_average(
|
|||
feedbacks: List[FeedbackResponse],
|
||||
course_session_id,
|
||||
generation: str,
|
||||
region: str,
|
||||
course_slug: str,
|
||||
urql_id_postfix: str = "",
|
||||
):
|
||||
|
|
@ -128,6 +131,7 @@ def circle_feedback_average(
|
|||
_id=f"circle:{circle_id}-course_session:{course_session_id}@{urql_id_postfix}", # noqa
|
||||
course_session_id=course_session_id, # noqa
|
||||
generation=generation, # noqa
|
||||
region=region, # noqa
|
||||
circle_id=circle_id, # noqa
|
||||
satisfaction_average=data["total"] / data["count"], # noqa
|
||||
satisfaction_max=4, # noqa
|
||||
|
|
|
|||
Loading…
Reference in New Issue