Add info block for teachers
Also refactor CirclePage Resolves VBV-310
This commit is contained in:
parent
96334b4eb6
commit
0bae4a8cb2
|
|
@ -16,6 +16,10 @@
|
||||||
"modalNameInformation": "Max. 70 Zeichen",
|
"modalNameInformation": "Max. 70 Zeichen",
|
||||||
"selectFile": "Bitte wähle eine Datei aus",
|
"selectFile": "Bitte wähle eine Datei aus",
|
||||||
"title": "Unterlagen",
|
"title": "Unterlagen",
|
||||||
|
"trainerDescription": "Finde auf Teams zusätzliche Inhalte für deinen Unterricht.",
|
||||||
|
"trainerLinkSrc": "https://teams.microsoft.com",
|
||||||
|
"trainerLinkText": "Inhalte auf Teams anschauen",
|
||||||
|
"trainerTitle": "Begleitung für Trainer",
|
||||||
"uploadErrorMessage": "Beim Hochladen ist ein Fehler aufgetreten. Bitte versuche es erneut.",
|
"uploadErrorMessage": "Beim Hochladen ist ein Fehler aufgetreten. Bitte versuche es erneut.",
|
||||||
"userDescription": "Hier findest du die Unterlagen, die dir die Fachexpertin zur Verfügung gestellt hat."
|
"userDescription": "Hier findest du die Unterlagen, die dir die Fachexpertin zur Verfügung gestellt hat."
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,29 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ItModal from "@/components/ui/ItModal.vue";
|
import log from "loglevel";
|
||||||
import * as log from "loglevel";
|
import { computed, onMounted } from "vue";
|
||||||
import { computed, onMounted, ref, watch } from "vue";
|
|
||||||
import CircleDiagram from "./CircleDiagram.vue";
|
import CircleDiagram from "./CircleDiagram.vue";
|
||||||
import CircleOverview from "./CircleOverview.vue";
|
import CircleOverview from "./CircleOverview.vue";
|
||||||
import DocumentUploadForm from "./DocumentUploadForm.vue";
|
import DocumentBlock from "./DocumentBlock.vue";
|
||||||
import LearningSequence from "./LearningSequence.vue";
|
import LearningSequence from "./LearningSequence.vue";
|
||||||
|
|
||||||
import { uploadCircleDocument } from "@/services/files";
|
|
||||||
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 { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||||
import type { CourseSessionUser, DocumentUploadData } from "@/types";
|
import type { CourseSessionUser } from "@/types";
|
||||||
import { humanizeDuration } from "@/utils/humanizeDuration";
|
import { humanizeDuration } from "@/utils/humanizeDuration";
|
||||||
import sumBy from "lodash/sumBy";
|
import sumBy from "lodash/sumBy";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
const route = useRoute();
|
export interface Props {
|
||||||
const courseSessionsStore = useCourseSessionsStore();
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
circleSlug: string;
|
circleSlug: string;
|
||||||
profileUser?: CourseSessionUser;
|
profileUser?: CourseSessionUser;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
readonly: false,
|
readonly: false,
|
||||||
profileUser: undefined,
|
profileUser: undefined,
|
||||||
|
|
@ -33,10 +31,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
|
|
||||||
log.debug("CirclePage created", props.readonly, props.profileUser);
|
log.debug("CirclePage created", props.readonly, props.profileUser);
|
||||||
|
|
||||||
const showUploadModal = ref(false);
|
|
||||||
const showUploadErrorMessage = ref(false);
|
|
||||||
const isUploading = ref(false);
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
appStore.showMainNavigationBar = true;
|
appStore.showMainNavigationBar = true;
|
||||||
|
|
||||||
|
|
@ -51,15 +45,6 @@ const duration = computed(() => {
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
const dropdownLearningSequences = computed(() =>
|
|
||||||
circleStore.circle?.learningSequences.map((sequence) => ({
|
|
||||||
id: sequence.id,
|
|
||||||
name: sequence.title,
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(showUploadModal, (_v) => (showUploadErrorMessage.value = false));
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
log.debug(
|
log.debug(
|
||||||
"CirclePage mounted",
|
"CirclePage mounted",
|
||||||
|
|
@ -107,28 +92,6 @@ onMounted(async () => {
|
||||||
log.error(error);
|
log.error(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function uploadDocument(data: DocumentUploadData) {
|
|
||||||
isUploading.value = true;
|
|
||||||
showUploadErrorMessage.value = false;
|
|
||||||
try {
|
|
||||||
if (!courseSessionsStore.currentCourseSession) {
|
|
||||||
throw new Error("No course session found");
|
|
||||||
}
|
|
||||||
const newDocument = await uploadCircleDocument(
|
|
||||||
data,
|
|
||||||
courseSessionsStore.currentCourseSession.id
|
|
||||||
);
|
|
||||||
const courseSessionStore = useCourseSessionsStore();
|
|
||||||
courseSessionStore.addDocument(newDocument);
|
|
||||||
showUploadModal.value = false;
|
|
||||||
isUploading.value = false;
|
|
||||||
} catch (error) {
|
|
||||||
log.error(error);
|
|
||||||
showUploadErrorMessage.value = true;
|
|
||||||
isUploading.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -213,60 +176,7 @@ async function uploadDocument(data: DocumentUploadData) {
|
||||||
{{ $t("circlePage.learnMore") }}
|
{{ $t("circlePage.learnMore") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!props.readonly" class="mt-8 block border p-6">
|
<DocumentBlock v-if="!readonly" />
|
||||||
<h3 class="text-blue-dark">
|
|
||||||
{{ $t("circlePage.documents.title") }}
|
|
||||||
</h3>
|
|
||||||
<div v-if="!courseSessionsStore.canUploadCircleDocuments">
|
|
||||||
<div class="mt-4 leading-relaxed">
|
|
||||||
{{ $t("circlePage.documents.userDescription") }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ol
|
|
||||||
v-if="
|
|
||||||
courseSessionsStore &&
|
|
||||||
courseSessionsStore.circleDocuments &&
|
|
||||||
courseSessionsStore.circleDocuments.length > 0
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
v-for="learningSequence of courseSessionsStore.circleDocuments"
|
|
||||||
:key="learningSequence.id"
|
|
||||||
>
|
|
||||||
<h4 class="text-bold mt-4">{{ learningSequence.title }}</h4>
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="document of learningSequence.documents"
|
|
||||||
:key="document.url"
|
|
||||||
>
|
|
||||||
<a :href="document.url" download>
|
|
||||||
<span>{{ document.name }}</span>
|
|
||||||
</a>
|
|
||||||
<button
|
|
||||||
v-if="courseSessionsStore.canUploadCircleDocuments"
|
|
||||||
type="button"
|
|
||||||
class="relative top-[1px] ml-2 inline-block h-3 w-3 cursor-pointer leading-6"
|
|
||||||
@click="courseSessionsStore.removeDocument(document.id)"
|
|
||||||
>
|
|
||||||
<it-icon-close class="h-3 w-3"></it-icon-close>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
<div v-if="courseSessionsStore.canUploadCircleDocuments">
|
|
||||||
<div class="mt-4 leading-relaxed">
|
|
||||||
{{ $t("circlePage.documents.expertDescription") }}
|
|
||||||
</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 mt-8 border p-6">
|
<div v-if="!props.readonly" class="expert mt-8 border p-6">
|
||||||
<h3 class="text-blue-dark">{{ $t("circlePage.gotQuestions") }}</h3>
|
<h3 class="text-blue-dark">{{ $t("circlePage.gotQuestions") }}</h3>
|
||||||
<div class="mt-4 leading-relaxed">
|
<div class="mt-4 leading-relaxed">
|
||||||
|
|
@ -312,17 +222,6 @@ async function uploadDocument(data: DocumentUploadData) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ItModal v-model="showUploadModal">
|
|
||||||
<template #title>{{ $t("circlePage.documents.action") }}</template>
|
|
||||||
<template #body>
|
|
||||||
<DocumentUploadForm
|
|
||||||
:learning-sequences="dropdownLearningSequences"
|
|
||||||
:show-upload-error-message="showUploadErrorMessage"
|
|
||||||
:is-uploading="isUploading"
|
|
||||||
@form-submit="uploadDocument"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</ItModal>
|
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
<template>
|
||||||
|
<div class="mt-8 block border p-6">
|
||||||
|
<!-- documents block -->
|
||||||
|
<h3 class="text-blue-dark">
|
||||||
|
{{ $t("circlePage.documents.title") }}
|
||||||
|
</h3>
|
||||||
|
<div v-if="!courseSessionsStore.canUploadCircleDocuments">
|
||||||
|
<div class="mt-4 leading-relaxed">
|
||||||
|
{{ $t("circlePage.documents.userDescription") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ol
|
||||||
|
v-if="
|
||||||
|
courseSessionsStore &&
|
||||||
|
courseSessionsStore.circleDocuments &&
|
||||||
|
courseSessionsStore.circleDocuments.length > 0
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
v-for="learningSequence of courseSessionsStore.circleDocuments"
|
||||||
|
:key="learningSequence.id"
|
||||||
|
>
|
||||||
|
<h4 class="text-bold mt-4">{{ learningSequence.title }}</h4>
|
||||||
|
<ul>
|
||||||
|
<li v-for="document of learningSequence.documents" :key="document.url">
|
||||||
|
<a :href="document.url" download>
|
||||||
|
<span>{{ document.name }}</span>
|
||||||
|
</a>
|
||||||
|
<button
|
||||||
|
v-if="courseSessionsStore.canUploadCircleDocuments"
|
||||||
|
type="button"
|
||||||
|
class="relative top-[1px] ml-2 inline-block h-3 w-3 cursor-pointer leading-6"
|
||||||
|
@click="courseSessionsStore.removeDocument(document.id)"
|
||||||
|
>
|
||||||
|
<it-icon-close class="h-3 w-3"></it-icon-close>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<div v-if="courseSessionsStore.canUploadCircleDocuments">
|
||||||
|
<div class="mt-4 leading-relaxed">
|
||||||
|
{{ $t("circlePage.documents.expertDescription") }}
|
||||||
|
</div>
|
||||||
|
<button class="btn-primary mt-4 text-xl" @click="showUploadModal = true">
|
||||||
|
{{ $t("circlePage.documents.action") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ItModal v-model="showUploadModal">
|
||||||
|
<template #title>{{ $t("circlePage.documents.action") }}</template>
|
||||||
|
<template #body>
|
||||||
|
<DocumentUploadForm
|
||||||
|
:learning-sequences="dropdownLearningSequences"
|
||||||
|
:show-upload-error-message="showUploadErrorMessage"
|
||||||
|
:is-uploading="isUploading"
|
||||||
|
@form-submit="uploadDocument"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</ItModal>
|
||||||
|
<div
|
||||||
|
v-if="courseSessionsStore.canUploadCircleDocuments"
|
||||||
|
class="mt-8 flex flex-col gap-y-4 border p-6"
|
||||||
|
>
|
||||||
|
<h3 class="text-blue-dark">
|
||||||
|
{{ $t("circlePage.documents.trainerTitle") }}
|
||||||
|
</h3>
|
||||||
|
<div class="leading-relaxed">
|
||||||
|
{{ $t("circlePage.documents.trainerDescription") }}
|
||||||
|
</div>
|
||||||
|
<a target="_blank" class="link" :href="$t('circlePage.documents.trainerLinkSrc')">
|
||||||
|
{{ $t("circlePage.documents.trainerLinkText") }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ItModal from "@/components/ui/ItModal.vue";
|
||||||
|
import { uploadCircleDocument } from "@/services/files";
|
||||||
|
import { useCircleStore } from "@/stores/circle";
|
||||||
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||||
|
import type { DocumentUploadData } from "@/types";
|
||||||
|
import log from "loglevel";
|
||||||
|
import { computed, ref, watch } from "vue";
|
||||||
|
import DocumentUploadForm from "./DocumentUploadForm.vue";
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
const circleStore = useCircleStore();
|
||||||
|
const showUploadModal = ref(false);
|
||||||
|
const showUploadErrorMessage = ref(false);
|
||||||
|
const isUploading = ref(false);
|
||||||
|
const dropdownLearningSequences = computed(() =>
|
||||||
|
circleStore.circle?.learningSequences.map((sequence) => ({
|
||||||
|
id: sequence.id,
|
||||||
|
name: sequence.title,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
watch(showUploadModal, () => (showUploadErrorMessage.value = false));
|
||||||
|
async function uploadDocument(data: DocumentUploadData) {
|
||||||
|
isUploading.value = true;
|
||||||
|
showUploadErrorMessage.value = false;
|
||||||
|
try {
|
||||||
|
if (!courseSessionsStore.currentCourseSession) {
|
||||||
|
throw new Error("No course session found");
|
||||||
|
}
|
||||||
|
const newDocument = await uploadCircleDocument(
|
||||||
|
data,
|
||||||
|
courseSessionsStore.currentCourseSession.id
|
||||||
|
);
|
||||||
|
const courseSessionStore = useCourseSessionsStore();
|
||||||
|
courseSessionStore.addDocument(newDocument);
|
||||||
|
showUploadModal.value = false;
|
||||||
|
isUploading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
log.error(error);
|
||||||
|
showUploadErrorMessage.value = true;
|
||||||
|
isUploading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Loading…
Reference in New Issue