diff --git a/frontend/src/components/Controls/MultiSelect.vue b/frontend/src/components/Controls/MultiSelect.vue index 19f08e10..cd8b7b8a 100644 --- a/frontend/src/components/Controls/MultiSelect.vue +++ b/frontend/src/components/Controls/MultiSelect.vue @@ -40,10 +40,10 @@ diff --git a/frontend/src/pages/QuizForm.vue b/frontend/src/pages/QuizForm.vue index dc8d753f..66ac87b5 100644 --- a/frontend/src/pages/QuizForm.vue +++ b/frontend/src/pages/QuizForm.vue @@ -226,7 +226,6 @@ import { onMounted, inject, onBeforeUnmount, - watch, } from 'vue' import { sessionStore } from '../stores/session' import { ClipboardList, ListChecks, Plus, Trash2 } from 'lucide-vue-next' @@ -252,7 +251,9 @@ const props = defineProps({ }, }) -const questions = ref([]) +const questions = computed(() => { + return quizDetails.doc?.questions || [] +}) onMounted(() => { if (!user.data?.is_moderator && !user.data?.is_instructor) { @@ -273,24 +274,10 @@ onBeforeUnmount(() => { window.removeEventListener('keydown', keyboardShortcut) }) -watch( - () => props.quizID !== 'new', - (newVal) => { - if (newVal) { - quizDetails.reload() - } - } -) - const quizDetails = createDocumentResource({ doctype: 'LMS Quiz', name: props.quizID, auto: false, - onSuccess(doc) { - if (doc.questions && doc.questions.length > 0) { - questions.value = doc.questions.map((question) => question) - } - }, }) const validateTitle = () => { diff --git a/frontend/src/utils/markdownParser.js b/frontend/src/utils/markdownParser.js index a5b10ae7..493bcb47 100644 --- a/frontend/src/utils/markdownParser.js +++ b/frontend/src/utils/markdownParser.js @@ -34,7 +34,9 @@ export class Markdown { } static get pasteConfig() { - return { tags: ['P'] } + return { + tags: ['P'], + } } render() { @@ -52,11 +54,277 @@ export class Markdown { this._togglePlaceholder() ) this.wrapper.addEventListener('keydown', (e) => this._onKeyDown(e)) + this.wrapper.addEventListener( + 'paste', + (e) => this._onNativePaste(e), + true + ) } return this.wrapper } + _onNativePaste(event) { + const clipboardData = event.clipboardData || window.clipboardData + if (!clipboardData) return + + const pastedText = clipboardData.getData('text/plain') + + if (pastedText && this._looksLikeMarkdown(pastedText)) { + event.preventDefault() + event.stopPropagation() + event.stopImmediatePropagation() + + this._insertMarkdownAsBlocks(pastedText) + } + } + + _looksLikeMarkdown(text) { + const markdownPatterns = [ + /^#{1,6}\s+/m, + /^[\-\*]\s+/m, + /^\d+\.\s+/m, + /```[\s\S]*```/, + ] + + return markdownPatterns.some((pattern) => pattern.test(text)) + } + + async _insertMarkdownAsBlocks(markdown) { + const blocks = this._parseMarkdownToBlocks(markdown) + + if (blocks.length === 0) return + + const currentIndex = this.api.blocks.getCurrentBlockIndex() + + for (let i = 0; i < blocks.length; i++) { + try { + await this.api.blocks.insert( + blocks[i].type, + blocks[i].data, + {}, + currentIndex + i, + false + ) + } catch (error) { + console.error('Failed to insert block:', blocks[i], error) + } + } + + try { + await this.api.blocks.delete(currentIndex + blocks.length) + } catch (error) { + console.error('Failed to delete original block:', error) + } + + setTimeout(() => { + this.api.caret.setToBlock(currentIndex, 'end') + }, 100) + } + + _parseMarkdownToBlocks(markdown) { + const lines = markdown.split('\n') + const blocks = [] + let i = 0 + + while (i < lines.length) { + const line = lines[i] + + if (line.trim() === '') { + i++ + continue + } + + if (line.trim().startsWith('```')) { + const codeBlock = this._parseCodeBlock(lines, i) + blocks.push(codeBlock.block) + i = codeBlock.nextIndex + continue + } + + if (/^#{1,6}\s+/.test(line)) { + blocks.push(this._parseHeading(line)) + i++ + continue + } + + if (/^[\s]*[-*+]\s+/.test(line)) { + const listBlock = this._parseUnorderedList(lines, i) + blocks.push(listBlock.block) + i = listBlock.nextIndex + continue + } + + if (/^[\s]*(\d+)\.\s+/.test(line)) { + const listBlock = this._parseOrderedList(lines, i) + blocks.push(listBlock.block) + i = listBlock.nextIndex + continue + } + + blocks.push({ + type: 'paragraph', + data: { text: this._parseInlineMarkdown(line) }, + }) + i++ + } + + return blocks + } + + _parseHeading(line) { + const match = line.match(/^(#{1,6})\s+(.*)$/) + const level = match[1].length + const text = match[2] + + return { + type: 'header', + data: { + text: this._parseInlineMarkdown(text), + level: level, + }, + } + } + + _parseUnorderedList(lines, startIndex) { + const items = [] + let i = startIndex + + while (i < lines.length) { + const line = lines[i] + + if (/^[\s]*[-*+]\s+/.test(line)) { + const text = line.replace(/^[\s]*[-*+]\s+/, '') + items.push({ + content: this._parseInlineMarkdown(text), + items: [], + }) + i++ + } else if (line.trim() === '') { + i++ + if (i < lines.length && /^[\s]*[-*+]\s+/.test(lines[i])) { + continue + } else { + break + } + } else { + break + } + } + + return { + block: { + type: 'list', + data: { + style: 'unordered', + items: items, + }, + }, + nextIndex: i, + } + } + + _parseOrderedList(lines, startIndex) { + const items = [] + let i = startIndex + + while (i < lines.length) { + const line = lines[i] + + const match = line.match(/^[\s]*(\d+)\.\s+(.*)$/) + + if (match) { + const number = match[1] + const text = match[2] + + if (number === '1') { + if (items.length > 0) { + break + } + } + + items.push({ + content: this._parseInlineMarkdown(text), + items: [], + }) + i++ + } else if (line.trim() === '') { + i++ + if (i < lines.length && /^[\s]*(\d+)\.\s+/.test(lines[i])) { + continue + } else { + break + } + } else { + break + } + } + + return { + block: { + type: 'list', + data: { + style: 'ordered', + items: items, + }, + }, + nextIndex: i, + } + } + + _parseCodeBlock(lines, startIndex) { + let i = startIndex + 1 + const codeLines = [] + let language = lines[startIndex].trim().substring(3).trim() + + while (i < lines.length) { + if (lines[i].trim().startsWith('```')) { + i++ + break + } + codeLines.push(lines[i]) + i++ + } + + return { + block: { + type: 'codeBox', + data: { + code: codeLines.join('\n'), + language: language || 'plaintext', + }, + }, + nextIndex: i, + } + } + + _parseInlineMarkdown(text) { + if (!text) return '' + + let html = this._escapeHtml(text) + + html = html.replace(/`([^`]+)`/g, '$1') + + html = html.replace(/\*\*([^\*\n]+?)\*\*/g, '$1') + html = html.replace(/__([^_\n]+?)__/g, '$1') + + html = html.replace(/\*([^\*\n]+?)\*/g, '$1') + html = html.replace(/(?$1') + + html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1') + + return html + } + + _escapeHtml(text) { + return text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + } + _togglePlaceholder() { const blocks = document.querySelectorAll( '.cdx-block.ce-paragraph[data-placeholder]' diff --git a/lms/lms/utils.py b/lms/lms/utils.py index 88bc96d0..c12aad1d 100644 --- a/lms/lms/utils.py +++ b/lms/lms/utils.py @@ -8,7 +8,6 @@ from frappe import _ from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_result from frappe.desk.doctype.notification_log.notification_log import make_notification_logs from frappe.desk.notifications import extract_mentions -from frappe.pulse.utils import get_frappe_version from frappe.rate_limiter import rate_limit from frappe.utils import ( add_months, @@ -17,6 +16,7 @@ from frappe.utils import ( fmt_money, format_datetime, get_datetime, + get_frappe_version, get_fullname, get_time_str, getdate, @@ -1115,11 +1115,12 @@ def get_neighbour_lesson(course, chapter, lesson): @rate_limit(limit=500, seconds=60 * 60) def get_batch_details(batch): batch_students = frappe.get_all("LMS Batch Enrollment", {"batch": batch}, pluck="member") - if ( - not frappe.db.get_value("LMS Batch", batch, "published") - and not can_create_batches() - and frappe.session.user not in batch_students - ): + + has_create_batch_role = can_create_batches() + is_course_published = frappe.db.get_value("LMS Batch", batch, "published") + is_student_enrolled = frappe.session.user in batch_students + + if not (is_course_published or has_create_batch_role or is_student_enrolled): return batch_details = frappe.db.get_value( @@ -1164,7 +1165,10 @@ def get_batch_details(batch): batch_details.courses = frappe.get_all( "Batch Course", filters={"parent": batch}, fields=["course", "title", "evaluator"] ) - batch_details.students = batch_students + if can_create_batches(): + batch_details.students = batch_students + else: + batch_details.students = [] if batch_details.paid_batch and batch_details.start_date >= getdate(): batch_details.amount, batch_details.currency = check_multicurrency( @@ -1173,7 +1177,7 @@ def get_batch_details(batch): batch_details.price = fmt_money(batch_details.amount, 0, batch_details.currency) if batch_details.seat_count: - batch_details.seats_left = batch_details.seat_count - len(batch_details.students) + batch_details.seats_left = batch_details.seat_count - len(batch_students) return batch_details diff --git a/lms/locale/main.pot b/lms/locale/main.pot index 4597128a..2958a63c 100644 --- a/lms/locale/main.pot +++ b/lms/locale/main.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Frappe LMS VERSION\n" "Report-Msgid-Bugs-To: jannat@frappe.io\n" -"POT-Creation-Date: 2026-01-16 16:04+0000\n" -"PO-Revision-Date: 2026-01-16 16:04+0000\n" +"POT-Creation-Date: 2026-01-23 16:05+0000\n" +"PO-Revision-Date: 2026-01-23 16:05+0000\n" "Last-Translator: jannat@frappe.io\n" "Language-Team: jannat@frappe.io\n" "MIME-Version: 1.0\n" @@ -317,7 +317,7 @@ msgid "Administrator" msgstr "" #. Name of a role -#: frontend/src/pages/Batches.vue:319 lms/lms/doctype/lms_badge/lms_badge.json +#: frontend/src/pages/Batches.vue:321 lms/lms/doctype/lms_badge/lms_badge.json msgid "All" msgstr "" @@ -484,7 +484,7 @@ msgstr "" msgid "Apps" msgstr "" -#: frontend/src/pages/Batches.vue:329 +#: frontend/src/pages/Batches.vue:331 msgid "Archived" msgstr "" @@ -751,7 +751,7 @@ msgstr "" #. Label of the batch_name (Link) field in DocType 'LMS Certificate' #. Label of the batch_name (Link) field in DocType 'LMS Certificate Request' #. Label of the batch_name (Link) field in DocType 'LMS Live Class' -#: frontend/src/components/Modals/Event.vue:32 +#: frontend/src/components/Modals/Event.vue:35 #: frontend/src/components/Settings/BadgeForm.vue:195 #: frontend/src/components/Settings/Badges.vue:200 #: frontend/src/components/Settings/Transactions/TransactionDetails.vue:125 @@ -876,7 +876,7 @@ msgid "Batch:" msgstr "" #. Label of the batches (Check) field in DocType 'LMS Settings' -#: frontend/src/pages/Batches.vue:350 frontend/src/pages/Batches.vue:357 +#: frontend/src/pages/Batches.vue:352 frontend/src/pages/Batches.vue:359 #: lms/lms/doctype/lms_settings/lms_settings.json lms/www/lms.py:121 msgid "Batches" msgstr "" @@ -1021,7 +1021,7 @@ msgstr "" msgid "Certificate of Completion" msgstr "" -#: frontend/src/components/Modals/Event.vue:347 +#: frontend/src/components/Modals/Event.vue:353 msgid "Certificate saved successfully" msgstr "" @@ -1041,7 +1041,7 @@ msgstr "" #. Label of a chart in the LMS Workspace #. Label of a Card Break in the LMS Workspace #. Label of a Link in the LMS Workspace -#: frontend/src/components/Modals/Event.vue:411 +#: frontend/src/components/Modals/Event.vue:427 #: frontend/src/components/Sidebar/AppSidebar.vue:550 #: frontend/src/pages/BatchForm.vue:69 frontend/src/pages/Batches.vue:100 #: frontend/src/pages/CourseCertification.vue:10 @@ -1769,7 +1769,7 @@ msgstr "" #: frontend/src/components/Modals/BatchStudentProgress.vue:95 #: frontend/src/pages/BatchDetail.vue:44 #: frontend/src/pages/CourseCertification.vue:127 -#: frontend/src/pages/Courses.vue:365 frontend/src/pages/Courses.vue:372 +#: frontend/src/pages/Courses.vue:364 frontend/src/pages/Courses.vue:371 #: frontend/src/pages/Programs/ProgramForm.vue:49 #: frontend/src/pages/Programs/Programs.vue:35 #: lms/lms/doctype/lms_batch/lms_batch.json @@ -1876,7 +1876,7 @@ msgstr "" msgid "Create your first quiz" msgstr "" -#: frontend/src/pages/Assignments.vue:178 frontend/src/pages/Courses.vue:355 +#: frontend/src/pages/Assignments.vue:178 frontend/src/pages/Courses.vue:354 msgid "Created" msgstr "" @@ -1952,7 +1952,7 @@ msgstr "" #. Label of the date (Date) field in DocType 'LMS Certificate Request' #. Label of the date (Date) field in DocType 'LMS Live Class' #. Label of the date (Date) field in DocType 'Scheduled Flow' -#: frontend/src/components/Modals/Event.vue:40 +#: frontend/src/components/Modals/Event.vue:46 #: frontend/src/components/Modals/LiveClassModal.vue:29 #: lms/lms/doctype/lms_batch_timetable/lms_batch_timetable.json #: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json @@ -2239,7 +2239,7 @@ msgstr "" msgid "Edit Email Template" msgstr "" -#: frontend/src/components/Settings/PaymentGatewayDetails.vue:8 +#: frontend/src/components/Settings/PaymentGatewayDetails.vue:13 msgid "Edit Payment Gateway" msgstr "" @@ -2422,7 +2422,7 @@ msgstr "" msgid "Enroll Now" msgstr "" -#: frontend/src/pages/Batches.vue:332 frontend/src/pages/Courses.vue:358 +#: frontend/src/pages/Batches.vue:334 frontend/src/pages/Courses.vue:357 #: frontend/src/pages/Programs/StudentPrograms.vue:96 msgid "Enrolled" msgstr "" @@ -2524,7 +2524,7 @@ msgstr "" #. Label of a Link in the LMS Workspace #. Label of a shortcut in the LMS Workspace -#: frontend/src/components/Modals/Event.vue:404 lms/lms/workspace/lms/lms.json +#: frontend/src/components/Modals/Event.vue:420 lms/lms/workspace/lms/lms.json msgid "Evaluation" msgstr "" @@ -2549,7 +2549,7 @@ msgstr "" msgid "Evaluation end date cannot be less than the batch end date." msgstr "" -#: frontend/src/components/Modals/Event.vue:286 +#: frontend/src/components/Modals/Event.vue:292 msgid "Evaluation saved successfully" msgstr "" @@ -2662,7 +2662,7 @@ msgstr "" #. Label of the expiry_date (Date) field in DocType 'LMS Certificate' #: frontend/src/components/Modals/BulkCertificates.vue:33 -#: frontend/src/components/Modals/Event.vue:144 +#: frontend/src/components/Modals/Event.vue:150 #: lms/lms/doctype/lms_certificate/lms_certificate.json msgid "Expiry Date" msgstr "" @@ -2693,7 +2693,7 @@ msgstr "" #. Submission' #. Option for the 'Status' (Select) field in DocType 'LMS Certificate #. Evaluation' -#: frontend/src/components/Modals/Event.vue:396 +#: frontend/src/components/Modals/Event.vue:412 #: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json #: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json msgid "Fail" @@ -3207,7 +3207,7 @@ msgstr "" #. Option for the 'Status' (Select) field in DocType 'LMS Certificate #. Evaluation' #. Option for the 'Status' (Select) field in DocType 'LMS Course' -#: frontend/src/components/Modals/Event.vue:388 +#: frontend/src/components/Modals/Event.vue:404 #: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json #: lms/lms/doctype/lms_course/lms_course.json msgid "In Progress" @@ -3351,7 +3351,7 @@ msgstr "" #. Label of the issue_date (Date) field in DocType 'Certification' #. Label of the issue_date (Date) field in DocType 'LMS Certificate' #: frontend/src/components/Modals/BulkCertificates.vue:28 -#: frontend/src/components/Modals/Event.vue:138 +#: frontend/src/components/Modals/Event.vue:144 #: lms/lms/doctype/certification/certification.json #: lms/lms/doctype/lms_certificate/lms_certificate.json msgid "Issue Date" @@ -3454,7 +3454,7 @@ msgstr "" msgid "Join Call" msgstr "" -#: frontend/src/components/Modals/Event.vue:78 +#: frontend/src/components/Modals/Event.vue:84 msgid "Join Meeting" msgstr "" @@ -3894,7 +3894,7 @@ msgstr "" msgid "LinkedIn ID" msgstr "" -#: frontend/src/pages/Courses.vue:341 +#: frontend/src/pages/Courses.vue:340 msgid "Live" msgstr "" @@ -4427,7 +4427,7 @@ msgstr "" #: frontend/src/components/Settings/Members.vue:17 #: frontend/src/components/Settings/PaymentGateways.vue:16 #: frontend/src/components/Settings/ZoomSettings.vue:17 -#: frontend/src/pages/Courses.vue:344 +#: frontend/src/pages/Courses.vue:343 #: frontend/src/pages/Programs/Programs.vue:10 #: lms/lms/doctype/lms_badge/lms_badge.json msgid "New" @@ -4459,7 +4459,7 @@ msgstr "" msgid "New Job Applicant" msgstr "" -#: frontend/src/components/Settings/PaymentGatewayDetails.vue:7 +#: frontend/src/components/Settings/PaymentGatewayDetails.vue:12 msgid "New Payment Gateway" msgstr "" @@ -4776,12 +4776,7 @@ msgstr "" #: frontend/src/components/UserAvatar.vue:11 #: frontend/src/pages/CertifiedParticipants.vue:46 #: frontend/src/pages/Profile.vue:69 -msgid "Open to Opportunities" -msgstr "" - -#. Option for the 'Open to' (Select) field in DocType 'User' -#: lms/fixtures/custom_field.json -msgid "Opportunities" +msgid "Open to Work" msgstr "" #. Label of the option (Data) field in DocType 'LMS Option' @@ -4922,7 +4917,7 @@ msgstr "" #. Submission' #. Option for the 'Status' (Select) field in DocType 'LMS Certificate #. Evaluation' -#: frontend/src/components/Modals/Event.vue:392 +#: frontend/src/components/Modals/Event.vue:408 #: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json #: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json msgid "Pass" @@ -5052,7 +5047,7 @@ msgstr "" #. Option for the 'Status' (Select) field in DocType 'LMS Certificate #. Evaluation' #. Option for the 'Status' (Select) field in DocType 'LMS Mentor Request' -#: frontend/src/components/Modals/Event.vue:384 +#: frontend/src/components/Modals/Event.vue:400 #: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json #: lms/lms/doctype/lms_mentor_request/lms_mentor_request.json msgid "Pending" @@ -5192,7 +5187,7 @@ msgstr "" msgid "Please login to continue with payment." msgstr "" -#: lms/lms/utils.py:2081 +#: lms/lms/utils.py:2082 msgid "Please login to enroll in the program." msgstr "" @@ -5523,7 +5518,7 @@ msgstr "" #. Label of the published (Check) field in DocType 'LMS Course' #. Label of the published (Check) field in DocType 'LMS Program' #: frontend/src/components/Modals/BulkCertificates.vue:51 -#: frontend/src/components/Modals/Event.vue:122 +#: frontend/src/components/Modals/Event.vue:128 #: frontend/src/pages/BatchForm.vue:59 frontend/src/pages/CourseForm.vue:105 #: frontend/src/pages/Programs/ProgramForm.vue:33 #: frontend/src/pages/Programs/StudentPrograms.vue:100 @@ -5691,7 +5686,7 @@ msgstr "" #. Label of the rating (Data) field in DocType 'LMS Course' #. Label of the rating (Rating) field in DocType 'LMS Course Review' #: frontend/src/components/CourseCardOverlay.vue:147 -#: frontend/src/components/Modals/Event.vue:92 +#: frontend/src/components/Modals/Event.vue:98 #: frontend/src/components/Modals/ReviewModal.vue:18 #: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json #: lms/lms/doctype/lms_course/lms_course.json @@ -5927,14 +5922,14 @@ msgstr "" #: frontend/src/components/Modals/AssignmentForm.vue:65 #: frontend/src/components/Modals/EditProfile.vue:121 #: frontend/src/components/Modals/EmailTemplateModal.vue:12 -#: frontend/src/components/Modals/Event.vue:115 -#: frontend/src/components/Modals/Event.vue:151 +#: frontend/src/components/Modals/Event.vue:121 +#: frontend/src/components/Modals/Event.vue:157 #: frontend/src/components/Modals/Question.vue:112 #: frontend/src/components/Modals/ZoomAccountModal.vue:10 #: frontend/src/components/Settings/BadgeAssignmentForm.vue:12 #: frontend/src/components/Settings/BadgeForm.vue:78 #: frontend/src/components/Settings/Coupons/CouponDetails.vue:78 -#: frontend/src/components/Settings/PaymentGatewayDetails.vue:38 +#: frontend/src/components/Settings/PaymentGatewayDetails.vue:41 #: frontend/src/components/Settings/Transactions/TransactionDetails.vue:129 #: frontend/src/pages/BatchForm.vue:14 frontend/src/pages/CourseForm.vue:17 #: frontend/src/pages/JobForm.vue:8 frontend/src/pages/LessonForm.vue:14 @@ -6046,7 +6041,7 @@ msgstr "" msgid "Select Date" msgstr "" -#: frontend/src/components/Settings/PaymentGatewayDetails.vue:22 +#: frontend/src/components/Settings/PaymentGatewayDetails.vue:26 msgid "Select Payment Gateway" msgstr "" @@ -6362,7 +6357,7 @@ msgstr "" #. Label of the status (Select) field in DocType 'LMS Programming Exercise #. Submission' #. Label of the status (Select) field in DocType 'LMS Test Case Submission' -#: frontend/src/components/Modals/Event.vue:99 +#: frontend/src/components/Modals/Event.vue:105 #: frontend/src/components/Settings/Badges.vue:228 #: frontend/src/components/Settings/ZoomSettings.vue:197 #: frontend/src/pages/AssignmentSubmissionList.vue:19 @@ -6473,7 +6468,7 @@ msgstr "" #. Label of the summary (Small Text) field in DocType 'LMS Certificate #. Evaluation' -#: frontend/src/components/Modals/Event.vue:106 +#: frontend/src/components/Modals/Event.vue:112 #: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json msgid "Summary" msgstr "" @@ -6569,7 +6564,7 @@ msgstr "" #. Label of the template (Link) field in DocType 'LMS Certificate' #: frontend/src/components/Modals/BulkCertificates.vue:43 -#: frontend/src/components/Modals/Event.vue:127 +#: frontend/src/components/Modals/Event.vue:133 #: lms/lms/doctype/lms_certificate/lms_certificate.json msgid "Template" msgstr "" @@ -6618,7 +6613,7 @@ msgstr "" msgid "Thanks and Regards" msgstr "" -#: lms/lms/utils.py:2247 +#: lms/lms/utils.py:2248 msgid "The batch does not exist." msgstr "" @@ -6626,7 +6621,7 @@ msgstr "" msgid "The batch you have enrolled for is starting tomorrow. Please be prepared and be on time for the session." msgstr "" -#: lms/lms/utils.py:1747 +#: lms/lms/utils.py:1748 msgid "The coupon code '{0}' is invalid." msgstr "" @@ -6650,7 +6645,7 @@ msgstr "" msgid "The last day to schedule your evaluations is " msgstr "" -#: lms/lms/utils.py:2231 +#: lms/lms/utils.py:2232 msgid "The lesson does not exist." msgstr "" @@ -6658,7 +6653,7 @@ msgstr "" msgid "The slot is already booked by another participant." msgstr "" -#: lms/lms/utils.py:1361 lms/lms/utils.py:1477 lms/lms/utils.py:1944 +#: lms/lms/utils.py:1362 lms/lms/utils.py:1478 lms/lms/utils.py:1945 msgid "The specified batch does not exist." msgstr "" @@ -6724,15 +6719,15 @@ msgstr "" msgid "This class has ended" msgstr "" -#: lms/lms/utils.py:1776 +#: lms/lms/utils.py:1777 msgid "This coupon has expired." msgstr "" -#: lms/lms/utils.py:1779 +#: lms/lms/utils.py:1780 msgid "This coupon has reached its maximum usage limit." msgstr "" -#: lms/lms/utils.py:1788 +#: lms/lms/utils.py:1789 msgid "This coupon is not applicable to this {0}." msgstr "" @@ -6740,7 +6735,7 @@ msgstr "" msgid "This course has:" msgstr "" -#: lms/lms/utils.py:1707 +#: lms/lms/utils.py:1708 msgid "This course is free." msgstr "" @@ -6797,7 +6792,7 @@ msgid "Thursday" msgstr "" #. Label of the time (Time) field in DocType 'LMS Live Class' -#: frontend/src/components/Modals/Event.vue:48 +#: frontend/src/components/Modals/Event.vue:54 #: frontend/src/components/Modals/LiveClassModal.vue:52 #: frontend/src/components/Quiz.vue:58 #: lms/lms/doctype/lms_live_class/lms_live_class.json @@ -6932,7 +6927,7 @@ msgstr "" msgid "To Date" msgstr "" -#: lms/lms/utils.py:1721 +#: lms/lms/utils.py:1722 msgid "To join this batch, please contact the Administrator." msgstr "" @@ -7054,7 +7049,7 @@ msgstr "" msgid "Under Review" msgstr "" -#: frontend/src/pages/Batches.vue:330 frontend/src/pages/Courses.vue:356 +#: frontend/src/pages/Batches.vue:332 frontend/src/pages/Courses.vue:355 msgid "Unpublished" msgstr "" @@ -7075,8 +7070,8 @@ msgstr "" #. Option for the 'Status' (Select) field in DocType 'LMS Certificate Request' #. Label of the upcoming (Check) field in DocType 'LMS Course' -#: frontend/src/pages/Batches.vue:328 frontend/src/pages/CourseForm.vue:117 -#: frontend/src/pages/Courses.vue:347 +#: frontend/src/pages/Batches.vue:330 frontend/src/pages/CourseForm.vue:117 +#: frontend/src/pages/Courses.vue:346 #: lms/lms/doctype/lms_certificate_request/lms_certificate_request.json #: lms/lms/doctype/lms_course/lms_course.json msgid "Upcoming" @@ -7218,7 +7213,7 @@ msgid "View Applications" msgstr "" #: frontend/src/components/CertificationLinks.vue:10 -#: frontend/src/components/Modals/Event.vue:67 +#: frontend/src/components/Modals/Event.vue:73 msgid "View Certificate" msgstr "" @@ -7325,6 +7320,11 @@ msgstr "" msgid "Withdrawn" msgstr "" +#. Option for the 'Open to' (Select) field in DocType 'User' +#: lms/fixtures/custom_field.json +msgid "Work" +msgstr "" + #. Label of the work_environment (Section Break) field in DocType 'User' #: lms/fixtures/custom_field.json msgid "Work Environment" @@ -7425,7 +7425,7 @@ msgstr "" msgid "You cannot enroll in an unpublished course." msgstr "" -#: lms/lms/utils.py:2085 +#: lms/lms/utils.py:2086 msgid "You cannot enroll in an unpublished program." msgstr "" @@ -7441,11 +7441,11 @@ msgstr "" msgid "You cannot schedule evaluations for past slots." msgstr "" -#: lms/lms/utils.py:2259 +#: lms/lms/utils.py:2260 msgid "You do not have access to this batch." msgstr "" -#: lms/lms/utils.py:2242 +#: lms/lms/utils.py:2243 msgid "You do not have access to this course." msgstr ""