Compare commits

..

13 Commits

Author SHA1 Message Date
Frappe PR Bot
736d79b8c9 chore(release): Bumped to Version 2.8.0 2024-10-09 06:04:56 +00:00
Jannat Patel
98c0bd5f3e Merge pull request #1042 from frappe/pot_develop_2024-10-04
chore: update POT file
2024-10-09 11:34:01 +05:30
Jannat Patel
289a0f9122 Merge pull request #1046 from pateljannat/issues-38
fix: quiz columns
2024-10-08 16:27:04 +05:30
Jannat Patel
3cd08c80c8 fix: reduced with of marks column 2024-10-08 16:09:21 +05:30
Jannat Patel
3d82c36250 fix: quiz columns 2024-10-08 16:03:37 +05:30
Jannat Patel
9b9af0215a Merge pull request #1045 from pateljannat/issues-37
fix: using google docs viewer to render pdf
2024-10-08 12:37:19 +05:30
Jannat Patel
2e4cf02737 fix: using google docs viewer to render pdf 2024-10-08 12:00:51 +05:30
Jannat Patel
438e9e1c47 Merge pull request #1044 from pateljannat/open-ended-questions
feat: open ended questions
2024-10-08 10:37:44 +05:30
Jannat Patel
36ded70eef fix: only allow instructor and moderator on submission page 2024-10-08 10:21:45 +05:30
Jannat Patel
ba78a15a1f fix: ui test button label 2024-10-08 10:14:04 +05:30
Jannat Patel
93061194bb fix: error toast when saving marks 2024-10-08 10:13:07 +05:30
Jannat Patel
6d41e4e552 feat: open ended questions 2024-10-07 21:18:42 +05:30
frappe-pr-bot
3b06968d0a chore: update POT file 2024-10-04 16:04:32 +00:00
29 changed files with 660 additions and 379 deletions

View File

@@ -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");

View File

@@ -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()
} }
}) })

View File

@@ -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,
}, },

View File

@@ -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>

View File

@@ -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)
} }

View File

@@ -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}`]"

View File

@@ -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 [
{ {

View File

@@ -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 }}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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">

View File

@@ -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',
}, },
] ]
}) })

View 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>

View File

@@ -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>

View 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>

View File

@@ -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"

View File

@@ -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,
}, },

View File

@@ -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(

View File

@@ -1 +1 @@
__version__ = "2.7.0" __version__ = "2.8.0"

View File

@@ -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",

View File

@@ -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",

View File

@@ -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)

View File

@@ -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"])

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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:

View File

@@ -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 ""