fix: misc issues

This commit is contained in:
Jannat Patel
2024-07-10 16:13:28 +05:30
parent 2ecc07ee58
commit 8164526763
17 changed files with 180 additions and 57 deletions

View File

@@ -18,20 +18,28 @@
</div> </div>
<div <div
v-if="sidebarSettings.data?.web_pages?.length || isModerator" v-if="sidebarSettings.data?.web_pages?.length || isModerator"
class="mt-4 pt-1 border-t border-gray-200" class="pt-1"
> >
<div <div
v-if="isModerator" class="flex items-center justify-between pr-2 cursor-pointer"
class="flex items-center justify-between pr-2" :class="isSidebarCollapsed ? 'pl-3' : 'pl-4'"
:class="isSidebarCollapsed ? 'pl-3' : 'pl-5'" @click="showWebPages = !showWebPages"
> >
<span <div
v-if="!isSidebarCollapsed" v-if="!isSidebarCollapsed"
class="text-sm font-medium text-gray-600" class="flex items-center text-sm font-medium text-gray-600"
> >
<span class="grid h-5 w-6 flex-shrink-0 place-items-center">
<ChevronRight
class="h-4 w-4 stroke-1.5 text-gray-900 transition-all duration-300 ease-in-out"
:class="{ 'rotate-90': showWebPages }"
/>
</span>
<span class="ml-2">
{{ __('Web Pages') }} {{ __('Web Pages') }}
</span> </span>
<Button variant="ghost" @click="openPageModal()"> </div>
<Button v-if="isModerator" variant="ghost" @click="openPageModal()">
<template #icon> <template #icon>
<Plus class="h-4 w-4 text-gray-700 stroke-1.5" /> <Plus class="h-4 w-4 text-gray-700 stroke-1.5" />
</template> </template>
@@ -39,7 +47,8 @@
</div> </div>
<div <div
v-if="sidebarSettings.data?.web_pages?.length" v-if="sidebarSettings.data?.web_pages?.length"
class="flex flex-col" class="flex flex-col transition-all duration-300 ease-in-out"
:class="showWebPages ? 'block' : 'hidden'"
> >
<SidebarLink <SidebarLink
v-for="link in sidebarSettings.data.web_pages" v-for="link in sidebarSettings.data.web_pages"
@@ -87,7 +96,7 @@ import { ref, onMounted, inject, watch } from 'vue'
import { getSidebarLinks } from '../utils' import { getSidebarLinks } from '../utils'
import { usersStore } from '@/stores/user' import { usersStore } from '@/stores/user'
import { sessionStore } from '@/stores/session' import { sessionStore } from '@/stores/session'
import { Plus } from 'lucide-vue-next' import { ChevronRight, Plus } from 'lucide-vue-next'
import { createResource, Button } from 'frappe-ui' import { createResource, Button } from 'frappe-ui'
import PageModal from '@/components/Modals/PageModal.vue' import PageModal from '@/components/Modals/PageModal.vue'
@@ -99,6 +108,7 @@ const sidebarLinks = ref(getSidebarLinks())
const showPageModal = ref(false) const showPageModal = ref(false)
const isModerator = ref(false) const isModerator = ref(false)
const pageToEdit = ref(null) const pageToEdit = ref(null)
const showWebPages = ref(false)
onMounted(() => { onMounted(() => {
socket.on('publish_lms_notifications', (data) => { socket.on('publish_lms_notifications', (data) => {

View File

@@ -41,7 +41,7 @@
</span> </span>
</div> </div>
<router-link <router-link
v-if="user?.data?.is_moderator" v-if="isModerator || isStudent"
:to="{ :to="{
name: 'Batch', name: 'Batch',
params: { params: {
@@ -51,7 +51,7 @@
> >
<Button variant="solid" class="w-full mt-4"> <Button variant="solid" class="w-full mt-4">
<span> <span>
{{ __('Manage Batch') }} {{ isModerator ? __('Manage Batch') : __('Visit Batch') }}
</span> </span>
</Button> </Button>
</router-link> </router-link>
@@ -65,7 +65,7 @@
}" }"
v-else-if="batch.data.paid_batch && batch.data.seats_left" v-else-if="batch.data.paid_batch && batch.data.seats_left"
> >
<Button class="w-full mt-4" variant="solid"> <Button v-if="!isStudent" class="w-full mt-4" variant="solid">
<span> <span>
{{ __('Register Now') }} {{ __('Register Now') }}
</span> </span>
@@ -79,7 +79,7 @@
{{ __('Enroll Now') }} {{ __('Enroll Now') }}
</Button> </Button>
<router-link <router-link
v-if="user?.data?.is_moderator" v-if="isModerator"
:to="{ :to="{
name: 'BatchCreation', name: 'BatchCreation',
params: { params: {
@@ -117,4 +117,12 @@ const seats_left = computed(() => {
} }
return null return null
}) })
const isStudent = computed(() => {
return props.batch.data?.students?.includes(user.data?.name)
})
const isModerator = computed(() => {
return user.data?.is_moderator
})
</script> </script>

View File

@@ -190,7 +190,8 @@ const updateLessonIndex = createResource({
makeParams(values) { makeParams(values) {
return { return {
lesson: values.lesson, lesson: values.lesson,
chapter: values.chapter, sourceChapter: values.sourceChapter,
targetChapter: values.targetChapter,
idx: values.idx, idx: values.idx,
} }
}, },
@@ -217,13 +218,10 @@ const getCurrentChapter = () => {
} }
const updateOutline = (e) => { const updateOutline = (e) => {
console.log(e)
const sourceChapter = e.from.dataset.chapter
const targetChapter = e.to.dataset.chapter
const lesson = e.item.__draggable_context.element.name
updateLessonIndex.submit({ updateLessonIndex.submit({
lesson: lesson, lesson: e.item.__draggable_context.element.name,
chapter: sourceChapter, sourceChapter: e.from.dataset.chapter,
targetChapter: e.to.dataset.chapter,
idx: e.newIndex, idx: e.newIndex,
}) })
} }

View File

@@ -20,7 +20,7 @@
</slot> </slot>
</Tooltip> </Tooltip>
<span <span
class="flex-shrink-0 text-base duration-300 ease-in-out" class="flex-shrink-0 text-sm duration-300 ease-in-out"
:class=" :class="
isCollapsed isCollapsed
? 'ml-0 w-0 overflow-hidden opacity-0' ? 'ml-0 w-0 overflow-hidden opacity-0'
@@ -38,12 +38,12 @@
> >
<component <component
:is="icons['Edit']" :is="icons['Edit']"
class="h-3 w-3 stroke-1.5 text-gray-800" class="h-3 w-3 stroke-1.5 text-gray-700"
@click.stop="openModal(link)" @click.stop="openModal(link)"
/> />
<component <component
:is="icons['X']" :is="icons['X']"
class="h-3 w-3 stroke-1.5 text-gray-800" class="h-3 w-3 stroke-1.5 text-gray-700"
@click.stop="deletePage(link)" @click.stop="deletePage(link)"
/> />
</div> </div>

View File

@@ -183,7 +183,7 @@ import {
MessageCircle, MessageCircle,
Globe, Globe,
} from 'lucide-vue-next' } from 'lucide-vue-next'
import { formatTime } from '@/utils' import { formatTime, updateDocumentTitle } from '@/utils'
import BatchDashboard from '@/components/BatchDashboard.vue' import BatchDashboard from '@/components/BatchDashboard.vue'
import BatchCourses from '@/components/BatchCourses.vue' import BatchCourses from '@/components/BatchCourses.vue'
import LiveClass from '@/components/LiveClass.vue' import LiveClass from '@/components/LiveClass.vue'
@@ -286,4 +286,13 @@ const redirectToLogin = () => {
const openAnnouncementModal = () => { const openAnnouncementModal = () => {
showAnnouncementModal.value = true showAnnouncementModal.value = true
} }
const pageMeta = computed(() => {
return {
title: batch.data?.title,
description: batch.data?.description,
}
})
updateDocumentTitle(pageMeta)
</script> </script>

View File

@@ -100,7 +100,7 @@
import { computed, inject } from 'vue' import { computed, inject } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { BookOpen, Clock } from 'lucide-vue-next' import { BookOpen, Clock } from 'lucide-vue-next'
import { formatTime } from '@/utils' import { formatTime, updateDocumentTitle } from '@/utils'
import { Breadcrumbs, createResource } from 'frappe-ui' import { Breadcrumbs, createResource } from 'frappe-ui'
import CourseCard from '@/components/CourseCard.vue' import CourseCard from '@/components/CourseCard.vue'
import BatchOverlay from '@/components/BatchOverlay.vue' import BatchOverlay from '@/components/BatchOverlay.vue'
@@ -125,16 +125,6 @@ const batch = createResource({
batch: props.batchName, batch: props.batchName,
}, },
auto: true, auto: true,
onSuccess(data) {
if (data.students?.includes(user.data?.name)) {
router.push({
name: 'Batch',
params: {
batchName: props.batchName,
},
})
}
},
}) })
const courses = createResource({ const courses = createResource({
@@ -154,6 +144,15 @@ const breadcrumbs = computed(() => {
}) })
return items return items
}) })
const pageMeta = computed(() => {
return {
title: batch.data?.title,
description: batch.data?.description,
}
})
updateDocumentTitle(pageMeta)
</script> </script>
<style> <style>
.batch-description p { .batch-description p {

View File

@@ -91,6 +91,7 @@ import { createListResource, Breadcrumbs, Button, Tabs, Badge } from 'frappe-ui'
import { Plus } from 'lucide-vue-next' import { Plus } from 'lucide-vue-next'
import BatchCard from '@/components/BatchCard.vue' import BatchCard from '@/components/BatchCard.vue'
import { inject, ref, computed } from 'vue' import { inject, ref, computed } from 'vue'
import { updateDocumentTitle } from '@/utils'
const user = inject('$user') const user = inject('$user')
@@ -129,4 +130,13 @@ if (user.data) {
count: computed(() => batches.data?.enrolled?.length), count: computed(() => batches.data?.enrolled?.length),
}) })
} }
const pageMeta = computed(() => {
return {
title: 'Batches',
description: 'All batches divided by categories',
}
})
updateDocumentTitle(pageMeta)
</script> </script>

View File

@@ -52,6 +52,7 @@ import { Breadcrumbs, FormControl, createResource } from 'frappe-ui'
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import { Search } from 'lucide-vue-next' import { Search } from 'lucide-vue-next'
import { updateDocumentTitle } from '@/utils'
const searchQuery = ref('') const searchQuery = ref('')
@@ -70,4 +71,13 @@ const participants = createResource({
const breadcrumbs = computed(() => { const breadcrumbs = computed(() => {
return [{ label: 'Certified Participants', to: '/certified-participants' }] return [{ label: 'Certified Participants', to: '/certified-participants' }]
}) })
const pageMeta = computed(() => {
return {
title: 'Certified Participants',
description: 'All participants that have been certified.',
}
})
updateDocumentTitle(pageMeta)
</script> </script>

View File

@@ -185,7 +185,7 @@ import UserAvatar from '@/components/UserAvatar.vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { ChevronLeft, ChevronRight } from 'lucide-vue-next' import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import Discussions from '@/components/Discussions.vue' import Discussions from '@/components/Discussions.vue'
import { getEditorTools } from '../utils' import { getEditorTools, updateDocumentTitle } from '../utils'
import EditorJS from '@editorjs/editorjs' import EditorJS from '@editorjs/editorjs'
import LessonContent from '@/components/LessonContent.vue' import LessonContent from '@/components/LessonContent.vue'
import CourseInstructors from '@/components/CourseInstructors.vue' import CourseInstructors from '@/components/CourseInstructors.vue'
@@ -338,6 +338,15 @@ const allowInstructorContent = () => {
const redirectToLogin = () => { const redirectToLogin = () => {
window.location.href = `/login?redirect-to=/lms/courses/${props.courseName}` window.location.href = `/login?redirect-to=/lms/courses/${props.courseName}`
} }
const pageMeta = computed(() => {
return {
title: lesson.data?.title,
description: lesson.data?.course,
}
})
updateDocumentTitle(pageMeta)
</script> </script>
<style> <style>
.avatar-group { .avatar-group {

View File

@@ -69,6 +69,7 @@ import { computed, inject, ref, onMounted } from 'vue'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { X } from 'lucide-vue-next' import { X } from 'lucide-vue-next'
import { updateDocumentTitle } from '@/utils'
const user = inject('$user') const user = inject('$user')
const socket = inject('$socket') const socket = inject('$socket')
@@ -146,6 +147,15 @@ const breadcrumbs = computed(() => {
] ]
return crumbs return crumbs
}) })
const pageMeta = computed(() => {
return {
title: 'Notifications',
description: 'All your notifications in one place.',
}
})
updateDocumentTitle(pageMeta)
</script> </script>
<style> <style>
.notification strong { .notification strong {

View File

@@ -93,7 +93,7 @@ import { Edit } from 'lucide-vue-next'
import UserAvatar from '@/components/UserAvatar.vue' import UserAvatar from '@/components/UserAvatar.vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import NoPermission from '@/components/NoPermission.vue' import NoPermission from '@/components/NoPermission.vue'
import { convertToTitleCase } from '@/utils' import { convertToTitleCase, updateDocumentTitle } from '@/utils'
import EditProfile from '@/components/Modals/EditProfile.vue' import EditProfile from '@/components/Modals/EditProfile.vue'
import EditCoverImage from '@/components/Modals/EditCoverImage.vue' import EditCoverImage from '@/components/Modals/EditCoverImage.vue'
@@ -208,4 +208,13 @@ const breadcrumbs = computed(() => {
] ]
return crumbs return crumbs
}) })
const pageMeta = computed(() => {
return {
title: profile.data?.full_name,
description: profile.data?.headline,
}
})
updateDocumentTitle(pageMeta)
</script> </script>

