Refactor learningPath views

This commit is contained in:
Daniel Egger 2022-07-04 11:52:05 +02:00
parent 7022827cf3
commit cbbf4e42a2
5 changed files with 118 additions and 88 deletions

View File

@ -1,6 +1,6 @@
<script>
import * as d3 from 'd3'
import * as _ from 'underscore'
import * as d3 from 'd3';
import { useLearningPathStore } from '../../stores/learningPath';
export default {
props: {
@ -157,23 +157,31 @@ export default {
type: Number,
},
},
setup() {
const learningPathStore = useLearningPathStore()
return { learningPathStore }
},
computed: {
viewBox() {
return `0 0 ${this.width} ${this.height* 1.5}`
},
circles() {
let internalCircles = _.flatten(_.pluck(this.learningPathContents.topics, 'circles'))
_.forEach(internalCircles, function (circle) {
let pieWeights = new Array(Math.max(circle.learning_sequences.length, 1)).fill(1)
let pieGenerator = d3.pie()
let pieData = pieGenerator(pieWeights)
_.forEach(pieData, function (pie) {
pie.done = circle.learning_sequences.length === 0 ? false : circle.learning_sequences[parseInt(pie.index)].done
})
circle.pieData = pieData
})
return internalCircles
if (this.learningPathStore.learningPath) {
let internalCircles = this.learningPathStore.learningPath.topics.flatMap(topic => topic.circles);
// console.log(internalCircles);
internalCircles.forEach((circle) => {
let pieWeights = new Array(Math.max(circle.learningSequences.length, 1)).fill(1)
let pieGenerator = d3.pie()
let pieData = pieGenerator(pieWeights)
// _.forEach(pieData, function(pie) {
// pie.done = circle.learning_sequences.length === 0 ? false : circle.learning_sequences[parseInt(pie.index)].done
// })
circle.pieData = pieData
});
return internalCircles
}
return [];
},
svg() {
return d3.select('.learning-path-visualization')

View File

@ -2,11 +2,11 @@ import type {
CircleChild,
CircleCompletion,
CircleGoal,
CircleInterface,
CircleJobSituation,
LearningContent,
LearningSequence,
LearningUnit
LearningUnit,
LearningWagtailPage
} from '@/types';
@ -107,7 +107,7 @@ export function parseLearningSequences (children: CircleChild[]): LearningSequen
return result;
}
export class Circle implements CircleInterface {
export class Circle implements LearningWagtailPage {
readonly type = 'learnpath.Circle';
readonly learningSequences: LearningSequence[];
readonly completed: boolean;

View File

@ -0,0 +1,59 @@
import * as log from 'loglevel';
import {defineStore} from 'pinia'
import type {LearningPath, Topic} from '@/types'
import {itGet} from '@/fetchHelpers';
import {Circle} from '@/services/circle';
export type LearningPathStoreState = {
learningPath: LearningPath;
}
export const useLearningPathStore = defineStore({
id: 'learningPath',
state: () => {
return {
learningPath: undefined,
} as LearningPathStoreState;
},
getters: {
},
actions: {
async loadLearningPath(slug: string) {
try {
this.learningPath = await itGet(`/learnpath/api/learningpath/${slug}/`);
this.learningPath.topics = [];
const emptyTopic: Topic = {
id: 0,
title: '',
slug: '',
type: 'learnpath.Topic',
translation_key: '',
is_visible: false,
circles: []
}
let topic = Object.assign({}, emptyTopic);
this.learningPath.children.forEach((page) => {
if (page.type === 'learnpath.Topic') {
if (topic.id !== 0) {
this.learningPath.topics.push(topic);
}
topic = Object.assign({}, emptyTopic, page);
}
if (page.type === 'learnpath.Circle') {
const circle = Circle.fromJson(page);
topic.circles.push(circle);
}
this.learningPath.topics.push(topic);
})
console.log(this.learningPath);
return this.learningPath;
} catch (error) {
log.error(error);
return error
}
},
}
})

View File

@ -1,4 +1,4 @@
import {parseLearningSequences} from '@/services/circle';
import type {Circle} from '@/services/circle';
export interface LearningContentBlock {
type: 'web-based-training' | 'competence' | 'exercise' | 'knowledge';
@ -95,6 +95,20 @@ export interface WagtailCircle extends LearningWagtailPage {
description: string;
}
export interface Topic extends LearningWagtailPage {
type: 'learnpath.Topic';
is_visible: boolean;
circles: Circle[];
}
export type LearningPathChild = Topic | WagtailCircle;
export interface LearningPath extends LearningWagtailPage {
type: 'learnpath.LearningPath';
children: LearningPathChild[];
topics: Topic[];
}
export interface CircleCompletion {
id: number;
created_at: string;
@ -107,17 +121,6 @@ export interface CircleCompletion {
json_data: any;
}
export interface CircleInterface extends LearningWagtailPage {
readonly type: 'learnpath.Circle';
readonly children: CircleChild[];
readonly description: string;
readonly goals: CircleGoal[];
readonly job_situations: CircleJobSituation[];
learningSequences: LearningSequence[];
}
export interface CircleDiagramData {
index: number
title: string

View File

@ -1,80 +1,40 @@
<script>
import axios from 'axios';
<script setup lang="ts">
import * as log from 'loglevel';
import { mapStores } from 'pinia';
import LearningPathDiagram from '../components/circle/LearningPathDiagram.vue';
import { useUserStore } from '../stores/user';
import {onMounted} from 'vue'
import {useLearningPathStore} from '@/stores/learningPath';
import {useUserStore} from '@/stores/user';
export default {
import LearningPathDiagram from '@/components/circle/LearningPathDiagram.vue';
components: {LearningPathDiagram},
props: ['learningPathSlug',],
data() {
return {
count: 0,
learningPathData: {},
learningPathContents: null,
circles: [],
learningSequences: [],
}
},
computed: {
...mapStores(useUserStore)
},
mounted() {
log.debug('LearningPath mounted', this.learningPathSlug);
axios({
method: 'get',
url: `/learnpath/api/learningpath/${this.learningPathSlug}/`,
}).then((response) => {
log.debug('LearningPathView created');
this.learningPathData = response.data
const props = defineProps<{
learningPathSlug: string
}>()
let learningPathContents = {topics: []}
let topic = {
id: 0,
title: '',
slug: '',
type: 'learnpath.Topic',
translation_key: '',
is_visible: false,
cirlces: []
}
response.data.children.forEach((child) => {
if (child.type === 'learnpath.Topic') {
if (topic.id != 0) {
learningPathContents.topics.push(child)
}
topic = child
topic.circles = []
}
if (child.type === 'learnpath.Circle') {
topic.circles.push(child)
}
});
learningPathContents.topics.push(topic)
this.learningPathContents = learningPathContents;
});
}
}
const learningPathStore = useLearningPathStore();
const userStore = useUserStore();
onMounted(async () => {
log.info('LearningPathView mounted');
await learningPathStore.loadLearningPath(props.learningPathSlug);
});
</script>
<template>
<div class="bg-gray-100" v-if="learningPathContents">
<div class="bg-gray-100" v-if="learningPathStore.learningPath">
<div class="learningpath flex flex-col">
<div class="flex flex-col h-max">
<div class="bg-white h-80 pt-8">
<LearningPathDiagram :learning-path-contents="learningPathContents"></LearningPathDiagram>
<LearningPathDiagram></LearningPathDiagram>
</div>
<h1 class="m-12">{{ learningPathData.title }}</h1>
<h1 class="m-12">{{ learningPathStore.learningPath.title }}</h1>
<div class="bg-white m-12 p-8 flex flex-row justify-start">
<div class="p-8 flex-auto">