fix: misc quiz submission issues

This commit is contained in:
Jannat Patel
2024-11-28 22:32:23 +05:30
parent 0e6df83961
commit 97543a43eb
10 changed files with 100 additions and 26 deletions

View File

@@ -186,18 +186,27 @@ const addQuizzes = () => {
} }
const addPrograms = () => { const addPrograms = () => {
if (settingsStore.learningPaths.data) { let activeFor = ['Programs', 'ProgramForm']
let activeFor = ['Programs', 'ProgramForm'] let index = 1
let index = 1 let canAddProgram = false
if (!isInstructor.value && !isModerator.value) {
sidebarLinks.value = sidebarLinks.value.filter(
(link) => link.label !== 'Courses'
)
activeFor.push('CourseDetail')
activeFor.push('Lesson')
index = 0
}
if (
!isInstructor.value &&
!isModerator.value &&
settingsStore.learningPaths.data
) {
sidebarLinks.value = sidebarLinks.value.filter(
(link) => link.label !== 'Courses'
)
activeFor.push('CourseDetail')
activeFor.push('Lesson')
index = 0
canAddProgram = true
} else if (isInstructor.value || isModerator.value) {
canAddProgram = true
}
if (canAddProgram) {
sidebarLinks.value.splice(index, 0, { sidebarLinks.value.splice(index, 0, {
label: 'Programs', label: 'Programs',
icon: 'Route', icon: 'Route',

View File

@@ -8,7 +8,6 @@
<AppSidebar /> <AppSidebar />
</div> </div>
<div class="w-full overflow-auto" id="scrollContainer"> <div class="w-full overflow-auto" id="scrollContainer">
<OnboardingBanner />
<slot /> <slot />
</div> </div>
</div> </div>
@@ -17,5 +16,4 @@
</template> </template>
<script setup> <script setup>
import AppSidebar from './AppSidebar.vue' import AppSidebar from './AppSidebar.vue'
import OnboardingBanner from '@/components/OnboardingBanner.vue'
</script> </script>

View File

@@ -3,7 +3,7 @@
class="sticky top-0 z-10 flex flex-col md:flex-row md:items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5" class="sticky top-0 z-10 flex flex-col md:flex-row md:items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
> >
<Breadcrumbs :items="breadbrumbs" /> <Breadcrumbs :items="breadbrumbs" />
<Button variant="solid"> <Button variant="solid" @click="saveProgram()">
{{ __('Save') }} {{ __('Save') }}
</Button> </Button>
</header> </header>
@@ -50,6 +50,7 @@
item-key="name" item-key="name"
group="items" group="items"
@end="updateOrder" @end="updateOrder"
class="cursor-move"
> >
<template #item="{ element: row }"> <template #item="{ element: row }">
<ListRow :row="row" /> <ListRow :row="row" />
@@ -175,7 +176,6 @@
import { import {
Breadcrumbs, Breadcrumbs,
Button, Button,
call,
createDocumentResource, createDocumentResource,
Dialog, Dialog,
FormControl, FormControl,
@@ -191,11 +191,13 @@ import { Plus, Trash2 } from 'lucide-vue-next'
import Link from '@/components/Controls/Link.vue' import Link from '@/components/Controls/Link.vue'
import { showToast } from '@/utils/' import { showToast } from '@/utils/'
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
import { useRouter } from 'vue-router'
const showDialog = ref(false) const showDialog = ref(false)
const currentForm = ref(null) const currentForm = ref(null)
const course = ref(null) const course = ref(null)
const member = ref(null) const member = ref(null)
const router = useRouter()
const props = defineProps({ const props = defineProps({
programName: { programName: {
@@ -302,6 +304,28 @@ const updateOrder = (e) => {
) )
} }
const saveProgram = () => {
program.setValue.submit(
{
title: program.doc.title,
program_courses: program.doc.program_courses,
program_members: program.doc.program_members,
},
{
onSuccess(data) {
router.push({
name: 'ProgramsForm',
params: { programName: data.name },
})
showToast(__('Success'), __('Program saved successfully'), 'check')
},
onError(err) {
showToast('Error', err.messages?.[0] || err, 'x')
},
}
)
}
const courseColumns = computed(() => { const courseColumns = computed(() => {
return [ return [
{ {

View File

@@ -205,7 +205,6 @@ import {
inject, inject,
onBeforeUnmount, onBeforeUnmount,
watch, watch,
isReactive,
} from 'vue' } from 'vue'
import { Plus, Trash2 } from 'lucide-vue-next' import { Plus, Trash2 } from 'lucide-vue-next'
import Question from '@/components/Modals/Question.vue' import Question from '@/components/Modals/Question.vue'

View File

@@ -15,7 +15,7 @@
</Button> </Button>
</div> </div>
</header> </header>
<div v-if="submisisonDetails.doc" class="w-1/2 mx-auto py-5 space-y-7"> <div v-if="submisisonDetails.doc" class="w-1/2 mx-auto py-5 space-y-5">
<div class="text-xl font-semibold"> <div class="text-xl font-semibold">
{{ submisisonDetails.doc.member_name }} {{ submisisonDetails.doc.member_name }}
</div> </div>
@@ -74,7 +74,7 @@ import {
Button, Button,
Badge, Badge,
} from 'frappe-ui' } from 'frappe-ui'
import { computed, onMounted, inject } from 'vue' import { computed, onBeforeUnmount, onMounted, inject } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { showToast } from '@/utils' import { showToast } from '@/utils'
@@ -84,8 +84,25 @@ const user = inject('$user')
onMounted(() => { onMounted(() => {
if (!user.data?.is_instructor && !user.data?.is_moderator) if (!user.data?.is_instructor && !user.data?.is_moderator)
router.push({ name: 'Courses' }) router.push({ name: 'Courses' })
window.addEventListener('keydown', keyboardShortcut)
}) })
onBeforeUnmount(() => {
window.removeEventListener('keydown', keyboardShortcut)
})
const keyboardShortcut = (e) => {
if (
e.key === 's' &&
(e.ctrlKey || e.metaKey) &&
!e.target.classList.contains('ProseMirror')
) {
saveSubmission()
e.preventDefault()
}
}
const props = defineProps({ const props = defineProps({
submission: { submission: {
type: String, type: String,

View File

@@ -34,7 +34,7 @@
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2024-11-20 12:26:02.214628", "modified": "2024-11-28 22:06:16.742867",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Program", "name": "LMS Program",
@@ -80,5 +80,6 @@
], ],
"sort_field": "creation", "sort_field": "creation",
"sort_order": "DESC", "sort_order": "DESC",
"states": [] "states": [],
"track_changes": 1
} }

View File

@@ -10,6 +10,7 @@ class LMSProgram(Document):
def validate(self): def validate(self):
self.validate_program_courses() self.validate_program_courses()
self.validate_program_members() self.validate_program_members()
self.validate_title()
def validate_program_courses(self): def validate_program_courses(self):
courses = [row.course for row in self.program_courses] courses = [row.course for row in self.program_courses]
@@ -30,3 +31,7 @@ class LMSProgram(Document):
frappe.bold(next(iter(duplicates))) frappe.bold(next(iter(duplicates)))
) )
) )
def validate_title(self):
if self.has_value_changed("title"):
frappe.rename_doc(self.doctype, self.name, self.title)

View File

@@ -145,7 +145,6 @@ def quiz_summary(quiz, results):
submission = frappe.new_doc("LMS Quiz Submission") submission = frappe.new_doc("LMS Quiz Submission")
# Score and percentage are calculated by the controller function # Score and percentage are calculated by the controller function
print(results)
submission.update( submission.update(
{ {
"doctype": "LMS Quiz Submission", "doctype": "LMS Quiz Submission",

View File

@@ -5,6 +5,7 @@ import frappe
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import cint from frappe.utils import cint
from frappe import _ from frappe import _
from frappe.desk.doctype.notification_log.notification_log import make_notification_logs
class LMSQuizSubmission(Document): class LMSQuizSubmission(Document):
@@ -12,6 +13,9 @@ class LMSQuizSubmission(Document):
self.validate_marks() self.validate_marks()
self.set_percentage() self.set_percentage()
def on_update(self):
self.notify_member()
def validate_marks(self): def validate_marks(self):
for row in self.result: for row in self.result:
if cint(row.marks) > cint(row.marks_out_of): if cint(row.marks) > cint(row.marks_out_of):
@@ -26,3 +30,25 @@ class LMSQuizSubmission(Document):
def set_percentage(self): def set_percentage(self):
if self.score and self.score_out_of: if self.score and self.score_out_of:
self.percentage = (self.score / self.score_out_of) * 100 self.percentage = (self.score / self.score_out_of) * 100
def notify_member(self):
print(self.is_new())
if self.score != 0 and self.has_value_changed("score"):
notification = frappe._dict(
{
"subject": _("You have got a score of {0} for the quiz {1}").format(
self.score, self.quiz_title
),
"email_content": _(
"There has been an update on your submission. You have got a score of {0} for the quiz {1}"
).format(self.score, self.quiz_title),
"document_type": self.doctype,
"document_name": self.name,
"for_user": self.member,
"from_user": "Administrator",
"type": "Alert",
"link": "",
}
)
make_notification_logs(notification, [self.member])

View File

@@ -6,11 +6,7 @@ import razorpay
import requests import requests
from frappe import _ from frappe import _
from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_result from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_result
from frappe.desk.doctype.notification_log.notification_log import ( from frappe.desk.doctype.notification_log.notification_log import make_notification_logs
make_notification_logs,
enqueue_create_notification,
get_title,
)
from frappe.desk.search import get_user_groups from frappe.desk.search import get_user_groups
from frappe.desk.notifications import extract_mentions from frappe.desk.notifications import extract_mentions
from frappe.utils import ( from frappe.utils import (