mirror of
https://github.com/frappe/lms.git
synced 2026-05-02 13:39:31 +03:00
Merge pull request #1882 from frappe/develop
chore: merge 'develop' into 'main'
This commit is contained in:
+44
-41
@@ -10,52 +10,55 @@
|
||||
"copy-html-entry": "cp ../lms/public/frontend/index.html ../lms/www/lms.html"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/lang-html": "^6.4.9",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@editorjs/checklist": "^1.6.0",
|
||||
"@editorjs/code": "^2.9.0",
|
||||
"@editorjs/editorjs": "^2.29.0",
|
||||
"@codemirror/lang-html": "6.4.9",
|
||||
"@codemirror/lang-javascript": "6.2.4",
|
||||
"@codemirror/lang-json": "6.0.1",
|
||||
"@codemirror/lang-python": "6.2.1",
|
||||
"@editorjs/checklist": "1.6.0",
|
||||
"@editorjs/code": "2.9.0",
|
||||
"@editorjs/editorjs": "2.29.0",
|
||||
"@editorjs/embed": "2.7.0",
|
||||
"@editorjs/header": "^2.8.1",
|
||||
"@editorjs/inline-code": "^1.5.0",
|
||||
"@editorjs/nested-list": "^1.4.2",
|
||||
"@editorjs/paragraph": "^2.11.3",
|
||||
"@editorjs/simple-image": "^1.6.0",
|
||||
"@editorjs/table": "^2.4.2",
|
||||
"@vueuse/core": "^10.4.1",
|
||||
"@vueuse/router": "^12.7.0",
|
||||
"ace-builds": "^1.36.2",
|
||||
"apexcharts": "^4.3.0",
|
||||
"chart.js": "^4.4.1",
|
||||
"codemirror": "^6.0.1",
|
||||
"dayjs": "^1.11.6",
|
||||
"dompurify": "^3.2.6",
|
||||
"feather-icons": "^4.28.0",
|
||||
"frappe-ui": "^0.1.227",
|
||||
"highlight.js": "^11.11.1",
|
||||
"lucide-vue-next": "^0.383.0",
|
||||
"markdown-it": "^14.0.0",
|
||||
"pinia": "^2.0.33",
|
||||
"plyr": "^3.7.8",
|
||||
"socket.io-client": "^4.7.2",
|
||||
"@editorjs/header": "2.8.1",
|
||||
"@editorjs/inline-code": "1.5.0",
|
||||
"@editorjs/nested-list": "1.4.2",
|
||||
"@editorjs/paragraph": "2.11.3",
|
||||
"@editorjs/simple-image": "1.6.0",
|
||||
"@editorjs/table": "2.4.2",
|
||||
"@vueuse/core": "10.4.1",
|
||||
"@vueuse/router": "12.7.0",
|
||||
"ace-builds": "1.36.2",
|
||||
"apexcharts": "4.3.0",
|
||||
"chart.js": "4.4.1",
|
||||
"codemirror": "6.0.1",
|
||||
"dayjs": "1.11.10",
|
||||
"dompurify": "3.2.6",
|
||||
"feather-icons": "4.28.0",
|
||||
"frappe-ui": "0.1.227",
|
||||
"highlight.js": "11.11.1",
|
||||
"lucide-vue-next": "0.383.0",
|
||||
"markdown-it": "14.0.0",
|
||||
"pinia": "2.0.33",
|
||||
"plyr": "3.7.8",
|
||||
"socket.io-client": "4.7.2",
|
||||
"tailwindcss": "3.4.15",
|
||||
"thememirror": "^2.0.1",
|
||||
"typescript": "^5.7.2",
|
||||
"vue": "^3.4.23",
|
||||
"vue-chartjs": "^5.3.0",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
"vue-draggable-next": "^2.2.1",
|
||||
"vue-router": "^4.0.12",
|
||||
"vue3-apexcharts": "^1.8.0",
|
||||
"thememirror": "2.0.1",
|
||||
"typescript": "5.7.2",
|
||||
"vue": "^3.5.0",
|
||||
"vue-chartjs": "5.3.0",
|
||||
"vue-codemirror": "6.1.1",
|
||||
"vue-draggable-next": "2.2.1",
|
||||
"vue-router": "4.2.2",
|
||||
"vue3-apexcharts": "1.8.0",
|
||||
"vuedraggable": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.0.3",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"postcss": "^8.4.5",
|
||||
"vite": "^5.0.11",
|
||||
"@vitejs/plugin-vue": "5.0.3",
|
||||
"autoprefixer": "10.4.2",
|
||||
"postcss": "8.4.5",
|
||||
"vite": "5.0.11",
|
||||
"vite-plugin-pwa": "0.15.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@iconify/utils": "2.1.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +179,9 @@
|
||||
"
|
||||
:editable="true"
|
||||
:fixedMenu="true"
|
||||
:uploadArgs="{
|
||||
private: true,
|
||||
}"
|
||||
editorClass="prose-sm max-w-none border-b border-x bg-surface-gray-2 rounded-b-md py-1 px-2 min-h-[7rem]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
class="w-4 h-4 text-ink-gray-7 stroke-1.5"
|
||||
:is="icons.Folder"
|
||||
/>
|
||||
<span v-if="selectedIcon">
|
||||
<span v-if="selectedIcon" class="text-ink-gray-7">
|
||||
{{ selectedIcon }}
|
||||
</span>
|
||||
<span v-else class="text-ink-gray-5">
|
||||
|
||||
@@ -66,12 +66,18 @@
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Dialog, createResource, Select, FormControl, toast } from 'frappe-ui'
|
||||
import {
|
||||
dayjs,
|
||||
Dialog,
|
||||
createResource,
|
||||
Select,
|
||||
FormControl,
|
||||
toast,
|
||||
} from 'frappe-ui'
|
||||
import { reactive, watch, inject } from 'vue'
|
||||
import { formatTime } from '@/utils/'
|
||||
|
||||
const user = inject('$user')
|
||||
const dayjs = inject('$dayjs')
|
||||
const show = defineModel()
|
||||
const evaluations = defineModel('reloadEvals')
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<Dialog
|
||||
v-model="show"
|
||||
class="text-base"
|
||||
:options="{
|
||||
title: __('Add web page to sidebar'),
|
||||
size: 'lg',
|
||||
@@ -17,15 +16,17 @@
|
||||
}"
|
||||
>
|
||||
<template #body-content>
|
||||
<Link
|
||||
v-model="page.webpage"
|
||||
doctype="Web Page"
|
||||
:label="__('Web Page')"
|
||||
:filters="{
|
||||
published: 1,
|
||||
}"
|
||||
/>
|
||||
<IconPicker v-model="page.icon" :label="__('Icon')" class="mt-4" />
|
||||
<div class="text-base">
|
||||
<Link
|
||||
v-model="page.webpage"
|
||||
doctype="Web Page"
|
||||
:label="__('Web Page')"
|
||||
:filters="{
|
||||
published: 1,
|
||||
}"
|
||||
/>
|
||||
<IconPicker v-model="page.icon" :label="__('Icon')" class="mt-4" />
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
:placeholder="__('Make notes for quick revision. Press / for menu.')"
|
||||
@change="(val: string) => updateNoteText(val)"
|
||||
:editable="true"
|
||||
:uploadArgs="{
|
||||
private: true,
|
||||
}"
|
||||
editorClass="prose prose-sm min-h-[200px] max-w-none"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -189,7 +189,7 @@ import { usersStore } from '@/stores/user'
|
||||
import { sessionStore } from '@/stores/session'
|
||||
import { useSidebar } from '@/stores/sidebar'
|
||||
import { useSettings } from '@/stores/settings'
|
||||
import { Button, call, createResource, Tooltip } from 'frappe-ui'
|
||||
import { Button, call, createResource, Tooltip, toast } from 'frappe-ui'
|
||||
import PageModal from '@/components/Modals/PageModal.vue'
|
||||
import { capture } from '@/telemetry'
|
||||
import LMSLogo from '@/components/Icons/LMSLogo.vue'
|
||||
@@ -437,21 +437,13 @@ const openPageModal = (link) => {
|
||||
}
|
||||
|
||||
const deletePage = (link) => {
|
||||
createResource({
|
||||
url: 'lms.lms.api.delete_sidebar_item',
|
||||
makeParams(values) {
|
||||
return {
|
||||
webpage: link.web_page,
|
||||
}
|
||||
},
|
||||
}).submit(
|
||||
{},
|
||||
{
|
||||
onSuccess() {
|
||||
sidebarSettings.reload()
|
||||
},
|
||||
}
|
||||
)
|
||||
call('lms.lms.api.delete_documents', {
|
||||
doctype: 'LMS Sidebar Item',
|
||||
documents: [link.name],
|
||||
}).then(() => {
|
||||
sidebarSettings.reload()
|
||||
toast.success(__('Page deleted successfully'))
|
||||
})
|
||||
}
|
||||
|
||||
const toggleSidebar = () => {
|
||||
|
||||
@@ -675,7 +675,7 @@ export const getMetaInfo = (type, route, meta) => {
|
||||
|
||||
export const updateMetaInfo = (type, route, meta) => {
|
||||
call('lms.lms.api.update_meta_info', {
|
||||
type: type,
|
||||
meta_type: type,
|
||||
route: route,
|
||||
meta_tags: [
|
||||
{ key: 'description', value: meta.description },
|
||||
|
||||
+520
-308
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
||||
__version__ = "2.40.0"
|
||||
__version__ = "2.41.0"
|
||||
|
||||
+4
-1
@@ -101,7 +101,10 @@ doc_events = {
|
||||
"lms.lms.doctype.lms_badge.lms_badge.process_badges",
|
||||
]
|
||||
},
|
||||
"Discussion Reply": {"after_insert": "lms.lms.utils.handle_notifications"},
|
||||
"Discussion Reply": {
|
||||
"after_insert": "lms.lms.utils.handle_notifications",
|
||||
"validate": "lms.lms.utils.validate_discussion_reply",
|
||||
},
|
||||
"Notification Log": {"on_change": "lms.lms.utils.publish_notifications"},
|
||||
"User": {
|
||||
"validate": "lms.lms.user.validate_username_duplicates",
|
||||
|
||||
+60
-17
@@ -520,7 +520,7 @@ def get_sidebar_settings():
|
||||
web_pages = frappe.get_all(
|
||||
"LMS Sidebar Item",
|
||||
{"parenttype": "LMS Settings", "parentfield": "sidebar_items"},
|
||||
["web_page", "route", "title as label", "icon"],
|
||||
["web_page", "route", "title as label", "icon", "name"],
|
||||
)
|
||||
for page in web_pages:
|
||||
page.to = page.route
|
||||
@@ -1014,6 +1014,7 @@ def give_discussions_permission():
|
||||
"write": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"if_owner": 0 if role == "Moderator" else 1,
|
||||
}
|
||||
).save(ignore_permissions=True)
|
||||
|
||||
@@ -1303,7 +1304,24 @@ def get_notifications(filters):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_lms_setting(field):
|
||||
def get_lms_setting(field=None):
|
||||
if not field:
|
||||
frappe.throw(_("Field name is required"))
|
||||
frappe.log_error("Field name is missing when accessing LMS Settings {0} {1} {2}").format(
|
||||
frappe.local.request_ip, frappe.get_request_header("Referer"), frappe.get_request_header("Origin")
|
||||
)
|
||||
|
||||
allowed_fields = [
|
||||
"allow_guest_access",
|
||||
"prevent_skipping_videos",
|
||||
"contact_us_email",
|
||||
"contact_us_url",
|
||||
"livecode_url",
|
||||
]
|
||||
|
||||
if field not in allowed_fields:
|
||||
frappe.throw(_("You are not allowed to access this field"))
|
||||
|
||||
return frappe.get_cached_value("LMS Settings", None, field)
|
||||
|
||||
|
||||
@@ -1451,11 +1469,11 @@ def get_meta_info(type, route):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_meta_info(type, route, meta_tags):
|
||||
parent_name = f"{type}/{route}"
|
||||
if not isinstance(meta_tags, list):
|
||||
frappe.throw(_("Meta tags should be a list."))
|
||||
def update_meta_info(meta_type, route, meta_tags):
|
||||
validate_meta_data_permissions()
|
||||
validate_meta_tags(meta_tags)
|
||||
|
||||
parent_name = f"{meta_type}/{route}"
|
||||
for tag in meta_tags:
|
||||
existing_tag = frappe.db.exists(
|
||||
"Website Meta Tag",
|
||||
@@ -1482,18 +1500,43 @@ def update_meta_info(type, route, meta_tags):
|
||||
|
||||
parent_exists = frappe.db.exists("Website Route Meta", parent_name)
|
||||
if not parent_exists:
|
||||
route_meta = frappe.new_doc("Website Route Meta")
|
||||
route_meta.update(
|
||||
{
|
||||
"__newname": parent_name,
|
||||
}
|
||||
)
|
||||
route_meta.append("meta_tags", tag_properties)
|
||||
route_meta.insert()
|
||||
create_meta(parent_name, tag_properties)
|
||||
else:
|
||||
new_tag = frappe.new_doc("Website Meta Tag")
|
||||
new_tag.update(tag_properties)
|
||||
new_tag.insert()
|
||||
create_meta_tag(tag_properties)
|
||||
|
||||
|
||||
def validate_meta_tags(meta_tags):
|
||||
if not isinstance(meta_tags, list):
|
||||
frappe.throw(_("Meta tags should be a list."))
|
||||
|
||||
|
||||
def create_meta(parent_name, tag_properties):
|
||||
route_meta = frappe.new_doc("Website Route Meta")
|
||||
route_meta.update(
|
||||
{
|
||||
"__newname": parent_name,
|
||||
}
|
||||
)
|
||||
route_meta.append("meta_tags", tag_properties)
|
||||
route_meta.insert()
|
||||
|
||||
|
||||
def create_meta_tag(tag_properties):
|
||||
new_tag = frappe.new_doc("Website Meta Tag")
|
||||
new_tag.update(tag_properties)
|
||||
new_tag.insert()
|
||||
|
||||
|
||||
def validate_meta_data_permissions(meta_type):
|
||||
roles = frappe.get_roles()
|
||||
|
||||
if meta_type == "courses":
|
||||
if not ("Course Creator" in roles or "Moderator" in roles):
|
||||
frappe.throw(_("You do not have permission to update meta tags."))
|
||||
|
||||
elif meta_type == "batches":
|
||||
if not ("Batch Evaluator" in roles or "Moderator" in roles):
|
||||
frappe.throw(_("You do not have permission to update meta tags."))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
from lms.lms.utils import has_course_instructor_role, has_course_moderator_role
|
||||
from lms.lms.utils import has_course_instructor_role, has_moderator_role
|
||||
|
||||
|
||||
class LMSAssignment(Document):
|
||||
@@ -13,7 +13,7 @@ class LMSAssignment(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def save_assignment(assignment, title, type, question):
|
||||
if not has_course_moderator_role() or not has_course_instructor_role():
|
||||
if not has_moderator_role() or not has_course_instructor_role():
|
||||
return
|
||||
|
||||
if assignment:
|
||||
|
||||
@@ -30,9 +30,7 @@ frappe.ui.form.on("LMS Badge", {
|
||||
|
||||
const user_fields = fields
|
||||
.filter(
|
||||
(df) =>
|
||||
(df.fieldtype === "Link" && df.options === "User") ||
|
||||
df.fieldtype === "Data"
|
||||
(df) => df.fieldtype === "Link" && df.options === "User"
|
||||
)
|
||||
.map(map_for_options)
|
||||
.concat([
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-11-10 11:39:42.233779",
|
||||
"modified": "2025-12-04 17:06:26.090276",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Badge Assignment",
|
||||
@@ -116,25 +116,13 @@
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "LMS Student",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
"role": "LMS Student"
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "LMS Student",
|
||||
"share": 1
|
||||
"role": "LMS Student"
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
|
||||
@@ -1,9 +1,64 @@
|
||||
# Copyright (c) 2024, Frappe and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
# import frappe
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
from lms.lms.doctype.lms_badge.lms_badge import eval_condition
|
||||
|
||||
|
||||
class LMSBadgeAssignment(Document):
|
||||
pass
|
||||
def validate(self):
|
||||
self.validate_owner()
|
||||
self.validate_duplicate_badge_assignment()
|
||||
self.validate_badge_criteria()
|
||||
|
||||
def validate_owner(self):
|
||||
if self.owner == self.member:
|
||||
return
|
||||
|
||||
roles = frappe.get_roles(self.owner)
|
||||
if "Moderator" not in roles:
|
||||
frappe.throw(_("You must be a Moderator to assign badges to users."))
|
||||
|
||||
def validate_duplicate_badge_assignment(self):
|
||||
grant_only_once = frappe.db.get_value("LMS Badge", self.badge, "grant_only_once")
|
||||
if not grant_only_once:
|
||||
return
|
||||
|
||||
if frappe.db.exists(
|
||||
"LMS Badge Assignment",
|
||||
{"badge": self.badge, "member": self.member, "name": ["!=", self.name]},
|
||||
):
|
||||
frappe.throw(
|
||||
_("Badge {0} has already been assigned to this {1}.").format(self.badge, self.member)
|
||||
)
|
||||
|
||||
def validate_badge_criteria(self):
|
||||
badge_details = frappe.db.get_value(
|
||||
"LMS Badge", self.badge, ["reference_doctype", "user_field", "condition", "enabled"], as_dict=True
|
||||
)
|
||||
|
||||
if badge_details:
|
||||
if badge_details.reference_doctype and badge_details.user_field and badge_details.condition:
|
||||
user_fieldname = frappe.db.get_value(
|
||||
"DocField",
|
||||
{"parent": badge_details.reference_doctype, "fieldname": badge_details.user_field},
|
||||
"fieldname",
|
||||
)
|
||||
|
||||
documents = frappe.get_all(
|
||||
badge_details.reference_doctype,
|
||||
{user_fieldname: self.member},
|
||||
)
|
||||
|
||||
for document in documents:
|
||||
reference_value = eval_condition(
|
||||
frappe.get_doc(badge_details.reference_doctype, document.name),
|
||||
badge_details.condition,
|
||||
)
|
||||
if reference_value:
|
||||
return
|
||||
|
||||
frappe.throw(_("Member does not meet the criteria for the badge {0}.").format(self.badge))
|
||||
|
||||
@@ -379,7 +379,7 @@
|
||||
"link_fieldname": "batch_name"
|
||||
}
|
||||
],
|
||||
"modified": "2025-05-26 15:30:55.083507",
|
||||
"modified": "2025-12-04 12:54:11.190967",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Batch",
|
||||
@@ -422,13 +422,8 @@
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "LMS Student",
|
||||
"share": 1
|
||||
"role": "LMS Student"
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
|
||||
@@ -73,8 +73,8 @@
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-02-11 10:39:57.259526",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2025-12-04 12:53:38.246250",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Batch Enrollment",
|
||||
"owner": "Administrator",
|
||||
@@ -105,18 +105,14 @@
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "LMS Student",
|
||||
"share": 1
|
||||
"role": "LMS Student"
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"title_field": "member_name"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,19 @@ class LMSBatchEnrollment(Document):
|
||||
self.add_member_to_live_class()
|
||||
|
||||
def validate(self):
|
||||
self.validate_owner()
|
||||
self.validate_duplicate_members()
|
||||
self.validate_seat_availability()
|
||||
self.validate_course_enrollment()
|
||||
|
||||
def validate_owner(self):
|
||||
if self.owner == self.member:
|
||||
return
|
||||
|
||||
roles = frappe.get_roles(self.owner)
|
||||
if not ("Moderator" in roles or "Batch Evaluator" in roles):
|
||||
frappe.throw(_("You must be a Moderator or Batch Evaluator to enroll users in a batch."))
|
||||
|
||||
def validate_duplicate_members(self):
|
||||
if frappe.db.exists(
|
||||
"LMS Batch Enrollment",
|
||||
@@ -25,6 +35,12 @@ class LMSBatchEnrollment(Document):
|
||||
):
|
||||
frappe.throw(_("Member already enrolled in this batch"))
|
||||
|
||||
def validate_seat_availability(self):
|
||||
seat_count = frappe.db.get_value("LMS Batch", self.batch, "seat_count")
|
||||
enrolled_count = frappe.db.count("LMS Batch Enrollment", {"batch": self.batch})
|
||||
if seat_count and enrolled_count >= seat_count:
|
||||
frappe.throw(_("There are no seats available in this batch."))
|
||||
|
||||
def validate_course_enrollment(self):
|
||||
courses = frappe.get_all("Batch Course", filters={"parent": self.batch}, fields=["course"])
|
||||
|
||||
|
||||
@@ -115,29 +115,14 @@ def has_website_permission(doc, ptype, user, verbose=False):
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_certificate(course):
|
||||
certificate = is_certified(course)
|
||||
|
||||
if certificate:
|
||||
if is_certified(course):
|
||||
return frappe.db.get_value(
|
||||
"LMS Certificate", certificate, ["name", "course", "template"], as_dict=True
|
||||
)
|
||||
|
||||
else:
|
||||
default_certificate_template = frappe.db.get_value(
|
||||
"Property Setter",
|
||||
{
|
||||
"doc_type": "LMS Certificate",
|
||||
"property": "default_print_format",
|
||||
},
|
||||
"value",
|
||||
)
|
||||
if not default_certificate_template:
|
||||
default_certificate_template = frappe.db.get_value(
|
||||
"Print Format",
|
||||
{
|
||||
"doc_type": "LMS Certificate",
|
||||
},
|
||||
)
|
||||
validate_certification_eligibility(course)
|
||||
default_certificate_template = get_default_certificate_template()
|
||||
certificate = frappe.get_doc(
|
||||
{
|
||||
"doctype": "LMS Certificate",
|
||||
@@ -149,3 +134,37 @@ def create_certificate(course):
|
||||
)
|
||||
certificate.save(ignore_permissions=True)
|
||||
return certificate
|
||||
|
||||
|
||||
def get_default_certificate_template():
|
||||
default_certificate_template = frappe.db.get_value(
|
||||
"Property Setter",
|
||||
{
|
||||
"doc_type": "LMS Certificate",
|
||||
"property": "default_print_format",
|
||||
},
|
||||
"value",
|
||||
)
|
||||
if not default_certificate_template:
|
||||
default_certificate_template = frappe.db.get_value(
|
||||
"Print Format",
|
||||
{
|
||||
"doc_type": "LMS Certificate",
|
||||
},
|
||||
)
|
||||
|
||||
return default_certificate_template
|
||||
|
||||
|
||||
def validate_certification_eligibility(course):
|
||||
if not frappe.db.exists("LMS Enrollment", {"course": course, "member": frappe.session.user}):
|
||||
frappe.throw(_("You are not enrolled in this course."))
|
||||
|
||||
if not frappe.db.get_value("LMS Course", course, "enable_certification"):
|
||||
frappe.throw(_("Certification is not enabled for this course."))
|
||||
|
||||
progress = frappe.db.get_value(
|
||||
"LMS Enrollment", {"course": course, "member": frappe.session.user}, "progress"
|
||||
)
|
||||
if progress < 100:
|
||||
frappe.throw(_("You have not completed the course yet."))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.utils import add_years, cint, nowdate
|
||||
from frappe.utils import cint, nowdate
|
||||
|
||||
from lms.lms.doctype.lms_certificate.lms_certificate import create_certificate
|
||||
from lms.lms.doctype.lms_course.test_lms_course import new_course
|
||||
@@ -18,6 +18,7 @@ class TestLMSCertificate(unittest.TestCase):
|
||||
"enable_certification": 1,
|
||||
},
|
||||
)
|
||||
create_enrollment(course.name)
|
||||
certificate = create_certificate(course.name)
|
||||
|
||||
self.assertEqual(certificate.member, "Administrator")
|
||||
@@ -26,3 +27,11 @@ class TestLMSCertificate(unittest.TestCase):
|
||||
|
||||
frappe.db.delete("LMS Certificate", certificate.name)
|
||||
frappe.db.delete("LMS Course", course.name)
|
||||
|
||||
|
||||
def create_enrollment(course):
|
||||
enrollment = frappe.new_doc("LMS Enrollment")
|
||||
enrollment.course = course
|
||||
enrollment.member = frappe.session.user
|
||||
enrollment.progress = cint(100)
|
||||
enrollment.save()
|
||||
|
||||
@@ -6,7 +6,7 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
from lms.lms.utils import has_course_moderator_role
|
||||
from lms.lms.utils import has_moderator_role
|
||||
|
||||
|
||||
class LMSCertificateEvaluation(Document):
|
||||
@@ -19,7 +19,7 @@ class LMSCertificateEvaluation(Document):
|
||||
|
||||
|
||||
def has_website_permission(doc, ptype, user, verbose=False):
|
||||
if has_course_moderator_role() or doc.member == frappe.session.user:
|
||||
if has_moderator_role() or doc.member == frappe.session.user:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ class TestLMSCourse(unittest.TestCase):
|
||||
frappe.delete_doc("User", "tester@example.com")
|
||||
|
||||
if frappe.db.exists("LMS Course", "test-course"):
|
||||
frappe.db.delete("Batch Course", {"course": "test-course"})
|
||||
frappe.db.delete("Exercise Submission", {"course": "test-course"})
|
||||
frappe.db.delete("Exercise Latest Submission", {"course": "test-course"})
|
||||
frappe.db.delete("LMS Exercise", {"course": "test-course"})
|
||||
|
||||
@@ -77,8 +77,7 @@ def update_program_progress(member):
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_membership(course, batch=None, member=None, member_type="Student", role="Member"):
|
||||
if frappe.db.get_value("LMS Course", course, "disable_self_learning"):
|
||||
return False
|
||||
validate_course_enrollment_eligibility(course, member)
|
||||
|
||||
enrollment = frappe.new_doc("LMS Enrollment")
|
||||
enrollment.update(
|
||||
@@ -95,6 +94,42 @@ def create_membership(course, batch=None, member=None, member_type="Student", ro
|
||||
return enrollment
|
||||
|
||||
|
||||
def validate_course_enrollment_eligibility(course, member):
|
||||
if not member:
|
||||
member = frappe.session.user
|
||||
|
||||
course_details = frappe.db.get_value(
|
||||
"LMS Course",
|
||||
course,
|
||||
["published", "disable_self_learning", "paid_course", "paid_certificate"],
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
if course_details.disable_self_learning:
|
||||
frappe.throw(
|
||||
_(
|
||||
"You cannot enroll in this course as self-learning is disabled. Please contact the Administrator."
|
||||
)
|
||||
)
|
||||
|
||||
if not course_details.published:
|
||||
frappe.throw(_("You cannot enroll in an unpublished course."))
|
||||
|
||||
if course_details.paid_course:
|
||||
payment = frappe.db.exists(
|
||||
"LMS Payment",
|
||||
{
|
||||
"reference_doctype": "LMS Course",
|
||||
"reference_docname": course,
|
||||
"member": member,
|
||||
"payment_receipt": True,
|
||||
},
|
||||
)
|
||||
|
||||
if not payment:
|
||||
frappe.throw(_("You need to complete the payment for this course before enrolling."))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_current_membership(batch, course, member):
|
||||
all_memberships = frappe.get_all("LMS Enrollment", {"member": member, "course": course})
|
||||
|
||||
@@ -9,60 +9,15 @@ from lms.lms.doctype.lms_course.test_lms_course import new_course, new_user
|
||||
|
||||
|
||||
class TestLMSEnrollment(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.db.delete("LMS Enrollment")
|
||||
frappe.db.delete("LMS Batch Old")
|
||||
frappe.db.delete("LMS Course Mentor Mapping")
|
||||
frappe.db.delete("User", {"email": ("like", "%@test.com")})
|
||||
|
||||
def new_course_batch(self):
|
||||
course = new_course("Test Course")
|
||||
|
||||
new_user("Test Mentor", "mentor@test.com")
|
||||
# without this, the creating batch will fail
|
||||
course.add_mentor("mentor@test.com")
|
||||
|
||||
frappe.session.user = "mentor@test.com"
|
||||
|
||||
batch = frappe.get_doc(
|
||||
{
|
||||
"doctype": "LMS Batch Old",
|
||||
"name": "test-batch",
|
||||
"title": "Test Batch",
|
||||
"course": course.name,
|
||||
}
|
||||
)
|
||||
batch.insert(ignore_permissions=True)
|
||||
|
||||
frappe.session.user = "Administrator"
|
||||
return course, batch
|
||||
|
||||
def add_membership(self, batch_name, member_name, course, member_type="Student"):
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "LMS Enrollment",
|
||||
"batch_old": batch_name,
|
||||
"member": member_name,
|
||||
"member_type": member_type,
|
||||
"course": course,
|
||||
}
|
||||
)
|
||||
doc.insert()
|
||||
return doc
|
||||
|
||||
def test_membership(self):
|
||||
course, batch = self.new_course_batch()
|
||||
member = new_user("Test", "test01@test.com")
|
||||
membership = self.add_membership(batch.name, member.name, course.name)
|
||||
course = new_course("Test Enrollment")
|
||||
enrollment = frappe.new_doc("LMS Enrollment")
|
||||
enrollment.course = course.name
|
||||
enrollment.member = frappe.session.user
|
||||
|
||||
assert membership.course == course.name
|
||||
assert membership.member_name == member.full_name
|
||||
enrollment.save()
|
||||
|
||||
def test_membership_change_role(self):
|
||||
course, batch = self.new_course_batch()
|
||||
member = new_user("Test", "test01@test.com")
|
||||
membership = self.add_membership(batch.name, member.name, course.name)
|
||||
|
||||
# it should be possible to change role
|
||||
membership.role = "Admin"
|
||||
membership.save()
|
||||
self.assertEqual(enrollment.course, course.name)
|
||||
self.assertEqual(enrollment.member, "Administrator")
|
||||
frappe.db.delete("LMS Enrollment", enrollment.name)
|
||||
frappe.db.delete("LMS Course", course.name)
|
||||
|
||||
@@ -3,52 +3,8 @@
|
||||
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
|
||||
from lms.lms.doctype.lms_course.test_lms_course import new_course
|
||||
# import frappe
|
||||
|
||||
|
||||
class TestLMSExercise(unittest.TestCase):
|
||||
def new_exercise(self):
|
||||
course = new_course("Test Course")
|
||||
member = frappe.get_doc(
|
||||
{
|
||||
"doctype": "LMS Enrollment",
|
||||
"course": course.name,
|
||||
"member": frappe.session.user,
|
||||
}
|
||||
)
|
||||
member.insert()
|
||||
e = frappe.get_doc(
|
||||
{
|
||||
"doctype": "LMS Exercise",
|
||||
"name": "test-problem",
|
||||
"course": course.name,
|
||||
"title": "Test Problem",
|
||||
"description": "draw a circle",
|
||||
"code": "# draw a single cicle",
|
||||
"answer": ("# draw a single circle\n" + "circle(100, 100, 50)"),
|
||||
}
|
||||
)
|
||||
e.insert()
|
||||
return e
|
||||
|
||||
def test_exercise(self):
|
||||
e = self.new_exercise()
|
||||
assert e.get_user_submission() is None
|
||||
|
||||
def test_exercise_submission(self):
|
||||
e = self.new_exercise()
|
||||
submission = e.submit("circle(100, 100, 50)")
|
||||
assert submission is not None
|
||||
assert submission.exercise == e.name
|
||||
assert submission.course == e.course
|
||||
|
||||
user_submission = e.get_user_submission()
|
||||
assert user_submission is not None
|
||||
assert user_submission.name == submission.name
|
||||
|
||||
def tearDown(self):
|
||||
frappe.db.delete("LMS Enrollment")
|
||||
frappe.db.delete("Exercise Submission")
|
||||
frappe.db.delete("LMS Exercise")
|
||||
pass
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
"grid_page_length": 50,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2025-08-20 12:28:57.238902",
|
||||
"modified": "2025-12-04 12:56:14.249363",
|
||||
"modified_by": "sayali@frappe.io",
|
||||
"module": "LMS",
|
||||
"name": "LMS Program",
|
||||
@@ -136,13 +136,8 @@
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "LMS Student",
|
||||
"share": 1
|
||||
"role": "LMS Student"
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
|
||||
@@ -5,7 +5,7 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
from lms.lms.utils import has_course_instructor_role, has_course_moderator_role
|
||||
from lms.lms.utils import has_course_instructor_role, has_moderator_role
|
||||
|
||||
|
||||
class LMSQuestion(Document):
|
||||
@@ -95,7 +95,7 @@ def get_correct_options(question):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_question_details(question):
|
||||
if not has_course_instructor_role() or not has_course_moderator_role():
|
||||
if not has_course_instructor_role() or not has_moderator_role():
|
||||
return
|
||||
|
||||
fields = ["question", "type", "name"]
|
||||
|
||||
+128
-39
@@ -201,7 +201,7 @@ def get_lesson_icon(body, content):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_tags(course):
|
||||
tags = frappe.db.get_value("LMS Course", course, "tags")
|
||||
return tags.split(",") if tags else []
|
||||
@@ -246,7 +246,7 @@ def get_average_rating(course):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_reviews(course):
|
||||
reviews = frappe.get_all(
|
||||
"LMS Course Review",
|
||||
@@ -492,7 +492,7 @@ def can_create_courses(course, member=None):
|
||||
if frappe.session.user == "Guest":
|
||||
return False
|
||||
|
||||
if has_course_moderator_role(member):
|
||||
if has_moderator_role(member):
|
||||
return True
|
||||
|
||||
if has_course_instructor_role(member) and member in instructors:
|
||||
@@ -508,14 +508,14 @@ def can_create_batches(member=None):
|
||||
if not member:
|
||||
member = frappe.session.user
|
||||
|
||||
if has_course_moderator_role(member):
|
||||
if has_moderator_role(member):
|
||||
return True
|
||||
if has_course_evaluator_role(member):
|
||||
if has_evaluator_role(member):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def has_course_moderator_role(member=None):
|
||||
def has_moderator_role(member=None):
|
||||
return frappe.db.get_value(
|
||||
"Has Role",
|
||||
{"parent": member or frappe.session.user, "role": "Moderator"},
|
||||
@@ -523,7 +523,7 @@ def has_course_moderator_role(member=None):
|
||||
)
|
||||
|
||||
|
||||
def has_course_evaluator_role(member=None):
|
||||
def has_evaluator_role(member=None):
|
||||
return frappe.db.get_value(
|
||||
"Has Role",
|
||||
{"parent": member or frappe.session.user, "role": "Batch Evaluator"},
|
||||
@@ -748,7 +748,7 @@ def has_lessons(course):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_chart_data(
|
||||
chart_name,
|
||||
timespan="Select Date Range",
|
||||
@@ -796,7 +796,7 @@ def get_chart_data(
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_course_completion_data():
|
||||
all_membership = frappe.db.count("LMS Enrollment")
|
||||
completed = frappe.db.count("LMS Enrollment", {"progress": ["like", "%100%"]})
|
||||
@@ -823,7 +823,7 @@ def get_telemetry_boot_info():
|
||||
|
||||
@frappe.whitelist()
|
||||
def is_onboarding_complete():
|
||||
if not has_course_moderator_role():
|
||||
if not has_moderator_role():
|
||||
return {"is_onboarded": True}
|
||||
|
||||
course_created = frappe.db.a_row_exists("LMS Course")
|
||||
@@ -972,7 +972,7 @@ def change_currency(amount, currency, country=None):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_courses(filters=None, start=0):
|
||||
"""Returns the list of courses."""
|
||||
|
||||
@@ -1113,7 +1113,7 @@ def get_course_fields():
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_course_details(course):
|
||||
course_details = frappe.db.get_value(
|
||||
"LMS Course",
|
||||
@@ -1235,7 +1235,7 @@ def get_course_outline(course, progress=False):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_lesson(course, chapter, lesson):
|
||||
chapter_name = frappe.db.get_value("Chapter Reference", {"parent": course, "idx": chapter}, "chapter")
|
||||
lesson_name = frappe.db.get_value("Lesson Reference", {"parent": chapter_name, "idx": lesson}, "lesson")
|
||||
@@ -1266,7 +1266,7 @@ def get_lesson(course, chapter, lesson):
|
||||
if (
|
||||
not lesson_details.include_in_preview
|
||||
and not membership
|
||||
and not has_course_moderator_role()
|
||||
and not has_moderator_role()
|
||||
and not is_instructor(course)
|
||||
):
|
||||
return {
|
||||
@@ -1467,7 +1467,7 @@ def get_question_details(question):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_batch_courses(batch):
|
||||
courses = []
|
||||
course_list = frappe.get_all("Batch Course", {"parent": batch}, ["name", "course"])
|
||||
@@ -1691,6 +1691,11 @@ def has_submitted_assessment(assessment, assessment_type, member=None):
|
||||
docfield = "quiz"
|
||||
fields = ["percentage"]
|
||||
not_attempted = 0
|
||||
elif assessment_type == "LMS Programming Exercise":
|
||||
doctype = "LMS Programming Exercise Submission"
|
||||
docfield = "exercise"
|
||||
fields = ["status"]
|
||||
not_attempted = "Not Attempted"
|
||||
|
||||
filters = {}
|
||||
filters[docfield] = assessment
|
||||
@@ -1954,9 +1959,9 @@ def get_lesson_creation_details(course, chapter, lesson):
|
||||
def get_roles(name):
|
||||
frappe.only_for("Moderator")
|
||||
return {
|
||||
"moderator": has_course_moderator_role(name),
|
||||
"moderator": has_moderator_role(name),
|
||||
"course_creator": has_course_instructor_role(name),
|
||||
"batch_evaluator": has_course_evaluator_role(name),
|
||||
"batch_evaluator": has_evaluator_role(name),
|
||||
"lms_student": has_student_role(name),
|
||||
}
|
||||
|
||||
@@ -2058,29 +2063,59 @@ def enroll_in_course(course, payment_name):
|
||||
|
||||
@frappe.whitelist()
|
||||
def enroll_in_batch(batch, payment_name=None):
|
||||
if not frappe.db.exists("LMS Batch Enrollment", {"batch": batch, "member": frappe.session.user}):
|
||||
batch_doc = frappe.db.get_value("LMS Batch", batch, ["name", "seat_count"], as_dict=True)
|
||||
students = frappe.db.count("LMS Batch Enrollment", {"batch": batch})
|
||||
if batch_doc.seat_count and students >= batch_doc.seat_count:
|
||||
frappe.throw(_("The batch is full. Please contact the Administrator."))
|
||||
if not frappe.db.exists("LMS Batch", batch):
|
||||
frappe.throw(_("The specified batch does not exist."))
|
||||
|
||||
new_student = frappe.new_doc("LMS Batch Enrollment")
|
||||
batch_doc = frappe.db.get_value(
|
||||
"LMS Batch", batch, ["name", "seat_count", "allow_self_enrollment"], as_dict=True
|
||||
)
|
||||
payment_doc = get_payment_details(payment_name)
|
||||
validate_enrollment_eligibility(batch_doc, payment_doc)
|
||||
create_enrollment(batch, payment_doc)
|
||||
|
||||
|
||||
def get_payment_details(payment_name):
|
||||
payment_doc = None
|
||||
if payment_name:
|
||||
payment_doc = frappe.db.get_value(
|
||||
"LMS Payment", payment_name, ["name", "source", "payment_received"], as_dict=True
|
||||
)
|
||||
return payment_doc
|
||||
|
||||
|
||||
def validate_enrollment_eligibility(batch_doc, payment_doc=None):
|
||||
if frappe.db.exists("LMS Batch Enrollment", {"batch": batch_doc.name, "member": frappe.session.user}):
|
||||
frappe.throw(_("You are already enrolled in this batch."))
|
||||
|
||||
if batch_doc.paid_batch:
|
||||
if not payment_doc or not payment_doc.payment_received:
|
||||
frappe.throw(_("Payment is required to enroll in this batch."))
|
||||
|
||||
elif not batch_doc.allow_self_enrollment:
|
||||
frappe.throw(_("Enrollment in this batch is restricted. Please contact the Administrator."))
|
||||
|
||||
students = frappe.db.count("LMS Batch Enrollment", {"batch": batch_doc.name})
|
||||
if batch_doc.seat_count and students >= batch_doc.seat_count:
|
||||
frappe.throw(_("There are no seats available in this batch."))
|
||||
|
||||
|
||||
def create_enrollment(batch, payment_doc=None):
|
||||
new_student = frappe.new_doc("LMS Batch Enrollment")
|
||||
new_student.update(
|
||||
{
|
||||
"member": frappe.session.user,
|
||||
"batch": batch,
|
||||
}
|
||||
)
|
||||
|
||||
if payment_doc:
|
||||
new_student.update(
|
||||
{
|
||||
"member": frappe.session.user,
|
||||
"batch": batch,
|
||||
"payment": payment_doc.name,
|
||||
"source": payment_doc.source,
|
||||
}
|
||||
)
|
||||
|
||||
if payment_name:
|
||||
payment = frappe.db.get_value("LMS Payment", payment_name, ["name", "source"], as_dict=True)
|
||||
new_student.update(
|
||||
{
|
||||
"payment": payment.name,
|
||||
"source": payment.source,
|
||||
}
|
||||
)
|
||||
new_student.save()
|
||||
new_student.save()
|
||||
|
||||
|
||||
def update_certificate_purchase(course, payment_name):
|
||||
@@ -2169,8 +2204,8 @@ def get_program_details(program_name):
|
||||
|
||||
@frappe.whitelist()
|
||||
def enroll_in_program(program):
|
||||
if frappe.session.user == "Guest":
|
||||
frappe.throw(_("Please login to enroll in the program."))
|
||||
validate_program_enrollment(program)
|
||||
|
||||
if not frappe.db.exists("LMS Program Member", {"parent": program, "member": frappe.session.user}):
|
||||
program_member = frappe.new_doc("LMS Program Member")
|
||||
program_member.update(
|
||||
@@ -2184,8 +2219,17 @@ def enroll_in_program(program):
|
||||
program_member.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def validate_program_enrollment(program):
|
||||
if frappe.session.user == "Guest":
|
||||
frappe.throw(_("Please login to enroll in the program."))
|
||||
|
||||
published = frappe.db.get_value("LMS Program", program, "published")
|
||||
if not published:
|
||||
frappe.throw(_("You cannot enroll in an unpublished program."))
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_batches(filters=None, start=0, order_by="start_date"):
|
||||
if not filters:
|
||||
filters = {}
|
||||
@@ -2299,7 +2343,7 @@ def get_palette(full_name):
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
@rate_limit(limit=50, seconds=60 * 60)
|
||||
@rate_limit(limit=500, seconds=60 * 60)
|
||||
def get_related_courses(course):
|
||||
related_course_details = []
|
||||
related_courses = frappe.get_all("Related Courses", {"parent": course}, order_by="idx", pluck="course")
|
||||
@@ -2648,3 +2692,48 @@ def get_streak_info():
|
||||
"current_streak": current_streak,
|
||||
"longest_streak": longest_streak,
|
||||
}
|
||||
|
||||
|
||||
def validate_discussion_reply(doc, method):
|
||||
topic = frappe.db.get_value(
|
||||
"Discussion Topic", doc.topic, ["reference_doctype", "reference_docname"], as_dict=True
|
||||
)
|
||||
|
||||
if topic.reference_doctype == "Course Lesson":
|
||||
validate_course_access(topic.reference_docname)
|
||||
|
||||
elif topic.reference_doctype == "LMS Batch":
|
||||
validate_batch_access(topic.reference_docname)
|
||||
|
||||
|
||||
def validate_course_access(lesson):
|
||||
if not frappe.db.exists("Course Lesson", lesson):
|
||||
frappe.throw(_("The lesson does not exist."))
|
||||
|
||||
if has_moderator_role():
|
||||
return
|
||||
|
||||
if has_course_instructor_role():
|
||||
return
|
||||
|
||||
course = frappe.db.get_value("Course Lesson", lesson, "course")
|
||||
enrollment_exists = frappe.db.exists("LMS Enrollment", {"member": frappe.session.user, "course": course})
|
||||
if not enrollment_exists:
|
||||
frappe.throw(_("You do not have access to this course."))
|
||||
|
||||
|
||||
def validate_batch_access(batch):
|
||||
if not frappe.db.exists("LMS Batch", batch):
|
||||
frappe.throw(_("The batch does not exist."))
|
||||
|
||||
if has_moderator_role():
|
||||
return
|
||||
|
||||
if has_evaluator_role():
|
||||
return
|
||||
|
||||
enrollment_exists = frappe.db.exists(
|
||||
"LMS Batch Enrollment", {"member": frappe.session.user, "batch": batch}
|
||||
)
|
||||
if not enrollment_exists:
|
||||
frappe.throw(_("You do not have access to this batch."))
|
||||
|
||||
+9
-9
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-11-28 16:04+0000\n"
|
||||
"PO-Revision-Date: 2025-12-02 16:12\n"
|
||||
"PO-Revision-Date: 2025-12-04 17:07\n"
|
||||
"Last-Translator: jannat@frappe.io\n"
|
||||
"Language-Team: Bosnian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -1375,20 +1375,20 @@ msgstr "Zajednica"
|
||||
#: lms/job/doctype/lms_job_application/lms_job_application.json
|
||||
#: lms/lms/doctype/work_experience/work_experience.json
|
||||
msgid "Company"
|
||||
msgstr "Kompanija"
|
||||
msgstr "Poduzeće"
|
||||
|
||||
#. Label of the section_break_6 (Section Break) field in DocType 'Job
|
||||
#. Opportunity'
|
||||
#: frontend/src/pages/JobForm.vue:63
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
msgid "Company Details"
|
||||
msgstr "Detalji o Kompaniji"
|
||||
msgstr "Detalji o Poduzeću"
|
||||
|
||||
#. Label of the company_email_address (Data) field in DocType 'Job Opportunity'
|
||||
#: frontend/src/pages/JobForm.vue:82
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
msgid "Company Email Address"
|
||||
msgstr "Adresa e-pošte Kompanije"
|
||||
msgstr "Adresa e-pošte Poduzeća"
|
||||
|
||||
#. Label of the company_logo (Attach Image) field in DocType 'Job Opportunity'
|
||||
#. Label of a field in the job-opportunity Web Form
|
||||
@@ -1396,7 +1396,7 @@ msgstr "Adresa e-pošte Kompanije"
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
#: lms/job/web_form/job_opportunity/job_opportunity.json
|
||||
msgid "Company Logo"
|
||||
msgstr "Logo Kompanije"
|
||||
msgstr "Logo Poduzeća"
|
||||
|
||||
#. Label of the company_name (Data) field in DocType 'Job Opportunity'
|
||||
#. Label of a field in the job-opportunity Web Form
|
||||
@@ -1404,12 +1404,12 @@ msgstr "Logo Kompanije"
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
#: lms/job/web_form/job_opportunity/job_opportunity.json
|
||||
msgid "Company Name"
|
||||
msgstr "Naziv Kompanije"
|
||||
msgstr "Naziv Poduzeća"
|
||||
|
||||
#. Label of the company_type (Select) field in DocType 'User'
|
||||
#: lms/fixtures/custom_field.json
|
||||
msgid "Company Type"
|
||||
msgstr "Tip Kompanije"
|
||||
msgstr "Tip Poduzeća"
|
||||
|
||||
#. Label of the company_website (Data) field in DocType 'Job Opportunity'
|
||||
#. Label of a field in the job-opportunity Web Form
|
||||
@@ -1417,7 +1417,7 @@ msgstr "Tip Kompanije"
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
#: lms/job/web_form/job_opportunity/job_opportunity.json
|
||||
msgid "Company Website"
|
||||
msgstr "Web stranica Kompanije"
|
||||
msgstr "Web stranica Poduzeća"
|
||||
|
||||
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:69
|
||||
msgid "Compiler Message"
|
||||
@@ -2258,7 +2258,7 @@ msgstr "Ne propusti priliku da unaprediš svoje veštine. Klikni ispod da završ
|
||||
#. Label of the dream_companies (Data) field in DocType 'User'
|
||||
#: lms/fixtures/custom_field.json
|
||||
msgid "Dream Companies"
|
||||
msgstr "San Snova Kompanije"
|
||||
msgstr "Poduzeće iz Snova"
|
||||
|
||||
#: lms/lms/doctype/lms_question/lms_question.py:34
|
||||
msgid "Duplicate options found for this question."
|
||||
|
||||
+9
-9
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-11-28 16:04+0000\n"
|
||||
"PO-Revision-Date: 2025-12-02 16:12\n"
|
||||
"PO-Revision-Date: 2025-12-04 17:07\n"
|
||||
"Last-Translator: jannat@frappe.io\n"
|
||||
"Language-Team: Croatian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -1375,20 +1375,20 @@ msgstr "Zajednica"
|
||||
#: lms/job/doctype/lms_job_application/lms_job_application.json
|
||||
#: lms/lms/doctype/work_experience/work_experience.json
|
||||
msgid "Company"
|
||||
msgstr "Kompanija"
|
||||
msgstr "Tvrtka"
|
||||
|
||||
#. Label of the section_break_6 (Section Break) field in DocType 'Job
|
||||
#. Opportunity'
|
||||
#: frontend/src/pages/JobForm.vue:63
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
msgid "Company Details"
|
||||
msgstr "Detalji Kompanije"
|
||||
msgstr "Detalji Tvrtke"
|
||||
|
||||
#. Label of the company_email_address (Data) field in DocType 'Job Opportunity'
|
||||
#: frontend/src/pages/JobForm.vue:82
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
msgid "Company Email Address"
|
||||
msgstr "Adresa e-pošte Kompanije"
|
||||
msgstr "Adresa e-pošte Tvrtke"
|
||||
|
||||
#. Label of the company_logo (Attach Image) field in DocType 'Job Opportunity'
|
||||
#. Label of a field in the job-opportunity Web Form
|
||||
@@ -1396,7 +1396,7 @@ msgstr "Adresa e-pošte Kompanije"
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
#: lms/job/web_form/job_opportunity/job_opportunity.json
|
||||
msgid "Company Logo"
|
||||
msgstr "Logo Kompanije"
|
||||
msgstr "Logo Tvrtke"
|
||||
|
||||
#. Label of the company_name (Data) field in DocType 'Job Opportunity'
|
||||
#. Label of a field in the job-opportunity Web Form
|
||||
@@ -1404,12 +1404,12 @@ msgstr "Logo Kompanije"
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
#: lms/job/web_form/job_opportunity/job_opportunity.json
|
||||
msgid "Company Name"
|
||||
msgstr "Naziv Kompanije"
|
||||
msgstr "Naziv Tvrtke"
|
||||
|
||||
#. Label of the company_type (Select) field in DocType 'User'
|
||||
#: lms/fixtures/custom_field.json
|
||||
msgid "Company Type"
|
||||
msgstr "Tip Kompanije"
|
||||
msgstr "Tip Tvrtke"
|
||||
|
||||
#. Label of the company_website (Data) field in DocType 'Job Opportunity'
|
||||
#. Label of a field in the job-opportunity Web Form
|
||||
@@ -1417,7 +1417,7 @@ msgstr "Tip Kompanije"
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
#: lms/job/web_form/job_opportunity/job_opportunity.json
|
||||
msgid "Company Website"
|
||||
msgstr "Web stranica Kompanije"
|
||||
msgstr "Web stranica Tvrtke"
|
||||
|
||||
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseSubmission.vue:69
|
||||
msgid "Compiler Message"
|
||||
@@ -2258,7 +2258,7 @@ msgstr "Ne propusti priliku da unaprediš svoje veštine. Klikni ispod da završ
|
||||
#. Label of the dream_companies (Data) field in DocType 'User'
|
||||
#: lms/fixtures/custom_field.json
|
||||
msgid "Dream Companies"
|
||||
msgstr "San Snova Kompanije"
|
||||
msgstr "Tvrtke iz Snova"
|
||||
|
||||
#: lms/lms/doctype/lms_question/lms_question.py:34
|
||||
msgid "Duplicate options found for this question."
|
||||
|
||||
+12
-12
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-11-28 16:04+0000\n"
|
||||
"PO-Revision-Date: 2025-12-01 15:58\n"
|
||||
"PO-Revision-Date: 2025-12-04 17:06\n"
|
||||
"Last-Translator: jannat@frappe.io\n"
|
||||
"Language-Team: Hungarian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -661,7 +661,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/pages/ProfileEvaluator.vue:146
|
||||
msgid "Authorize Google Calendar Access"
|
||||
msgstr ""
|
||||
msgstr "Google Naptár Hozzáférés Engedélyezése"
|
||||
|
||||
#. Option for the 'Event' (Select) field in DocType 'LMS Badge'
|
||||
#: lms/lms/doctype/lms_badge/lms_badge.json
|
||||
@@ -919,14 +919,14 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Modals/EditProfile.vue:81
|
||||
msgid "Bio"
|
||||
msgstr ""
|
||||
msgstr "Életrajz"
|
||||
|
||||
#. Option for the 'Color' (Select) field in DocType 'LMS Course'
|
||||
#. Option for the 'Color' (Select) field in DocType 'LMS Lesson Note'
|
||||
#: lms/lms/doctype/lms_course/lms_course.json
|
||||
#: lms/lms/doctype/lms_lesson_note/lms_lesson_note.json
|
||||
msgid "Blue"
|
||||
msgstr ""
|
||||
msgstr "Kék"
|
||||
|
||||
#. Label of the body (Markdown Editor) field in DocType 'Course Lesson'
|
||||
#: lms/lms/doctype/course_lesson/course_lesson.json
|
||||
@@ -1004,7 +1004,7 @@ msgstr "Kategória"
|
||||
|
||||
#: frontend/src/components/Settings/Categories.vue:39
|
||||
msgid "Category Name"
|
||||
msgstr ""
|
||||
msgstr "Kategória Neve"
|
||||
|
||||
#: frontend/src/components/Settings/Categories.vue:133
|
||||
msgid "Category added successfully"
|
||||
@@ -1148,7 +1148,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Quiz.vue:229
|
||||
msgid "Check"
|
||||
msgstr ""
|
||||
msgstr "Jelölje be"
|
||||
|
||||
#: frontend/src/pages/ProgrammingExercises/ProgrammingExercises.vue:16
|
||||
msgid "Check All Submissions"
|
||||
@@ -1233,7 +1233,7 @@ msgstr "Kattints ide"
|
||||
#: lms/lms/doctype/lms_zoom_settings/lms_zoom_settings.json
|
||||
#: lms/lms/doctype/zoom_settings/zoom_settings.json
|
||||
msgid "Client ID"
|
||||
msgstr ""
|
||||
msgstr "Ügyfél Azonosító"
|
||||
|
||||
#. Label of the client_secret (Password) field in DocType 'LMS Zoom Settings'
|
||||
#. Label of the client_secret (Password) field in DocType 'Zoom Settings'
|
||||
@@ -1241,7 +1241,7 @@ msgstr ""
|
||||
#: lms/lms/doctype/lms_zoom_settings/lms_zoom_settings.json
|
||||
#: lms/lms/doctype/zoom_settings/zoom_settings.json
|
||||
msgid "Client Secret"
|
||||
msgstr ""
|
||||
msgstr "Ügyfél Jelszó"
|
||||
|
||||
#: frontend/src/components/Settings/Categories.vue:27
|
||||
msgid "Close"
|
||||
@@ -1270,7 +1270,7 @@ msgstr ""
|
||||
#: lms/lms/doctype/lms_exercise/lms_exercise.json
|
||||
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
msgstr "Kód"
|
||||
|
||||
#. Name of a DocType
|
||||
#. Label of the cohort (Link) field in DocType 'Cohort Join Request'
|
||||
@@ -1482,7 +1482,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Sidebar/Configuration.vue:12
|
||||
msgid "Configuration"
|
||||
msgstr ""
|
||||
msgstr "Beállítás"
|
||||
|
||||
#: frontend/src/pages/BatchForm.vue:148
|
||||
msgid "Configurations"
|
||||
@@ -2012,7 +2012,7 @@ msgstr ""
|
||||
#. Option for the 'Color' (Select) field in DocType 'LMS Course'
|
||||
#: lms/lms/doctype/lms_course/lms_course.json
|
||||
msgid "Cyan"
|
||||
msgstr ""
|
||||
msgstr "Cián"
|
||||
|
||||
#. Label of the show_dashboard (Check) field in DocType 'LMS Settings'
|
||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||
@@ -2241,7 +2241,7 @@ msgstr ""
|
||||
#: lms/lms/doctype/lms_assignment/lms_assignment.json
|
||||
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
||||
msgid "Document"
|
||||
msgstr ""
|
||||
msgstr "Dokumentum"
|
||||
|
||||
#: frontend/src/components/Settings/Coupons/CouponItems.vue:11
|
||||
msgid "Document Name"
|
||||
|
||||
+811
-811
File diff suppressed because it is too large
Load Diff
+91
-91
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
|
||||
"POT-Creation-Date: 2025-11-28 16:04+0000\n"
|
||||
"PO-Revision-Date: 2025-12-01 15:58\n"
|
||||
"PO-Revision-Date: 2025-12-04 17:06\n"
|
||||
"Last-Translator: jannat@frappe.io\n"
|
||||
"Language-Team: Slovenian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -24,11 +24,11 @@ msgstr "Brskaj i Oceni"
|
||||
|
||||
#: frontend/src/pages/Programs/ProgramEnrollment.vue:32
|
||||
msgid " designed as a learning path to guide your progress. You may take the courses in any order that suits you. "
|
||||
msgstr ""
|
||||
msgstr " zasnovano kot učna pot, ki vas bo vodila skozi napredek. Tečaje lahko obiskujete v poljubnem vrstnem redu, ki vam ustreza. "
|
||||
|
||||
#: frontend/src/pages/Programs/ProgramEnrollment.vue:25
|
||||
msgid " designed as a structured learning path to guide your progress. Courses in this program must be taken in order, and each course will unlock as you complete the previous one. "
|
||||
msgstr ""
|
||||
msgstr " zasnovan kot strukturirana učna pot, ki vas bo vodila skozi napredek. Tečaje v tem programu je treba obiskovati po vrsti, vsak tečaj pa se bo odklenil, ko boste zaključili prejšnjega. "
|
||||
|
||||
#: frontend/src/pages/Home/Streak.vue:21
|
||||
msgid " you are on a"
|
||||
@@ -84,7 +84,7 @@ msgstr "Tečaj ne more imeti hkrati plačanega potrdila in potrdila o opravljene
|
||||
|
||||
#: frontend/src/pages/CourseForm.vue:190
|
||||
msgid "A one line introduction to the course that appears on the course card"
|
||||
msgstr ""
|
||||
msgstr "Enovrstični uvod v tečaj, ki se prikaže na kartici tečaja"
|
||||
|
||||
#: frontend/src/pages/ProfileAbout.vue:4
|
||||
msgid "About"
|
||||
@@ -232,15 +232,15 @@ msgstr "Dodajte vajo programiranja svoji lekciji"
|
||||
|
||||
#: frontend/src/components/AssessmentPlugin.vue:7
|
||||
msgid "Add a quiz to your lesson"
|
||||
msgstr ""
|
||||
msgstr "Dodaj kviza v lekcijo"
|
||||
|
||||
#: frontend/src/components/Modals/AssessmentModal.vue:5
|
||||
msgid "Add an assessment"
|
||||
msgstr ""
|
||||
msgstr "Dodaj oceno"
|
||||
|
||||
#: frontend/src/components/AssessmentPlugin.vue:8
|
||||
msgid "Add an assignment to your lesson"
|
||||
msgstr ""
|
||||
msgstr "Dodaj nalogo lekciji"
|
||||
|
||||
#: lms/lms/doctype/lms_question/lms_question.py:67
|
||||
msgid "Add at least one possible answer for this question: {0}"
|
||||
@@ -252,7 +252,7 @@ msgstr "Dodaj tečaje v skupino"
|
||||
|
||||
#: frontend/src/components/Modals/QuizInVideo.vue:5
|
||||
msgid "Add quiz to this video"
|
||||
msgstr ""
|
||||
msgstr "Dodaj kviz temu videoposnetku"
|
||||
|
||||
#: frontend/src/components/Sidebar/AppSidebar.vue:567
|
||||
msgid "Add students to your batch"
|
||||
@@ -264,19 +264,19 @@ msgstr "Dodaj v Opombe"
|
||||
|
||||
#: frontend/src/components/Modals/PageModal.vue:6
|
||||
msgid "Add web page to sidebar"
|
||||
msgstr ""
|
||||
msgstr "Dodaj spletno stran v stransko vrstico"
|
||||
|
||||
#: frontend/src/components/Assignment.vue:68
|
||||
msgid "Add your assignment as {0}"
|
||||
msgstr ""
|
||||
msgstr "Dodajte svojo nalogo kot {0}"
|
||||
|
||||
#: frontend/src/components/Sidebar/AppSidebar.vue:500
|
||||
msgid "Add your first chapter"
|
||||
msgstr ""
|
||||
msgstr "Dodajte svoje prvo poglavje"
|
||||
|
||||
#: frontend/src/components/Sidebar/AppSidebar.vue:516
|
||||
msgid "Add your first lesson"
|
||||
msgstr ""
|
||||
msgstr "Dodajte svojo prvo lekcijo"
|
||||
|
||||
#. Label of the address (Link) field in DocType 'LMS Payment'
|
||||
#: frontend/src/components/Settings/Transactions/TransactionDetails.vue:103
|
||||
@@ -322,21 +322,21 @@ msgstr "Vsi Tečaji"
|
||||
|
||||
#: frontend/src/pages/Programs/StudentPrograms.vue:5
|
||||
msgid "All Programs"
|
||||
msgstr ""
|
||||
msgstr "Vsi Programi"
|
||||
|
||||
#: lms/lms/doctype/lms_quiz/lms_quiz.py:42
|
||||
msgid "All questions should have the same marks if the limit is set."
|
||||
msgstr ""
|
||||
msgstr "Če je določena omejitev, bi morala imeti vsa vprašanja enako število točk."
|
||||
|
||||
#. Label of the allow_guest_access (Check) field in DocType 'LMS Settings'
|
||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||
msgid "Allow Guest Access"
|
||||
msgstr ""
|
||||
msgstr "Dovoli dostop gostom"
|
||||
|
||||
#. Label of the allow_posting (Check) field in DocType 'Job Settings'
|
||||
#: lms/job/doctype/job_settings/job_settings.json
|
||||
msgid "Allow Job Posting From Website"
|
||||
msgstr ""
|
||||
msgstr "Dovoli objavo delovnih mest s spletnega mesta"
|
||||
|
||||
#. Label of the allow_self_enrollment (Check) field in DocType 'LMS Batch'
|
||||
#: lms/lms/doctype/lms_batch/lms_batch.json
|
||||
@@ -423,7 +423,7 @@ msgstr "Odgovor"
|
||||
|
||||
#: frontend/src/pages/CourseForm.vue:104 frontend/src/pages/CourseForm.vue:123
|
||||
msgid "Appears on the course card in the course list"
|
||||
msgstr ""
|
||||
msgstr "Prikaže se na kartici predmeta na seznamu predmetov"
|
||||
|
||||
#: frontend/src/pages/BatchForm.vue:250
|
||||
msgid "Appears when the batch URL is shared on any online platform"
|
||||
@@ -458,7 +458,7 @@ msgstr "Prijave"
|
||||
|
||||
#: frontend/src/pages/JobApplications.vue:292
|
||||
msgid "Applied On"
|
||||
msgstr ""
|
||||
msgstr "Uporabljeno na"
|
||||
|
||||
#: frontend/src/pages/Billing.vue:81 frontend/src/pages/JobDetail.vue:62
|
||||
msgid "Apply"
|
||||
@@ -476,7 +476,7 @@ msgstr "Zaokroževanje na Ekvivalent"
|
||||
|
||||
#: frontend/src/components/Modals/JobApplicationModal.vue:6
|
||||
msgid "Apply for this job"
|
||||
msgstr ""
|
||||
msgstr "Prijavite se za to delovno mesto"
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'LMS Course'
|
||||
#. Option for the 'Status' (Select) field in DocType 'LMS Mentor Request'
|
||||
@@ -600,7 +600,7 @@ msgstr ""
|
||||
#. Submission'
|
||||
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
||||
msgid "Assignment Title"
|
||||
msgstr ""
|
||||
msgstr "Naslov Naloge"
|
||||
|
||||
#: frontend/src/components/Modals/AssignmentForm.vue:146
|
||||
msgid "Assignment created successfully"
|
||||
@@ -1196,7 +1196,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Controls/IconPicker.vue:27
|
||||
msgid "Choose an icon"
|
||||
msgstr ""
|
||||
msgstr "Izberi ikono"
|
||||
|
||||
#: frontend/src/components/Quiz.vue:655
|
||||
msgid "Choose one answer"
|
||||
@@ -1482,7 +1482,7 @@ msgstr "Izvedi Vrednotenje"
|
||||
|
||||
#: frontend/src/components/Sidebar/Configuration.vue:12
|
||||
msgid "Configuration"
|
||||
msgstr ""
|
||||
msgstr "Konfiguracija"
|
||||
|
||||
#: frontend/src/pages/BatchForm.vue:148
|
||||
msgid "Configurations"
|
||||
@@ -1513,7 +1513,7 @@ msgstr "Predloga potrditvenega e-poštnega sporočila"
|
||||
|
||||
#: lms/lms/doctype/lms_certificate/lms_certificate.py:30
|
||||
msgid "Congratulations on getting certified!"
|
||||
msgstr ""
|
||||
msgstr "Čestitamo za pridobitev certifikata!"
|
||||
|
||||
#. Label of the contact_us_tab (Tab Break) field in DocType 'LMS Settings'
|
||||
#: frontend/src/components/ContactUsEmail.vue:5
|
||||
@@ -1578,7 +1578,7 @@ msgstr "Pravilno"
|
||||
|
||||
#: frontend/src/components/Modals/Question.vue:79
|
||||
msgid "Correct Answer"
|
||||
msgstr ""
|
||||
msgstr "Pravilen odgovor"
|
||||
|
||||
#. Label of the country (Link) field in DocType 'User'
|
||||
#. Label of the country (Link) field in DocType 'Job Opportunity'
|
||||
@@ -1814,7 +1814,7 @@ msgstr "Tečaj uspešno dodan v program"
|
||||
|
||||
#: frontend/src/pages/Programs/ProgramForm.vue:446
|
||||
msgid "Course already added to program"
|
||||
msgstr ""
|
||||
msgstr "Tečaj je že dodan v program"
|
||||
|
||||
#: frontend/src/pages/CourseForm.vue:569
|
||||
msgid "Course created successfully"
|
||||
@@ -1834,7 +1834,7 @@ msgstr "Tečaj {0} je bil že dodan tej skupini."
|
||||
|
||||
#: lms/lms/doctype/lms_program/lms_program.py:20
|
||||
msgid "Course {0} has already been added to this program."
|
||||
msgstr ""
|
||||
msgstr "Tečaj {0} je že dodan v ta program."
|
||||
|
||||
#. Label of the courses (Table) field in DocType 'LMS Batch'
|
||||
#. Label of the show_courses (Check) field in DocType 'LMS Settings'
|
||||
@@ -1962,7 +1962,7 @@ msgstr "Ustvari Skupino"
|
||||
|
||||
#: frontend/src/components/Sidebar/AppSidebar.vue:620
|
||||
msgid "Creating a course"
|
||||
msgstr ""
|
||||
msgstr "Ustvarjanje tečaja"
|
||||
|
||||
#. Label of the currency (Link) field in DocType 'LMS Batch'
|
||||
#. Label of the currency (Link) field in DocType 'LMS Course'
|
||||
@@ -2022,7 +2022,7 @@ msgstr "Nadzorna Plošča"
|
||||
#: frontend/src/components/Sidebar/Configuration.vue:33
|
||||
#: frontend/src/pages/DataImport.vue:35
|
||||
msgid "Data Import"
|
||||
msgstr ""
|
||||
msgstr "Uvoz Podatkov"
|
||||
|
||||
#. Label of the date (Date) field in DocType 'LMS Batch Timetable'
|
||||
#. Label of the date (Date) field in DocType 'LMS Certificate Evaluation'
|
||||
@@ -2099,27 +2099,27 @@ msgstr "Izbriši"
|
||||
|
||||
#: frontend/src/components/CourseOutline.vue:67
|
||||
msgid "Delete Chapter"
|
||||
msgstr ""
|
||||
msgstr "Izbriši Poglavje"
|
||||
|
||||
#: frontend/src/pages/CourseForm.vue:613
|
||||
msgid "Delete Course"
|
||||
msgstr ""
|
||||
msgstr "Izbriši Tečaj"
|
||||
|
||||
#: frontend/src/pages/Programs/ProgramForm.vue:561
|
||||
msgid "Delete Program"
|
||||
msgstr ""
|
||||
msgstr "Izbriši Program"
|
||||
|
||||
#: frontend/src/components/CourseOutline.vue:354
|
||||
msgid "Delete this chapter?"
|
||||
msgstr ""
|
||||
msgstr "Izbriši Poglavje?"
|
||||
|
||||
#: frontend/src/components/Settings/Coupons/CouponList.vue:127
|
||||
msgid "Delete this coupon?"
|
||||
msgstr ""
|
||||
msgstr "Izbriši Kupon?"
|
||||
|
||||
#: frontend/src/components/CourseOutline.vue:288
|
||||
msgid "Delete this lesson?"
|
||||
msgstr ""
|
||||
msgstr "Izbriši Lekcijo?"
|
||||
|
||||
#: frontend/src/pages/CourseForm.vue:614
|
||||
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
|
||||
@@ -2170,7 +2170,7 @@ msgstr "Opis"
|
||||
|
||||
#: frontend/src/components/Sidebar/Apps.vue:50
|
||||
msgid "Desk"
|
||||
msgstr ""
|
||||
msgstr "Pisalna miza"
|
||||
|
||||
#: frontend/src/components/Modals/DiscussionModal.vue:22
|
||||
#: frontend/src/pages/BatchForm.vue:21 frontend/src/pages/CourseForm.vue:25
|
||||
@@ -2199,17 +2199,17 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/ZoomSettings.vue:66
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
msgstr "Onemogočeno"
|
||||
|
||||
#: frontend/src/components/DiscussionReplies.vue:57
|
||||
#: lms/lms/widgets/NoPreviewModal.html:25 lms/templates/reviews.html:159
|
||||
msgid "Discard"
|
||||
msgstr ""
|
||||
msgstr "Zavrzi"
|
||||
|
||||
#: frontend/src/components/Settings/Coupons/CouponList.vue:169
|
||||
#: frontend/src/pages/Billing.vue:41
|
||||
msgid "Discount"
|
||||
msgstr ""
|
||||
msgstr "Popust"
|
||||
|
||||
#. Label of the discount_amount (Currency) field in DocType 'LMS Payment'
|
||||
#: frontend/src/components/Settings/Coupons/CouponDetails.vue:53
|
||||
@@ -2220,13 +2220,13 @@ msgstr "Znesek Popusta"
|
||||
|
||||
#: frontend/src/components/Settings/Coupons/CouponDetails.vue:46
|
||||
msgid "Discount Percentage"
|
||||
msgstr ""
|
||||
msgstr "Odstotek popusta"
|
||||
|
||||
#. Label of the discount_type (Select) field in DocType 'LMS Coupon'
|
||||
#: frontend/src/components/Settings/Coupons/CouponDetails.vue:30
|
||||
#: lms/lms/doctype/lms_coupon/lms_coupon.json
|
||||
msgid "Discount Type"
|
||||
msgstr ""
|
||||
msgstr "Tip Popusta"
|
||||
|
||||
#. Label of the show_discussions (Check) field in DocType 'LMS Settings'
|
||||
#: frontend/src/pages/Batch.vue:91
|
||||
@@ -2241,15 +2241,15 @@ msgstr "Razprave"
|
||||
#: lms/lms/doctype/lms_assignment/lms_assignment.json
|
||||
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
||||
msgid "Document"
|
||||
msgstr ""
|
||||
msgstr "Dokument"
|
||||
|
||||
#: frontend/src/components/Settings/Coupons/CouponItems.vue:11
|
||||
msgid "Document Name"
|
||||
msgstr ""
|
||||
msgstr "Ime Dokumenta"
|
||||
|
||||
#: frontend/src/components/Settings/Coupons/CouponItems.vue:8
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
msgstr "Tip Dokumenta"
|
||||
|
||||
#: lms/templates/emails/payment_reminder.html:11
|
||||
msgid "Don’t miss this opportunity to enhance your skills. Click below to complete your enrollment"
|
||||
@@ -2258,7 +2258,7 @@ msgstr ""
|
||||
#. Label of the dream_companies (Data) field in DocType 'User'
|
||||
#: lms/fixtures/custom_field.json
|
||||
msgid "Dream Companies"
|
||||
msgstr ""
|
||||
msgstr "Sanjska Podjetja"
|
||||
|
||||
#: lms/lms/doctype/lms_question/lms_question.py:34
|
||||
msgid "Duplicate options found for this question."
|
||||
@@ -2311,7 +2311,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/Settings/BadgeForm.vue:5
|
||||
msgid "Edit Badge"
|
||||
msgstr ""
|
||||
msgstr "Uredi Značko"
|
||||
|
||||
#: frontend/src/components/Settings/BadgeAssignmentForm.vue:8
|
||||
msgid "Edit Badge Assignment"
|
||||
@@ -2320,35 +2320,35 @@ msgstr ""
|
||||
#: frontend/src/components/CourseOutline.vue:60
|
||||
#: frontend/src/components/Modals/ChapterModal.vue:5
|
||||
msgid "Edit Chapter"
|
||||
msgstr ""
|
||||
msgstr "Uredi poglavje"
|
||||
|
||||
#: frontend/src/components/Settings/Coupons/CouponDetails.vue:9
|
||||
msgid "Edit Coupon"
|
||||
msgstr ""
|
||||
msgstr "Uredi Kupon"
|
||||
|
||||
#: frontend/src/components/Modals/EmailTemplateModal.vue:8
|
||||
msgid "Edit Email Template"
|
||||
msgstr ""
|
||||
msgstr "Uredi predloge e-pošte"
|
||||
|
||||
#: frontend/src/components/Settings/PaymentGatewayDetails.vue:8
|
||||
msgid "Edit Payment Gateway"
|
||||
msgstr ""
|
||||
msgstr "Uredi Plačilni Prehod"
|
||||
|
||||
#: frontend/src/pages/Profile.vue:80
|
||||
msgid "Edit Profile"
|
||||
msgstr ""
|
||||
msgstr "Uredi Profil"
|
||||
|
||||
#: frontend/src/pages/Programs/ProgramForm.vue:12
|
||||
msgid "Edit Program"
|
||||
msgstr ""
|
||||
msgstr "Uredi Program"
|
||||
|
||||
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:8
|
||||
msgid "Edit Programming Exercise"
|
||||
msgstr ""
|
||||
msgstr "Uredi Programsko Vaje"
|
||||
|
||||
#: frontend/src/components/Modals/ZoomAccountModal.vue:6
|
||||
msgid "Edit Zoom Account"
|
||||
msgstr ""
|
||||
msgstr "Uredi Zoom Račun"
|
||||
|
||||
#: frontend/src/pages/QuizForm.vue:199
|
||||
msgid "Edit the question"
|
||||
@@ -2357,7 +2357,7 @@ msgstr ""
|
||||
#. Label of the education (Table) field in DocType 'User'
|
||||
#: lms/fixtures/custom_field.json
|
||||
msgid "Education"
|
||||
msgstr ""
|
||||
msgstr "Izobrazba"
|
||||
|
||||
#. Name of a DocType
|
||||
#: lms/lms/doctype/education_detail/education_detail.json
|
||||
@@ -2373,7 +2373,7 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/Members.vue:103
|
||||
#: frontend/src/pages/JobApplications.vue:286 lms/templates/signup-form.html:10
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
msgstr "E-pošta"
|
||||
|
||||
#: frontend/src/components/Modals/Event.vue:16
|
||||
msgid "Email ID"
|
||||
@@ -2414,7 +2414,7 @@ msgstr ""
|
||||
#. Label of the show_emails (Check) field in DocType 'LMS Settings'
|
||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||
msgid "Emails"
|
||||
msgstr ""
|
||||
msgstr "E-pošta"
|
||||
|
||||
#. Option for the 'User Category' (Select) field in DocType 'User'
|
||||
#: lms/fixtures/custom_field.json lms/templates/signup-form.html:25
|
||||
@@ -2424,7 +2424,7 @@ msgstr "Osebje"
|
||||
#. Label of the enable (Check) field in DocType 'Zoom Settings'
|
||||
#: lms/lms/doctype/zoom_settings/zoom_settings.json
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
msgstr "Omogoči"
|
||||
|
||||
#: lms/lms/doctype/lms_settings/lms_settings.py:22
|
||||
msgid "Enable Google API in Google Settings to send calendar invites for evaluations."
|
||||
@@ -2454,7 +2454,7 @@ msgstr ""
|
||||
#: lms/lms/doctype/lms_coupon/lms_coupon.json
|
||||
#: lms/lms/doctype/lms_zoom_settings/lms_zoom_settings.json
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
msgstr "Omogočeno"
|
||||
|
||||
#: frontend/src/components/Modals/BulkCertificates.vue:53
|
||||
msgid "Enabling this will publish the certificate on the certified participants page."
|
||||
@@ -2493,7 +2493,7 @@ msgstr "Končni čas"
|
||||
#: frontend/src/pages/Home/AdminHome.vue:186
|
||||
#: frontend/src/pages/Home/StudentHome.vue:129
|
||||
msgid "Ended"
|
||||
msgstr ""
|
||||
msgstr "Končano"
|
||||
|
||||
#. Label of the enforce_course_order (Check) field in DocType 'LMS Program'
|
||||
#: frontend/src/pages/Programs/ProgramForm.vue:39
|
||||
@@ -2541,7 +2541,7 @@ msgstr ""
|
||||
#: frontend/src/pages/Programs/ProgramProgressSummary.vue:15
|
||||
#: lms/lms/doctype/lms_course/lms_course.json lms/lms/workspace/lms/lms.json
|
||||
msgid "Enrollments"
|
||||
msgstr ""
|
||||
msgstr "Vpisi"
|
||||
|
||||
#: lms/lms/doctype/lms_settings/lms_settings.py:27
|
||||
msgid "Enter Client Id and Client Secret in Google Settings to send calendar invites for evaluations."
|
||||
@@ -2690,7 +2690,7 @@ msgstr ""
|
||||
#: lms/lms/doctype/lms_badge/lms_badge.json
|
||||
#: lms/lms/doctype/lms_live_class/lms_live_class.json
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
msgstr "Dogodek"
|
||||
|
||||
#: frontend/src/pages/BatchForm.vue:116
|
||||
msgid "Example: IST (+5:30)"
|
||||
@@ -2705,17 +2705,17 @@ msgstr "Primer: IST (+5:30)"
|
||||
#: lms/lms/doctype/exercise_submission/exercise_submission.json
|
||||
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
|
||||
msgid "Exercise"
|
||||
msgstr ""
|
||||
msgstr "Vaja"
|
||||
|
||||
#. Name of a DocType
|
||||
#: lms/lms/doctype/exercise_latest_submission/exercise_latest_submission.json
|
||||
msgid "Exercise Latest Submission"
|
||||
msgstr ""
|
||||
msgstr "Vaja Najnovejša Oddaja"
|
||||
|
||||
#. Name of a DocType
|
||||
#: lms/lms/doctype/exercise_submission/exercise_submission.json
|
||||
msgid "Exercise Submission"
|
||||
msgstr ""
|
||||
msgstr "Oddaja Vaje"
|
||||
|
||||
#. Label of the exercise_title (Data) field in DocType 'Exercise Latest
|
||||
#. Submission'
|
||||
@@ -2726,11 +2726,11 @@ msgstr ""
|
||||
#: lms/lms/doctype/exercise_submission/exercise_submission.json
|
||||
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
|
||||
msgid "Exercise Title"
|
||||
msgstr ""
|
||||
msgstr "Naslov Vaje"
|
||||
|
||||
#: frontend/src/components/Sidebar/AppSidebar.vue:145
|
||||
msgid "Expand"
|
||||
msgstr ""
|
||||
msgstr "Razširi"
|
||||
|
||||
#. Label of the expected_output (Data) field in DocType 'LMS Test Case'
|
||||
#. Label of the expected_output (Data) field in DocType 'LMS Test Case
|
||||
@@ -2751,18 +2751,18 @@ msgstr ""
|
||||
#: frontend/src/components/Settings/Coupons/CouponList.vue:176
|
||||
#: lms/lms/doctype/lms_coupon/lms_coupon.json
|
||||
msgid "Expires On"
|
||||
msgstr ""
|
||||
msgstr "Poteče"
|
||||
|
||||
#. 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
|
||||
#: lms/lms/doctype/lms_certificate/lms_certificate.json
|
||||
msgid "Expiry Date"
|
||||
msgstr ""
|
||||
msgstr "Datum Poteka"
|
||||
|
||||
#: lms/lms/doctype/lms_coupon/lms_coupon.py:23
|
||||
msgid "Expiry date cannot be in the past"
|
||||
msgstr ""
|
||||
msgstr "Datum veljavnosti ne sme biti v preteklosti"
|
||||
|
||||
#. Label of the explanation_1 (Small Text) field in DocType 'LMS Question'
|
||||
#. Label of the explanation_3 (Small Text) field in DocType 'LMS Question'
|
||||
@@ -2770,17 +2770,17 @@ msgstr ""
|
||||
#: frontend/src/components/Modals/Question.vue:75
|
||||
#: lms/lms/doctype/lms_question/lms_question.json
|
||||
msgid "Explanation"
|
||||
msgstr ""
|
||||
msgstr "Razlaga"
|
||||
|
||||
#. Label of the explanation_2 (Small Text) field in DocType 'LMS Question'
|
||||
#: lms/lms/doctype/lms_question/lms_question.json
|
||||
msgid "Explanation "
|
||||
msgstr ""
|
||||
msgstr "Razlaga "
|
||||
|
||||
#: lms/lms/web_template/course_cards/course_cards.html:15
|
||||
#: lms/lms/web_template/recently_published_courses/recently_published_courses.html:16
|
||||
msgid "Explore More"
|
||||
msgstr ""
|
||||
msgstr "Razišči več"
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'LMS Assignment
|
||||
#. Submission'
|
||||
@@ -2790,7 +2790,7 @@ msgstr ""
|
||||
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
|
||||
#: lms/lms/doctype/lms_certificate_evaluation/lms_certificate_evaluation.json
|
||||
msgid "Fail"
|
||||
msgstr ""
|
||||
msgstr "Neuspeh"
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'LMS Programming Exercise
|
||||
#. Submission'
|
||||
@@ -2799,7 +2799,7 @@ msgstr ""
|
||||
#: lms/lms/doctype/lms_programming_exercise_submission/lms_programming_exercise_submission.json
|
||||
#: lms/lms/doctype/lms_test_case_submission/lms_test_case_submission.json
|
||||
msgid "Failed"
|
||||
msgstr ""
|
||||
msgstr "Neuspešno"
|
||||
|
||||
#: frontend/src/components/Settings/BadgeAssignmentForm.vue:136
|
||||
msgid "Failed to create badge assignment: "
|
||||
@@ -2835,7 +2835,7 @@ msgstr ""
|
||||
#: frontend/src/pages/CourseForm.vue:169
|
||||
#: lms/lms/doctype/lms_course/lms_course.json
|
||||
msgid "Featured"
|
||||
msgstr ""
|
||||
msgstr "Izabrano"
|
||||
|
||||
#. Label of the feedback (Small Text) field in DocType 'LMS Batch Feedback'
|
||||
#: frontend/src/components/BatchFeedback.vue:30
|
||||
@@ -2912,7 +2912,7 @@ msgstr ""
|
||||
|
||||
#: lms/lms/widgets/CourseCard.html:114
|
||||
msgid "Free"
|
||||
msgstr ""
|
||||
msgstr "Brezplačno"
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'Job Opportunity'
|
||||
#. Option in a Select field in the job-opportunity Web Form
|
||||
@@ -2920,35 +2920,35 @@ msgstr ""
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
#: lms/job/web_form/job_opportunity/job_opportunity.json
|
||||
msgid "Freelance"
|
||||
msgstr ""
|
||||
msgstr "Samostojni delavec"
|
||||
|
||||
#. Option for the 'User Category' (Select) field in DocType 'User'
|
||||
#: lms/fixtures/custom_field.json lms/templates/signup-form.html:27
|
||||
msgid "Freelancer/Just looking"
|
||||
msgstr ""
|
||||
msgstr "Samostojni delavec/Samo iščem"
|
||||
|
||||
#. Option for the 'Grade Type' (Select) field in DocType 'Education Detail'
|
||||
#: lms/lms/doctype/education_detail/education_detail.json
|
||||
msgid "French (e.g. Distinction)"
|
||||
msgstr ""
|
||||
msgstr "Francoščina (npr. Razlikovanje)"
|
||||
|
||||
#. Option for the 'Day' (Select) field in DocType 'Evaluator Schedule'
|
||||
#. Option for the 'Day' (Select) field in DocType 'LMS Certificate Request'
|
||||
#: lms/lms/doctype/evaluator_schedule/evaluator_schedule.json
|
||||
#: lms/lms/doctype/lms_certificate_request/lms_certificate_request.json
|
||||
msgid "Friday"
|
||||
msgstr ""
|
||||
msgstr "Petek"
|
||||
|
||||
#. Label of the unavailable_from (Date) field in DocType 'Course Evaluator'
|
||||
#: frontend/src/pages/ProfileEvaluator.vue:106
|
||||
#: lms/lms/doctype/course_evaluator/course_evaluator.json
|
||||
msgid "From"
|
||||
msgstr ""
|
||||
msgstr "Od"
|
||||
|
||||
#. Label of the from_date (Date) field in DocType 'Work Experience'
|
||||
#: lms/lms/doctype/work_experience/work_experience.json
|
||||
msgid "From Date"
|
||||
msgstr ""
|
||||
msgstr "Od datuma"
|
||||
|
||||
#. Label of the full_name (Data) field in DocType 'Course Evaluator'
|
||||
#. Label of the full_name (Data) field in DocType 'LMS Program Member'
|
||||
@@ -2957,7 +2957,7 @@ msgstr ""
|
||||
#: lms/lms/doctype/lms_program_member/lms_program_member.json
|
||||
#: lms/templates/signup-form.html:5
|
||||
msgid "Full Name"
|
||||
msgstr ""
|
||||
msgstr "Polno ime"
|
||||
|
||||
#. Option for the 'Type' (Select) field in DocType 'Job Opportunity'
|
||||
#. Option in a Select field in the job-opportunity Web Form
|
||||
@@ -2965,7 +2965,7 @@ msgstr ""
|
||||
#: lms/job/doctype/job_opportunity/job_opportunity.json
|
||||
#: lms/job/web_form/job_opportunity/job_opportunity.json
|
||||
msgid "Full Time"
|
||||
msgstr ""
|
||||
msgstr "Polni delovni čas"
|
||||
|
||||
#. Name of a DocType
|
||||
#. Label of the function (Data) field in DocType 'Function'
|
||||
@@ -2973,30 +2973,30 @@ msgstr ""
|
||||
#: lms/lms/doctype/function/function.json
|
||||
#: lms/lms/doctype/preferred_function/preferred_function.json
|
||||
msgid "Function"
|
||||
msgstr ""
|
||||
msgstr "Funkcija"
|
||||
|
||||
#: frontend/src/pages/Billing.vue:46
|
||||
msgid "GST Amount"
|
||||
msgstr ""
|
||||
msgstr "Znesek DDV"
|
||||
|
||||
#: frontend/src/pages/Billing.vue:145
|
||||
msgid "GST Number"
|
||||
msgstr ""
|
||||
msgstr "Številka DDV"
|
||||
|
||||
#. Label of the gstin (Data) field in DocType 'LMS Payment'
|
||||
#: frontend/src/components/Settings/Transactions/TransactionDetails.vue:107
|
||||
#: lms/lms/doctype/lms_payment/lms_payment.json
|
||||
msgid "GSTIN"
|
||||
msgstr ""
|
||||
msgstr "GSTIN"
|
||||
|
||||
#: frontend/src/components/Settings/PaymentGateways.vue:134
|
||||
msgid "Gateway"
|
||||
msgstr ""
|
||||
msgstr "Prehod"
|
||||
|
||||
#. Label of the general_tab (Tab Break) field in DocType 'LMS Settings'
|
||||
#: lms/lms/doctype/lms_settings/lms_settings.json
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
msgstr "Splošno"
|
||||
|
||||
#: frontend/src/components/Modals/BulkCertificates.vue:5
|
||||
#: frontend/src/pages/Batch.vue:12
|
||||
@@ -3348,7 +3348,7 @@ msgstr ""
|
||||
|
||||
#: frontend/src/components/InstallPrompt.vue:18
|
||||
msgid "Install"
|
||||
msgstr ""
|
||||
msgstr "Namesti"
|
||||
|
||||
#: frontend/src/components/InstallPrompt.vue:4
|
||||
#: frontend/src/components/InstallPrompt.vue:32
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% set onboarding_status = is_onboarding_complete() %}
|
||||
|
||||
{% if has_course_moderator_role() and not onboarding_status.is_onboarded %}
|
||||
{% if has_moderator_role() and not onboarding_status.is_onboarded %}
|
||||
<div class="onboarding-parent">
|
||||
<div class="container">
|
||||
<div class="onboarding-skip">{{ _("Skip") }}</div>
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/frappe/lms#readme",
|
||||
"devDependencies": {
|
||||
"cypress": "^14.5.2",
|
||||
"cypress": "^15.7.1",
|
||||
"cypress-file-upload": "^5.0.8",
|
||||
"cypress-real-events": "^1.14.0"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user