Add ts types for circle data
This commit is contained in:
parent
b6f26eaa61
commit
c1a7f4551d
|
|
@ -13,7 +13,6 @@ module.exports = {
|
||||||
'vue/setup-compiler-macros': true
|
'vue/setup-compiler-macros': true
|
||||||
},
|
},
|
||||||
'rules': {
|
'rules': {
|
||||||
'quotes': ['error', 'single'],
|
|
||||||
'@typescript-eslint/no-unused-vars': ['warn'],
|
'@typescript-eslint/no-unused-vars': ['warn'],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
import {describe, it} from 'vitest'
|
||||||
|
import type {Circle} from '../circle';
|
||||||
|
import {parseLearningSequences} from '../circle';
|
||||||
|
|
||||||
|
describe('circleService.parseLearningSequences', () => {
|
||||||
|
it('can parse learning sequences from api response', () => {
|
||||||
|
const input = {
|
||||||
|
"id": 10,
|
||||||
|
"title": "Analyse",
|
||||||
|
"slug": "analyse",
|
||||||
|
"type": "learnpath.Circle",
|
||||||
|
"translation_key": "c9832aaf-02b2-47af-baeb-bde60d8ec1f5",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": 18,
|
||||||
|
"title": "Anwenden",
|
||||||
|
"slug": "anwenden",
|
||||||
|
"type": "learnpath.LearningSequence",
|
||||||
|
"translation_key": "2e4c431a-9602-4398-ad18-20dd4bb189fa",
|
||||||
|
"icon": "it-icon-ls-apply"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 19,
|
||||||
|
"title": "Prämien einsparen",
|
||||||
|
"slug": "pramien-einsparen",
|
||||||
|
"type": "learnpath.LearningUnit",
|
||||||
|
"translation_key": "75c1f31a-ae25-4d9c-9206-a4e7fdae8c13",
|
||||||
|
"questions": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 20,
|
||||||
|
"title": "Versicherungsbedarf für Familien",
|
||||||
|
"slug": "versicherungsbedarf-für-familien",
|
||||||
|
"type": "learnpath.LearningContent",
|
||||||
|
"translation_key": "2a422da3-a3ad-468a-831e-9141c122ffef",
|
||||||
|
"minutes": 60,
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"type": "exercise",
|
||||||
|
"value": {
|
||||||
|
"description": "Beispiel Aufgabe"
|
||||||
|
},
|
||||||
|
"id": "ee0bcef7-702b-42f3-a891-88a0332fce6f"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 21,
|
||||||
|
"title": "Alles klar?",
|
||||||
|
"slug": "alles-klar",
|
||||||
|
"type": "learnpath.LearningContent",
|
||||||
|
"translation_key": "7dc9d96d-07f9-4b9f-bec1-43ba67cf9010",
|
||||||
|
"minutes": 60,
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"type": "exercise",
|
||||||
|
"value": {
|
||||||
|
"description": "Beispiel Aufgabe"
|
||||||
|
},
|
||||||
|
"id": "a556ebb2-f902-4d78-9b76-38b7933118b8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 22,
|
||||||
|
"title": "Sich selbständig machen",
|
||||||
|
"slug": "sich-selbstandig-machen",
|
||||||
|
"type": "learnpath.LearningUnit",
|
||||||
|
"translation_key": "c40d5266-3c94-4b9b-8469-9ac6b32a6231",
|
||||||
|
"questions": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23,
|
||||||
|
"title": "GmbH oder AG",
|
||||||
|
"slug": "gmbh-oder-ag",
|
||||||
|
"type": "learnpath.LearningContent",
|
||||||
|
"translation_key": "59331843-9f52-4b41-9cd1-2293a8d90064",
|
||||||
|
"minutes": 120,
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"type": "video",
|
||||||
|
"value": {
|
||||||
|
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam",
|
||||||
|
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
||||||
|
},
|
||||||
|
"id": "a4974834-f404-4fb8-af94-a24c6db56bb8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 24,
|
||||||
|
"title": "Tiertherapie Patrizia Feller",
|
||||||
|
"slug": "tiertherapie-patrizia-feller",
|
||||||
|
"type": "learnpath.LearningContent",
|
||||||
|
"translation_key": "13f6d661-1d10-4b59-b8e5-01fcec47a38f",
|
||||||
|
"minutes": 120,
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"type": "exercise",
|
||||||
|
"value": {
|
||||||
|
"description": "Beispiel Aufgabe"
|
||||||
|
},
|
||||||
|
"id": "5947c947-8656-44b5-826c-1787057c2df2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 25,
|
||||||
|
"title": "Auto verkaufen",
|
||||||
|
"slug": "auto-verkaufen",
|
||||||
|
"type": "learnpath.LearningUnit",
|
||||||
|
"translation_key": "3b42e514-0bbe-4c23-9c88-3f5263e47cf9",
|
||||||
|
"questions": []
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"description": "Nach dem Gespräch werten sie die Analyse aus...",
|
||||||
|
"job_situations": [],
|
||||||
|
"goals": [],
|
||||||
|
"experts": []
|
||||||
|
} as Circle;
|
||||||
|
|
||||||
|
const learningSequences = parseLearningSequences(input.children);
|
||||||
|
|
||||||
|
expect(learningSequences.length).toBe(4);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
export interface LearningContentBlock {
|
||||||
|
type: 'video' | 'web-based-training' | 'podcast' | 'competence' | 'exercise' | 'document' | 'knowledge';
|
||||||
|
value: {
|
||||||
|
description: string;
|
||||||
|
url?: string;
|
||||||
|
},
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface CircleGoal {
|
||||||
|
type: 'goal';
|
||||||
|
value: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface CircleJobSituation {
|
||||||
|
type: 'job_situation';
|
||||||
|
value: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface LearningWagtailPage {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
slug: string;
|
||||||
|
translation_key: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface LearningContent extends LearningWagtailPage {
|
||||||
|
type: 'learnpath.LearningContent';
|
||||||
|
minutes: number;
|
||||||
|
contents: LearningContentBlock[];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface LearningUnit extends LearningWagtailPage {
|
||||||
|
type: 'learnpath.LearningUnit';
|
||||||
|
questions: [];
|
||||||
|
learningContents: LearningContent[];
|
||||||
|
minutes: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface LearningSequence extends LearningWagtailPage {
|
||||||
|
type: 'learnpath.LearningSequence';
|
||||||
|
icon: string;
|
||||||
|
learningUnits: LearningUnit[];
|
||||||
|
minutes: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type CircleChild = LearningContent | LearningUnit | LearningSequence;
|
||||||
|
|
||||||
|
export interface Circle extends LearningWagtailPage {
|
||||||
|
type: 'learnpath.Circle';
|
||||||
|
children: CircleChild[];
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEmptyLearningUnit(): LearningUnit {
|
||||||
|
return {
|
||||||
|
id: -1,
|
||||||
|
title: '',
|
||||||
|
slug: '',
|
||||||
|
translation_key: '',
|
||||||
|
type: 'learnpath.LearningUnit',
|
||||||
|
questions: [],
|
||||||
|
learningContents: [],
|
||||||
|
minutes: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseLearningSequences (children: CircleChild[]): LearningSequence[] {
|
||||||
|
let learningSequence:LearningSequence|null = null;
|
||||||
|
let learningUnit:LearningUnit|null = null;
|
||||||
|
const result:LearningSequence[] = [];
|
||||||
|
|
||||||
|
children.forEach((child) => {
|
||||||
|
// FIXME add error detection if the data does not conform to expectations
|
||||||
|
if (child.type === 'learnpath.LearningSequence') {
|
||||||
|
if (learningSequence) {
|
||||||
|
if (learningUnit) {
|
||||||
|
learningSequence.learningUnits.push(learningUnit);
|
||||||
|
}
|
||||||
|
result.push(learningSequence);
|
||||||
|
}
|
||||||
|
learningSequence = Object.assign(child, {learningUnits: []});
|
||||||
|
|
||||||
|
// initialize empty learning unit if there will not come a learning unit next
|
||||||
|
learningUnit = createEmptyLearningUnit();
|
||||||
|
} else if (child.type === 'learnpath.LearningUnit') {
|
||||||
|
if (learningSequence === null) {
|
||||||
|
throw new Error('LearningUnit found before LearningSequence');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (learningUnit && learningUnit.learningContents.length) {
|
||||||
|
learningSequence.learningUnits.push(learningUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
learningUnit = Object.assign(child, {learningContents: []});
|
||||||
|
} else if (child.type === 'learnpath.LearningContent') {
|
||||||
|
if (learningUnit === null) {
|
||||||
|
throw new Error('LearningContent found before LearningUnit');
|
||||||
|
}
|
||||||
|
|
||||||
|
learningUnit.learningContents.push(child);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (learningUnit && learningSequence) {
|
||||||
|
(learningSequence as LearningSequence).learningUnits.push(learningUnit);
|
||||||
|
result.push(learningSequence);
|
||||||
|
} else {
|
||||||
|
throw new Error('Finished with LearningContent but there is no LearningSequence and LearningUnit');
|
||||||
|
}
|
||||||
|
|
||||||
|
// sum minutes
|
||||||
|
result.forEach((learningSequence) => {
|
||||||
|
learningSequence.minutes = 0;
|
||||||
|
learningSequence.learningUnits.forEach((learningUnit) => {
|
||||||
|
learningUnit.minutes = 0;
|
||||||
|
learningUnit.learningContents.forEach((learningContent) => {
|
||||||
|
learningUnit.minutes += learningContent.minutes;
|
||||||
|
});
|
||||||
|
learningSequence.minutes += learningUnit.minutes;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import * as log from 'loglevel';
|
||||||
import MainNavigationBar from '../components/MainNavigationBar.vue';
|
import MainNavigationBar from '../components/MainNavigationBar.vue';
|
||||||
import LearningSequence from '../components/circle/LearningSequence.vue';
|
import LearningSequence from '../components/circle/LearningSequence.vue';
|
||||||
import { itGet, itPost } from '../fetchHelpers';
|
import { itGet, itPost } from '../fetchHelpers';
|
||||||
|
import { parseLearningSequences } from '../services/circle';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { LearningSequence, MainNavigationBar },
|
components: { LearningSequence, MainNavigationBar },
|
||||||
|
|
@ -29,56 +30,13 @@ export default {
|
||||||
this.completionData = data;
|
this.completionData = data;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
createLearningSequences(circleData) {
|
|
||||||
// aggregate wagtail data into LearningSequence > LearningUnit > LearningContent hierarchy
|
|
||||||
let learningSequence = null;
|
|
||||||
let learningUnit = null;
|
|
||||||
circleData.children.forEach((child) => {
|
|
||||||
// FIXME add error detection if the data does not conform to expectations
|
|
||||||
if(child.type === 'learnpath.LearningSequence') {
|
|
||||||
if(learningSequence) {
|
|
||||||
if(learningUnit) {
|
|
||||||
learningSequence.learningUnits.push(learningUnit);
|
|
||||||
}
|
|
||||||
this.learningSequences.push(learningSequence);
|
|
||||||
}
|
|
||||||
learningSequence = Object.assign({}, child, { learningUnits: [] });
|
|
||||||
learningUnit = { id: null, title: '', learningContents: [] };
|
|
||||||
} else if(child.type === 'learnpath.LearningUnit') {
|
|
||||||
if(learningUnit && learningUnit.learningContents.length) {
|
|
||||||
learningSequence.learningUnits.push(learningUnit);
|
|
||||||
}
|
|
||||||
learningUnit = Object.assign({}, child, { learningContents: [] });
|
|
||||||
} else {
|
|
||||||
learningUnit.learningContents.push(child);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if(learningUnit) {
|
|
||||||
learningSequence.learningUnits.push(learningUnit);
|
|
||||||
}
|
|
||||||
this.learningSequences.push(learningSequence);
|
|
||||||
|
|
||||||
// sum minutes
|
|
||||||
this.learningSequences.forEach((learningSequence) => {
|
|
||||||
learningSequence.minutes = 0;
|
|
||||||
learningSequence.learningUnits.forEach((learningUnit) => {
|
|
||||||
learningUnit.minutes = 0;
|
|
||||||
learningUnit.learningContents.forEach((learningContent) => {
|
|
||||||
learningUnit.minutes += learningContent.minutes;
|
|
||||||
});
|
|
||||||
learningSequence.minutes += learningUnit.minutes;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
log.debug(this.learningSequences);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
log.debug('CircleView mounted', this.circleSlug);
|
log.debug('CircleView mounted', this.circleSlug);
|
||||||
itGet(`/learnpath/api/circle/${this.circleSlug}/`).then((data) => {
|
itGet(`/learnpath/api/circle/${this.circleSlug}/`).then((data) => {
|
||||||
this.circleData = data;
|
this.circleData = data;
|
||||||
this.createLearningSequences(data);
|
this.learningSequences = parseLearningSequences(this.circleData.children);
|
||||||
|
log.debug(this.learningSequences);
|
||||||
|
|
||||||
itGet(`/api/completion/circle/${this.circleData.translation_key}/`).then((completionData) => {
|
itGet(`/api/completion/circle/${this.circleData.translation_key}/`).then((completionData) => {
|
||||||
this.completionData = completionData;
|
this.completionData = completionData;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue