Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
736d79b8c9 | ||
|
|
98c0bd5f3e | ||
|
|
289a0f9122 | ||
|
|
3cd08c80c8 | ||
|
|
3d82c36250 | ||
|
|
9b9af0215a | ||
|
|
2e4cf02737 | ||
|
|
438e9e1c47 | ||
|
|
36ded70eef | ||
|
|
ba78a15a1f | ||
|
|
93061194bb | ||
|
|
6d41e4e552 | ||
|
|
3b06968d0a |
@@ -5,7 +5,7 @@ describe("Course Creation", () => {
|
|||||||
cy.visit("/lms/courses");
|
cy.visit("/lms/courses");
|
||||||
|
|
||||||
// Create a course
|
// Create a course
|
||||||
cy.get("a").contains("New Course").click();
|
cy.get("a").contains("New").click();
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
cy.url().should("include", "/courses/new/edit");
|
cy.url().should("include", "/courses/new/edit");
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ const unreadCount = ref(0)
|
|||||||
const sidebarLinks = ref(getSidebarLinks())
|
const sidebarLinks = ref(getSidebarLinks())
|
||||||
const showPageModal = ref(false)
|
const showPageModal = ref(false)
|
||||||
const isModerator = ref(false)
|
const isModerator = ref(false)
|
||||||
|
const isInstructor = ref(false)
|
||||||
const pageToEdit = ref(null)
|
const pageToEdit = ref(null)
|
||||||
const showWebPages = ref(false)
|
const showWebPages = ref(false)
|
||||||
|
|
||||||
@@ -167,6 +168,17 @@ const addNotifications = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addQuizzes = () => {
|
||||||
|
if (isInstructor.value || isModerator.value) {
|
||||||
|
sidebarLinks.value.push({
|
||||||
|
label: 'Quizzes',
|
||||||
|
icon: 'CircleHelp',
|
||||||
|
to: 'Quizzes',
|
||||||
|
activeFor: ['Quizzes', 'QuizForm'],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const openPageModal = (link) => {
|
const openPageModal = (link) => {
|
||||||
showPageModal.value = true
|
showPageModal.value = true
|
||||||
pageToEdit.value = link
|
pageToEdit.value = link
|
||||||
@@ -197,6 +209,8 @@ const getSidebarFromStorage = () => {
|
|||||||
watch(userResource, () => {
|
watch(userResource, () => {
|
||||||
if (userResource.data) {
|
if (userResource.data) {
|
||||||
isModerator.value = userResource.data.is_moderator
|
isModerator.value = userResource.data.is_moderator
|
||||||
|
isInstructor.value = userResource.data.is_instructor
|
||||||
|
addQuizzes()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ const getRowRoute = (row) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
name: 'Quiz',
|
name: 'QuizPage',
|
||||||
params: {
|
params: {
|
||||||
quizID: row.assessment_name,
|
quizID: row.assessment_name,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
<iframe
|
<iframe
|
||||||
:src="getPDFSource(block)"
|
:src="getPDFSource(block)"
|
||||||
width="100%"
|
width="100%"
|
||||||
height="400"
|
height="700px"
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
allowfullscreen
|
allowfullscreen
|
||||||
></iframe>
|
></iframe>
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="sidebarSettings.data"
|
v-if="sidebarSettings.data"
|
||||||
class="fixed flex justify-around border-t border-gray-300 bottom-0 z-10 w-full bg-white standalone:pb-4"
|
class="fixed flex items-center justify-around border-t border-gray-300 bottom-0 z-10 w-full bg-white standalone:pb-4"
|
||||||
:style="{
|
:style="{
|
||||||
gridTemplateColumns: `repeat(${sidebarLinks.length}, minmax(0, 1fr))`,
|
gridTemplateColumns: `repeat(${
|
||||||
|
sidebarLinks.length + 1
|
||||||
|
}, minmax(0, 1fr))`,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@@ -23,15 +25,46 @@
|
|||||||
:class="[isActive(tab) ? 'text-gray-900' : 'text-gray-600']"
|
:class="[isActive(tab) ? 'text-gray-900' : 'text-gray-600']"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<Popover
|
||||||
|
trigger="hover"
|
||||||
|
popoverClass="bottom-28 mx-2"
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
|
<template #target>
|
||||||
|
<component
|
||||||
|
:is="icons['List']"
|
||||||
|
class="h-6 w-6 stroke-1.5 text-gray-600"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #body-main>
|
||||||
|
<div class="text-base p-5 space-y-4">
|
||||||
|
<div
|
||||||
|
v-for="link in otherLinks"
|
||||||
|
:key="link.label"
|
||||||
|
class="flex items-center space-x-2"
|
||||||
|
@click="handleClick(link)"
|
||||||
|
>
|
||||||
|
<component
|
||||||
|
:is="icons[link.icon]"
|
||||||
|
class="h-4 w-4 stroke-1.5 text-gray-600"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
{{ link.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { getSidebarLinks } from '../utils'
|
import { getSidebarLinks } from '../utils'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { computed, ref, onMounted } from 'vue'
|
import { watch, ref, onMounted } from 'vue'
|
||||||
import { sessionStore } from '@/stores/session'
|
import { sessionStore } from '@/stores/session'
|
||||||
import { usersStore } from '@/stores/user'
|
import { usersStore } from '@/stores/user'
|
||||||
|
import { Popover } from 'frappe-ui'
|
||||||
import * as icons from 'lucide-vue-next'
|
import * as icons from 'lucide-vue-next'
|
||||||
|
|
||||||
const { logout, user, sidebarSettings } = sessionStore()
|
const { logout, user, sidebarSettings } = sessionStore()
|
||||||
@@ -39,6 +72,7 @@ let { isLoggedIn } = sessionStore()
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
let { userResource } = usersStore()
|
let { userResource } = usersStore()
|
||||||
const sidebarLinks = ref(getSidebarLinks())
|
const sidebarLinks = ref(getSidebarLinks())
|
||||||
|
const otherLinks = ref([])
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
sidebarSettings.reload(
|
sidebarSettings.reload(
|
||||||
@@ -52,37 +86,53 @@ onMounted(() => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
addAccessLinks()
|
|
||||||
|
addOtherLinks()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const addAccessLinks = () => {
|
const addOtherLinks = () => {
|
||||||
if (user) {
|
if (user) {
|
||||||
sidebarLinks.value.push({
|
otherLinks.value.push({
|
||||||
|
label: 'Notifications',
|
||||||
|
icon: 'Bell',
|
||||||
|
to: 'Notifications',
|
||||||
|
})
|
||||||
|
otherLinks.value.push({
|
||||||
label: 'Profile',
|
label: 'Profile',
|
||||||
icon: 'UserRound',
|
icon: 'UserRound',
|
||||||
activeFor: [
|
|
||||||
'Profile',
|
|
||||||
'ProfileAbout',
|
|
||||||
'ProfileCertification',
|
|
||||||
'ProfileEvaluator',
|
|
||||||
'ProfileRoles',
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
sidebarLinks.value.push({
|
otherLinks.value.push({
|
||||||
label: 'Log out',
|
label: 'Log out',
|
||||||
icon: 'LogOut',
|
icon: 'LogOut',
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
sidebarLinks.value.push({
|
otherLinks.value.push({
|
||||||
label: 'Log in',
|
label: 'Log in',
|
||||||
icon: 'LogIn',
|
icon: 'LogIn',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(userResource, () => {
|
||||||
|
if (
|
||||||
|
userResource.data &&
|
||||||
|
(userResource.data.is_moderator || userResource.data.is_instructor)
|
||||||
|
) {
|
||||||
|
addQuizzes()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const addQuizzes = () => {
|
||||||
|
otherLinks.value.push({
|
||||||
|
label: 'Quizzes',
|
||||||
|
icon: 'CircleHelp',
|
||||||
|
to: 'Quizzes',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let isActive = (tab) => {
|
let isActive = (tab) => {
|
||||||
return tab.activeFor?.includes(router.currentRoute.value.name)
|
return tab.activeFor?.includes(router.currentRoute.value.name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
:label="__('Type')"
|
:label="__('Type')"
|
||||||
v-model="question.type"
|
v-model="question.type"
|
||||||
type="select"
|
type="select"
|
||||||
:options="['Choices', 'User Input']"
|
:options="['Choices', 'User Input', 'Open Ended']"
|
||||||
class="pb-2"
|
class="pb-2"
|
||||||
/>
|
/>
|
||||||
<div v-if="question.type == 'Choices'" class="divide-y border-t">
|
<div v-if="question.type == 'Choices'" class="divide-y border-t">
|
||||||
@@ -74,7 +74,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else v-for="n in 4" class="space-y-2">
|
<div
|
||||||
|
v-else-if="question.type == 'User Input'"
|
||||||
|
v-for="n in 4"
|
||||||
|
class="space-y-2"
|
||||||
|
>
|
||||||
<FormControl
|
<FormControl
|
||||||
:label="__('Possibility') + ' ' + n"
|
:label="__('Possibility') + ' ' + n"
|
||||||
v-model="question[`possibility_${n}`]"
|
v-model="question[`possibility_${n}`]"
|
||||||
|
|||||||
@@ -67,15 +67,8 @@
|
|||||||
<span class="mr-2">
|
<span class="mr-2">
|
||||||
{{ __('Question {0}').format(activeQuestion) }}:
|
{{ __('Question {0}').format(activeQuestion) }}:
|
||||||
</span>
|
</span>
|
||||||
<span v-if="questionDetails.data.type == 'User Input'">
|
<span>
|
||||||
{{ __('Type your answer') }}
|
{{ getInstructions(questionDetails.data) }}
|
||||||
</span>
|
|
||||||
<span v-else>
|
|
||||||
{{
|
|
||||||
questionDetails.data.multiple
|
|
||||||
? __('Choose all answers that apply')
|
|
||||||
: __('Choose one answer')
|
|
||||||
}}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-gray-900 text-sm font-semibold item-left">
|
<div class="text-gray-900 text-sm font-semibold item-left">
|
||||||
@@ -139,7 +132,7 @@
|
|||||||
{{ questionDetails.data[`explanation_${index}`] }}
|
{{ questionDetails.data[`explanation_${index}`] }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else-if="questionDetails.data.type == 'User Input'">
|
||||||
<FormControl
|
<FormControl
|
||||||
v-model="possibleAnswer"
|
v-model="possibleAnswer"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
@@ -159,6 +152,16 @@
|
|||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<TextEditor
|
||||||
|
class="mt-4"
|
||||||
|
:content="possibleAnswer"
|
||||||
|
@change="(val) => (possibleAnswer = val)"
|
||||||
|
:editable="true"
|
||||||
|
:fixedMenu="true"
|
||||||
|
editorClass="prose-sm max-w-none border-b border-x bg-gray-100 rounded-b-md py-1 px-2 min-h-[7rem]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="flex items-center justify-between mt-5">
|
<div class="flex items-center justify-between mt-5">
|
||||||
<div>
|
<div>
|
||||||
{{
|
{{
|
||||||
@@ -169,7 +172,11 @@
|
|||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
v-if="quiz.data.show_answers && !showAnswers.length"
|
v-if="
|
||||||
|
quiz.data.show_answers &&
|
||||||
|
!showAnswers.length &&
|
||||||
|
questionDetails.data.type != 'Open Ended'
|
||||||
|
"
|
||||||
@click="checkAnswer()"
|
@click="checkAnswer()"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
@@ -193,11 +200,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="border rounded-md p-20 text-center">
|
<div v-else class="border rounded-md p-20 text-center space-y-4">
|
||||||
<div class="text-lg font-semibold">
|
<div class="text-lg font-semibold">
|
||||||
{{ __('Quiz Summary') }}
|
{{ __('Quiz Summary') }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div v-if="quizSubmission.data.is_open_ended">
|
||||||
|
{{
|
||||||
|
__(
|
||||||
|
"Your submission has been successfully saved. The instructor will review and grade it shortly, and you'll be notified of your final result."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
{{
|
{{
|
||||||
__(
|
__(
|
||||||
'You got {0}% correct answers with a score of {1} out of {2}'
|
'You got {0}% correct answers with a score of {1} out of {2}'
|
||||||
@@ -236,7 +250,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Badge, Button, createResource, ListView } from 'frappe-ui'
|
import { Badge, Button, createResource, ListView, TextEditor } from 'frappe-ui'
|
||||||
import { ref, watch, reactive, inject } from 'vue'
|
import { ref, watch, reactive, inject } from 'vue'
|
||||||
import { createToast } from '@/utils/'
|
import { createToast } from '@/utils/'
|
||||||
import { CheckCircle, XCircle, MinusCircle } from 'lucide-vue-next'
|
import { CheckCircle, XCircle, MinusCircle } from 'lucide-vue-next'
|
||||||
@@ -450,9 +464,10 @@ const addToLocalStorage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nextQuetion = () => {
|
const nextQuetion = () => {
|
||||||
if (!quiz.data.show_answers) {
|
if (!quiz.data.show_answers && questionDetails.data?.type != 'Open Ended') {
|
||||||
checkAnswer()
|
checkAnswer()
|
||||||
} else {
|
} else {
|
||||||
|
if (questionDetails.data?.type == 'Open Ended') addToLocalStorage()
|
||||||
resetQuestion()
|
resetQuestion()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -467,7 +482,8 @@ const resetQuestion = () => {
|
|||||||
|
|
||||||
const submitQuiz = () => {
|
const submitQuiz = () => {
|
||||||
if (!quiz.data.show_answers) {
|
if (!quiz.data.show_answers) {
|
||||||
checkAnswer()
|
if (questionDetails.data.type == 'Open Ended') addToLocalStorage()
|
||||||
|
else checkAnswer()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
createSubmission()
|
createSubmission()
|
||||||
}, 500)
|
}, 500)
|
||||||
@@ -490,6 +506,13 @@ const resetQuiz = () => {
|
|||||||
populateQuestions()
|
populateQuestions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getInstructions = (question) => {
|
||||||
|
if (question.type == 'Choices')
|
||||||
|
if (question.multiple) return __('Choose all answers that apply')
|
||||||
|
else return __('Choose one answer')
|
||||||
|
else return __('Type your answer')
|
||||||
|
}
|
||||||
|
|
||||||
const getSubmissionColumns = () => {
|
const getSubmissionColumns = () => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
: 'ml-2 w-auto opacity-100'
|
: 'ml-2 w-auto opacity-100'
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ link.label }}
|
{{ __(link.label) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="link.count" class="!ml-auto block text-xs text-gray-600">
|
<span v-if="link.count" class="!ml-auto block text-xs text-gray-600">
|
||||||
{{ link.count }}
|
{{ link.count }}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<template #prefix>
|
<template #prefix>
|
||||||
<Plus class="h-4 w-4 stroke-1.5" />
|
<Plus class="h-4 w-4 stroke-1.5" />
|
||||||
</template>
|
</template>
|
||||||
{{ __('New Batch') }}
|
{{ __('New') }}
|
||||||
</Button>
|
</Button>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -122,9 +122,18 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="solid" class="mt-8" @click="generatePaymentLink()">
|
<div class="flex items-center justify-between border-t pt-4 mt-8">
|
||||||
{{ __('Proceed to Payment') }}
|
<p class="text-gray-600">
|
||||||
</Button>
|
{{
|
||||||
|
__(
|
||||||
|
'Make sure to enter the right billing name as the same will be used in your invoice.'
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<Button variant="solid" size="md" @click="generatePaymentLink()">
|
||||||
|
{{ __('Proceed to Payment') }}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
:items="[{ label: __('Courses'), route: { name: 'Courses' } }]"
|
:items="[{ label: __('Courses'), route: { name: 'Courses' } }]"
|
||||||
/>
|
/>
|
||||||
<div class="flex space-x-2 justify-end">
|
<div class="flex space-x-2 justify-end">
|
||||||
<div class="w-44">
|
<div class="w-46 md:w-44">
|
||||||
<FormControl
|
<FormControl
|
||||||
v-if="categories.data?.length"
|
v-if="categories.data?.length"
|
||||||
type="select"
|
type="select"
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
:placeholder="__('Category')"
|
:placeholder="__('Category')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-36">
|
<div class="w-28 md:w-36">
|
||||||
<FormControl
|
<FormControl
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<template #prefix>
|
<template #prefix>
|
||||||
<Plus class="h-4 w-4" />
|
<Plus class="h-4 w-4" />
|
||||||
</template>
|
</template>
|
||||||
{{ __('New Course') }}
|
{{ __('New') }}
|
||||||
</Button>
|
</Button>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
<img
|
<img
|
||||||
:src="badge.badge_image"
|
:src="badge.badge_image"
|
||||||
:alt="badge.badge"
|
:alt="badge.badge"
|
||||||
class="bg-gray-100 rounded-t-md"
|
class="bg-gray-100 rounded-t-md h-[200px] mx-auto"
|
||||||
/>
|
/>
|
||||||
<div class="p-5">
|
<div class="p-5">
|
||||||
<div class="text-2xl font-semibold mb-2">
|
<div class="text-2xl font-semibold mb-2">
|
||||||
|
|||||||
@@ -3,9 +3,24 @@
|
|||||||
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
||||||
>
|
>
|
||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
<Button variant="solid" @click="submitQuiz()">
|
<div class="space-x-2">
|
||||||
{{ __('Save') }}
|
<router-link
|
||||||
</Button>
|
v-if="quizDetails.data?.name"
|
||||||
|
:to="{
|
||||||
|
name: 'QuizSubmissionList',
|
||||||
|
params: {
|
||||||
|
quizID: quizDetails.data.name,
|
||||||
|
},
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<Button>
|
||||||
|
{{ __('Submission List') }}
|
||||||
|
</Button>
|
||||||
|
</router-link>
|
||||||
|
<Button variant="solid" @click="submitQuiz()">
|
||||||
|
{{ __('Save') }}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="w-3/4 mx-auto py-5">
|
<div class="w-3/4 mx-auto py-5">
|
||||||
<!-- Details -->
|
<!-- Details -->
|
||||||
@@ -347,17 +362,17 @@ const questionColumns = computed(() => {
|
|||||||
{
|
{
|
||||||
label: __('ID'),
|
label: __('ID'),
|
||||||
key: 'question',
|
key: 'question',
|
||||||
width: '25%',
|
width: '10rem',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __('Question'),
|
label: __('Question'),
|
||||||
key: __('question_detail'),
|
key: __('question_detail'),
|
||||||
width: '60%',
|
width: '40rem',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: __('Marks'),
|
label: __('Marks'),
|
||||||
key: 'marks',
|
key: 'marks',
|
||||||
width: '10%',
|
width: '5rem',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
58
frontend/src/pages/QuizPage.vue
Normal file
58
frontend/src/pages/QuizPage.vue
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<header
|
||||||
|
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
||||||
|
>
|
||||||
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
|
</header>
|
||||||
|
<div class="md:w-7/12 md:mx-auto mx-4 py-10">
|
||||||
|
<Quiz :quizName="quizID" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import Quiz from '@/components/Quiz.vue'
|
||||||
|
import { createResource, Breadcrumbs } from 'frappe-ui'
|
||||||
|
import { computed, inject, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { updateDocumentTitle } from '@/utils'
|
||||||
|
|
||||||
|
const user = inject('$user')
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!user.data) {
|
||||||
|
router.push({ name: 'Courses' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
quizID: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const title = createResource({
|
||||||
|
url: 'frappe.client.get_value',
|
||||||
|
params: {
|
||||||
|
doctype: 'LMS Quiz',
|
||||||
|
fieldname: 'title',
|
||||||
|
filters: {
|
||||||
|
name: props.quizID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
auto: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const breadcrumbs = computed(() => {
|
||||||
|
return [{ label: __('Quiz Submission') }, { label: title.data?.title }]
|
||||||
|
})
|
||||||
|
|
||||||
|
const pageMeta = computed(() => {
|
||||||
|
return {
|
||||||
|
title: title.data?.title,
|
||||||
|
description: __('Quiz Submission'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
updateDocumentTitle(pageMeta)
|
||||||
|
</script>
|
||||||
@@ -2,47 +2,121 @@
|
|||||||
<header
|
<header
|
||||||
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
||||||
>
|
>
|
||||||
<Breadcrumbs :items="breadcrumbs" />
|
<Breadcrumbs v-if="submisisonDetails.doc" :items="breadcrumbs" />
|
||||||
|
<div class="space-x-2">
|
||||||
|
<Badge
|
||||||
|
v-if="submisisonDetails.isDirty"
|
||||||
|
:label="__('Not Saved')"
|
||||||
|
variant="subtle"
|
||||||
|
theme="orange"
|
||||||
|
/>
|
||||||
|
<Button variant="solid" @click="saveSubmission()">
|
||||||
|
{{ __('Save') }}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="w-1/2 mx-auto py-10">
|
<div v-if="submisisonDetails.doc" class="w-1/2 mx-auto py-5 space-y-4">
|
||||||
<Quiz :quizName="quizID" />
|
<div class="grid grid-cols-2 gap-5">
|
||||||
|
<FormControl
|
||||||
|
v-model="submisisonDetails.doc.quiz_title"
|
||||||
|
:label="__('Quiz')"
|
||||||
|
:disabled="true"
|
||||||
|
/>
|
||||||
|
<FormControl
|
||||||
|
v-model="submisisonDetails.doc.member_name"
|
||||||
|
:label="__('Member')"
|
||||||
|
:disabled="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 gap-5">
|
||||||
|
<FormControl
|
||||||
|
v-model="submisisonDetails.doc.score"
|
||||||
|
:label="__('Score')"
|
||||||
|
:disabled="true"
|
||||||
|
/>
|
||||||
|
<FormControl
|
||||||
|
v-model="submisisonDetails.doc.percentage"
|
||||||
|
:label="__('Percentage')"
|
||||||
|
:disabled="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-for="row in submisisonDetails.doc.result"
|
||||||
|
class="border p-5 rounded-md space-y-4"
|
||||||
|
>
|
||||||
|
<div class="font-semibold">{{ row.idx }}. {{ row.question }}</div>
|
||||||
|
<div v-html="row.answer" class="leading-5"></div>
|
||||||
|
<div class="grid grid-cols-2 gap-5">
|
||||||
|
<FormControl v-model="row.marks" :label="__('Marks')" />
|
||||||
|
<FormControl
|
||||||
|
v-model="row.marks_out_of"
|
||||||
|
:label="__('Marks out of')"
|
||||||
|
:disabled="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import Quiz from '@/components/Quiz.vue'
|
import {
|
||||||
import { createResource, Breadcrumbs } from 'frappe-ui'
|
createDocumentResource,
|
||||||
import { computed, inject, onMounted } from 'vue'
|
Breadcrumbs,
|
||||||
|
FormControl,
|
||||||
|
Button,
|
||||||
|
Badge,
|
||||||
|
} from 'frappe-ui'
|
||||||
|
import { computed, onMounted, inject } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
import { showToast } from '@/utils'
|
||||||
|
|
||||||
const user = inject('$user')
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const user = inject('$user')
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!user.data) {
|
if (!user.data?.is_instructor && !user.data?.is_moderator)
|
||||||
router.push({ name: 'Courses' })
|
router.push({ name: 'Courses' })
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
quizID: {
|
submission: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const title = createResource({
|
const submisisonDetails = createDocumentResource({
|
||||||
url: 'frappe.client.get_value',
|
doctype: 'LMS Quiz Submission',
|
||||||
params: {
|
name: props.submission,
|
||||||
doctype: 'LMS Quiz',
|
|
||||||
fieldname: 'title',
|
|
||||||
filters: {
|
|
||||||
name: props.quizID,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
auto: true,
|
auto: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const breadcrumbs = computed(() => {
|
const breadcrumbs = computed(() => {
|
||||||
return [{ label: __('Quiz Submission') }, { label: title.data?.title }]
|
return [
|
||||||
|
{
|
||||||
|
label: __('Quiz Submissions'),
|
||||||
|
route: {
|
||||||
|
name: 'QuizSubmissionList',
|
||||||
|
params: {
|
||||||
|
quizID: submisisonDetails.doc.quiz,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: submisisonDetails.doc.quiz_title,
|
||||||
|
},
|
||||||
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const saveSubmission = () => {
|
||||||
|
submisisonDetails.save.submit(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
onError(err) {
|
||||||
|
showToast(__('Error'), __(err.messages?.[0] || err), 'x')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
104
frontend/src/pages/QuizSubmissionList.vue
Normal file
104
frontend/src/pages/QuizSubmissionList.vue
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<header
|
||||||
|
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
||||||
|
>
|
||||||
|
<Breadcrumbs :items="breadcrumbs" />
|
||||||
|
</header>
|
||||||
|
<div v-if="submissions.data?.length" class="md:w-3/4 md:mx-auto py-5 mx-5">
|
||||||
|
<ListView
|
||||||
|
:columns="quizColumns"
|
||||||
|
:rows="submissions.data"
|
||||||
|
row-key="name"
|
||||||
|
:options="{ showTooltip: false, selectable: false }"
|
||||||
|
>
|
||||||
|
<ListHeader
|
||||||
|
class="mb-2 grid items-center space-x-4 rounded bg-gray-100 p-2"
|
||||||
|
>
|
||||||
|
<ListHeaderItem :item="item" v-for="item in quizColumns">
|
||||||
|
</ListHeaderItem>
|
||||||
|
</ListHeader>
|
||||||
|
<ListRows>
|
||||||
|
<router-link
|
||||||
|
v-for="row in submissions.data"
|
||||||
|
:to="{
|
||||||
|
name: 'QuizSubmission',
|
||||||
|
params: {
|
||||||
|
submission: row.name,
|
||||||
|
},
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<ListRow :row="row" />
|
||||||
|
</router-link>
|
||||||
|
</ListRows>
|
||||||
|
</ListView>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
createListResource,
|
||||||
|
Breadcrumbs,
|
||||||
|
ListView,
|
||||||
|
ListRow,
|
||||||
|
ListRows,
|
||||||
|
ListHeader,
|
||||||
|
ListHeaderItem,
|
||||||
|
} from 'frappe-ui'
|
||||||
|
import { computed, onMounted, inject } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const user = inject('$user')
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!user.data?.is_instructor && !user.data?.is_moderator)
|
||||||
|
router.push({ name: 'Courses' })
|
||||||
|
})
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
quizID: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const submissions = createListResource({
|
||||||
|
doctype: 'LMS Quiz Submission',
|
||||||
|
filters: {
|
||||||
|
quiz: props.quizID,
|
||||||
|
},
|
||||||
|
fields: ['name', 'member_name', 'score', 'percentage', 'quiz_title'],
|
||||||
|
orderBy: 'creation desc',
|
||||||
|
auto: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const quizColumns = computed(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: __('Member'),
|
||||||
|
key: 'member_name',
|
||||||
|
width: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Quiz'),
|
||||||
|
key: 'quiz_title',
|
||||||
|
width: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Score'),
|
||||||
|
key: 'score',
|
||||||
|
width: 1,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Percentage'),
|
||||||
|
key: 'percentage',
|
||||||
|
width: 1,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const breadcrumbs = computed(() => {
|
||||||
|
return [{ label: __('Quiz Submissions') }]
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</router-link>
|
</router-link>
|
||||||
</header>
|
</header>
|
||||||
<div v-if="quizzes.data?.length" class="w-3/4 mx-auto py-5">
|
<div v-if="quizzes.data?.length" class="md:w-3/4 md:mx-auto py-5 mx-5">
|
||||||
<ListView
|
<ListView
|
||||||
:columns="quizColumns"
|
:columns="quizColumns"
|
||||||
:rows="quizzes.data"
|
:rows="quizzes.data"
|
||||||
|
|||||||
@@ -160,7 +160,19 @@ const routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/quiz/:quizID',
|
path: '/quiz/:quizID',
|
||||||
name: 'Quiz',
|
name: 'QuizPage',
|
||||||
|
component: () => import('@/pages/QuizPage.vue'),
|
||||||
|
props: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/quiz-submissions/:quizID',
|
||||||
|
name: 'QuizSubmissionList',
|
||||||
|
component: () => import('@/pages/QuizSubmissionList.vue'),
|
||||||
|
props: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/quiz-submission/:submission',
|
||||||
|
name: 'QuizSubmission',
|
||||||
component: () => import('@/pages/QuizSubmission.vue'),
|
component: () => import('@/pages/QuizSubmission.vue'),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -56,9 +56,11 @@ export class Upload {
|
|||||||
app.mount(this.wrapper)
|
app.mount(this.wrapper)
|
||||||
return
|
return
|
||||||
} else if (file.file_type == 'PDF') {
|
} else if (file.file_type == 'PDF') {
|
||||||
this.wrapper.innerHTML = `<iframe src="${encodeURI(
|
this.wrapper.innerHTML = `<iframe src="https://docs.google.com/viewer?url=${
|
||||||
|
window.location.origin
|
||||||
|
}${encodeURI(
|
||||||
file.file_url
|
file.file_url
|
||||||
)}#toolbar=0" width='100%' height='700px' class="mb-4"></iframe>`
|
)}&embedded=true" width='100%' height='700px' class="mb-4" type="application/pdf"></iframe>`
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
this.wrapper.innerHTML = `<img class="mb-4" src=${encodeURI(
|
this.wrapper.innerHTML = `<img class="mb-4" src=${encodeURI(
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "2.7.0"
|
__version__ = "2.8.0"
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
"fieldname": "title",
|
"fieldname": "title",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
"label": "Title",
|
"label": "Title",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
@@ -161,7 +162,7 @@
|
|||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-04-03 10:48:17.525859",
|
"modified": "2024-10-08 11:04:54.748773",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Course Lesson",
|
"name": "Course Lesson",
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Type",
|
"label": "Type",
|
||||||
"options": "Choices\nUser Input"
|
"options": "Choices\nUser Input\nOpen Ended"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.type == \"Choices\";",
|
"depends_on": "eval:doc.type == \"Choices\";",
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"make_attachments_public": 1,
|
"make_attachments_public": 1,
|
||||||
"modified": "2024-08-01 12:53:22.540990",
|
"modified": "2024-10-07 09:41:17.862774",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Question",
|
"name": "LMS Question",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ def validate_correct_answers(question):
|
|||||||
if question.type == "Choices":
|
if question.type == "Choices":
|
||||||
validate_duplicate_options(question)
|
validate_duplicate_options(question)
|
||||||
validate_correct_options(question)
|
validate_correct_options(question)
|
||||||
else:
|
elif question.type == "User Input":
|
||||||
validate_possible_answer(question)
|
validate_possible_answer(question)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
import re
|
||||||
|
from frappe import _, safe_decode
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cstr, comma_and, cint
|
from frappe.utils import cstr, comma_and, cint
|
||||||
from fuzzywuzzy import fuzz
|
from fuzzywuzzy import fuzz
|
||||||
@@ -13,6 +14,9 @@ from lms.lms.utils import (
|
|||||||
has_course_moderator_role,
|
has_course_moderator_role,
|
||||||
has_course_instructor_role,
|
has_course_instructor_role,
|
||||||
)
|
)
|
||||||
|
from binascii import Error as BinasciiError
|
||||||
|
from frappe.utils.file_manager import safe_b64decode
|
||||||
|
from frappe.core.doctype.file.utils import get_random_filename
|
||||||
|
|
||||||
|
|
||||||
class LMSQuiz(Document):
|
class LMSQuiz(Document):
|
||||||
@@ -20,6 +24,7 @@ class LMSQuiz(Document):
|
|||||||
self.validate_duplicate_questions()
|
self.validate_duplicate_questions()
|
||||||
self.validate_limit()
|
self.validate_limit()
|
||||||
self.calculate_total_marks()
|
self.calculate_total_marks()
|
||||||
|
self.validate_open_ended_questions()
|
||||||
|
|
||||||
def validate_duplicate_questions(self):
|
def validate_duplicate_questions(self):
|
||||||
questions = [row.question for row in self.questions]
|
questions = [row.question for row in self.questions]
|
||||||
@@ -48,6 +53,19 @@ class LMSQuiz(Document):
|
|||||||
else:
|
else:
|
||||||
self.total_marks = sum(cint(question.marks) for question in self.questions)
|
self.total_marks = sum(cint(question.marks) for question in self.questions)
|
||||||
|
|
||||||
|
def validate_open_ended_questions(self):
|
||||||
|
types = [question.type for question in self.questions]
|
||||||
|
types = set(types)
|
||||||
|
|
||||||
|
if "Open Ended" in types and len(types) > 1:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"If you want open ended questions then make sure each question in the quiz is of open ended type."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.show_answers = 0
|
||||||
|
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
if not self.name:
|
if not self.name:
|
||||||
self.name = generate_slug(self.title, "LMS Quiz")
|
self.name = generate_slug(self.title, "LMS Quiz")
|
||||||
@@ -81,34 +99,50 @@ def set_total_marks(questions):
|
|||||||
def quiz_summary(quiz, results):
|
def quiz_summary(quiz, results):
|
||||||
score = 0
|
score = 0
|
||||||
results = results and json.loads(results)
|
results = results and json.loads(results)
|
||||||
|
is_open_ended = False
|
||||||
|
|
||||||
for result in results:
|
for result in results:
|
||||||
correct = result["is_correct"][0]
|
|
||||||
for point in result["is_correct"]:
|
|
||||||
correct = correct and point
|
|
||||||
result["is_correct"] = correct
|
|
||||||
|
|
||||||
question_details = frappe.db.get_value(
|
question_details = frappe.db.get_value(
|
||||||
"LMS Quiz Question",
|
"LMS Quiz Question",
|
||||||
{"parent": quiz, "question": result["question_name"]},
|
{"parent": quiz, "question": result["question_name"]},
|
||||||
["question", "marks", "question_detail"],
|
["question", "marks", "question_detail", "type"],
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
result["question_name"] = question_details.question
|
result["question_name"] = question_details.question
|
||||||
result["question"] = question_details.question_detail
|
result["question"] = question_details.question_detail
|
||||||
marks = question_details.marks if correct else 0
|
result["marks_out_of"] = question_details.marks
|
||||||
|
|
||||||
result["marks"] = marks
|
quiz_details = frappe.get_doc(
|
||||||
score += marks
|
"LMS Quiz",
|
||||||
|
quiz,
|
||||||
|
["total_marks", "passing_percentage", "lesson", "course"],
|
||||||
|
as_dict=1,
|
||||||
|
)
|
||||||
|
|
||||||
del result["question_name"]
|
score = 0
|
||||||
|
percentage = 0
|
||||||
|
score_out_of = quiz_details.total_marks
|
||||||
|
|
||||||
quiz_details = frappe.db.get_value(
|
if question_details.type != "Open Ended":
|
||||||
"LMS Quiz", quiz, ["total_marks", "passing_percentage", "lesson", "course"], as_dict=1
|
correct = result["is_correct"][0]
|
||||||
)
|
for point in result["is_correct"]:
|
||||||
score_out_of = quiz_details.total_marks
|
correct = correct and point
|
||||||
percentage = (score / score_out_of) * 100
|
result["is_correct"] = correct
|
||||||
|
|
||||||
|
marks = question_details.marks if correct else 0
|
||||||
|
result["marks"] = marks
|
||||||
|
score += marks
|
||||||
|
|
||||||
|
del result["question_name"]
|
||||||
|
percentage = (score / score_out_of) * 100
|
||||||
|
else:
|
||||||
|
result["is_correct"] = 0
|
||||||
|
is_open_ended = True
|
||||||
|
|
||||||
|
result["answer"] = re.sub(
|
||||||
|
r'<img[^>]*src\s*=\s*["\'](?=data:)(.*?)["\']', _save_file, result["answer"]
|
||||||
|
)
|
||||||
|
|
||||||
submission = frappe.get_doc(
|
submission = frappe.get_doc(
|
||||||
{
|
{
|
||||||
@@ -139,128 +173,51 @@ def quiz_summary(quiz, results):
|
|||||||
"submission": submission.name,
|
"submission": submission.name,
|
||||||
"pass": percentage == quiz_details.passing_percentage,
|
"pass": percentage == quiz_details.passing_percentage,
|
||||||
"percentage": percentage,
|
"percentage": percentage,
|
||||||
|
"is_open_ended": is_open_ended,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
def _save_file(match):
|
||||||
def save_quiz(
|
data = match.group(1).split("data:")[1]
|
||||||
quiz_title,
|
headers, content = data.split(",")
|
||||||
passing_percentage,
|
mtype = headers.split(";", 1)[0]
|
||||||
questions,
|
|
||||||
max_attempts=0,
|
|
||||||
quiz=None,
|
|
||||||
show_answers=1,
|
|
||||||
show_submission_history=0,
|
|
||||||
):
|
|
||||||
if not has_course_moderator_role() or not has_course_instructor_role():
|
|
||||||
return
|
|
||||||
|
|
||||||
values = {
|
if isinstance(content, str):
|
||||||
"title": quiz_title,
|
content = content.encode("utf-8")
|
||||||
"passing_percentage": passing_percentage,
|
if b"," in content:
|
||||||
"max_attempts": max_attempts,
|
content = content.split(b",")[1]
|
||||||
"show_answers": show_answers,
|
|
||||||
"show_submission_history": show_submission_history,
|
try:
|
||||||
}
|
content = safe_b64decode(content)
|
||||||
|
except BinasciiError:
|
||||||
|
frappe.flags.has_dataurl = True
|
||||||
|
return f'<img src="#broken-image" alt="{get_corrupted_image_msg()}"'
|
||||||
|
|
||||||
|
if "filename=" in headers:
|
||||||
|
filename = headers.split("filename=")[-1]
|
||||||
|
filename = safe_decode(filename).split(";", 1)[0]
|
||||||
|
|
||||||
if quiz:
|
|
||||||
frappe.db.set_value("LMS Quiz", quiz, values)
|
|
||||||
update_questions(quiz, questions)
|
|
||||||
return quiz
|
|
||||||
else:
|
else:
|
||||||
doc = frappe.new_doc("LMS Quiz")
|
filename = get_random_filename(content_type=mtype)
|
||||||
doc.update(values)
|
|
||||||
doc.save()
|
|
||||||
update_questions(doc.name, questions)
|
|
||||||
return doc.name
|
|
||||||
|
|
||||||
|
_file = frappe.get_doc(
|
||||||
def update_questions(quiz, questions):
|
|
||||||
questions = json.loads(questions)
|
|
||||||
|
|
||||||
delete_questions(quiz, questions)
|
|
||||||
add_questions(quiz, questions)
|
|
||||||
frappe.db.set_value("LMS Quiz", quiz, "total_marks", set_total_marks(quiz, questions))
|
|
||||||
|
|
||||||
|
|
||||||
def delete_questions(quiz, questions):
|
|
||||||
existing_questions = frappe.get_all(
|
|
||||||
"LMS Quiz Question",
|
|
||||||
{
|
{
|
||||||
"parent": quiz,
|
"doctype": "File",
|
||||||
},
|
"file_name": filename,
|
||||||
pluck="name",
|
"content": content,
|
||||||
)
|
"decode": False,
|
||||||
|
"is_private": False,
|
||||||
current_questions = [question.get("question_name") for question in questions]
|
|
||||||
|
|
||||||
for question in existing_questions:
|
|
||||||
if question not in current_questions:
|
|
||||||
frappe.db.delete("LMS Quiz Question", question)
|
|
||||||
|
|
||||||
|
|
||||||
def add_questions(quiz, questions):
|
|
||||||
for index, question in enumerate(questions):
|
|
||||||
question = frappe._dict(question)
|
|
||||||
if question.question_name:
|
|
||||||
doc = frappe.get_doc("LMS Quiz Question", question.question_name)
|
|
||||||
else:
|
|
||||||
doc = frappe.new_doc("LMS Quiz Question")
|
|
||||||
doc.update(
|
|
||||||
{
|
|
||||||
"parent": quiz,
|
|
||||||
"parenttype": "LMS Quiz",
|
|
||||||
"parentfield": "questions",
|
|
||||||
"idx": index + 1,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
doc.update({"question": question.question, "marks": question.marks})
|
|
||||||
|
|
||||||
doc.save()
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def save_question(quiz, values, index):
|
|
||||||
values = frappe._dict(json.loads(values))
|
|
||||||
|
|
||||||
if values.get("name"):
|
|
||||||
doc = frappe.get_doc("LMS Question", values.get("name"))
|
|
||||||
else:
|
|
||||||
doc = frappe.new_doc("LMS Question")
|
|
||||||
|
|
||||||
doc.update(
|
|
||||||
{
|
|
||||||
"question": values.question,
|
|
||||||
"type": values["type"],
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
_file.save(ignore_permissions=True)
|
||||||
|
file_url = _file.unique_url
|
||||||
|
frappe.flags.has_dataurl = True
|
||||||
|
|
||||||
for num in range(1, 5):
|
return f'<img src="{file_url}"'
|
||||||
if values.get(f"option_{num}"):
|
|
||||||
doc.update(
|
|
||||||
{
|
|
||||||
f"option_{num}": values[f"option_{num}"],
|
|
||||||
f"is_correct_{num}": values[f"is_correct_{num}"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if values.get(f"explanation_{num}"):
|
|
||||||
doc.update(
|
|
||||||
{
|
|
||||||
f"explanation_{num}": values[f"explanation_{num}"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if values.get(f"possibility_{num}"):
|
def get_corrupted_image_msg():
|
||||||
doc.update(
|
return _("Image: Corrupted Data Stream")
|
||||||
{
|
|
||||||
f"possibility_{num}": values[f"possibility_{num}"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
doc.save()
|
|
||||||
return doc.name
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@@ -318,9 +275,3 @@ def check_input_answers(question, answer):
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_user_quizzes():
|
|
||||||
filters = {} if has_course_moderator_role() else {"owner": frappe.session.user}
|
|
||||||
return frappe.get_all("LMS Quiz", filters=filters, fields=["name", "title"])
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
"column_break_qcpo",
|
"column_break_qcpo",
|
||||||
"marks",
|
"marks",
|
||||||
"section_break_huup",
|
"section_break_huup",
|
||||||
"question_detail"
|
"question_detail",
|
||||||
|
"type"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -44,12 +45,21 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "section_break_huup",
|
"fieldname": "section_break_huup",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "question.type",
|
||||||
|
"fieldname": "type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Type",
|
||||||
|
"options": "Choices\nUser Input\nOpen Ended",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-07-29 15:10:09.662715",
|
"modified": "2024-10-07 15:01:38.800906",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Quiz Question",
|
"name": "LMS Quiz Question",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"answer",
|
"answer",
|
||||||
"column_break_flus",
|
"column_break_flus",
|
||||||
"marks",
|
"marks",
|
||||||
|
"marks_out_of",
|
||||||
"is_correct"
|
"is_correct"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@@ -33,8 +34,7 @@
|
|||||||
"fieldname": "is_correct",
|
"fieldname": "is_correct",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Is Correct",
|
"label": "Is Correct"
|
||||||
"read_only": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_fztv",
|
"fieldname": "section_break_fztv",
|
||||||
@@ -54,14 +54,20 @@
|
|||||||
"fieldname": "marks",
|
"fieldname": "marks",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Marks",
|
"label": "Marks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "marks_out_of",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Marks out of",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-05-17 17:38:51.760653",
|
"modified": "2024-10-07 17:28:38.597472",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Quiz Result",
|
"name": "LMS Quiz Result",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"quiz",
|
"quiz",
|
||||||
|
"quiz_title",
|
||||||
"course",
|
"course",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"member",
|
"member",
|
||||||
@@ -39,7 +40,6 @@
|
|||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Score",
|
"label": "Score",
|
||||||
"read_only": 1,
|
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -95,7 +95,6 @@
|
|||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Percentage",
|
"label": "Percentage",
|
||||||
"non_negative": 1,
|
"non_negative": 1,
|
||||||
"read_only": 1,
|
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -105,12 +104,19 @@
|
|||||||
"non_negative": 1,
|
"non_negative": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "quiz.title",
|
||||||
|
"fieldname": "quiz_title",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Quiz Title",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-02-27 13:01:53.611726",
|
"modified": "2024-10-07 16:52:04.162521",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Quiz Submission",
|
"name": "LMS Quiz Submission",
|
||||||
|
|||||||
@@ -1,14 +1,27 @@
|
|||||||
# Copyright (c) 2021, FOSS United and contributors
|
# Copyright (c) 2021, FOSS United and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
# import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe.utils import cint
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
|
||||||
class LMSQuizSubmission(Document):
|
class LMSQuizSubmission(Document):
|
||||||
def before_insert(self):
|
def validate(self):
|
||||||
if not self.percentage:
|
self.validate_marks()
|
||||||
self.set_percentage()
|
self.set_percentage()
|
||||||
|
|
||||||
|
def validate_marks(self):
|
||||||
|
for row in self.result:
|
||||||
|
if cint(row.marks) > cint(row.marks_out_of):
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Marks for question number {0} cannot be greater than the marks allotted for that question."
|
||||||
|
).format(row.idx)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.score += cint(row.marks)
|
||||||
|
|
||||||
def set_percentage(self):
|
def set_percentage(self):
|
||||||
if self.score and self.score_out_of:
|
if self.score and self.score_out_of:
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Frappe LMS VERSION\n"
|
"Project-Id-Version: Frappe LMS VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
|
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
|
||||||
"POT-Creation-Date: 2024-09-27 16:04+0000\n"
|
"POT-Creation-Date: 2024-10-04 16:04+0000\n"
|
||||||
"PO-Revision-Date: 2024-09-27 16:04+0000\n"
|
"PO-Revision-Date: 2024-10-04 16:04+0000\n"
|
||||||
"Last-Translator: jannat@frappe.io\n"
|
"Last-Translator: jannat@frappe.io\n"
|
||||||
"Language-Team: jannat@frappe.io\n"
|
"Language-Team: jannat@frappe.io\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -92,6 +92,7 @@ msgstr ""
|
|||||||
#: frontend/src/components/BatchCourses.vue:11
|
#: frontend/src/components/BatchCourses.vue:11
|
||||||
#: frontend/src/components/BatchStudents.vue:6
|
#: frontend/src/components/BatchStudents.vue:6
|
||||||
#: frontend/src/components/Categories.vue:26
|
#: frontend/src/components/Categories.vue:26
|
||||||
|
#: frontend/src/components/LiveClass.vue:11
|
||||||
#: frontend/src/components/Members.vue:43
|
#: frontend/src/components/Members.vue:43
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -107,10 +108,6 @@ msgstr ""
|
|||||||
msgid "Add Lesson"
|
msgid "Add Lesson"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/LiveClass.vue:12
|
|
||||||
msgid "Add Live Class"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: frontend/src/pages/ProfileEvaluator.vue:75
|
#: frontend/src/pages/ProfileEvaluator.vue:75
|
||||||
msgid "Add Slot"
|
msgid "Add Slot"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -161,12 +158,12 @@ msgid "Add your assignment as {0}"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the address (Link) field in DocType 'LMS Payment'
|
#. Label of the address (Link) field in DocType 'LMS Payment'
|
||||||
#: frontend/src/pages/Billing.vue:62
|
#: frontend/src/pages/Billing.vue:17 frontend/src/pages/Billing.vue:69
|
||||||
#: lms/lms/doctype/lms_payment/lms_payment.json
|
#: lms/lms/doctype/lms_payment/lms_payment.json
|
||||||
msgid "Address"
|
msgid "Address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:77
|
#: frontend/src/pages/Billing.vue:79
|
||||||
msgid "Address Line 1"
|
msgid "Address Line 1"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -328,7 +325,7 @@ msgstr ""
|
|||||||
msgid "Assessment added successfully"
|
msgid "Assessment added successfully"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:66
|
#: lms/lms/doctype/lms_batch/lms_batch.py:74
|
||||||
msgid "Assessment {0} has already been added to this batch."
|
msgid "Assessment {0} has already been added to this batch."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -346,7 +343,6 @@ msgstr ""
|
|||||||
#. Label of the section_break_16 (Section Break) field in DocType 'Course
|
#. Label of the section_break_16 (Section Break) field in DocType 'Course
|
||||||
#. Lesson'
|
#. Lesson'
|
||||||
#. Label of the assignment (Link) field in DocType 'LMS Assignment Submission'
|
#. Label of the assignment (Link) field in DocType 'LMS Assignment Submission'
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:32
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.json
|
#: lms/lms/doctype/course_lesson/course_lesson.json
|
||||||
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
||||||
#: lms/templates/assignment.html:3
|
#: lms/templates/assignment.html:3
|
||||||
@@ -522,7 +518,7 @@ msgstr ""
|
|||||||
msgid "Batch Updated"
|
msgid "Batch Updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:37
|
#: lms/lms/doctype/lms_batch/lms_batch.py:39
|
||||||
msgid "Batch end date cannot be before the batch start date"
|
msgid "Batch end date cannot be before the batch start date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -555,7 +551,7 @@ msgid "Billing Details"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the billing_name (Data) field in DocType 'LMS Payment'
|
#. Label of the billing_name (Data) field in DocType 'LMS Payment'
|
||||||
#: frontend/src/pages/Billing.vue:71
|
#: frontend/src/pages/Billing.vue:75
|
||||||
#: lms/lms/doctype/lms_payment/lms_payment.json
|
#: lms/lms/doctype/lms_payment/lms_payment.json
|
||||||
msgid "Billing Name"
|
msgid "Billing Name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -752,7 +748,7 @@ msgid "Choose one answer"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the city (Data) field in DocType 'User'
|
#. Label of the city (Data) field in DocType 'User'
|
||||||
#: frontend/src/pages/Billing.vue:89 lms/fixtures/custom_field.json
|
#: frontend/src/pages/Billing.vue:86 lms/fixtures/custom_field.json
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -968,10 +964,6 @@ msgstr ""
|
|||||||
msgid "Content"
|
msgid "Content"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:17
|
|
||||||
msgid "Content Type"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: frontend/src/components/CourseCardOverlay.vue:29
|
#: frontend/src/components/CourseCardOverlay.vue:29
|
||||||
msgid "Continue Learning"
|
msgid "Continue Learning"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -985,18 +977,6 @@ msgstr ""
|
|||||||
msgid "Cookie Policy"
|
msgid "Cookie Policy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:17
|
|
||||||
msgid "Copy and paste the syntax in the editor. Replace 'embed_src' with the embed source that YouTube provides. To get the source, follow the steps mentioned below."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:29
|
|
||||||
msgid "Copy and paste the syntax in the editor. Replace 'exercise_id' with the ID of the Exercise you want to add. You can get the ID of the exercise from the {0}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:23
|
|
||||||
msgid "Copy and paste the syntax in the editor. Replace 'lms_quiz_id' with the ID of the Quiz you want to add. You can get the ID of the quiz from the {0}."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: frontend/src/components/LessonHelp.vue:53
|
#: frontend/src/components/LessonHelp.vue:53
|
||||||
msgid "Copy the URL of the video from YouTube and paste it in the editor."
|
msgid "Copy the URL of the video from YouTube and paste it in the editor."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1021,7 +1001,7 @@ msgstr ""
|
|||||||
|
|
||||||
#. Label of the country (Link) field in DocType 'User'
|
#. Label of the country (Link) field in DocType 'User'
|
||||||
#. Label of the country (Link) field in DocType 'Payment Country'
|
#. Label of the country (Link) field in DocType 'Payment Country'
|
||||||
#: frontend/src/pages/Billing.vue:103 lms/fixtures/custom_field.json
|
#: frontend/src/pages/Billing.vue:97 lms/fixtures/custom_field.json
|
||||||
#: lms/lms/doctype/payment_country/payment_country.json
|
#: lms/lms/doctype/payment_country/payment_country.json
|
||||||
msgid "Country"
|
msgid "Country"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1175,7 +1155,7 @@ msgstr ""
|
|||||||
msgid "Course Title"
|
msgid "Course Title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:324
|
#: lms/lms/doctype/lms_batch/lms_batch.py:318
|
||||||
msgid "Course already added to the batch."
|
msgid "Course already added to the batch."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1183,7 +1163,7 @@ msgstr ""
|
|||||||
msgid "Course price and currency are mandatory for paid courses"
|
msgid "Course price and currency are mandatory for paid courses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:55
|
#: lms/lms/doctype/lms_batch/lms_batch.py:57
|
||||||
msgid "Course {0} has already been added to this batch."
|
msgid "Course {0} has already been added to this batch."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1354,7 +1334,6 @@ msgstr ""
|
|||||||
#: lms/lms/doctype/cohort/cohort.json
|
#: lms/lms/doctype/cohort/cohort.json
|
||||||
#: lms/lms/doctype/cohort_subgroup/cohort_subgroup.json
|
#: lms/lms/doctype/cohort_subgroup/cohort_subgroup.json
|
||||||
#: lms/lms/doctype/course_chapter/course_chapter.json
|
#: lms/lms/doctype/course_chapter/course_chapter.json
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:17
|
|
||||||
#: lms/lms/doctype/lms_badge/lms_badge.json
|
#: lms/lms/doctype/lms_badge/lms_badge.json
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.json
|
#: lms/lms/doctype/lms_batch/lms_batch.json
|
||||||
#: lms/lms/doctype/lms_batch_old/lms_batch_old.json
|
#: lms/lms/doctype/lms_batch_old/lms_batch_old.json
|
||||||
@@ -1404,7 +1383,6 @@ msgstr ""
|
|||||||
#. Option for the 'File Type' (Select) field in DocType 'Course Lesson'
|
#. Option for the 'File Type' (Select) field in DocType 'Course Lesson'
|
||||||
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment'
|
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment'
|
||||||
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment Submission'
|
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment Submission'
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:32
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.json
|
#: lms/lms/doctype/course_lesson/course_lesson.json
|
||||||
#: lms/lms/doctype/lms_assignment/lms_assignment.json
|
#: lms/lms/doctype/lms_assignment/lms_assignment.json
|
||||||
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
||||||
@@ -1573,7 +1551,7 @@ msgstr ""
|
|||||||
msgid "Enrolled successfully"
|
msgid "Enrolled successfully"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:89
|
#: lms/lms/doctype/lms_batch/lms_batch.py:97
|
||||||
msgid "Enrollment Confirmation for the Next Training Batch"
|
msgid "Enrollment Confirmation for the Next Training Batch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1582,6 +1560,10 @@ msgstr ""
|
|||||||
msgid "Enrollment Count"
|
msgid "Enrollment Count"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lms/lms/utils.py:1682
|
||||||
|
msgid "Enrollment Failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Label of a chart in the LMS Workspace
|
#. Label of a chart in the LMS Workspace
|
||||||
#. Label of a shortcut in the LMS Workspace
|
#. Label of a shortcut in the LMS Workspace
|
||||||
#: frontend/src/pages/Statistics.vue:45 lms/lms/workspace/lms/lms.json
|
#: frontend/src/pages/Statistics.vue:45 lms/lms/workspace/lms/lms.json
|
||||||
@@ -1600,10 +1582,6 @@ msgstr ""
|
|||||||
msgid "Enter a title and save the quiz to proceed"
|
msgid "Enter a title and save the quiz to proceed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:11
|
|
||||||
msgid "Enter the billing information to complete the payment."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lms/templates/quiz/quiz.html:53
|
#: lms/templates/quiz/quiz.html:53
|
||||||
msgid "Enter the correct answer"
|
msgid "Enter the correct answer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1611,14 +1589,11 @@ msgstr ""
|
|||||||
#: frontend/src/components/Modals/Question.vue:242
|
#: frontend/src/components/Modals/Question.vue:242
|
||||||
#: frontend/src/components/Modals/Question.vue:262
|
#: frontend/src/components/Modals/Question.vue:262
|
||||||
#: frontend/src/components/Modals/Question.vue:319
|
#: frontend/src/components/Modals/Question.vue:319
|
||||||
#: frontend/src/pages/QuizForm.vue:314 frontend/src/pages/QuizForm.vue:329
|
#: frontend/src/pages/Billing.vue:255 frontend/src/pages/QuizForm.vue:314
|
||||||
|
#: frontend/src/pages/QuizForm.vue:329
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/utils.py:1070
|
|
||||||
msgid "Error during payment: {0} Please contact the Administrator. Amount {1} Currency {2} Formatted {3}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of a Link in the LMS Workspace
|
#. Label of a Link in the LMS Workspace
|
||||||
#. Label of a shortcut in the LMS Workspace
|
#. Label of a shortcut in the LMS Workspace
|
||||||
#: frontend/src/components/Modals/Event.vue:364 lms/lms/workspace/lms/lms.json
|
#: frontend/src/components/Modals/Event.vue:364 lms/lms/workspace/lms/lms.json
|
||||||
@@ -1643,7 +1618,7 @@ msgstr ""
|
|||||||
msgid "Evaluation Request"
|
msgid "Evaluation Request"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:73
|
#: lms/lms/doctype/lms_batch/lms_batch.py:81
|
||||||
msgid "Evaluation end date cannot be less than the batch end date."
|
msgid "Evaluation end date cannot be less than the batch end date."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1706,10 +1681,6 @@ msgstr ""
|
|||||||
msgid "Exercise Latest Submission"
|
msgid "Exercise Latest Submission"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:10
|
|
||||||
msgid "Exercise List"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Name of a DocType
|
#. Name of a DocType
|
||||||
#: lms/lms/doctype/exercise_submission/exercise_submission.json
|
#: lms/lms/doctype/exercise_submission/exercise_submission.json
|
||||||
msgid "Exercise Submission"
|
msgid "Exercise Submission"
|
||||||
@@ -1787,10 +1758,6 @@ msgstr ""
|
|||||||
msgid "Field of Major/Study"
|
msgid "Field of Major/Study"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:13
|
|
||||||
msgid "File DocType"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of the file_type (Select) field in DocType 'Course Lesson'
|
#. Label of the file_type (Select) field in DocType 'Course Lesson'
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.json
|
#: lms/lms/doctype/course_lesson/course_lesson.json
|
||||||
msgid "File Type"
|
msgid "File Type"
|
||||||
@@ -1876,11 +1843,11 @@ msgstr ""
|
|||||||
msgid "Function"
|
msgid "Function"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:42
|
#: frontend/src/pages/Billing.vue:48
|
||||||
msgid "GST Amount"
|
msgid "GST Amount"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:135
|
#: frontend/src/pages/Billing.vue:115
|
||||||
msgid "GST Number"
|
msgid "GST Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2058,7 +2025,6 @@ msgstr ""
|
|||||||
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment Submission'
|
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment Submission'
|
||||||
#. Label of the image (Attach Image) field in DocType 'LMS Badge'
|
#. Label of the image (Attach Image) field in DocType 'LMS Badge'
|
||||||
#. Label of the image (Code) field in DocType 'LMS Exercise'
|
#. Label of the image (Code) field in DocType 'LMS Exercise'
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:32
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.json
|
#: lms/lms/doctype/course_lesson/course_lesson.json
|
||||||
#: lms/lms/doctype/exercise_latest_submission/exercise_latest_submission.json
|
#: lms/lms/doctype/exercise_latest_submission/exercise_latest_submission.json
|
||||||
#: lms/lms/doctype/exercise_submission/exercise_submission.json
|
#: lms/lms/doctype/exercise_submission/exercise_submission.json
|
||||||
@@ -2192,10 +2158,6 @@ msgstr ""
|
|||||||
msgid "Invalid Start or End Time."
|
msgid "Invalid Start or End Time."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/utils.py:914
|
|
||||||
msgid "Invalid document provided."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of the invite_code (Data) field in DocType 'Cohort Subgroup'
|
#. Label of the invite_code (Data) field in DocType 'Cohort Subgroup'
|
||||||
#. Label of the invite_code (Data) field in DocType 'Invite Request'
|
#. Label of the invite_code (Data) field in DocType 'Invite Request'
|
||||||
#: lms/lms/doctype/cohort_subgroup/cohort_subgroup.json
|
#: lms/lms/doctype/cohort_subgroup/cohort_subgroup.json
|
||||||
@@ -2309,7 +2271,7 @@ msgstr ""
|
|||||||
msgid "Jobs"
|
msgid "Jobs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/LiveClass.vue:56
|
#: frontend/src/components/LiveClass.vue:53
|
||||||
#: lms/templates/upcoming_evals.html:15
|
#: lms/templates/upcoming_evals.html:15
|
||||||
msgid "Join"
|
msgid "Join"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -2631,7 +2593,7 @@ msgid "Live"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the show_live_class (Check) field in DocType 'LMS Settings'
|
#. Label of the show_live_class (Check) field in DocType 'LMS Settings'
|
||||||
#: frontend/src/components/LiveClass.vue:16
|
#: frontend/src/components/LiveClass.vue:4
|
||||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||||
msgid "Live Class"
|
msgid "Live Class"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -2679,12 +2641,6 @@ msgstr ""
|
|||||||
msgid "Login to apply"
|
msgid "Login to apply"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the exception_country (Table MultiSelect) field in DocType 'LMS
|
|
||||||
#. Settings'
|
|
||||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
|
||||||
msgid "Maintain Original Currency"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of the default_home (Check) field in DocType 'LMS Settings'
|
#. Label of the default_home (Check) field in DocType 'LMS Settings'
|
||||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||||
msgid "Make LMS the default home"
|
msgid "Make LMS the default home"
|
||||||
@@ -3057,7 +3013,7 @@ msgstr ""
|
|||||||
msgid "No jobs posted"
|
msgid "No jobs posted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/LiveClass.vue:62
|
#: frontend/src/components/LiveClass.vue:59
|
||||||
msgid "No live classes scheduled"
|
msgid "No live classes scheduled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3114,6 +3070,7 @@ msgid "Not Permitted"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/BrandSettings.vue:10
|
#: frontend/src/components/BrandSettings.vue:10
|
||||||
|
#: frontend/src/components/PaymentSettings.vue:9
|
||||||
#: frontend/src/components/SettingDetails.vue:10
|
#: frontend/src/components/SettingDetails.vue:10
|
||||||
msgid "Not Saved"
|
msgid "Not Saved"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -3146,10 +3103,6 @@ msgstr ""
|
|||||||
msgid "Offline"
|
msgid "Offline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:21
|
|
||||||
msgid "On clicking it, it provides an iframe. Copy the source (src) of the iframe and paste it here."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lms/templates/emails/certification.html:16
|
#: lms/templates/emails/certification.html:16
|
||||||
msgid "Once again, congratulations on this significant accomplishment."
|
msgid "Once again, congratulations on this significant accomplishment."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -3221,11 +3174,19 @@ msgstr ""
|
|||||||
msgid "Order ID"
|
msgid "Order ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/pages/Billing.vue:26
|
||||||
|
msgid "Ordered Item"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the organization (Data) field in DocType 'Certification'
|
#. Label of the organization (Data) field in DocType 'Certification'
|
||||||
#: lms/lms/doctype/certification/certification.json
|
#: lms/lms/doctype/certification/certification.json
|
||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/pages/Billing.vue:37
|
||||||
|
msgid "Original Amount"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Option for the 'User Category' (Select) field in DocType 'User'
|
#. Option for the 'User Category' (Select) field in DocType 'User'
|
||||||
#: lms/fixtures/custom_field.json lms/templates/signup-form.html:28
|
#: lms/fixtures/custom_field.json lms/templates/signup-form.html:28
|
||||||
msgid "Others"
|
msgid "Others"
|
||||||
@@ -3243,7 +3204,6 @@ msgstr ""
|
|||||||
#. Option for the 'File Type' (Select) field in DocType 'Course Lesson'
|
#. Option for the 'File Type' (Select) field in DocType 'Course Lesson'
|
||||||
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment'
|
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment'
|
||||||
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment Submission'
|
#. Option for the 'Type' (Select) field in DocType 'LMS Assignment Submission'
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:32
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.json
|
#: lms/lms/doctype/course_lesson/course_lesson.json
|
||||||
#: lms/lms/doctype/lms_assignment/lms_assignment.json
|
#: lms/lms/doctype/lms_assignment/lms_assignment.json
|
||||||
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
||||||
@@ -3268,7 +3228,7 @@ msgstr ""
|
|||||||
msgid "Paid Course"
|
msgid "Paid Course"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:141
|
#: frontend/src/pages/Billing.vue:120
|
||||||
msgid "Pan Number"
|
msgid "Pan Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3325,7 +3285,9 @@ msgid "Payment Details"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the payment_gateway (Link) field in DocType 'Web Form'
|
#. Label of the payment_gateway (Link) field in DocType 'Web Form'
|
||||||
|
#. Label of the payment_gateway (Data) field in DocType 'LMS Settings'
|
||||||
#: lms/fixtures/custom_field.json
|
#: lms/fixtures/custom_field.json
|
||||||
|
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||||
msgid "Payment Gateway"
|
msgid "Payment Gateway"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3357,15 +3319,17 @@ msgstr ""
|
|||||||
msgid "Payment for Document Type"
|
msgid "Payment for Document Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/utils.py:931
|
|
||||||
msgid "Payment for {0} course"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of the payments_tab (Tab Break) field in DocType 'Web Form'
|
#. Label of the payments_tab (Tab Break) field in DocType 'Web Form'
|
||||||
#: lms/fixtures/custom_field.json
|
#: lms/fixtures/custom_field.json
|
||||||
msgid "Payments"
|
msgid "Payments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the payments_app_is_not_installed (HTML) field in DocType 'LMS
|
||||||
|
#. Settings'
|
||||||
|
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||||
|
msgid "Payments app is not installed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Option for the 'Status' (Select) field in DocType 'Cohort Join Request'
|
#. Option for the 'Status' (Select) field in DocType 'Cohort Join Request'
|
||||||
#. Option for the 'Status' (Select) field in DocType 'Invite Request'
|
#. Option for the 'Status' (Select) field in DocType 'Invite Request'
|
||||||
#. Option for the 'Status' (Select) field in DocType 'LMS Certificate
|
#. Option for the 'Status' (Select) field in DocType 'LMS Certificate
|
||||||
@@ -3389,7 +3353,7 @@ msgstr ""
|
|||||||
msgid "Percentage (e.g. 70%)"
|
msgid "Percentage (e.g. 70%)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:119
|
#: frontend/src/pages/Billing.vue:104
|
||||||
msgid "Phone Number"
|
msgid "Phone Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3409,7 +3373,7 @@ msgstr ""
|
|||||||
msgid "Please click on the following button to set your new password"
|
msgid "Please click on the following button to set your new password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:235
|
#: lms/lms/doctype/lms_batch/lms_batch.py:229
|
||||||
msgid "Please enable Zoom Settings to use this feature."
|
msgid "Please enable Zoom Settings to use this feature."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3426,6 +3390,18 @@ msgstr ""
|
|||||||
msgid "Please enter your answer"
|
msgid "Please enter your answer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lms/lms/doctype/lms_batch/lms_batch.py:64
|
||||||
|
msgid "Please install the Payments app to create a paid batches."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lms/lms/doctype/lms_course/lms_course.py:52
|
||||||
|
msgid "Please install the Payments app to create a paid courses."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: frontend/src/pages/Billing.vue:247
|
||||||
|
msgid "Please let us know where you heard about us from."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/QuizBlock.vue:5
|
#: frontend/src/components/QuizBlock.vue:5
|
||||||
msgid "Please login to access the quiz."
|
msgid "Please login to access the quiz."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -3485,7 +3461,7 @@ msgstr ""
|
|||||||
msgid "Post"
|
msgid "Post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:113
|
#: frontend/src/pages/Billing.vue:100
|
||||||
msgid "Postal Code"
|
msgid "Postal Code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3537,6 +3513,12 @@ msgstr ""
|
|||||||
msgid "Pricing"
|
msgid "Pricing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Label of the exception_country (Table MultiSelect) field in DocType 'LMS
|
||||||
|
#. Settings'
|
||||||
|
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||||
|
msgid "Primary Countries"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the subgroup (Link) field in DocType 'Cohort Mentor'
|
#. Label of the subgroup (Link) field in DocType 'Cohort Mentor'
|
||||||
#: lms/lms/doctype/cohort_mentor/cohort_mentor.json
|
#: lms/lms/doctype/cohort_mentor/cohort_mentor.json
|
||||||
msgid "Primary Subgroup"
|
msgid "Primary Subgroup"
|
||||||
@@ -3557,7 +3539,7 @@ msgstr ""
|
|||||||
msgid "Private Information includes your Grade and Work Environment Preferences"
|
msgid "Private Information includes your Grade and Work Environment Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:148
|
#: frontend/src/pages/Billing.vue:126
|
||||||
msgid "Proceed to Payment"
|
msgid "Proceed to Payment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3674,7 +3656,6 @@ msgstr ""
|
|||||||
#. Label of the quiz (Link) field in DocType 'LMS Quiz Submission'
|
#. Label of the quiz (Link) field in DocType 'LMS Quiz Submission'
|
||||||
#. Label of a Link in the LMS Workspace
|
#. Label of a Link in the LMS Workspace
|
||||||
#: frontend/src/utils/quiz.js:24
|
#: frontend/src/utils/quiz.js:24
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:23
|
|
||||||
#: lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.json
|
#: lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.json
|
||||||
#: lms/lms/workspace/lms/lms.json
|
#: lms/lms/workspace/lms/lms.json
|
||||||
msgid "Quiz"
|
msgid "Quiz"
|
||||||
@@ -3685,10 +3666,6 @@ msgstr ""
|
|||||||
msgid "Quiz ID"
|
msgid "Quiz ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:9
|
|
||||||
msgid "Quiz List"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of a Link in the LMS Workspace
|
#. Label of a Link in the LMS Workspace
|
||||||
#: frontend/src/pages/QuizSubmission.vue:46 lms/lms/workspace/lms/lms.json
|
#: frontend/src/pages/QuizSubmission.vue:46 lms/lms/workspace/lms/lms.json
|
||||||
msgid "Quiz Submission"
|
msgid "Quiz Submission"
|
||||||
@@ -3735,16 +3712,6 @@ msgstr ""
|
|||||||
msgid "Rating cannot be 0"
|
msgid "Rating cannot be 0"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the razorpay_key (Data) field in DocType 'LMS Settings'
|
|
||||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
|
||||||
msgid "Razorpay Key"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of the razorpay_secret (Password) field in DocType 'LMS Settings'
|
|
||||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
|
||||||
msgid "Razorpay Secret"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: frontend/src/pages/AssignmentSubmission.vue:30
|
#: frontend/src/pages/AssignmentSubmission.vue:30
|
||||||
msgid "Read the question carefully before attempting the assignment."
|
msgid "Read the question carefully before attempting the assignment."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -3850,10 +3817,6 @@ msgstr ""
|
|||||||
msgid "Review the course"
|
msgid "Review the course"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:18
|
|
||||||
msgid "Review the details of your purchase."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of the reviewed_by (Link) field in DocType 'LMS Mentor Request'
|
#. Label of the reviewed_by (Link) field in DocType 'LMS Mentor Request'
|
||||||
#: lms/lms/doctype/lms_mentor_request/lms_mentor_request.json
|
#: lms/lms/doctype/lms_mentor_request/lms_mentor_request.json
|
||||||
msgid "Reviewed By"
|
msgid "Reviewed By"
|
||||||
@@ -3880,19 +3843,19 @@ msgstr ""
|
|||||||
msgid "Route"
|
msgid "Route"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:164
|
#: lms/lms/doctype/lms_batch/lms_batch.py:172
|
||||||
msgid "Row #{0} Date cannot be outside the batch duration."
|
msgid "Row #{0} Date cannot be outside the batch duration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:159
|
#: lms/lms/doctype/lms_batch/lms_batch.py:167
|
||||||
msgid "Row #{0} End time cannot be outside the batch duration."
|
msgid "Row #{0} End time cannot be outside the batch duration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:141
|
#: lms/lms/doctype/lms_batch/lms_batch.py:149
|
||||||
msgid "Row #{0} Start time cannot be greater than or equal to end time."
|
msgid "Row #{0} Start time cannot be greater than or equal to end time."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:150
|
#: lms/lms/doctype/lms_batch/lms_batch.py:158
|
||||||
msgid "Row #{0} Start time cannot be outside the batch duration."
|
msgid "Row #{0} Start time cannot be outside the batch duration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4154,17 +4117,12 @@ msgstr ""
|
|||||||
#. Label of the source (Link) field in DocType 'Batch Student'
|
#. Label of the source (Link) field in DocType 'Batch Student'
|
||||||
#. Label of the source (Link) field in DocType 'LMS Payment'
|
#. Label of the source (Link) field in DocType 'LMS Payment'
|
||||||
#. Label of the source (Data) field in DocType 'LMS Source'
|
#. Label of the source (Data) field in DocType 'LMS Source'
|
||||||
#: frontend/src/pages/Billing.vue:125
|
|
||||||
#: lms/lms/doctype/batch_student/batch_student.json
|
#: lms/lms/doctype/batch_student/batch_student.json
|
||||||
#: lms/lms/doctype/lms_payment/lms_payment.json
|
#: lms/lms/doctype/lms_payment/lms_payment.json
|
||||||
#: lms/lms/doctype/lms_source/lms_source.json
|
#: lms/lms/doctype/lms_source/lms_source.json
|
||||||
msgid "Source"
|
msgid "Source"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:65
|
|
||||||
msgid "Specify your billing address correctly."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Option for the 'Role' (Select) field in DocType 'Cohort Staff'
|
#. Option for the 'Role' (Select) field in DocType 'Cohort Staff'
|
||||||
#. Option for the 'Member Type' (Select) field in DocType 'LMS Enrollment'
|
#. Option for the 'Member Type' (Select) field in DocType 'LMS Enrollment'
|
||||||
#: lms/lms/doctype/cohort_staff/cohort_staff.json
|
#: lms/lms/doctype/cohort_staff/cohort_staff.json
|
||||||
@@ -4177,7 +4135,7 @@ msgstr ""
|
|||||||
msgid "Stage"
|
msgid "Stage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/LiveClass.vue:48 frontend/src/components/Quiz.vue:47
|
#: frontend/src/components/LiveClass.vue:45 frontend/src/components/Quiz.vue:47
|
||||||
#: lms/templates/quiz/quiz.html:39
|
#: lms/templates/quiz/quiz.html:39
|
||||||
msgid "Start"
|
msgid "Start"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4241,7 +4199,7 @@ msgstr ""
|
|||||||
msgid "Startup Organization"
|
msgid "Startup Organization"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:95
|
#: frontend/src/pages/Billing.vue:88
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4310,7 +4268,7 @@ msgstr ""
|
|||||||
msgid "Student Reviews"
|
msgid "Student Reviews"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:44
|
#: lms/lms/doctype/lms_batch/lms_batch.py:46
|
||||||
msgid "Student {0} has already been added to this batch."
|
msgid "Student {0} has already been added to this batch."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4383,7 +4341,6 @@ msgstr ""
|
|||||||
#. Label of the summary (Small Text) field in DocType 'LMS Certificate
|
#. Label of the summary (Small Text) field in DocType 'LMS Certificate
|
||||||
#. Evaluation'
|
#. Evaluation'
|
||||||
#: frontend/src/components/Modals/Event.vue:97
|
#: frontend/src/components/Modals/Event.vue:97
|
||||||
#: frontend/src/pages/Billing.vue:15
|
|
||||||
#: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json
|
#: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json
|
||||||
msgid "Summary"
|
msgid "Summary"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4395,15 +4352,6 @@ msgstr ""
|
|||||||
msgid "Sunday"
|
msgid "Sunday"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:32
|
|
||||||
msgid "Supported File Types for Assignment"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:17
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:32
|
|
||||||
msgid "Syntax"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Name of a role
|
#. Name of a role
|
||||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||||
#: lms/job/doctype/job_settings/job_settings.json
|
#: lms/job/doctype/job_settings/job_settings.json
|
||||||
@@ -4537,7 +4485,7 @@ msgstr ""
|
|||||||
msgid "There are no chapters in this course. Create and manage chapters from here."
|
msgid "There are no chapters in this course. Create and manage chapters from here."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.py:132
|
#: lms/lms/doctype/lms_batch/lms_batch.py:140
|
||||||
msgid "There are no seats available in this batch."
|
msgid "There are no seats available in this batch."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4549,10 +4497,6 @@ msgstr ""
|
|||||||
msgid "There are no {0} on this site."
|
msgid "There are no {0} on this site."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/utils.py:1052
|
|
||||||
msgid "There is a problem with the payment gateway. Please contact the Administrator to proceed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Description of the 'section_break_ubxi' (Section Break) field in DocType
|
#. Description of the 'section_break_ubxi' (Section Break) field in DocType
|
||||||
#. 'LMS Batch'
|
#. 'LMS Batch'
|
||||||
#: lms/lms/doctype/lms_batch/lms_batch.json
|
#: lms/lms/doctype/lms_batch/lms_batch.json
|
||||||
@@ -4572,7 +4516,7 @@ msgstr ""
|
|||||||
msgid "This course has:"
|
msgid "This course has:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/utils.py:1010 lms/lms/utils.py:1752
|
#: lms/lms/utils.py:1562
|
||||||
msgid "This course is free."
|
msgid "This course is free."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4706,7 +4650,7 @@ msgstr ""
|
|||||||
msgid "To Date is mandatory in Work Experience."
|
msgid "To Date is mandatory in Work Experience."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/utils.py:1019 lms/lms/utils.py:1763
|
#: lms/lms/utils.py:1573
|
||||||
msgid "To join this batch, please contact the Administrator."
|
msgid "To join this batch, please contact the Administrator."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -4718,8 +4662,8 @@ msgstr ""
|
|||||||
msgid "Too many users signed up recently, so the registration is disabled. Please try back in an hour"
|
msgid "Too many users signed up recently, so the registration is disabled. Please try back in an hour"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/pages/Billing.vue:53
|
#: frontend/src/pages/Billing.vue:58
|
||||||
msgid "Total Amount"
|
msgid "Total"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Label of the total_marks (Int) field in DocType 'LMS Quiz'
|
#. Label of the total_marks (Int) field in DocType 'LMS Quiz'
|
||||||
@@ -4836,6 +4780,7 @@ msgid "Upcoming Evaluations"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: frontend/src/components/BrandSettings.vue:22
|
#: frontend/src/components/BrandSettings.vue:22
|
||||||
|
#: frontend/src/components/PaymentSettings.vue:27
|
||||||
#: frontend/src/components/SettingDetails.vue:23
|
#: frontend/src/components/SettingDetails.vue:23
|
||||||
msgid "Update"
|
msgid "Update"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4848,14 +4793,6 @@ msgstr ""
|
|||||||
msgid "Upload File"
|
msgid "Upload File"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:26
|
|
||||||
msgid "Upload a video from your local machine to the {0}. Copy and paste this syntax in the editor. Replace 'url_of_source' with the File URL field of the document you created in the File DocType."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:19
|
|
||||||
msgid "Upload the video on youtube."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: frontend/src/pages/AssignmentSubmission.vue:68
|
#: frontend/src/pages/AssignmentSubmission.vue:68
|
||||||
msgid "Uploading {0}%"
|
msgid "Uploading {0}%"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -4919,10 +4856,6 @@ msgstr ""
|
|||||||
msgid "Value Change"
|
msgid "Value Change"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:26
|
|
||||||
msgid "Video"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of the video_link (Data) field in DocType 'LMS Course'
|
#. Label of the video_link (Data) field in DocType 'LMS Course'
|
||||||
#: lms/lms/doctype/lms_course/lms_course.json
|
#: lms/lms/doctype/lms_course/lms_course.json
|
||||||
msgid "Video Embed Link"
|
msgid "Video Embed Link"
|
||||||
@@ -4980,8 +4913,8 @@ msgstr ""
|
|||||||
msgid "When a course gets submitted for review, it will be listed here."
|
msgid "When a course gets submitted for review, it will be listed here."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:19
|
#: frontend/src/pages/Billing.vue:111
|
||||||
msgid "When you share a youtube video, it shows an option called Embed."
|
msgid "Where did you hear about us?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/templates/emails/certification.html:10
|
#: lms/templates/emails/certification.html:10
|
||||||
@@ -5045,10 +4978,6 @@ msgstr ""
|
|||||||
msgid "You are not a mentor of the course {0}"
|
msgid "You are not a mentor of the course {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:15
|
|
||||||
msgid "You can add some more additional content to the lesson using a special syntax. The table below mentions all types of dynamic content that you can add to the lessons and the syntax for the same."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lms/templates/emails/lms_course_interest.html:13
|
#: lms/templates/emails/lms_course_interest.html:13
|
||||||
#: lms/templates/emails/lms_invite_request_approved.html:11
|
#: lms/templates/emails/lms_invite_request_approved.html:11
|
||||||
msgid "You can also copy-paste following link in your browser"
|
msgid "You can also copy-paste following link in your browser"
|
||||||
@@ -5124,10 +5053,6 @@ msgstr ""
|
|||||||
msgid "You've successfully submitted the assignment."
|
msgid "You've successfully submitted the assignment."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.js:17
|
|
||||||
msgid "YouTube Video"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#. Label of the youtube (Data) field in DocType 'Course Lesson'
|
#. Label of the youtube (Data) field in DocType 'Course Lesson'
|
||||||
#: lms/lms/doctype/course_lesson/course_lesson.json
|
#: lms/lms/doctype/course_lesson/course_lesson.json
|
||||||
msgid "YouTube Video URL"
|
msgid "YouTube Video URL"
|
||||||
@@ -5229,6 +5154,10 @@ msgstr ""
|
|||||||
msgid "you can"
|
msgid "you can"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lms/lms/api.py:725 lms/lms/api.py:733
|
||||||
|
msgid "{0} Settings not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: lms/templates/emails/job_application.html:2
|
#: lms/templates/emails/job_application.html:2
|
||||||
msgid "{0} has applied for the job position {1}"
|
msgid "{0} has applied for the job position {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
Reference in New Issue
Block a user