View File

@@ -357,13 +357,19 @@ export function getSidebarLinks() {
label: 'Courses', label: 'Courses',
icon: 'BookOpen', icon: 'BookOpen',
to: 'Courses', to: 'Courses',
activeFor: ['Courses', 'CourseDetail', 'Lesson'], activeFor: [
'Courses',
'CourseDetail',
'Lesson',
'CreateCourse',
'CreateLesson',
],
}, },
{ {
label: 'Batches', label: 'Batches',
icon: 'Users', icon: 'Users',
to: 'Batches', to: 'Batches',
activeFor: ['Batches', 'BatchDetail', 'Batch'], activeFor: ['Batches', 'BatchDetail', 'Batch', 'BatchCreation'],
}, },
{ {
label: 'Certified Participants', label: 'Certified Participants',

View File

@@ -486,20 +486,62 @@ def delete_lesson(lesson, chapter):
@frappe.whitelist() @frappe.whitelist()
def update_lesson_index(lesson, chapter, idx): def update_lesson_index(lesson, sourceChapter, targetChapter, idx):
name = frappe.db.get_value( hasMoved = sourceChapter == targetChapter
update_source_chapter(lesson, sourceChapter, idx, hasMoved)
if not hasMoved:
update_target_chapter(lesson, targetChapter, idx)
def update_source_chapter(lesson, chapter, idx, hasMoved=False):
lessons = frappe.get_all(
"Lesson Reference", "Lesson Reference",
{"lesson": lesson, "parent": chapter}, {
["name", "idx", "parent", "lesson"], "parent": chapter,
},
pluck="lesson",
order_by="idx",
) )
print(name)
frappe.db.set_value( lessons.remove(lesson)
if not hasMoved:
frappe.db.delete("Lesson Reference", {"parent": chapter, "lesson": lesson})
else:
lessons.insert(idx, lesson)
update_index(lessons, chapter)
def update_target_chapter(lesson, chapter, idx):
lessons = frappe.get_all(
"Lesson Reference", "Lesson Reference",
{
"parent": chapter,
},
pluck="lesson",
order_by="idx",
)
lessons.insert(idx, lesson)
new_lesson_reference = frappe.new_doc("Lesson Reference")
new_lesson_reference.update(
{ {
"lesson": lesson, "lesson": lesson,
"parent": chapter, "parent": chapter,
}, "parenttype": "Course Chapter",
"idx", "parentfield": "lessons",
idx, }
)
new_lesson_reference.insert()
update_index(lessons, chapter)
def update_index(lessons, chapter):
print("final")
print(lessons)
for row in lessons:
frappe.db.set_value(
"Lesson Reference", {"lesson": row, "parent": chapter}, "idx", lessons.index(row) + 1
) )
frappe.db.commit() frappe.db.commit()

View File

@@ -1,7 +1,9 @@
{% set title = frappe.db.get_value("LMS Course", doc.course, "title") %} {% set title = frappe.db.get_value("LMS Course", doc.course, "title") %}
{% set timezone = frappe.db.get_value("LMS Batch", doc.batch, "timezone") %} {% set timezone = frappe.db.get_value("LMS Batch", doc.batch, "timezone") %}
{% set timezone = timezone if timezone else '' %} {% set timezone = timezone if timezone else '' %}
{% set evaluator_name = frappe.db.get_value("User", doc.evaluator, "full_name") %}
<p> {{ _("Hey {0}").format(doc.member_name) }} </p> <p> {{ _("Hey {0}").format(doc.member_name) }} </p>
<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, "medium"), frappe.utils.format_time(doc.start_time, "short"), timezone) }}</p> <p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, "medium"), frappe.utils.format_time(doc.start_time, "short"), timezone) }}</p>
<p> {{ _("Your evaluator is {0}").format(evaluator_name) }}
<p> {{ _("Please prepare well and be on time for the evaluations.") }} </p> <p> {{ _("Please prepare well and be on time for the evaluations.") }} </p>

