diff --git a/client/package-lock.json b/client/package-lock.json
index 5ce4098f..a46c22ae 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -10,6 +10,7 @@
"dependencies": {
"@headlessui/tailwindcss": "^0.2.1",
"@headlessui/vue": "^1.7.22",
+ "@parcel/watcher": "^2.4.1",
"@sentry/tracing": "^7.114.0",
"@sentry/vue": "^8.17.0",
"@urql/exchange-graphcache": "^7.1.2",
@@ -5722,7 +5723,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
@@ -8258,7 +8258,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -9317,7 +9316,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -9334,7 +9332,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -9388,7 +9385,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
"engines": {
"node": ">=0.12.0"
}
@@ -10334,7 +10330,6 @@
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
"dependencies": {
"braces": "^3.0.2",
"picomatch": "^2.3.1"
@@ -11072,7 +11067,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
"engines": {
"node": ">=8.6"
},
@@ -12672,7 +12666,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
@@ -18806,7 +18799,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
"requires": {
"fill-range": "^7.0.1"
}
@@ -20667,7 +20659,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
@@ -21425,8 +21416,7 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
},
"is-fullwidth-code-point": {
"version": "3.0.0",
@@ -21437,7 +21427,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
@@ -21475,8 +21464,7 @@
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"is-number-object": {
"version": "1.0.7",
@@ -22174,7 +22162,6 @@
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
"requires": {
"braces": "^3.0.2",
"picomatch": "^2.3.1"
@@ -22727,8 +22714,7 @@
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
},
"pify": {
"version": "2.3.0",
@@ -23824,7 +23810,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"requires": {
"is-number": "^7.0.0"
}
diff --git a/client/package.json b/client/package.json
index d8bc6fb9..f5296e99 100644
--- a/client/package.json
+++ b/client/package.json
@@ -10,8 +10,9 @@
"cypress:open": "cypress open",
"dev": "concurrently \"vite\" \"npm run codegen:watch\"",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
+ "lint:errors": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --quiet --ignore-path .gitignore",
"prettier": "prettier . --write",
- "prettier:check": "prettier . --check",
+ "prettier:check": "prettier . --check --ignore-unknown",
"tailwind": "tailwindcss -i tailwind.css -o ../server/vbv_lernwelt/static/css/tailwind.css --watch",
"test": "vitest run",
"typecheck": "npm run codegen && vue-tsc --noEmit -p tsconfig.app.json --composite false",
@@ -20,6 +21,7 @@
"dependencies": {
"@headlessui/tailwindcss": "^0.2.1",
"@headlessui/vue": "^1.7.22",
+ "@parcel/watcher": "^2.4.1",
"@sentry/tracing": "^7.114.0",
"@sentry/vue": "^8.17.0",
"@urql/exchange-graphcache": "^7.1.2",
diff --git a/client/src/components/header/MainNavigationBar.vue b/client/src/components/header/MainNavigationBar.vue
index f7efdce5..14cb45ca 100644
--- a/client/src/components/header/MainNavigationBar.vue
+++ b/client/src/components/header/MainNavigationBar.vue
@@ -342,7 +342,7 @@ const hasSessionTitle = computed(() => {
v-if="hasSessionTitle"
class="nav-item hidden items-center lg:inline-flex"
>
-
+
{{ selectedCourseSessionTitle }}
diff --git a/client/src/components/learningPath/LearningPathDiagram.vue b/client/src/components/learningPath/LearningPathDiagram.vue
index e91aae0c..f3129073 100644
--- a/client/src/components/learningPath/LearningPathDiagram.vue
+++ b/client/src/components/learningPath/LearningPathDiagram.vue
@@ -1,6 +1,10 @@
@@ -66,7 +74,7 @@ const { inProgressCirclesCount, circlesCount } = useCourseCircleProgress(
diff --git a/client/src/components/onboarding/WizardPage.vue b/client/src/components/onboarding/WizardPage.vue
index 570081c0..cbafd525 100644
--- a/client/src/components/onboarding/WizardPage.vue
+++ b/client/src/components/onboarding/WizardPage.vue
@@ -1,15 +1,27 @@
-
+
diff --git a/client/src/components/ui/ItDropdownSelect.vue b/client/src/components/ui/ItDropdownSelect.vue
index 8a9c3139..b1cb47df 100644
--- a/client/src/components/ui/ItDropdownSelect.vue
+++ b/client/src/components/ui/ItDropdownSelect.vue
@@ -5,17 +5,14 @@ import { computed } from "vue"; // https://stackoverflow.com/questions/64775876/
// https://stackoverflow.com/questions/64775876/vue-3-pass-reactive-object-to-component-with-two-way-binding
interface Props {
- modelValue?: {
- id: string | number;
- name: string;
- };
+ modelValue?: DropdownSelectable;
items?: DropdownSelectable[];
borderless?: boolean;
placeholderText?: string | null;
}
const emit = defineEmits<{
- (e: "update:modelValue", data: object): void;
+ (e: "update:modelValue", data: DropdownSelectable): void;
}>();
const props = withDefaults(defineProps
(), {
diff --git a/client/src/composables.ts b/client/src/composables.ts
index 753966ef..6ba8621c 100644
--- a/client/src/composables.ts
+++ b/client/src/composables.ts
@@ -1,33 +1,30 @@
-import { useCSRFFetch } from "@/fetchHelpers";
-import type { CourseStatisticsType } from "@/gql/graphql";
-import { graphqlClient } from "@/graphql/client";
-import { COURSE_QUERY, COURSE_SESSION_DETAIL_QUERY } from "@/graphql/queries";
+import {useCSRFFetch} from "@/fetchHelpers";
+import type {CourseStatisticsType} from "@/gql/graphql";
+import {graphqlClient} from "@/graphql/client";
+import {COURSE_QUERY, COURSE_SESSION_DETAIL_QUERY} from "@/graphql/queries";
import {
circleFlatChildren,
circleFlatLearningContents,
circleFlatLearningUnits,
someFinishedInLearningSequence,
} from "@/services/circle";
-import type {
- DashboardDueDate,
- DashboardPersonRoleType,
- DashboardPersonType,
-} from "@/services/dashboard";
+import type {DashboardDueDate, DashboardPersonRoleType, DashboardPersonType,} from "@/services/dashboard";
import {
courseIdForCourseSlug,
fetchDashboardDueDates,
fetchDashboardPersons,
fetchStatisticData,
} from "@/services/dashboard";
-import { presignUpload, uploadFile } from "@/services/files";
-import { useCompletionStore } from "@/stores/completion";
-import { useCourseSessionsStore } from "@/stores/courseSessions";
-import { useDashboardStore } from "@/stores/dashboard";
-import { useUserStore } from "@/stores/user";
+import {presignUpload, uploadFile} from "@/services/files";
+import {useCompletionStore} from "@/stores/completion";
+import {useCourseSessionsStore} from "@/stores/courseSessions";
+import {useDashboardStore} from "@/stores/dashboard";
+import {useUserStore} from "@/stores/user";
import type {
ActionCompetence,
AgentParticipantRelation,
CircleType,
+ CompetenceCertificate,
Course,
CourseCompletion,
CourseCompletionStatus,
@@ -39,14 +36,16 @@ import type {
LearningUnitPerformanceCriteria,
PerformanceCriteria,
} from "@/types";
-import { useQuery } from "@urql/vue";
+import {useQuery} from "@urql/vue";
import dayjs from "dayjs";
-import { t } from "i18next";
+import {t} from "i18next";
import orderBy from "lodash/orderBy";
import log from "loglevel";
-import type { ComputedRef, Ref } from "vue";
-import { computed, onMounted, ref, watchEffect } from "vue";
-import { type RouteLocationRaw, useRouter } from "vue-router";
+import type {ComputedRef, Ref} from "vue";
+import {computed, onMounted, ref, watchEffect} from "vue";
+import {type RouteLocationRaw, useRouter} from "vue-router";
+import {getCertificates} from "./services/competence";
+import {mergeCompetenceCertificates} from "./pages/competence/utils";
export function useCurrentCourseSession() {
/**
@@ -178,7 +177,7 @@ export function useCourseData(courseSlug: string) {
// urql.useQuery is not meant to be used programmatically, so we use graphqlClient.query instead
const resultPromise = graphqlClient
- .query(COURSE_QUERY, { slug: `${courseSlug}` })
+ .query(COURSE_QUERY, {slug: `${courseSlug}`})
.toPromise();
resultPromise.then((result) => {
@@ -443,7 +442,7 @@ export function useFileUpload() {
const fileInfo = ref({} as { id: string; name: string; url: string });
async function upload(e: Event) {
- const { files } = e.target as HTMLInputElement;
+ const {files} = e.target as HTMLInputElement;
if (!files?.length) return;
try {
@@ -461,7 +460,7 @@ export function useFileUpload() {
}
}
- return { upload, error, loading, fileInfo };
+ return {upload, error, loading, fileInfo};
}
export function useMyLearningMentors() {
@@ -471,7 +470,7 @@ export function useMyLearningMentors() {
const fetchMentors = async () => {
loading.value = true;
- const { data } = await useCSRFFetch(
+ const {data} = await useCSRFFetch(
`/api/mentor/${currentCourseSessionId}/mentors`
).json();
learningMentors.value = data.value;
@@ -623,7 +622,7 @@ export function useCourseCircleProgress(circles: Ref)
return circles.value?.length ?? 0;
});
- return { inProgressCirclesCount, circlesCount };
+ return {inProgressCirclesCount, circlesCount};
}
export function useCourseStatisticsv2(courseSlug: string) {
@@ -669,6 +668,25 @@ export function useCourseStatisticsv2(courseSlug: string) {
};
}
+export function useCertificateQuery(
+ userIds: string[] | undefined,
+ courseSlug: string,
+ courseSession: CourseSession
+) {
+ const certificatesQuery = (() => {
+ return useQuery({
+ query: COMPETENCE_NAVI_CERTIFICATE_QUERY,
+ variables: {
+ courseSlug: courseSlug,
+ courseSessionId: courseSession.id,
+ userIds,
+ },
+ });
+ })();
+
+ return {certificatesQuery};
+}
+
export function useEvaluationWithFeedback() {
const currentCourseSession = useCurrentCourseSession();
const hasFeedback = computed(
@@ -677,7 +695,7 @@ export function useEvaluationWithFeedback() {
currentCourseSession.value.course.configuration.is_vv
);
- return { hasFeedback };
+ return {hasFeedback};
}
export function useVVByLink() {
@@ -687,9 +705,36 @@ export function useVVByLink() {
() =>
router.resolve({
name: "accountConfirm",
- params: { courseType: `vv-${userStore.language}` },
+ params: {courseType: `vv-${userStore.language}`},
}).href as RouteLocationRaw
);
- return { href };
+ return {href};
+}
+
+export function useAllCompetenceCertificates(
+ userId: string | undefined,
+ courseSlug: string
+) {
+ const courseSessionsStore = useCourseSessionsStore();
+ const certificateQueries = courseSessionsStore.allCourseSessions.map(
+ (courseSession) => {
+ return useCertificateQuery([userId], courseSlug, courseSession).certificatesQuery;
+ }
+ );
+
+ const competenceCertificatesPerCs = computed(() =>
+ certificateQueries.map((query) => {
+ return getCertificates(query.data.value, userId ?? null)
+ ?.competence_certificates as unknown as CompetenceCertificate[];
+ })
+ );
+ const isLoaded = computed(() => !certificateQueries.some((q) => q.fetching.value));
+ const competenceCertificates = computed(() =>
+ mergeCompetenceCertificates(competenceCertificatesPerCs.value.flat())
+ );
+ return {
+ competenceCertificates,
+ isLoaded,
+ };
}
diff --git a/client/src/constants.ts b/client/src/constants.ts
index 84aaefc3..57c51683 100644
--- a/client/src/constants.ts
+++ b/client/src/constants.ts
@@ -3,3 +3,5 @@ export const itCheckboxDefaultIconCheckedTailwindClass =
export const itCheckboxDefaultIconUncheckedTailwindClass =
"bg-[url(/static/icons/icon-checkbox-unchecked.svg)] hover:bg-[url(/static/icons/icon-checkbox-unchecked-hover.svg)]";
+
+export const COURSE_PROFILE_ALL_FILTER = "all";
diff --git a/client/src/gql/gql.ts b/client/src/gql/gql.ts
index d59098d5..4a360391 100644
--- a/client/src/gql/gql.ts
+++ b/client/src/gql/gql.ts
@@ -15,12 +15,14 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-
const documents = {
"\n mutation AttendanceCheckMutation(\n $attendanceCourseId: ID!\n $attendanceUserList: [AttendanceUserInputType]!\n ) {\n update_course_session_attendance_course_users(\n id: $attendanceCourseId\n attendance_user_list: $attendanceUserList\n ) {\n course_session_attendance_course {\n id\n attendance_user_list {\n user_id\n first_name\n last_name\n email\n status\n }\n }\n }\n }\n": types.AttendanceCheckMutationDocument,
"\n mutation UpsertAssignmentCompletion(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n $completionStatus: AssignmentCompletionStatus!\n $completionDataString: String!\n $evaluationPoints: Float\n $initializeCompletion: Boolean\n $evaluationUserId: ID\n ) {\n upsert_assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n assignment_user_id: $assignmentUserId\n completion_status: $completionStatus\n completion_data_string: $completionDataString\n evaluation_points: $evaluationPoints\n initialize_completion: $initializeCompletion\n evaluation_user_id: $evaluationUserId\n ) {\n assignment_completion {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_points\n completion_data\n task_completion_data\n }\n }\n }\n": types.UpsertAssignmentCompletionDocument,
+ "\n mutation UpdateCourseSessionProfile($input: CourseSessionProfileMutationInput!) {\n update_course_session_profile(input: $input) {\n clientMutationId\n result {\n __typename\n ... on UpdateCourseProfileSuccess {\n user {\n id\n chosen_profile\n }\n }\n ... on UpdateCourseProfileError {\n message\n }\n }\n }\n }\n": types.UpdateCourseSessionProfileDocument,
"\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 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 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 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 competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_deducted\n evaluation_points_final\n evaluation_max_points\n evaluation_passed\n course_session {\n id\n title\n }\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 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 course_session {\n id\n title\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 optional_attendance\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!, $user: String) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n profiles\n course_session_users(id: $user) {\n id\n __typename\n chosen_profile\n course_session {\n id\n }\n }\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n is_uk\n is_vv\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 profiles\n is_base_circle\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 dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n": types.DashboardProgressDocument,
"\n query dashboardCourseData($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n }\n }\n": types.DashboardCourseDataDocument,
@@ -51,6 +53,10 @@ export function graphql(source: "\n mutation AttendanceCheckMutation(\n $att
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation UpsertAssignmentCompletion(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n $completionStatus: AssignmentCompletionStatus!\n $completionDataString: String!\n $evaluationPoints: Float\n $initializeCompletion: Boolean\n $evaluationUserId: ID\n ) {\n upsert_assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n assignment_user_id: $assignmentUserId\n completion_status: $completionStatus\n completion_data_string: $completionDataString\n evaluation_points: $evaluationPoints\n initialize_completion: $initializeCompletion\n evaluation_user_id: $evaluationUserId\n ) {\n assignment_completion {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_points\n completion_data\n task_completion_data\n }\n }\n }\n"): (typeof documents)["\n mutation UpsertAssignmentCompletion(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n $completionStatus: AssignmentCompletionStatus!\n $completionDataString: String!\n $evaluationPoints: Float\n $initializeCompletion: Boolean\n $evaluationUserId: ID\n ) {\n upsert_assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n assignment_user_id: $assignmentUserId\n completion_status: $completionStatus\n completion_data_string: $completionDataString\n evaluation_points: $evaluationPoints\n initialize_completion: $initializeCompletion\n evaluation_user_id: $evaluationUserId\n ) {\n assignment_completion {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_points\n completion_data\n task_completion_data\n }\n }\n }\n"];
+/**
+ * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
+ */
+export function graphql(source: "\n mutation UpdateCourseSessionProfile($input: CourseSessionProfileMutationInput!) {\n update_course_session_profile(input: $input) {\n clientMutationId\n result {\n __typename\n ... on UpdateCourseProfileSuccess {\n user {\n id\n chosen_profile\n }\n }\n ... on UpdateCourseProfileError {\n message\n }\n }\n }\n }\n"): (typeof documents)["\n mutation UpdateCourseSessionProfile($input: CourseSessionProfileMutationInput!) {\n update_course_session_profile(input: $input) {\n clientMutationId\n result {\n __typename\n ... on UpdateCourseProfileSuccess {\n user {\n id\n chosen_profile\n }\n }\n ... on UpdateCourseProfileError {\n message\n }\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -66,7 +72,11 @@ 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.
*/
-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"];
+export function graphql(source: "\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 competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_deducted\n evaluation_points_final\n evaluation_max_points\n evaluation_passed\n course_session {\n id\n title\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 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 competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_deducted\n evaluation_points_final\n evaluation_max_points\n evaluation_passed\n course_session {\n id\n title\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.
+ */
+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 course_session {\n id\n title\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 course_session {\n id\n title\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.
*/
@@ -74,7 +84,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.
*/
-export function graphql(source: "\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"): (typeof documents)["\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"];
+export function graphql(source: "\n query courseQuery($slug: String!, $user: String) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n profiles\n course_session_users(id: $user) {\n id\n __typename\n chosen_profile\n course_session {\n id\n }\n }\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n is_uk\n is_vv\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 profiles\n is_base_circle\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"): (typeof documents)["\n query courseQuery($slug: String!, $user: String) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n profiles\n course_session_users(id: $user) {\n id\n __typename\n chosen_profile\n course_session {\n id\n }\n }\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n is_uk\n is_vv\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 profiles\n is_base_circle\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"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
diff --git a/client/src/gql/graphql.ts b/client/src/gql/graphql.ts
index f60bb9a4..ee1d1a2d 100644
--- a/client/src/gql/graphql.ts
+++ b/client/src/gql/graphql.ts
@@ -278,8 +278,10 @@ export type CircleObjectType = CoursePageInterface & {
frontend_url: Scalars['String']['output'];
goals: Scalars['String']['output'];
id: Scalars['ID']['output'];
+ is_base_circle: Scalars['Boolean']['output'];
learning_sequences: Array;
live: Scalars['Boolean']['output'];
+ profiles: Array>;
slug: Scalars['String']['output'];
title: Scalars['String']['output'];
translation_key: Scalars['String']['output'];
@@ -372,12 +374,19 @@ export type CourseObjectType = {
action_competences: Array;
category_name: Scalars['String']['output'];
configuration: CourseConfigurationObjectType;
+ course_session_users: Array>;
id: Scalars['ID']['output'];
learning_path: LearningPathObjectType;
+ profiles?: Maybe>>;
slug: Scalars['String']['output'];
title: Scalars['String']['output'];
};
+
+export type CourseObjectTypeCourseSessionUsersArgs = {
+ id?: InputMaybe;
+};
+
export type CoursePageInterface = {
content_type: Scalars['String']['output'];
course?: Maybe;
@@ -444,6 +453,18 @@ export type CourseSessionObjectType = {
users: Array;
};
+export type CourseSessionProfileMutationInput = {
+ clientMutationId?: InputMaybe;
+ course_profile: Scalars['String']['input'];
+ course_slug: Scalars['String']['input'];
+};
+
+export type CourseSessionProfileMutationPayload = {
+ __typename?: 'CourseSessionProfileMutationPayload';
+ clientMutationId?: Maybe;
+ result?: Maybe;
+};
+
export type CourseSessionUserExpertCircleType = {
__typename?: 'CourseSessionUserExpertCircleType';
id: Scalars['ID']['output'];
@@ -471,6 +492,13 @@ export type CourseSessionUserObjectsType = {
user_id: Scalars['UUID']['output'];
};
+export type CourseSessionUserType = {
+ __typename?: 'CourseSessionUserType';
+ chosen_profile: Scalars['String']['output'];
+ course_session: CourseSessionObjectType;
+ id: Scalars['UUID']['output'];
+};
+
export type CourseStatisticsType = {
__typename?: 'CourseStatisticsType';
_id: Scalars['ID']['output'];
@@ -856,6 +884,7 @@ export type Mutation = {
__typename?: 'Mutation';
send_feedback?: Maybe;
update_course_session_attendance_course_users?: Maybe;
+ update_course_session_profile?: Maybe;
upsert_assignment_completion?: Maybe;
};
@@ -875,6 +904,11 @@ export type MutationUpdateCourseSessionAttendanceCourseUsersArgs = {
};
+export type MutationUpdateCourseSessionProfileArgs = {
+ input: CourseSessionProfileMutationInput;
+};
+
+
export type MutationUpsertAssignmentCompletionArgs = {
assignment_id: Scalars['ID']['input'];
assignment_user_id?: InputMaybe;
@@ -1079,6 +1113,18 @@ export type TopicObjectType = CoursePageInterface & {
translation_key: Scalars['String']['output'];
};
+export type UpdateCourseProfileError = {
+ __typename?: 'UpdateCourseProfileError';
+ message?: Maybe;
+};
+
+export type UpdateCourseProfileResult = UpdateCourseProfileError | UpdateCourseProfileSuccess;
+
+export type UpdateCourseProfileSuccess = {
+ __typename?: 'UpdateCourseProfileSuccess';
+ user: CourseSessionUserType;
+};
+
export type UserObjectType = {
__typename?: 'UserObjectType';
avatar_url?: Maybe;
@@ -1114,6 +1160,13 @@ export type UpsertAssignmentCompletionMutationVariables = Exact<{
export type UpsertAssignmentCompletionMutation = { __typename?: 'Mutation', upsert_assignment_completion?: { __typename?: 'AssignmentCompletionMutation', assignment_completion?: { __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: string | null, evaluation_submitted_at?: string | null, evaluation_points?: number | null, completion_data?: any | null, task_completion_data?: any | null } | null } | null };
+export type UpdateCourseSessionProfileMutationVariables = Exact<{
+ input: CourseSessionProfileMutationInput;
+}>;
+
+
+export type UpdateCourseSessionProfileMutation = { __typename?: 'Mutation', update_course_session_profile?: { __typename?: 'CourseSessionProfileMutationPayload', clientMutationId?: string | null, result?: { __typename: 'UpdateCourseProfileError', message?: string | null } | { __typename: 'UpdateCourseProfileSuccess', user: { __typename?: 'CourseSessionUserType', id: string, chosen_profile: string } } | null } | null };
+
type CoursePageFieldsActionCompetenceObjectTypeFragment = { __typename?: 'ActionCompetenceObjectType', title: string, id: string, slug: string, content_type: string, frontend_url: string } & { ' $fragmentName'?: 'CoursePageFieldsActionCompetenceObjectTypeFragment' };
type CoursePageFieldsAssignmentObjectTypeFragment = { __typename?: 'AssignmentObjectType', title: string, id: string, slug: string, content_type: string, frontend_url: string } & { ' $fragmentName'?: 'CoursePageFieldsAssignmentObjectTypeFragment' };
@@ -1180,6 +1233,59 @@ export type AssignmentCompletionQueryQuery = { __typename?: 'Query', assignment?
& { ' $fragmentRefs'?: { 'CoursePageFieldsCompetenceCertificateObjectTypeFragment': CoursePageFieldsCompetenceCertificateObjectTypeFragment } }
) | null } | null, assignment_completion?: { __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: string | null, evaluation_submitted_at?: string | null, evaluation_points?: number | null, evaluation_max_points?: number | null, evaluation_points_deducted: number, evaluation_points_deducted_reason: string, evaluation_points_final?: number | null, evaluation_passed?: boolean | null, edoniq_extended_time_flag: boolean, completion_data?: any | null, task_completion_data?: any | null, evaluation_user?: { __typename?: 'UserObjectType', id: string, first_name: string, last_name: string } | null, assignment_user: { __typename?: 'UserObjectType', avatar_url?: string | null, first_name: string, last_name: string, id: string } } | null };
+export type CompetenceCertificateQueryQueryVariables = Exact<{
+ courseSlug: Scalars['String']['input'];
+ courseSessionId: Scalars['ID']['input'];
+}>;
+
+
+export type CompetenceCertificateQueryQuery = { __typename?: 'Query', competence_certificate_list?: (
+ { __typename?: 'CompetenceCertificateListObjectType', competence_certificates: Array<(
+ { __typename?: 'CompetenceCertificateObjectType', assignments: Array<(
+ { __typename?: 'AssignmentObjectType', assignment_type: AssignmentAssignmentAssignmentTypeChoices, max_points?: number | null, competence_certificate_weight?: number | null, completions?: Array<{ __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: string | null, evaluation_points?: number | null, evaluation_points_deducted: number, evaluation_points_final?: number | null, evaluation_max_points?: number | null, evaluation_passed?: boolean | null, course_session: { __typename?: 'CourseSessionObjectType', id: string, title: string } } | null> | null, learning_content?: (
+ { __typename?: 'LearningContentAssignmentObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentAssignmentObjectTypeFragment': CoursePageFieldsLearningContentAssignmentObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentAttendanceCourseObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentAttendanceCourseObjectTypeFragment': CoursePageFieldsLearningContentAttendanceCourseObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentDocumentListObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentDocumentListObjectTypeFragment': CoursePageFieldsLearningContentDocumentListObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentEdoniqTestObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentEdoniqTestObjectTypeFragment': CoursePageFieldsLearningContentEdoniqTestObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentFeedbackUKObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentFeedbackUkObjectTypeFragment': CoursePageFieldsLearningContentFeedbackUkObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentFeedbackVVObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentFeedbackVvObjectTypeFragment': CoursePageFieldsLearningContentFeedbackVvObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentKnowledgeAssessmentObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment': CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentLearningModuleObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentLearningModuleObjectTypeFragment': CoursePageFieldsLearningContentLearningModuleObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentMediaLibraryObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentMediaLibraryObjectTypeFragment': CoursePageFieldsLearningContentMediaLibraryObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentPlaceholderObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentPlaceholderObjectTypeFragment': CoursePageFieldsLearningContentPlaceholderObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentRichTextObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentRichTextObjectTypeFragment': CoursePageFieldsLearningContentRichTextObjectTypeFragment } }
+ ) | (
+ { __typename?: 'LearningContentVideoObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentVideoObjectTypeFragment': CoursePageFieldsLearningContentVideoObjectTypeFragment } }
+ ) | null }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsAssignmentObjectTypeFragment': CoursePageFieldsAssignmentObjectTypeFragment } }
+ )> }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsCompetenceCertificateObjectTypeFragment': CoursePageFieldsCompetenceCertificateObjectTypeFragment } }
+ )> }
+ & { ' $fragmentRefs'?: { 'CoursePageFieldsCompetenceCertificateListObjectTypeFragment': CoursePageFieldsCompetenceCertificateListObjectTypeFragment } }
+ ) | null };
+
export type CompetenceCertificateForUserQueryQueryVariables = Exact<{
courseSlug: Scalars['String']['input'];
courseSessionId: Scalars['ID']['input'];
@@ -1190,7 +1296,7 @@ export type CompetenceCertificateForUserQueryQueryVariables = Exact<{
export type CompetenceCertificateForUserQueryQuery = { __typename?: 'Query', competence_certificate_list?: (
{ __typename?: 'CompetenceCertificateListObjectType', competence_certificates: Array<(
{ __typename?: 'CompetenceCertificateObjectType', assignments: Array<(
- { __typename?: 'AssignmentObjectType', assignment_type: AssignmentAssignmentAssignmentTypeChoices, max_points?: number | null, competence_certificate_weight?: number | null, completions?: Array<{ __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: string | null, evaluation_points?: number | null, evaluation_points_final?: number | null, evaluation_points_deducted: number, evaluation_max_points?: number | null, evaluation_passed?: boolean | null, evaluation_percent?: number | null, assignment_user: { __typename?: 'UserObjectType', id: string } } | null> | null, learning_content?: (
+ { __typename?: 'AssignmentObjectType', assignment_type: AssignmentAssignmentAssignmentTypeChoices, max_points?: number | null, competence_certificate_weight?: number | null, completions?: Array<{ __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: string | null, evaluation_points?: number | null, evaluation_points_final?: number | null, evaluation_points_deducted: number, evaluation_max_points?: number | null, evaluation_passed?: boolean | null, evaluation_percent?: number | null, assignment_user: { __typename?: 'UserObjectType', id: string }, course_session: { __typename?: 'CourseSessionObjectType', id: string, title: string } } | null> | null, learning_content?: (
{ __typename?: 'LearningContentAssignmentObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null }
& { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentAssignmentObjectTypeFragment': CoursePageFieldsLearningContentAssignmentObjectTypeFragment } }
) | (
@@ -1243,10 +1349,11 @@ export type CourseSessionDetailQuery = { __typename?: 'Query', course_session?:
export type CourseQueryQueryVariables = Exact<{
slug: Scalars['String']['input'];
+ user?: InputMaybe;
}>;
-export type CourseQueryQuery = { __typename?: 'Query', course?: { __typename?: 'CourseObjectType', id: string, title: string, slug: string, category_name: string, configuration: { __typename?: 'CourseConfigurationObjectType', id: string, enable_circle_documents: boolean, enable_learning_mentor: boolean, enable_competence_certificates: boolean, is_uk: boolean }, action_competences: Array<(
+export type CourseQueryQuery = { __typename?: 'Query', course?: { __typename?: 'CourseObjectType', id: string, title: string, slug: string, category_name: string, profiles?: Array | null, course_session_users: Array<{ __typename: 'CourseSessionUserType', id: string, chosen_profile: string, course_session: { __typename?: 'CourseSessionObjectType', id: string } } | null>, configuration: { __typename?: 'CourseConfigurationObjectType', id: string, enable_circle_documents: boolean, enable_learning_mentor: boolean, enable_competence_certificates: boolean, is_uk: boolean, is_vv: boolean }, action_competences: Array<(
{ __typename?: 'ActionCompetenceObjectType', competence_id: string, performance_criteria: Array<(
{ __typename?: 'PerformanceCriteriaObjectType', competence_id: string, learning_unit?: { __typename?: 'LearningUnitObjectType', id: string, slug: string, evaluate_url: string } | null }
& { ' $fragmentRefs'?: { 'CoursePageFieldsPerformanceCriteriaObjectTypeFragment': CoursePageFieldsPerformanceCriteriaObjectTypeFragment } }
@@ -1255,7 +1362,7 @@ export type CourseQueryQuery = { __typename?: 'Query', course?: { __typename?: '
)>, learning_path: (
{ __typename?: 'LearningPathObjectType', topics: Array<(
{ __typename?: 'TopicObjectType', is_visible: boolean, circles: Array<(
- { __typename?: 'CircleObjectType', description: string, goals: string, learning_sequences: Array<(
+ { __typename?: 'CircleObjectType', description: string, goals: string, profiles: Array, is_base_circle: boolean, learning_sequences: Array<(
{ __typename?: 'LearningSequenceObjectType', icon: string, learning_units: Array<(
{ __typename?: 'LearningUnitObjectType', evaluate_url: string, performance_criteria: Array<(
{ __typename?: 'PerformanceCriteriaObjectType' }
@@ -1362,11 +1469,13 @@ export type SendFeedbackMutationMutation = { __typename?: 'Mutation', send_feedb
export const CoursePageFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode;
export const AttendanceCheckMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AttendanceCheckMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"attendanceCourseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"attendanceUserList"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AttendanceUserInputType"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update_course_session_attendance_course_users"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"attendanceCourseId"}}},{"kind":"Argument","name":{"kind":"Name","value":"attendance_user_list"},"value":{"kind":"Variable","name":{"kind":"Name","value":"attendanceUserList"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_session_attendance_course"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attendance_user_list"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user_id"}},{"kind":"Field","name":{"kind":"Name","value":"first_name"}},{"kind":"Field","name":{"kind":"Name","value":"last_name"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}}]}}]} as unknown as DocumentNode;
export const UpsertAssignmentCompletionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpsertAssignmentCompletion"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"completionStatus"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AssignmentCompletionStatus"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"completionDataString"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"evaluationPoints"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Float"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"initializeCompletion"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"evaluationUserId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"upsert_assignment_completion"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"assignment_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"assignment_user_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}}},{"kind":"Argument","name":{"kind":"Name","value":"completion_status"},"value":{"kind":"Variable","name":{"kind":"Name","value":"completionStatus"}}},{"kind":"Argument","name":{"kind":"Name","value":"completion_data_string"},"value":{"kind":"Variable","name":{"kind":"Name","value":"completionDataString"}}},{"kind":"Argument","name":{"kind":"Name","value":"evaluation_points"},"value":{"kind":"Variable","name":{"kind":"Name","value":"evaluationPoints"}}},{"kind":"Argument","name":{"kind":"Name","value":"initialize_completion"},"value":{"kind":"Variable","name":{"kind":"Name","value":"initializeCompletion"}}},{"kind":"Argument","name":{"kind":"Name","value":"evaluation_user_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"evaluationUserId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_completion"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"completion_data"}},{"kind":"Field","name":{"kind":"Name","value":"task_completion_data"}}]}}]}}]}}]} as unknown as DocumentNode;
+export const UpdateCourseSessionProfileDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateCourseSessionProfile"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CourseSessionProfileMutationInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update_course_session_profile"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"clientMutationId"}},{"kind":"Field","name":{"kind":"Name","value":"result"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateCourseProfileSuccess"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"chosen_profile"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateCourseProfileError"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode;
export const AttendanceCheckQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"attendanceCheckQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_session_attendance_course"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attendance_user_list"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user_id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}}]} as unknown as DocumentNode;
export const AssignmentCompletionQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"assignmentCompletionQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"needs_expert_evaluation"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"effort_required"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_description"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_document_url"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_tasks"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"intro_text"}},{"kind":"Field","name":{"kind":"Name","value":"performance_objectives"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"tasks"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"translation_key"}},{"kind":"Field","name":{"kind":"Name","value":"solution_sample"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment_completion"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"assignment_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"assignment_user_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"first_name"}},{"kind":"Field","name":{"kind":"Name","value":"last_name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar_url"}},{"kind":"Field","name":{"kind":"Name","value":"first_name"}},{"kind":"Field","name":{"kind":"Name","value":"last_name"}},{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_max_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_deducted"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_deducted_reason"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_final"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_passed"}},{"kind":"Field","name":{"kind":"Name","value":"edoniq_extended_time_flag"}},{"kind":"Field","name":{"kind":"Name","value":"completion_data"}},{"kind":"Field","name":{"kind":"Name","value":"task_completion_data"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode;
-export const CompetenceCertificateForUserQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"competenceCertificateForUserQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userIds"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_certificate_list"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}}},{"kind":"Argument","name":{"kind":"Name","value":"user_ids"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userIds"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificates"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate_weight"}},{"kind":"Field","name":{"kind":"Name","value":"completions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_final"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_deducted"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_max_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_passed"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_percent"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"circle"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode;
+export const CompetenceCertificateQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"competenceCertificateQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_certificate_list"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificates"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate_weight"}},{"kind":"Field","name":{"kind":"Name","value":"completions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_deducted"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_final"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_max_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_passed"}},{"kind":"Field","name":{"kind":"Name","value":"course_session"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"circle"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode;
+export const CompetenceCertificateForUserQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"competenceCertificateForUserQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userIds"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_certificate_list"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}}},{"kind":"Argument","name":{"kind":"Name","value":"user_ids"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userIds"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificates"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate_weight"}},{"kind":"Field","name":{"kind":"Name","value":"completions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_final"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points_deducted"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_max_points"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_passed"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_percent"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"course_session"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"circle"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode;
export const CourseSessionDetailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"courseSessionDetail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_session"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"course"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"configuration"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"enable_circle_documents"}},{"kind":"Field","name":{"kind":"Name","value":"enable_learning_mentor"}},{"kind":"Field","name":{"kind":"Name","value":"enable_competence_certificates"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"users"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"user_id"}},{"kind":"Field","name":{"kind":"Name","value":"first_name"}},{"kind":"Field","name":{"kind":"Name","value":"last_name"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"avatar_url"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"circles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}},{"kind":"Field","name":{"kind":"Name","value":"optional_attendance"}}]}},{"kind":"Field","name":{"kind":"Name","value":"attendance_courses"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"location"}},{"kind":"Field","name":{"kind":"Name","value":"trainer"}},{"kind":"Field","name":{"kind":"Name","value":"due_date"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"start"}},{"kind":"Field","name":{"kind":"Name","value":"end"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content_id"}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"circle"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"submission_deadline"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"start"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_deadline"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"start"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"edoniq_tests"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"deadline"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"start"}},{"kind":"Field","name":{"kind":"Name","value":"end"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode;
-export const CourseQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"courseQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"slug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"slug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"category_name"}},{"kind":"Field","name":{"kind":"Name","value":"configuration"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"enable_circle_documents"}},{"kind":"Field","name":{"kind":"Name","value":"enable_learning_mentor"}},{"kind":"Field","name":{"kind":"Name","value":"enable_competence_certificates"}},{"kind":"Field","name":{"kind":"Name","value":"is_uk"}}]}},{"kind":"Field","name":{"kind":"Name","value":"action_competences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"performance_criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_id"}},{"kind":"Field","name":{"kind":"Name","value":"learning_unit"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"evaluate_url"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_path"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"topics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"is_visible"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"circles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"goals"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"learning_sequences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"learning_units"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evaluate_url"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"performance_criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_contents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"can_user_self_toggle_course_completion"}},{"kind":"Field","name":{"kind":"Name","value":"content_url"}},{"kind":"Field","name":{"kind":"Name","value":"minutes"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentAssignmentObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentEdoniqTestObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"checkbox_text"}},{"kind":"Field","name":{"kind":"Name","value":"has_extended_time_test"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentRichTextObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"}}]}}]}}]}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode;
+export const CourseQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"courseQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"slug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"user"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"slug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"category_name"}},{"kind":"Field","name":{"kind":"Name","value":"profiles"}},{"kind":"Field","name":{"kind":"Name","value":"course_session_users"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"user"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"chosen_profile"}},{"kind":"Field","name":{"kind":"Name","value":"course_session"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"configuration"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"enable_circle_documents"}},{"kind":"Field","name":{"kind":"Name","value":"enable_learning_mentor"}},{"kind":"Field","name":{"kind":"Name","value":"enable_competence_certificates"}},{"kind":"Field","name":{"kind":"Name","value":"is_uk"}},{"kind":"Field","name":{"kind":"Name","value":"is_vv"}}]}},{"kind":"Field","name":{"kind":"Name","value":"action_competences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"performance_criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_id"}},{"kind":"Field","name":{"kind":"Name","value":"learning_unit"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"evaluate_url"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_path"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"topics"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"is_visible"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"circles"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"goals"}},{"kind":"Field","name":{"kind":"Name","value":"profiles"}},{"kind":"Field","name":{"kind":"Name","value":"is_base_circle"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"learning_sequences"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"learning_units"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evaluate_url"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"performance_criteria"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_contents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"can_user_self_toggle_course_completion"}},{"kind":"Field","name":{"kind":"Name","value":"content_url"}},{"kind":"Field","name":{"kind":"Name","value":"minutes"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentAssignmentObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentEdoniqTestObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"checkbox_text"}},{"kind":"Field","name":{"kind":"Name","value":"has_extended_time_test"}},{"kind":"Field","name":{"kind":"Name","value":"content_assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LearningContentRichTextObjectType"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"}}]}}]}}]}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode;
export const DashboardConfigDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"dashboardConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"dashboard_config"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"dashboard_type"}},{"kind":"Field","name":{"kind":"Name","value":"course_configuration"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"enable_circle_documents"}},{"kind":"Field","name":{"kind":"Name","value":"enable_learning_mentor"}},{"kind":"Field","name":{"kind":"Name","value":"enable_competence_certificates"}},{"kind":"Field","name":{"kind":"Name","value":"is_uk"}}]}}]}}]}}]} as unknown as DocumentNode;
export const DashboardProgressDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"dashboardProgress"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_progress"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_id"}},{"kind":"Field","name":{"kind":"Name","value":"session_to_continue_id"}},{"kind":"Field","name":{"kind":"Name","value":"competence"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"total_count"}},{"kind":"Field","name":{"kind":"Name","value":"success_count"}},{"kind":"Field","name":{"kind":"Name","value":"fail_count"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"total_count"}},{"kind":"Field","name":{"kind":"Name","value":"points_max_count"}},{"kind":"Field","name":{"kind":"Name","value":"points_achieved_count"}}]}}]}}]}}]} as unknown as DocumentNode;
export const DashboardCourseDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"dashboardCourseData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_progress"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"_id"}},{"kind":"Field","name":{"kind":"Name","value":"course_id"}},{"kind":"Field","name":{"kind":"Name","value":"session_to_continue_id"}}]}}]}}]} as unknown as DocumentNode;
diff --git a/client/src/gql/schema.graphql b/client/src/gql/schema.graphql
index c23a4ff0..1c644eb4 100644
--- a/client/src/gql/schema.graphql
+++ b/client/src/gql/schema.graphql
@@ -278,6 +278,8 @@ type CourseObjectType {
configuration: CourseConfigurationObjectType!
learning_path: LearningPathObjectType!
action_competences: [ActionCompetenceObjectType!]!
+ profiles: [String]
+ course_session_users(id: String): [CourseSessionUserType]!
}
type ActionCompetenceObjectType implements CoursePageInterface {
@@ -343,45 +345,38 @@ type CircleLightObjectType {
slug: String!
}
-type TopicObjectType implements CoursePageInterface {
- is_visible: Boolean!
- id: ID!
- title: String!
- slug: String!
- content_type: String!
- live: Boolean!
- translation_key: String!
- frontend_url: String!
- course: CourseObjectType
- circles: [CircleObjectType!]!
+type CourseSessionUserType {
+ id: UUID!
+ chosen_profile: String!
+ course_session: CourseSessionObjectType!
}
-type CircleObjectType implements CoursePageInterface {
- description: String!
- goals: String!
+"""
+Leverages the internal Python implementation of UUID (uuid.UUID) to provide native UUID objects
+in fields, resolvers and input.
+"""
+scalar UUID
+
+type CourseSessionObjectType {
id: ID!
+ created_at: DateTime!
+ updated_at: DateTime!
+ course: CourseObjectType!
title: String!
- slug: String!
- content_type: String!
- live: Boolean!
- translation_key: String!
- frontend_url: String!
- course: CourseObjectType
- learning_sequences: [LearningSequenceObjectType!]!
+ start_date: Date
+ end_date: Date
+ attendance_courses: [CourseSessionAttendanceCourseObjectType!]!
+ assignments: [CourseSessionAssignmentObjectType!]!
+ edoniq_tests: [CourseSessionEdoniqTestObjectType!]!
+ users: [CourseSessionUserObjectsType!]!
}
-type LearningSequenceObjectType implements CoursePageInterface {
- icon: String!
- id: ID!
- title: String!
- slug: String!
- content_type: String!
- live: Boolean!
- translation_key: String!
- frontend_url: String!
- course: CourseObjectType
- learning_units: [LearningUnitObjectType!]!
-}
+"""
+The `Date` scalar type represents a Date
+value as specified by
+[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
+"""
+scalar Date
type CourseSessionAttendanceCourseObjectType {
id: ID!
@@ -443,26 +438,19 @@ type DueDateObjectType {
course_session: CourseSessionObjectType!
}
-type CourseSessionObjectType {
- id: ID!
- created_at: DateTime!
- updated_at: DateTime!
- course: CourseObjectType!
- title: String!
- start_date: Date
- end_date: Date
- attendance_courses: [CourseSessionAttendanceCourseObjectType!]!
- assignments: [CourseSessionAssignmentObjectType!]!
- edoniq_tests: [CourseSessionEdoniqTestObjectType!]!
- users: [CourseSessionUserObjectsType!]!
+type AttendanceUserObjectType {
+ user_id: UUID!
+ status: AttendanceUserStatus!
+ first_name: String
+ last_name: String
+ email: String
}
-"""
-The `Date` scalar type represents a Date
-value as specified by
-[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
-"""
-scalar Date
+"""An enumeration."""
+enum AttendanceUserStatus {
+ PRESENT
+ ABSENT
+}
type CourseSessionAssignmentObjectType {
id: ID!
@@ -591,12 +579,6 @@ type AssignmentCompletionObjectType {
evaluation_percent: Float
}
-"""
-Leverages the internal Python implementation of UUID (uuid.UUID) to provide native UUID objects
-in fields, resolvers and input.
-"""
-scalar UUID
-
type UserObjectType {
"""
Erforderlich. 150 Zeichen oder weniger. Nur Buchstaben, Ziffern und @/./+/-/_.
@@ -735,18 +717,46 @@ type CourseSessionUserExpertCircleType {
slug: String!
}
-type AttendanceUserObjectType {
- user_id: UUID!
- status: AttendanceUserStatus!
- first_name: String
- last_name: String
- email: String
+type TopicObjectType implements CoursePageInterface {
+ is_visible: Boolean!
+ id: ID!
+ title: String!
+ slug: String!
+ content_type: String!
+ live: Boolean!
+ translation_key: String!
+ frontend_url: String!
+ course: CourseObjectType
+ circles: [CircleObjectType!]!
}
-"""An enumeration."""
-enum AttendanceUserStatus {
- PRESENT
- ABSENT
+type CircleObjectType implements CoursePageInterface {
+ description: String!
+ goals: String!
+ is_base_circle: Boolean!
+ id: ID!
+ title: String!
+ slug: String!
+ content_type: String!
+ live: Boolean!
+ translation_key: String!
+ frontend_url: String!
+ course: CourseObjectType
+ learning_sequences: [LearningSequenceObjectType!]!
+ profiles: [String]!
+}
+
+type LearningSequenceObjectType implements CoursePageInterface {
+ icon: String!
+ id: ID!
+ title: String!
+ slug: String!
+ content_type: String!
+ live: Boolean!
+ translation_key: String!
+ frontend_url: String!
+ course: CourseObjectType
+ learning_units: [LearningUnitObjectType!]!
}
type LearningContentMediaLibraryObjectType implements CoursePageInterface & LearningContentInterface {
@@ -909,6 +919,7 @@ type CompetenceCertificateListObjectType implements CoursePageInterface {
type Mutation {
send_feedback(course_session_id: ID!, data: GenericScalar, learning_content_page_id: ID!, learning_content_type: String!, submitted: Boolean = false): SendFeedbackMutation
update_course_session_attendance_course_users(attendance_user_list: [AttendanceUserInputType]!, id: ID!): AttendanceCourseUserMutation
+ update_course_session_profile(input: CourseSessionProfileMutationInput!): CourseSessionProfileMutationPayload
upsert_assignment_completion(assignment_id: ID!, assignment_user_id: UUID, completion_data_string: String, completion_status: AssignmentCompletionStatus, course_session_id: ID!, evaluation_passed: Boolean, evaluation_points: Float, evaluation_user_id: ID, initialize_completion: Boolean, learning_content_page_id: ID): AssignmentCompletionMutation
}
@@ -939,6 +950,27 @@ input AttendanceUserInputType {
status: AttendanceUserStatus!
}
+type CourseSessionProfileMutationPayload {
+ result: UpdateCourseProfileResult
+ clientMutationId: String
+}
+
+union UpdateCourseProfileResult = UpdateCourseProfileError | UpdateCourseProfileSuccess
+
+type UpdateCourseProfileError {
+ message: String
+}
+
+type UpdateCourseProfileSuccess {
+ user: CourseSessionUserType!
+}
+
+input CourseSessionProfileMutationInput {
+ course_profile: String!
+ course_slug: String!
+ clientMutationId: String
+}
+
type AssignmentCompletionMutation {
assignment_completion: AssignmentCompletionObjectType
}
diff --git a/client/src/gql/typenames.ts b/client/src/gql/typenames.ts
index 36d7ab4c..c6712dfd 100644
--- a/client/src/gql/typenames.ts
+++ b/client/src/gql/typenames.ts
@@ -34,8 +34,11 @@ export const CourseSessionAssignmentObjectType = "CourseSessionAssignmentObjectT
export const CourseSessionAttendanceCourseObjectType = "CourseSessionAttendanceCourseObjectType";
export const CourseSessionEdoniqTestObjectType = "CourseSessionEdoniqTestObjectType";
export const CourseSessionObjectType = "CourseSessionObjectType";
+export const CourseSessionProfileMutationInput = "CourseSessionProfileMutationInput";
+export const CourseSessionProfileMutationPayload = "CourseSessionProfileMutationPayload";
export const CourseSessionUserExpertCircleType = "CourseSessionUserExpertCircleType";
export const CourseSessionUserObjectsType = "CourseSessionUserObjectsType";
+export const CourseSessionUserType = "CourseSessionUserType";
export const CourseStatisticsType = "CourseStatisticsType";
export const DashboardConfigType = "DashboardConfigType";
export const DashboardType = "DashboardType";
@@ -84,4 +87,7 @@ export const StatisticsCourseSessionsSelectionMetricType = "StatisticsCourseSess
export const String = "String";
export const TopicObjectType = "TopicObjectType";
export const UUID = "UUID";
+export const UpdateCourseProfileError = "UpdateCourseProfileError";
+export const UpdateCourseProfileResult = "UpdateCourseProfileResult";
+export const UpdateCourseProfileSuccess = "UpdateCourseProfileSuccess";
export const UserObjectType = "UserObjectType";
diff --git a/client/src/graphql/mutations.ts b/client/src/graphql/mutations.ts
index 09fcf8e3..99180b51 100644
--- a/client/src/graphql/mutations.ts
+++ b/client/src/graphql/mutations.ts
@@ -58,3 +58,23 @@ export const UPSERT_ASSIGNMENT_COMPLETION_MUTATION = graphql(`
}
}
`);
+
+export const UPDATE_COURSE_PROFILE_MUTATION = graphql(`
+ mutation UpdateCourseSessionProfile($input: CourseSessionProfileMutationInput!) {
+ update_course_session_profile(input: $input) {
+ clientMutationId
+ result {
+ __typename
+ ... on UpdateCourseProfileSuccess {
+ user {
+ id
+ chosen_profile
+ }
+ }
+ ... on UpdateCourseProfileError {
+ message
+ }
+ }
+ }
+ }
+`);
diff --git a/client/src/graphql/queries.ts b/client/src/graphql/queries.ts
index 00ed10c4..acbd08cd 100644
--- a/client/src/graphql/queries.ts
+++ b/client/src/graphql/queries.ts
@@ -1,4 +1,4 @@
-import { graphql } from "@/gql";
+import {graphql} from "@/gql";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const CoursePageFragment = graphql(`
@@ -90,6 +90,45 @@ export const ASSIGNMENT_COMPLETION_QUERY = graphql(`
`);
export const COMPETENCE_NAVI_CERTIFICATE_QUERY = graphql(`
+ query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {
+ competence_certificate_list(course_slug: $courseSlug) {
+ ...CoursePageFields
+ competence_certificates {
+ ...CoursePageFields
+ assignments {
+ ...CoursePageFields
+ assignment_type
+ max_points
+ competence_certificate_weight
+ completions(course_session_id: $courseSessionId) {
+ id
+ completion_status
+ submitted_at
+ evaluation_points
+ evaluation_points_deducted
+ evaluation_points_final
+ evaluation_max_points
+ evaluation_passed
+ course_session {
+ id
+ title
+ }
+ }
+ learning_content {
+ ...CoursePageFields
+ circle {
+ id
+ title
+ slug
+ }
+ }
+ }
+ }
+ }
+ }
+`);
+
+export const COMPETENCE_NAVI_CERTIFICATE_FOR_USER_QUERY = graphql(`
query competenceCertificateForUserQuery(
$courseSlug: String!
$courseSessionId: ID!
@@ -117,6 +156,10 @@ export const COMPETENCE_NAVI_CERTIFICATE_QUERY = graphql(`
assignment_user {
id
}
+ course_session {
+ id
+ title
+ }
}
learning_content {
...CoursePageFields
@@ -225,18 +268,28 @@ export const COURSE_SESSION_DETAIL_QUERY = graphql(`
`);
export const COURSE_QUERY = graphql(`
- query courseQuery($slug: String!) {
+ query courseQuery($slug: String!, $user: String) {
course(slug: $slug) {
id
title
slug
category_name
+ profiles
+ course_session_users(id: $user) {
+ id
+ __typename
+ chosen_profile
+ course_session {
+ id
+ }
+ }
configuration {
id
enable_circle_documents
enable_learning_mentor
enable_competence_certificates
is_uk
+ is_vv
}
action_competences {
competence_id
@@ -259,6 +312,8 @@ export const COURSE_QUERY = graphql(`
circles {
description
goals
+ profiles
+ is_base_circle
...CoursePageFields
learning_sequences {
icon
diff --git a/client/src/pages/StyleGuidePage.vue b/client/src/pages/StyleGuidePage.vue
index 25ff5db5..24f03a87 100644
--- a/client/src/pages/StyleGuidePage.vue
+++ b/client/src/pages/StyleGuidePage.vue
@@ -403,6 +403,13 @@ function log(data: any) {
+ Tags
+
+
+ Active
+ Inactive
+
+
Dropdown (Work-in-progress)
+import { useCurrentCourseSession } from "@/composables";
+import router from "@/router";
+import { useCourseSessionsStore } from "@/stores/courseSessions";
import type { CompetenceCertificateAssignment } from "@/types";
import * as log from "loglevel";
log.debug("CompetenceAssignmentRow setup");
+const currentCourseSession = useCurrentCourseSession();
+const { switchCourseSessionById } = useCourseSessionsStore();
+
export interface Props {
assignment: CompetenceCertificateAssignment;
+ showCourseSession: boolean;
addBorderBottom?: boolean;
}
@@ -19,6 +26,13 @@ const getIconName = () => {
}
return "it-icon-assignment-large";
};
+
+const openInCircle = (assignment: CompetenceCertificateAssignment) => {
+ if (assignment.completion?.course_session !== currentCourseSession.value) {
+ switchCourseSessionById(assignment.completion!.course_session.id);
+ }
+ router.push(assignment.frontend_url);
+};
@@ -30,19 +44,26 @@ const getIconName = () => {
diff --git a/client/src/pages/competence/CompetenceCertificateComponent.vue b/client/src/pages/competence/CompetenceCertificateComponent.vue
index 0e4a822a..af6cbd83 100644
--- a/client/src/pages/competence/CompetenceCertificateComponent.vue
+++ b/client/src/pages/competence/CompetenceCertificateComponent.vue
@@ -9,6 +9,7 @@ import {
calcCompetenceCertificateGrade,
competenceCertificateProgressStatusCount,
} from "@/pages/competence/utils";
+import { useCurrentCourseSession } from "@/composables";
log.debug("CompetenceCertificateComponent setup");
@@ -51,6 +52,15 @@ const frontendUrl = computed(() => {
? props.frontendUrl
: props.competenceCertificate.frontend_url;
});
+
+const showCourseSession = computed(() => {
+ const currentCourseSession = useCurrentCourseSession();
+ return props.competenceCertificate.assignments.some((assignment) => {
+ return (
+ assignment.completion?.course_session.title !== currentCourseSession.value.title
+ );
+ });
+});
@@ -134,6 +144,7 @@ const frontendUrl = computed(() => {
diff --git a/client/src/pages/competence/CompetenceCertificateDetailPage.vue b/client/src/pages/competence/CompetenceCertificateDetailPage.vue
index 9bd49535..25daf926 100644
--- a/client/src/pages/competence/CompetenceCertificateDetailPage.vue
+++ b/client/src/pages/competence/CompetenceCertificateDetailPage.vue
@@ -1,13 +1,10 @@
diff --git a/client/src/pages/competence/utils.ts b/client/src/pages/competence/utils.ts
index 27158bd3..e274fa2a 100644
--- a/client/src/pages/competence/utils.ts
+++ b/client/src/pages/competence/utils.ts
@@ -1,6 +1,7 @@
import type { StatusCount } from "@/components/ui/ItProgress.vue";
import { percentToRoundedGrade } from "@/services/assignmentService";
import type { CompetenceCertificate, CompetenceCertificateAssignment } from "@/types";
+import dayjs from "dayjs";
import _ from "lodash";
export function assignmentsMaxEvaluationPoints(
@@ -84,3 +85,55 @@ export function competenceCertificateProgressStatusCount(
FAIL: 0,
} as StatusCount;
}
+
+export function mergeCompetenceCertificates(
+ competenceCertificates: CompetenceCertificate[]
+) {
+ const groupedCompetenceCertificates: Record<
+ string,
+ Array
+ > = {};
+ competenceCertificates.forEach((certificate) => {
+ if (!certificate) {
+ return;
+ }
+ if (!groupedCompetenceCertificates[certificate.id]) {
+ groupedCompetenceCertificates[certificate.id] = [];
+ }
+ groupedCompetenceCertificates[certificate.id].push(certificate);
+ });
+
+ console.log(
+ `Found ${Object.keys(groupedCompetenceCertificates).length} competence certificates over all course sessions`
+ );
+
+ return Object.values(groupedCompetenceCertificates).map((certificates) => {
+ const mergedCertificate: CompetenceCertificate = {
+ ...certificates[0],
+ assignments: [],
+ };
+ certificates.forEach((certificate) => {
+ certificate.assignments.forEach((assignment) => {
+ const existingAssignment = mergedCertificate.assignments.find(
+ (a) => a.id === assignment.id
+ );
+ if (!existingAssignment) {
+ mergedCertificate.assignments.push(assignment);
+ } else if (
+ assignment.completion != null &&
+ (existingAssignment.completion == null ||
+ dayjs(existingAssignment.completion.evaluation_submitted_at).isBefore(
+ assignment.completion.evaluation_submitted_at
+ ))
+ ) {
+ mergedCertificate.assignments.splice(
+ mergedCertificate.assignments.findIndex((a) => a.id === assignment.id),
+ 1
+ );
+ mergedCertificate.assignments.push(assignment);
+ }
+ });
+ });
+ return mergedCertificate;
+ });
+}
diff --git a/client/src/pages/learningPath/learningPathPage/LearningPathListTopic.vue b/client/src/pages/learningPath/learningPathPage/LearningPathListTopic.vue
new file mode 100644
index 00000000..4cf545ea
--- /dev/null
+++ b/client/src/pages/learningPath/learningPathPage/LearningPathListTopic.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+ {{ topic.title }}
+
+
+
+
diff --git a/client/src/pages/learningPath/learningPathPage/LearningPathListView.vue b/client/src/pages/learningPath/learningPathPage/LearningPathListView.vue
index 3fe62231..334331ad 100644
--- a/client/src/pages/learningPath/learningPathPage/LearningPathListView.vue
+++ b/client/src/pages/learningPath/learningPathPage/LearningPathListView.vue
@@ -1,26 +1,23 @@
-
-
- {{ topic.title }}
-
-
-
+
diff --git a/client/src/pages/learningPath/learningPathPage/LearningPathPage.vue b/client/src/pages/learningPath/learningPathPage/LearningPathPage.vue
index 0e051681..3d8aecc8 100644
--- a/client/src/pages/learningPath/learningPathPage/LearningPathPage.vue
+++ b/client/src/pages/learningPath/learningPathPage/LearningPathPage.vue
@@ -3,6 +3,7 @@ import LearningPathListView from "@/pages/learningPath/learningPathPage/Learning
import LearningPathPathView from "@/pages/learningPath/learningPathPage/LearningPathPathView.vue";
import CircleProgress from "@/pages/learningPath/learningPathPage/LearningPathProgress.vue";
import LearningPathTopics from "@/pages/learningPath/learningPathPage/LearningPathTopics.vue";
+import LearningPathProfileFilter from "@/pages/learningPath/learningPathPage/LearningPathProfileFilter.vue";
import type { ViewType } from "@/pages/learningPath/learningPathPage/LearningPathViewSwitch.vue";
import LearningPathViewSwitch from "@/pages/learningPath/learningPathPage/LearningPathViewSwitch.vue";
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core";
@@ -13,6 +14,9 @@ import {
useCurrentCourseSession,
} from "@/composables";
import CourseSessionDueDatesList from "@/components/dueDates/CourseSessionDueDatesList.vue";
+import { useMutation } from "@urql/vue";
+import { UPDATE_COURSE_PROFILE_MUTATION } from "@/graphql/mutations";
+import { filterCircles, useCourseFilter } from "./utils";
const props = defineProps<{
courseSlug: string;
@@ -33,9 +37,28 @@ const course = computed(() => lpQueryResult.course.value);
const courseSession = useCurrentCourseSession();
-const { inProgressCirclesCount, circlesCount } = useCourseCircleProgress(
- lpQueryResult.circles
-);
+const { filter } = useCourseFilter(props.courseSlug);
+
+const filteredCircles = computed(() => {
+ if (lpQueryResult.circles.value === undefined) {
+ return [];
+ }
+ return filterCircles(filter.value, lpQueryResult.circles.value);
+});
+
+const { inProgressCirclesCount, circlesCount } =
+ useCourseCircleProgress(filteredCircles);
+
+const updateCourseProfileMutation = useMutation(UPDATE_COURSE_PROFILE_MUTATION);
+
+const updateCourseProfile = (profile: string) => {
+ updateCourseProfileMutation.executeMutation({
+ input: {
+ course_profile: profile,
+ course_slug: props.courseSlug,
+ },
+ });
+};
const changeViewType = (viewType: ViewType) => {
selectedView.value = viewType;
@@ -46,7 +69,9 @@ const changeViewType = (viewType: ViewType) => {
-
+
@@ -64,15 +89,21 @@ const changeViewType = (viewType: ViewType) => {
>
-
-
-
@@ -101,6 +132,7 @@ const changeViewType = (viewType: ViewType) => {
@@ -114,6 +146,7 @@ const changeViewType = (viewType: ViewType) => {
+import { computed } from "vue";
+import type { LearningContentWithCompletion, TopicType } from "@/types";
+import LearningPathCircleColumn from "./LearningPathCircleColumn.vue";
+import { filterCircles } from "./utils";
+
+interface Props {
+ topic: TopicType;
+ topicIndex: number;
+ nextLearningContent?: LearningContentWithCompletion;
+ overrideCircleUrlBase?: string;
+ filter?: string;
+ isLastTopic: boolean;
+}
+
+const props = defineProps
();
+
+const isFirstCircle = (circleIndex: number) =>
+ props.topicIndex === 0 && circleIndex === 0;
+
+const isLastCircle = (circleIndex: number, numCircles: number) =>
+ props.isLastTopic && circleIndex === numCircles - 1;
+
+const filteredCircles = computed(() => {
+ return filterCircles(props.filter, props.topic.circles);
+});
+
+
+
+
+
+ {{ topic.title }}
+
+
+
+
+
+
diff --git a/client/src/pages/learningPath/learningPathPage/LearningPathPathView.vue b/client/src/pages/learningPath/learningPathPage/LearningPathPathView.vue
index 7150b719..0b6353ab 100644
--- a/client/src/pages/learningPath/learningPathPage/LearningPathPathView.vue
+++ b/client/src/pages/learningPath/learningPathPage/LearningPathPathView.vue
@@ -1,10 +1,10 @@
@@ -50,37 +60,16 @@ const scrollLearnPathDiagram = (offset: number) => {
ref="learnPathDiagram"
class="no-scrollbar flex h-96 snap-x flex-row overflow-auto py-5 sm:py-10"
>
-
-
- {{ topic.title }}
-
-
-
-
-
+ :topic-index="topicIndex"
+ :topic="topic"
+ :next-learning-content="nextLearningContent"
+ :override-circle-url-base="overrideCircleUrlBase"
+ :filter="filter"
+ :is-last-topic="topicIndex === topics.length - 1"
+ />
+import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
+import { COURSE_PROFILE_ALL_FILTER } from "@/constants";
+import type { DropdownSelectable } from "@/types";
+import { useTranslation } from "i18next-vue";
+import { computed } from "vue";
+
+interface Props {
+ profiles?: string[];
+ selected?: string;
+}
+
+const props = defineProps();
+const emit = defineEmits(["select"]);
+
+const { t } = useTranslation();
+const items = computed(() => {
+ return props.profiles?.map((p) => ({ id: p, name: t(`profile.${p}`) })) || [];
+});
+
+const selectedItem = computed(() => {
+ if (props.selected) {
+ return { id: props.selected || "", name: t(`profile.${props.selected}`) };
+ }
+ return {
+ id: COURSE_PROFILE_ALL_FILTER,
+ name: t(`profile.${COURSE_PROFILE_ALL_FILTER}`),
+ };
+});
+
+const updateFilter = (e: DropdownSelectable) => {
+ emit("select", e.id);
+};
+
+
+
+
+
{{ $t("a.Zulassungsprofil") }}:
+
+
+
+
+
diff --git a/client/src/pages/learningPath/learningPathPage/utils.ts b/client/src/pages/learningPath/learningPathPage/utils.ts
index 46410d94..d27f27f8 100644
--- a/client/src/pages/learningPath/learningPathPage/utils.ts
+++ b/client/src/pages/learningPath/learningPathPage/utils.ts
@@ -1,3 +1,6 @@
+import { useCurrentCourseSession } from "@/composables";
+import { COURSE_PROFILE_ALL_FILTER } from "@/constants";
+import { COURSE_QUERY } from "@/graphql/queries";
import type {
CircleSectorData,
CircleSectorProgress,
@@ -7,6 +10,8 @@ import {
someFinishedInLearningSequence,
} from "@/services/circle";
import type { CircleType } from "@/types";
+import { useQuery } from "@urql/vue";
+import { computed } from "vue";
export function calculateCircleSectorData(circle: CircleType): CircleSectorData[] {
return circle.learning_sequences.map((ls) => {
@@ -21,3 +26,42 @@ export function calculateCircleSectorData(circle: CircleType): CircleSectorData[
};
});
}
+
+export function useCourseFilter(courseSlug: string, courseSessionId?: string) {
+ const csId = computed(() => {
+ if (courseSessionId) {
+ return courseSessionId;
+ }
+ // assume we're on a page with a current course session
+ const courseSession = useCurrentCourseSession();
+ return courseSession.value.id;
+ });
+ const courseReactiveResult = useQuery({
+ query: COURSE_QUERY,
+ variables: { slug: courseSlug },
+ });
+ const courseReactive = computed(() => courseReactiveResult.data.value?.course);
+ const courseSessionUser = computed(() => {
+ return courseReactive.value?.course_session_users.find(
+ (e) => e?.course_session.id === csId.value
+ );
+ });
+ const filter = computed(() => {
+ return courseSessionUser.value?.chosen_profile || "";
+ });
+
+ return {
+ filter,
+ courseReactive,
+ courseSessionUser,
+ };
+}
+
+export function filterCircles(filter: string | undefined, circles: CircleType[]) {
+ if (filter === undefined || filter === "" || filter === COURSE_PROFILE_ALL_FILTER) {
+ return circles;
+ }
+ return circles.filter(
+ (circle) => circle.profiles.indexOf(filter as string) > -1 || circle.is_base_circle
+ );
+}
diff --git a/client/src/pages/onboarding/vv/AccountCourseProfile.vue b/client/src/pages/onboarding/vv/AccountCourseProfile.vue
new file mode 100644
index 00000000..c101a0e2
--- /dev/null
+++ b/client/src/pages/onboarding/vv/AccountCourseProfile.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+ {{ $t("a.Zulassungsprofil auswählen") }}
+
+
+
+ {{
+ $t(
+ "a.Wähle ein Zulassungsprofil, damit du deinen Lehrgang an der richtigen Stelle beginnen kannst. Du kannst ihn später jederzeit ändern."
+ )
+ }}
+
+
+
+
+
+
+
+
+ {{ $t("general.next") }}
+
+
+
+
+
+
diff --git a/client/src/pages/onboarding/vv/CheckoutAddress.vue b/client/src/pages/onboarding/vv/CheckoutAddress.vue
index 3bcfa0d3..918dc3a3 100644
--- a/client/src/pages/onboarding/vv/CheckoutAddress.vue
+++ b/client/src/pages/onboarding/vv/CheckoutAddress.vue
@@ -229,6 +229,7 @@ const executePayment = async () => {
redirect_url: fullHost,
address: addressData,
product: props.courseType,
+ chosen_profile: user.chosen_profile?.id || "",
with_cembra_byjuno_invoice: address.value.payment_method === "cembra_byjuno",
device_fingerprint_session_key: getLocalSessionKey(),
}).then((res: any) => {
diff --git a/client/src/pages/start/VVStartPage.vue b/client/src/pages/start/VVStartPage.vue
index 7cf3f310..1b55cde8 100644
--- a/client/src/pages/start/VVStartPage.vue
+++ b/client/src/pages/start/VVStartPage.vue
@@ -47,6 +47,14 @@ const { t } = useTranslation();
$t("Füge dein Profilbild hinzu und ergänze die fehlenden Angaben.")
}}
+
+ {{ $t("a.Zulassungsprofil auswählen") }}:
+ {{
+ $t(
+ "a.Wähle ein Zulassungsprofil, damit du deinen Lehrgang an der richtigen Stelle beginnen kannst."
+ )
+ }}
+
{{ $t("a.Lehrgang kaufen") }}:
{{
diff --git a/client/src/pages/userProfile/LearningPathProfilePage.vue b/client/src/pages/userProfile/LearningPathProfilePage.vue
index 34413b25..ca7921c9 100644
--- a/client/src/pages/userProfile/LearningPathProfilePage.vue
+++ b/client/src/pages/userProfile/LearningPathProfilePage.vue
@@ -1,11 +1,12 @@
+
+
+
+
{{ topic.title }} {{ filter }}
+
+
+ {{ circle.title }}
+
+
+
diff --git a/client/src/router/__tests__/onboarding.spec.ts b/client/src/router/__tests__/onboarding.spec.ts
index 199bc5e0..20278cb7 100644
--- a/client/src/router/__tests__/onboarding.spec.ts
+++ b/client/src/router/__tests__/onboarding.spec.ts
@@ -61,7 +61,7 @@ describe("Onboarding", () => {
mockNext
);
expect(mockNext).toHaveBeenCalledWith({
- name: "checkoutAddress",
+ name: "accountCourseProfile",
params: { courseType: testCase },
});
});
diff --git a/client/src/router/index.ts b/client/src/router/index.ts
index 716bb5a8..7347bd92 100644
--- a/client/src/router/index.ts
+++ b/client/src/router/index.ts
@@ -417,6 +417,12 @@ const router = createRouter({
component: () => import("@/pages/onboarding/uk/SetupComplete.vue"),
name: "setupComplete",
},
+ {
+ path: "account/course-profile",
+ component: () => import("@/pages/onboarding/vv/AccountCourseProfile.vue"),
+ name: "accountCourseProfile",
+ props: true,
+ },
{
path: "checkout/address",
component: () => import("@/pages/onboarding/vv/CheckoutAddress.vue"),
diff --git a/client/src/services/entities.ts b/client/src/services/entities.ts
index 2de7f01c..588627b1 100644
--- a/client/src/services/entities.ts
+++ b/client/src/services/entities.ts
@@ -13,14 +13,21 @@ export type Country = {
name: string;
};
+export type CourseProfile = {
+ id: number;
+ code: string;
+};
+
export function useEntities() {
const countries: Ref = ref([]);
const organisations: Ref = ref([]);
+ const courseProfiles: Ref = ref([]);
itGetCached("/api/core/entities/").then((res: any) => {
countries.value = res.countries;
organisations.value = res.organisations;
+ courseProfiles.value = res.courseProfiles;
});
- return { organisations, countries };
+ return { organisations, countries, courseProfiles };
}
diff --git a/client/src/services/onboarding.ts b/client/src/services/onboarding.ts
index 9c59ef48..1b2e4d5e 100644
--- a/client/src/services/onboarding.ts
+++ b/client/src/services/onboarding.ts
@@ -11,7 +11,7 @@ export function profileNextRoute(courseType: string | string[]) {
}
// vv- -> vv-de, vv-fr or vv-it
if (isString(courseType) && startsWith(courseType, "vv-")) {
- return "checkoutAddress";
+ return "accountCourseProfile";
}
return "";
}
diff --git a/client/src/stores/user.ts b/client/src/stores/user.ts
index 2c85dba7..6e9e9e53 100644
--- a/client/src/stores/user.ts
+++ b/client/src/stores/user.ts
@@ -1,6 +1,6 @@
import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers";
import { setI18nLanguage } from "@/i18nextWrapper";
-import type { Country } from "@/services/entities";
+import type { Country, CourseProfile } from "@/services/entities";
import { directUpload } from "@/services/files";
import dayjs from "dayjs";
import { defineStore } from "pinia";
@@ -44,6 +44,7 @@ export interface User {
organisation_postal_code: string;
organisation_city: string;
organisation_country: Country | null;
+ chosen_profile?: CourseProfile;
}
let defaultLanguage: AvailableLanguages = "de";
@@ -89,6 +90,7 @@ const initialUserState: User = {
organisation_postal_code: "",
organisation_city: "",
organisation_country: null,
+ chosen_profile: undefined,
};
async function setLocale(language: AvailableLanguages) {
@@ -176,5 +178,8 @@ export const useUserStore = defineStore({
await itPost("/api/core/me/", profileData, { method: "PUT" });
Object.assign(this.$state, profileData);
},
+ updateChosenCourseProfile(courseProfile: CourseProfile) {
+ Object.assign(this.$state, { chosen_profile: courseProfile });
+ },
},
});
diff --git a/client/src/types.ts b/client/src/types.ts
index 7dec9dc2..fcd32d40 100644
--- a/client/src/types.ts
+++ b/client/src/types.ts
@@ -202,6 +202,7 @@ export interface Course {
title: string;
category_name: string;
slug: string;
+ profiles: string[];
configuration: CourseConfiguration;
}
@@ -408,6 +409,10 @@ export interface CompetenceCertificateAssignment extends BaseCourseWagtailPage {
evaluation_points_reason: string;
evaluation_max_points: number | null;
evaluation_passed: boolean | null;
+ course_session: {
+ id: string;
+ title: string;
+ };
}[];
}
diff --git a/client/tailwind.css b/client/tailwind.css
index 2417d110..14a41aea 100644
--- a/client/tailwind.css
+++ b/client/tailwind.css
@@ -93,7 +93,7 @@ textarea {
}
.link {
- @apply underline underline-offset-2;
+ @apply cursor-pointer underline underline-offset-2;
}
.link-large {
@@ -167,6 +167,14 @@ textarea {
top: 1rem;
transform: translateY(-50%);
}
+
+ .tag-inactive {
+ @apply rounded-full border-2 border-blue-900 px-4 py-2 font-semibold text-blue-900;
+ }
+
+ .tag-active {
+ @apply rounded-full bg-blue-900 px-4 py-2 font-semibold text-white;
+ }
}
@layer utilities {
@@ -181,7 +189,9 @@ textarea {
}
.no-scrollbar {
- -ms-overflow-style: none; /* IE and Edge */
- scrollbar-width: none; /* Firefox */
+ -ms-overflow-style: none;
+ /* IE and Edge */
+ scrollbar-width: none;
+ /* Firefox */
}
}
diff --git a/cypress/consts.js b/cypress/consts.js
index 43ef6b5b..a32c8474 100644
--- a/cypress/consts.js
+++ b/cypress/consts.js
@@ -1,16 +1,22 @@
// ids for cypress test data
-export const ADMIN_USER_ID = "872efd96-3bd7-4a1e-a239-2d72cad9f604"
-export const TEST_SUPERVISOR1_USER_ID = "a9a8b741-f115-4521-af2d-7dfef673b8c5"
-export const TEST_TRAINER1_USER_ID = "b9e71f59-c44f-4290-b93a-9b3151e9a2fc"
-export const TEST_TRAINER2_USER_ID = "299941ae-1e4b-4f45-8180-876c3ad340b4"
-export const TEST_STUDENT1_USER_ID = "65c73ad0-6d53-43a9-a4a4-64143f27b03a"
-export const TEST_STUDENT2_USER_ID = "19c40d94-15cc-4198-aaad-ef707c4b0900"
-export const TEST_STUDENT3_USER_ID = "bcf94dba-53bc-474b-a22d-e4af39aa042b"
-export const TEST_MENTOR1_USER_ID = "d1f5f5a9-5b0a-4e1a-9e1a-9e9b5b5e1b1b"
-export const TEST_STUDENT1_VV_USER_ID = "5ff59857-8de5-415e-a387-4449f9a0337a"
-export const TEST_STUDENT2_VV_AND_VV_MENTOR_USER_ID = "7e8ebf0b-e6e2-4022-88f4-6e663ba0a9db"
-export const TEST_USER_EMPTY_ID = "daecbabe-4ab9-4edf-a71f-4119042ccb02"
-
+export const ADMIN_USER_ID = "872efd96-3bd7-4a1e-a239-2d72cad9f604";
+export const TEST_SUPERVISOR1_USER_ID = "a9a8b741-f115-4521-af2d-7dfef673b8c5";
+export const TEST_TRAINER1_USER_ID = "b9e71f59-c44f-4290-b93a-9b3151e9a2fc";
+export const TEST_TRAINER2_USER_ID = "299941ae-1e4b-4f45-8180-876c3ad340b4";
+export const TEST_STUDENT1_USER_ID = "65c73ad0-6d53-43a9-a4a4-64143f27b03a";
+export const TEST_STUDENT2_USER_ID = "19c40d94-15cc-4198-aaad-ef707c4b0900";
+export const TEST_STUDENT3_USER_ID = "bcf94dba-53bc-474b-a22d-e4af39aa042b";
+export const TEST_MENTOR1_USER_ID = "d1f5f5a9-5b0a-4e1a-9e1a-9e9b5b5e1b1b";
+export const TEST_STUDENT1_VV_USER_ID = "5ff59857-8de5-415e-a387-4449f9a0337a";
+export const TEST_STUDENT2_VV_AND_VV_MENTOR_USER_ID =
+ "7e8ebf0b-e6e2-4022-88f4-6e663ba0a9db";
+export const TEST_USER_EMPTY_ID = "daecbabe-4ab9-4edf-a71f-4119042ccb02";
export const TEST_COURSE_SESSION_BERN_ID = -1;
export const TEST_COURSE_SESSION_ZURICH_ID = -2;
+export const TEST_COURSE_SESSION_VV_ID = 1;
+
+export const COURSE_PROFILE_LEBEN_ID = -1;
+export const COURSE_PROFILE_NICHTLEBEN_ID = -2;
+export const COURSE_PROFILE_KRANKENZUSATZ_ID = -3;
+export const COURSE_PROFILE_ALL_ID = -99;
diff --git a/cypress/e2e/checkout-vv/checkout.cy.js b/cypress/e2e/checkout-vv/checkout.cy.js
index e6007b44..d00c6cca 100644
--- a/cypress/e2e/checkout-vv/checkout.cy.js
+++ b/cypress/e2e/checkout-vv/checkout.cy.js
@@ -1,4 +1,9 @@
-import { TEST_USER_EMPTY_ID } from "../../consts";
+import {
+ COURSE_PROFILE_ALL_ID,
+ COURSE_PROFILE_NICHTLEBEN_ID,
+ TEST_COURSE_SESSION_VV_ID,
+ TEST_USER_EMPTY_ID,
+} from "../../consts";
import { login } from "../helpers";
describe("checkout.cy.js", () => {
@@ -32,6 +37,15 @@ describe("checkout.cy.js", () => {
cy.get("#organisationDetailName").type("FdH GmbH");
cy.get('[data-cy="continue-button"]').click();
+ cy.get('[data-cy="account-course-profile-title"]').should(
+ "have.text",
+ "Zulassungsprofil auswählen",
+ );
+
+ cy.get('[data-cy="dropdown-select"]').click();
+ cy.get('[data-cy="dropdown-select-option-Nichtleben"]').click();
+ cy.get('[data-cy="continue-button"]').click();
+
cy.loadUser("id", TEST_USER_EMPTY_ID).then((u) => {
expect(u.organisation_detail_name).to.equal("FdH GmbH");
// 2 -> andere Krankenversicherer
@@ -121,6 +135,12 @@ describe("checkout.cy.js", () => {
cy.loadCheckoutInformation("user_id", TEST_USER_EMPTY_ID).then((ci) => {
expect(ci.state).to.equal("paid");
});
+
+ cy.loadCourseSessionUser("user_id", TEST_USER_EMPTY_ID).then((csu) => {
+ expect(csu.role).to.equal("MEMBER");
+ expect(csu.course_session).to.equal(TEST_COURSE_SESSION_VV_ID);
+ expect(csu.chosen_profile).to.equal(COURSE_PROFILE_NICHTLEBEN_ID);
+ });
});
it("can checkout and pay Versicherungsvermittlerin with Cembra invoice", () => {
@@ -143,6 +163,15 @@ describe("checkout.cy.js", () => {
cy.get('[data-cy="dropdown-select-option-Baloise"]').click();
cy.get('[data-cy="continue-button"]').click();
+ cy.get('[data-cy="account-course-profile-title"]').should(
+ "have.text",
+ "Zulassungsprofil auswählen",
+ );
+
+ cy.get('[data-cy="dropdown-select"]').click();
+ cy.get('[data-cy="dropdown-select-option-Allbranche"]').click();
+ cy.get('[data-cy="continue-button"]').click();
+
// Adressdaten ausfüllen
cy.get('[data-cy="account-checkout-title"]').should(
"contain",
@@ -236,5 +265,32 @@ describe("checkout.cy.js", () => {
// 7 -> Baloise
expect(u.organisation).to.equal(7);
});
+
+ // pay
+ cy.get('[data-cy="pay-button"]').click();
+
+ cy.get('[data-cy="checkout-success-title"]').should(
+ "contain",
+ "Gratuliere",
+ );
+ // wait for payment callback
+ cy.wait(3000);
+ cy.get('[data-cy="start-vv-button"]').click();
+
+ // back on dashboard page
+ cy.get('[data-cy="db-course-title"]').should(
+ "contain",
+ "Versicherungsvermittler",
+ );
+
+ cy.loadCheckoutInformation("user_id", TEST_USER_EMPTY_ID).then((ci) => {
+ expect(ci.state).to.equal("paid");
+ });
+
+ cy.loadCourseSessionUser("user_id", TEST_USER_EMPTY_ID).then((csu) => {
+ expect(csu.role).to.equal("MEMBER");
+ expect(csu.course_session).to.equal(TEST_COURSE_SESSION_VV_ID);
+ expect(csu.chosen_profile).to.equal(COURSE_PROFILE_ALL_ID);
+ });
});
});
diff --git a/cypress/e2e/competenceNavi/competenceCertificate.cy.js b/cypress/e2e/competenceNavi/competenceCertificate.cy.js
index aea07312..86cf58a1 100644
--- a/cypress/e2e/competenceNavi/competenceCertificate.cy.js
+++ b/cypress/e2e/competenceNavi/competenceCertificate.cy.js
@@ -1,26 +1,26 @@
-import { login } from "../helpers";
+import { login } from "../helpers"
describe("competenceCertificate.cy.js", () => {
- beforeEach(() => {});
+ beforeEach(() => { })
it("check without points", () => {
- cy.manageCommand("cypress_reset");
- login("test-student1@example.com", "test");
- cy.visit("/course/test-lehrgang/competence");
+ cy.manageCommand("cypress_reset")
+ login("test-student1@example.com", "test")
+ cy.visit("/course/test-lehrgang/competence")
cy.get('[data-cy="certificate-total-points-text"]').contains(
"Der Punktestand wird zu einem späteren Zeitpunkt berechnet."
- );
+ )
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
- ).and("contain", "0 von 2 Kompetenznachweis-Elementen");
+ ).and("contain", "0 von 2 Kompetenznachweis-Elementen")
// check on certificates page
- cy.get('[data-cy="certificates-show-all-button"]').click();
+ cy.get('[data-cy="certificates-show-all-button"]').click()
cy.get('[data-cy="certificate-total-points-text"]').contains(
"Der Punktestand wird zu einem späteren Zeitpunkt berechnet."
- );
+ )
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
@@ -29,100 +29,100 @@ describe("competenceCertificate.cy.js", () => {
"contain",
"Der Punktestand wird zu einem späteren Zeitpunkt berechnet."
)
- .and("contain", "0 von 2 Kompetenznachweis-Elementen");
+ .and("contain", "0 von 2 Kompetenznachweis-Elementen")
// check certificate detail page
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-detail-link"]'
- ).click();
+ ).click()
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"]'
- ).should("contain", "Höchstpunktzahl");
+ ).should("contain", "Höchstpunktzahl")
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"]'
- ).should("contain", "Höchstpunktzahl");
- });
+ ).should("contain", "Höchstpunktzahl")
+ })
it("check with finished passed edoniq test", () => {
cy.manageCommand(
"cypress_reset --create-assignment-completion --create-edoniq-test-results 19 24 0"
- );
- login("test-student1@example.com", "test");
- cy.visit("/course/test-lehrgang/competence");
+ )
+ login("test-student1@example.com", "test")
+ cy.visit("/course/test-lehrgang/competence")
cy.get('[data-cy="certificate-total-points-text"]').contains(
"Erfahrungsnote üK: 5"
- );
+ )
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
)
.should("contain", "Note: 5")
- .and("contain", "1 von 2 Kompetenznachweis-Elementen");
+ .and("contain", "1 von 2 Kompetenznachweis-Elementen")
// check on certificates page
- cy.get('[data-cy="certificates-show-all-button"]').click();
+ cy.get('[data-cy="certificates-show-all-button"]').click()
cy.get('[data-cy="certificate-total-points-text"]')
.should("contain", "Erfahrungsnote üK")
- .and("contain", "Zwischenstand");
- cy.get('[data-cy="certificate-total-grade"]').should("contain", "Note: 5");
+ .and("contain", "Zwischenstand")
+ cy.get('[data-cy="certificate-total-grade"]').should("contain", "Note: 5")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade"]'
- ).should("contain", "Note: 5");
+ ).should("contain", "Note: 5")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade-percent"]'
- ).should("contain", "Ungerundete Note: 4.96");
+ ).should("contain", "Ungerundete Note: 4.96")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
)
.and("contain", "Zwischenstand")
- .and("contain", "1 von 2 Kompetenznachweis-Elementen");
+ .and("contain", "1 von 2 Kompetenznachweis-Elementen")
// check certificate detail page
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-detail-link"]'
- ).click();
+ ).click()
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"]'
)
.should("contain", "Höchstpunktzahl")
- .and("contain", "Ergebnisse abgegeben");
+ .and("contain", "Ergebnisse abgegeben")
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"]'
)
.should("contain", "19")
.and("contain", "Bewertung freigegeben")
- .and("not.contain", "Nicht Bestanden");
+ .and("not.contain", "Nicht Bestanden")
// it can open learning content page directly
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"] [data-cy="open-learning-content"]'
- ).click();
+ ).click()
cy.get('[data-cy="test-result"]')
.should("contain", "19 von 24 Punkten")
- .and("contain", "79%");
- });
+ .and("contain", "79%")
+ })
it("check with finished failed edoniq test", () => {
cy.manageCommand(
"cypress_reset --create-assignment-completion --create-edoniq-test-results 10 24 0"
- );
- login("test-student1@example.com", "test");
+ )
+ login("test-student1@example.com", "test")
// go to certificate detail page
cy.visit(
"/course/test-lehrgang/competence/certificates/kompetenznachweis-1"
- );
+ )
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade"]'
- ).should("contain", "Note: 3");
+ ).should("contain", "Note: 3")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade-percent"]'
- ).should("contain", "Ungerundete Note: 3.08");
+ ).should("contain", "Ungerundete Note: 3.08")
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"]'
@@ -130,90 +130,170 @@ describe("competenceCertificate.cy.js", () => {
.should("contain", "10")
.and("contain", "Bewertung freigegeben")
.and("contain", "42%")
- .and("contain", "Nicht bestanden");
+ .and("contain", "Nicht bestanden")
// it can open learning content page directly
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"] [data-cy="open-learning-content"]'
- ).click();
+ ).click()
cy.get('[data-cy="test-result"]')
.should("contain", "10 von 24 Punkten")
.and("contain", "42%")
- .and("contain", "Nicht bestanden");
- });
+ .and("contain", "Nicht bestanden")
+ })
it("check with finished edoniq test and finished casework", () => {
cy.manageCommand(
"cypress_reset --create-assignment-evaluation --create-edoniq-test-results 19 24 0"
- );
- login("test-student1@example.com", "test");
- cy.visit("/course/test-lehrgang/competence");
+ )
+ login("test-student1@example.com", "test")
+ cy.visit("/course/test-lehrgang/competence")
cy.get('[data-cy="certificate-total-points-text"]').contains(
"Erfahrungsnote üK: 5.5"
- );
+ )
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
)
.should("contain", "Note: 5.5")
- .and("contain", "2 von 2 Kompetenznachweis-Elementen");
+ .and("contain", "2 von 2 Kompetenznachweis-Elementen")
// check on certificates page
- cy.get('[data-cy="certificates-show-all-button"]').click();
+ cy.get('[data-cy="certificates-show-all-button"]').click()
cy.get('[data-cy="certificate-total-points-text"]')
.should("contain", "Erfahrungsnote üK")
.and("contain", "Note: 5.5")
- .and("not.contain", "Zwischenstand");
+ .and("not.contain", "Zwischenstand")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
)
.and("not.contain", "Zwischenstand")
- .and("contain", "2 von 2 Kompetenznachweis-Elementen");
+ .and("contain", "2 von 2 Kompetenznachweis-Elementen")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade"]'
- ).should("contain", "Note: 5.5");
+ ).should("contain", "Note: 5.5")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade-percent"]'
- ).should("contain", "Ungerundete Note: 5.48");
+ ).should("contain", "Ungerundete Note: 5.48")
// check certificate detail page
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-detail-link"]'
- ).click();
+ ).click()
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"]'
)
.should("contain", "24")
.and("contain", "von 24 Punkten")
- .and("contain", "Bewertung freigegeben");
+ .and("contain", "Bewertung freigegeben")
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"]'
)
.should("contain", "19")
.and("contain", "von 24 Punkten")
- .and("contain", "Bewertung freigegeben");
- });
+ .and("contain", "Bewertung freigegeben")
+ })
+
+ it("check with finished edoniq test and finished casework in different course sessions", () => {
+ const TEST_TRAINER2_USER_ID = "299941ae-1e4b-4f45-8180-876c3ad340b4"
+ const TEST_STUDENT2_USER_ID = "19c40d94-15cc-4198-aaad-ef707c4b0900"
+ const TEST_COURSE_SESSION_ZURICH_ID = -2
+ cy.manageCommand(
+ `cypress_reset --create-assignment-evaluation --assignment-evaluation-user-id ${TEST_TRAINER2_USER_ID} --assignment-completion-user-id ${TEST_STUDENT2_USER_ID} --edoniq-user-id ${TEST_STUDENT2_USER_ID} --edoniq-course-session-id '${TEST_COURSE_SESSION_ZURICH_ID}' --create-edoniq-test-results 19 24 0`
+ )
+ login("test-student2@example.com", "test")
+ cy.visit("/course/test-lehrgang/competence")
+
+ cy.get('[data-cy="certificate-total-points-text"]').contains(
+ "Erfahrungsnote üK: 5.5"
+ )
+
+ cy.get(
+ '[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
+ )
+ .should("contain", "Note: 5.5")
+ .and("contain", "2 von 2 Kompetenznachweis-Elementen")
+
+ // check on certificates page
+ cy.get('[data-cy="certificates-show-all-button"]').click()
+ cy.get('[data-cy="certificate-total-points-text"]')
+ .should("contain", "Erfahrungsnote üK")
+ .and("contain", "Note: 5.5")
+ .and("not.contain", "Zwischenstand")
+
+ cy.get(
+ '[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
+ )
+ .and("not.contain", "Zwischenstand")
+ .and("contain", "2 von 2 Kompetenznachweis-Elementen")
+ cy.get(
+ '[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade"]'
+ ).should("contain", "Note: 5.5")
+ cy.get(
+ '[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade-percent"]'
+ ).should("contain", "Ungerundete Note: 5.48")
+
+ // check certificate detail page
+ cy.get(
+ '[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-detail-link"]'
+ ).click()
+
+ cy.get(
+ '[data-cy="assignment-test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"]'
+ )
+ .should("contain", "24")
+ .and("contain", "von 24 Punkten")
+ .and("contain", "Bewertung freigegeben")
+ cy.get(
+ '[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"]'
+ )
+ .should("contain", "19")
+ .and("contain", "von 24 Punkten")
+ .and("contain", "Bewertung freigegeben")
+
+ cy.get('[data-cy="assignment-test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice-course-session"]').should("contain", "Test Bern 2022 a")
+ cy.get('[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo-course-session"]').should("contain", "Test Zürich 2022 a")
+ })
+
+ it("check show assignment in different course session", () => {
+ const TEST_TRAINER2_USER_ID = "299941ae-1e4b-4f45-8180-876c3ad340b4"
+ const TEST_STUDENT2_USER_ID = "19c40d94-15cc-4198-aaad-ef707c4b0900"
+ const TEST_COURSE_SESSION_ZURICH_ID = -2
+ cy.manageCommand(
+ `cypress_reset --create-assignment-evaluation --assignment-evaluation-user-id ${TEST_TRAINER2_USER_ID} --assignment-completion-user-id ${TEST_STUDENT2_USER_ID} --edoniq-user-id ${TEST_STUDENT2_USER_ID} --edoniq-course-session-id '${TEST_COURSE_SESSION_ZURICH_ID}' --create-edoniq-test-results 19 24 0`
+ )
+ login("test-student2@example.com", "test")
+ cy.visit("course/test-lehrgang/competence/certificates/kompetenznachweis-1")
+
+ cy.get('[data-cy="current-course-session-title"]').should("contain", "Test Bern 2022 a")
+
+ cy.get(
+ '[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"] [data-cy="open-learning-content"]'
+ ).click()
+
+ cy.get('[data-cy="current-course-session-title"]').should("contain", "Test Zürich 2022 a")
+ })
it("check with finished edoniq test with deducted points", () => {
cy.manageCommand(
"cypress_reset --create-assignment-completion --create-edoniq-test-results 19 24 8"
- );
- login("test-student1@example.com", "test");
+ )
+ login("test-student1@example.com", "test")
// go to certificate detail page
cy.visit(
"/course/test-lehrgang/competence/certificates/kompetenznachweis-1"
- );
+ )
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade"]'
- ).should("contain", "Note: 3.5");
+ ).should("contain", "Note: 3.5")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade-percent"]'
- ).should("contain", "Ungerundete Note: 3.29");
+ ).should("contain", "Ungerundete Note: 3.29")
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"]'
@@ -222,61 +302,61 @@ describe("competenceCertificate.cy.js", () => {
.and("contain", "Bewertung freigegeben")
.and("contain", "46%")
.and("contain", "mit Abzug")
- .and("contain", "Nicht bestanden");
+ .and("contain", "Nicht bestanden")
// it can open learning content page directly
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"] [data-cy="open-learning-content"]'
- ).click();
+ ).click()
cy.get('[data-cy="test-result"]')
.should("contain", "11 von 24 Punkten")
.and("contain", "46%")
.and("contain", "Punkte aus Bewertung: 19")
.and("contain", "Abgezogene Punkte: 8")
.and("contain", "Grund: Edoniq Punkteabzug Test")
- .and("contain", "Nicht bestanden");
- });
+ .and("contain", "Nicht bestanden")
+ })
it("check with finished casework and points deducted", () => {
cy.manageCommand(
"cypress_reset --create-assignment-evaluation --assignment-evaluation-scores 4,6,4,3,2 --assignment-points-deducted 5"
- );
- login("test-student1@example.com", "test");
- cy.visit("/course/test-lehrgang/competence");
+ )
+ login("test-student1@example.com", "test")
+ cy.visit("/course/test-lehrgang/competence")
cy.get('[data-cy="certificate-total-points-text"]').contains(
"Erfahrungsnote üK: 4"
- );
+ )
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
)
.should("contain", "Note: 4")
- .and("contain", "1 von 2 Kompetenznachweis-Elementen");
+ .and("contain", "1 von 2 Kompetenznachweis-Elementen")
// check on certificates page
- cy.get('[data-cy="certificates-show-all-button"]').click();
+ cy.get('[data-cy="certificates-show-all-button"]').click()
cy.get('[data-cy="certificate-total-points-text"]')
.should("contain", "Erfahrungsnote üK")
.and("contain", "Note: 4")
- .and("contain", "Zwischenstand");
+ .and("contain", "Zwischenstand")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1"]'
)
.and("contain", "Zwischenstand")
- .and("contain", "1 von 2 Kompetenznachweis-Elementen");
+ .and("contain", "1 von 2 Kompetenznachweis-Elementen")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade"]'
- ).should("contain", "Note: 4");
+ ).should("contain", "Note: 4")
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-grade-percent"]'
- ).should("contain", "Ungerundete Note: 3.92");
+ ).should("contain", "Ungerundete Note: 3.92")
// check certificate detail page
cy.get(
'[data-cy="certificate-test-lehrgang-competencenavi-certificates-kompetenznachweis-1-detail-link"]'
- ).click();
+ ).click()
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"]'
@@ -285,28 +365,28 @@ describe("competenceCertificate.cy.js", () => {
.and("contain", "von 24 Punkten")
.and("contain", "58%")
.and("contain", "mit Abzug")
- .and("contain", "Bewertung freigegeben");
+ .and("contain", "Bewertung freigegeben")
cy.get(
'[data-cy="assignment-test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"] [data-cy="open-learning-content"]'
- ).click();
- cy.get('[data-cy="user-points"]').should("contain", "14");
+ ).click()
+ cy.get('[data-cy="user-points"]').should("contain", "14")
cy.get('[data-cy="total-points"]').should(
"contain",
"von 24 Punkten (58%)"
- );
+ )
cy.get('[data-cy="points-deducted"]')
.should("contain", "Punkte aus Bewertung: 19")
.and("contain", "Abgezogene Punkte: 5")
- .and("contain", "Grund: Assignment Punkteabzug Test");
- });
+ .and("contain", "Grund: Assignment Punkteabzug Test")
+ })
it("should display link to details", () => {
- cy.manageCommand("cypress_reset");
- login("test-student1@example.com", "test");
- cy.visit("/course/test-lehrgang/competence/self-evaluation-and-feedback");
+ cy.manageCommand("cypress_reset")
+ login("test-student1@example.com", "test")
+ cy.visit("/course/test-lehrgang/competence/self-evaluation-and-feedback")
cy.get('[data-cy^="self-eval-"][data-cy$="-detail-url"]:first').contains(
"Selbsteinschätzung anschauen"
- );
- });
-});
+ )
+ })
+})
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index b1aab6a0..e0d40b56 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -50,20 +50,20 @@
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
-const _ = Cypress._;
+const _ = Cypress._
Cypress.Commands.add("manageCommand", (command, preCommand = "") => {
- const execCommand = `${preCommand} python server/manage.py ${command} --settings=config.settings.test_cypress`;
- console.log(execCommand);
+ const execCommand = `${preCommand} python server/manage.py ${command} --settings=config.settings.test_cypress`
+ console.log(execCommand)
// hack to add my asdf python instance to the path
// so I can run the test directly from within IntelliJ
let pythonPaths = [
"/Users/daniel/workspace/vbv_lernwelt/.direnv/python-3.10.6/bin",
- "/Users/eliabieri/iterativ/vbv_lernwelt/.direnv/python-3.10.6/bin",
+ "/Users/eliabieri/iterativ/vbv_lernwelt/.direnv/python-3.10/bin",
"/Users/christiancueni/workspace/vbv_lernwelt/.direnv/python-3.10.6/bin",
"/Users/renzo/workspace/vbv_lernwelt/.direnv/python-3.10.6/bin",
- ];
- let bashCommand = `PATH=${pythonPaths.join(":")}:$PATH && ${execCommand}`;
+ ]
+ let bashCommand = `PATH=${pythonPaths.join(":")}:$PATH && ${execCommand}`
return cy
.exec(`bash -c "${bashCommand}"`, {
failOnNonZeroExit: true,
@@ -73,14 +73,14 @@ Cypress.Commands.add("manageCommand", (command, preCommand = "") => {
throw new Error(`Execution of "${command}" failed
Exit code: ${result.code}
Stdout:\n${result.stdout}
- Stderr:\n${result.stderr}`);
+ Stderr:\n${result.stderr}`)
}
- });
-});
+ })
+})
Cypress.Commands.add("manageShellCommand", (command) => {
- return cy.manageCommand(`shell -c '${command}'`);
-});
+ return cy.manageCommand(`shell -c '${command}'`)
+})
function loadObjectJson(
key,
@@ -89,28 +89,28 @@ function loadObjectJson(
serializerModelPath,
valueAsString = false,
) {
- const djangoModel = _.last(djangoModelPath.split("."));
- const djangoModelImportPath = _.initial(djangoModelPath.split(".")).join(".");
- const serializerModel = _.last(serializerModelPath.split("."));
+ const djangoModel = _.last(djangoModelPath.split("."))
+ const djangoModelImportPath = _.initial(djangoModelPath.split(".")).join(".")
+ const serializerModel = _.last(serializerModelPath.split("."))
const serializerModelImportPath = _.initial(
serializerModelPath.split("."),
).join(".");
- let filterPart = `${key}=${value}`;
+ let filterPart = `${key}=${value}`
if (valueAsString) {
- filterPart = `${key}=\\"${value}\\"`;
+ filterPart = `${key}=\\"${value}\\"`
}
if (_.isArray(key)) {
filterPart = _.zip(key, value)
.map(([k, v]) => {
if (valueAsString) {
- return `${k}=\\"${v}\\"`;
+ return `${k}=\\"${v}\\"`
} else {
- return `${k}=${v}`;
+ return `${k}=${v}`
}
})
- .join(",");
+ .join(",")
}
const command = `from ${djangoModelImportPath} import ${djangoModel};
@@ -119,13 +119,13 @@ function loadObjectJson(
object = ${djangoModel}.objects.filter(${filterPart}).first();
print(create_json_from_objects(object, ${serializerModel}, many=False));
exit();
- `.replace(/(?:\r\n|\r|\n)/g, "");
+ `.replace(/(?:\r\n|\r|\n)/g, "")
return cy.manageShellCommand(command).then((result) => {
- const objectJson = JSON.parse(result.stdout);
+ const objectJson = JSON.parse(result.stdout)
// console.log(command);
- console.log(objectJson);
- return objectJson;
- });
+ console.log(objectJson)
+ return objectJson
+ })
}
Cypress.Commands.add("loadAssignmentCompletion", (key, value) => {
@@ -138,6 +138,7 @@ Cypress.Commands.add("loadAssignmentCompletion", (key, value) => {
);
});
+
Cypress.Commands.add("loadSecurityRequestResponseLog", (key, value) => {
return loadObjectJson(
key,
@@ -148,6 +149,7 @@ Cypress.Commands.add("loadSecurityRequestResponseLog", (key, value) => {
);
});
+
Cypress.Commands.add("loadExternalApiRequestLog", (key, value) => {
return loadObjectJson(
key,
@@ -158,6 +160,7 @@ Cypress.Commands.add("loadExternalApiRequestLog", (key, value) => {
);
});
+
Cypress.Commands.add("loadFeedbackResponse", (key, value) => {
return loadObjectJson(
key,
@@ -168,6 +171,7 @@ Cypress.Commands.add("loadFeedbackResponse", (key, value) => {
);
});
+
Cypress.Commands.add("loadCheckoutInformation", (key, value) => {
return loadObjectJson(
key,
@@ -178,6 +182,7 @@ Cypress.Commands.add("loadCheckoutInformation", (key, value) => {
);
});
+
Cypress.Commands.add("loadUser", (key, value) => {
return loadObjectJson(
key,
@@ -188,6 +193,15 @@ Cypress.Commands.add("loadUser", (key, value) => {
);
});
+Cypress.Commands.add("loadCourseSessionUser", (key, value) => {
+ return loadObjectJson(
+ key,
+ value,
+ "vbv_lernwelt.course.models.CourseSessionUser",
+ "vbv_lernwelt.course.serializers.CypressCourseSessionUserSerializer",
+ true
+ );
+});
Cypress.Commands.add("makeSelfEvaluation", (answers, withCompletion = true) => {
for (let i = 0; i < answers.length; i++) {
@@ -200,28 +214,28 @@ Cypress.Commands.add("makeSelfEvaluation", (answers, withCompletion = true) => {
if (withCompletion) {
if (i < answers.length - 1) {
- cy.get('[data-cy="next-step"]').click({ force: true });
+ cy.get('[data-cy="next-step"]').click({force: true});
} else {
- cy.get('[data-cy="complete-and-continue"]').click({ force: true });
+ cy.get('[data-cy="complete-and-continue"]').click({force: true});
}
} else {
- cy.get('[data-cy="next-step"]').click({ force: true });
+ cy.get('[data-cy="next-step"]').click({force: true});
}
}
});
Cypress.Commands.add("learningContentMultiLayoutNextStep", () => {
- return cy.get('[data-cy="next-step"]').click({ force: true });
-});
+ return cy.get('[data-cy="next-step"]').click({force: true})
+})
Cypress.Commands.add("learningContentMultiLayoutPreviousStep", () => {
- return cy.get('[data-cy="previous-step"]').click({ force: true });
-});
+ return cy.get('[data-cy="previous-step"]').click({force: true})
+})
Cypress.Commands.add("testLearningContentTitle", (title) => {
- return cy.get('[data-cy="lc-title"]').should("contain", title);
-});
+ return cy.get('[data-cy="lc-title"]').should("contain", title)
+})
Cypress.Commands.add("testLearningContentSubtitle", (subtitle) => {
- return cy.get('[data-cy="lc-subtitle"]').should("contain", subtitle);
-});
+ return cy.get('[data-cy="lc-subtitle"]').should("contain", subtitle)
+})
diff --git a/env_secrets/local_elia.env b/env_secrets/local_elia.env
index 133603a6..2ea6b0a9 100644
Binary files a/env_secrets/local_elia.env and b/env_secrets/local_elia.env differ
diff --git a/git-pre-push.sh b/git-pre-push.sh
index 8cb53b69..fcf48120 100755
--- a/git-pre-push.sh
+++ b/git-pre-push.sh
@@ -7,7 +7,7 @@ echo 'prettier:check'
(cd client && npm run prettier:check)
echo 'lint and typecheck'
-(cd client && npm run lint && npm run typecheck)
+(cd client && npm run lint:errors && npm run typecheck)
echo 'python ufmt check'
ufmt check server
diff --git a/package.json b/package.json
index b0bd1099..3448b150 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"test": "echo \"Error: no test specified\" && exit 1",
"cypress:open": "cypress open",
"cypress:ci": "cypress-cloud run --parallel --record",
+ "cypress:install": "cypress install",
"prettier": "npm run prettier --prefix client"
},
"devDependencies": {
diff --git a/server/vbv_lernwelt/api/directory.py b/server/vbv_lernwelt/api/directory.py
index bc5d9673..9f843c87 100644
--- a/server/vbv_lernwelt/api/directory.py
+++ b/server/vbv_lernwelt/api/directory.py
@@ -4,6 +4,8 @@ from rest_framework.response import Response
from vbv_lernwelt.core.models import Country, Organisation
from vbv_lernwelt.core.serializers import CountrySerializer, OrganisationSerializer
+from vbv_lernwelt.learnpath.models import CourseProfile
+from vbv_lernwelt.learnpath.serializers import CourseProfileSerializer
@api_view(["GET"])
@@ -26,4 +28,13 @@ def list_entities(request):
countries = CountrySerializer(
Country.objects.all(), many=True, context=context
).data
- return Response({"organisations": organisations, "countries": countries})
+ course_profiles = CourseProfileSerializer(
+ CourseProfile.objects.all(), many=True, context=context
+ ).data
+ return Response(
+ {
+ "organisations": organisations,
+ "countries": countries,
+ "courseProfiles": course_profiles,
+ }
+ )
diff --git a/server/vbv_lernwelt/api/user.py b/server/vbv_lernwelt/api/user.py
index dccad63b..248030c2 100644
--- a/server/vbv_lernwelt/api/user.py
+++ b/server/vbv_lernwelt/api/user.py
@@ -1,4 +1,3 @@
-from django.shortcuts import get_object_or_404
from rest_framework.decorators import api_view, permission_classes
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAuthenticated
diff --git a/server/vbv_lernwelt/core/management/commands/cypress_reset.py b/server/vbv_lernwelt/core/management/commands/cypress_reset.py
index 04451d0b..3be6b86c 100644
--- a/server/vbv_lernwelt/core/management/commands/cypress_reset.py
+++ b/server/vbv_lernwelt/core/management/commands/cypress_reset.py
@@ -64,12 +64,32 @@ from vbv_lernwelt.shop.models import CheckoutInformation
@click.option(
"--create-assignment-completion/--no-create-assignment-completion",
default=False,
- help="will create assignment completion data for test-student1@example.com",
+ help="will create assignment completion data for test-student1@example.com by default. Other user can be specified with --assignment-completion-user",
+)
+@click.option(
+ "--assignment-completion-user-id",
+ default=TEST_STUDENT1_USER_ID,
+ help="user to create assignment completion for. Defaults to test-student1@example.com. Hint: Is only evaluated if --create-assignment-completion is set.",
+)
+@click.option(
+ "--assignment-completion-course-session-id",
+ default=TEST_COURSE_SESSION_BERN_ID,
+ help="course session to create assignment completion in. Defaults to 'Test Bern 2022 a'. Hint: Is only evaluated if --create-assignment-completion is set.",
)
@click.option(
"--create-assignment-evaluation/--no-create-assignment-evaluation",
default=False,
- help="will create assignment evaluation data for test-student1@example.com",
+ help="will create assignment evaluation data for test-student1@example.com by default. Other user can be specified with --assignment-evaluation-user",
+)
+@click.option(
+ "--assignment-evaluation-user-id",
+ default=TEST_TRAINER1_USER_ID,
+ help="user to create assignment evaluation for. Defaults to test-trainer1@example.com. Hint: Is only evaluated if --create-assignment-completion is set.",
+)
+@click.option(
+ "--assignment-evaluation-course-session-id",
+ default=TEST_COURSE_SESSION_BERN_ID,
+ help="course session to create assignment evaluation in. Defaults to 'Test Bern 2022 a'. Hint: Is only evaluated if --create-assignment-completion is set.",
)
@click.option(
"--assignment-evaluation-scores",
@@ -86,7 +106,17 @@ from vbv_lernwelt.shop.models import CheckoutInformation
type=(int, int, float),
default=(None, None, 0.0),
metavar="USER_POINTS MAX_POINTS POINTS_DEDUCTED",
- help="Create edoniq result data for test-student1@example.com with user points and max points",
+ help="Create edoniq result data for test-student1@example.com by default with user points and max points. Use --edoniq-user-id to specify a different user.",
+)
+@click.option(
+ "--edoniq-user-id",
+ default=TEST_STUDENT1_USER_ID,
+ help="User to create edoniq test results for. Defaults to test-student1@example.com. Hint: Is only evaluated if --create-edoniq-test-results is set.",
+)
+@click.option(
+ "--edoniq-course-session-id",
+ default=TEST_COURSE_SESSION_BERN_ID,
+ help="course session to create edoniq test results in. Defaults to 'Test Bern 2022 a'. Hint: Is only evaluated if --create-edoniq-test-results is set.",
)
@click.option(
"--create-feedback-responses/--no-create-feedback-responses",
@@ -130,10 +160,16 @@ from vbv_lernwelt.shop.models import CheckoutInformation
)
def command(
create_assignment_completion,
+ assignment_completion_user_id,
+ assignment_completion_course_session_id,
create_assignment_evaluation,
+ assignment_evaluation_user_id,
+ assignment_evaluation_course_session_id,
assignment_evaluation_scores,
assignment_points_deducted,
create_edoniq_test_results,
+ edoniq_user_id,
+ edoniq_course_session_id,
create_feedback_responses,
create_course_completion_performance_criteria,
create_attendance_days,
@@ -186,15 +222,19 @@ def command(
assignment=Assignment.objects.get(
slug="test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"
),
- course_session=CourseSession.objects.get(id=TEST_COURSE_SESSION_BERN_ID),
- user=User.objects.get(id=TEST_STUDENT1_USER_ID),
+ course_session=CourseSession.objects.get(
+ id=assignment_completion_course_session_id
+ ),
+ user=User.objects.get(id=assignment_completion_user_id),
)
create_test_assignment_submitted_data(
assignment=Assignment.objects.get(
slug="test-lehrgang-assignment-mein-kundenstamm"
),
- course_session=CourseSession.objects.get(id=TEST_COURSE_SESSION_BERN_ID),
- user=User.objects.get(id=TEST_STUDENT1_USER_ID),
+ course_session=CourseSession.objects.get(
+ id=assignment_completion_course_session_id
+ ),
+ user=User.objects.get(id=assignment_completion_user_id),
)
if create_assignment_evaluation:
if not assignment_evaluation_scores:
@@ -211,9 +251,11 @@ def command(
assignment=Assignment.objects.get(
slug="test-lehrgang-assignment-überprüfen-einer-motorfahrzeugs-versicherungspolice"
),
- course_session=CourseSession.objects.get(id=TEST_COURSE_SESSION_BERN_ID),
- assignment_user=User.objects.get(id=TEST_STUDENT1_USER_ID),
- evaluation_user=User.objects.get(id=TEST_TRAINER1_USER_ID),
+ course_session=CourseSession.objects.get(
+ id=assignment_evaluation_course_session_id
+ ),
+ assignment_user=User.objects.get(id=assignment_completion_user_id),
+ evaluation_user=User.objects.get(id=assignment_evaluation_user_id),
input_scores=assignment_evaluation_scores,
points_deducted=assignment_points_deducted,
)
@@ -227,8 +269,8 @@ def command(
assignment=Assignment.objects.get(
slug="test-lehrgang-assignment-edoniq-wissens-und-verständisfragen-circle-fahrzeug-demo"
),
- course_session=CourseSession.objects.get(id=TEST_COURSE_SESSION_BERN_ID),
- assignment_user=User.objects.get(id=TEST_STUDENT1_USER_ID),
+ course_session=CourseSession.objects.get(id=edoniq_course_session_id),
+ assignment_user=User.objects.get(id=edoniq_user_id),
user_points=user_points,
max_points=max_points,
evaluation_points_deducted=points_deducted,
diff --git a/server/vbv_lernwelt/course/graphql/types.py b/server/vbv_lernwelt/course/graphql/types.py
index 32665319..934fa119 100644
--- a/server/vbv_lernwelt/course/graphql/types.py
+++ b/server/vbv_lernwelt/course/graphql/types.py
@@ -8,6 +8,7 @@ from graphql import GraphQLError
from rest_framework.exceptions import PermissionDenied
from vbv_lernwelt.competence.graphql.types import ActionCompetenceObjectType
+from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.models import (
CircleDocument,
Course,
@@ -29,8 +30,9 @@ from vbv_lernwelt.course_session.models import (
)
from vbv_lernwelt.course_session_group.models import CourseSessionGroup
from vbv_lernwelt.iam.permissions import has_course_access
+from vbv_lernwelt.learnpath.consts import COURSE_PROFILE_ALL_ID
from vbv_lernwelt.learnpath.graphql.types import LearningPathObjectType
-from vbv_lernwelt.learnpath.models import Circle
+from vbv_lernwelt.learnpath.models import Circle, CourseProfile
logger = structlog.get_logger(__name__)
@@ -106,6 +108,12 @@ class CourseObjectType(DjangoObjectType):
graphene.NonNull(ActionCompetenceObjectType), required=True
)
configuration = graphene.Field(CourseConfigurationObjectType, required=True)
+ profiles = graphene.List(graphene.String)
+ course_session_users = graphene.List(
+ "vbv_lernwelt.course.graphql.types.CourseSessionUserType",
+ required=True,
+ id=graphene.String(),
+ )
class Meta:
model = Course
@@ -125,6 +133,22 @@ class CourseObjectType(DjangoObjectType):
def resolve_action_competences(root: Course, info):
return root.get_action_competences()
+ @staticmethod
+ def resolve_profiles(root: Course, info, **kwargs):
+ if root.configuration.is_vv:
+ return CourseProfile.objects.values_list("code", flat=True)
+ return []
+
+ @staticmethod
+ def resolve_course_session_users(root: Course, info, id=None, **kwargs):
+ # todo: restrict users that can be queried
+ if id is not None:
+ user = User.objects.get(id=id)
+ else:
+ user = info.context.user
+ users = CourseSessionUser.objects.filter(user=user, course_session__course=root)
+ return users
+
class CourseSessionUserExpertCircleType(ObjectType):
id = graphene.ID(required=True)
@@ -132,6 +156,21 @@ class CourseSessionUserExpertCircleType(ObjectType):
slug = graphene.String(required=True)
+class CourseSessionUserType(DjangoObjectType):
+ chosen_profile = graphene.String(required=True)
+ course_session = graphene.Field(
+ "vbv_lernwelt.course.graphql.types.CourseSessionObjectType", required=True
+ )
+
+ class Meta:
+ model = CourseSessionUser
+ fields = ["chosen_profile", "id"]
+
+ @staticmethod
+ def resolve_chosen_profile(root: CourseSessionUser, info, **kwargs):
+ return getattr(root.chosen_profile, "code", "")
+
+
class CourseSessionUserObjectsType(ObjectType):
"""
WORKAROUND:
diff --git a/server/vbv_lernwelt/course/management/commands/create_default_courses.py b/server/vbv_lernwelt/course/management/commands/create_default_courses.py
index 8ebfc82d..5388dc35 100644
--- a/server/vbv_lernwelt/course/management/commands/create_default_courses.py
+++ b/server/vbv_lernwelt/course/management/commands/create_default_courses.py
@@ -97,6 +97,7 @@ from vbv_lernwelt.learnpath.create_vv_new_learning_path import (
create_vv_new_learning_path,
create_vv_pruefung_learning_path,
)
+from vbv_lernwelt.learnpath.creators import assign_circles_to_profiles
from vbv_lernwelt.learnpath.models import (
Circle,
LearningContent,
@@ -218,6 +219,7 @@ def create_versicherungsvermittlerin_course(
create_vv_gewinnen_casework(course_id=course_id)
create_vv_reflection(course_id=course_id)
create_vv_new_learning_path(course_id=course_id)
+ assign_circles_to_profiles()
cs = CourseSession.objects.create(course_id=course_id, title=names[language])
diff --git a/server/vbv_lernwelt/course/migrations/0009_coursesessionuser_chosen_profile.py b/server/vbv_lernwelt/course/migrations/0009_coursesessionuser_chosen_profile.py
new file mode 100644
index 00000000..5ae47808
--- /dev/null
+++ b/server/vbv_lernwelt/course/migrations/0009_coursesessionuser_chosen_profile.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2.20 on 2024-07-11 09:00
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("learnpath", "0017_auto_20240711_1100"),
+ ("course", "0008_auto_20240403_1132"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="coursesessionuser",
+ name="chosen_profile",
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ to="learnpath.courseprofile",
+ ),
+ ),
+ ]
diff --git a/server/vbv_lernwelt/course/migrations/0010_alter_coursecompletion_completion_status.py b/server/vbv_lernwelt/course/migrations/0010_alter_coursecompletion_completion_status.py
new file mode 100644
index 00000000..b864ab57
--- /dev/null
+++ b/server/vbv_lernwelt/course/migrations/0010_alter_coursecompletion_completion_status.py
@@ -0,0 +1,27 @@
+# Generated by Django 4.2.13 on 2024-07-22 19:45
+
+from django.db import migrations, models
+
+import vbv_lernwelt.course.models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("course", "0009_coursesessionuser_chosen_profile"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="coursecompletion",
+ name="completion_status",
+ field=models.CharField(
+ choices=[
+ ("SUCCESS", "Success"),
+ ("FAIL", "Fail"),
+ ("UNKNOWN", "Unknown"),
+ ],
+ default=vbv_lernwelt.course.models.CourseCompletionStatus["UNKNOWN"],
+ max_length=255,
+ ),
+ ),
+ ]
diff --git a/server/vbv_lernwelt/course/migrations/0011_merge_20240807_1317.py b/server/vbv_lernwelt/course/migrations/0011_merge_20240807_1317.py
new file mode 100644
index 00000000..2d76afb8
--- /dev/null
+++ b/server/vbv_lernwelt/course/migrations/0011_merge_20240807_1317.py
@@ -0,0 +1,12 @@
+# Generated by Django 4.2.13 on 2024-08-07 11:17
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("course", "0009_coursesessionuser_required_attendance_and_more"),
+ ("course", "0010_alter_coursecompletion_completion_status"),
+ ]
+
+ operations = []
diff --git a/server/vbv_lernwelt/course/models.py b/server/vbv_lernwelt/course/models.py
index d85c6a9a..aa5ef372 100644
--- a/server/vbv_lernwelt/course/models.py
+++ b/server/vbv_lernwelt/course/models.py
@@ -285,6 +285,10 @@ class CourseSessionUser(models.Model):
)
optional_attendance = models.BooleanField(default=False)
+ chosen_profile = models.ForeignKey(
+ "learnpath.CourseProfile", on_delete=models.SET_NULL, blank=True, null=True
+ )
+
class Meta:
constraints = [
UniqueConstraint(
diff --git a/server/vbv_lernwelt/course/serializers.py b/server/vbv_lernwelt/course/serializers.py
index bd6d9f1a..0ff76b4f 100644
--- a/server/vbv_lernwelt/course/serializers.py
+++ b/server/vbv_lernwelt/course/serializers.py
@@ -8,8 +8,10 @@ from vbv_lernwelt.course.models import (
CourseCompletion,
CourseConfiguration,
CourseSession,
+ CourseSessionUser,
)
from vbv_lernwelt.iam.permissions import course_session_permissions
+from vbv_lernwelt.learnpath.models import CourseProfile
class CourseConfigurationSerializer(serializers.ModelSerializer):
@@ -31,10 +33,23 @@ class CourseSerializer(serializers.ModelSerializer):
configuration = CourseConfigurationSerializer(
read_only=True,
)
+ course_profiles = serializers.SerializerMethodField()
+
+ def get_course_profiles(self, obj):
+ if obj.configuration.is_vv:
+ return CourseProfile.objects.all().values_list("code", flat=True)
+ return []
class Meta:
model = Course
- fields = ["id", "title", "category_name", "slug", "configuration"]
+ fields = [
+ "id",
+ "title",
+ "category_name",
+ "slug",
+ "configuration",
+ "course_profiles",
+ ]
class CourseCategorySerializer(serializers.ModelSerializer):
@@ -103,6 +118,12 @@ class CourseSessionSerializer(serializers.ModelSerializer):
return []
+class CypressCourseSessionUserSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = CourseSessionUser
+ fields = "__all__"
+
+
class CircleDocumentSerializer(serializers.ModelSerializer):
learning_sequence = serializers.SerializerMethodField()
diff --git a/server/vbv_lernwelt/course/tests/test_update_course_profile.py b/server/vbv_lernwelt/course/tests/test_update_course_profile.py
new file mode 100644
index 00000000..c4a4b12c
--- /dev/null
+++ b/server/vbv_lernwelt/course/tests/test_update_course_profile.py
@@ -0,0 +1,164 @@
+from django.test import RequestFactory, TestCase
+from graphene.test import Client
+
+from vbv_lernwelt.core.admin import User
+from vbv_lernwelt.core.create_default_users import create_default_users
+from vbv_lernwelt.core.schema import schema
+from vbv_lernwelt.course.management.commands.create_default_courses import (
+ create_versicherungsvermittlerin_course,
+)
+from vbv_lernwelt.course.models import CourseSessionUser
+from vbv_lernwelt.learnpath.creators import create_course_profiles
+from vbv_lernwelt.learnpath.models import CourseProfile
+
+
+class CourseGraphQLTestCase(TestCase):
+ def setUp(self) -> None:
+ create_default_users()
+ create_course_profiles()
+ create_versicherungsvermittlerin_course()
+
+ def test_update_course_profile(self):
+ user = User.objects.get(username="student-vv@eiger-versicherungen.ch")
+ request = RequestFactory().get("/")
+ request.user = user
+ client = Client(schema=schema, context_value=request)
+ query = """
+ query CourseQuery($slug: String!) {
+ course(slug: $slug){
+ id
+ profiles
+ course_session_users {
+ id
+ __typename
+ chosen_profile
+ course_session {
+ id
+ }
+ }
+ }
+ }
+ """
+ slug = "versicherungsvermittler-in"
+ variables = {"slug": slug}
+ result = client.execute(query, variables=variables)
+
+ self.assertIsNone(result.get("errors"))
+ data = result.get("data")
+ course = data.get("course")
+ profiles = course.get("profiles")
+ self.assertEqual(
+ set(profiles),
+ set(["all", "nichtleben", "leben", "krankenzusatzversicherung"]),
+ )
+ course_session_user = course.get("course_session_users")[0]
+ chosen_profile = course_session_user.get("chosen_profile")
+
+ self.assertEqual(chosen_profile, "")
+
+ mutation = """
+ mutation UpdateCourseSessionProfile($input: CourseSessionProfileMutationInput!) {
+ update_course_session_profile(input: $input) {
+ clientMutationId
+ result {
+ __typename
+ ... on UpdateCourseProfileSuccess {
+ user {
+ id
+ chosen_profile
+ }
+ }
+ ... on UpdateCourseProfileError {
+ message
+ }
+ }
+ }
+ }
+ """
+
+ profile = "nichtleben"
+ input = {"course_profile": profile, "course_slug": slug}
+
+ mutation_result = client.execute(mutation, variables={"input": input})
+
+ self.assertIsNone(mutation_result.get("errors"))
+
+ second_query_result = client.execute(query, variables=variables)
+
+ self.assertIsNone(second_query_result.get("errors"))
+ data = second_query_result.get("data")
+ course = data.get("course")
+ profiles = course.get("profiles")
+ self.assertEqual(
+ set(profiles),
+ set(["all", "nichtleben", "leben", "krankenzusatzversicherung"]),
+ )
+ course_session_user = course.get("course_session_users")[0]
+ chosen_profile = course_session_user.get("chosen_profile")
+ self.assertEqual(chosen_profile, profile)
+
+ def test_mentor_profile_view(self):
+ user = User.objects.get(username="test-mentor1@example.com")
+ request = RequestFactory().get("/")
+ request.user = user
+ client = Client(schema=schema, context_value=request)
+
+ query = """
+ query courseQuery($slug: String!, $user: String) {
+ course(slug: $slug) {
+ id
+ title
+ slug
+ category_name
+ profiles
+ course_session_users(id: $user) {
+ id
+ __typename
+ chosen_profile
+ course_session {
+ id
+ __typename
+ }
+ }
+ __typename
+ }
+ }
+ """
+ student = User.objects.get(username="student-vv@eiger-versicherungen.ch")
+
+ slug = "versicherungsvermittler-in"
+ student_id = str(student.id)
+ variables = {"slug": slug, "user": student_id}
+ print(variables)
+ result = client.execute(query, variables=variables)
+ self.assertIsNone(result.get("errors"))
+ data = result.get("data")
+ course = data.get("course")
+ profiles = course.get("profiles")
+ self.assertEqual(
+ set(profiles),
+ set(["all", "nichtleben", "leben", "krankenzusatzversicherung"]),
+ )
+ course_session_user = course.get("course_session_users")[0]
+ chosen_profile = course_session_user.get("chosen_profile")
+ self.assertEqual(chosen_profile, "")
+
+ csu = CourseSessionUser.objects.get(
+ course_session__course__slug=slug, user=student
+ )
+ course_profile = CourseProfile.objects.get(code="nichtleben")
+ csu.chosen_profile = course_profile
+ csu.save()
+
+ second_result = client.execute(query, variables=variables)
+ self.assertIsNone(second_result.get("errors"))
+ data = second_result.get("data")
+ course = data.get("course")
+ profiles = course.get("profiles")
+ self.assertEqual(
+ set(profiles),
+ set(["all", "nichtleben", "leben", "krankenzusatzversicherung"]),
+ )
+ course_session_user = course.get("course_session_users")[0]
+ chosen_profile = course_session_user.get("chosen_profile")
+ self.assertEqual(chosen_profile, "nichtleben")
diff --git a/server/vbv_lernwelt/course_session/graphql/mutations.py b/server/vbv_lernwelt/course_session/graphql/mutations.py
index 1d00013b..11160149 100644
--- a/server/vbv_lernwelt/course_session/graphql/mutations.py
+++ b/server/vbv_lernwelt/course_session/graphql/mutations.py
@@ -1,7 +1,10 @@
import graphene
import structlog
+from graphene import relay
from rest_framework.exceptions import PermissionDenied
+from vbv_lernwelt.course.graphql.types import CourseSessionUserType
+from vbv_lernwelt.course.models import CourseSessionUser
from vbv_lernwelt.course_session.graphql.types import (
CourseSessionAttendanceCourseObjectType,
)
@@ -11,10 +14,33 @@ from vbv_lernwelt.course_session.services.attendance import (
update_attendance_list,
)
from vbv_lernwelt.iam.permissions import has_course_access
+from vbv_lernwelt.learnpath.models import CourseProfile
logger = structlog.get_logger(__name__)
+class UpdateCourseProfileSuccess(graphene.ObjectType):
+ user = graphene.Field(CourseSessionUserType(), required=True)
+
+
+class UpdateCourseProfileError(graphene.ObjectType):
+ message = graphene.String()
+
+
+class UpdateCourseProfileResult(graphene.Union):
+ class Meta:
+ types = (
+ UpdateCourseProfileError,
+ UpdateCourseProfileSuccess,
+ )
+
+ @classmethod
+ def resolve_type(cls, instance, info):
+ if type(instance).__name__ == "UpdateCourseProfileSuccess":
+ return UpdateCourseProfileSuccess
+ return UpdateCourseProfileError
+
+
class AttendanceUserInputType(graphene.InputObjectType):
user_id = graphene.UUID(required=True)
status = graphene.Field(
@@ -57,5 +83,40 @@ class AttendanceCourseUserMutation(graphene.Mutation):
)
+class CourseSessionProfileMutation(relay.ClientIDMutation):
+ class Input:
+ course_profile = graphene.String(required=True)
+ course_slug = graphene.String(required=True)
+
+ result = UpdateCourseProfileResult()
+
+ @classmethod
+ def mutate_and_get_payload(cls, root, info, **input):
+ course_profile = input.get("course_profile")
+ course_slug = input.get("course_slug")
+ user = info.context.user
+
+ try:
+ if course_profile == "":
+ profile = None
+ else:
+ profile = CourseProfile.objects.get(code=course_profile)
+
+ # csu = user.coursesessionuser_set.first()
+ csu = CourseSessionUser.objects.get(
+ course_session__course__slug=course_slug, user=user
+ )
+ csu.chosen_profile = profile
+ csu.save()
+ return cls(result=UpdateCourseProfileSuccess(user=csu))
+ except CourseProfile.DoesNotExist:
+ return cls(result=UpdateCourseProfileError("Course Profile does not exist"))
+ except CourseSessionUser.DoesNotExist:
+ return cls(
+ result=UpdateCourseProfileError("Course Session User does not exist")
+ )
+
+
class CourseSessionMutation:
update_course_session_attendance_course_users = AttendanceCourseUserMutation.Field()
+ update_course_session_profile = CourseSessionProfileMutation.Field()
diff --git a/server/vbv_lernwelt/learnpath/admin.py b/server/vbv_lernwelt/learnpath/admin.py
index 8c38f3f3..7de0335d 100644
--- a/server/vbv_lernwelt/learnpath/admin.py
+++ b/server/vbv_lernwelt/learnpath/admin.py
@@ -1,3 +1,8 @@
from django.contrib import admin
-# Register your models here.
+from vbv_lernwelt.learnpath.models import CourseProfile
+
+
+@admin.register(CourseProfile)
+class CourseProfileAdmin(admin.ModelAdmin):
+ pass
diff --git a/server/vbv_lernwelt/learnpath/consts.py b/server/vbv_lernwelt/learnpath/consts.py
new file mode 100644
index 00000000..f9c71875
--- /dev/null
+++ b/server/vbv_lernwelt/learnpath/consts.py
@@ -0,0 +1,9 @@
+COURSE_PROFILE_LEBEN_ID = -1
+COURSE_PROFILE_NICHTLEBEN_ID = -2
+COURSE_PROFILE_KRANKENZUSATZ_ID = -3
+COURSE_PROFILE_ALL_ID = -99
+
+COURSE_PROFILE_LEBEN_CODE = "leben"
+COURSE_PROFILE_NICHTLEBEN_CODE = "nichtleben"
+COURSE_PROFILE_KRANKENZUSATZ_CODE = "krankenzusatzversicherung"
+COURSE_PROFILE_ALL_CODE = "all"
diff --git a/server/vbv_lernwelt/learnpath/creators.py b/server/vbv_lernwelt/learnpath/creators.py
new file mode 100644
index 00000000..d238e6eb
--- /dev/null
+++ b/server/vbv_lernwelt/learnpath/creators.py
@@ -0,0 +1,192 @@
+import structlog
+
+from vbv_lernwelt.course.consts import (
+ COURSE_VERSICHERUNGSVERMITTLERIN_FR_ID,
+ COURSE_VERSICHERUNGSVERMITTLERIN_ID,
+ COURSE_VERSICHERUNGSVERMITTLERIN_IT_ID,
+)
+from vbv_lernwelt.learnpath.consts import (
+ COURSE_PROFILE_ALL_CODE,
+ COURSE_PROFILE_ALL_ID,
+ COURSE_PROFILE_KRANKENZUSATZ_CODE,
+ COURSE_PROFILE_KRANKENZUSATZ_ID,
+ COURSE_PROFILE_LEBEN_CODE,
+ COURSE_PROFILE_LEBEN_ID,
+ COURSE_PROFILE_NICHTLEBEN_CODE,
+ COURSE_PROFILE_NICHTLEBEN_ID,
+)
+
+logger = structlog.get_logger(__name__)
+
+
+def create_course_profiles():
+ from vbv_lernwelt.learnpath.models import CourseProfile
+
+ # Allbranche, Krankenzusatzversicherung, nicht Leben, Leben
+ CourseProfile.objects.get_or_create(
+ id=COURSE_PROFILE_ALL_ID, code=COURSE_PROFILE_ALL_CODE, order=1
+ )
+ CourseProfile.objects.get_or_create(
+ id=COURSE_PROFILE_KRANKENZUSATZ_ID,
+ code=COURSE_PROFILE_KRANKENZUSATZ_CODE,
+ order=2,
+ )
+ CourseProfile.objects.get_or_create(
+ id=COURSE_PROFILE_NICHTLEBEN_ID, code=COURSE_PROFILE_NICHTLEBEN_CODE, order=3
+ )
+ CourseProfile.objects.get_or_create(
+ id=COURSE_PROFILE_LEBEN_ID, code=COURSE_PROFILE_LEBEN_CODE, order=4
+ )
+
+
+def assign_circle_to_profile_curry(course_page):
+ from vbv_lernwelt.learnpath.models import Circle, CourseProfile
+
+ def assign_circle_to_profile(title, code):
+ try:
+ circle = Circle.objects.descendant_of(course_page).get(title=title)
+ course_profile = CourseProfile.objects.get(code=code)
+ circle.profiles.add(course_profile)
+ circle.save()
+ except Circle.DoesNotExist:
+ logger.warning("assign_circle_to_profile: circle not found", title=title)
+
+ return assign_circle_to_profile
+
+
+def make_base_circle_curry(course_page):
+ from vbv_lernwelt.learnpath.models import Circle
+
+ def make_base_circle(title):
+ try:
+ circle = Circle.objects.descendant_of(course_page).get(title=title)
+ circle.is_base_circle = True
+ circle.save()
+ except Circle.DoesNotExist:
+ logger.warning("assign_circle_to_profile: circle not found", title=title)
+
+ return make_base_circle
+
+
+def assign_de_circles_to_profiles():
+ from vbv_lernwelt.course.models import CoursePage
+
+ try:
+ course_page = CoursePage.objects.get(
+ course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID
+ )
+ except CoursePage.DoesNotExist:
+ logger.warning("Course does not exist yet")
+ return
+
+ assign_circle_to_profile = assign_circle_to_profile_curry(course_page)
+ make_base_circle = make_base_circle_curry(course_page)
+
+ assign_circle_to_profile("Fahrzeug", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Haushalt", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Rechtsstreitigkeiten", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Reisen", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Wohneigentum", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile(
+ "Selbstständigkeit", COURSE_PROFILE_NICHTLEBEN_CODE
+ ) # typo, but that's how it is in prod data
+ assign_circle_to_profile("KMU", COURSE_PROFILE_NICHTLEBEN_CODE)
+
+ assign_circle_to_profile("Einkommenssicherung", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Pensionierung", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Erben/Vererben", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Sparen", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile(
+ "Selbstständigkeit", COURSE_PROFILE_LEBEN_CODE
+ ) # typo, but that's how it is in prod data
+ assign_circle_to_profile("KMU", COURSE_PROFILE_LEBEN_CODE)
+
+ assign_circle_to_profile("Gesundheit", COURSE_PROFILE_KRANKENZUSATZ_CODE)
+
+ make_base_circle("Kickoff")
+ make_base_circle("Basis")
+ make_base_circle("Gewinnen")
+ make_base_circle("Prüfungsvorbereitung")
+ make_base_circle("Prüfung")
+
+
+def assign_fr_circles_to_profiles():
+ from vbv_lernwelt.course.models import CoursePage
+
+ try:
+ course_page = CoursePage.objects.get(
+ course_id=COURSE_VERSICHERUNGSVERMITTLERIN_FR_ID
+ )
+ except CoursePage.DoesNotExist:
+ logger.warning("Course does not exist yet")
+ return
+
+ assign_circle_to_profile = assign_circle_to_profile_curry(course_page)
+ make_base_circle = make_base_circle_curry(course_page)
+
+ assign_circle_to_profile("Véhicule", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Ménage", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Litiges juridiques", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Voyages", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Propriété du logement", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Activité indépendante", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("PME", COURSE_PROFILE_NICHTLEBEN_CODE)
+
+ assign_circle_to_profile("Garantie des revenus", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Retraite", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Hériter\xa0/\xa0léguer", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Épargne", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Activité indépendante", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("PME", COURSE_PROFILE_LEBEN_CODE)
+
+ assign_circle_to_profile("Santé", COURSE_PROFILE_KRANKENZUSATZ_CODE)
+
+ make_base_circle("Lancement")
+ make_base_circle("Base")
+ make_base_circle("Acquisition")
+ make_base_circle("Préparation à l’examen")
+ make_base_circle("L’examen")
+
+
+def assign_it_circles_to_profiles():
+ from vbv_lernwelt.course.models import CoursePage
+
+ try:
+ course_page = CoursePage.objects.get(
+ course_id=COURSE_VERSICHERUNGSVERMITTLERIN_IT_ID
+ )
+ except CoursePage.DoesNotExist:
+ logger.warning("Course does not exist yet")
+ return
+
+ assign_circle_to_profile = assign_circle_to_profile_curry(course_page)
+ make_base_circle = make_base_circle_curry(course_page)
+
+ assign_circle_to_profile("Veicolo", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Economia domestica", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Controversie giuridiche", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Viaggi", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Casa di proprietà", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("Attività indipendente", COURSE_PROFILE_NICHTLEBEN_CODE)
+ assign_circle_to_profile("PMI", COURSE_PROFILE_NICHTLEBEN_CODE)
+
+ assign_circle_to_profile("Protezione del reddito", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Pensionamento", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Ereditare/lasciare in eredità", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Risparmio", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("Attività indipendente", COURSE_PROFILE_LEBEN_CODE)
+ assign_circle_to_profile("PMI", COURSE_PROFILE_LEBEN_CODE)
+
+ assign_circle_to_profile("Salute", COURSE_PROFILE_KRANKENZUSATZ_CODE)
+
+ make_base_circle("Kickoff")
+ make_base_circle("Base")
+ make_base_circle("Acquisizione")
+ make_base_circle("Preparazione all'esame")
+ make_base_circle("Esame")
+
+
+def assign_circles_to_profiles():
+ assign_de_circles_to_profiles()
+ assign_fr_circles_to_profiles()
+ assign_it_circles_to_profiles()
diff --git a/server/vbv_lernwelt/learnpath/graphql/types.py b/server/vbv_lernwelt/learnpath/graphql/types.py
index 4e12cc4b..7d29e5fd 100644
--- a/server/vbv_lernwelt/learnpath/graphql/types.py
+++ b/server/vbv_lernwelt/learnpath/graphql/types.py
@@ -1,3 +1,5 @@
+import random
+
import graphene
import structlog
from graphene_django import DjangoObjectType
@@ -6,6 +8,7 @@ from vbv_lernwelt.core.utils import find_first_index
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
from vbv_lernwelt.learnpath.models import (
Circle,
+ CourseProfile,
LearningContentAssignment,
LearningContentAttendanceCourse,
LearningContentDocumentList,
@@ -299,14 +302,12 @@ class CircleObjectType(DjangoObjectType):
learning_sequences = graphene.List(
graphene.NonNull(LearningSequenceObjectType), required=True
)
+ profiles = graphene.List(graphene.String, required=True)
class Meta:
model = Circle
interfaces = (CoursePageInterface,)
- fields = [
- "description",
- "goals",
- ]
+ fields = ["description", "goals", "is_base_circle"]
def resolve_learning_sequences(self: Circle, info, **kwargs):
circle_descendants = None
@@ -335,6 +336,10 @@ class CircleObjectType(DjangoObjectType):
if descendant.specific_class == LearningSequence
]
+ @staticmethod
+ def resolve_profiles(root: Circle, info, **kwargs):
+ return root.profiles.all()
+
class TopicObjectType(DjangoObjectType):
circles = graphene.List(graphene.NonNull(CircleObjectType), required=True)
diff --git a/server/vbv_lernwelt/learnpath/migrations/0017_auto_20240711_1100.py b/server/vbv_lernwelt/learnpath/migrations/0017_auto_20240711_1100.py
new file mode 100644
index 00000000..7eba3179
--- /dev/null
+++ b/server/vbv_lernwelt/learnpath/migrations/0017_auto_20240711_1100.py
@@ -0,0 +1,48 @@
+# Generated by Django 3.2.20 on 2024-07-11 09:00
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("learnpath", "0016_remove_learningunit_feedback_user"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="CourseProfile",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("code", models.CharField(max_length=255)),
+ ],
+ ),
+ migrations.CreateModel(
+ name="CourseProfileToCircle",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ],
+ ),
+ migrations.AddField(
+ model_name="circle",
+ name="profiles",
+ field=models.ManyToManyField(
+ related_name="circles", to="learnpath.CourseProfile"
+ ),
+ ),
+ ]
diff --git a/server/vbv_lernwelt/learnpath/migrations/0018_alter_courseprofile_options_circle_is_base_circle_and_more.py b/server/vbv_lernwelt/learnpath/migrations/0018_alter_courseprofile_options_circle_is_base_circle_and_more.py
new file mode 100644
index 00000000..8d9f3b72
--- /dev/null
+++ b/server/vbv_lernwelt/learnpath/migrations/0018_alter_courseprofile_options_circle_is_base_circle_and_more.py
@@ -0,0 +1,34 @@
+# Generated by Django 4.2.13 on 2024-07-30 07:03
+
+import modelcluster.fields
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("learnpath", "0017_auto_20240711_1100"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="courseprofile",
+ options={"ordering": ["order"]},
+ ),
+ migrations.AddField(
+ model_name="circle",
+ name="is_base_circle",
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name="courseprofile",
+ name="order",
+ field=models.IntegerField(default=999),
+ ),
+ migrations.AlterField(
+ model_name="circle",
+ name="profiles",
+ field=modelcluster.fields.ParentalManyToManyField(
+ related_name="circles", to="learnpath.courseprofile"
+ ),
+ ),
+ ]
diff --git a/server/vbv_lernwelt/learnpath/migrations/0019_auto_20240730_0904.py b/server/vbv_lernwelt/learnpath/migrations/0019_auto_20240730_0904.py
new file mode 100644
index 00000000..46464f1e
--- /dev/null
+++ b/server/vbv_lernwelt/learnpath/migrations/0019_auto_20240730_0904.py
@@ -0,0 +1,20 @@
+# Generated by Django 4.2.13 on 2024-07-30 07:04
+
+from django.db import migrations
+
+from vbv_lernwelt.learnpath.creators import create_course_profiles
+
+
+def migrate(apps, schema_editor):
+ create_course_profiles()
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ (
+ "learnpath",
+ "0018_alter_courseprofile_options_circle_is_base_circle_and_more",
+ ),
+ ]
+
+ operations = [migrations.RunPython(migrate)]
diff --git a/server/vbv_lernwelt/learnpath/migrations/0020_auto_20240730_0905.py b/server/vbv_lernwelt/learnpath/migrations/0020_auto_20240730_0905.py
new file mode 100644
index 00000000..edac10fc
--- /dev/null
+++ b/server/vbv_lernwelt/learnpath/migrations/0020_auto_20240730_0905.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.2.13 on 2024-07-30 07:05
+
+from django.db import migrations
+
+from vbv_lernwelt.learnpath.creators import assign_circles_to_profiles
+
+
+def migrate(apps, schema_editor):
+ assign_circles_to_profiles()
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("learnpath", "0019_auto_20240730_0904"),
+ ]
+
+ operations = [migrations.RunPython(migrate)]
diff --git a/server/vbv_lernwelt/learnpath/models.py b/server/vbv_lernwelt/learnpath/models.py
index 20d7d517..a0a76f03 100644
--- a/server/vbv_lernwelt/learnpath/models.py
+++ b/server/vbv_lernwelt/learnpath/models.py
@@ -3,6 +3,7 @@ from typing import Tuple
from django.db import models
from django.utils.text import slugify
+from modelcluster.models import ParentalManyToManyField
from wagtail.admin.panels import FieldPanel, PageChooserPanel
from wagtail.fields import RichTextField, StreamField
from wagtail.models import Page
@@ -66,6 +67,25 @@ class Topic(CourseBasePage):
return f"{self.title}"
+class CourseProfile(models.Model):
+ code = models.CharField(max_length=255)
+ order = models.IntegerField(default=999)
+
+ def __str__(self) -> str:
+ return self.code
+
+ class Meta:
+ ordering = [
+ "order",
+ ]
+
+
+class CourseProfileToCircle(models.Model):
+ # this connects the course profile to a circle, because a circle can be in multiple profiles
+ # todo: to we even need a through model?
+ pass
+
+
class Circle(CourseBasePage):
parent_page_types = ["learnpath.LearningPath"]
subpage_types = [
@@ -95,9 +115,25 @@ class Circle(CourseBasePage):
goals = RichTextField(features=DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER)
+ profiles = ParentalManyToManyField(CourseProfile, related_name="circles")
+
+ # base circles do never belong to a course profile and should also get displayed no matter what profile is chosen
+ is_base_circle = models.BooleanField(default=False)
+
+ # profile = models.ForeignKey(
+ # ApprovalProfile,
+ # null=True,
+ # blank=True,
+ # on_delete=models.SET_NULL,
+ # related_name="circles",
+ # help_text="Zulassungsprofil",
+ # )
+
content_panels = Page.content_panels + [
FieldPanel("description"),
FieldPanel("goals"),
+ FieldPanel("is_base_circle"),
+ FieldPanel("profiles"),
]
def get_frontend_url(self):
diff --git a/server/vbv_lernwelt/learnpath/serializers.py b/server/vbv_lernwelt/learnpath/serializers.py
index 3f6a3255..b03a7dbf 100644
--- a/server/vbv_lernwelt/learnpath/serializers.py
+++ b/server/vbv_lernwelt/learnpath/serializers.py
@@ -1,3 +1,4 @@
+from rest_framework import serializers
from rest_framework.fields import SerializerMethodField
from vbv_lernwelt.competence.serializers import (
@@ -6,6 +7,7 @@ from vbv_lernwelt.competence.serializers import (
from vbv_lernwelt.core.utils import get_django_content_type
from vbv_lernwelt.course.serializer_helpers import get_course_serializer_class
from vbv_lernwelt.learnpath.models import (
+ CourseProfile,
LearningContentAssignment,
LearningContentEdoniqTest,
LearningUnit,
@@ -98,3 +100,9 @@ class LearningContentAssignmentSerializer(
}
except Exception:
return None
+
+
+class CourseProfileSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = CourseProfile
+ fields = ["id", "code"]
diff --git a/server/vbv_lernwelt/media_files/migrations/0002_alter_contentimagerendition_file_and_more.py b/server/vbv_lernwelt/media_files/migrations/0002_alter_contentimagerendition_file_and_more.py
new file mode 100644
index 00000000..bf01ce1c
--- /dev/null
+++ b/server/vbv_lernwelt/media_files/migrations/0002_alter_contentimagerendition_file_and_more.py
@@ -0,0 +1,33 @@
+# Generated by Django 4.2.13 on 2024-07-22 19:45
+
+import wagtail.images.models
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("media_files", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="contentimagerendition",
+ name="file",
+ field=wagtail.images.models.WagtailImageField(
+ height_field="height",
+ storage=wagtail.images.models.get_rendition_storage,
+ upload_to=wagtail.images.models.get_rendition_upload_to,
+ width_field="width",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="userimagerendition",
+ name="file",
+ field=wagtail.images.models.WagtailImageField(
+ height_field="height",
+ storage=wagtail.images.models.get_rendition_storage,
+ upload_to=wagtail.images.models.get_rendition_upload_to,
+ width_field="width",
+ ),
+ ),
+ ]
diff --git a/server/vbv_lernwelt/shop/migrations/0017_checkoutinformation_chosen_profile.py b/server/vbv_lernwelt/shop/migrations/0017_checkoutinformation_chosen_profile.py
new file mode 100644
index 00000000..091915d3
--- /dev/null
+++ b/server/vbv_lernwelt/shop/migrations/0017_checkoutinformation_chosen_profile.py
@@ -0,0 +1,27 @@
+# Generated by Django 4.2.13 on 2024-07-30 07:03
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ (
+ "learnpath",
+ "0018_alter_courseprofile_options_circle_is_base_circle_and_more",
+ ),
+ ("shop", "0016_alter_checkoutinformation_refno2"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="checkoutinformation",
+ name="chosen_profile",
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ to="learnpath.courseprofile",
+ ),
+ ),
+ ]
diff --git a/server/vbv_lernwelt/shop/models.py b/server/vbv_lernwelt/shop/models.py
index 04694fc6..5a6da1ac 100644
--- a/server/vbv_lernwelt/shop/models.py
+++ b/server/vbv_lernwelt/shop/models.py
@@ -106,7 +106,9 @@ class CheckoutInformation(models.Model):
null=True,
blank=True,
)
-
+ chosen_profile = models.ForeignKey(
+ "learnpath.CourseProfile", on_delete=models.SET_NULL, null=True, blank=True
+ )
# webhook metadata
webhook_history = models.JSONField(default=list)
diff --git a/server/vbv_lernwelt/shop/tests/test_checkout_api.py b/server/vbv_lernwelt/shop/tests/test_checkout_api.py
index f5f46b37..23a8bac2 100644
--- a/server/vbv_lernwelt/shop/tests/test_checkout_api.py
+++ b/server/vbv_lernwelt/shop/tests/test_checkout_api.py
@@ -6,6 +6,8 @@ from rest_framework.test import APITestCase
from vbv_lernwelt.core.admin import User
from vbv_lernwelt.core.model_utils import add_countries
+from vbv_lernwelt.learnpath.consts import COURSE_PROFILE_ALL_CODE, COURSE_PROFILE_ALL_ID
+from vbv_lernwelt.learnpath.models import CourseProfile
from vbv_lernwelt.shop.const import VV_DE_PRODUCT_SKU
from vbv_lernwelt.shop.models import CheckoutInformation, CheckoutState, Product
from vbv_lernwelt.shop.services import InitTransactionException
@@ -50,6 +52,10 @@ class CheckoutAPITestCase(APITestCase):
is_active=True,
)
+ CourseProfile.objects.get_or_create(
+ id=COURSE_PROFILE_ALL_ID, code=COURSE_PROFILE_ALL_CODE
+ )
+
self.client.login(username=USER_USERNAME, password=USER_PASSWORD)
add_countries(small_set=True)
diff --git a/server/vbv_lernwelt/shop/views.py b/server/vbv_lernwelt/shop/views.py
index a245520a..58591f49 100644
--- a/server/vbv_lernwelt/shop/views.py
+++ b/server/vbv_lernwelt/shop/views.py
@@ -8,6 +8,8 @@ from rest_framework.permissions import IsAuthenticated
from sentry_sdk import capture_exception
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
+from vbv_lernwelt.learnpath.consts import COURSE_PROFILE_ALL_ID
+from vbv_lernwelt.learnpath.models import CourseProfile
from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email
from vbv_lernwelt.shop.const import (
VV_DE_PRODUCT_SKU,
@@ -92,6 +94,7 @@ def checkout_vv(request):
sku = request.data["product"]
base_redirect_url = request.data["redirect_url"]
+ chosen_profile_id = request.data.get("chosen_profile", COURSE_PROFILE_ALL_ID)
log.info("Checkout requested: sku", user_id=request.user.id, sku=sku)
@@ -106,6 +109,11 @@ def checkout_vv(request):
),
)
+ try:
+ chosen_profile = CourseProfile.objects.get(id=chosen_profile_id)
+ except CourseProfile.DoesNotExist:
+ chosen_profile = CourseProfile.objects.get(id=COURSE_PROFILE_ALL_ID)
+
checkouts = CheckoutInformation.objects.filter(
user=request.user,
product_sku=sku,
@@ -151,6 +159,7 @@ def checkout_vv(request):
"device_fingerprint_session_key", ""
),
# address
+ chosen_profile=chosen_profile,
**request.data["address"],
)
@@ -257,9 +266,11 @@ def create_vv_course_session_user(checkout_info: CheckoutInformation):
_, created = CourseSessionUser.objects.get_or_create(
user=checkout_info.user,
role=CourseSessionUser.Role.MEMBER,
+ chosen_profile=checkout_info.chosen_profile,
course_session=CourseSession.objects.get(
id=PRODUCT_SKU_TO_COURSE_SESSION_ID[checkout_info.product_sku]
),
+ # chosen_profile=bla,
)
if created: