VBV-80: Refactor next learning content
This commit is contained in:
parent
97f01e0a08
commit
a32c8ccbff
|
|
@ -15,6 +15,7 @@
|
|||
"@headlessui/vue": "^1.6.7",
|
||||
"axios": "^0.26.1",
|
||||
"d3": "^7.6.1",
|
||||
"lodash": "^4.17.21",
|
||||
"loglevel": "^1.8.0",
|
||||
"pinia": "^2.0.21",
|
||||
"vue": "^3.2.38",
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ function _createEmptyLearningUnit(parentLearningSequence: LearningSequence): Lea
|
|||
}
|
||||
}
|
||||
|
||||
export function parseLearningSequences (children: CircleChild[]): LearningSequence[] {
|
||||
export function parseLearningSequences (circle: Circle, children: CircleChild[]): LearningSequence[] {
|
||||
let learningSequence:LearningSequence | undefined;
|
||||
let learningUnit:LearningUnit | undefined;
|
||||
let learningContent:LearningContent | undefined;
|
||||
|
|
@ -69,6 +69,7 @@ export function parseLearningSequences (children: CircleChild[]): LearningSequen
|
|||
previousLearningContent = learningContent;
|
||||
|
||||
learningContent = Object.assign(child, {
|
||||
parentCircle: circle,
|
||||
parentLearningSequence: learningSequence,
|
||||
parentLearningUnit: learningUnit,
|
||||
previousLearningContent: previousLearningContent,
|
||||
|
|
@ -111,6 +112,9 @@ export class Circle implements LearningWagtailPage {
|
|||
readonly learningSequences: LearningSequence[];
|
||||
readonly completed: boolean;
|
||||
|
||||
nextCircle?: Circle;
|
||||
previousCircle?: Circle;
|
||||
|
||||
constructor(
|
||||
public readonly id: number,
|
||||
public readonly slug: string,
|
||||
|
|
@ -121,7 +125,7 @@ export class Circle implements LearningWagtailPage {
|
|||
public goals: CircleGoal[],
|
||||
public job_situations: CircleJobSituation[],
|
||||
) {
|
||||
this.learningSequences = parseLearningSequences(this.children);
|
||||
this.learningSequences = parseLearningSequences(this, this.children);
|
||||
this.completed = false;
|
||||
}
|
||||
|
||||
|
|
@ -154,6 +158,18 @@ export class Circle implements LearningWagtailPage {
|
|||
return result;
|
||||
}
|
||||
|
||||
public get flatLearningContents(): LearningContent[] {
|
||||
const result: LearningContent[] = [];
|
||||
this.learningSequences.forEach((learningSequence) => {
|
||||
learningSequence.learningUnits.forEach((learningUnit) => {
|
||||
learningUnit.learningContents.forEach((learningContent) => {
|
||||
result.push(learningContent);
|
||||
});
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public someFinishedInLearningSequence(translationKey: string): boolean {
|
||||
if (translationKey) {
|
||||
return this.flatChildren.filter((lc) => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,19 @@
|
|||
import type { LearningPathChild, LearningWagtailPage, Topic } from '@/types'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import type { CircleCompletion, LearningContent, LearningPathChild, LearningWagtailPage, Topic } from '@/types'
|
||||
import { Circle } from '@/services/circle'
|
||||
|
||||
function getLastCompleted(learningPathKey: string, completionData: CircleCompletion[]) {
|
||||
return _.orderBy(completionData, ['updated_at'], 'desc').find((c: CircleCompletion) => {
|
||||
return c.completed && c.learning_path_key === learningPathKey && c.page_type === 'learnpath.LearningContent'
|
||||
})
|
||||
}
|
||||
|
||||
export class LearningPath implements LearningWagtailPage {
|
||||
readonly type = 'learnpath.LearningPath'
|
||||
public topics: Topic[]
|
||||
public circles: Circle[]
|
||||
public nextLearningContent?: LearningContent
|
||||
|
||||
public static fromJson(json: any, completionData: any): LearningPath {
|
||||
return new LearningPath(json.id, json.slug, json.title, json.translation_key, json.children, completionData)
|
||||
|
|
@ -37,6 +46,11 @@ export class LearningPath implements LearningWagtailPage {
|
|||
if (topic) {
|
||||
topic.circles.push(circle)
|
||||
}
|
||||
|
||||
circle.previousCircle = this.circles[this.circles.length - 1]
|
||||
if (circle.previousCircle) {
|
||||
circle.previousCircle.nextCircle = circle
|
||||
}
|
||||
this.circles.push(circle)
|
||||
}
|
||||
})
|
||||
|
|
@ -44,5 +58,26 @@ export class LearningPath implements LearningWagtailPage {
|
|||
if (topic) {
|
||||
this.topics.push(topic)
|
||||
}
|
||||
|
||||
// find next learning content
|
||||
const lastCompletedLearningContent = getLastCompleted(this.translation_key, completionData);
|
||||
|
||||
if (lastCompletedLearningContent) {
|
||||
const lastCircle = this.circles.find(circle => circle.translation_key === lastCompletedLearningContent.circle_key);
|
||||
if (lastCircle) {
|
||||
const lastLearningContent = lastCircle.flatLearningContents.find(learningContent => learningContent.translation_key === lastCompletedLearningContent.page_key);
|
||||
if (lastLearningContent && lastLearningContent.nextLearningContent) {
|
||||
this.nextLearningContent = lastLearningContent.nextLearningContent;
|
||||
} else {
|
||||
if (lastCircle.nextCircle) {
|
||||
this.nextLearningContent = lastCircle.nextCircle.flatLearningContents[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.nextLearningContent = this.circles[0].flatLearningContents[0];
|
||||
}
|
||||
|
||||
console.log('################# ', this.nextLearningContent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,67 +3,16 @@ import * as log from 'loglevel'
|
|||
import { defineStore } from 'pinia'
|
||||
import { itGet } from '@/fetchHelpers'
|
||||
import { LearningPath } from '@/services/learningPath'
|
||||
import {defineStore} from 'pinia'
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import type {LearningPath, Topic} from '@/types'
|
||||
import {itGet} from '@/fetchHelpers';
|
||||
import {Circle} from '@/services/circle';
|
||||
import learningPathDiagram from "@/components/circle/LearningPathDiagram.vue";
|
||||
|
||||
export type LearningPathStoreState = {
|
||||
learningPath: LearningPath | undefined
|
||||
}
|
||||
|
||||
|
||||
function getLastCompleted(completionData: any) {
|
||||
return _.filter(_.orderBy(completionData, ['updated_at'], 'desc'), c =>{return c.completed && c.page_type === "learnpath.LearningContent" })[0]
|
||||
}
|
||||
|
||||
|
||||
function getFirstLearningContent(lastCopleted, learningPathData) {
|
||||
const circles = _.filter(learningPathData.children, {'type': 'learnpath.Circle'})
|
||||
|
||||
let currentCircle = Circle.fromJson(circles[0])
|
||||
const currentLearningUnit = currentCircle.flatChildren[0]
|
||||
let currentLearningSequence = currentLearningUnit.parentLearningSequence
|
||||
return [currentCircle, currentLearningSequence, currentLearningUnit]
|
||||
}
|
||||
|
||||
function getNextLearningContent(lastCopleted, learningPathData) {
|
||||
|
||||
let currentCircle, currentLearningSequence, currentLearningUnit
|
||||
|
||||
currentLearningUnit = getFirstLearningContent(lastCopleted, learningPathData)
|
||||
|
||||
if (lastCopleted) {
|
||||
const circles = _.filter(learningPathData.children, {'type': 'learnpath.Circle'})
|
||||
_.forEach(circles, circle => {
|
||||
_.forEach(Circle.fromJson(circle).learningSequences, learningSequence => {
|
||||
_.forEach(learningSequence.learningUnits, learningUnit => {
|
||||
_.forEach(learningUnit.learningContents, content => {
|
||||
if (lastCopleted.page_key === content.translation_key) {
|
||||
currentCircle = Circle.fromJson(circle)
|
||||
currentLearningSequence = learningSequence
|
||||
currentLearningUnit = content
|
||||
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
currentLearningUnit = [currentCircle, currentLearningSequence, currentLearningUnit]
|
||||
}
|
||||
return currentLearningUnit
|
||||
}
|
||||
|
||||
|
||||
export const useLearningPathStore = defineStore({
|
||||
id: 'learningPath',
|
||||
state: () => {
|
||||
return {
|
||||
learningPath: undefined,
|
||||
|
||||
} as LearningPathStoreState;
|
||||
},
|
||||
getters: {},
|
||||
|
|
@ -76,19 +25,7 @@ export const useLearningPathStore = defineStore({
|
|||
const learningPathData = await itGet(`/learnpath/api/page/${slug}/`);
|
||||
const completionData = await itGet(`/api/completion/learning_path/${learningPathData.translation_key}/`);
|
||||
|
||||
this.learningPath = learningPathData;
|
||||
|
||||
|
||||
if (learningPathData) {
|
||||
this.learningPath.lastCompleted = getLastCompleted(completionData)
|
||||
const nextLearningContent = getNextLearningContent(this.learningPath.lastCompleted, learningPathData)
|
||||
|
||||
console.log('nextLearningContent', nextLearningContent)
|
||||
this.learningPath.nextCircle = nextLearningContent[0]
|
||||
this.learningPath.nextLearningSequence = nextLearningContent[1]
|
||||
this.learningPath.nextLearningUnit = nextLearningContent[2]
|
||||
|
||||
|
||||
this.learningPath = LearningPath.fromJson(learningPathData, completionData);
|
||||
}
|
||||
return this.learningPath;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ export interface LearningContent extends LearningWagtailPage {
|
|||
type: 'learnpath.LearningContent';
|
||||
minutes: number;
|
||||
contents: (LearningContentBlock | VideoBlock | PodcastBlock | DocumentBlock)[];
|
||||
parentCircle: Circle;
|
||||
parentLearningSequence?: LearningSequence;
|
||||
parentLearningUnit?: LearningUnit;
|
||||
nextLearningContent?: LearningContent;
|
||||
|
|
@ -111,6 +112,7 @@ export interface CircleCompletion {
|
|||
page_key: string;
|
||||
page_type: string;
|
||||
circle_key: string;
|
||||
learning_path_key: string;
|
||||
completed: boolean;
|
||||
json_data: any;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import * as log from 'loglevel';
|
||||
|
||||
import {computed, onMounted} from 'vue'
|
||||
import {onMounted} from 'vue'
|
||||
import {useLearningPathStore} from '@/stores/learningPath';
|
||||
import {useUserStore} from '@/stores/user';
|
||||
|
||||
|
|
@ -20,10 +20,6 @@ const learningPathStore = useLearningPathStore();
|
|||
const userStore = useUserStore();
|
||||
|
||||
|
||||
const continueRoute = computed(() => {
|
||||
return "/circle/" + learningPathStore.learningPath.nextCircle.slug + "/";
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
log.info('LearningPathView mounted');
|
||||
await learningPathStore.loadLearningPath(props.learningPathSlug);
|
||||
|
|
@ -72,10 +68,14 @@ onMounted(async () => {
|
|||
|
||||
</p>
|
||||
</div>
|
||||
<div class="p-8 flex-2" v-if="learningPathStore.learningPath.nextCircle" translate>
|
||||
<div class="p-8 flex-2" v-if="learningPathStore.learningPath.nextLearningContent" translate>
|
||||
Nächster Schirtt
|
||||
<h3>{{ learningPathStore.learningPath.nextCircle.title }}: {{ learningPathStore.learningPath.nextLearningSequence.title }}</h3>
|
||||
<router-link class="mt-4 btn-blue" v-bind:to="this.continueRoute" translate>
|
||||
<h3>{{ learningPathStore.learningPath.nextLearningContent.parentCircle.title }}: {{ learningPathStore.learningPath.nextLearningContent.parentLearningSequence.title }}</h3>
|
||||
<router-link
|
||||
class="mt-4 btn-blue"
|
||||
:to="`/circle/${learningPathStore.learningPath.nextLearningContent.parentCircle.slug}/`"
|
||||
translate
|
||||
>
|
||||
Los geht's
|
||||
</router-link>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default defineConfig(({ mode }) => {
|
|||
},
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'happy-dom',
|
||||
environment: 'jsdom',
|
||||
},
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue