Merged develop into feature/use_currents_dev
This commit is contained in:
commit
819985f858
|
|
@ -3,5 +3,6 @@
|
||||||
"singleQuote": false,
|
"singleQuote": false,
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"printWidth": 88,
|
"printWidth": 88,
|
||||||
"organizeImportsSkipDestructiveCodeActions": true
|
"organizeImportsSkipDestructiveCodeActions": true,
|
||||||
|
"htmlWhitespaceSensitivity": "ignore"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,19 @@ const profileDropdownData: DropdownListItem[] = [
|
||||||
<!-- Cockpit-->
|
<!-- Cockpit-->
|
||||||
<!-- </router-link>-->
|
<!-- </router-link>-->
|
||||||
|
|
||||||
|
<router-link
|
||||||
|
v-if="
|
||||||
|
inCourse() &&
|
||||||
|
courseSessionsStore.courseSessionForRoute &&
|
||||||
|
courseSessionsStore.hasCockpit
|
||||||
|
"
|
||||||
|
:to="`${courseSessionsStore.courseSessionForRoute.course_url}/cockpit`"
|
||||||
|
class="nav-item"
|
||||||
|
:class="{ 'nav-item--active': inCockpit() }"
|
||||||
|
>
|
||||||
|
{{ $t("cockpit.title") }}
|
||||||
|
</router-link>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
v-if="inCourse() && courseSessionsStore.courseSessionForRoute"
|
v-if="inCourse() && courseSessionsStore.courseSessionForRoute"
|
||||||
:to="courseSessionsStore.courseSessionForRoute.learning_path_url"
|
:to="courseSessionsStore.courseSessionForRoute.learning_path_url"
|
||||||
|
|
@ -186,28 +199,16 @@ const profileDropdownData: DropdownListItem[] = [
|
||||||
{{ $t("competences.title") }}
|
{{ $t("competences.title") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<router-link
|
|
||||||
v-if="
|
|
||||||
inCourse() &&
|
|
||||||
courseSessionsStore.courseSessionForRoute &&
|
|
||||||
courseSessionsStore.hasCockpit
|
|
||||||
"
|
|
||||||
:to="`${courseSessionsStore.courseSessionForRoute.course_url}/cockpit`"
|
|
||||||
class="nav-item"
|
|
||||||
:class="{ 'nav-item--active': inCockpit() }"
|
|
||||||
>
|
|
||||||
{{ $t("cockpit.title") }}
|
|
||||||
</router-link>
|
|
||||||
|
|
||||||
<div class="hidden lg:block flex-auto"></div>
|
<div class="hidden lg:block flex-auto"></div>
|
||||||
<a
|
<a
|
||||||
class="nav-item"
|
class="nav-item"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://bildung.vbv.ch/ilp/pages/catalogsearch.jsf"
|
href="https://bildung.vbv.ch/ilp/pages/catalogsearch.jsf"
|
||||||
>Shop</a
|
|
||||||
>
|
>
|
||||||
|
Shop
|
||||||
|
</a>
|
||||||
<router-link
|
<router-link
|
||||||
to="/media/versicherungsvermittlerin-media"
|
to="/media/versicherungsvermittler-in-media"
|
||||||
class="nav-item"
|
class="nav-item"
|
||||||
:class="{ 'nav-item--active': inMediaLibrary() }"
|
:class="{ 'nav-item--active': inMediaLibrary() }"
|
||||||
data-cy="medialibrary-link"
|
data-cy="medialibrary-link"
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ const clickLink = (to: string | undefined) => {
|
||||||
@click="clickLink('/profile')"
|
@click="clickLink('/profile')"
|
||||||
>
|
>
|
||||||
<IconSettings class="inline-block" />
|
<IconSettings class="inline-block" />
|
||||||
<span class="ml-3"> {{ $t("mainNavigation.settings") }} </span>
|
<span class="ml-3">{{ $t("mainNavigation.settings") }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -72,11 +72,12 @@ const clickLink = (to: string | undefined) => {
|
||||||
class="nav-item"
|
class="nav-item"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://bildung.vbv.ch/ilp/pages/catalogsearch.jsf"
|
href="https://bildung.vbv.ch/ilp/pages/catalogsearch.jsf"
|
||||||
>Shop</a
|
|
||||||
>
|
>
|
||||||
|
Shop
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="mt-6">
|
<li class="mt-6">
|
||||||
<button @click="clickLink(`/media/versicherungsvermittlerin-media`)">
|
<button @click="clickLink(`/media/versicherungsvermittler-in-media`)">
|
||||||
{{ $t("mediaLibrary.title") }}
|
{{ $t("mediaLibrary.title") }}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useCircleStore } from "@/stores/circle";
|
import { useCircleStore } from "@/stores/circle";
|
||||||
|
import type { DefaultArcObject } from "d3";
|
||||||
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";
|
||||||
|
|
@ -8,7 +9,6 @@ import { computed, onMounted } from "vue";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import colors from "@/colors.json";
|
import colors from "@/colors.json";
|
||||||
import type { LearningSequence } from "@/types";
|
import type { LearningSequence } from "@/types";
|
||||||
import type { DefaultArcObject } from "d3";
|
|
||||||
|
|
||||||
const circleStore = useCircleStore();
|
const circleStore = useCircleStore();
|
||||||
|
|
||||||
|
|
@ -48,11 +48,8 @@ interface CirclePie extends d3.PieArcDatum<number> {
|
||||||
|
|
||||||
const pieData = computed(() => {
|
const pieData = computed(() => {
|
||||||
const circle = circleStore.circle;
|
const circle = circleStore.circle;
|
||||||
console.log("initial of compute pie data ", circle);
|
|
||||||
|
|
||||||
if (circle) {
|
if (circle) {
|
||||||
console.log("initial of compute pie data ", circle);
|
|
||||||
|
|
||||||
const pieWeights = new Array(Math.max(circle.learningSequences.length, 1)).fill(1);
|
const pieWeights = new Array(Math.max(circle.learningSequences.length, 1)).fill(1);
|
||||||
const pieGenerator = d3.pie();
|
const pieGenerator = d3.pie();
|
||||||
const angles = pieGenerator(pieWeights);
|
const angles = pieGenerator(pieWeights);
|
||||||
|
|
@ -177,7 +174,7 @@ function render() {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.on("click", function (d, elm) {
|
.on("click", function (d, elm) {
|
||||||
console.log("clicked on ", d, elm);
|
log.info("clicked on ", d, elm);
|
||||||
document.getElementById(elm.slug)?.scrollIntoView({ behavior: "smooth" });
|
document.getElementById(elm.slug)?.scrollIntoView({ behavior: "smooth" });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,7 @@ const block = computed(() => {
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
|
allow="accelerometer; encrypted-media; gyroscope; picture-in-picture"
|
||||||
allowfullscreen
|
allowfullscreen
|
||||||
>
|
></iframe>
|
||||||
</iframe>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="block.type === 'media_library'" class="mt-4 lg:mt-12">
|
<div v-else-if="block.type === 'media_library'" class="mt-4 lg:mt-12">
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,18 @@ export type DiagramType = "horizontal" | "vertical" | "horizontalSmall";
|
||||||
export interface Props {
|
export interface Props {
|
||||||
diagramType?: DiagramType;
|
diagramType?: DiagramType;
|
||||||
postfix?: string;
|
postfix?: string;
|
||||||
|
profileUserId?: string;
|
||||||
learningPath: LearningPath;
|
learningPath: LearningPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
diagramType: "horizontal",
|
diagramType: "horizontal",
|
||||||
postfix: "",
|
postfix: "",
|
||||||
|
profileUserId: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
log.debug("LearningPathDiagram created", props.postfix, props.profileUserId);
|
||||||
|
|
||||||
const state = reactive({ width: 1640, height: 384 });
|
const state = reactive({ width: 1640, height: 384 });
|
||||||
|
|
||||||
const svgId = computed(() => {
|
const svgId = computed(() => {
|
||||||
|
|
@ -38,8 +42,7 @@ const viewBox = computed(() => {
|
||||||
const vueRouter = useRouter();
|
const vueRouter = useRouter();
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
log.debug("LearningPathDiagram mounted");
|
log.debug("LearningPathDiagram mounted", props.postfix, props.profileUserId);
|
||||||
console.log(props.learningPath);
|
|
||||||
render();
|
render();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -57,6 +60,14 @@ function allFinished(circle: Circle, learningSequence: LearningSequence) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function circleUrl(circle: InternalCircle) {
|
||||||
|
let circleUrl = circle.frontend_url;
|
||||||
|
if (props.profileUserId) {
|
||||||
|
circleUrl = `/course/${props.learningPath.course.slug}/cockpit/profile/${props.profileUserId}/${circle.slug}`;
|
||||||
|
}
|
||||||
|
return circleUrl;
|
||||||
|
}
|
||||||
|
|
||||||
interface CirclePie extends d3.PieArcDatum<number> {
|
interface CirclePie extends d3.PieArcDatum<number> {
|
||||||
someFinished: boolean;
|
someFinished: boolean;
|
||||||
allFinished: boolean;
|
allFinished: boolean;
|
||||||
|
|
@ -90,6 +101,7 @@ const circles = computed(() => {
|
||||||
pie.someFinished = someFinished(circle, thisLearningSequence);
|
pie.someFinished = someFinished(circle, thisLearningSequence);
|
||||||
pie.allFinished = allFinished(circle, thisLearningSequence);
|
pie.allFinished = allFinished(circle, thisLearningSequence);
|
||||||
});
|
});
|
||||||
|
|
||||||
internalCircles.push({
|
internalCircles.push({
|
||||||
pieData: pieData.reverse() as CirclePie[],
|
pieData: pieData.reverse() as CirclePie[],
|
||||||
title: circle.title,
|
title: circle.title,
|
||||||
|
|
@ -181,7 +193,7 @@ function render() {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.on("click", (d, i) => {
|
.on("click", (d, i) => {
|
||||||
vueRouter.push(i.frontend_url);
|
vueRouter.push(circleUrl(i));
|
||||||
})
|
})
|
||||||
|
|
||||||
.attr("role", "button");
|
.attr("role", "button");
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,14 @@ import _ from "lodash";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import LearningContentBadge from "./LearningContentTypeBadge.vue";
|
import LearningContentBadge from "./LearningContentTypeBadge.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
interface Props {
|
||||||
learningSequence: LearningSequence;
|
learningSequence: LearningSequence;
|
||||||
}>();
|
readonly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
readonly: false,
|
||||||
|
});
|
||||||
|
|
||||||
const circleStore = useCircleStore();
|
const circleStore = useCircleStore();
|
||||||
|
|
||||||
|
|
@ -112,14 +117,26 @@ const learningSequenceBorderClass = computed(() => {
|
||||||
:key="learningContent.id"
|
:key="learningContent.id"
|
||||||
class="flex gap-4 pb-3 lg:pb-6 items-center"
|
class="flex gap-4 pb-3 lg:pb-6 items-center"
|
||||||
>
|
>
|
||||||
|
<div v-if="props.readonly">
|
||||||
|
<it-icon-check
|
||||||
|
v-if="learningContent.completion_status === 'success'"
|
||||||
|
class="block w-8 h-8"
|
||||||
|
></it-icon-check>
|
||||||
|
<div v-else class="w-8 h-8"></div>
|
||||||
|
</div>
|
||||||
<ItCheckbox
|
<ItCheckbox
|
||||||
|
v-else
|
||||||
:model-value="learningContent.completion_status === 'success'"
|
:model-value="learningContent.completion_status === 'success'"
|
||||||
:on-toggle="() => toggleCompleted(learningContent)"
|
:on-toggle="() => toggleCompleted(learningContent)"
|
||||||
:data-cy="`${learningContent.slug}-checkbox`"
|
:data-cy="`${learningContent.slug}-checkbox`"
|
||||||
/>
|
/>
|
||||||
<div class="flex-auto pt-1 sm:pt-0">
|
<div class="flex-auto pt-1 sm:pt-0">
|
||||||
<span class="flex gap-4 items-center xl:h-10">
|
<span class="flex gap-4 items-center xl:h-10">
|
||||||
|
<div v-if="props.readonly" class="w-full sm:w-auto text-left">
|
||||||
|
{{ learningContent.title }}
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
|
v-else
|
||||||
class="cursor-pointer w-full sm:w-auto text-left"
|
class="cursor-pointer w-full sm:w-auto text-left"
|
||||||
:data-cy="`${learningContent.slug}`"
|
:data-cy="`${learningContent.slug}`"
|
||||||
@click.stop="circleStore.openLearningContent(learningContent)"
|
@click.stop="circleStore.openLearningContent(learningContent)"
|
||||||
|
|
@ -132,7 +149,8 @@ const learningSequenceBorderClass = computed(() => {
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-if="
|
v-if="
|
||||||
learningContent.translation_key === continueTranslationKeyTuple[0]
|
learningContent.translation_key ===
|
||||||
|
continueTranslationKeyTuple[0] && !props.readonly
|
||||||
"
|
"
|
||||||
class="btn-blue order-1 sm:order-none"
|
class="btn-blue order-1 sm:order-none"
|
||||||
data-cy="ls-continue-button"
|
data-cy="ls-continue-button"
|
||||||
|
|
@ -162,9 +180,9 @@ const learningSequenceBorderClass = computed(() => {
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="learningUnit.children.length"
|
v-if="learningUnit.children.length"
|
||||||
class="hover:cursor-pointer"
|
:class="{ 'cursor-pointer': !props.readonly }"
|
||||||
:data-cy="`${learningUnit.slug}`"
|
:data-cy="`${learningUnit.slug}`"
|
||||||
@click="circleStore.openSelfEvaluation(learningUnit)"
|
@click="!props.readonly && circleStore.openSelfEvaluation(learningUnit)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="circleStore.calcSelfEvaluationStatus(learningUnit) === 'success'"
|
v-if="circleStore.calcSelfEvaluationStatus(learningUnit) === 'success'"
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,8 @@ function handleBack() {
|
||||||
<p class="text-large mt-4">
|
<p class="text-large mt-4">
|
||||||
{{ $t("selfEvaluation.instruction[0]") }}
|
{{ $t("selfEvaluation.instruction[0]") }}
|
||||||
<span class="font-bold">«{{ learningUnit.title }}»</span>
|
<span class="font-bold">«{{ learningUnit.title }}»</span>
|
||||||
{{ $t("selfEvaluation.instruction[1]") }}<br />
|
{{ $t("selfEvaluation.instruction[1]") }}
|
||||||
|
<br />
|
||||||
{{ $t("selfEvaluation.instruction[2]") }}
|
{{ $t("selfEvaluation.instruction[2]") }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -85,9 +86,7 @@ function handleBack() {
|
||||||
@click="circleStore.markCompletion(currentQuestion, 'success')"
|
@click="circleStore.markCompletion(currentQuestion, 'success')"
|
||||||
>
|
>
|
||||||
<it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy>
|
<it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy>
|
||||||
<span class="font-bold text-large">
|
<span class="font-bold text-large">{{ $t("selfEvaluation.yes") }}.</span>
|
||||||
{{ $t("selfEvaluation.yes") }}.
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="flex-1 inline-flex items-center text-left p-4 border"
|
class="flex-1 inline-flex items-center text-left p-4 border"
|
||||||
|
|
@ -99,7 +98,7 @@ function handleBack() {
|
||||||
@click="circleStore.markCompletion(currentQuestion, 'fail')"
|
@click="circleStore.markCompletion(currentQuestion, 'fail')"
|
||||||
>
|
>
|
||||||
<it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking>
|
<it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking>
|
||||||
<span class="font-bold text-xl"> {{ $t("selfEvaluation.no") }}. </span>
|
<span class="font-bold text-xl">{{ $t("selfEvaluation.no") }}.</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<li
|
||||||
|
class="py-4 leading-[45px] border-b border-gray-500 last:border-0 flex flex-row justify-between"
|
||||||
|
>
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<slot name="left"></slot>
|
||||||
|
</div>
|
||||||
|
<div class="leading-[45px]">
|
||||||
|
<slot name="center"></slot>
|
||||||
|
</div>
|
||||||
|
<div class="leading-[45px]">
|
||||||
|
<slot name="link"></slot>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Dialog, DialogDescription, DialogPanel, DialogTitle } from "@headlessui/vue";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
modelValue: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
modelValue: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(["update:modelValue"]);
|
||||||
|
|
||||||
|
function setIsOpen(value: boolean) {
|
||||||
|
emits("update:modelValue", value);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog :open="modelValue" class="relative z-50" @close="setIsOpen">
|
||||||
|
<div class="fixed inset-0 bg-black/30" aria-hidden="true"></div>
|
||||||
|
<div class="fixed inset-0 flex items-center justify-center p-4">
|
||||||
|
<DialogPanel class="w-full max-w-2xl bg-white px-8 pt-8 pb-4">
|
||||||
|
<DialogTitle class="flex flex-row relative mb-8">
|
||||||
|
<slot name="title"></slot>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="w-4 h-4 absolute right-4 cursor-pointer"
|
||||||
|
@click="setIsOpen(false)"
|
||||||
|
>
|
||||||
|
<it-icon-close></it-icon-close>
|
||||||
|
</button>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
|
|
||||||
|
<slot name="body"></slot>
|
||||||
|
</DialogPanel>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
@ -10,13 +10,15 @@
|
||||||
"save": "Speichern",
|
"save": "Speichern",
|
||||||
"learningUnit": "Lerneinheit",
|
"learningUnit": "Lerneinheit",
|
||||||
"learningPath": "Lernpfad",
|
"learningPath": "Lernpfad",
|
||||||
|
"learningSequence": "Lernsequenz",
|
||||||
"show": "Anschauen",
|
"show": "Anschauen",
|
||||||
"circles": "Circles",
|
"circles": "Circles",
|
||||||
"transferTask": "Transferauftrag | Transferaufträge",
|
"transferTask": "Transferauftrag | Transferaufträge",
|
||||||
"feedback": "Feedback | Feedbacks",
|
"feedback": "Feedback | Feedbacks",
|
||||||
"exam": "Prüfung | Prüfungen",
|
"exam": "Prüfung | Prüfungen",
|
||||||
"examResult": "Prüfungsresultat | Prüfungsresultate",
|
"examResult": "Prüfungsresultat | Prüfungsresultate",
|
||||||
"certificate": "Zertifikat | Zertifikate"
|
"certificate": "Zertifikat | Zertifikate",
|
||||||
|
"notification": "Benachrichtigung | Benachrichtigungen"
|
||||||
},
|
},
|
||||||
"mainNavigation": {
|
"mainNavigation": {
|
||||||
"logout": "Abmelden",
|
"logout": "Abmelden",
|
||||||
|
|
@ -32,7 +34,18 @@
|
||||||
},
|
},
|
||||||
"circlePage": {
|
"circlePage": {
|
||||||
"duration": "Dauer",
|
"duration": "Dauer",
|
||||||
"circleContentBoxTitle": "Das lernst du in diesem Circle."
|
"circleContentBoxTitle": "Das lernst du in diesem Circle.",
|
||||||
|
"gotQuestions": "Hast du Fragen?",
|
||||||
|
"documents": {
|
||||||
|
"title": "Unterlagen",
|
||||||
|
"description": "Stelle deinen Lernenden zusätzliche Inhalte zur Verfügung.",
|
||||||
|
"action": "Unterlagen hochladen",
|
||||||
|
"modalAction": "Datei auswählen",
|
||||||
|
"fileLabel": "Datei",
|
||||||
|
"modalFileName": "Name",
|
||||||
|
"modalNameInformation": "Max. 70 Zeichen",
|
||||||
|
"chooseSequence": "Wähle eine Lernsequenz aus"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"learningContent": {
|
"learningContent": {
|
||||||
"completeAndContinue": "Abschliessen und weiter"
|
"completeAndContinue": "Abschliessen und weiter"
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,8 @@ onMounted(async () => {
|
||||||
<p class="text-bold">Check-up</p>
|
<p class="text-bold">Check-up</p>
|
||||||
<p>Vermittler/-in VBV</p>
|
<p>Vermittler/-in VBV</p>
|
||||||
<p>
|
<p>
|
||||||
Gültig bis: <span class="text-green-500 text-bold">31.12.2026</span>
|
Gültig bis:
|
||||||
|
<span class="text-green-500 text-bold">31.12.2026</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -122,7 +123,10 @@ onMounted(async () => {
|
||||||
<div>
|
<div>
|
||||||
<p class="text-bold">Zulassungsprüfung</p>
|
<p class="text-bold">Zulassungsprüfung</p>
|
||||||
<p>Vermittler/-in VBV</p>
|
<p>Vermittler/-in VBV</p>
|
||||||
<p>Bestanden: <span class="text-bold">14.11.2022</span></p>
|
<p>
|
||||||
|
Bestanden:
|
||||||
|
<span class="text-bold">14.11.2022</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ItListRow from "@/components/ui/ItListRow.vue";
|
||||||
|
import * as log from "loglevel";
|
||||||
|
|
||||||
|
log.debug("ProfileView created");
|
||||||
|
|
||||||
|
const fakeData = {
|
||||||
|
notifications: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
source: {
|
||||||
|
name: "Daniel",
|
||||||
|
title: "EFZ Kaufmann/-frau",
|
||||||
|
course: "üK",
|
||||||
|
avatar: "https://picsum.photos/200",
|
||||||
|
},
|
||||||
|
ago: "Vor 1 Stunde",
|
||||||
|
title: "hat den Transferauftrag «Die Motorhaftpflicht» mit dir geteilt.",
|
||||||
|
unread: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
source: {
|
||||||
|
name: "Sofia",
|
||||||
|
title: "EFZ Kaufmann/-frau",
|
||||||
|
course: "üK",
|
||||||
|
avatar: "https://picsum.photos/200",
|
||||||
|
},
|
||||||
|
ago: "Vor 1 Tag",
|
||||||
|
title: "hat dir ein Feedback zum Kreis «Analyse» mit dir geteilt.",
|
||||||
|
unread: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bg-gray-200">
|
||||||
|
<div class="container-large">
|
||||||
|
<header class="mt-12 mb-8">
|
||||||
|
<h1>{{ $t("general.notification", 2) }}</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<div class="bg-white px-8 py-2">
|
||||||
|
<ItListRow
|
||||||
|
v-for="notification in fakeData.notifications"
|
||||||
|
:key="notification.id"
|
||||||
|
>
|
||||||
|
<template #left>
|
||||||
|
<img
|
||||||
|
class="h-[45px] rounded-full mr-2"
|
||||||
|
:src="notification.source.avatar"
|
||||||
|
/>
|
||||||
|
<div class="ml-1">
|
||||||
|
<p class="leading-6">
|
||||||
|
{{ `${notification.source.name} ${notification.title}` }}
|
||||||
|
</p>
|
||||||
|
<p class="leading-6 text-sm text-gray-800">
|
||||||
|
{{ `${notification.source.title} ‐ ${notification.ago}` }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #link>
|
||||||
|
<div
|
||||||
|
v-if="notification.unread"
|
||||||
|
class="flex items-center h-[45px] flex-row"
|
||||||
|
>
|
||||||
|
<div class="w-[10px] h-[10px] bg-blue-500 rounded-full"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ItListRow>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -356,14 +356,13 @@ function log(data: any) {
|
||||||
v-model="state.dropdownSelected"
|
v-model="state.dropdownSelected"
|
||||||
class="w-full lg:w-96 mt-4 lg:mt-0"
|
class="w-full lg:w-96 mt-4 lg:mt-0"
|
||||||
:items="state.dropdownValues"
|
:items="state.dropdownValues"
|
||||||
>
|
></ItDropdownSelect>
|
||||||
</ItDropdownSelect>
|
|
||||||
{{ state.dropdownSelected }}
|
{{ state.dropdownSelected }}
|
||||||
|
|
||||||
<h2 class="mt-8 mb-8">Checkbox</h2>
|
<h2 class="mt-8 mb-8">Checkbox</h2>
|
||||||
|
|
||||||
<ItCheckbox v-model="state.checkboxValue" :disabled="false" class=""
|
<ItCheckbox v-model="state.checkboxValue" :disabled="false" class="">
|
||||||
>Label
|
Label
|
||||||
</ItCheckbox>
|
</ItCheckbox>
|
||||||
|
|
||||||
<ItCheckbox disabled class="mt-4">Disabled</ItCheckbox>
|
<ItCheckbox disabled class="mt-4">Disabled</ItCheckbox>
|
||||||
|
|
@ -376,7 +375,8 @@ function log(data: any) {
|
||||||
:list-items="dropdownData"
|
:list-items="dropdownData"
|
||||||
:align="'left'"
|
:align="'left'"
|
||||||
@select="log"
|
@select="log"
|
||||||
>Click Me
|
>
|
||||||
|
Click Me
|
||||||
</ItDropdown>
|
</ItDropdown>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import { useCockpitStore } from "@/stores/cockpit";
|
||||||
import { useCompetenceStore } from "@/stores/competence";
|
import { useCompetenceStore } from "@/stores/competence";
|
||||||
import { useLearningPathStore } from "@/stores/learningPath";
|
import { useLearningPathStore } from "@/stores/learningPath";
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
import { ref } from "vue";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
|
|
@ -27,7 +26,6 @@ function userCountStatus(userId: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
circles: ["KMU Teil 1", "KMU Teil 2", "3-Säuli-Prinzip"],
|
|
||||||
transferProgress: {
|
transferProgress: {
|
||||||
fail: 0,
|
fail: 0,
|
||||||
success: 3,
|
success: 3,
|
||||||
|
|
@ -35,17 +33,11 @@ const data = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedCircle = ref(1);
|
|
||||||
|
|
||||||
function setActiveClasses(id: number) {
|
function setActiveClasses(id: number) {
|
||||||
return cockpitStore.selectedCircle === id
|
return cockpitStore.selectedCircles.indexOf(id) > -1
|
||||||
? ["bg-blue-900", "text-white"]
|
? ["bg-blue-900", "text-white"]
|
||||||
: ["text-bg-900"];
|
: ["text-bg-900"];
|
||||||
}
|
}
|
||||||
|
|
||||||
function setActiveCircle(id: number) {
|
|
||||||
cockpitStore.selectedCircle = id;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -62,7 +54,7 @@ function setActiveCircle(id: number) {
|
||||||
<button
|
<button
|
||||||
class="border-2 border-blue-900 rounded-full px-4 mr-4 last:mr-0"
|
class="border-2 border-blue-900 rounded-full px-4 mr-4 last:mr-0"
|
||||||
:class="setActiveClasses(circle.id)"
|
:class="setActiveClasses(circle.id)"
|
||||||
@click="setActiveCircle(circle.id)"
|
@click="cockpitStore.toggleCourseSelection(circle.id)"
|
||||||
>
|
>
|
||||||
{{ circle.title }}
|
{{ circle.title }}
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -134,10 +126,18 @@ function setActiveCircle(id: number) {
|
||||||
) as LearningPath
|
) as LearningPath
|
||||||
"
|
"
|
||||||
:postfix="`cockpit-${csu.user_id}`"
|
:postfix="`cockpit-${csu.user_id}`"
|
||||||
|
:profile-user-id="`${csu.user_id}`"
|
||||||
diagram-type="horizontalSmall"
|
diagram-type="horizontalSmall"
|
||||||
></LearningPathDiagram>
|
></LearningPathDiagram>
|
||||||
</div>
|
</div>
|
||||||
<div>KMU Teil 1</div>
|
<div>
|
||||||
|
<span
|
||||||
|
v-for="title in cockpitStore.selectedCirclesTitles"
|
||||||
|
:key="title"
|
||||||
|
>
|
||||||
|
{{ title }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 flex flex-row items-center">
|
<div class="ml-4 flex flex-row items-center">
|
||||||
<div class="flex flex-row items-center mr-6">
|
<div class="flex flex-row items-center mr-6">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import CirclePage from "@/pages/learningPath/CirclePage.vue";
|
||||||
|
import { useCockpitStore } from "@/stores/cockpit";
|
||||||
|
import * as log from "loglevel";
|
||||||
|
import { computed, onMounted } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
userId: string;
|
||||||
|
courseSlug: string;
|
||||||
|
circleSlug: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
log.debug("CockpitUserCirclePage created", props.userId, props.circleSlug);
|
||||||
|
|
||||||
|
const cockpitStore = useCockpitStore();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
log.debug("CockpitUserCirclePage mounted");
|
||||||
|
});
|
||||||
|
|
||||||
|
const user = computed(() => {
|
||||||
|
return cockpitStore.courseSessionUsers?.find(
|
||||||
|
(csu) => csu.user_id === Number(props.userId)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CirclePage
|
||||||
|
v-if="user"
|
||||||
|
:course-slug="props.courseSlug"
|
||||||
|
:circle-slug="props.circleSlug"
|
||||||
|
:profile-user="user"
|
||||||
|
:readonly="true"
|
||||||
|
></CirclePage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -67,6 +67,7 @@ function setActiveClasses(isActive: boolean) {
|
||||||
diagram-type="horizontal"
|
diagram-type="horizontal"
|
||||||
:learning-path="learningPath"
|
:learning-path="learningPath"
|
||||||
:postfix="userId"
|
:postfix="userId"
|
||||||
|
:profile-user-id="userId"
|
||||||
></LearningPathDiagram>
|
></LearningPathDiagram>
|
||||||
</div>
|
</div>
|
||||||
<ul class="flex flex-row border-b-2 mb-5">
|
<ul class="flex flex-row border-b-2 mb-5">
|
||||||
|
|
@ -85,8 +86,8 @@ function setActiveClasses(isActive: boolean) {
|
||||||
</ul>
|
</ul>
|
||||||
<div>
|
<div>
|
||||||
<ul
|
<ul
|
||||||
class="px-8 bg-white"
|
|
||||||
v-if="competenceStore.competenceProfilePage(user.user_id)"
|
v-if="competenceStore.competenceProfilePage(user.user_id)"
|
||||||
|
class="px-8 bg-white"
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
v-for="competence in competenceStore.competences(user.user_id)"
|
v-for="competence in competenceStore.competences(user.user_id)"
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ findCriteria();
|
||||||
@click="circleStore.markCompletion(currentQuestion, 'success')"
|
@click="circleStore.markCompletion(currentQuestion, 'success')"
|
||||||
>
|
>
|
||||||
<it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy>
|
<it-icon-smiley-happy class="w-16 h-16 mr-4"></it-icon-smiley-happy>
|
||||||
<span class="font-bold text-large"> {{ $t("selfEvaluation.yes") }} </span>
|
<span class="font-bold text-large">{{ $t("selfEvaluation.yes") }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="flex-1 inline-flex items-center text-left p-4 border"
|
class="flex-1 inline-flex items-center text-left p-4 border"
|
||||||
|
|
@ -92,7 +92,7 @@ findCriteria();
|
||||||
@click="circleStore.markCompletion(currentQuestion, 'fail')"
|
@click="circleStore.markCompletion(currentQuestion, 'fail')"
|
||||||
>
|
>
|
||||||
<it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking>
|
<it-icon-smiley-thinking class="w-16 h-16 mr-4"></it-icon-smiley-thinking>
|
||||||
<span class="font-bold text-xl"> {{ $t("selfEvaluation.no") }} </span>
|
<span class="font-bold text-xl">{{ $t("selfEvaluation.no") }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,47 @@
|
||||||
import CircleDiagram from "@/components/learningPath/CircleDiagram.vue";
|
import CircleDiagram from "@/components/learningPath/CircleDiagram.vue";
|
||||||
import CircleOverview from "@/components/learningPath/CircleOverview.vue";
|
import CircleOverview from "@/components/learningPath/CircleOverview.vue";
|
||||||
import LearningSequence from "@/components/learningPath/LearningSequence.vue";
|
import LearningSequence from "@/components/learningPath/LearningSequence.vue";
|
||||||
|
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||||
|
import ItModal from "@/components/ui/ItModal.vue";
|
||||||
import * as log from "loglevel";
|
import * as log from "loglevel";
|
||||||
|
import { computed, onMounted, reactive, ref } from "vue";
|
||||||
|
|
||||||
import { useAppStore } from "@/stores/app";
|
import { useAppStore } from "@/stores/app";
|
||||||
import { useCircleStore } from "@/stores/circle";
|
import { useCircleStore } from "@/stores/circle";
|
||||||
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||||
|
import type { CourseSessionUser } from "@/types";
|
||||||
import { humanizeDuration } from "@/utils/humanizeDuration";
|
import { humanizeDuration } from "@/utils/humanizeDuration";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { computed, onMounted } from "vue";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
|
||||||
log.debug("CircleView.vue created", route);
|
interface Props {
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
circleSlug: string;
|
circleSlug: string;
|
||||||
}>();
|
profileUser?: CourseSessionUser;
|
||||||
|
readonly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
readonly: false,
|
||||||
|
profileUser: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
log.debug("CirclePage created", props.readonly, props.profileUser);
|
||||||
|
|
||||||
|
const showUploadModal = ref(false);
|
||||||
|
const formData = reactive({
|
||||||
|
file: "",
|
||||||
|
name: "",
|
||||||
|
learningSequence: {
|
||||||
|
id: -1,
|
||||||
|
name: t("circlePage.documents.chooseSequence"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
appStore.showMainNavigationBar = true;
|
appStore.showMainNavigationBar = true;
|
||||||
|
|
@ -34,11 +58,31 @@ const duration = computed(() => {
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dropdownLearningSequences = computed(() =>
|
||||||
|
circleStore.circle?.learningSequences.map((sequence) => ({
|
||||||
|
id: sequence.id,
|
||||||
|
name: sequence.title,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
log.debug("CircleView.vue mounted", props.courseSlug, props.circleSlug);
|
log.debug(
|
||||||
|
"CirclePage mounted",
|
||||||
|
props.courseSlug,
|
||||||
|
props.circleSlug,
|
||||||
|
props.profileUser
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await circleStore.loadCircle(props.courseSlug, props.circleSlug);
|
if (props.profileUser) {
|
||||||
|
await circleStore.loadCircle(
|
||||||
|
props.courseSlug,
|
||||||
|
props.circleSlug,
|
||||||
|
props.profileUser.user_id
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await circleStore.loadCircle(props.courseSlug, props.circleSlug);
|
||||||
|
}
|
||||||
|
|
||||||
if (route.hash.startsWith("#ls-") || route.hash.startsWith("#lu-")) {
|
if (route.hash.startsWith("#ls-") || route.hash.startsWith("#lu-")) {
|
||||||
const slugEnd = route.hash.replace("#", "");
|
const slugEnd = route.hash.replace("#", "");
|
||||||
|
|
@ -83,9 +127,33 @@ onMounted(async () => {
|
||||||
<div>
|
<div>
|
||||||
<div class="circle-container bg-gray-200">
|
<div class="circle-container bg-gray-200">
|
||||||
<div class="circle max-w-9xl">
|
<div class="circle max-w-9xl">
|
||||||
|
<div v-if="profileUser" class="user-profile">
|
||||||
|
<header
|
||||||
|
class="flex flex-row items-center p-8 bg-white relative shadow-xl"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="w-32 h-32 rounded-full mr-8"
|
||||||
|
:src="profileUser.avatar_url"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<h1 class="mb-2">
|
||||||
|
{{ profileUser.first_name }} {{ profileUser.last_name }}
|
||||||
|
</h1>
|
||||||
|
<div>
|
||||||
|
<router-link
|
||||||
|
class="link"
|
||||||
|
:to="`/course/${courseSlug}/cockpit/profile/${profileUser.user_id}`"
|
||||||
|
>
|
||||||
|
Profil anzeigen
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
<div class="flex flex-col lg:flex-row">
|
<div class="flex flex-col lg:flex-row">
|
||||||
<div class="flex-initial lg:w-128 px-4 py-4 lg:px-8 lg:pt-4 bg-white">
|
<div class="flex-initial lg:w-128 px-4 py-4 lg:px-8 lg:pt-4 bg-white">
|
||||||
<router-link
|
<router-link
|
||||||
|
v-if="!props.readonly"
|
||||||
:to="`/course/${props.courseSlug}/learn`"
|
:to="`/course/${props.courseSlug}/learn`"
|
||||||
class="btn-text inline-flex items-center px-3 py-4"
|
class="btn-text inline-flex items-center px-3 py-4"
|
||||||
data-cy="back-to-learning-path-button"
|
data-cy="back-to-learning-path-button"
|
||||||
|
|
@ -104,15 +172,15 @@ onMounted(async () => {
|
||||||
<CircleDiagram></CircleDiagram>
|
<CircleDiagram></CircleDiagram>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-t-2 mt-4 lg:hidden">
|
<div v-if="!props.readonly" class="border-t-2 mt-4 lg:hidden">
|
||||||
<div
|
<div
|
||||||
class="mt-4 inline-flex items-center"
|
class="mt-4 inline-flex items-center"
|
||||||
@click="circleStore.page = 'OVERVIEW'"
|
@click="circleStore.page = 'OVERVIEW'"
|
||||||
>
|
>
|
||||||
<it-icon-info class="mr-2" />
|
<it-icon-info class="mr-2" />
|
||||||
Das lernst du in diesem Circle
|
{{ $t("circlePage.circleContentBoxTitle") }}
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-flex items-center">
|
<div v-if="!props.readonly" class="inline-flex items-center">
|
||||||
<it-icon-message class="mr-2" />
|
<it-icon-message class="mr-2" />
|
||||||
Fachexpertin kontaktieren
|
Fachexpertin kontaktieren
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -135,8 +203,25 @@ onMounted(async () => {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="expert border mt-8 p-6">
|
<div v-if="!props.readonly" class="block border mt-8 p-6">
|
||||||
<h3 class="text-blue-dark">Hast du Fragen?</h3>
|
<h3 class="text-blue-dark">
|
||||||
|
{{ $t("circlePage.documents.title") }}
|
||||||
|
</h3>
|
||||||
|
<div v-if="courseSessionsStore.hasCockpit">
|
||||||
|
<div class="leading-relaxed mt-4">
|
||||||
|
{{ $t("circlePage.documents.description") }}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="btn-primary mt-4 text-xl"
|
||||||
|
@click="showUploadModal = true"
|
||||||
|
>
|
||||||
|
{{ $t("circlePage.documents.action") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!props.readonly" class="expert border mt-8 p-6">
|
||||||
|
<h3 class="text-blue-dark">{{ $t("circlePage.gotQuestions") }}</h3>
|
||||||
<div class="leading-relaxed mt-4">
|
<div class="leading-relaxed mt-4">
|
||||||
Tausche dich mit der Fachexpertin aus für den Circle Analyse aus.
|
Tausche dich mit der Fachexpertin aus für den Circle Analyse aus.
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -155,12 +240,50 @@ onMounted(async () => {
|
||||||
>
|
>
|
||||||
<LearningSequence
|
<LearningSequence
|
||||||
:learning-sequence="learningSequence"
|
:learning-sequence="learningSequence"
|
||||||
|
:readonly="props.readonly"
|
||||||
></LearningSequence>
|
></LearningSequence>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ItModal v-model="showUploadModal">
|
||||||
|
<template #title>{{ $t("circlePage.documents.action") }}</template>
|
||||||
|
<template #body>
|
||||||
|
<form>
|
||||||
|
<label class="block text-bold" for="upload">
|
||||||
|
{{ $t("circlePage.documents.fileLabel") }}
|
||||||
|
</label>
|
||||||
|
<div class="btn-secondary mt-4 mb-8 text-xl relative cursor-pointer">
|
||||||
|
<input id="upload" type="file" class="absolute opacity-0" />
|
||||||
|
{{ $t("circlePage.documents.modalAction") }}
|
||||||
|
</div>
|
||||||
|
<!--p>{{ $t("circlePage.documentsModalInformation") }}</p-->
|
||||||
|
<div class="mb-8">
|
||||||
|
<label class="block text-bold mb-4" for="name">
|
||||||
|
{{ $t("circlePage.documents.modalFileName") }}
|
||||||
|
</label>
|
||||||
|
<input id="name" type="text" class="w-1/2 mb-2" />
|
||||||
|
<p>{{ $t("circlePage.documents.modalNameInformation") }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="mb-8">
|
||||||
|
<label class="block text-bold mb-4" for="learningsequnce">
|
||||||
|
{{ $t("general.learningSequence") }}
|
||||||
|
</label>
|
||||||
|
<ItDropdownSelect
|
||||||
|
v-model="formData.learningSequence"
|
||||||
|
class="w-full lg:w-96 mt-4 lg:mt-0"
|
||||||
|
:items="dropdownLearningSequences"
|
||||||
|
></ItDropdownSelect>
|
||||||
|
</div>
|
||||||
|
<div class="-mx-8 px-8 pt-4 border-t">
|
||||||
|
<button class="btn-primary text-xl mb-0">
|
||||||
|
{{ $t("general.save") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
</ItModal>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,7 @@ watch(dropdownSelected, (newValue) =>
|
||||||
:description="$t('mediaLibrary.learningMedia.description')"
|
:description="$t('mediaLibrary.learningMedia.description')"
|
||||||
icon="lernmedien-overview"
|
icon="lernmedien-overview"
|
||||||
class="mb-6"
|
class="mb-6"
|
||||||
>
|
></OverviewCard>
|
||||||
</OverviewCard>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,8 @@ const mediaList = computed(() => {
|
||||||
:to="item.value.url"
|
:to="item.value.url"
|
||||||
:blank="item.value.open_window"
|
:blank="item.value.open_window"
|
||||||
class="link"
|
class="link"
|
||||||
>{{ item.value.link_display_text }}
|
>
|
||||||
|
{{ item.value.link_display_text }}
|
||||||
</media-link>
|
</media-link>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { useUserStore } from "@/stores/user";
|
import { useUserStore } from "@/stores/user";
|
||||||
import type { NavigationGuardWithThis, RouteLocationNormalized } from "vue-router";
|
import type { NavigationGuardWithThis, RouteLocationNormalized } from "vue-router";
|
||||||
|
|
||||||
export const updateLoggedIn: NavigationGuardWithThis<undefined> = (_to) => {
|
export const updateLoggedIn: NavigationGuardWithThis<undefined> = async (_to) => {
|
||||||
const loggedIn = getCookieValue("loginStatus") === "true";
|
const loggedIn = getCookieValue("loginStatus") === "true";
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
userStore.$patch({ loggedIn });
|
userStore.$patch({ loggedIn });
|
||||||
if (loggedIn && !userStore.email) {
|
if (loggedIn && !userStore.id) {
|
||||||
userStore.fetchUser();
|
await userStore.fetchUser();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,11 @@ const router = createRouter({
|
||||||
component: () => import("@/pages/cockpit/CockpitUserProfilePage.vue"),
|
component: () => import("@/pages/cockpit/CockpitUserProfilePage.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "profile/:userId/:circleSlug",
|
||||||
|
component: () => import("@/pages/cockpit/CockpitUserCirclePage.vue"),
|
||||||
|
props: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -128,6 +133,10 @@ const router = createRouter({
|
||||||
path: "/profile",
|
path: "/profile",
|
||||||
component: () => import("@/pages/ProfilePage.vue"),
|
component: () => import("@/pages/ProfilePage.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/notifications",
|
||||||
|
component: () => import("@/pages/NotificationsPage.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/styleguide",
|
path: "/styleguide",
|
||||||
component: () => import("../pages/StyleGuidePage.vue"),
|
component: () => import("../pages/StyleGuidePage.vue"),
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { defineStore } from "pinia";
|
||||||
export type CockpitStoreState = {
|
export type CockpitStoreState = {
|
||||||
courseSessionUsers: CourseSessionUser[] | undefined;
|
courseSessionUsers: CourseSessionUser[] | undefined;
|
||||||
cockpitSessionUser: ExpertSessionUser | undefined;
|
cockpitSessionUser: ExpertSessionUser | undefined;
|
||||||
selectedCircle: number;
|
selectedCircles: number[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCockpitStore = defineStore({
|
export const useCockpitStore = defineStore({
|
||||||
|
|
@ -16,11 +16,15 @@ export const useCockpitStore = defineStore({
|
||||||
return {
|
return {
|
||||||
courseSessionUsers: undefined,
|
courseSessionUsers: undefined,
|
||||||
cockpitSessionUser: undefined,
|
cockpitSessionUser: undefined,
|
||||||
selectedCircle: -1,
|
selectedCircles: [],
|
||||||
} as CockpitStoreState;
|
} as CockpitStoreState;
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
circles: (state) => state.cockpitSessionUser?.circles,
|
circles: (state) => state.cockpitSessionUser?.circles,
|
||||||
|
selectedCirclesTitles: (state) =>
|
||||||
|
state.cockpitSessionUser?.circles
|
||||||
|
.filter((circle) => state.selectedCircles.indexOf(circle.id) > -1)
|
||||||
|
.map((circle) => circle.title),
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async loadCourseSessionUsers(courseSlug: string, reload = false) {
|
async loadCourseSessionUsers(courseSlug: string, reload = false) {
|
||||||
|
|
@ -32,8 +36,8 @@ export const useCockpitStore = defineStore({
|
||||||
this.courseSessionUsers = data.users;
|
this.courseSessionUsers = data.users;
|
||||||
this.cockpitSessionUser = data.cockpit_user;
|
this.cockpitSessionUser = data.cockpit_user;
|
||||||
|
|
||||||
if (this.cockpitSessionUser.circles?.length > 0) {
|
if (this.cockpitSessionUser && this.cockpitSessionUser.circles?.length > 0) {
|
||||||
this.selectedCircle = this.cockpitSessionUser.circles[0].id;
|
this.selectedCircles = [this.cockpitSessionUser.circles[0].id];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.courseSessionUsers) {
|
if (!this.courseSessionUsers) {
|
||||||
|
|
@ -41,5 +45,16 @@ export const useCockpitStore = defineStore({
|
||||||
}
|
}
|
||||||
return this.courseSessionUsers;
|
return this.courseSessionUsers;
|
||||||
},
|
},
|
||||||
|
toggleCourseSelection(id: number) {
|
||||||
|
if (this.selectedCircles.indexOf(id) < 0) {
|
||||||
|
this.selectedCircles.push(id);
|
||||||
|
} else {
|
||||||
|
if (this.selectedCircles.length === 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const index = this.selectedCircles.indexOf(id);
|
||||||
|
this.selectedCircles.splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ export const useCourseSessionsStore = defineStore({
|
||||||
hasCockpit() {
|
hasCockpit() {
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
return (
|
return (
|
||||||
this.courseSessionForRoute.experts.filter(
|
this.courseSessionForRoute &&
|
||||||
|
(this.courseSessionForRoute as unknown as CourseSession).experts.filter(
|
||||||
(expert) => expert.user_id === userStore.id
|
(expert) => expert.user_id === userStore.id
|
||||||
).length > 0
|
).length > 0
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export const useMediaLibraryStore = defineStore({
|
||||||
selectedLearningPath: { id: 1, name: "Alle Lehrgänge" },
|
selectedLearningPath: { id: 1, name: "Alle Lehrgänge" },
|
||||||
availableLearningPaths: [
|
availableLearningPaths: [
|
||||||
{ id: 1, name: "Alle Lehrgänge" },
|
{ id: 1, name: "Alle Lehrgänge" },
|
||||||
{ id: 2, name: "Versicherungsvermittler/in" },
|
{ id: 2, name: "Versicherungsvermittler/-in" },
|
||||||
],
|
],
|
||||||
} as MediaLibraryStoreState;
|
} as MediaLibraryStoreState;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -71,20 +71,14 @@ export const useUserStore = defineStore({
|
||||||
window.location.href = redirectUrl;
|
window.location.href = redirectUrl;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
fetchUser() {
|
async fetchUser() {
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
itGetCached("/api/core/me/")
|
const data = await itGetCached("/api/core/me/");
|
||||||
.then((data) => {
|
this.$state = data;
|
||||||
this.$state = data;
|
this.loggedIn = true;
|
||||||
this.loggedIn = true;
|
appStore.userLoaded = true;
|
||||||
appStore.userLoaded = true;
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
const courseSessionsStore = useCourseSessionsStore();
|
await courseSessionsStore.loadCourseSessionsData();
|
||||||
courseSessionsStore.loadCourseSessionsData();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.loggedIn = false;
|
|
||||||
appStore.userLoaded = true;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ describe("circle page", () => {
|
||||||
cy.manageCommand("cypress_reset");
|
cy.manageCommand("cypress_reset");
|
||||||
|
|
||||||
login("admin", "test");
|
login("admin", "test");
|
||||||
cy.visit("/learn/test-lehrgang-lp/analyse");
|
cy.visit("/course/test-lehrgang/learn/analyse");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can open circle page", () => {
|
it("can open circle page", () => {
|
||||||
|
|
@ -92,7 +92,7 @@ describe("circle page", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can open learning content by url", () => {
|
it("can open learning content by url", () => {
|
||||||
cy.visit("/learn/test-lehrgang-lp/analyse/reiseversicherung");
|
cy.visit("/course/test-lehrgang/learn/analyse/reiseversicherung");
|
||||||
cy.get('[data-cy="ln-title"]').should("contain", "Reiseversicherung");
|
cy.get('[data-cy="ln-title"]').should("contain", "Reiseversicherung");
|
||||||
|
|
||||||
cy.get('[data-cy="close-learning-content"]').click();
|
cy.get('[data-cy="close-learning-content"]').click();
|
||||||
|
|
|
||||||
|
|
@ -5,28 +5,50 @@ describe("Competence", () => {
|
||||||
cy.manageCommand("cypress_reset");
|
cy.manageCommand("cypress_reset");
|
||||||
|
|
||||||
login("admin", "test");
|
login("admin", "test");
|
||||||
cy.visit("/learn/test-lehrgang-lp/analyse");
|
cy.visit("/course/versicherungsvermittler-in/learn/analyse");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("self evaluation should be neutral", () => {
|
it("self evaluation should be neutral", () => {
|
||||||
cy.get('[data-cy="test-lehrgang-lp-circle-analyse-lu-fahrzeug"]').find('[data-cy="unknown"]').should('exist');
|
cy.get(
|
||||||
|
'[data-cy="versicherungsvermittler-in-lp-circle-analyse-lu-fahrzeug"]'
|
||||||
|
)
|
||||||
|
.find('[data-cy="unknown"]')
|
||||||
|
.should("exist");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to make a happy self evaluation", () => {
|
it("should be able to make a happy self evaluation", () => {
|
||||||
cy.get('[data-cy="test-lehrgang-lp-circle-analyse-lu-fahrzeug"]').click();
|
cy.get(
|
||||||
cy.makeSelfEvaluation([true, true])
|
'[data-cy="versicherungsvermittler-in-lp-circle-analyse-lu-fahrzeug"]'
|
||||||
cy.get('[data-cy="test-lehrgang-lp-circle-analyse-lu-fahrzeug"]').find('[data-cy="success"]').should('exist');
|
).click();
|
||||||
|
cy.makeSelfEvaluation([true, true, true]);
|
||||||
|
cy.get(
|
||||||
|
'[data-cy="versicherungsvermittler-in-lp-circle-analyse-lu-fahrzeug"]'
|
||||||
|
)
|
||||||
|
.find('[data-cy="success"]')
|
||||||
|
.should("exist");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to make a fail self evaluation", () => {
|
it("should be able to make a fail self evaluation", () => {
|
||||||
cy.get('[data-cy="test-lehrgang-lp-circle-analyse-lu-fahrzeug"]').click();
|
cy.get(
|
||||||
cy.makeSelfEvaluation([false, false])
|
'[data-cy="versicherungsvermittler-in-lp-circle-analyse-lu-fahrzeug"]'
|
||||||
cy.get('[data-cy="test-lehrgang-lp-circle-analyse-lu-fahrzeug"]').find('[data-cy="fail"]').should('exist');
|
).click();
|
||||||
|
cy.makeSelfEvaluation([false, false, false]);
|
||||||
|
cy.get(
|
||||||
|
'[data-cy="versicherungsvermittler-in-lp-circle-analyse-lu-fahrzeug"]'
|
||||||
|
)
|
||||||
|
.find('[data-cy="fail"]')
|
||||||
|
.should("exist");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be able to make a mixed self evaluation", () => {
|
it("should be able to make a mixed self evaluation", () => {
|
||||||
cy.get('[data-cy="test-lehrgang-lp-circle-analyse-lu-fahrzeug"]').click();
|
cy.get(
|
||||||
cy.makeSelfEvaluation([false, true])
|
'[data-cy="versicherungsvermittler-in-lp-circle-analyse-lu-fahrzeug"]'
|
||||||
cy.get('[data-cy="test-lehrgang-lp-circle-analyse-lu-fahrzeug"]').find('[data-cy="fail"]').should('exist');
|
).click();
|
||||||
|
cy.makeSelfEvaluation([false, true, true]);
|
||||||
|
cy.get(
|
||||||
|
'[data-cy="versicherungsvermittler-in-lp-circle-analyse-lu-fahrzeug"]'
|
||||||
|
)
|
||||||
|
.find('[data-cy="fail"]')
|
||||||
|
.should("exist");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -7,40 +7,46 @@ describe("learningPath page", () => {
|
||||||
|
|
||||||
it("can open learningPath page", () => {
|
it("can open learningPath page", () => {
|
||||||
login("admin", "test");
|
login("admin", "test");
|
||||||
cy.visit("/learn/versicherungsvermittlerin-lp");
|
cy.visit("/course/versicherungsvermittler-in/learn");
|
||||||
|
|
||||||
cy.get('[data-cy="learning-path-title"]').should(
|
cy.get('[data-cy="learning-path-title"]').should(
|
||||||
"contain",
|
"contain",
|
||||||
"Versicherungsvermittler/in"
|
"Versicherungsvermittler/-in"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("click on circle on learningPath page will open circle", () => {
|
it("/course/versicherungsvermittler-in/learn", () => {
|
||||||
login("admin", "test");
|
login("admin", "test");
|
||||||
cy.visit("/learn/test-lehrgang-lp");
|
cy.visit("/course/versicherungsvermittler-in/learn");
|
||||||
|
|
||||||
cy.get('[data-cy="circle-analyse"]').click({ force: true });
|
cy.get('[data-cy="circle-analyse"]').click({ force: true });
|
||||||
|
|
||||||
cy.url().should("include", "/learn/test-lehrgang-lp/analyse");
|
cy.url().should(
|
||||||
|
"include",
|
||||||
|
"/course/versicherungsvermittler-in/learn/analyse"
|
||||||
|
);
|
||||||
cy.get('[data-cy="circle-title"]').should("contain", "Analyse");
|
cy.get('[data-cy="circle-title"]').should("contain", "Analyse");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("open listView and click on circle will open circle", () => {
|
it("open listView and click on circle will open circle", () => {
|
||||||
login("admin", "test");
|
login("admin", "test");
|
||||||
cy.visit("/learn/test-lehrgang-lp");
|
cy.visit("/course/versicherungsvermittler-in/learn");
|
||||||
|
|
||||||
cy.get('[data-cy="show-list-view"]').click();
|
cy.get('[data-cy="show-list-view"]').click();
|
||||||
cy.get('[data-cy="full-screen-modal"]').should("be.visible");
|
cy.get('[data-cy="full-screen-modal"]').should("be.visible");
|
||||||
|
|
||||||
cy.get('[data-cy="circle-analyse-vertical"]').click({ force: true });
|
cy.get('[data-cy="circle-analyse-vertical"]').click({ force: true });
|
||||||
|
|
||||||
cy.url().should("include", "/learn/test-lehrgang-lp/analyse");
|
cy.url().should(
|
||||||
|
"include",
|
||||||
|
"/course/versicherungsvermittler-in/learn/analyse"
|
||||||
|
);
|
||||||
cy.get('[data-cy="circle-title"]').should("contain", "Analyse");
|
cy.get('[data-cy="circle-title"]').should("contain", "Analyse");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("weiter gehts button will open next circle", () => {
|
it("weiter gehts button will open next circle", () => {
|
||||||
login("admin", "test");
|
login("admin", "test");
|
||||||
cy.visit("/learn/test-lehrgang-lp");
|
cy.visit("/course/versicherungsvermittler-in/learn");
|
||||||
|
|
||||||
// first click will open first circle
|
// first click will open first circle
|
||||||
cy.get('[data-cy="lp-continue-button"]').should("contain", "Los geht's");
|
cy.get('[data-cy="lp-continue-button"]').should("contain", "Los geht's");
|
||||||
|
|
@ -51,7 +57,7 @@ describe("learningPath page", () => {
|
||||||
// mark a learning content in second circle
|
// mark a learning content in second circle
|
||||||
cy.get('[data-cy="circle-analyse"]').click({ force: true });
|
cy.get('[data-cy="circle-analyse"]').click({ force: true });
|
||||||
cy.get(
|
cy.get(
|
||||||
'[data-cy="test-lehrgang-lp-circle-analyse-lc-fachcheck-fahrzeug-checkbox"] > .cy-checkbox'
|
'[data-cy="versicherungsvermittler-in-lp-circle-analyse-lc-fachcheck-fahrzeug-checkbox"] > .cy-checkbox'
|
||||||
).click();
|
).click();
|
||||||
cy.get('[data-cy="back-to-learning-path-button"]').click();
|
cy.get('[data-cy="back-to-learning-path-button"]').click();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
import { login } from "./helpers";
|
import { login } from "./helpers";
|
||||||
|
|
||||||
describe("login", () => {
|
describe("login", () => {
|
||||||
|
Cypress.on("uncaught:exception", (err, runnable) => {
|
||||||
|
// do not fail on failed requests during tests
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.manageCommand("cypress_reset");
|
cy.manageCommand("cypress_reset");
|
||||||
});
|
});
|
||||||
|
|
@ -31,7 +36,7 @@ describe("login", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("login will redirect to requestet page", () => {
|
it("login will redirect to requestet page", () => {
|
||||||
cy.visit("/learn/versicherungsvermittlerin-lp");
|
cy.visit("/course/versicherungsvermittler-in/learn");
|
||||||
cy.get("h1").should("contain", "Login");
|
cy.get("h1").should("contain", "Login");
|
||||||
|
|
||||||
cy.get("#username").type("admin");
|
cy.get("#username").type("admin");
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ describe("MediaLibrary", () => {
|
||||||
cy.manageCommand("cypress_reset");
|
cy.manageCommand("cypress_reset");
|
||||||
|
|
||||||
login("admin", "test");
|
login("admin", "test");
|
||||||
cy.visit("/learn/test-lehrgang-lp/analyse");
|
cy.visit("/");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be accessible", () => {
|
it("should be accessible", () => {
|
||||||
cy.get('[data-cy="medialibrary-link"]').click();
|
cy.get('[data-cy="medialibrary-link"]').click();
|
||||||
cy.get('[data-cy="Handlungsfelder-link"]').click();
|
cy.get('[data-cy="Handlungsfelder-link"]').click();
|
||||||
cy.get('[data-cy="Fahrzeug-link"]').click();
|
cy.get('[data-cy="Fahrzeug-link"]').click();
|
||||||
cy.get('[data-cy="hf-title"]').should('contain', 'Fahrzeug')
|
cy.get('[data-cy="hf-title"]').should("contain", "Fahrzeug");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -122,10 +122,11 @@ def create_default_users(user_model=User, group_model=Group, default_password=No
|
||||||
last_name="VV",
|
last_name="VV",
|
||||||
)
|
)
|
||||||
_create_student_user(
|
_create_student_user(
|
||||||
email="patrizia.huggel@eiger-versicherung.ch",
|
email="patrizia.huggel@eiger-versicherungen.ch",
|
||||||
first_name="Patrizia",
|
first_name="Patrizia",
|
||||||
last_name="Huggel",
|
last_name="Huggel",
|
||||||
avatar_url="/static/avatars/uk1.patrizia.huggel.jpg",
|
avatar_url="/static/avatars/uk1.patrizia.huggel.jpg",
|
||||||
|
password="myvbv1234",
|
||||||
)
|
)
|
||||||
_create_student_user(
|
_create_student_user(
|
||||||
email="daniel.tanaka@eiger-versicherung.ch",
|
email="daniel.tanaka@eiger-versicherung.ch",
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,4 @@ from vbv_lernwelt.course.models import CourseCompletion
|
||||||
@click.command()
|
@click.command()
|
||||||
def command():
|
def command():
|
||||||
print("cypress reset data")
|
print("cypress reset data")
|
||||||
|
|
||||||
CourseCompletion.objects.all().delete()
|
CourseCompletion.objects.all().delete()
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ def create_versicherungsvermittlerin_with_categories(
|
||||||
apps=None,
|
apps=None,
|
||||||
schema_editor=None,
|
schema_editor=None,
|
||||||
course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
||||||
title="Versicherungsvermittler/in",
|
title="Versicherungsvermittler/-in",
|
||||||
):
|
):
|
||||||
if apps is not None:
|
if apps is not None:
|
||||||
Course = apps.get_model("course", "Course")
|
Course = apps.get_model("course", "Course")
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,12 @@ class CourseFactory(DjangoModelFactory):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Course
|
model = Course
|
||||||
|
|
||||||
title = "Versicherungsvermittler/in"
|
title = "Versicherungsvermittler/-in"
|
||||||
category_name = "Handlungsfeld"
|
category_name = "Handlungsfeld"
|
||||||
|
|
||||||
|
|
||||||
class CoursePageFactory(wagtail_factories.PageFactory):
|
class CoursePageFactory(wagtail_factories.PageFactory):
|
||||||
title = "Versicherungsvermittler/in"
|
title = "Versicherungsvermittler/-in"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CoursePage
|
model = CoursePage
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ def command():
|
||||||
# course session Versicherungsvermittler/in
|
# course session Versicherungsvermittler/in
|
||||||
cs = CourseSession.objects.create(
|
cs = CourseSession.objects.create(
|
||||||
course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
||||||
title="Versicherungsvermittler/in",
|
title="Versicherungsvermittler/-in",
|
||||||
)
|
)
|
||||||
for user_data in default_users:
|
for user_data in default_users:
|
||||||
CourseSessionUser.objects.create(
|
CourseSessionUser.objects.create(
|
||||||
|
|
@ -80,7 +80,7 @@ def command():
|
||||||
role=CourseSessionUser.Role.EXPERT,
|
role=CourseSessionUser.Role.EXPERT,
|
||||||
)
|
)
|
||||||
csu.expert.add(
|
csu.expert.add(
|
||||||
Circle.objects.get(slug="versicherungsvermittlerin-lp-circle-einstieg")
|
Circle.objects.get(slug="versicherungsvermittler-in-lp-circle-einstieg")
|
||||||
)
|
)
|
||||||
csu = CourseSessionUser.objects.create(
|
csu = CourseSessionUser.objects.create(
|
||||||
course_session=cs,
|
course_session=cs,
|
||||||
|
|
@ -88,7 +88,7 @@ def command():
|
||||||
role=CourseSessionUser.Role.EXPERT,
|
role=CourseSessionUser.Role.EXPERT,
|
||||||
)
|
)
|
||||||
csu.expert.add(
|
csu.expert.add(
|
||||||
Circle.objects.get(slug="versicherungsvermittlerin-lp-circle-analyse")
|
Circle.objects.get(slug="versicherungsvermittler-in-lp-circle-analyse")
|
||||||
)
|
)
|
||||||
|
|
||||||
# course session Überbetriebliche Kurse Lehrjahr 1 - Region Bern
|
# course session Überbetriebliche Kurse Lehrjahr 1 - Region Bern
|
||||||
|
|
@ -119,7 +119,7 @@ def command():
|
||||||
# figma demo users and data
|
# figma demo users and data
|
||||||
csu = CourseSessionUser.objects.create(
|
csu = CourseSessionUser.objects.create(
|
||||||
course_session=cs,
|
course_session=cs,
|
||||||
user=User.objects.get(username="patrizia.huggel@eiger-versicherung.ch"),
|
user=User.objects.get(username="patrizia.huggel@eiger-versicherungen.ch"),
|
||||||
role=CourseSessionUser.Role.EXPERT,
|
role=CourseSessionUser.Role.EXPERT,
|
||||||
)
|
)
|
||||||
csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-einstieg"))
|
csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-einstieg"))
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ class CourseSessionUser(models.Model):
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
|
"session_id": self.course_session.id,
|
||||||
"session_title": self.course_session.title,
|
"session_title": self.course_session.title,
|
||||||
"user_id": self.user.id,
|
"user_id": self.user.id,
|
||||||
"first_name": self.user.first_name,
|
"first_name": self.user.first_name,
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,11 @@ def get_course_session_users(request, course_slug):
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"cockpit_user": cockpit_user_csu[0].to_dict()
|
"cockpit_user": cockpit_user_csu[0].to_dict()
|
||||||
| {"circles": cockpit_user_csu[0].expert.all().values("id", "title")},
|
| {
|
||||||
|
"circles": cockpit_user_csu[0]
|
||||||
|
.expert.all()
|
||||||
|
.values("id", "title", "slug", "translation_key")
|
||||||
|
},
|
||||||
"users": user_data,
|
"users": user_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -811,7 +811,7 @@ def create_standard_learning_unit(
|
||||||
(
|
(
|
||||||
"media_library",
|
"media_library",
|
||||||
MediaLibraryBlockFactory(
|
MediaLibraryBlockFactory(
|
||||||
url=f"/media/versicherungsvermittlerin-media/category/{slugify(category_name)}"
|
url=f"/media/versicherungsvermittler-in-media/category/{slugify(category_name)}"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ from vbv_lernwelt.learnpath.models_learning_unit_content import (
|
||||||
|
|
||||||
|
|
||||||
class LearningPathFactory(wagtail_factories.PageFactory):
|
class LearningPathFactory(wagtail_factories.PageFactory):
|
||||||
title = "Versicherungsvermittler/in"
|
title = "Versicherungsvermittler/-in"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = LearningPath
|
model = LearningPath
|
||||||
|
|
|
||||||
|
|
@ -131,25 +131,25 @@ die der Fahrzeugbesitzer und die Fahrzeugbesitzerin in einem grösseren Schadenf
|
||||||
create_internal_link_block(
|
create_internal_link_block(
|
||||||
InternalLinkBlockFactory(
|
InternalLinkBlockFactory(
|
||||||
title="Circle: Einstieg – Lernsequenz: Anwenden",
|
title="Circle: Einstieg – Lernsequenz: Anwenden",
|
||||||
url="/learn/versicherungsvermittlerin-lp/einstieg#lu-fahrzeug",
|
url="/learn/versicherungsvermittler-in-lp/einstieg#lu-fahrzeug",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_internal_link_block(
|
create_internal_link_block(
|
||||||
InternalLinkBlockFactory(
|
InternalLinkBlockFactory(
|
||||||
title="Circle: Analyse – Lernsequenz: Anwenden",
|
title="Circle: Analyse – Lernsequenz: Anwenden",
|
||||||
url="/learn/versicherungsvermittlerin-lp/analyse#lu-fahrzeug",
|
url="/learn/versicherungsvermittler-in-lp/analyse#lu-fahrzeug",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_internal_link_block(
|
create_internal_link_block(
|
||||||
InternalLinkBlockFactory(
|
InternalLinkBlockFactory(
|
||||||
title="Circle: Lösung – Lernsequenz: Anwenden",
|
title="Circle: Lösung – Lernsequenz: Anwenden",
|
||||||
url="/learn/versicherungsvermittlerin-lp/lösung#lu-fahrzeug",
|
url="/learn/versicherungsvermittler-in-lp/lösung#lu-fahrzeug",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_internal_link_block(
|
create_internal_link_block(
|
||||||
InternalLinkBlockFactory(
|
InternalLinkBlockFactory(
|
||||||
title="Circle: Abschluss – Lernsequenz: Anwenden",
|
title="Circle: Abschluss – Lernsequenz: Anwenden",
|
||||||
url="/learn/versicherungsvermittlerin-lp/abschluss#lu-fahrzeug",
|
url="/learn/versicherungsvermittler-in-lp/abschluss#lu-fahrzeug",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -161,14 +161,14 @@ die der Fahrzeugbesitzer und die Fahrzeugbesitzerin in einem grösseren Schadenf
|
||||||
RelativeLinkBlockFactory(
|
RelativeLinkBlockFactory(
|
||||||
title="Rechtsstreitigkeiten",
|
title="Rechtsstreitigkeiten",
|
||||||
description="VBV 303/12.3 Verkehrsrechtsschutz",
|
description="VBV 303/12.3 Verkehrsrechtsschutz",
|
||||||
url="/media/versicherungsvermittlerin-media/category/rechtsstreitigkeiten",
|
url="/media/versicherungsvermittler-in-media/category/rechtsstreitigkeiten",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_relative_link_block(
|
create_relative_link_block(
|
||||||
RelativeLinkBlockFactory(
|
RelativeLinkBlockFactory(
|
||||||
title="Reisen",
|
title="Reisen",
|
||||||
description="VBV 303/13 Reiseversicherung",
|
description="VBV 303/13 Reiseversicherung",
|
||||||
url="/media/versicherungsvermittlerin-media/category/reisen",
|
url="/media/versicherungsvermittler-in-media/category/reisen",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -236,25 +236,25 @@ Diese können negative Folgen verschiedener Art nach sich ziehen, darunter recht
|
||||||
create_internal_link_block(
|
create_internal_link_block(
|
||||||
InternalLinkBlockFactory(
|
InternalLinkBlockFactory(
|
||||||
title="Circle: Einstieg – Lernsequenz: Anwenden",
|
title="Circle: Einstieg – Lernsequenz: Anwenden",
|
||||||
url="/learn/versicherungsvermittlerin-lp/einstieg#lu-reisen",
|
url="/learn/versicherungsvermittler-in-lp/einstieg#lu-reisen",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_internal_link_block(
|
create_internal_link_block(
|
||||||
InternalLinkBlockFactory(
|
InternalLinkBlockFactory(
|
||||||
title="Circle: Analyse – Lernsequenz: Anwenden",
|
title="Circle: Analyse – Lernsequenz: Anwenden",
|
||||||
url="/learn/versicherungsvermittlerin-lp/analyse#lu-reisen",
|
url="/learn/versicherungsvermittler-in-lp/analyse#lu-reisen",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_internal_link_block(
|
create_internal_link_block(
|
||||||
InternalLinkBlockFactory(
|
InternalLinkBlockFactory(
|
||||||
title="Circle: Lösung – Lernsequenz: Anwenden",
|
title="Circle: Lösung – Lernsequenz: Anwenden",
|
||||||
url="/learn/versicherungsvermittlerin-lp/lösung#lu-reisen",
|
url="/learn/versicherungsvermittler-in-lp/lösung#lu-reisen",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_internal_link_block(
|
create_internal_link_block(
|
||||||
InternalLinkBlockFactory(
|
InternalLinkBlockFactory(
|
||||||
title="Circle: Abschluss – Lernsequenz: Anwenden",
|
title="Circle: Abschluss – Lernsequenz: Anwenden",
|
||||||
url="/learn/versicherungsvermittlerin-lp/abschluss#lu-reisen",
|
url="/learn/versicherungsvermittler-in-lp/abschluss#lu-reisen",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -266,21 +266,21 @@ Diese können negative Folgen verschiedener Art nach sich ziehen, darunter recht
|
||||||
RelativeLinkBlockFactory(
|
RelativeLinkBlockFactory(
|
||||||
title="Haushalt",
|
title="Haushalt",
|
||||||
description="VBV 303/03 Hausratversicherung",
|
description="VBV 303/03 Hausratversicherung",
|
||||||
url="/media/versicherungsvermittlerin-media/category/haushalt",
|
url="/media/versicherungsvermittler-in-media/category/haushalt",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_relative_link_block(
|
create_relative_link_block(
|
||||||
RelativeLinkBlockFactory(
|
RelativeLinkBlockFactory(
|
||||||
title="Rechtsstreitigkeiten",
|
title="Rechtsstreitigkeiten",
|
||||||
desciption="VBV 303/12 Rechtschutzversicherung",
|
desciption="VBV 303/12 Rechtschutzversicherung",
|
||||||
url="/media/versicherungsvermittlerin-media/category/rechtsstreitigkeiten",
|
url="/media/versicherungsvermittler-in-media/category/rechtsstreitigkeiten",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
create_relative_link_block(
|
create_relative_link_block(
|
||||||
RelativeLinkBlockFactory(
|
RelativeLinkBlockFactory(
|
||||||
title="Gesundheit",
|
title="Gesundheit",
|
||||||
description="VBV 304/Teil E Obligatorische Krankenversicherung",
|
description="VBV 304/Teil E Obligatorische Krankenversicherung",
|
||||||
url="/media/versicherungsvermittlerin-media/category/gesundheit",
|
url="/media/versicherungsvermittler-in-media/category/gesundheit",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ class InternalLinkBlockFactory(wagtail_factories.StructBlockFactory):
|
||||||
title = "Platzhalter interner Link"
|
title = "Platzhalter interner Link"
|
||||||
description = "Link to a Learning Content"
|
description = "Link to a Learning Content"
|
||||||
link_display_text = "Lerneinheit anzeigen"
|
link_display_text = "Lerneinheit anzeigen"
|
||||||
url = "/learn/versicherungsvermittlerin-lp/basis"
|
url = "/learn/versicherungsvermittler-in-lp/basis"
|
||||||
# TODO: page = blocks.PageChooserBlock mit Titel etc
|
# TODO: page = blocks.PageChooserBlock mit Titel etc
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -103,7 +103,7 @@ class RelativeLinkBlockFactory(wagtail_factories.StructBlockFactory):
|
||||||
description = "Platzhalter Querverweis"
|
description = "Platzhalter Querverweis"
|
||||||
link_display_text = "Handlungsfeld anzeigen"
|
link_display_text = "Handlungsfeld anzeigen"
|
||||||
icon_url = "/static/icons/demo/icon-hf-reisen.svg"
|
icon_url = "/static/icons/demo/icon-hf-reisen.svg"
|
||||||
url = "/media/versicherungsvermittlerin-media/category/fahrzeug"
|
url = "/media/versicherungsvermittler-in-media/category/fahrzeug"
|
||||||
# TODO: page = blocks.PageChooserBlock zu Handlungsfeld
|
# TODO: page = blocks.PageChooserBlock zu Handlungsfeld
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue