Make AgentCompetenceGradeDetailPage
This commit is contained in:
parent
da348b7756
commit
b24dbc84c8
|
|
@ -73,14 +73,14 @@ export function useCurrentCourseSession() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useCourseSessionDetailQuery(courSessionId?: string) {
|
export function useCourseSessionDetailQuery(courseSessionId?: string) {
|
||||||
if (!courSessionId) {
|
if (!courseSessionId) {
|
||||||
courSessionId = useCurrentCourseSession().value.id;
|
courseSessionId = useCurrentCourseSession().value.id;
|
||||||
}
|
}
|
||||||
const queryResult = useQuery({
|
const queryResult = useQuery({
|
||||||
query: COURSE_SESSION_DETAIL_QUERY,
|
query: COURSE_SESSION_DETAIL_QUERY,
|
||||||
variables: {
|
variables: {
|
||||||
courseSessionId: courSessionId,
|
courseSessionId: courseSessionId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const documents = {
|
||||||
"\n fragment CoursePageFields on CoursePageInterface {\n title\n id\n slug\n content_type\n frontend_url\n }\n": types.CoursePageFieldsFragmentDoc,
|
"\n fragment CoursePageFields on CoursePageInterface {\n title\n id\n slug\n content_type\n frontend_url\n }\n": types.CoursePageFieldsFragmentDoc,
|
||||||
"\n query attendanceCheckQuery($courseSessionId: ID!) {\n course_session_attendance_course(id: $courseSessionId) {\n id\n attendance_user_list {\n user_id\n status\n }\n }\n }\n": types.AttendanceCheckQueryDocument,
|
"\n query attendanceCheckQuery($courseSessionId: ID!) {\n course_session_attendance_course(id: $courseSessionId) {\n id\n attendance_user_list {\n user_id\n status\n }\n }\n }\n": types.AttendanceCheckQueryDocument,
|
||||||
"\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n first_name\n last_name\n }\n assignment_user {\n avatar_url\n first_name\n last_name\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_points_deducted\n evaluation_points_deducted_reason\n evaluation_points_final\n\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n": types.AssignmentCompletionQueryDocument,
|
"\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n first_name\n last_name\n }\n assignment_user {\n avatar_url\n first_name\n last_name\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_points_deducted\n evaluation_points_deducted_reason\n evaluation_points_final\n\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n": types.AssignmentCompletionQueryDocument,
|
||||||
"\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n": types.CompetenceCertificateForUserQueryDocument,
|
"\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n evaluation_percent\n assignment_user {\n id\n }\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n": types.CompetenceCertificateForUserQueryDocument,
|
||||||
"\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n }\n }\n": types.CourseSessionDetailDocument,
|
"\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n }\n }\n": types.CourseSessionDetailDocument,
|
||||||
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n is_uk\n }\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n evaluate_url\n ...CoursePageFields\n performance_criteria {\n ...CoursePageFields\n }\n learning_contents {\n can_user_self_toggle_course_completion\n content_url\n minutes\n description\n ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument,
|
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n is_uk\n }\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n evaluate_url\n ...CoursePageFields\n performance_criteria {\n ...CoursePageFields\n }\n learning_contents {\n can_user_self_toggle_course_completion\n content_url\n minutes\n description\n ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument,
|
||||||
"\n query dashboardConfig {\n dashboard_config {\n id\n slug\n name\n dashboard_type\n course_configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n is_uk\n }\n }\n }\n": types.DashboardConfigDocument,
|
"\n query dashboardConfig {\n dashboard_config {\n id\n slug\n name\n dashboard_type\n course_configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n is_uk\n }\n }\n }\n": types.DashboardConfigDocument,
|
||||||
|
|
@ -66,7 +66,7 @@ export function graphql(source: "\n query assignmentCompletionQuery(\n $assi
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"];
|
export function graphql(source: "\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n evaluation_percent\n assignment_user {\n id\n }\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n evaluation_percent\n assignment_user {\n id\n }\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -581,6 +581,7 @@ type AssignmentCompletionObjectType {
|
||||||
evaluation_points: Float
|
evaluation_points: Float
|
||||||
evaluation_points_final: Float
|
evaluation_points_final: Float
|
||||||
evaluation_max_points: Float
|
evaluation_max_points: Float
|
||||||
|
evaluation_percent: Float
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ export const COMPETENCE_NAVI_CERTIFICATE_QUERY = graphql(`
|
||||||
evaluation_points_deducted
|
evaluation_points_deducted
|
||||||
evaluation_max_points
|
evaluation_max_points
|
||||||
evaluation_passed
|
evaluation_passed
|
||||||
|
evaluation_percent
|
||||||
|
assignment_user {
|
||||||
|
id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
learning_content {
|
learning_content {
|
||||||
...CoursePageFields
|
...CoursePageFields
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import {
|
import { type DashboardPersonType, fetchDashboardPersons } from "@/services/dashboard";
|
||||||
courseIdForCourseSlug,
|
|
||||||
fetchMentorCompetenceSummary,
|
|
||||||
} from "@/services/dashboard";
|
|
||||||
import type { AssignmentStatisticsRecordType, BaseStatisticsType } from "@/gql/graphql";
|
|
||||||
import { useDashboardStore } from "@/stores/dashboard";
|
|
||||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||||
|
import { useCurrentCourseSession } from "@/composables";
|
||||||
|
import { COMPETENCE_NAVI_CERTIFICATE_QUERY } from "@/graphql/queries";
|
||||||
|
import { graphqlClient } from "@/graphql/client";
|
||||||
|
import type { CompetenceCertificateObjectType } from "@/gql/graphql";
|
||||||
|
import { calcCompetenceCertificateGrade } from "@/pages/competence/utils";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
import type { CompetenceCertificateAssignment } from "@/types";
|
||||||
import { percentToRoundedGrade } from "@/services/assignmentService";
|
import { percentToRoundedGrade } from "@/services/assignmentService";
|
||||||
|
|
||||||
const dashboardStore = useDashboardStore();
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
agentRole: string;
|
agentRole: string;
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
|
|
@ -22,102 +21,88 @@ const props = defineProps<{
|
||||||
|
|
||||||
log.debug("AgentCompetenceGradeDetailPage created", props);
|
log.debug("AgentCompetenceGradeDetailPage created", props);
|
||||||
|
|
||||||
|
const courseSession = useCurrentCourseSession();
|
||||||
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const courseId = ref<string | undefined>(undefined);
|
|
||||||
const agentAssignmentData = ref<BaseStatisticsType | null>(null);
|
|
||||||
|
|
||||||
const courseSessionName = (courseSessionId: string) => {
|
const participants = ref<DashboardPersonType[]>([]);
|
||||||
return (
|
const participantUserIds = computed(() => {
|
||||||
agentAssignmentData.value?.course_session_properties?.sessions.find(
|
return (participants.value ?? []).map((p) => p.user_id);
|
||||||
(session) => session.id === courseSessionId
|
});
|
||||||
)?.name ?? ""
|
|
||||||
|
const certificateData = ref<CompetenceCertificateObjectType | undefined>(undefined);
|
||||||
|
|
||||||
|
function userGrade(userId: string) {
|
||||||
|
if (certificateData.value) {
|
||||||
|
const assignmentsWithUserCompletions = _.cloneDeep(
|
||||||
|
certificateData.value.assignments
|
||||||
);
|
);
|
||||||
};
|
for (const assignment of assignmentsWithUserCompletions) {
|
||||||
|
assignment.completions = assignment.completions?.filter(
|
||||||
onMounted(async () => {
|
(c) => c?.assignment_user.id === userId
|
||||||
await dashboardStore.loadDashboardDetails();
|
|
||||||
courseId.value = courseIdForCourseSlug(
|
|
||||||
dashboardStore.dashboardConfigsv2,
|
|
||||||
props.courseSlug
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!courseId.value) {
|
|
||||||
log.error("CourseId not found for courseSlug", props.courseSlug);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("courseId", courseId.value);
|
return calcCompetenceCertificateGrade(
|
||||||
agentAssignmentData.value = await fetchMentorCompetenceSummary(
|
assignmentsWithUserCompletions as unknown as CompetenceCertificateAssignment[],
|
||||||
courseId.value,
|
false
|
||||||
props.agentRole
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalAverageGrade = computed(() => {
|
||||||
|
if (certificateData.value) {
|
||||||
|
let divisor = 0;
|
||||||
|
const assignmentAverageGrades = certificateData.value.assignments.map(
|
||||||
|
(assignment) => {
|
||||||
|
const relevantCompletions = (assignment.completions ?? []).filter(
|
||||||
|
(c) => c?.completion_status == "EVALUATION_SUBMITTED"
|
||||||
|
);
|
||||||
|
|
||||||
|
const averagePercent =
|
||||||
|
_.sumBy(relevantCompletions, (c) => c?.evaluation_percent ?? 0) /
|
||||||
|
relevantCompletions.length;
|
||||||
|
|
||||||
|
if (averagePercent > 0.0001) {
|
||||||
|
divisor += assignment.competence_certificate_weight ?? 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return averagePercent * (assignment.competence_certificate_weight ?? 1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return percentToRoundedGrade(
|
||||||
|
_.sum(assignmentAverageGrades) / (divisor ?? 1),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
log.debug("AgentAssignmentDetailPage mounted", courseSession);
|
||||||
|
|
||||||
|
const personData = await fetchDashboardPersons("default");
|
||||||
|
participants.value = personData?.filter((p) => {
|
||||||
|
return p.course_sessions.find(
|
||||||
|
(cs) => cs.id === courseSession.value.id && cs.my_role === "BERUFSBILDNER"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await graphqlClient.query(COMPETENCE_NAVI_CERTIFICATE_QUERY, {
|
||||||
|
courseSlug: props.courseSlug,
|
||||||
|
courseSessionId: courseSession.value.id,
|
||||||
|
userIds: participantUserIds.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
certificateData.value =
|
||||||
|
res.data?.competence_certificate_list?.competence_certificates.find(
|
||||||
|
// @ts-ignore
|
||||||
|
(cc) => cc.id === props.competenceCertificateId
|
||||||
);
|
);
|
||||||
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
type GroupedAssignments = {
|
|
||||||
competenceCertificateId: string;
|
|
||||||
competenceCertificateTitle: string;
|
|
||||||
generation: string;
|
|
||||||
courseSessionId: string;
|
|
||||||
assignments: AssignmentStatisticsRecordType[];
|
|
||||||
sumAverageEvaluationPercent: number;
|
|
||||||
averageEvaluationPercent: number | null;
|
|
||||||
averageGrade: number | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const courseSessionCompetenceAssignments = computed(() => {
|
|
||||||
let resultArray = [] as GroupedAssignments[];
|
|
||||||
|
|
||||||
// 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
|
|
||||||
);
|
|
||||||
if (entry) {
|
|
||||||
if (assignment.metrics.ranking_completed) {
|
|
||||||
entry.assignments.push(assignment);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const newEntry = {
|
|
||||||
competenceCertificateId: assignment.competence_certificate_id ?? "",
|
|
||||||
competenceCertificateTitle: assignment.competence_certificate_title ?? "",
|
|
||||||
generation: assignment.generation ?? "",
|
|
||||||
courseSessionId: assignment.course_session_id ?? "",
|
|
||||||
assignments: [] as AssignmentStatisticsRecordType[],
|
|
||||||
sumAverageEvaluationPercent: 0,
|
|
||||||
averageEvaluationPercent: null,
|
|
||||||
averageGrade: null,
|
|
||||||
};
|
|
||||||
if (assignment && assignment.metrics.ranking_completed) {
|
|
||||||
newEntry.assignments.push(assignment);
|
|
||||||
}
|
|
||||||
resultArray.push(newEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter out entries without assignments
|
|
||||||
resultArray = resultArray.filter((entry) => entry.assignments.length > 0);
|
|
||||||
|
|
||||||
// calculate average grade
|
|
||||||
for (const entry of resultArray) {
|
|
||||||
entry.sumAverageEvaluationPercent = _.sumBy(entry.assignments, (a) => {
|
|
||||||
return (
|
|
||||||
(a.metrics.average_evaluation_percent ?? 0) *
|
|
||||||
(a.metrics.competence_certificate_weight ?? 1)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
entry.averageEvaluationPercent =
|
|
||||||
entry.sumAverageEvaluationPercent /
|
|
||||||
_.sumBy(entry.assignments, (a) => {
|
|
||||||
return a.metrics.competence_certificate_weight ?? 1;
|
|
||||||
});
|
|
||||||
entry.averageGrade = percentToRoundedGrade(entry.averageEvaluationPercent, false);
|
|
||||||
}
|
|
||||||
return resultArray;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -136,34 +121,47 @@ const courseSessionCompetenceAssignments = computed(() => {
|
||||||
{{ $t("a.Statistik für alle Lernenden") }}
|
{{ $t("a.Statistik für alle Lernenden") }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<pre>{{ totalAverageGrade }}</pre>
|
||||||
|
|
||||||
<div class="bg-white px-4 py-2">
|
<div class="bg-white px-4 py-2">
|
||||||
<section
|
<section
|
||||||
class="flex flex-col space-x-0 border-b bg-white lg:flex-row lg:space-x-3"
|
class="flex flex-col space-x-0 border-b bg-white lg:flex-row lg:space-x-3"
|
||||||
></section>
|
></section>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-for="entry in courseSessionCompetenceAssignments"
|
v-for="person in participants"
|
||||||
:key="entry.courseSessionId"
|
:key="person.user_id"
|
||||||
:data-cy="`entry-${entry.courseSessionId}`"
|
data-cy="person"
|
||||||
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"
|
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="w-full flex-auto md:w-1/3">
|
<div class="w-full flex-auto md:w-1/2">
|
||||||
{{ entry.competenceCertificateTitle }}
|
<div class="flex items-center space-x-2">
|
||||||
<br />
|
<img
|
||||||
{{ $t("a.Durchführung") }} «{{
|
class="inline-block h-11 w-11 rounded-full"
|
||||||
courseSessionName(entry.courseSessionId)
|
:src="
|
||||||
}}»
|
person.avatar_url_small ||
|
||||||
|
'/static/avatars/myvbv-default-avatar.png'
|
||||||
|
"
|
||||||
|
:alt="`${person.first_name} ${person.last_name}`"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div class="text-bold">
|
||||||
|
{{ person.first_name }}
|
||||||
|
{{ person.last_name }}
|
||||||
|
</div>
|
||||||
|
<div class="text-gray-900">{{ person.email }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex w-full flex-auto items-start md:w-1/3">
|
<div class="flex w-full flex-auto items-start md:w-1/4">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div>{{ $t("a.Durchschnittsnote") }}:</div>
|
<div>{{ $t("a.Note") }}:</div>
|
||||||
<div class="w-16 text-center">
|
<div class="w-16 text-center">{{ userGrade(person.user_id) }}</div>
|
||||||
{{ entry.averageGrade }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full flex-auto items-end md:w-1/3 md:text-end">
|
<div class="w-full flex-auto items-end md:w-1/4 md:text-end">
|
||||||
Details anzeigen
|
Details anzeigen
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,6 @@ const courseSessionName = (courseSessionId: string) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const circleMeta = (circleId: string) => {
|
|
||||||
return agentAssignmentData.value?.course_session_properties.circles.find(
|
|
||||||
(circle) => circle.id === circleId
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await dashboardStore.loadDashboardDetails();
|
await dashboardStore.loadDashboardDetails();
|
||||||
courseId.value = courseIdForCourseSlug(
|
courseId.value = courseIdForCourseSlug(
|
||||||
|
|
@ -168,7 +162,13 @@ const courseSessionCompetenceAssignments = computed(() => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full flex-auto items-end md:w-1/3 md:text-end">
|
<div class="w-full flex-auto items-end md:w-1/3 md:text-end">
|
||||||
Details anzeigen
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -358,6 +358,12 @@ const router = createRouter({
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/pages/dashboard/agentAssignment/AgentCompetenceGradePage.vue"),
|
import("@/pages/dashboard/agentAssignment/AgentCompetenceGradePage.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/statistic/:agentRole/:courseSlug/competence-grade/:courseSessionId/:competenceCertificateId",
|
||||||
|
props: true,
|
||||||
|
component: () =>
|
||||||
|
import("@/pages/dashboard/agentAssignment/AgentCompetenceGradeDetailPage.vue"),
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: "/shop",
|
path: "/shop",
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ class AssignmentCompletionObjectType(DjangoObjectType):
|
||||||
evaluation_points = graphene.Float()
|
evaluation_points = graphene.Float()
|
||||||
evaluation_points_final = graphene.Float()
|
evaluation_points_final = graphene.Float()
|
||||||
evaluation_max_points = graphene.Float()
|
evaluation_max_points = graphene.Float()
|
||||||
|
evaluation_percent = graphene.Float()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = AssignmentCompletion
|
model = AssignmentCompletion
|
||||||
|
|
@ -61,6 +62,11 @@ class AssignmentCompletionObjectType(DjangoObjectType):
|
||||||
return round(self.evaluation_max_points, 1) # noqa
|
return round(self.evaluation_max_points, 1) # noqa
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def resolve_evaluation_percent(self, info):
|
||||||
|
if self.evaluation_points:
|
||||||
|
return self.evaluation_percent
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class AssignmentObjectType(DjangoObjectType):
|
class AssignmentObjectType(DjangoObjectType):
|
||||||
tasks = JSONStreamField()
|
tasks = JSONStreamField()
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,10 @@ class AssignmentCompletion(models.Model):
|
||||||
return None
|
return None
|
||||||
return self.evaluation_points - self.evaluation_points_deducted
|
return self.evaluation_points - self.evaluation_points_deducted
|
||||||
|
|
||||||
|
@property
|
||||||
|
def evaluation_percent(self):
|
||||||
|
return (self.evaluation_points_final or 0) / (self.evaluation_max_points or 1)
|
||||||
|
|
||||||
assignment_user = models.ForeignKey(User, on_delete=models.CASCADE)
|
assignment_user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
|
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
|
||||||
course_session = models.ForeignKey("course.CourseSession", on_delete=models.CASCADE)
|
course_session = models.ForeignKey("course.CourseSession", on_delete=models.CASCADE)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue