Merge pull request #2155 from pateljannat/issues-202

fix: misc issues
This commit is contained in:
Jannat Patel
2026-03-02 13:43:38 +05:30
committed by GitHub
9 changed files with 168 additions and 31 deletions

View File

@@ -10,7 +10,7 @@
{{ course.data.price }}
</div>
<div v-if="!readOnlyMode">
<div v-if="course.data.membership" class="space-y-2">
<div v-if="course.data.membership" class="space-y-2 mb-8">
<router-link
:to="{
name: 'Lesson',
@@ -46,7 +46,7 @@
},
}"
>
<Button variant="solid" size="md" class="w-full">
<Button variant="solid" size="md" class="w-full mb-8">
<template #prefix>
<CreditCard class="size-4 stroke-1.5" />
</template>
@@ -67,7 +67,7 @@
v-else-if="!isAdmin"
@click="enrollStudent()"
variant="solid"
class="w-full"
class="w-full mb-8"
size="md"
>
<template #prefix>
@@ -91,10 +91,7 @@
</Button>
</div>
<div class="space-y-4">
<div
class="font-medium text-ink-gray-9"
:class="{ 'mt-8': !readOnlyMode }"
>
<div class="font-medium text-ink-gray-9">
{{ __('This course has:') }}
</div>
<div class="flex items-center text-ink-gray-9">

View File