View File

@@ -10,10 +10,10 @@
"event": "New", "event": "New",
"idx": 0, "idx": 0,
"is_standard": 1, "is_standard": 1,
"message": "{% set title = frappe.db.get_value(\"LMS Course\", doc.course, \"title\") %}\n{% set timezone = frappe.db.get_value(\"LMS Batch\", doc.batch, \"timezone\") %}\n{% set timezone = timezone if timezone else '' %}\n\n<p> {{ _(\"Hey {0}\").format(doc.member_name) }} </p>\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\"), timezone) }}</p>\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n", "message": "{% set title = frappe.db.get_value(\"LMS Course\", doc.course, \"title\") %}\n{% set timezone = frappe.db.get_value(\"LMS Batch\", doc.batch, \"timezone\") %}\n{% set timezone = timezone if timezone else '' %}\n{% set evaluator_name = frappe.db.get_value(\"User\", doc.evaluator, \"full_name\") %}\n\n<p> {{ _(\"Hey {0}\").format(doc.member_name) }} </p>\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\"), timezone) }}</p>\n<p> {{ _(\"Your evaluator is {0}\").format(evaluator_name) }}\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n",
"message_type": "HTML", "message_type": "HTML",
"modified": "2024-06-21 13:15:38.588768", "modified": "2024-07-10 15:51:03.429317",
"modified_by": "Administrator", "modified_by": "sayali@erpnext.com",
"module": "LMS", "module": "LMS",
"name": "Certificate Request Creation", "name": "Certificate Request Creation",
"owner": "Administrator", "owner": "Administrator",

