Merge pull request #1263 from FahidLatheef/feat/scorm-progress

feat: SCORM Course Resume Functionality
This commit is contained in:
Jannat Patel
2025-09-17 12:50:22 +05:30
committed by GitHub
7 changed files with 121 additions and 20 deletions

View File

@@ -12,7 +12,10 @@
user.data?.is_instructor)
"
>
<iframe :src="chapter.doc.launch_file" class="w-full h-screen" />
<iframe
:src="chapter.doc.launch_file"
class="w-full h-[calc(100vh-3.00rem)]"
/>
</div>
<div v-else-if="!enrollment.data?.length">
<div class="text-center pt-10 px-5 md:px-0 pb-10">
@@ -49,6 +52,12 @@ const { brand } = sessionStore()
const sidebarStore = useSidebar()
const user = inject('$user')
const readyToRender = ref(false)
const isSuccessfullyCompleted = ref(false)
// If courseRestartOnFailure is true, student has to restart the whole course if failed.
// Otherwise, student could retake the final quiz portion.
// Ideally, this should be configurable along with `Number of failures before course should restart`.
const courseRestartOnFailure = false
const props = defineProps({
courseName: {
@@ -88,25 +97,51 @@ const enrollment = createListResource({
})
const getDataFromLMS = (key) => {
if (key == 'cmi.core.lesson_status') {
if (progress.data?.status == 'Complete') {
return 'passed'
}
return 'incomplete'
if (key === 'cmi.core.lesson_status') {
return progress.data?.status === 'Complete' ? 'passed' : 'incomplete'
} else if (key === 'cmi.launch_data') {
return progress.data?.scorm_content || ''
} else if (key === 'cmi.suspend_data') {
return progress.data?.scorm_content || ''
}
return ''
}
let saveTimeout = null
const debouncedSaveProgress = (scormDetails) => {
clearTimeout(saveTimeout)
saveTimeout = setTimeout(() => {
saveProgress(scormDetails)
}, 300)
}
const saveDataToLMS = (key, value) => {
if (key == 'cmi.core.lesson_status' && value == 'passed') {
saveProgress()
if (key === 'cmi.core.lesson_status') {
if (value === 'passed') {
isSuccessfullyCompleted.value = true
saveProgress({
is_complete: isSuccessfullyCompleted.value,
scorm_content: '',
})
} else if (value === 'failed' && courseRestartOnFailure) {
saveProgress({
is_complete: isSuccessfullyCompleted.value,
scorm_content: '',
})
}
} else if (key === 'cmi.suspend_data' && !isSuccessfullyCompleted.value) {
debouncedSaveProgress({
is_complete: false,
scorm_content: value,
})
}
}
const saveProgress = () => {
const saveProgress = (scormDetails = null) => {
call('lms.lms.doctype.course_lesson.course_lesson.save_progress', {
lesson: chapter.doc.lessons[0].lesson,
course: props.courseName,
scorm_details: scormDetails,
})
}
@@ -115,7 +150,7 @@ const progress = createResource({
makeParams(values) {
return {
doctype: 'LMS Course Progress',
fieldname: 'status',
fieldname: ['status', 'scorm_content'],
filters: {
member: user.data?.name,
lesson: chapter.doc.lessons[0].lesson,