@@ -48,7 +48,7 @@ const apps = createResource({
name: 'frappe',
logo: '/assets/lms/images/desk.png',
title: __('Desk'),
route: '/desk/lms',
route: '/desk/learning',
},
]
data.map((app) => {

View File

@@ -164,7 +164,7 @@
:label="__('Preview Video')"
:placeholder="
__(
'Paste the youtube link of a short video introducing the course'
'Paste a YouTube link of a short video introducing the course'
)
"
@input="makeFormDirty()"

View File

@@ -694,7 +694,6 @@ export const escapeHTML = (text) => {
'"': '&quot;',
"'": '&#39;',
'`': '&#x60;',
'=': '&#x3D;',
}
return String(text).replace(
@@ -707,6 +706,19 @@ export const sanitizeHTML = (text) => {
text = DOMPurify.sanitize(decodeEntities(text), {
ALLOWED_TAGS: [
'b',
'br',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'table',
'thead',
'tbody',
'tr',
'th',
'td',
'i',
'em',
'strong',
@@ -717,6 +729,7 @@ export const sanitizeHTML = (text) => {
'ol',
'li',
'img',
'blockquote',
],
ALLOWED_ATTR: ['href', 'target', 'src'],
})

View File

@@ -164,7 +164,8 @@ def is_certified(course):
@frappe.whitelist()
def create_certificate(course: str):
if is_certified(course):
certificate = is_certified(course)
if certificate:
return frappe.db.get_value(
"LMS Certificate", certificate, ["name", "course", "template"], as_dict=True
)

View File

@@ -16,7 +16,7 @@ frappe.ui.form.on("LMS Certificate Request", {
frappe.call({
method: "lms.lms.doctype.lms_certificate_request.lms_certificate_request.setup_calendar_event",
args: {
eval: frm.doc,
eval_name: frm.doc.name,
},
});
});

View File

@@ -161,16 +161,20 @@ def schedule_evals():
},
["name", "member", "member_name", "evaluator", "date", "start_time", "end_time"],
)
for eval in evals:
setup_calendar_event(eval)
for evaluation in evals:
setup_calendar_event(evaluation.name)
@frappe.whitelist()
def setup_calendar_event(eval: str):
if isinstance(eval, str):
eval = frappe._dict(json.loads(eval))
def setup_calendar_event(eval_name: str):
evaluation = frappe.db.get_value(
"LMS Certificate Request",
eval_name,
["name", "member", "member_name", "evaluator", "date", "start_time", "end_time"],
as_dict=1,
)
is_member = eval.member == frappe.session.user
is_member = evaluation.member == frappe.session.user
roles = frappe.get_roles(frappe.session.user)
is_admin = "Moderator" in roles or "Batch Evaluator" in roles
@@ -180,29 +184,31 @@ def setup_calendar_event(eval: str):
frappe.PermissionError,
)
calendar = frappe.db.get_value("Google Calendar", {"user": eval.evaluator, "enable": 1}, "name")
calendar = frappe.db.get_value("Google Calendar", {"user": evaluation.evaluator, "enable": 1}, "name")
if calendar:
event = create_event(eval)
add_participants(eval, event)
update_meeting_details(eval, event, calendar)
event = create_event(evaluation)
add_participants(evaluation, event)
update_meeting_details(evaluation, event, calendar)
def create_event(eval: dict):
def create_event(evaluation: dict):
event = frappe.get_doc(
{
"doctype": "Event",
"subject": f"Evaluation of {eval.member_name}",
"starts_on": f"{eval.date} {eval.start_time}",
"ends_on": f"{eval.date} {eval.end_time}",
"subject": f"Evaluation of {evaluation.member_name}",
"starts_on": f"{evaluation.date} {evaluation.start_time}",
"ends_on": f"{evaluation.date} {evaluation.end_time}",
"reference_doctype": "LMS Certificate Request",
"reference_docname": evaluation.name,
}
)
event.save()
return event
def add_participants(eval: dict, event: Document):
participants = [eval.member, eval.evaluator]
def add_participants(evaluation: dict, event: Document):
participants = [evaluation.member, evaluation.evaluator]
for participant in participants:
contact_name = frappe.db.get_value("Contact", {"email_id": participant}, "name")
frappe.get_doc(
@@ -218,7 +224,7 @@ def add_participants(eval: dict, event: Document):
).save()
def update_meeting_details(eval: dict, event: Document, calendar: str):
def update_meeting_details(evaluation: dict, event: Document, calendar: str):
event.reload()
event.update(
{
@@ -230,7 +236,9 @@ def update_meeting_details(eval: dict, event: Document, calendar: str):
event.save()
event.reload()
frappe.db.set_value("LMS Certificate Request", eval.name, "google_meet_link", event.google_meet_link)
frappe.db.set_value(
"LMS Certificate Request", evaluation.name, "google_meet_link", event.google_meet_link
)
@frappe.whitelist()

View File

@@ -47,7 +47,9 @@ class LMSCourse(Document):
).save(ignore_permissions=True)
def validate_video_link(self):
if self.video_link and "/" in self.video_link:
if self.video_link and "watch?v=" in self.video_link:
self.video_link = self.video_link.split("watch?v=")[-1]
elif self.video_link and "/" in self.video_link:
self.video_link = self.video_link.split("/")[-1]
def validate_status(self):

View File

@@ -0,0 +1,116 @@
{
"app": "lms",
"creation": "2025-11-24 14:35:18.461657",
"docstatus": 0,
"doctype": "Workspace Sidebar",
"header_icon": "education",
"idx": 0,
"items": [
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Home",
"link_to": "Learning",
"link_type": "Workspace",
"show_arrow": 0,
"type": "Link"
},
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Users",
"link_to": "User",
"link_type": "DocType",
"show_arrow": 0,
"type": "Link"
},
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Course",
"link_to": "LMS Course",
"link_type": "DocType",
"show_arrow": 0,
"type": "Link"
},
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Enrollments",
"link_to": "LMS Enrollment",
"link_type": "DocType",
"show_arrow": 0,
"type": "Link"
},
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Batch",
"link_to": "LMS Batch",
"link_type": "DocType",
"show_arrow": 0,
"type": "Link"
},
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Batch Enrollment",
"link_to": "LMS Batch Enrollment",
"link_type": "DocType",
"show_arrow": 0,
"type": "Link"
},
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Evaluation Request",
"link_to": "LMS Certificate Request",
"link_type": "DocType",
"show_arrow": 0,
"type": "Link"
},
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Evaluation",
"link_to": "LMS Certificate Evaluation",
"link_type": "DocType",
"show_arrow": 0,
"type": "Link"
},
{
"child": 0,
"collapsible": 1,
"indent": 0,
"keep_closed": 0,
"label": "Certificate",
"link_to": "LMS Certificate",
"link_type": "DocType",
"show_arrow": 0,
"type": "Link"
}
],
"modified": "2026-03-02 13:07:37.040316",
"modified_by": "sayali@frappe.io",
"module": "LMS",
"name": "LMS",
"owner": "Administrator",
"standard": 1,
"title": "LMS"
}