View File

@@ -1,7 +1,8 @@
{% set title = frappe.db.get_value("LMS Course", doc.course, "title") %} {% set title = frappe.db.get_value("LMS Course", doc.course, "title") %}
{% set timezone = frappe.db.get_value("LMS Batch", doc.batch, "timezone") %} {% set timezone = frappe.db.get_value("LMS Batch", doc.batch, "timezone") %}
{% set timezone = timezone if timezone else '' %} {% set timezone = timezone if timezone else '' %}
{% set evaluator_name = frappe.db.get_value("User", doc.evaluator, "full_name") %}
<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, "medium"), frappe.utils.format_time(doc.start_time, "short"), timezone) }}</p> <p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, "medium"), frappe.utils.format_time(doc.start_time, "short"), timezone) }}</p>
<p> {{ _("Your evaluator is {0}").format(evaluator_name) }}
<p> {{ _("Please prepare well and be on time for the evaluations.") }} </p> <p> {{ _("Please prepare well and be on time for the evaluations.") }} </p>

View File

@@ -11,10 +11,10 @@
"event": "Days Before", "event": "Days Before",
"idx": 0, "idx": 0,
"is_standard": 1, "is_standard": 1,
"message": "{% set title = frappe.db.get_value(\"LMS Course\", doc.course, \"title\") %}\n{% set timezone = frappe.db.get_value(\"LMS Batch\", doc.batch, \"timezone\") %}\n{% set timezone = timezone if timezone else '' %}\n\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\"), timezone) }}</p>\n\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n", "message": "{% set title = frappe.db.get_value(\"LMS Course\", doc.course, \"title\") %}\n{% set timezone = frappe.db.get_value(\"LMS Batch\", doc.batch, \"timezone\") %}\n{% set timezone = timezone if timezone else '' %}\n{% set evaluator_name = frappe.db.get_value(\"User\", doc.evaluator, \"full_name\") %}\n\n<p> {{ _('Your evaluation for the course {0} has been scheduled on {1} at {2} {3}.').format(title, frappe.utils.format_date(doc.date, \"medium\"), frappe.utils.format_time(doc.start_time, \"short\"), timezone) }}</p>\n<p> {{ _(\"Your evaluator is {0}\").format(evaluator_name) }}\n<p> {{ _(\"Please prepare well and be on time for the evaluations.\") }} </p>\n",
"message_type": "HTML", "message_type": "HTML",
"modified": "2024-06-21 13:17:26.360030", "modified": "2024-07-10 15:51:33.803704",
"modified_by": "Administrator", "modified_by": "sayali@erpnext.com",
"module": "LMS", "module": "LMS",
"name": "Certificate Request Reminder", "name": "Certificate Request Reminder",
"owner": "Administrator", "owner": "Administrator",