Add LearningPathDiagram mini version

This commit is contained in:
Daniel Egger 2022-11-11 13:17:21 +01:00
parent 55d4ea6080
commit 1f7321f935
4 changed files with 53 additions and 25 deletions

View File

@ -1,20 +1,20 @@
<script> <script>
import colors from "@/colors.json"; import colors from "@/colors.json";
import { useLearningPathStore } from "@/stores/learningPath";
import * as d3 from "d3"; import * as d3 from "d3";
import * as _ from "lodash"; import * as _ from "lodash";
import * as log from "loglevel"; import * as log from "loglevel";
import { mapState } from "pinia";
// type DiagramType = "horizontal" | "vertical" | "horizontalSmall";
export default { export default {
props: { props: {
vertical: { diagramType: {
default: false,
type: Boolean,
},
identifier: {
required: true,
type: String, type: String,
default: "horizontal",
},
learningPath: {
required: true,
type: Object,
}, },
}, },
data() { data() {
@ -24,7 +24,9 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(useLearningPathStore, ["learningPath"]), svgId() {
return `learningpath-diagram-${this.learningPath.slug}-${this.diagramType}`;
},
viewBox() { viewBox() {
return `0 0 ${this.width} ${this.height}`; return `0 0 ${this.width} ${this.height}`;
}, },
@ -76,7 +78,7 @@ export default {
return []; return [];
}, },
svg() { svg() {
const result = d3.select("#" + this.identifier); const result = d3.select("#" + this.svgId);
result.selectAll("*").remove(); result.selectAll("*").remove();
return result; return result;
}, },
@ -86,14 +88,17 @@ export default {
log.debug("LearningPathDiagram mounted"); log.debug("LearningPathDiagram mounted");
// clean old svg // clean old svg
d3.select("#" + this.identifier) d3.select("#" + this.svgId)
.selectAll("*") .selectAll("*")
.remove(); .remove();
const circleWidth = this.vertical ? 60 : 200; let circleWidth = 200;
if (this.diagramType === "vertical") {
circleWidth = 60;
}
const radius = (circleWidth * 0.8) / 2; const radius = (circleWidth * 0.8) / 2;
if (this.vertical) { if (this.diagramType === "vertical") {
this.width = Math.min(960, window.innerWidth - 32); this.width = Math.min(960, window.innerWidth - 32);
this.height = 860; this.height = 860;
} else { } else {
@ -132,7 +137,7 @@ export default {
.append("g") .append("g")
.attr("class", "circle") .attr("class", "circle")
.attr("data-cy", (d) => { .attr("data-cy", (d) => {
if (this.vertical) { if (this.diagramType === "vertical") {
return `circle-${d.slug}-vertical`; return `circle-${d.slug}-vertical`;
} else { } else {
return `circle-${d.slug}`; return `circle-${d.slug}`;
@ -196,7 +201,7 @@ export default {
.style("font-size", "18px") .style("font-size", "18px")
.style("overflow-wrap", "break-word") .style("overflow-wrap", "break-word")
.text((d) => { .text((d) => {
if (!this.vertical) { if (this.diagramType === "horizontal") {
return d.title.replace("Prüfungsvorbereitung", "Prüfungs- vorbereitung"); return d.title.replace("Prüfungsvorbereitung", "Prüfungs- vorbereitung");
} }
return d.title; return d.title;
@ -267,7 +272,7 @@ export default {
// Calculate positions of objects // Calculate positions of objects
if (this.vertical) { if (this.diagramType === "vertical") {
const Circles_X = radius; const Circles_X = radius;
const Topics_X = Circles_X - 20; const Topics_X = Circles_X - 20;
@ -313,7 +318,16 @@ export default {
.attr("y", radius + 30) .attr("y", radius + 30)
.style("text-anchor", "middle") .style("text-anchor", "middle")
.call(wrap, circleWidth - 20) .call(wrap, circleWidth - 20)
.attr("class", "circlesText text-xl font-bold hidden lg:block"); .attr("class", () => {
let classes = "circlesText text-xl font-bold block";
if (
this.diagramType === "vertical" ||
this.diagramType === "horizontalSmall"
) {
classes += " hidden";
}
return classes;
});
topicGroups topicGroups
.attr("transform", (d, i) => { .attr("transform", (d, i) => {
@ -324,7 +338,15 @@ export default {
); );
}) })
.attr("class", (d) => { .attr("class", (d) => {
return "topic ".concat(d.is_visible ? "hidden lg:block" : "hidden"); let classes = "topic";
if (
this.diagramType === "vertical" ||
this.diagramType === "horizontalSmall" ||
!d.is_visible
) {
classes += " hidden";
}
return classes;
}); });
topicLines topicLines
@ -336,11 +358,15 @@ export default {
.duration("1000") .duration("1000")
.attr("y2", 350); .attr("y2", 350);
let topicTitlesClassValue = "topic-title font-bold";
if (this.diagramType === "horizontalSmall") {
topicTitlesClassValue += " hidden";
}
topicTitles topicTitles
.attr("y", 20) .attr("y", 20)
.style("font-size", "18px") .style("font-size", "18px")
.call(wrap, circleWidth * 0.8) .call(wrap, circleWidth * 0.8)
.attr("class", "topicTitles font-bold"); .attr("class", topicTitlesClassValue);
} }
function wrap(text, width) { function wrap(text, width) {
@ -384,10 +410,10 @@ export default {
<template> <template>
<div class="svg-container h-full content-start"> <div class="svg-container h-full content-start">
<svg <svg
:id="identifier" :id="svgId"
class="learning-path-visualization h-full mx-auto -mt-6 lg:mt-0" class="learning-path-visualization h-full mx-auto -mt-6 lg:mt-0"
:class="{ :class="{
'max-h-[384px]': !vertical, 'max-h-[384px]': ['horizontal', 'horizontalSmall'].includes(diagramType),
}" }"
:viewBox="viewBox" :viewBox="viewBox"
></svg> ></svg>

View File

@ -25,8 +25,8 @@ const emits = defineEmits(["closemodal"]);
<LearningPathDiagram <LearningPathDiagram
v-if="learningPathStore.learningPath" v-if="learningPathStore.learningPath"
class="w-full" class="w-full"
:identifier="`verticalVisualization-${learningPathStore.learningPath.slug}`" :learning-path="learningPathStore.learningPath"
:vertical="true" diagram-type="vertical"
></LearningPathDiagram> ></LearningPathDiagram>
</div> </div>
</div> </div>

View File

@ -6,6 +6,8 @@ import { computed } from "vue";
import { RouterLink } from "vue-router"; import { RouterLink } from "vue-router";
const props = defineProps({ const props = defineProps({
// Vue-TypeScript make special things with `defineProps` so it's hard
// to make this without @ts-ignore...
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
...RouterLink.props, ...RouterLink.props,

View File

@ -69,8 +69,8 @@ const createContinueUrl = (learningPath: LearningPath): [string, boolean] => {
</div> </div>
<LearningPathDiagram <LearningPathDiagram
class="mx-auto max-w-[1920px] max-h-[380px] w-full px-4" class="mx-auto max-w-[1920px] max-h-[380px] w-full px-4"
:identifier="`mainVisualization-${learningPathStore.learningPath.slug}`" diagram-type="horizontal"
:vertical="false" :learning-path="learningPathStore.learningPath"
></LearningPathDiagram> ></LearningPathDiagram>
</div> </div>