UI: Refactor for Course home

pull/4351/head
Angel Fernando Quiroz Campos 3 years ago
parent 08cbbe7605
commit 8252bf6c8f
  1. 4
      assets/vue/router/index.js
  2. 354
      assets/vue/views/course/Home.vue

@ -60,7 +60,9 @@ const router = createRouter({
} }
}, },
{ {
path: '/course/:id/home', name: 'CourseHome', component: CourseHome path: '/course/:id/home',
name: 'CourseHome',
component: CourseHome
}, },
{ {
path: '/courses', path: '/courses',

@ -1,130 +1,92 @@
<template> <template>
<div v-if="course" class="grid gap-4"> <div
<div class="flex flex-row justify-between border-b-2 border-gray-200 "> v-if="course"
<div class="line-clamp-1 text-h3 font-bold"> class="flex flex-col gap-4"
>
<div class="flex gap-4 items-center">
<h2 class="mr-auto">
{{ course.title }} {{ course.title }}
<span v-if="session"> <small v-if="session">
({{ session.name }}) ({{ session.name }})
</span> </small>
</div> </h2>
<Button
v-if="isCurrentTeacher"
:label="t('See as student')"
icon="pi pi-eye"
class="p-button-outlined p-button-plain"
type="button"
/>
<div> <Button
<div class="flex flex-row" v-if="isCurrentTeacher && course"> icon="mdi mdi-cog"
<a class="btn btn--info mr-2"> class="p-button-text p-button-plain"
<v-icon icon="mdi-eye" class="pr-2" /> type="button"
{{ $t('See as student') }} aria-haspopup="true"
</a> aria-controls="course-tmenu"
@click="toggleCourseTMenu"
<div class="relative"> />
<!-- shadow rounded-full-->
<button
@click="dropdownOpen = !dropdownOpen"
class="relative z-10 block h-8 w-8 overflow-hidden focus:outline-none"
>
<v-icon>mdi-cog</v-icon>
</button>
<div <TieredMenu
v-show="dropdownOpen" id="course-tmenu"
@click="dropdownOpen = false" ref="courseTMenu"
class="fixed inset-0 h-full w-full z-10" :model="courseItems"
></div> :popup="true"
/>
</div>
<div <div
v-show="dropdownOpen" v-if="isCurrentTeacher"
class="absolute right-0 mt-2 py-2 w-48 bg-white rounded-md shadow-xl z-20"
>
<q-list dense>
<!-- <q-item replace :to="'/main/messages/index.php'" clickable class="">-->
<!-- <q-item-section>Inbox</q-item-section>-->
<!-- </q-item>-->
<q-item
:href="goToCourseTool(course, tool)"
tag="a"
class=""
v-for="tool in tools.admin"
> >
<q-item-section> <div
{{ $t(tool.tool.nameToShow) }} v-if="intro"
</q-item-section> class="flex flex-col gap-4"
</q-item>
</q-list>
</div>
</div>
</div>
</div>
</div>
<div v-if="isCurrentTeacher"
class="bg-gradient-to-r from-gray-100 to-gray-50 flex flex-col rounded-md text-center p-2"
> >
<div v-if="intro" class="p-10 text-center"> <div v-html="intro.introText" />
<span v-html="intro.introText" />
<div v-if="createInSession"> <Button
<button v-if="createInSession && introTool"
v-if="introTool" class="p-button-outlined ml-auto"
class="mt-2 btn btn--info" icon="mdi mdi-plus"
:label="t('Course introduction')"
@click="addIntro(course, introTool)" @click="addIntro(course, introTool)"
> />
<v-icon>mdi-plus</v-icon> <Button
{{ $t('Course introduction') }} v-else
</button> class="p-button-outlined ml-auto"
</div> icon="mdi mdi-pencil"
<div v-else> :label="t('Update')"
<button
class="mt-2 btn btn--info"
@click="updateIntro(intro)" @click="updateIntro(intro)"
>
<v-icon>mdi-pencil</v-icon>
{{ $t('Update') }}
</button>
</div>
</div>
<div v-else>
<div>
<v-icon
icon="mdi-book-open-page-variant"
size="72px"
class="font-extrabold text-transparent bg-clip-text bg-gradient-to-br from-primary to-primary-gradient"
/> />
</div> </div>
<EmptyState
<div class="mt-2 font-bold"> v-else
{{ $t("You don't have any course content yet.") }} :summary="t('You don\'t have any course content yet.')"
</div> :detail="t('Add a course introduction to display to your students.')"
icon="mdi mdi-book-open-page-variant"
<div v-if="introTool"> >
{{ $t('Add a course introduction to display to your students.') }} <Button
</div>
<button
v-if="introTool" v-if="introTool"
class="mt-2 btn btn--info" class="mt-4 p-button-outlined"
icon="mdi mdi-plus"
:label="t('Course introduction')"
@click="addIntro(course, introTool)" @click="addIntro(course, introTool)"
> />
<v-icon>mdi-plus</v-icon> </EmptyState>
{{ $t('Course introduction') }}
</button>
</div>
</div>
<div v-else>
<div v-if="intro" class="p-10 text-center">
<span v-html="intro.introText" />
</div>
</div> </div>
<div
v-else-if="intro"
v-html="intro.introText"
/>
<div v-if="isCurrentTeacher && course" class="flex justify-between border-b-2 border-gray-200"> <div
v-if="isCurrentTeacher && course"
class="flex justify-between border-b-2 border-gray-200"
>
<div class="text-h6 font-bold"> <div class="text-h6 font-bold">
{{ $t('Tools') }} {{ $t('Tools') }}
</div> </div>
<!-- <div>-->
<!-- <v-icon>-->
<!-- mdi-format-paint-->
<!-- </v-icon>-->
<!-- Customize-->
<!-- </div>-->
</div> </div>
<div <div
@ -132,183 +94,188 @@
> >
<CourseToolList <CourseToolList
v-for="tool in tools.authoring" v-for="tool in tools.authoring"
:change-visibility="changeVisibility"
:course="course" :course="course"
:tool="tool"
:go-to-course-tool="goToCourseTool" :go-to-course-tool="goToCourseTool"
:change-visibility="changeVisibility"
:go-to-setting-course-tool="goToSettingCourseTool" :go-to-setting-course-tool="goToSettingCourseTool"
:tool="tool"
/> />
<CourseToolList <CourseToolList
v-for="tool in tools.interaction" v-for="tool in tools.interaction"
:change-visibility="changeVisibility"
:course="course" :course="course"
:tool="tool"
:go-to-course-tool="goToCourseTool" :go-to-course-tool="goToCourseTool"
:change-visibility="changeVisibility"
:go-to-setting-course-tool="goToSettingCourseTool" :go-to-setting-course-tool="goToSettingCourseTool"
:tool="tool"
/> />
<CourseToolList <CourseToolList
v-for="tool in tools.plugin" v-for="tool in tools.plugin"
:change-visibility="changeVisibility"
:course="course" :course="course"
:tool="tool"
:go-to-course-tool="goToCourseTool" :go-to-course-tool="goToCourseTool"
:change-visibility="changeVisibility"
:go-to-setting-course-tool="goToSettingCourseTool" :go-to-setting-course-tool="goToSettingCourseTool"
:tool="tool"
/> />
<ShortCutList <ShortCutList
v-for="shortcut in shortcuts" v-for="shortcut in shortcuts"
:shortcut="shortcut"
:go-to-short-cut="goToShortCut"
:change-visibility="changeVisibility" :change-visibility="changeVisibility"
:go-to-short-cut="goToShortCut"
:shortcut="shortcut"
/> />
</div> </div>
</div> </div>
</template> </template>
<script> <script setup>
import Loading from '../../components/Loading.vue'; import { computed, ref } from 'vue';
import Toolbar from '../../components/Toolbar.vue'; import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';
import isEmpty from 'lodash/isEmpty';
import axios from 'axios';
import { ENTRYPOINT } from '../../config/entrypoint';
import Button from 'primevue/button';
import TieredMenu from 'primevue/tieredmenu';
import CourseToolList from '../../components/course/CourseToolList.vue'; import CourseToolList from '../../components/course/CourseToolList.vue';
import ShortCutList from '../../components/course/ShortCutList.vue'; import ShortCutList from '../../components/course/ShortCutList.vue';
import isEmpty from "lodash/isEmpty";
import {useRoute, useRouter} from 'vue-router'
import axios from "axios";
import {ENTRYPOINT} from '../../config/entrypoint';
import {computed, onMounted, reactive, toRefs} from 'vue'
import {mapGetters, useStore} from "vuex";
import translateHtml from '../../../js/translatehtml.js'; import translateHtml from '../../../js/translatehtml.js';
import { useI18n } from 'vue-i18n';
import EmptyState from '../../components/EmptyState';
export default { const servicePrefix = 'Courses';
name: 'Home',
servicePrefix: 'Courses', const course = ref([]);
components: { const session = ref([]);
Loading, const tools = ref([]);
Toolbar, const shortcuts = ref([]);
CourseToolList, const intro = ref(null);
ShortCutList const introTool = ref(null);
}, const createInSession = ref(false);
setup() {
const state = reactive({ const route = useRoute();
course: [], const store = useStore();
session: [], const router = useRouter();
tools: [], const { t } = useI18n();
shortcuts: [],
dropdownOpen: false,
intro: null,
introTool: null,
createInSession: false,
goToCourseTool,
changeVisibility,
goToSettingCourseTool,
goToShortCut,
addIntro,
updateIntro
});
const route = useRoute()
const store = useStore();
const router = useRouter();
let courseId = route.params.id; let courseId = route.params.id;
let sessionId = route.query.sid ?? 0; let sessionId = route.query.sid ?? 0;
// Remove the course session state. const isCurrentTeacher = computed(() => store.getters['security/isCurrentTeacher']);
store.dispatch('session/cleanSession');
axios.get(ENTRYPOINT + '../course/' + courseId + '/home.json?sid=' + sessionId).then(response => { // Remove the course session state.
state.course = response.data.course; store.dispatch('session/cleanSession');
state.session = response.data.session;
state.tools = response.data.tools; axios.get(ENTRYPOINT + '../course/' + courseId + '/home.json?sid=' + sessionId).then(response => {
state.shortcuts = response.data.shortcuts; course.value = response.data.course;
session.value = response.data.session;
tools.value = response.data.tools;
shortcuts.value = response.data.shortcuts;
getIntro(); getIntro();
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
const courseTMenu = ref(null);
const courseItems = computed(() => {
if (tools.value.admin) {
return tools.value.admin.map(tool => ({
label: tool.tool.nameToShow,
url: goToCourseTool(course, tool)
}));
}
return [];
});
async function getIntro() { const toggleCourseTMenu = event => {
courseTMenu.value.toggle(event);
}
async function getIntro () {
// Searching for the CTool called 'course_homepage'. // Searching for the CTool called 'course_homepage'.
let introTool = state.course.tools.find(element => element.name === 'course_homepage'); let currentIntroTool = course.value.tools.find(element => element.name === 'course_homepage');
if (!isEmpty(introTool)) { if (!isEmpty(introTool)) {
state.introTool = introTool; introTool.value = currentIntroTool;
// Search CToolIntro for this // Search CToolIntro for this
const filter = { const filter = {
courseTool: introTool.iid, courseTool: currentIntroTool.iid,
cid: courseId, cid: courseId,
}; };
store.dispatch('ctoolintro/findAll', filter).then(response => { store.dispatch('ctoolintro/findAll', filter).then(response => {
if (!isEmpty(response)) { if (!isEmpty(response)) {
// first item // first item
state.intro = response[0]; intro.value = response[0];
translateHtml(); translateHtml();
} }
}); });
if (!isEmpty(sessionId)) { if (!isEmpty(sessionId)) {
state.createInSession = true; createInSession.value = true;
const filter = { const filter = {
courseTool: introTool.iid, courseTool: currentIntroTool.iid,
cid: courseId, cid: courseId,
sid: sessionId, sid: sessionId,
}; };
store.dispatch('ctoolintro/findAll', filter).then(response => { store.dispatch('ctoolintro/findAll', filter).then(response => {
if (!isEmpty(response)) { if (!isEmpty(response)) {
state.createInSession = false; createInSession.value = false;
state.intro = response[0]; intro.value = response[0];
translateHtml(); translateHtml();
} }
}); });
} }
} }
} }
function addIntro(course, introTool) { function addIntro (course, introTool) {
return router.push({ return router.push({
name: 'ToolIntroCreate', name: 'ToolIntroCreate',
params: {'courseTool': introTool.iid }, params: { 'courseTool': introTool.iid },
query: { query: {
'cid': courseId, 'cid': courseId,
'sid': sessionId, 'sid': sessionId,
'parentResourceNodeId': course.resourceNode.id 'parentResourceNodeId': course.resourceNode.id
} }
}); });
} }
function updateIntro(intro) { function updateIntro (intro) {
return router.push({ return router.push({
name: 'ToolIntroUpdate', name: 'ToolIntroUpdate',
params: {'id': intro['@id'] }, params: { 'id': intro['@id'] },
query: { query: {
'cid': courseId, 'cid': courseId,
'sid': sessionId, 'sid': sessionId,
'id': intro['@id'] 'id': intro['@id']
} }
}); });
} }
function goToSettingCourseTool(course, tool) { function goToSettingCourseTool (course, tool) {
return '/course/' + courseId + '/settings/' + tool.tool.name + '?sid=' + sessionId; return '/course/' + courseId + '/settings/' + tool.tool.name + '?sid=' + sessionId;
} }
function goToCourseTool(course, tool) { function goToCourseTool (course, tool) {
return '/course/' + courseId + '/tool/' + tool.tool.name + '?sid=' + sessionId; return '/course/' + courseId + '/tool/' + tool.tool.name + '?sid=' + sessionId;
} }
function goToShortCut(shortcut) { function goToShortCut (shortcut) {
const url = new URLSearchParams('?') const url = new URLSearchParams('?');
url.append('cid', courseId); url.append('cid', courseId);
url.append('sid', sessionId); url.append('sid', sessionId);
return shortcut.url + '?' + url; return shortcut.url + '?' + url;
} }
function changeVisibility(course, tool) { function changeVisibility (course, tool) {
axios.post(ENTRYPOINT + '../r/course_tool/links/' + tool.ctool.resourceNode.id + '/change_visibility').then(response => { axios.post(ENTRYPOINT + '../r/course_tool/links/' + tool.ctool.resourceNode.id + '/change_visibility').then(response => {
if (response.data.ok) { if (response.data.ok) {
tool.ctool.resourceNode.resourceLinks[0].visibility = response.data.visibility; tool.ctool.resourceNode.resourceLinks[0].visibility = response.data.visibility;
@ -316,14 +283,5 @@ export default {
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
} }
return toRefs(state);
},
computed: {
...mapGetters({
'isCurrentTeacher': 'security/isCurrentTeacher',
}),
},
};
</script> </script>

Loading…
Cancel
Save