diff --git a/client/src/components/circle/CircleDiagram.vue b/client/src/components/circle/CircleDiagram.vue
index c40ec640..4845a4f2 100644
--- a/client/src/components/circle/CircleDiagram.vue
+++ b/client/src/components/circle/CircleDiagram.vue
@@ -1,10 +1,10 @@
@@ -17,7 +17,7 @@ const props = defineProps<{
-
Überblick: Circle "{{ circleData.title }}"
+ Überblick: Circle "{{ circle.title }}"
Hier zeigen wir dir, was du in diesem Circle lernen wirst.
@@ -25,7 +25,7 @@ const props = defineProps<{
Du wirst in der Lage sein, ...
- -
+
-
{{ goal.value }}
@@ -38,7 +38,7 @@ const props = defineProps<{
-
diff --git a/client/src/components/circle/LearningSequence.vue b/client/src/components/circle/LearningSequence.vue
index 91c2b5c5..a2578260 100644
--- a/client/src/components/circle/LearningSequence.vue
+++ b/client/src/components/circle/LearningSequence.vue
@@ -15,10 +15,8 @@ function toggleCompleted(learningContent: LearningContent) {
}
const someFinished = computed(() => {
- if (props.learningSequence) {
- return circleStore.flatChildren.filter((lc) => {
- return lc.completed && lc.parentLearningSequence?.translation_key === props.learningSequence.translation_key;
- }).length > 0;
+ if (props.learningSequence && circleStore.circle) {
+ return circleStore.circle.someFinishedInLearningSequence(props.learningSequence.translation_key);
}
return false;
diff --git a/client/src/services/circle.ts b/client/src/services/circle.ts
index 3cb8c462..acb460a9 100644
--- a/client/src/services/circle.ts
+++ b/client/src/services/circle.ts
@@ -1,4 +1,13 @@
-import type {CircleChild, LearningContent, LearningSequence, LearningUnit} from '@/types';
+import type {
+ CircleChild,
+ CircleCompletion,
+ CircleGoal,
+ CircleInterface,
+ CircleJobSituation,
+ LearningContent,
+ LearningSequence,
+ LearningUnit
+} from '@/types';
function _createEmptyLearningUnit(parentLearningSequence: LearningSequence): LearningUnit {
@@ -98,3 +107,74 @@ export function parseLearningSequences (children: CircleChild[]): LearningSequen
return result;
}
+export class Circle implements CircleInterface {
+ readonly type = 'learnpath.Circle';
+ readonly learningSequences: LearningSequence[];
+ readonly completed: boolean;
+
+ constructor(
+ public readonly id: number,
+ public readonly slug: string,
+ public readonly title: string,
+ public readonly translation_key: string,
+ public description: string,
+ public children: CircleChild[],
+ public goals: CircleGoal[],
+ public job_situations: CircleJobSituation[],
+ ) {
+ this.learningSequences = parseLearningSequences(this.children);
+ this.completed = false;
+ }
+
+ public static fromJson(json: any): Circle {
+ // TODO add error checking when the data does not conform to the schema
+ return new Circle(
+ json.id,
+ json.slug,
+ json.title,
+ json.translation_key,
+ json.description,
+ json.children,
+ json.goals,
+ json.job_situations,
+ )
+ }
+
+ public get flatChildren(): CircleChild[] {
+ const result: CircleChild[] = [];
+ this.learningSequences.forEach((learningSequence) => {
+ learningSequence.learningUnits.forEach((learningUnit) => {
+ learningUnit.children.forEach((learningUnitQuestion) => {
+ result.push(learningUnitQuestion);
+ })
+ learningUnit.learningContents.forEach((learningContent) => {
+ result.push(learningContent);
+ });
+ });
+ });
+ return result;
+ }
+
+ public someFinishedInLearningSequence(translationKey: string): boolean {
+ if (translationKey) {
+ return this.flatChildren.filter((lc) => {
+ return lc.completed && lc.parentLearningSequence?.translation_key === translationKey;
+ }).length > 0;
+ }
+
+ return false;
+ }
+
+ public parseCompletionData(completionData: CircleCompletion[]) {
+ this.flatChildren.forEach((page) => {
+ const pageIndex = completionData.findIndex((e) => {
+ return e.page_key === page.translation_key;
+ });
+ if (pageIndex >= 0) {
+ page.completed = completionData[pageIndex].completed;
+ } else {
+ page.completed = undefined;
+ }
+ });
+ }
+}
diff --git a/client/src/stores/circle.ts b/client/src/stores/circle.ts
index cd5b1917..a3474604 100644
--- a/client/src/stores/circle.ts
+++ b/client/src/stores/circle.ts
@@ -2,14 +2,13 @@ import * as log from 'loglevel';
import {defineStore} from 'pinia'
-import type {Circle, CircleChild, CircleCompletion, LearningContent, LearningUnit, LearningUnitQuestion} from '@/types'
+import type {LearningContent, LearningUnit, LearningUnitQuestion} from '@/types'
+import {Circle} from '@/services/circle'
import {itGet, itPost} from '@/fetchHelpers';
-import {parseLearningSequences} from '@/services/circle';
import {useAppStore} from '@/stores/app';
export type CircleStoreState = {
- circleData: Circle;
- completionData: CircleCompletion[];
+ circle: Circle | undefined;
currentLearningContent: LearningContent | undefined;
currentSelfEvaluation: LearningUnit | undefined;
page: 'INDEX' | 'OVERVIEW' | 'LEARNING_CONTENT' | 'SELF_EVALUATION';
@@ -19,7 +18,7 @@ export const useCircleStore = defineStore({
id: 'circle',
state: () => {
return {
- circleData: {},
+ circle: undefined,
completionData: {},
currentLearningContent: undefined,
currentSelfEvaluation: undefined,
@@ -28,27 +27,15 @@ export const useCircleStore = defineStore({
},
getters: {
flatChildren: (state) => {
- const result:CircleChild[] = [];
- state.circleData.learningSequences.forEach((learningSequence) => {
- learningSequence.learningUnits.forEach((learningUnit) => {
- learningUnit.children.forEach((learningUnitQuestion) => {
- result.push(learningUnitQuestion);
- })
- learningUnit.learningContents.forEach((learningContent) => {
- result.push(learningContent);
- });
- });
- });
- return result;
},
},
actions: {
async loadCircle(slug: string) {
try {
- this.circleData = await itGet(`/learnpath/api/circle/${slug}/`);
- this.circleData.learningSequences = parseLearningSequences(this.circleData.children);
- this.completionData = await itGet(`/api/completion/circle/${this.circleData.translation_key}/`);
- this.parseCompletionData();
+ const circleData = await itGet(`/learnpath/api/circle/${slug}/`);
+ this.circle = Circle.fromJson(circleData);
+ const completionData = await itGet(`/api/completion/circle/${this.circle.translation_key}/`);
+ this.circle.parseCompletionData(completionData);
} catch (error) {
log.error(error);
return error
@@ -57,28 +44,18 @@ export const useCircleStore = defineStore({
async markCompletion(page: LearningContent | LearningUnitQuestion, flag = true) {
try {
page.completed = flag;
- this.completionData = await itPost('/api/completion/circle/mark/', {
+ const completionData = await itPost('/api/completion/circle/mark/', {
page_key: page.translation_key,
completed: page.completed,
});
- this.parseCompletionData();
+ if (this.circle) {
+ this.circle.parseCompletionData(completionData);
+ }
} catch (error) {
log.error(error);
return error
}
},
- parseCompletionData() {
- this.flatChildren.forEach((page) => {
- const pageIndex = this.completionData.findIndex((e) => {
- return e.page_key === page.translation_key;
- });
- if (pageIndex >= 0) {
- page.completed = this.completionData[pageIndex].completed;
- } else {
- page.completed = undefined;
- }
- });
- },
openLearningContent(learningContent: LearningContent) {
this.currentLearningContent = learningContent;
const appStore = useAppStore();
diff --git a/client/src/types.ts b/client/src/types.ts
index 006b1d25..01dbae35 100644
--- a/client/src/types.ts
+++ b/client/src/types.ts
@@ -1,3 +1,5 @@
+import {parseLearningSequences} from '@/services/circle';
+
export interface LearningContentBlock {
type: 'web-based-training' | 'competence' | 'exercise' | 'knowledge';
value: {
@@ -46,10 +48,10 @@ export interface CircleJobSituation {
}
export interface LearningWagtailPage {
- id: number;
- title: string;
- slug: string;
- translation_key: string;
+ readonly id: number;
+ readonly title: string;
+ readonly slug: string;
+ readonly translation_key: string;
completed?: boolean;
}
@@ -105,15 +107,17 @@ export interface CircleCompletion {
json_data: any;
}
-export interface Circle extends LearningWagtailPage {
- type: 'learnpath.Circle';
- children: CircleChild[];
- description: string;
+export interface CircleInterface extends LearningWagtailPage {
+ readonly type: 'learnpath.Circle';
+ readonly children: CircleChild[];
+ readonly description: string;
+ readonly goals: CircleGoal[];
+ readonly job_situations: CircleJobSituation[];
learningSequences: LearningSequence[];
- goals: CircleGoal[];
- job_situations: CircleJobSituation[];
}
+
+
export interface CircleDiagramData {
index: number
title: string
diff --git a/client/src/views/CircleView.vue b/client/src/views/CircleView.vue
index 7d07b4f2..c310d8e0 100644
--- a/client/src/views/CircleView.vue
+++ b/client/src/views/CircleView.vue
@@ -35,15 +35,15 @@ onMounted(async () => {
-
+
- {{ circleStore.circleData.title }}
+ {{ circleStore.circle.title }}
-
+
@@ -65,7 +65,7 @@ onMounted(async () => {
Das lernst du in diesem Circle.
- {{ circleStore.circleData.description }}
+ {{ circleStore.circle.description }}
@@ -83,12 +83,11 @@ onMounted(async () => {