Query performance criteria also by course
This commit is contained in:
parent
a6cf4ad128
commit
a637775b81
|
|
@ -1,10 +1,11 @@
|
||||||
import { graphqlClient } from "@/graphql/client";
|
import { graphqlClient } from "@/graphql/client";
|
||||||
import { COURSE_SESSION_DETAIL_QUERY, LEARNING_PATH_QUERY } from "@/graphql/queries";
|
import { COURSE_QUERY, COURSE_SESSION_DETAIL_QUERY } from "@/graphql/queries";
|
||||||
import { circleFlatChildren, circleFlatLearningContents } from "@/services/circle";
|
import { circleFlatChildren, circleFlatLearningContents } from "@/services/circle";
|
||||||
import { useCompletionStore } from "@/stores/completion";
|
import { useCompletionStore } from "@/stores/completion";
|
||||||
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||||
import { useUserStore } from "@/stores/user";
|
import { useUserStore } from "@/stores/user";
|
||||||
import type {
|
import type {
|
||||||
|
ActionCompetence,
|
||||||
CourseCompletion,
|
CourseCompletion,
|
||||||
CourseCompletionStatus,
|
CourseCompletionStatus,
|
||||||
CourseSession,
|
CourseSession,
|
||||||
|
|
@ -12,6 +13,7 @@ import type {
|
||||||
LearningContentWithCompletion,
|
LearningContentWithCompletion,
|
||||||
LearningPathType,
|
LearningPathType,
|
||||||
LearningUnitPerformanceCriteria,
|
LearningUnitPerformanceCriteria,
|
||||||
|
PerformanceCriteria,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
import { useQuery } from "@urql/vue";
|
import { useQuery } from "@urql/vue";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
|
|
@ -140,14 +142,18 @@ export function flatCircles(learningPath: LearningPathType) {
|
||||||
|
|
||||||
export function useLearningPath(courseSlug: string) {
|
export function useLearningPath(courseSlug: string) {
|
||||||
const learningPath = ref<LearningPathType | undefined>(undefined);
|
const learningPath = ref<LearningPathType | undefined>(undefined);
|
||||||
|
const actionCompetences = ref<ActionCompetence[]>([]);
|
||||||
|
|
||||||
// urql.useQuery is not meant to be used programmatically, so we use graphqlClient.query instead
|
// urql.useQuery is not meant to be used programmatically, so we use graphqlClient.query instead
|
||||||
const resultPromise = graphqlClient
|
const resultPromise = graphqlClient
|
||||||
.query(LEARNING_PATH_QUERY, { slug: `${courseSlug}-lp` })
|
.query(COURSE_QUERY, { slug: `${courseSlug}` })
|
||||||
.toPromise();
|
.toPromise();
|
||||||
|
|
||||||
resultPromise.then((result) => {
|
resultPromise.then((result) => {
|
||||||
learningPath.value = result.data?.learning_path as LearningPathType;
|
actionCompetences.value = result.data?.course
|
||||||
|
?.action_competences as ActionCompetence[];
|
||||||
|
learningPath.value = result.data?.course?.learning_path as LearningPathType;
|
||||||
|
|
||||||
// attach circle information to learning contents
|
// attach circle information to learning contents
|
||||||
if (learningPath.value) {
|
if (learningPath.value) {
|
||||||
flatCircles(learningPath.value).forEach((circle) => {
|
flatCircles(learningPath.value).forEach((circle) => {
|
||||||
|
|
@ -157,6 +163,17 @@ export function useLearningPath(courseSlug: string) {
|
||||||
slug: circle.slug,
|
slug: circle.slug,
|
||||||
title: circle.title,
|
title: circle.title,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (lc.content_type === "competence.PerformanceCriteria") {
|
||||||
|
const pc = findPerformanceCriterion(lc.id);
|
||||||
|
if (pc) {
|
||||||
|
pc.circle = {
|
||||||
|
id: circle.id,
|
||||||
|
slug: circle.slug,
|
||||||
|
title: circle.title,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -175,6 +192,16 @@ export function useLearningPath(courseSlug: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findPerformanceCriterion(id: string) {
|
||||||
|
return (actionCompetences.value ?? [])
|
||||||
|
.flatMap((ac) => {
|
||||||
|
return ac.performance_criteria;
|
||||||
|
})
|
||||||
|
.find((pc) => {
|
||||||
|
return pc.id === id;
|
||||||
|
}) as PerformanceCriteria | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function findLearningContent(learningContentId: string) {
|
function findLearningContent(learningContentId: string) {
|
||||||
return (circles.value ?? [])
|
return (circles.value ?? [])
|
||||||
.flatMap((c) => {
|
.flatMap((c) => {
|
||||||
|
|
@ -185,7 +212,21 @@ export function useLearningPath(courseSlug: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return { resultPromise, learningPath, circles, findCircle, findLearningContent };
|
const flatPerformanceCriteria = computed(() => {
|
||||||
|
return (actionCompetences.value ?? []).flatMap((ac) => {
|
||||||
|
return ac.performance_criteria;
|
||||||
|
}) as PerformanceCriteria[];
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
resultPromise,
|
||||||
|
learningPath,
|
||||||
|
actionCompetences,
|
||||||
|
circles,
|
||||||
|
findCircle,
|
||||||
|
findLearningContent,
|
||||||
|
flatPerformanceCriteria,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useLearningPathWithCompletion(
|
export function useLearningPathWithCompletion(
|
||||||
|
|
@ -203,9 +244,10 @@ export function useLearningPathWithCompletion(
|
||||||
courseSessionId = useCurrentCourseSession().value.id;
|
courseSessionId = useCurrentCourseSession().value.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
const learningPathResult = useLearningPath(courseSlug);
|
const courseResult = useLearningPath(courseSlug);
|
||||||
const completionStore = useCompletionStore();
|
const completionStore = useCompletionStore();
|
||||||
const nextLearningContent = ref<LearningContentWithCompletion | null>(null);
|
const nextLearningContent = ref<LearningContentWithCompletion | null>(null);
|
||||||
|
const loaded = ref(false);
|
||||||
|
|
||||||
function updateCompletionData() {
|
function updateCompletionData() {
|
||||||
if (userId && courseSessionId) {
|
if (userId && courseSessionId) {
|
||||||
|
|
@ -215,8 +257,8 @@ export function useLearningPathWithCompletion(
|
||||||
}
|
}
|
||||||
|
|
||||||
function _parseCompletionData(completionData: CourseCompletion[]) {
|
function _parseCompletionData(completionData: CourseCompletion[]) {
|
||||||
if (learningPathResult.circles.value) {
|
if (courseResult.circles.value) {
|
||||||
learningPathResult.circles.value.forEach((circle) => {
|
courseResult.circles.value.forEach((circle) => {
|
||||||
circleFlatChildren(circle).forEach((lc) => {
|
circleFlatChildren(circle).forEach((lc) => {
|
||||||
const pageIndex = completionData.findIndex((e) => {
|
const pageIndex = completionData.findIndex((e) => {
|
||||||
return e.page_id === lc.id;
|
return e.page_id === lc.id;
|
||||||
|
|
@ -230,10 +272,25 @@ export function useLearningPathWithCompletion(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (courseResult.actionCompetences.value) {
|
||||||
|
courseResult.actionCompetences.value.forEach((ac) => {
|
||||||
|
ac.performance_criteria.forEach((pc) => {
|
||||||
|
const pageIndex = completionData.findIndex((e) => {
|
||||||
|
return e.page_id === pc.id;
|
||||||
|
});
|
||||||
|
if (pageIndex >= 0) {
|
||||||
|
pc.completion_status = completionData[pageIndex].completion_status;
|
||||||
|
} else {
|
||||||
|
pc.completion_status = "UNKNOWN";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME calculate nextLearningContent
|
// FIXME calculate nextLearningContent
|
||||||
if (learningPathResult.circles.value?.length) {
|
if (courseResult.circles.value?.length) {
|
||||||
nextLearningContent.value = circleFlatLearningContents(
|
nextLearningContent.value = circleFlatLearningContents(
|
||||||
learningPathResult.circles.value[0]
|
courseResult.circles.value[0]
|
||||||
)[0];
|
)[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -254,10 +311,11 @@ export function useLearningPathWithCompletion(
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _start() {
|
async function _start() {
|
||||||
Promise.all([learningPathResult.resultPromise, updateCompletionData()]).then(
|
Promise.all([courseResult.resultPromise, updateCompletionData()]).then(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
([_queryResults, completionData]) => {
|
([_queryResults, completionData]) => {
|
||||||
_parseCompletionData(completionData);
|
_parseCompletionData(completionData);
|
||||||
|
loaded.value = true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +323,8 @@ export function useLearningPathWithCompletion(
|
||||||
_start();
|
_start();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...learningPathResult,
|
...courseResult,
|
||||||
|
loaded,
|
||||||
updateCompletionData,
|
updateCompletionData,
|
||||||
markCompletion,
|
markCompletion,
|
||||||
nextLearningContent,
|
nextLearningContent,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const documents = {
|
||||||
"\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 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 }\n assignment_user {\n id\n }\n evaluation_points\n evaluation_max_points\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 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 }\n assignment_user {\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n": types.AssignmentCompletionQueryDocument,
|
||||||
"\n query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {\n competence_certificate_list(course_slug: $courseSlug) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\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.CompetenceCertificateQueryDocument,
|
"\n query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {\n competence_certificate_list(course_slug: $courseSlug) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\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.CompetenceCertificateQueryDocument,
|
||||||
"\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\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 }\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 learningPathQuery($slug: String!) {\n learning_path(slug: $slug) {\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 ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n competence_certificate {\n ...CoursePageFields\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.LearningPathQueryDocument,
|
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n slug\n category_name\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 ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n competence_certificate {\n ...CoursePageFields\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument,
|
||||||
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
|
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ export function graphql(source: "\n query courseSessionDetail($courseSessionId:
|
||||||
/**
|
/**
|
||||||
* 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 learningPathQuery($slug: String!) {\n learning_path(slug: $slug) {\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 ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n competence_certificate {\n ...CoursePageFields\n }\n }\n }\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query learningPathQuery($slug: String!) {\n learning_path(slug: $slug) {\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 ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n competence_certificate {\n ...CoursePageFields\n }\n }\n }\n }\n }\n }\n }\n }\n }\n"];
|
export function graphql(source: "\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n slug\n category_name\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 ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n competence_certificate {\n ...CoursePageFields\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n slug\n category_name\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 ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n competence_certificate {\n ...CoursePageFields\n }\n }\n }\n }\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
|
|
@ -1,5 +1,8 @@
|
||||||
type Query {
|
type Query {
|
||||||
learning_path(id: ID, slug: String, course_id: ID, course_slug: String): LearningPathObjectType
|
learning_path(id: ID, slug: String, course_id: ID, course_slug: String): LearningPathObjectType
|
||||||
|
course_session_attendance_course(id: ID!, assignment_user_id: ID): CourseSessionAttendanceCourseObjectType
|
||||||
|
course(id: ID, slug: String): CourseObjectType
|
||||||
|
course_session(id: ID): CourseSessionObjectType
|
||||||
learning_content_media_library: LearningContentMediaLibraryObjectType
|
learning_content_media_library: LearningContentMediaLibraryObjectType
|
||||||
learning_content_assignment: LearningContentAssignmentObjectType
|
learning_content_assignment: LearningContentAssignmentObjectType
|
||||||
learning_content_attendance_course: LearningContentAttendanceCourseObjectType
|
learning_content_attendance_course: LearningContentAttendanceCourseObjectType
|
||||||
|
|
@ -10,9 +13,6 @@ type Query {
|
||||||
learning_content_test: LearningContentEdoniqTestObjectType
|
learning_content_test: LearningContentEdoniqTestObjectType
|
||||||
learning_content_video: LearningContentVideoObjectType
|
learning_content_video: LearningContentVideoObjectType
|
||||||
learning_content_document_list: LearningContentDocumentListObjectType
|
learning_content_document_list: LearningContentDocumentListObjectType
|
||||||
course_session_attendance_course(id: ID!, assignment_user_id: ID): CourseSessionAttendanceCourseObjectType
|
|
||||||
course(id: ID): CourseObjectType
|
|
||||||
course_session(id: ID): CourseSessionObjectType
|
|
||||||
competence_certificate(id: ID, slug: String): CompetenceCertificateObjectType
|
competence_certificate(id: ID, slug: String): CompetenceCertificateObjectType
|
||||||
competence_certificate_list(id: ID, slug: String, course_id: ID, course_slug: String): CompetenceCertificateListObjectType
|
competence_certificate_list(id: ID, slug: String, course_id: ID, course_slug: String): CompetenceCertificateListObjectType
|
||||||
assignment(id: ID, slug: String): AssignmentObjectType
|
assignment(id: ID, slug: String): AssignmentObjectType
|
||||||
|
|
@ -47,6 +47,71 @@ type CourseObjectType {
|
||||||
title: String!
|
title: String!
|
||||||
category_name: String!
|
category_name: String!
|
||||||
slug: String!
|
slug: String!
|
||||||
|
learning_path: LearningPathObjectType!
|
||||||
|
action_competences: [ActionCompetenceObjectType!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActionCompetenceObjectType implements CoursePageInterface {
|
||||||
|
competence_id: String!
|
||||||
|
id: ID!
|
||||||
|
title: String!
|
||||||
|
slug: String!
|
||||||
|
content_type: String!
|
||||||
|
live: Boolean!
|
||||||
|
translation_key: String!
|
||||||
|
frontend_url: String!
|
||||||
|
course: CourseObjectType
|
||||||
|
performance_criteria: [PerformanceCriteriaObjectType!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type PerformanceCriteriaObjectType implements CoursePageInterface {
|
||||||
|
competence_id: String!
|
||||||
|
id: ID!
|
||||||
|
title: String!
|
||||||
|
slug: String!
|
||||||
|
content_type: String!
|
||||||
|
live: Boolean!
|
||||||
|
translation_key: String!
|
||||||
|
frontend_url: String!
|
||||||
|
course: CourseObjectType
|
||||||
|
learning_unit: LearningUnitObjectType
|
||||||
|
}
|
||||||
|
|
||||||
|
type LearningUnitObjectType implements CoursePageInterface {
|
||||||
|
title_hidden: Boolean!
|
||||||
|
id: ID!
|
||||||
|
title: String!
|
||||||
|
slug: String!
|
||||||
|
content_type: String!
|
||||||
|
live: Boolean!
|
||||||
|
translation_key: String!
|
||||||
|
frontend_url: String!
|
||||||
|
course: CourseObjectType
|
||||||
|
learning_contents: [LearningContentInterface!]!
|
||||||
|
performance_criteria: [PerformanceCriteriaObjectType!]!
|
||||||
|
evaluate_url: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LearningContentInterface {
|
||||||
|
id: ID!
|
||||||
|
title: String!
|
||||||
|
slug: String!
|
||||||
|
content_type: String!
|
||||||
|
live: Boolean!
|
||||||
|
translation_key: String!
|
||||||
|
frontend_url: String!
|
||||||
|
course: CourseObjectType
|
||||||
|
minutes: Int
|
||||||
|
description: String!
|
||||||
|
content_url: String!
|
||||||
|
can_user_self_toggle_course_completion: Boolean!
|
||||||
|
circle: CircleLightObjectType
|
||||||
|
}
|
||||||
|
|
||||||
|
type CircleLightObjectType {
|
||||||
|
id: ID!
|
||||||
|
title: String!
|
||||||
|
slug: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type TopicObjectType implements CoursePageInterface {
|
type TopicObjectType implements CoursePageInterface {
|
||||||
|
|
@ -89,22 +154,18 @@ type LearningSequenceObjectType implements CoursePageInterface {
|
||||||
learning_units: [LearningUnitObjectType!]!
|
learning_units: [LearningUnitObjectType!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type LearningUnitObjectType implements CoursePageInterface {
|
type CourseSessionAttendanceCourseObjectType {
|
||||||
title_hidden: Boolean!
|
|
||||||
id: ID!
|
id: ID!
|
||||||
title: String!
|
learning_content: LearningContentAttendanceCourseObjectType!
|
||||||
slug: String!
|
due_date: DueDateObjectType
|
||||||
content_type: String!
|
location: String!
|
||||||
live: Boolean!
|
trainer: String!
|
||||||
translation_key: String!
|
course_session_id: ID
|
||||||
frontend_url: String!
|
learning_content_id: ID
|
||||||
course: CourseObjectType
|
attendance_user_list: [AttendanceUserObjectType]
|
||||||
learning_contents: [LearningContentInterface!]!
|
|
||||||
performance_criteria: [PerformanceCriteriaObjectType!]!
|
|
||||||
evaluate_url: String!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LearningContentInterface {
|
type LearningContentAttendanceCourseObjectType implements CoursePageInterface & LearningContentInterface {
|
||||||
id: ID!
|
id: ID!
|
||||||
title: String!
|
title: String!
|
||||||
slug: String!
|
slug: String!
|
||||||
|
|
@ -120,38 +181,74 @@ interface LearningContentInterface {
|
||||||
circle: CircleLightObjectType
|
circle: CircleLightObjectType
|
||||||
}
|
}
|
||||||
|
|
||||||
type CircleLightObjectType {
|
type DueDateObjectType {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
|
||||||
|
"""Startdatum ist Pflicht"""
|
||||||
|
start: DateTime
|
||||||
|
|
||||||
|
"""Enddatum ist optional"""
|
||||||
|
end: DateTime
|
||||||
|
|
||||||
|
"""Nur aktivieren, wenn man die Felder manuell überschreiben will"""
|
||||||
|
manual_override_fields: Boolean!
|
||||||
|
|
||||||
|
"""Title wird standarmässig vom LearningContent übernommen"""
|
||||||
title: String!
|
title: String!
|
||||||
slug: String!
|
|
||||||
|
"""Translation Key aus dem Frontend"""
|
||||||
|
assignment_type_translation_key: String!
|
||||||
|
|
||||||
|
"""Translation Key aus dem Frontend"""
|
||||||
|
date_type_translation_key: String!
|
||||||
|
|
||||||
|
"""
|
||||||
|
Überschreibt den Untertitel bei `assignment_type_translation_key` und `date_type_translation_key`
|
||||||
|
"""
|
||||||
|
subtitle: String!
|
||||||
|
|
||||||
|
"""
|
||||||
|
URL wird vom LearningContent übernommen (sichtbar für Member/Teilnehmer)
|
||||||
|
"""
|
||||||
|
url: String!
|
||||||
|
course_session: CourseSessionObjectType!
|
||||||
}
|
}
|
||||||
|
|
||||||
type PerformanceCriteriaObjectType implements CoursePageInterface {
|
"""
|
||||||
competence_id: String!
|
The `DateTime` scalar type represents a DateTime
|
||||||
|
value as specified by
|
||||||
|
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
|
||||||
|
"""
|
||||||
|
scalar DateTime
|
||||||
|
|
||||||
|
type CourseSessionObjectType {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
created_at: DateTime!
|
||||||
|
updated_at: DateTime!
|
||||||
|
course: CourseObjectType!
|
||||||
title: String!
|
title: String!
|
||||||
slug: String!
|
start_date: Date
|
||||||
content_type: String!
|
end_date: Date
|
||||||
live: Boolean!
|
attendance_courses: [CourseSessionAttendanceCourseObjectType!]!
|
||||||
translation_key: String!
|
assignments: [CourseSessionAssignmentObjectType!]!
|
||||||
frontend_url: String!
|
edoniq_tests: [CourseSessionEdoniqTestObjectType!]!
|
||||||
course: CourseObjectType
|
users: [CourseSessionUserObjectsType!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type LearningContentMediaLibraryObjectType implements CoursePageInterface & LearningContentInterface {
|
"""
|
||||||
|
The `Date` scalar type represents a Date
|
||||||
|
value as specified by
|
||||||
|
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
|
||||||
|
"""
|
||||||
|
scalar Date
|
||||||
|
|
||||||
|
type CourseSessionAssignmentObjectType {
|
||||||
id: ID!
|
id: ID!
|
||||||
title: String!
|
learning_content: LearningContentAssignmentObjectType!
|
||||||
slug: String!
|
submission_deadline: DueDateObjectType
|
||||||
content_type: String!
|
evaluation_deadline: DueDateObjectType
|
||||||
live: Boolean!
|
course_session_id: ID!
|
||||||
translation_key: String!
|
learning_content_id: ID!
|
||||||
frontend_url: String!
|
|
||||||
course: CourseObjectType
|
|
||||||
minutes: Int
|
|
||||||
description: String!
|
|
||||||
content_url: String!
|
|
||||||
can_user_self_toggle_course_completion: Boolean!
|
|
||||||
circle: CircleLightObjectType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type LearningContentAssignmentObjectType implements CoursePageInterface & LearningContentInterface {
|
type LearningContentAssignmentObjectType implements CoursePageInterface & LearningContentInterface {
|
||||||
|
|
@ -268,13 +365,6 @@ in fields, resolvers and input.
|
||||||
"""
|
"""
|
||||||
scalar UUID
|
scalar UUID
|
||||||
|
|
||||||
"""
|
|
||||||
The `DateTime` scalar type represents a DateTime
|
|
||||||
value as specified by
|
|
||||||
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
|
|
||||||
"""
|
|
||||||
scalar DateTime
|
|
||||||
|
|
||||||
type UserObjectType {
|
type UserObjectType {
|
||||||
"""
|
"""
|
||||||
Erforderlich. 150 Zeichen oder weniger. Nur Buchstaben, Ziffern und @/./+/-/_.
|
Erforderlich. 150 Zeichen oder weniger. Nur Buchstaben, Ziffern und @/./+/-/_.
|
||||||
|
|
@ -300,108 +390,52 @@ enum CoreUserLanguageChoices {
|
||||||
IT
|
IT
|
||||||
}
|
}
|
||||||
|
|
||||||
type CourseSessionObjectType {
|
"""An enumeration."""
|
||||||
id: ID!
|
enum AssignmentAssignmentCompletionCompletionStatusChoices {
|
||||||
created_at: DateTime!
|
"""IN_PROGRESS"""
|
||||||
updated_at: DateTime!
|
IN_PROGRESS
|
||||||
course: CourseObjectType!
|
|
||||||
title: String!
|
"""SUBMITTED"""
|
||||||
start_date: Date
|
SUBMITTED
|
||||||
end_date: Date
|
|
||||||
attendance_courses: [CourseSessionAttendanceCourseObjectType!]!
|
"""EVALUATION_IN_PROGRESS"""
|
||||||
assignments: [CourseSessionAssignmentObjectType!]!
|
EVALUATION_IN_PROGRESS
|
||||||
edoniq_tests: [CourseSessionEdoniqTestObjectType!]!
|
|
||||||
users: [CourseSessionUserObjectsType!]!
|
"""EVALUATION_SUBMITTED"""
|
||||||
|
EVALUATION_SUBMITTED
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
The `Date` scalar type represents a Date
|
The `GenericScalar` scalar type represents a generic
|
||||||
value as specified by
|
GraphQL scalar value that could be:
|
||||||
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
|
String, Boolean, Int, Float, List or Object.
|
||||||
"""
|
"""
|
||||||
scalar Date
|
scalar GenericScalar
|
||||||
|
|
||||||
type CourseSessionAttendanceCourseObjectType {
|
|
||||||
id: ID!
|
|
||||||
learning_content: LearningContentAttendanceCourseObjectType!
|
|
||||||
due_date: DueDateObjectType
|
|
||||||
location: String!
|
|
||||||
trainer: String!
|
|
||||||
course_session_id: ID
|
|
||||||
learning_content_id: ID
|
|
||||||
attendance_user_list: [AttendanceUserObjectType]
|
|
||||||
}
|
|
||||||
|
|
||||||
type LearningContentAttendanceCourseObjectType implements CoursePageInterface & LearningContentInterface {
|
|
||||||
id: ID!
|
|
||||||
title: String!
|
|
||||||
slug: String!
|
|
||||||
content_type: String!
|
|
||||||
live: Boolean!
|
|
||||||
translation_key: String!
|
|
||||||
frontend_url: String!
|
|
||||||
course: CourseObjectType
|
|
||||||
minutes: Int
|
|
||||||
description: String!
|
|
||||||
content_url: String!
|
|
||||||
can_user_self_toggle_course_completion: Boolean!
|
|
||||||
circle: CircleLightObjectType
|
|
||||||
}
|
|
||||||
|
|
||||||
type DueDateObjectType {
|
|
||||||
id: ID!
|
|
||||||
|
|
||||||
"""Startdatum ist Pflicht"""
|
|
||||||
start: DateTime
|
|
||||||
|
|
||||||
"""Enddatum ist optional"""
|
|
||||||
end: DateTime
|
|
||||||
|
|
||||||
"""Nur aktivieren, wenn man die Felder manuell überschreiben will"""
|
|
||||||
manual_override_fields: Boolean!
|
|
||||||
|
|
||||||
"""Title wird standarmässig vom LearningContent übernommen"""
|
|
||||||
title: String!
|
|
||||||
|
|
||||||
"""Translation Key aus dem Frontend"""
|
|
||||||
assignment_type_translation_key: String!
|
|
||||||
|
|
||||||
"""Translation Key aus dem Frontend"""
|
|
||||||
date_type_translation_key: String!
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Überschreibt den Untertitel bei `assignment_type_translation_key` und `date_type_translation_key`
|
Allows use of a JSON String for input / output from the GraphQL schema.
|
||||||
"""
|
|
||||||
subtitle: String!
|
|
||||||
|
|
||||||
|
Use of this type is *not recommended* as you lose the benefits of having a defined, static
|
||||||
|
schema (one of the key benefits of GraphQL).
|
||||||
"""
|
"""
|
||||||
URL wird vom LearningContent übernommen (sichtbar für Member/Teilnehmer)
|
scalar JSONString
|
||||||
"""
|
|
||||||
url: String!
|
|
||||||
course_session: CourseSessionObjectType!
|
|
||||||
}
|
|
||||||
|
|
||||||
type AttendanceUserObjectType {
|
|
||||||
user_id: UUID!
|
|
||||||
status: AttendanceUserStatus!
|
|
||||||
first_name: String
|
|
||||||
last_name: String
|
|
||||||
email: String
|
|
||||||
}
|
|
||||||
|
|
||||||
"""An enumeration."""
|
"""An enumeration."""
|
||||||
enum AttendanceUserStatus {
|
enum LearnpathLearningContentAssignmentAssignmentTypeChoices {
|
||||||
PRESENT
|
"""CASEWORK"""
|
||||||
ABSENT
|
CASEWORK
|
||||||
}
|
|
||||||
|
|
||||||
type CourseSessionAssignmentObjectType {
|
"""PREP_ASSIGNMENT"""
|
||||||
id: ID!
|
PREP_ASSIGNMENT
|
||||||
learning_content: LearningContentAssignmentObjectType!
|
|
||||||
submission_deadline: DueDateObjectType
|
"""REFLECTION"""
|
||||||
evaluation_deadline: DueDateObjectType
|
REFLECTION
|
||||||
course_session_id: ID!
|
|
||||||
learning_content_id: ID!
|
"""CONDITION_ACCEPTANCE"""
|
||||||
|
CONDITION_ACCEPTANCE
|
||||||
|
|
||||||
|
"""EDONIQ_TEST"""
|
||||||
|
EDONIQ_TEST
|
||||||
}
|
}
|
||||||
|
|
||||||
type CourseSessionEdoniqTestObjectType {
|
type CourseSessionEdoniqTestObjectType {
|
||||||
|
|
@ -460,52 +494,34 @@ type CourseSessionUserExpertCircleType {
|
||||||
slug: String!
|
slug: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
"""An enumeration."""
|
type AttendanceUserObjectType {
|
||||||
enum AssignmentAssignmentCompletionCompletionStatusChoices {
|
user_id: UUID!
|
||||||
"""IN_PROGRESS"""
|
status: AttendanceUserStatus!
|
||||||
IN_PROGRESS
|
first_name: String
|
||||||
|
last_name: String
|
||||||
"""SUBMITTED"""
|
email: String
|
||||||
SUBMITTED
|
|
||||||
|
|
||||||
"""EVALUATION_IN_PROGRESS"""
|
|
||||||
EVALUATION_IN_PROGRESS
|
|
||||||
|
|
||||||
"""EVALUATION_SUBMITTED"""
|
|
||||||
EVALUATION_SUBMITTED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
|
||||||
The `GenericScalar` scalar type represents a generic
|
|
||||||
GraphQL scalar value that could be:
|
|
||||||
String, Boolean, Int, Float, List or Object.
|
|
||||||
"""
|
|
||||||
scalar GenericScalar
|
|
||||||
|
|
||||||
"""
|
|
||||||
Allows use of a JSON String for input / output from the GraphQL schema.
|
|
||||||
|
|
||||||
Use of this type is *not recommended* as you lose the benefits of having a defined, static
|
|
||||||
schema (one of the key benefits of GraphQL).
|
|
||||||
"""
|
|
||||||
scalar JSONString
|
|
||||||
|
|
||||||
"""An enumeration."""
|
"""An enumeration."""
|
||||||
enum LearnpathLearningContentAssignmentAssignmentTypeChoices {
|
enum AttendanceUserStatus {
|
||||||
"""CASEWORK"""
|
PRESENT
|
||||||
CASEWORK
|
ABSENT
|
||||||
|
}
|
||||||
|
|
||||||
"""PREP_ASSIGNMENT"""
|
type LearningContentMediaLibraryObjectType implements CoursePageInterface & LearningContentInterface {
|
||||||
PREP_ASSIGNMENT
|
id: ID!
|
||||||
|
title: String!
|
||||||
"""REFLECTION"""
|
slug: String!
|
||||||
REFLECTION
|
content_type: String!
|
||||||
|
live: Boolean!
|
||||||
"""CONDITION_ACCEPTANCE"""
|
translation_key: String!
|
||||||
CONDITION_ACCEPTANCE
|
frontend_url: String!
|
||||||
|
course: CourseObjectType
|
||||||
"""EDONIQ_TEST"""
|
minutes: Int
|
||||||
EDONIQ_TEST
|
description: String!
|
||||||
|
content_url: String!
|
||||||
|
can_user_self_toggle_course_completion: Boolean!
|
||||||
|
circle: CircleLightObjectType
|
||||||
}
|
}
|
||||||
|
|
||||||
type LearningContentFeedbackObjectType implements CoursePageInterface & LearningContentInterface {
|
type LearningContentFeedbackObjectType implements CoursePageInterface & LearningContentInterface {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
export const ActionCompetenceObjectType = "ActionCompetenceObjectType";
|
||||||
export const AssignmentAssignmentAssignmentTypeChoices = "AssignmentAssignmentAssignmentTypeChoices";
|
export const AssignmentAssignmentAssignmentTypeChoices = "AssignmentAssignmentAssignmentTypeChoices";
|
||||||
export const AssignmentAssignmentCompletionCompletionStatusChoices = "AssignmentAssignmentCompletionCompletionStatusChoices";
|
export const AssignmentAssignmentCompletionCompletionStatusChoices = "AssignmentAssignmentCompletionCompletionStatusChoices";
|
||||||
export const AssignmentCompletionMutation = "AssignmentCompletionMutation";
|
export const AssignmentCompletionMutation = "AssignmentCompletionMutation";
|
||||||
|
|
|
||||||
|
|
@ -193,9 +193,26 @@ export const COURSE_SESSION_DETAIL_QUERY = graphql(`
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
export const LEARNING_PATH_QUERY = graphql(`
|
export const COURSE_QUERY = graphql(`
|
||||||
query learningPathQuery($slug: String!) {
|
query courseQuery($slug: String!) {
|
||||||
learning_path(slug: $slug) {
|
course(slug: $slug) {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
category_name
|
||||||
|
action_competences {
|
||||||
|
competence_id
|
||||||
|
...CoursePageFields
|
||||||
|
performance_criteria {
|
||||||
|
competence_id
|
||||||
|
learning_unit {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
evaluate_url
|
||||||
|
}
|
||||||
|
...CoursePageFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
learning_path {
|
||||||
...CoursePageFields
|
...CoursePageFields
|
||||||
topics {
|
topics {
|
||||||
is_visible
|
is_visible
|
||||||
|
|
@ -238,4 +255,5 @@ export const LEARNING_PATH_QUERY = graphql(`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useCourseSessionDetailQuery } from "@/composables";
|
import { useCourseSessionDetailQuery } from "@/composables";
|
||||||
import { useCockpitStore } from "@/stores/cockpit";
|
import { useCockpitStore } from "@/stores/cockpit";
|
||||||
import { useCompetenceStore } from "@/stores/competence";
|
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
import { onMounted } from "vue";
|
import { onMounted } from "vue";
|
||||||
|
|
||||||
|
|
@ -12,7 +11,6 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const cockpitStore = useCockpitStore();
|
const cockpitStore = useCockpitStore();
|
||||||
const competenceStore = useCompetenceStore();
|
|
||||||
const courseSessionDetailResult = useCourseSessionDetailQuery();
|
const courseSessionDetailResult = useCourseSessionDetailQuery();
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|
@ -20,17 +18,13 @@ onMounted(async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await courseSessionDetailResult.waitForData();
|
await courseSessionDetailResult.waitForData();
|
||||||
const members = courseSessionDetailResult.filterMembers();
|
|
||||||
members.forEach((csu) => {
|
|
||||||
competenceStore.loadCompetenceProfilePage(
|
|
||||||
props.courseSlug + "-competencenavi-competences",
|
|
||||||
csu.user_id
|
|
||||||
);
|
|
||||||
});
|
|
||||||
await cockpitStore.loadCircles(
|
await cockpitStore.loadCircles(
|
||||||
props.courseSlug,
|
props.courseSlug,
|
||||||
courseSessionDetailResult.findCurrentUser()
|
courseSessionDetailResult.findCurrentUser()
|
||||||
);
|
);
|
||||||
|
// const members = courseSessionDetailResult.filterMembers().map((m) => {
|
||||||
|
// return {}
|
||||||
|
// });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(error);
|
log.error(error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ import ItPersonRow from "@/components/ui/ItPersonRow.vue";
|
||||||
import { useCourseSessionDetailQuery, useCurrentCourseSession } from "@/composables";
|
import { useCourseSessionDetailQuery, useCurrentCourseSession } from "@/composables";
|
||||||
import SubmissionsOverview from "@/pages/cockpit/cockpitPage/SubmissionsOverview.vue";
|
import SubmissionsOverview from "@/pages/cockpit/cockpitPage/SubmissionsOverview.vue";
|
||||||
import { useCockpitStore } from "@/stores/cockpit";
|
import { useCockpitStore } from "@/stores/cockpit";
|
||||||
import { useCompetenceStore } from "@/stores/competence";
|
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import CockpitDates from "@/pages/cockpit/cockpitPage/CockpitDates.vue";
|
import CockpitDates from "@/pages/cockpit/cockpitPage/CockpitDates.vue";
|
||||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||||
|
import UserStatusCount from "@/pages/cockpit/cockpitPage/UserStatusCount.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
|
|
@ -17,18 +17,8 @@ const props = defineProps<{
|
||||||
log.debug("CockpitIndexPage created", props.courseSlug);
|
log.debug("CockpitIndexPage created", props.courseSlug);
|
||||||
|
|
||||||
const cockpitStore = useCockpitStore();
|
const cockpitStore = useCockpitStore();
|
||||||
const competenceStore = useCompetenceStore();
|
|
||||||
const courseSession = useCurrentCourseSession();
|
const courseSession = useCurrentCourseSession();
|
||||||
const courseSessionDetailResult = useCourseSessionDetailQuery();
|
const courseSessionDetailResult = useCourseSessionDetailQuery();
|
||||||
|
|
||||||
function userCountStatusForCircle(userId: string) {
|
|
||||||
if (!cockpitStore.currentCircle) return { FAIL: 0, SUCCESS: 0, UNKNOWN: 0 };
|
|
||||||
const criteria = competenceStore.flatPerformanceCriteria(
|
|
||||||
userId,
|
|
||||||
cockpitStore.currentCircle.id
|
|
||||||
);
|
|
||||||
return competenceStore.calcStatusCount(criteria);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -150,32 +140,10 @@ function userCountStatusForCircle(userId: string) {
|
||||||
<p class="lg:min-w-[150px]">
|
<p class="lg:min-w-[150px]">
|
||||||
{{ cockpitStore.currentCircle.title }}
|
{{ cockpitStore.currentCircle.title }}
|
||||||
</p>
|
</p>
|
||||||
<div class="ml-4 flex flex-row items-center">
|
<UserStatusCount
|
||||||
<div class="mr-6 flex flex-row items-center">
|
:course-slug="props.courseSlug"
|
||||||
<it-icon-smiley-thinking
|
:user-id="csu.user_id"
|
||||||
class="mr-2 inline-block h-8 w-8"
|
></UserStatusCount>
|
||||||
></it-icon-smiley-thinking>
|
|
||||||
<p class="text-bold inline-block w-6">
|
|
||||||
{{ userCountStatusForCircle(csu.user_id).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).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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #link>
|
<template #link>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useLearningPathWithCompletion } from "@/composables";
|
||||||
|
import { computed } from "vue";
|
||||||
|
import { calcPerformanceCriteriaStatusCount } from "@/services/competence";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
courseSlug: string;
|
||||||
|
userId: string;
|
||||||
|
circleId?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const courseData = useLearningPathWithCompletion(props.courseSlug, props.userId);
|
||||||
|
|
||||||
|
const circleStatusCount = computed(() => {
|
||||||
|
if (props.circleId) {
|
||||||
|
return calcPerformanceCriteriaStatusCount(
|
||||||
|
(courseData.flatPerformanceCriteria.value ?? []).filter(
|
||||||
|
(pc) => pc.circle.id === props.circleId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return calcPerformanceCriteriaStatusCount(courseData.flatPerformanceCriteria.value);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="courseData.loaded" 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">
|
||||||
|
{{ circleStatusCount.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">
|
||||||
|
{{ circleStatusCount.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">
|
||||||
|
{{ circleStatusCount.UNKNOWN }}
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ItToggleArrow from "@/components/ui/ItToggleArrow.vue";
|
import ItToggleArrow from "@/components/ui/ItToggleArrow.vue";
|
||||||
import { useCompetenceStore } from "@/stores/competence";
|
|
||||||
import type { CompetencePage } from "@/types";
|
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import SinglePerformanceCriteriaRow from "@/pages/competence/SinglePerformanceCriteriaRow.vue";
|
import SinglePerformanceCriteriaRow from "@/pages/competence/SinglePerformanceCriteriaRow.vue";
|
||||||
|
import type { ActionCompetence } from "@/types";
|
||||||
const competenceStore = useCompetenceStore();
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
competence: CompetencePage;
|
competence: ActionCompetence;
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
showAssessAgain?: boolean;
|
showAssessAgain?: boolean;
|
||||||
isInline?: boolean;
|
isInline?: boolean;
|
||||||
|
|
@ -60,12 +57,12 @@ const togglePerformanceCriteria = () => {
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li
|
<li
|
||||||
v-for="performanceCriteria in competenceStore.criteriaByCompetence(competence)"
|
v-for="performanceCriteria in competence.performance_criteria"
|
||||||
:key="performanceCriteria.id"
|
:key="performanceCriteria.id"
|
||||||
class="my-4 border-b pb-4 last:border-0"
|
class="my-4 border-b pb-4 last:border-0"
|
||||||
>
|
>
|
||||||
<SinglePerformanceCriteriaRow
|
<SinglePerformanceCriteriaRow
|
||||||
:criteria="performanceCriteria"
|
:criterion="performanceCriteria"
|
||||||
:show-state="false"
|
:show-state="false"
|
||||||
:course-slug="props.courseSlug"
|
:course-slug="props.courseSlug"
|
||||||
:show-assess-again="props.showAssessAgain"
|
:show-assess-again="props.showAssessAgain"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import CompetenceDetail from "@/pages/competence/ActionCompetenceDetail.vue";
|
import CompetenceDetail from "@/pages/competence/ActionCompetenceDetail.vue";
|
||||||
import { useCompetenceStore } from "@/stores/competence";
|
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
import { useLearningPathWithCompletion } from "@/composables";
|
||||||
|
|
||||||
log.debug("CompetenceListPage created");
|
log.debug("CompetenceListPage created");
|
||||||
|
|
||||||
|
|
@ -10,7 +10,7 @@ const props = defineProps<{
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const competenceStore = useCompetenceStore();
|
const courseData = useLearningPathWithCompletion(props.courseSlug);
|
||||||
|
|
||||||
const isOpenAll = ref(false);
|
const isOpenAll = ref(false);
|
||||||
|
|
||||||
|
|
@ -40,9 +40,9 @@ function toggleOpen() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul v-if="competenceStore.competenceProfilePage()">
|
<ul v-if="courseData.actionCompetences.value?.length">
|
||||||
<li
|
<li
|
||||||
v-for="competence in competenceStore.competences()"
|
v-for="competence in courseData.actionCompetences.value"
|
||||||
:key="competence.id"
|
:key="competence.id"
|
||||||
class="mb-8 bg-white px-8 pt-6"
|
class="mb-8 bg-white px-8 pt-6"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@ import { COMPETENCE_NAVI_CERTIFICATE_QUERY } from "@/graphql/queries";
|
||||||
import { useQuery } from "@urql/vue";
|
import { useQuery } from "@urql/vue";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import type { CompetenceCertificate } from "@/types";
|
import type { CompetenceCertificate } from "@/types";
|
||||||
import { useCurrentCourseSession } from "@/composables";
|
import { useCurrentCourseSession, useLearningPathWithCompletion } from "@/composables";
|
||||||
import {
|
import {
|
||||||
assignmentsMaxEvaluationPoints,
|
assignmentsMaxEvaluationPoints,
|
||||||
assignmentsUserPoints,
|
assignmentsUserPoints,
|
||||||
competenceCertificateProgressStatusCount,
|
competenceCertificateProgressStatusCount,
|
||||||
} from "@/pages/competence/utils";
|
} from "@/pages/competence/utils";
|
||||||
import ItProgress from "@/components/ui/ItProgress.vue";
|
import ItProgress from "@/components/ui/ItProgress.vue";
|
||||||
import { useCompetenceStore } from "@/stores/competence";
|
import { calcPerformanceCriteriaStatusCount } from "@/services/competence";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
|
|
@ -20,8 +20,7 @@ const props = defineProps<{
|
||||||
log.debug("CompetenceIndexPage setup", props);
|
log.debug("CompetenceIndexPage setup", props);
|
||||||
|
|
||||||
const courseSession = useCurrentCourseSession();
|
const courseSession = useCurrentCourseSession();
|
||||||
|
const courseData = useLearningPathWithCompletion(props.courseSlug);
|
||||||
const competenceStore = useCompetenceStore();
|
|
||||||
|
|
||||||
const certificatesQuery = useQuery({
|
const certificatesQuery = useQuery({
|
||||||
query: COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
query: COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
||||||
|
|
@ -51,7 +50,7 @@ const userPointsEvaluatedAssignments = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const performanceCriteriaStatusCount = computed(() => {
|
const performanceCriteriaStatusCount = computed(() => {
|
||||||
return competenceStore.calcStatusCount(competenceStore.flatPerformanceCriteria());
|
return calcPerformanceCriteriaStatusCount(courseData.flatPerformanceCriteria.value);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import type { PerformanceCriteria } from "@/types";
|
import type { PerformanceCriteria } from "@/types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
criteria: PerformanceCriteria;
|
criterion: PerformanceCriteria;
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
showState?: boolean;
|
showState?: boolean;
|
||||||
showAssessAgain?: boolean;
|
showAssessAgain?: boolean;
|
||||||
|
|
@ -19,24 +19,24 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
<div class="flex flex-row items-center">
|
<div class="flex flex-row items-center">
|
||||||
<div v-if="showState" class="mr-4 h-8 w-8">
|
<div v-if="showState" class="mr-4 h-8 w-8">
|
||||||
<it-icon-smiley-happy
|
<it-icon-smiley-happy
|
||||||
v-if="criteria.completion_status === 'SUCCESS'"
|
v-if="criterion.completion_status === 'SUCCESS'"
|
||||||
></it-icon-smiley-happy>
|
></it-icon-smiley-happy>
|
||||||
<it-icon-smiley-thinking
|
<it-icon-smiley-thinking
|
||||||
v-else-if="criteria.completion_status === 'FAIL'"
|
v-else-if="criterion.completion_status === 'FAIL'"
|
||||||
></it-icon-smiley-thinking>
|
></it-icon-smiley-thinking>
|
||||||
<it-icon-smiley-neutral v-else></it-icon-smiley-neutral>
|
<it-icon-smiley-neutral v-else></it-icon-smiley-neutral>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4 pr-4 lg:mb-0 lg:mr-8">
|
<div class="mb-4 pr-4 lg:mb-0 lg:mr-8">
|
||||||
{{ criteria.title }}
|
{{ criterion.title }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="lg:whitespace-nowrap">
|
<span class="lg:whitespace-nowrap">
|
||||||
<router-link
|
<router-link
|
||||||
v-if="props.showAssessAgain"
|
v-if="props.showAssessAgain && criterion.learning_unit?.evaluate_url"
|
||||||
class="link"
|
class="link"
|
||||||
:to="criteria.learning_unit.evaluate_url"
|
:to="criterion.learning_unit.evaluate_url"
|
||||||
>
|
>
|
||||||
{{ $t("competences.assessAgain", { x: criteria.circle.title }) }}
|
{{ $t("competences.assessAgain", { x: criterion.circle.title }) }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import type { PerformanceCriteria } from "@/types";
|
||||||
|
import groupBy from "lodash/groupBy";
|
||||||
|
|
||||||
|
export function calcPerformanceCriteriaStatusCount(criteria: PerformanceCriteria[]) {
|
||||||
|
if (criteria) {
|
||||||
|
const grouped = groupBy(criteria, "completion_status");
|
||||||
|
return {
|
||||||
|
UNKNOWN: grouped?.UNKNOWN?.length || 0,
|
||||||
|
SUCCESS: grouped?.SUCCESS?.length || 0,
|
||||||
|
FAIL: grouped?.FAIL?.length || 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
UNKNOWN: 0,
|
||||||
|
SUCCESS: 0,
|
||||||
|
FAIL: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import type {
|
import type {
|
||||||
|
ActionCompetenceObjectType,
|
||||||
|
AssignmentAssignmentAssignmentTypeChoices,
|
||||||
AssignmentCompletionObjectType,
|
AssignmentCompletionObjectType,
|
||||||
AssignmentCompletionStatus as AssignmentCompletionStatusGenerated,
|
AssignmentCompletionStatus as AssignmentCompletionStatusGenerated,
|
||||||
|
AssignmentObjectType,
|
||||||
CircleObjectType,
|
CircleObjectType,
|
||||||
CourseCourseSessionUserRoleChoices,
|
CourseCourseSessionUserRoleChoices,
|
||||||
CourseSessionObjectType,
|
CourseSessionObjectType,
|
||||||
|
|
@ -327,57 +330,31 @@ export interface AssignmentEvaluationTask {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AssignmentType =
|
export type AssignmentType = AssignmentAssignmentAssignmentTypeChoices;
|
||||||
| "CASEWORK"
|
|
||||||
| "PREP_ASSIGNMENT"
|
|
||||||
| "REFLECTION"
|
|
||||||
| "CONDITION_ACCEPTANCE"
|
|
||||||
| "EDONIQ_TEST";
|
|
||||||
|
|
||||||
export interface Assignment extends BaseCourseWagtailPage {
|
export type Assignment = Omit<
|
||||||
|
AssignmentObjectType,
|
||||||
|
"content_type" | "performance_objectives" | "tasks" | "evaluation_tasks"
|
||||||
|
> & {
|
||||||
readonly content_type: "assignment.Assignment";
|
readonly content_type: "assignment.Assignment";
|
||||||
readonly assignment_type: AssignmentType;
|
|
||||||
readonly needs_expert_evaluation: boolean;
|
|
||||||
readonly intro_text: string;
|
|
||||||
readonly effort_required: string;
|
|
||||||
readonly performance_objectives: AssignmentPerformanceObjective[];
|
readonly performance_objectives: AssignmentPerformanceObjective[];
|
||||||
readonly evaluation_description: string;
|
|
||||||
readonly evaluation_document_url: string;
|
|
||||||
readonly tasks: AssignmentTask[];
|
readonly tasks: AssignmentTask[];
|
||||||
readonly evaluation_tasks: AssignmentEvaluationTask[];
|
readonly evaluation_tasks: AssignmentEvaluationTask[];
|
||||||
readonly max_points: number;
|
|
||||||
readonly competence_certificate?: {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
slug: string;
|
|
||||||
content_type: string;
|
|
||||||
translation_key: string;
|
|
||||||
frontend_url: string;
|
|
||||||
} | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PerformanceCriteria extends BaseCourseWagtailPage {
|
|
||||||
readonly content_type: "competence.PerformanceCriteria";
|
|
||||||
readonly competence_id: string;
|
|
||||||
readonly circle: CircleLight;
|
|
||||||
readonly course_category: CourseCategory;
|
|
||||||
readonly learning_unit: BaseCourseWagtailPage & {
|
|
||||||
evaluate_url: string;
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export interface CompetencePage extends BaseCourseWagtailPage {
|
export type PerformanceCriteria = Omit<PerformanceCriteriaObjectType, "content_type"> &
|
||||||
readonly content_type: "competence.CompetencePage";
|
Completable & {
|
||||||
readonly competence_id: string;
|
readonly content_type: "competence.PerformanceCriteria";
|
||||||
readonly children: PerformanceCriteria[];
|
circle: CircleLight;
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface CompetenceProfilePage extends BaseCourseWagtailPage {
|
export type ActionCompetence = Omit<
|
||||||
readonly content_type: "competence.CompetenceProfilePage";
|
ActionCompetenceObjectType,
|
||||||
readonly course: Course;
|
"content_type" | "performance_criteria"
|
||||||
readonly circles: CircleLight[];
|
> & {
|
||||||
readonly children: CompetencePage[];
|
readonly content_type: "competence.ActionCompetence";
|
||||||
}
|
performance_criteria: PerformanceCriteria[];
|
||||||
|
};
|
||||||
|
|
||||||
export interface CompetenceCertificateAssignment extends BaseCourseWagtailPage {
|
export interface CompetenceCertificateAssignment extends BaseCourseWagtailPage {
|
||||||
assignment_type: "CASEWORK" | "EDONIQ_TEST";
|
assignment_type: "CASEWORK" | "EDONIQ_TEST";
|
||||||
|
|
@ -437,47 +414,6 @@ export interface CircleDocument {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// export interface CourseSessionAttendanceCourse {
|
|
||||||
// id: string;
|
|
||||||
// due_date: SimpleDueDate;
|
|
||||||
// location: string;
|
|
||||||
// trainer: string;
|
|
||||||
// circle_title: string;
|
|
||||||
// learning_content: {
|
|
||||||
// id: string;
|
|
||||||
// title: string;
|
|
||||||
// circle: CircleLight;
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// export interface CourseSessionAssignment {
|
|
||||||
// id: string;
|
|
||||||
// submission_deadline: SimpleDueDate;
|
|
||||||
// evaluation_deadline: SimpleDueDate;
|
|
||||||
// learning_content: {
|
|
||||||
// id: string;
|
|
||||||
// content_assignment: {
|
|
||||||
// id: string;
|
|
||||||
// title: string;
|
|
||||||
// assignment_type: AssignmentType;
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// export interface CourseSessionEdoniqTest {
|
|
||||||
// id: number;
|
|
||||||
// course_session_id: string;
|
|
||||||
// deadline: SimpleDueDate;
|
|
||||||
// learning_content: {
|
|
||||||
// id: string;
|
|
||||||
// content_assignment: {
|
|
||||||
// id: string;
|
|
||||||
// title: string;
|
|
||||||
// assignment_type: AssignmentType;
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
export interface CourseSession {
|
export interface CourseSession {
|
||||||
id: string;
|
id: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@ from vbv_lernwelt.competence.models import (
|
||||||
CompetenceCertificate,
|
CompetenceCertificate,
|
||||||
CompetenceCertificateList,
|
CompetenceCertificateList,
|
||||||
PerformanceCriteria,
|
PerformanceCriteria,
|
||||||
|
ActionCompetence,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
||||||
|
from vbv_lernwelt.learnpath.graphql.types import LearningUnitObjectType
|
||||||
|
|
||||||
|
|
||||||
class CompetenceCertificateObjectType(DjangoObjectType):
|
class CompetenceCertificateObjectType(DjangoObjectType):
|
||||||
|
|
@ -38,7 +40,26 @@ class CompetenceCertificateListObjectType(DjangoObjectType):
|
||||||
|
|
||||||
|
|
||||||
class PerformanceCriteriaObjectType(DjangoObjectType):
|
class PerformanceCriteriaObjectType(DjangoObjectType):
|
||||||
|
learning_unit = graphene.Field(LearningUnitObjectType)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PerformanceCriteria
|
model = PerformanceCriteria
|
||||||
interfaces = (CoursePageInterface,)
|
interfaces = (CoursePageInterface,)
|
||||||
fields = ["competence_id"]
|
fields = ["competence_id"]
|
||||||
|
|
||||||
|
def resolve_learning_unit(self: PerformanceCriteria, info):
|
||||||
|
return self.learning_unit
|
||||||
|
|
||||||
|
|
||||||
|
class ActionCompetenceObjectType(DjangoObjectType):
|
||||||
|
performance_criteria = graphene.List(
|
||||||
|
graphene.NonNull(PerformanceCriteriaObjectType), required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ActionCompetence
|
||||||
|
interfaces = (CoursePageInterface,)
|
||||||
|
fields = ["competence_id", "children"]
|
||||||
|
|
||||||
|
def resolve_performance_criteria(self, info):
|
||||||
|
return self.get_children().specific()
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,9 @@ class ActionCompetence(CourseBasePage):
|
||||||
use_json_field=True,
|
use_json_field=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_frontend_url(self):
|
||||||
|
return f""
|
||||||
|
|
||||||
content_panels = [
|
content_panels = [
|
||||||
FieldPanel("title"),
|
FieldPanel("title"),
|
||||||
FieldPanel("competence_id"),
|
FieldPanel("competence_id"),
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,92 @@
|
||||||
import graphene
|
import graphene
|
||||||
|
from django.db.models import Q
|
||||||
|
from graphql import GraphQLError
|
||||||
|
|
||||||
from vbv_lernwelt.course.graphql.types import CourseObjectType, CourseSessionObjectType
|
from vbv_lernwelt.course.graphql.types import CourseObjectType, CourseSessionObjectType
|
||||||
from vbv_lernwelt.course.models import Course, CourseSession
|
from vbv_lernwelt.course.models import Course, CourseSession
|
||||||
from vbv_lernwelt.course.permissions import has_course_access
|
from vbv_lernwelt.course.permissions import has_course_access
|
||||||
|
from vbv_lernwelt.learnpath.graphql.types import (
|
||||||
|
LearningContentMediaLibraryObjectType,
|
||||||
|
LearningContentAssignmentObjectType,
|
||||||
|
LearningContentAttendanceCourseObjectType,
|
||||||
|
LearningContentFeedbackObjectType,
|
||||||
|
LearningContentLearningModuleObjectType,
|
||||||
|
LearningContentPlaceholderObjectType,
|
||||||
|
LearningContentRichTextObjectType,
|
||||||
|
LearningContentEdoniqTestObjectType,
|
||||||
|
LearningContentVideoObjectType,
|
||||||
|
LearningContentDocumentListObjectType,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CourseQuery(graphene.ObjectType):
|
class CourseQuery(graphene.ObjectType):
|
||||||
course = graphene.Field(CourseObjectType, id=graphene.ID())
|
course = graphene.Field(
|
||||||
|
CourseObjectType,
|
||||||
|
id=graphene.ID(),
|
||||||
|
slug=graphene.String(),
|
||||||
|
)
|
||||||
course_session = graphene.Field(CourseSessionObjectType, id=graphene.ID())
|
course_session = graphene.Field(CourseSessionObjectType, id=graphene.ID())
|
||||||
|
|
||||||
def resolve_course(root, info, id):
|
def resolve_course(self, info, id=None, slug=None):
|
||||||
course = Course.objects.get(pk=id)
|
if id is None and slug is None:
|
||||||
|
raise GraphQLError("Either 'id', 'slug' must be provided.")
|
||||||
|
course = Course.objects.get(Q(id=id) | Q(slug=slug))
|
||||||
if has_course_access(info.context.user, course):
|
if has_course_access(info.context.user, course):
|
||||||
return course
|
return course
|
||||||
raise PermissionError("You do not have access to this course")
|
raise PermissionError("You do not have access to this course")
|
||||||
|
|
||||||
def resolve_course_session(root, info, id):
|
def resolve_course_session(self, info, id):
|
||||||
course_session = CourseSession.objects.get(pk=id)
|
course_session = CourseSession.objects.get(pk=id)
|
||||||
if has_course_access(info.context.user, course_session.course):
|
if has_course_access(info.context.user, course_session.course):
|
||||||
return course_session
|
return course_session
|
||||||
raise PermissionError("You do not have access to this course session")
|
raise PermissionError("You do not have access to this course session")
|
||||||
|
|
||||||
|
# dummy import, so that graphene recognizes the types
|
||||||
|
learning_content_media_library = graphene.Field(
|
||||||
|
LearningContentMediaLibraryObjectType
|
||||||
|
)
|
||||||
|
learning_content_assignment = graphene.Field(LearningContentAssignmentObjectType)
|
||||||
|
learning_content_attendance_course = graphene.Field(
|
||||||
|
LearningContentAttendanceCourseObjectType
|
||||||
|
)
|
||||||
|
learning_content_feedback = graphene.Field(LearningContentFeedbackObjectType)
|
||||||
|
learning_content_learning_module = graphene.Field(
|
||||||
|
LearningContentLearningModuleObjectType
|
||||||
|
)
|
||||||
|
learning_content_placeholder = graphene.Field(LearningContentPlaceholderObjectType)
|
||||||
|
learning_content_rich_text = graphene.Field(LearningContentRichTextObjectType)
|
||||||
|
learning_content_test = graphene.Field(LearningContentEdoniqTestObjectType)
|
||||||
|
learning_content_video = graphene.Field(LearningContentVideoObjectType)
|
||||||
|
learning_content_document_list = graphene.Field(
|
||||||
|
LearningContentDocumentListObjectType
|
||||||
|
)
|
||||||
|
|
||||||
|
def resolve_learning_content_media_library(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_assignment(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_attendance_course(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_feedback(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_learning_module(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_placeholder(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_rich_text(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_test(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_video(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_document_list(self, info):
|
||||||
|
return None
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ from graphene_django import DjangoObjectType
|
||||||
from graphql import GraphQLError
|
from graphql import GraphQLError
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
|
|
||||||
|
from vbv_lernwelt.competence.graphql.types import ActionCompetenceObjectType
|
||||||
from vbv_lernwelt.course.models import (
|
from vbv_lernwelt.course.models import (
|
||||||
CircleDocument,
|
CircleDocument,
|
||||||
Course,
|
Course,
|
||||||
|
|
@ -26,6 +27,7 @@ from vbv_lernwelt.course_session.models import (
|
||||||
CourseSessionAttendanceCourse,
|
CourseSessionAttendanceCourse,
|
||||||
CourseSessionEdoniqTest,
|
CourseSessionEdoniqTest,
|
||||||
)
|
)
|
||||||
|
from vbv_lernwelt.learnpath.graphql.types import LearningPathObjectType
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
@ -83,10 +85,23 @@ def resolve_course_page(
|
||||||
|
|
||||||
|
|
||||||
class CourseObjectType(DjangoObjectType):
|
class CourseObjectType(DjangoObjectType):
|
||||||
|
learning_path = graphene.Field(LearningPathObjectType, required=True)
|
||||||
|
action_competences = graphene.List(
|
||||||
|
graphene.NonNull(ActionCompetenceObjectType), required=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Course
|
model = Course
|
||||||
fields = ("id", "title", "category_name", "slug")
|
fields = ("id", "title", "category_name", "slug")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_learning_path(root: Course, info):
|
||||||
|
return root.get_learning_path()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_action_competences(root: Course, info):
|
||||||
|
return root.get_action_competences()
|
||||||
|
|
||||||
|
|
||||||
class CourseSessionUserExpertCircleType(ObjectType):
|
class CourseSessionUserExpertCircleType(ObjectType):
|
||||||
id = graphene.ID(required=True)
|
id = graphene.ID(required=True)
|
||||||
|
|
|
||||||
|
|
@ -32,21 +32,10 @@ class Course(models.Model):
|
||||||
|
|
||||||
return self.coursepage.get_children().exact_type(LearningPath).first().specific
|
return self.coursepage.get_children().exact_type(LearningPath).first().specific
|
||||||
|
|
||||||
def get_learning_path_url(self):
|
def get_action_competences(self):
|
||||||
return self.get_learning_path().get_frontend_url()
|
from vbv_lernwelt.competence.models import ActionCompetence
|
||||||
|
|
||||||
def get_cockpit_url(self):
|
return self.coursepage.get_descendants().exact_type(ActionCompetence).specific()
|
||||||
return self.get_learning_path().get_cockpit_url()
|
|
||||||
|
|
||||||
def get_competence_url(self):
|
|
||||||
from vbv_lernwelt.competence.models import ActionCompetenceListPage
|
|
||||||
|
|
||||||
competence_page = (
|
|
||||||
self.coursepage.get_descendants()
|
|
||||||
.exact_type(ActionCompetenceListPage)
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
return competence_page.specific.get_frontend_url()
|
|
||||||
|
|
||||||
def get_media_library_url(self):
|
def get_media_library_url(self):
|
||||||
from vbv_lernwelt.media_library.models import MediaLibraryPage
|
from vbv_lernwelt.media_library.models import MediaLibraryPage
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,6 @@ import graphene
|
||||||
|
|
||||||
from vbv_lernwelt.course.graphql.types import resolve_course_page
|
from vbv_lernwelt.course.graphql.types import resolve_course_page
|
||||||
from vbv_lernwelt.learnpath.graphql.types import (
|
from vbv_lernwelt.learnpath.graphql.types import (
|
||||||
LearningContentAssignmentObjectType,
|
|
||||||
LearningContentAttendanceCourseObjectType,
|
|
||||||
LearningContentDocumentListObjectType,
|
|
||||||
LearningContentEdoniqTestObjectType,
|
|
||||||
LearningContentFeedbackObjectType,
|
|
||||||
LearningContentLearningModuleObjectType,
|
|
||||||
LearningContentMediaLibraryObjectType,
|
|
||||||
LearningContentPlaceholderObjectType,
|
|
||||||
LearningContentRichTextObjectType,
|
|
||||||
LearningContentVideoObjectType,
|
|
||||||
LearningPathObjectType,
|
LearningPathObjectType,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.learnpath.models import LearningPath
|
from vbv_lernwelt.learnpath.models import LearningPath
|
||||||
|
|
@ -38,53 +28,3 @@ class LearningPathQuery:
|
||||||
course_id=course_id,
|
course_id=course_id,
|
||||||
course_slug=course_slug,
|
course_slug=course_slug,
|
||||||
)
|
)
|
||||||
|
|
||||||
# dummy import, so that graphene recognizes the types
|
|
||||||
learning_content_media_library = graphene.Field(
|
|
||||||
LearningContentMediaLibraryObjectType
|
|
||||||
)
|
|
||||||
learning_content_assignment = graphene.Field(LearningContentAssignmentObjectType)
|
|
||||||
learning_content_attendance_course = graphene.Field(
|
|
||||||
LearningContentAttendanceCourseObjectType
|
|
||||||
)
|
|
||||||
learning_content_feedback = graphene.Field(LearningContentFeedbackObjectType)
|
|
||||||
learning_content_learning_module = graphene.Field(
|
|
||||||
LearningContentLearningModuleObjectType
|
|
||||||
)
|
|
||||||
learning_content_placeholder = graphene.Field(LearningContentPlaceholderObjectType)
|
|
||||||
learning_content_rich_text = graphene.Field(LearningContentRichTextObjectType)
|
|
||||||
learning_content_test = graphene.Field(LearningContentEdoniqTestObjectType)
|
|
||||||
learning_content_video = graphene.Field(LearningContentVideoObjectType)
|
|
||||||
learning_content_document_list = graphene.Field(
|
|
||||||
LearningContentDocumentListObjectType
|
|
||||||
)
|
|
||||||
|
|
||||||
def resolve_learning_content_media_library(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_assignment(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_attendance_course(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_feedback(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_learning_module(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_placeholder(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_rich_text(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_test(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_video(self, info):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resolve_learning_content_document_list(self, info):
|
|
||||||
return None
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue