|
|
|
|
@ -1,18 +1,24 @@ |
|
|
|
|
<template> |
|
|
|
|
<div |
|
|
|
|
v-if="course" |
|
|
|
|
class="flex flex-col gap-4" |
|
|
|
|
> |
|
|
|
|
<div class="flex gap-4 items-center"> |
|
|
|
|
<h2 class="mr-auto"> |
|
|
|
|
<h2 |
|
|
|
|
v-if="course" |
|
|
|
|
class="mr-auto" |
|
|
|
|
> |
|
|
|
|
{{ course.title }} |
|
|
|
|
<small v-if="session"> |
|
|
|
|
({{ session.name }}) |
|
|
|
|
</small> |
|
|
|
|
</h2> |
|
|
|
|
<Skeleton |
|
|
|
|
v-else |
|
|
|
|
height="2rem" |
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
<Button |
|
|
|
|
v-if="isCurrentTeacher" |
|
|
|
|
v-if="course && isCurrentTeacher" |
|
|
|
|
:label="t('See as student')" |
|
|
|
|
icon="pi pi-eye" |
|
|
|
|
class="p-button-outlined p-button-plain" |
|
|
|
|
@ -20,6 +26,7 @@ |
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
<Button |
|
|
|
|
v-if="course && isCurrentTeacher" |
|
|
|
|
icon="mdi mdi-cog" |
|
|
|
|
class="p-button-text p-button-plain" |
|
|
|
|
type="button" |
|
|
|
|
@ -60,40 +67,55 @@ |
|
|
|
|
@click="updateIntro(intro)" |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
<EmptyState |
|
|
|
|
<div |
|
|
|
|
v-else |
|
|
|
|
:summary="t('You don\'t have any course content yet.')" |
|
|
|
|
:detail="t('Add a course introduction to display to your students.')" |
|
|
|
|
icon="mdi mdi-book-open-page-variant" |
|
|
|
|
> |
|
|
|
|
<Button |
|
|
|
|
<EmptyState |
|
|
|
|
v-if="introTool" |
|
|
|
|
class="mt-4 p-button-outlined" |
|
|
|
|
icon="mdi mdi-plus" |
|
|
|
|
:label="t('Course introduction')" |
|
|
|
|
@click="addIntro(course, introTool)" |
|
|
|
|
:summary="t('You don\'t have any course content yet.')" |
|
|
|
|
:detail="t('Add a course introduction to display to your students.')" |
|
|
|
|
icon="mdi mdi-book-open-page-variant" |
|
|
|
|
> |
|
|
|
|
<Button |
|
|
|
|
class="mt-4 p-button-outlined" |
|
|
|
|
icon="mdi mdi-plus" |
|
|
|
|
:label="t('Course introduction')" |
|
|
|
|
@click="addIntro(course, introTool)" |
|
|
|
|
/> |
|
|
|
|
</EmptyState> |
|
|
|
|
<Skeleton |
|
|
|
|
v-else |
|
|
|
|
height="18rem" |
|
|
|
|
/> |
|
|
|
|
</EmptyState> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<div |
|
|
|
|
v-else-if="intro" |
|
|
|
|
v-html="intro.introText" |
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
<h6 v-t="'Tools'" /> |
|
|
|
|
<hr class="mt-0 mb-4"> |
|
|
|
|
|
|
|
|
|
<div |
|
|
|
|
v-if="isCurrentTeacher && course" |
|
|
|
|
class="flex justify-between border-b-2 border-gray-200" |
|
|
|
|
v-if="!course" |
|
|
|
|
class="grid gap-y-12 sm:gap-x-5 md:gap-x-16 md:gap-y-12 justify-between grid-cols-course-tools" |
|
|
|
|
> |
|
|
|
|
<div class="text-h6 font-bold"> |
|
|
|
|
{{ $t('Tools') }} |
|
|
|
|
</div> |
|
|
|
|
<Skeleton |
|
|
|
|
v-for="v in 30" |
|
|
|
|
:key="v" |
|
|
|
|
height="auto" |
|
|
|
|
width="7.5rem" |
|
|
|
|
class="aspect-square" |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div |
|
|
|
|
v-else |
|
|
|
|
class="grid gap-y-12 sm:gap-x-5 md:gap-x-16 md:gap-y-12 justify-between grid-cols-course-tools" |
|
|
|
|
> |
|
|
|
|
<CourseToolList |
|
|
|
|
v-for="tool in tools.authoring" |
|
|
|
|
v-for="(tool, index) in tools.authoring" |
|
|
|
|
:key="index" |
|
|
|
|
:change-visibility="changeVisibility" |
|
|
|
|
:course="course" |
|
|
|
|
:go-to-course-tool="goToCourseTool" |
|
|
|
|
@ -102,7 +124,8 @@ |
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
<CourseToolList |
|
|
|
|
v-for="tool in tools.interaction" |
|
|
|
|
v-for="(tool, index) in tools.interaction" |
|
|
|
|
:key="index" |
|
|
|
|
:change-visibility="changeVisibility" |
|
|
|
|
:course="course" |
|
|
|
|
:go-to-course-tool="goToCourseTool" |
|
|
|
|
@ -111,7 +134,8 @@ |
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
<CourseToolList |
|
|
|
|
v-for="tool in tools.plugin" |
|
|
|
|
v-for="(tool, index) in tools.plugin" |
|
|
|
|
:key="index" |
|
|
|
|
:change-visibility="changeVisibility" |
|
|
|
|
:course="course" |
|
|
|
|
:go-to-course-tool="goToCourseTool" |
|
|
|
|
@ -120,7 +144,8 @@ |
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
<ShortCutList |
|
|
|
|
v-for="shortcut in shortcuts" |
|
|
|
|
v-for="(shortcut, index) in shortcuts" |
|
|
|
|
:key="index" |
|
|
|
|
:change-visibility="changeVisibility" |
|
|
|
|
:go-to-short-cut="goToShortCut" |
|
|
|
|
:shortcut="shortcut" |
|
|
|
|
@ -133,7 +158,7 @@ |
|
|
|
|
import { computed, ref } from 'vue'; |
|
|
|
|
import { useStore } from 'vuex'; |
|
|
|
|
import { useRoute, useRouter } from 'vue-router'; |
|
|
|
|
import isEmpty from 'lodash/isEmpty'; |
|
|
|
|
import { useI18n } from 'vue-i18n'; |
|
|
|
|
import axios from 'axios'; |
|
|
|
|
import { ENTRYPOINT } from '../../config/entrypoint'; |
|
|
|
|
import Button from 'primevue/button'; |
|
|
|
|
@ -141,24 +166,22 @@ import TieredMenu from 'primevue/tieredmenu'; |
|
|
|
|
import CourseToolList from '../../components/course/CourseToolList.vue'; |
|
|
|
|
import ShortCutList from '../../components/course/ShortCutList.vue'; |
|
|
|
|
import translateHtml from '../../../js/translatehtml.js'; |
|
|
|
|
import { useI18n } from 'vue-i18n'; |
|
|
|
|
import EmptyState from '../../components/EmptyState'; |
|
|
|
|
import Skeleton from 'primevue/skeleton'; |
|
|
|
|
|
|
|
|
|
const servicePrefix = 'Courses'; |
|
|
|
|
const route = useRoute(); |
|
|
|
|
const store = useStore(); |
|
|
|
|
const router = useRouter(); |
|
|
|
|
const { t } = useI18n(); |
|
|
|
|
|
|
|
|
|
const course = ref([]); |
|
|
|
|
const session = ref([]); |
|
|
|
|
const tools = ref([]); |
|
|
|
|
const course = ref(null); |
|
|
|
|
const session = ref(null); |
|
|
|
|
const tools = ref({}); |
|
|
|
|
const shortcuts = ref([]); |
|
|
|
|
const intro = ref(null); |
|
|
|
|
const introTool = ref(null); |
|
|
|
|
const createInSession = ref(false); |
|
|
|
|
|
|
|
|
|
const route = useRoute(); |
|
|
|
|
const store = useStore(); |
|
|
|
|
const router = useRouter(); |
|
|
|
|
const { t } = useI18n(); |
|
|
|
|
|
|
|
|
|
let courseId = route.params.id; |
|
|
|
|
let sessionId = route.query.sid ?? 0; |
|
|
|
|
|
|
|
|
|
@ -167,28 +190,28 @@ const isCurrentTeacher = computed(() => store.getters['security/isCurrentTeacher |
|
|
|
|
// Remove the course session state. |
|
|
|
|
store.dispatch('session/cleanSession'); |
|
|
|
|
|
|
|
|
|
axios.get(ENTRYPOINT + '../course/' + courseId + '/home.json?sid=' + sessionId).then(response => { |
|
|
|
|
course.value = response.data.course; |
|
|
|
|
session.value = response.data.session; |
|
|
|
|
tools.value = response.data.tools; |
|
|
|
|
shortcuts.value = response.data.shortcuts; |
|
|
|
|
getIntro(); |
|
|
|
|
}).catch(function (error) { |
|
|
|
|
console.log(error); |
|
|
|
|
}); |
|
|
|
|
const courseItems = ref([]); |
|
|
|
|
|
|
|
|
|
axios |
|
|
|
|
.get(ENTRYPOINT + `../course/${courseId}/home.json?sid=${sessionId}`) |
|
|
|
|
.then(({data}) => { |
|
|
|
|
course.value = data.course; |
|
|
|
|
session.value = data.session; |
|
|
|
|
tools.value = data.tools; |
|
|
|
|
shortcuts.value = data.shortcuts; |
|
|
|
|
|
|
|
|
|
if (tools.value.admin) { |
|
|
|
|
courseItems.value = tools.value.admin.map(tool => ({ |
|
|
|
|
label: tool.tool.nameToShow, |
|
|
|
|
url: goToCourseTool(course, tool) |
|
|
|
|
})); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const courseTMenu = ref(null); |
|
|
|
|
getIntro(); |
|
|
|
|
}) |
|
|
|
|
.catch(error => console.log(error)); |
|
|
|
|
|
|
|
|
|
const courseItems = computed(() => { |
|
|
|
|
if (tools.value.admin) { |
|
|
|
|
return tools.value.admin.map(tool => ({ |
|
|
|
|
label: tool.tool.nameToShow, |
|
|
|
|
url: goToCourseTool(course, tool) |
|
|
|
|
})); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return []; |
|
|
|
|
}); |
|
|
|
|
const courseTMenu = ref(null); |
|
|
|
|
|
|
|
|
|
const toggleCourseTMenu = event => { |
|
|
|
|
courseTMenu.value.toggle(event); |
|
|
|
|
@ -198,39 +221,31 @@ async function getIntro () { |
|
|
|
|
// Searching for the CTool called 'course_homepage'. |
|
|
|
|
let currentIntroTool = course.value.tools.find(element => element.name === 'course_homepage'); |
|
|
|
|
|
|
|
|
|
if (!isEmpty(introTool)) { |
|
|
|
|
if (!introTool.value) { |
|
|
|
|
introTool.value = currentIntroTool; |
|
|
|
|
|
|
|
|
|
if (sessionId) { |
|
|
|
|
createInSession.value = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Search CToolIntro for this |
|
|
|
|
const filter = { |
|
|
|
|
courseTool: currentIntroTool.iid, |
|
|
|
|
cid: courseId, |
|
|
|
|
sid: sessionId, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
store.dispatch('ctoolintro/findAll', filter).then(response => { |
|
|
|
|
if (!isEmpty(response)) { |
|
|
|
|
// first item |
|
|
|
|
intro.value = response[0]; |
|
|
|
|
translateHtml(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
if (!isEmpty(sessionId)) { |
|
|
|
|
createInSession.value = true; |
|
|
|
|
const filter = { |
|
|
|
|
courseTool: currentIntroTool.iid, |
|
|
|
|
cid: courseId, |
|
|
|
|
sid: sessionId, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
store.dispatch('ctoolintro/findAll', filter).then(response => { |
|
|
|
|
if (!isEmpty(response)) { |
|
|
|
|
createInSession.value = false; |
|
|
|
|
store.dispatch('ctoolintro/findAll', filter) |
|
|
|
|
.then(response => { |
|
|
|
|
if (response) { |
|
|
|
|
if (sessionId) { |
|
|
|
|
createInSession.value = false; |
|
|
|
|
} |
|
|
|
|
// first item |
|
|
|
|
intro.value = response[0]; |
|
|
|
|
translateHtml(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -276,12 +291,12 @@ function goToShortCut (shortcut) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function changeVisibility (course, tool) { |
|
|
|
|
axios.post(ENTRYPOINT + '../r/course_tool/links/' + tool.ctool.resourceNode.id + '/change_visibility').then(response => { |
|
|
|
|
if (response.data.ok) { |
|
|
|
|
tool.ctool.resourceNode.resourceLinks[0].visibility = response.data.visibility; |
|
|
|
|
} |
|
|
|
|
}).catch(function (error) { |
|
|
|
|
console.log(error); |
|
|
|
|
}); |
|
|
|
|
axios.post(ENTRYPOINT + '../r/course_tool/links/' + tool.ctool.resourceNode.id + '/change_visibility') |
|
|
|
|
.then(response => { |
|
|
|
|
if (response.data.ok) { |
|
|
|
|
tool.ctool.resourceNode.resourceLinks[0].visibility = response.data.visibility; |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
.catch(error => console.log(error)); |
|
|
|
|
} |
|
|
|
|
</script> |
|
|
|
|
|