fix: pre commit issues

This commit is contained in:
Jannat Patel
2022-11-04 11:47:09 +05:30
parent cda26ab248
commit 603eddf878
210 changed files with 10725 additions and 6733 deletions

View File

@@ -1,4 +1 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
__version__ = '0.0.1'
__version__ = "0.0.1"

View File

@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from frappe import _
def get_data():
return [
{
@@ -9,6 +8,6 @@ def get_data():
"color": "grey",
"icon": "octicon octicon-file-directory",
"type": "module",
"label": _("Community")
"label": _("Community"),
}
]

View File

@@ -7,5 +7,6 @@ Configuration for docs
# headline = "App that does everything"
# sub_heading = "Yes, you got that right the first time, everything"
def get_context(context):
context.brand_html = "Community"

View File

@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from . import __version__ as app_version
app_name = "frappe_lms"
@@ -88,7 +86,7 @@ after_uninstall = "lms.install.after_uninstall"
override_doctype_class = {
"User": "lms.overrides.user.CustomUser",
"Web Template": "lms.overrides.web_template.CustomWebTemplate"
"Web Template": "lms.overrides.web_template.CustomWebTemplate",
}
# Document Events
@@ -96,18 +94,16 @@ override_doctype_class = {
# Hook on document methods and events
doc_events = {
"Discussion Reply": {
"after_insert": "lms.lms.utils.create_notification_log"
}
"Discussion Reply": {"after_insert": "lms.lms.utils.create_notification_log"}
}
# Scheduled Tasks
# ---------------
#scheduler_events = {
# scheduler_events = {
# "daily": [
# "erpnext.stock.reorder_item.reorder_item"
# ]
#}
# }
fixtures = ["Custom Field", "Function", "Industry"]
@@ -140,19 +136,34 @@ website_route_rules = [
{"from_route": "/courses/<course>", "to_route": "courses/course"},
{"from_route": "/courses/<course>/<certificate>", "to_route": "courses/certificate"},
{"from_route": "/courses/<course>/learn", "to_route": "batch/learn"},
{"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>", "to_route": "batch/learn"},
{
"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>",
"to_route": "batch/learn",
},
{"from_route": "/quizzes", "to_route": "batch/quiz_list"},
{"from_route": "/quizzes/<quizname>", "to_route": "batch/quiz"},
{"from_route": "/courses/<course>/progress", "to_route": "batch/progress"},
{"from_route": "/courses/<course>/join", "to_route": "batch/join"},
{"from_route": "/courses/<course>/manage", "to_route": "cohorts"},
{"from_route": "/courses/<course>/cohorts/<cohort>", "to_route": "cohorts/cohort"},
{"from_route": "/courses/<course>/cohorts/<cohort>/<page>", "to_route": "cohorts/cohort"},
{"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>", "to_route": "cohorts/subgroup"},
{"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>/<page>", "to_route": "cohorts/subgroup"},
{"from_route": "/courses/<course>/join/<cohort>/<subgroup>/<invite_code>", "to_route": "cohorts/join"},
{
"from_route": "/courses/<course>/cohorts/<cohort>/<page>",
"to_route": "cohorts/cohort",
},
{
"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>",
"to_route": "cohorts/subgroup",
},
{
"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>/<page>",
"to_route": "cohorts/subgroup",
},
{
"from_route": "/courses/<course>/join/<cohort>/<subgroup>/<invite_code>",
"to_route": "cohorts/join",
},
{"from_route": "/users", "to_route": "profiles/profile"},
{"from_route": "/jobs/<job>", "to_route": "jobs/job"}
{"from_route": "/jobs/<job>", "to_route": "jobs/job"},
]
website_redirects = [
@@ -161,7 +172,7 @@ website_redirects = [
]
update_website_context = [
'lms.widgets.update_website_context',
"lms.widgets.update_website_context",
]
jinja = {
@@ -206,9 +217,9 @@ jinja = {
"lms.lms.utils.get_all_memberships",
"lms.lms.utils.get_filtered_membership",
"lms.lms.utils.show_start_learing_cta",
"lms.lms.utils.can_create_courses"
"lms.lms.utils.can_create_courses",
],
"filters": []
"filters": [],
}
## Specify the additional tabs to be included in the user profile page.
## Each entry must be a subclass of lms.lms.plugins.ProfileTab
@@ -219,9 +230,9 @@ jinja = {
## subclass of lms.plugins.PageExtension
# lms_lesson_page_extension = None
#lms_lesson_page_extensions = [
# lms_lesson_page_extensions = [
# "lms.plugins.LiveCodeExtension"
#]
# ]
profile_mandatory_fields = [
"first_name",
@@ -239,7 +250,7 @@ profile_mandatory_fields = [
"role",
"location_preference",
"time",
"company_type"
"company_type",
]
## Markdown Macros for Lessons
@@ -248,13 +259,13 @@ lms_markdown_macro_renderers = {
"Quiz": "lms.plugins.quiz_renderer",
"YouTubeVideo": "lms.plugins.youtube_video_renderer",
"Video": "lms.plugins.video_renderer",
"Assignment": "lms.plugins.assignment_renderer"
"Assignment": "lms.plugins.assignment_renderer",
}
# page_renderer to manage profile pages
page_renderer = [
"lms.page_renderers.ProfileRedirectPage",
"lms.page_renderers.ProfilePage"
"lms.page_renderers.ProfilePage",
]
# set this to "/" to have profiles on the top-level

View File

@@ -23,36 +23,69 @@ def set_default_home():
def create_instructor_role():
if not frappe.db.exists("Role", "Course Instructor"):
role = frappe.get_doc({
role = frappe.get_doc(
{
"doctype": "Role",
"role_name": "Course Instructor",
"home_page": "",
"desk_access": 0
})
"desk_access": 0,
}
)
role.save(ignore_permissions=True)
def create_moderator_role():
if not frappe.db.exists("Role", "Course Moderator"):
role = frappe.get_doc({
role = frappe.get_doc(
{
"doctype": "Role",
"role_name": "Course Moderator",
"home_page": "",
"desk_access": 0
})
"desk_access": 0,
}
)
role.save(ignore_permissions=True)
def delete_custom_fields():
fields = [ "user_category", "headline", "college", "city", "verify_terms", "country",
"preferred_location", "preferred_functions", "preferred_industries",
"work_environment_column", "time", "role", "carrer_preference_details",
"skill", "certification_details", "internship", "branch", "github",
"medium", "linkedin", "profession", "looking_for_job", "cover_image"
"work_environment", "dream_companies", "career_preference_column",
"attire", "collaboration", "location_preference", "company_type",
"skill_details", "certification", "education", "work_experience",
"education_details", "hide_private", "work_experience_details", "profile_complete"
fields = [
"user_category",
"headline",
"college",
"city",
"verify_terms",
"country",
"preferred_location",
"preferred_functions",
"preferred_industries",
"work_environment_column",
"time",
"role",
"carrer_preference_details",
"skill",
"certification_details",
"internship",
"branch",
"github",
"medium",
"linkedin",
"profession",
"looking_for_job",
"cover_image" "work_environment",
"dream_companies",
"career_preference_column",
"attire",
"collaboration",
"location_preference",
"company_type",
"skill_details",
"certification",
"education",
"work_experience",
"education_details",
"hide_private",
"work_experience_details",
"profile_complete",
]
for field in fields:

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Job Opportunity', {
frappe.ui.form.on("Job Opportunity", {
// refresh: function(frm) {
// }
});

View File

@@ -2,20 +2,19 @@
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
from frappe.utils.user import get_system_managers
from frappe import _
from frappe.model.document import Document
from frappe.utils import get_link_to_form
from frappe.utils.user import get_system_managers
from lms.lms.utils import validate_image
class JobOpportunity(Document):
def validate(self):
self.validate_urls()
self.company_logo = validate_image(self.company_logo)
def validate_urls(self):
frappe.utils.validate_url(self.company_website, True)
frappe.utils.validate_url(self.application_link, True)
@@ -30,12 +29,13 @@ def report(job, reason):
"job": job,
"job_url": get_link_to_form("Job Opportunity", job),
"user": user,
"reason": reason
"reason": reason,
}
frappe.sendmail(
recipients = system_managers,
recipients=system_managers,
subject=subject,
header=[subject, "green"],
template = "job_report",
template="job_report",
args=args,
now=True)
now=True,
)

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestJobOpportunity(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2022, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Job Settings', {
frappe.ui.form.on("Job Settings", {
// refresh: function(frm) {
// }
});

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class JobSettings(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestJobSettings(unittest.TestCase):
pass

View File

@@ -1,5 +1,6 @@
import frappe
def get_context(context):
# do your magic here
pass

View File

@@ -1,7 +1,7 @@
frappe.ready(function() {
frappe.ready(function () {
frappe.web_form.after_save = () => {
setTimeout(() => {
window.location.href = `/jobs`;
})
}
})
});
};
});

View File

@@ -1,5 +1,6 @@
import frappe
def get_context(context):
# do your magic here
pass

View File

@@ -3,18 +3,17 @@
import frappe
@frappe.whitelist()
def autosave_section(section, code):
"""Saves the code edited in one of the sections.
"""
"""Saves the code edited in one of the sections."""
doc = frappe.get_doc(
doctype="Code Revision",
section=section,
code=code,
author=frappe.session.user)
doctype="Code Revision", section=section, code=code, author=frappe.session.user
)
doc.insert()
return {"name": doc.name}
@frappe.whitelist()
def submit_solution(exercise, code):
"""Submits a solution.
@@ -28,17 +27,15 @@ def submit_solution(exercise, code):
doc = ex.submit(code)
return {"name": doc.name, "creation": doc.creation}
@frappe.whitelist()
def save_current_lesson(course_name, lesson_name):
"""Saves the current lesson for a student/mentor.
"""
"""Saves the current lesson for a student/mentor."""
name = frappe.get_value(
doctype="LMS Batch Membership",
filters={
"course": course_name,
"member": frappe.session.user
},
fieldname="name")
filters={"course": course_name, "member": frappe.session.user},
fieldname="name",
)
if not name:
return
doc = frappe.get_doc("LMS Batch Membership", name)
@@ -49,24 +46,20 @@ def save_current_lesson(course_name, lesson_name):
@frappe.whitelist()
def join_cohort(course, cohort, subgroup, invite_code):
"""Creates a Cohort Join Request for given user.
"""
"""Creates a Cohort Join Request for given user."""
course_doc = frappe.get_doc("LMS Course", course)
cohort_doc = course_doc and course_doc.get_cohort(cohort)
subgroup_doc = cohort_doc and cohort_doc.get_subgroup(subgroup)
if not subgroup_doc or subgroup_doc.invite_code != invite_code:
return {
"ok": False,
"error": "Invalid join link"
}
return {"ok": False, "error": "Invalid join link"}
data = {
"doctype": "Cohort Join Request",
"cohort": cohort_doc.name,
"subgroup": subgroup_doc.name,
"email": frappe.session.user,
"status": "Pending"
"status": "Pending",
}
# Don't insert duplicate records
if frappe.db.exists(data):
@@ -76,39 +69,33 @@ def join_cohort(course, cohort, subgroup, invite_code):
doc.insert(ignore_permissions=True)
return {"ok": True, "status": "record created"}
@frappe.whitelist()
def approve_cohort_join_request(join_request):
r = frappe.get_doc("Cohort Join Request", join_request)
sg = r and frappe.get_doc("Cohort Subgroup", r.subgroup)
if not sg or r.status not in ["Pending", "Accepted"]:
return {
"ok": False,
"error": "Invalid Join Request"
}
if not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles():
return {
"ok": False,
"error": "Permission Deined"
}
return {"ok": False, "error": "Invalid Join Request"}
if (
not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles()
):
return {"ok": False, "error": "Permission Deined"}
r.status = "Accepted"
r.save(ignore_permissions=True)
return {"ok": True}
@frappe.whitelist()
def reject_cohort_join_request(join_request):
r = frappe.get_doc("Cohort Join Request", join_request)
sg = r and frappe.get_doc("Cohort Subgroup", r.subgroup)
if not sg or r.status not in ["Pending", "Rejected"]:
return {
"ok": False,
"error": "Invalid Join Request"
}
if not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles():
return {
"ok": False,
"error": "Permission Deined"
}
return {"ok": False, "error": "Invalid Join Request"}
if (
not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles()
):
return {"ok": False, "error": "Permission Deined"}
r.status = "Rejected"
r.save(ignore_permissions=True)
@@ -121,43 +108,34 @@ def undo_reject_cohort_join_request(join_request):
sg = r and frappe.get_doc("Cohort Subgroup", r.subgroup)
# keeping Pending as well to consider the case of duplicate requests
if not sg or r.status not in ["Pending", "Rejected"]:
return {
"ok": False,
"error": "Invalid Join Request"
}
if not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles():
return {
"ok": False,
"error": "Permission Deined"
}
return {"ok": False, "error": "Invalid Join Request"}
if (
not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles()
):
return {"ok": False, "error": "Permission Deined"}
r.status = "Pending"
r.save(ignore_permissions=True)
return {"ok": True}
@frappe.whitelist()
def add_mentor_to_subgroup(subgroup, email):
try:
sg = frappe.get_doc("Cohort Subgroup", subgroup)
except frappe.DoesNotExistError:
return {
"ok": False,
"error": f"Invalid subgroup: {subgroup}"
}
return {"ok": False, "error": f"Invalid subgroup: {subgroup}"}
if not sg.get_cohort().is_admin(frappe.session.user) and "System Manager" not in frappe.get_roles():
return {
"ok": False,
"error": "Permission Deined"
}
if (
not sg.get_cohort().is_admin(frappe.session.user)
and "System Manager" not in frappe.get_roles()
):
return {"ok": False, "error": "Permission Deined"}
try:
user = frappe.get_doc("User", email)
except frappe.DoesNotExistError:
return {
"ok": False,
"error": f"Invalid user: {email}"
}
return {"ok": False, "error": f"Invalid user: {email}"}
sg.add_mentor(email)
return {"ok": True}

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Certification', {
frappe.ui.form.on("Certification", {
// refresh: function(frm) {
// }
});

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class Certification(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestCertification(unittest.TestCase):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class ChapterReference(Document):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cohort', {
frappe.ui.form.on("Cohort", {
// refresh: function(frm) {
// }
});

View File

@@ -4,6 +4,7 @@
import frappe
from frappe.model.document import Document
class Cohort(Document):
def get_url(self):
return f"{frappe.utils.get_url()}/courses/{self.course}/cohorts/{self.slug}"
@@ -27,11 +28,13 @@ class Cohort(Document):
return subgroups
def _get_subgroup_counts(self, doctype, **kw):
rows = frappe.get_all(doctype,
rows = frappe.get_all(
doctype,
filters={"cohort": self.name, **kw},
fields=['subgroup', 'count(*) as count'],
group_by='subgroup')
return {row['subgroup']: row['count'] for row in rows}
fields=["subgroup", "count(*) as count"],
group_by="subgroup",
)
return {row["subgroup"]: row["count"] for row in rows}
def _get_count(self, doctype, **kw):
filters = {"cohort": self.name, **kw}
@@ -68,18 +71,9 @@ class Cohort(Document):
return name and frappe.get_doc("Cohort Mentor", name)
def is_mentor(self, email):
q = {
"doctype": "Cohort Mentor",
"cohort": self.name,
"email": email
}
q = {"doctype": "Cohort Mentor", "cohort": self.name, "email": email}
return frappe.db.exists(q)
def is_admin(self, email):
q = {
"doctype": "Cohort Staff",
"cohort": self.name,
"email": email,
"role": "Admin"
}
q = {"doctype": "Cohort Staff", "cohort": self.name, "email": email, "role": "Admin"}
return frappe.db.exists(q)

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestCohort(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cohort Join Request', {
frappe.ui.form.on("Cohort Join Request", {
// refresh: function(frm) {
// }
});

View File

@@ -4,6 +4,7 @@
import frappe
from frappe.model.document import Document
class CohortJoinRequest(Document):
def on_update(self):
if self.status == "Accepted":
@@ -16,7 +17,7 @@ class CohortJoinRequest(Document):
"cohort": self.cohort,
"subgroup": self.subgroup,
"member": self.email,
"member_type": "Student"
"member_type": "Student",
}
if frappe.db.exists(q):
return
@@ -28,7 +29,7 @@ class CohortJoinRequest(Document):
"doctype": "LMS Batch Membership",
"course": cohort.course,
"member": self.email,
"member_type": "Student"
"member_type": "Student",
}
name = frappe.db.exists(q)
if name:
@@ -45,7 +46,7 @@ class CohortJoinRequest(Document):
"subgroup": self.subgroup,
"member": self.email,
"member_type": "Student",
"role": "Member"
"role": "Member",
}
doc = frappe.get_doc(data)
doc.insert(ignore_permissions=True)

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestCohortJoinRequest(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cohort Mentor', {
frappe.ui.form.on("Cohort Mentor", {
// refresh: function(frm) {
// }
});

View File

@@ -4,6 +4,7 @@
import frappe
from frappe.model.document import Document
class CohortMentor(Document):
def get_subgroup(self):
return frappe.get_doc("Cohort Subgroup", self.subgroup)

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestCohortMentor(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cohort Staff', {
frappe.ui.form.on("Cohort Staff", {
// refresh: function(frm) {
// }
});

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class CohortStaff(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestCohortStaff(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Cohort Subgroup', {
frappe.ui.form.on("Cohort Subgroup", {
// refresh: function(frm) {
// }
});

View File

@@ -5,6 +5,7 @@ import frappe
from frappe.model.document import Document
from frappe.utils import random_string
class CohortSubgroup(Document):
def before_save(self):
if not self.invite_code:
@@ -12,49 +13,44 @@ class CohortSubgroup(Document):
def get_url(self):
cohort = frappe.get_doc("Cohort", self.cohort)
return f"{frappe.utils.get_url()}/courses/{self.course}/subgroups/{cohort.slug}/{self.slug}"
return (
f"{frappe.utils.get_url()}/courses/{self.course}/subgroups/{cohort.slug}/{self.slug}"
)
def get_invite_link(self):
cohort = frappe.get_doc("Cohort", self.cohort)
return f"{frappe.utils.get_url()}/courses/{self.course}/join/{cohort.slug}/{self.slug}/{self.invite_code}"
def has_student(self, email):
"""Check if given user is a student of this subgroup.
"""
q = {
"doctype": "LMS Batch Membership",
"subgroup": self.name,
"member": email
}
"""Check if given user is a student of this subgroup."""
q = {"doctype": "LMS Batch Membership", "subgroup": self.name, "member": email}
return frappe.db.exists(q)
def has_join_request(self, email):
"""Check if given user is a student of this subgroup.
"""
q = {
"doctype": "Cohort Join Request",
"subgroup": self.name,
"email": email
}
"""Check if given user is a student of this subgroup."""
q = {"doctype": "Cohort Join Request", "subgroup": self.name, "email": email}
return frappe.db.exists(q)
def get_join_requests(self, status="Pending"):
q = {
"subgroup": self.name,
"status": status
}
return frappe.get_all("Cohort Join Request", filters=q, fields=["*"], order_by="creation desc")
q = {"subgroup": self.name, "status": status}
return frappe.get_all(
"Cohort Join Request", filters=q, fields=["*"], order_by="creation desc"
)
def get_mentors(self):
emails = frappe.get_all("Cohort Mentor", filters={"subgroup": self.name}, fields=["email"], pluck='email')
emails = frappe.get_all(
"Cohort Mentor", filters={"subgroup": self.name}, fields=["email"], pluck="email"
)
return self._get_users(emails)
def get_students(self):
emails = frappe.get_all("LMS Batch Membership",
emails = frappe.get_all(
"LMS Batch Membership",
filters={"subgroup": self.name},
fields=["member"],
pluck='member',
page_length=1000)
pluck="member",
page_length=1000,
)
return self._get_users(emails)
def _get_users(self, emails):
@@ -62,11 +58,7 @@ class CohortSubgroup(Document):
return sorted(users, key=lambda user: user.full_name)
def is_mentor(self, email):
q = {
"doctype": "Cohort Mentor",
"subgroup": self.name,
"email": email
}
q = {"doctype": "Cohort Mentor", "subgroup": self.name, "email": email}
return frappe.db.exists(q)
def is_manager(self, email):
@@ -84,12 +76,13 @@ class CohortSubgroup(Document):
"doctype": "Cohort Mentor",
"subgroup": self.name,
"cohort": self.cohort,
"email": email
"email": email,
}
if frappe.db.exists(d):
return
doc = frappe.get_doc(d)
doc.insert(ignore_permissions=True)
#def after_doctype_insert():
# def after_doctype_insert():
# frappe.db.add_unique("Cohort Subgroup", ("cohort", "slug"))

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestCohortSubgroup(unittest.TestCase):
pass

View File

@@ -4,6 +4,7 @@
import frappe
from frappe.model.document import Document
class CohortWebPage(Document):
def get_template_html(self):
return frappe.get_doc("Web Template", self.template).template

View File

@@ -1,14 +1,14 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Course Chapter', {
frappe.ui.form.on("Course Chapter", {
onload: function (frm) {
frm.set_query("lesson", "lessons", function () {
return {
filters: {
"chapter": frm.doc.name,
}
chapter: frm.doc.name,
},
};
});
}
},
});

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class CourseChapter(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestCourseChapter(unittest.TestCase):
pass

View File

@@ -1,14 +1,14 @@
// Copyright (c) 2022, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Course Evaluator', {
frappe.ui.form.on("Course Evaluator", {
onload: (frm) => {
frm.set_query('evaluator', function(doc) {
frm.set_query("evaluator", function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
ignore_user_type: 1,
},
};
});
}
},
});

View File

@@ -5,8 +5,8 @@ import frappe
from frappe import _
from frappe.model.document import Document
class CourseEvaluator(Document):
class CourseEvaluator(Document):
def validate(self):
self.validate_time_slots()
@@ -18,7 +18,9 @@ class CourseEvaluator(Document):
self.validate_overlaps(schedule)
def validate_overlaps(self, schedule):
same_day_slots = list(filter(lambda x: x.day == schedule.day and x.name != schedule.name , self.schedule))
same_day_slots = list(
filter(lambda x: x.day == schedule.day and x.name != schedule.name, self.schedule)
)
overlap = False
for slot in same_day_slots:
@@ -32,15 +34,20 @@ class CourseEvaluator(Document):
if overlap:
frappe.throw(_("Slot Times are overlapping for some schedules."))
@frappe.whitelist()
def get_schedule(course, date):
evaluator = frappe.db.get_value("LMS Course", course, "evaluator")
all_slots = frappe.get_all("Evaluator Schedule",
filters = { "parent": evaluator },
fields = ["day", "start_time", "end_time"])
booked_slots = frappe.get_all("LMS Certificate Request",
filters = {"evaluator": evaluator, "date": date},
fields = ["start_time"])
all_slots = frappe.get_all(
"Evaluator Schedule",
filters={"parent": evaluator},
fields=["day", "start_time", "end_time"],
)
booked_slots = frappe.get_all(
"LMS Certificate Request",
filters={"evaluator": evaluator, "date": date},
fields=["start_time"],
)
for slot in booked_slots:
same_slot = list(filter(lambda x: x.start_time == slot.start_time, all_slots))

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class CourseInstructor(Document):
pass

View File

@@ -1,17 +1,21 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Course Lesson', {
frappe.ui.form.on("Course Lesson", {
setup: function (frm) {
frm.trigger('setup_help');
frm.trigger("setup_help");
},
setup_help(frm) {
let quiz_link = `<a href="/app/lms-quiz"> ${__("Quiz List")} </a>`;
let exercise_link = `<a href="/app/exercise"> ${__("Exercise List")} </a>`;
let exercise_link = `<a href="/app/exercise"> ${__(
"Exercise List"
)} </a>`;
let file_link = `<a href="/app/file"> ${__("File DocType")} </a>`;
frm.get_field('help').html(`
<p>${__("You can add some more additional content to the lesson using a special syntax. The table below mentions all types of dynamic content that you can add to the lessons and the syntax for the same.")}</p>
frm.get_field("help").html(`
<p>${__(
"You can add some more additional content to the lesson using a special syntax. The table below mentions all types of dynamic content that you can add to the lessons and the syntax for the same."
)}</p>
<table class="table">
<tr style="background-color: var(--fg-hover-color); font-weight: bold">
<th style="width: 20%;">
@@ -33,17 +37,23 @@ frappe.ui.form.on('Course Lesson', {
</td>
<td>
<span>
${ __("Copy and paste the syntax in the editor. Replace 'embed_src' with the embed source that YouTube provides. To get the source, follow the steps mentioned below.") }
${__(
"Copy and paste the syntax in the editor. Replace 'embed_src' with the embed source that YouTube provides. To get the source, follow the steps mentioned below."
)}
</span>
<ul class="p-4">
<li>
${ __("Upload the video on youtube.") }
${__("Upload the video on youtube.")}
</li>
<li>
${ __("When you share a youtube video, it shows an option called Embed.") }
${__(
"When you share a youtube video, it shows an option called Embed."
)}
</li>
<li>
${ __("On clicking it, it provides an iframe. Copy the source (src) of the iframe and paste it here.") }
${__(
"On clicking it, it provides an iframe. Copy the source (src) of the iframe and paste it here."
)}
</li>
</ul>
</td>
@@ -56,7 +66,10 @@ frappe.ui.form.on('Course Lesson', {
{{ Quiz("lms_quiz_id") }}
</td>
<td>
${ __("Copy and paste the syntax in the editor. Replace 'lms_quiz_id' with the ID of the Quiz you want to add. You can get the ID of the quiz from the {0}.", [quiz_link]) }
${__(
"Copy and paste the syntax in the editor. Replace 'lms_quiz_id' with the ID of the Quiz you want to add. You can get the ID of the quiz from the {0}.",
[quiz_link]
)}
</td>
</tr>
<tr>
@@ -67,7 +80,10 @@ frappe.ui.form.on('Course Lesson', {
{{ Video("url_of_source") }}
</td>
<td>
${ __("Upload a video from your local machine to the {0}. Copy and paste this syntax in the editor. Replace 'url_of_source' with the File URL field of the document you created in the File DocType.", [file_link]) }
${__(
"Upload a video from your local machine to the {0}. Copy and paste this syntax in the editor. Replace 'url_of_source' with the File URL field of the document you created in the File DocType.",
[file_link]
)}
</td>
</tr>
<tr>
@@ -78,7 +94,10 @@ frappe.ui.form.on('Course Lesson', {
{{ Exercise("exercise_id") }}
</td>
<td>
${ __("Copy and paste the syntax in the editor. Replace 'exercise_id' with the ID of the Exercise you want to add. You can get the ID of the exercise from the {0}.", [exercise_link]) }
${__(
"Copy and paste the syntax in the editor. Replace 'exercise_id' with the ID of the Exercise you want to add. You can get the ID of the exercise from the {0}.",
[exercise_link]
)}
</td>
</tr>
<tr>
@@ -125,5 +144,5 @@ frappe.ui.form.on('Course Lesson', {
</tr>
</table>
`);
}
},
});

View File

@@ -1,37 +1,31 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from ...md import find_macros
from lms.lms.utils import get_course_progress, get_lesson_url
from ...md import find_macros
class CourseLesson(Document):
def validate(self):
#self.check_and_create_folder()
# self.check_and_create_folder()
self.validate_quiz_id()
def validate_quiz_id(self):
if self.quiz_id and not frappe.db.exists("LMS Quiz", self.quiz_id):
frappe.throw(_("Invalid Quiz ID"))
def on_update(self):
dynamic_documents = ["Exercise", "Quiz"]
for section in dynamic_documents:
self.update_lesson_name_in_document(section)
def update_lesson_name_in_document(self, section):
doctype_map= {
"Exercise": "Exercise",
"Quiz": "LMS Quiz"
}
doctype_map = {"Exercise": "Exercise", "Quiz": "LMS Quiz"}
macros = find_macros(self.body)
documents = [value for name, value in macros if name == section]
index = 1
@@ -43,12 +37,13 @@ class CourseLesson(Document):
index += 1
self.update_orphan_documents(doctype_map[section], documents)
def update_orphan_documents(self, doctype, documents):
"""Updates the documents that were previously part of this lesson,
but not any more.
"""
linked_documents = {row['name'] for row in frappe.get_all(doctype, {"lesson": self.name})}
linked_documents = {
row["name"] for row in frappe.get_all(doctype, {"lesson": self.name})
}
active_documents = set(documents)
orphan_documents = linked_documents - active_documents
for name in orphan_documents:
@@ -58,18 +53,16 @@ class CourseLesson(Document):
ex.index_label = ""
ex.save()
def check_and_create_folder(self):
args = {
"doctype": "File",
"is_folder": True,
"file_name": f"{self.name} {self.course}"
"file_name": f"{self.name} {self.course}",
}
if not frappe.db.exists(args):
folder = frappe.get_doc(args)
folder.save(ignore_permissions=True)
def get_exercises(self):
if not self.body:
return []
@@ -79,41 +72,42 @@ class CourseLesson(Document):
return [frappe.get_doc("Exercise", name) for name in exercises]
def get_progress(self):
return frappe.db.get_value("LMS Course Progress", {"lesson": self.name, "owner": frappe.session.user}, "status")
return frappe.db.get_value(
"LMS Course Progress", {"lesson": self.name, "owner": frappe.session.user}, "status"
)
def get_slugified_class(self):
if self.get_progress():
return ("").join([ s for s in self.get_progress().lower().split() ])
return ("").join([s for s in self.get_progress().lower().split()])
return
@frappe.whitelist()
def save_progress(lesson, course, status):
membership = frappe.db.exists("LMS Batch Membership", {
"member": frappe.session.user,
"course": course
})
membership = frappe.db.exists(
"LMS Batch Membership", {"member": frappe.session.user, "course": course}
)
if not membership:
return
if frappe.db.exists("LMS Course Progress", {
"lesson": lesson,
"owner": frappe.session.user,
"course": course
}):
doc = frappe.get_doc("LMS Course Progress", {
"lesson": lesson,
"owner": frappe.session.user,
"course": course
})
if frappe.db.exists(
"LMS Course Progress",
{"lesson": lesson, "owner": frappe.session.user, "course": course},
):
doc = frappe.get_doc(
"LMS Course Progress",
{"lesson": lesson, "owner": frappe.session.user, "course": course},
)
doc.status = status
doc.save(ignore_permissions=True)
else:
frappe.get_doc({
frappe.get_doc(
{
"doctype": "LMS Course Progress",
"lesson": lesson,
"status": status,
}).save(ignore_permissions=True)
}
).save(ignore_permissions=True)
progress = get_course_progress(course)
frappe.db.set_value("LMS Batch Membership", membership, "progress", progress)

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestCourseLesson(unittest.TestCase):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class EducationDetail(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class EvaluatorSchedule(Document):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Exercise', {
frappe.ui.form.on("Exercise", {
// refresh: function(frm) {
// }
});

View File

@@ -3,31 +3,30 @@
import frappe
from frappe.model.document import Document
from lms.lms.utils import get_membership
class Exercise(Document):
def get_user_submission(self):
"""Returns the latest submission for this user.
"""
"""Returns the latest submission for this user."""
user = frappe.session.user
if not user or user == "Guest":
return
result = frappe.get_all('Exercise Submission',
result = frappe.get_all(
"Exercise Submission",
fields="*",
filters={
"owner": user,
"exercise": self.name
},
filters={"owner": user, "exercise": self.name},
order_by="creation desc",
page_length=1)
page_length=1,
)
if result:
return result[0]
def submit(self, code):
"""Submits the given code as solution to exercise.
"""
"""Submits the given code as solution to exercise."""
user = frappe.session.user
if not user or user == "Guest":
return
@@ -46,8 +45,8 @@ class Exercise(Document):
lesson=self.lesson,
batch=member.batch,
solution=code,
member=member.name)
member=member.name,
)
doc.insert(ignore_permissions=True)
return doc

View File

@@ -1,31 +1,35 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
import frappe
import unittest
import frappe
from lms.lms.doctype.lms_course.test_lms_course import new_course
class TestExercise(unittest.TestCase):
class TestExercise(unittest.TestCase):
def new_exercise(self):
course = new_course("Test Course")
member = frappe.get_doc({
member = frappe.get_doc(
{
"doctype": "LMS Batch Membership",
"course": course.name,
"member": frappe.session.user
})
"member": frappe.session.user,
}
)
member.insert()
e = frappe.get_doc({
e = frappe.get_doc(
{
"doctype": "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)")
})
"answer": ("# draw a single circle\n" + "circle(100, 100, 50)"),
}
)
e.insert()
return e
@@ -45,6 +49,6 @@ class TestExercise(unittest.TestCase):
assert user_submission.name == submission.name
def tearDown(self):
frappe.db.sql('delete from `tabLMS Batch Membership`')
frappe.db.sql('delete from `tabExercise Submission`')
frappe.db.sql('delete from `tabExercise`')
frappe.db.sql("delete from `tabLMS Batch Membership`")
frappe.db.sql("delete from `tabExercise Submission`")
frappe.db.sql("delete from `tabExercise`")

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Exercise Latest Submission', {
frappe.ui.form.on("Exercise Latest Submission", {
// refresh: function(frm) {
// }
});

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class ExerciseLatestSubmission(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestExerciseLatestSubmission(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Exercise Submission', {
frappe.ui.form.on("Exercise Submission", {
// refresh: function(frm) {
// }
});

View File

@@ -4,21 +4,26 @@
import frappe
from frappe.model.document import Document
class ExerciseSubmission(Document):
def on_update(self):
self.update_latest_submission()
def update_latest_submission(self):
names = frappe.get_all("Exercise Latest Submission", {"exercise": self.exercise, "member": self.member})
names = frappe.get_all(
"Exercise Latest Submission", {"exercise": self.exercise, "member": self.member}
)
if names:
doc = frappe.get_doc("Exercise Latest Submission", names[0])
doc.latest_submission = self.name
doc.save(ignore_permissions=True)
else:
doc = frappe.get_doc({
doc = frappe.get_doc(
{
"doctype": "Exercise Latest Submission",
"exercise": self.exercise,
"member": self.member,
"latest_submission": self.name
})
"latest_submission": self.name,
}
)
doc.insert(ignore_permissions=True)

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestExerciseSubmission(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Function', {
frappe.ui.form.on("Function", {
// refresh: function(frm) {
// }
});

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class Function(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestFunction(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Industry', {
frappe.ui.form.on("Industry", {
// refresh: function(frm) {
// }
});

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class Industry(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestIndustry(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('Invite Request', {
frappe.ui.form.on("Invite Request", {
// refresh: function(frm) {
// }
});

View File

@@ -1,14 +1,14 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import json
import frappe
from frappe import _
from frappe.model.document import Document
import json
from frappe.utils.password import get_decrypted_password
class InviteRequest(Document):
def on_update(self):
if self.has_value_changed("status") and self.status == "Approved":
@@ -16,7 +16,8 @@ class InviteRequest(Document):
def create_user(self, password):
full_name_split = self.full_name.split(" ")
user = frappe.get_doc({
user = frappe.get_doc(
{
"doctype": "User",
"email": self.signup_email,
"first_name": full_name_split[0],
@@ -24,8 +25,9 @@ class InviteRequest(Document):
"username": self.username,
"send_welcome_email": 0,
"user_type": "Website User",
"new_password": password
})
"new_password": password,
}
)
user.save(ignore_permissions=True)
return user
@@ -35,17 +37,19 @@ class InviteRequest(Document):
args = {
"full_name": self.full_name,
"signup_form_link": "/new-sign-up?invite_code={0}".format(self.name),
"signup_form_link": f"/new-sign-up?invite_code={self.name}",
"site_name": site_name,
"site_url": frappe.utils.get_url()
"site_url": frappe.utils.get_url(),
}
frappe.sendmail(
recipients=self.invite_email,
subject=subject,
header=[subject, "green"],
template = "lms_invite_request_approved",
template="lms_invite_request_approved",
args=args,
now=True)
now=True,
)
@frappe.whitelist(allow_guest=True)
def create_invite_request(invite_email):
@@ -59,11 +63,9 @@ def create_invite_request(invite_email):
if frappe.db.exists("Invite Request", {"invite_email": invite_email}):
return "invite"
frappe.get_doc({
"doctype": "Invite Request",
"invite_email": invite_email,
"status": "Approved"
}).save(ignore_permissions=True)
frappe.get_doc(
{"doctype": "Invite Request", "invite_email": invite_email, "status": "Approved"}
).save(ignore_permissions=True)
return "OK"

View File

@@ -1,23 +1,26 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
from __future__ import unicode_literals
from lms.lms.doctype.invite_request.invite_request import create_invite_request, update_invite
import frappe
import unittest
class TestInviteRequest(unittest.TestCase):
import frappe
from lms.lms.doctype.invite_request.invite_request import (
create_invite_request, update_invite)
class TestInviteRequest(unittest.TestCase):
@classmethod
def setUpClass(self):
create_invite_request("test_invite@example.com")
def test_create_invite_request(self):
if frappe.db.exists("Invite Request", {"invite_email": "test_invite@example.com"}):
invite = frappe.db.get_value("Invite Request",
invite = frappe.db.get_value(
"Invite Request",
filters={"invite_email": "test_invite@example.com"},
fieldname=["invite_email", "status", "signup_email"],
as_dict=True)
as_dict=True,
)
self.assertEqual(invite.status, "Approved")
self.assertEqual(invite.signup_email, None)
@@ -29,23 +32,38 @@ class TestInviteRequest(unittest.TestCase):
"username": "test_invite",
"full_name": "Test Invite",
"password": "Test@invite",
"invite_code": frappe.db.get_value("Invite Request", {"invite_email": "test_invite@example.com"}, "name")
"invite_code": frappe.db.get_value(
"Invite Request", {"invite_email": "test_invite@example.com"}, "name"
),
}
update_invite(data)
invite = frappe.db.get_value("Invite Request",
invite = frappe.db.get_value(
"Invite Request",
filters={"invite_email": "test_invite@example.com"},
fieldname=["invite_email", "status", "signup_email", "full_name", "username", "invite_code", "name"],
as_dict=True)
fieldname=[
"invite_email",
"status",
"signup_email",
"full_name",
"username",
"invite_code",
"name",
],
as_dict=True,
)
self.assertEqual(invite.signup_email, "test_invite@example.com")
self.assertEqual(invite.full_name, "Test Invite")
self.assertEqual(invite.username, "test_invite")
self.assertEqual(invite.invite_code, invite.name)
self.assertEqual(invite.status, "Registered")
user = frappe.db.get_value("User", "test_invite@example.com",
user = frappe.db.get_value(
"User",
"test_invite@example.com",
fieldname=["first_name", "username", "send_welcome_email", "user_type"],
as_dict=True)
as_dict=True,
)
self.assertTrue(user)
self.assertEqual(user.first_name, invite.full_name.split(" ")[0])
self.assertEqual(user.username, invite.username)
@@ -57,6 +75,8 @@ class TestInviteRequest(unittest.TestCase):
if frappe.db.exists("User", "test_invite@example.com"):
frappe.delete_doc("User", "test_invite@example.com")
invite_request = frappe.db.exists("Invite Request", {"invite_email": "test_invite@example.com"})
invite_request = frappe.db.exists(
"Invite Request", {"invite_email": "test_invite@example.com"}
)
if invite_request:
frappe.delete_doc("Invite Request", invite_request)

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('Lesson Assignment', {
frappe.ui.form.on("Lesson Assignment", {
// refresh: function(frm) {
// }
});

View File

@@ -2,19 +2,24 @@
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
from frappe import _
from frappe.model.document import Document
class LessonAssignment(Document):
def validate(self):
self.validate_duplicates()
def validate_duplicates(self):
if frappe.db.exists("Lesson Assignment", {"lesson": self.lesson, "member": self.member}):
if frappe.db.exists(
"Lesson Assignment", {"lesson": self.lesson, "member": self.member}
):
lesson_title = frappe.db.get_value("Course Lesson", self.lesson, "title")
frappe.throw(_("Assignment for Lesson {0} by {1} already exists.").format(lesson_title, self.member_name))
frappe.throw(
_("Assignment for Lesson {0} by {1} already exists.").format(
lesson_title, self.member_name
)
)
@frappe.whitelist()
@@ -22,7 +27,7 @@ def upload_assignment(assignment, lesson):
args = {
"doctype": "Lesson Assignment",
"lesson": lesson,
"member": frappe.session.user
"member": frappe.session.user,
}
if frappe.db.exists(args):
del args["doctype"]
@@ -35,15 +40,13 @@ def upload_assignment(assignment, lesson):
@frappe.whitelist()
def get_assignment(lesson):
assignment = frappe.db.get_value("Lesson Assignment", {
"lesson": lesson,
"member": frappe.session.user
}, ["lesson", "member", "assignment"],
as_dict=True)
assignment.file_name = frappe.db.get_value("File", {"file_url": assignment.assignment}, "file_name")
assignment = frappe.db.get_value(
"Lesson Assignment",
{"lesson": lesson, "member": frappe.session.user},
["lesson", "member", "assignment"],
as_dict=True,
)
assignment.file_name = frappe.db.get_value(
"File", {"file_url": assignment.assignment}, "file_name"
)
return assignment

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestLessonAssignment(unittest.TestCase):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class LessonReference(Document):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Batch', {
frappe.ui.form.on("LMS Batch", {
// refresh: function(frm) {
// }
});

View File

@@ -1,18 +1,19 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
from lms.lms.doctype.lms_batch_membership.lms_batch_membership import create_membership
from frappe.model.document import Document
from lms.lms.doctype.lms_batch_membership.lms_batch_membership import \
create_membership
from lms.lms.utils import is_mentor
class LMSBatch(Document):
def validate(self):
pass
#self.validate_if_mentor()
# self.validate_if_mentor()
def validate_if_mentor(self):
if not is_mentor(self.course, frappe.session.user):
@@ -28,49 +29,44 @@ class LMSBatch(Document):
If member_type is specified, checks if the person is a Student/Mentor.
"""
filters = {
"batch": self.name,
"member": email
}
filters = {"batch": self.name, "member": email}
if member_type:
filters['member_type'] = member_type
filters["member_type"] = member_type
return frappe.db.exists("LMS Batch Membership", filters)
def get_membership(self, email):
"""Returns the membership document of given user.
"""
"""Returns the membership document of given user."""
name = frappe.get_value(
doctype="LMS Batch Membership",
filters={
"batch": self.name,
"member": email
},
fieldname="name")
filters={"batch": self.name, "member": email},
fieldname="name",
)
return frappe.get_doc("LMS Batch Membership", name)
def get_current_lesson(self, user):
"""Returns the name of the current lesson for the given user.
"""
"""Returns the name of the current lesson for the given user."""
membership = self.get_membership(user)
return membership and membership.current_lesson
@frappe.whitelist()
def save_message(message, batch):
doc = frappe.get_doc({
doc = frappe.get_doc(
{
"doctype": "LMS Message",
"batch": batch,
"author": frappe.session.user,
"message": message
})
"message": message,
}
)
doc.save(ignore_permissions=True)
def switch_batch(course_name, email, batch_name):
"""Switches the user from the current batch of the course to a new batch.
"""
"""Switches the user from the current batch of the course to a new batch."""
membership = frappe.get_last_doc(
"LMS Batch Membership",
filters={"course": course_name, "member": email})
"LMS Batch Membership", filters={"course": course_name, "member": email}
)
batch = frappe.get_doc("LMS Batch", batch_name)
if not batch:
@@ -90,11 +86,8 @@ def switch_batch(course_name, email, batch_name):
membership.save()
# update exercise submissions
filters = {
"owner": email,
"batch": old_batch.name
}
for name in frappe.db.get_all("Exercise Submission", filters=filters, pluck='name'):
filters = {"owner": email, "batch": old_batch.name}
for name in frappe.db.get_all("Exercise Submission", filters=filters, pluck="name"):
doc = frappe.get_doc("Exercise Submission", name)
print("updating exercise submission", name)
doc.batch = batch_name

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestLMSBatch(unittest.TestCase):
pass

View File

@@ -1,14 +1,14 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Batch Membership', {
onload: function(frm) {
frm.set_query('member', function(doc) {
frappe.ui.form.on("LMS Batch Membership", {
onload: function (frm) {
frm.set_query("member", function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
ignore_user_type: 1,
},
};
});
}
},
});

View File

@@ -1,39 +1,35 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
from frappe.model.document import Document
class LMSBatchMembership(Document):
def validate(self):
self.validate_membership_in_same_batch()
self.validate_membership_in_different_batch_same_course()
def validate_membership_in_same_batch(self):
filters={
"member": self.member,
"course": self.course,
"name": ["!=", self.name]
}
filters = {"member": self.member, "course": self.course, "name": ["!=", self.name]}
if self.batch:
filters["batch"] = self.batch
previous_membership = frappe.db.get_value("LMS Batch Membership",
filters,
fieldname=["member_type","member"],
as_dict=1)
previous_membership = frappe.db.get_value(
"LMS Batch Membership", filters, fieldname=["member_type", "member"], as_dict=1
)
if previous_membership:
member_name = frappe.db.get_value("User", self.member, "full_name")
course_title = frappe.db.get_value("LMS Course", self.course, "title")
frappe.throw(_("{0} is already a {1} of the course {2}").format(member_name, previous_membership.member_type, course_title))
frappe.throw(
_("{0} is already a {1} of the course {2}").format(
member_name, previous_membership.member_type, course_title
)
)
def validate_membership_in_different_batch_same_course(self):
"""Ensures that a studnet is only part of one batch.
"""
"""Ensures that a studnet is only part of one batch."""
# nothing to worry if the member is not a student
if self.member_type != "Student":
return
@@ -45,34 +41,50 @@ class LMSBatchMembership(Document):
"member": self.member,
"name": ["!=", self.name],
"member_type": "Student",
"course": self.course
"course": self.course,
},
fields=["batch", "member_type", "name"]
fields=["batch", "member_type", "name"],
)
if memberships:
membership = memberships[0]
member_name = frappe.db.get_value("User", self.member, "full_name")
frappe.throw(_("{0} is already a Student of {1} course through {2} batch").format(member_name, course, membership.batch))
frappe.throw(
_("{0} is already a Student of {1} course through {2} batch").format(
member_name, course, membership.batch
)
)
@frappe.whitelist()
def create_membership(course, batch=None, member=None, member_type="Student", role="Member"):
frappe.get_doc({
def create_membership(
course, batch=None, member=None, member_type="Student", role="Member"
):
frappe.get_doc(
{
"doctype": "LMS Batch Membership",
"batch": batch,
"course": course,
"role": role,
"member_type": member_type,
"member": member or frappe.session.user
}).save(ignore_permissions=True)
"member": member or frappe.session.user,
}
).save(ignore_permissions=True)
return "OK"
@frappe.whitelist()
def update_current_membership(batch, course, member):
all_memberships = frappe.get_all("LMS Batch Membership", {"member": member, "course": course})
all_memberships = frappe.get_all(
"LMS Batch Membership", {"member": member, "course": course}
)
for membership in all_memberships:
frappe.db.set_value("LMS Batch Membership", membership.name, "is_current", 0)
current_membership = frappe.get_all("LMS Batch Membership", {"batch": batch, "member": member})
current_membership = frappe.get_all(
"LMS Batch Membership", {"batch": batch, "member": member}
)
if len(current_membership):
frappe.db.set_value("LMS Batch Membership", current_membership[0].name, "is_current", 1)
frappe.db.set_value(
"LMS Batch Membership", current_membership[0].name, "is_current", 1
)

View File

@@ -1,17 +1,18 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
from __future__ import unicode_literals
import unittest
import frappe
import unittest
from lms.lms.doctype.lms_course.test_lms_course import new_user, new_course
from lms.lms.doctype.lms_course.test_lms_course import new_course, new_user
class TestLMSBatchMembership(unittest.TestCase):
def setUp(self):
frappe.db.sql("DELETE FROM `tabLMS Batch Membership`")
frappe.db.sql("DELETE FROM `tabLMS Batch`")
frappe.db.sql('delete from `tabLMS Course Mentor Mapping`')
frappe.db.sql("delete from `tabLMS Course Mentor Mapping`")
frappe.db.sql("DELETE FROM `tabUser` where email like '%@test.com'")
def new_course_batch(self):
@@ -23,24 +24,28 @@ class TestLMSBatchMembership(unittest.TestCase):
frappe.session.user = "mentor@test.com"
batch = frappe.get_doc({
batch = frappe.get_doc(
{
"doctype": "LMS Batch",
"name": "test-batch",
"title": "Test Batch",
"course": course.name
})
"course": course.name,
}
)
batch.insert(ignore_permissions=True)
frappe.session.user = "Administrator"
return course, batch
def add_membership(self, batch_name, member_name, member_type="Student"):
doc = frappe.get_doc({
doc = frappe.get_doc(
{
"doctype": "LMS Batch Membership",
"batch": batch_name,
"member": member_name,
"member_type": member_type
})
"member_type": member_type,
}
)
doc.insert()
return doc

View File

@@ -1,17 +1,21 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Certificate', {
frappe.ui.form.on("LMS Certificate", {
onload: (frm) => {
frm.set_query("member", function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
ignore_user_type: 1,
},
};
});
},
refresh: (frm) => {
if (frm.doc.name) frm.add_web_link(`/courses/${frm.doc.course}/${frm.doc.name}`, 'See on Website')
}
if (frm.doc.name)
frm.add_web_link(
`/courses/${frm.doc.course}/${frm.doc.name}`,
"See on Website"
);
},
});

View File

@@ -2,23 +2,26 @@
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
from frappe.utils import nowdate, add_years
from frappe import _
from frappe.model.document import Document
from frappe.utils import add_years, nowdate
from frappe.utils.pdf import get_pdf
from lms.lms.utils import is_certified
class LMSCertificate(Document):
class LMSCertificate(Document):
def before_insert(self):
certificates = frappe.get_all("LMS Certificate", {
"member": self.member,
"course": self.course
})
certificates = frappe.get_all(
"LMS Certificate", {"member": self.member, "course": self.course}
)
if len(certificates):
full_name = frappe.db.get_value("User", self.member, "full_name")
course_name = frappe.db.get_value("LMS Course", self.course, "title")
frappe.throw(_("{0} is already certified for the course {1}").format(full_name, course_name))
frappe.throw(
_("{0} is already certified for the course {1}").format(full_name, course_name)
)
@frappe.whitelist()
def create_certificate(course):
@@ -33,16 +36,19 @@ def create_certificate(course):
if expires_after_yrs:
expiry_date = add_years(nowdate(), expires_after_yrs)
certificate = frappe.get_doc({
certificate = frappe.get_doc(
{
"doctype": "LMS Certificate",
"member": frappe.session.user,
"course": course,
"issue_date": nowdate(),
"expiry_date": expiry_date
})
"expiry_date": expiry_date,
}
)
certificate.save(ignore_permissions=True)
return certificate
@frappe.whitelist()
def get_certificate_pdf(html):
frappe.local.response.filename = "certificate.pdf"

View File

@@ -1,19 +1,18 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
import frappe
import unittest
from lms.lms.doctype.lms_course.test_lms_course import new_course
import frappe
from frappe.utils import add_years, cint, nowdate
from lms.lms.doctype.lms_certificate.lms_certificate import create_certificate
from frappe.utils import nowdate, add_years, cint
from lms.lms.doctype.lms_course.test_lms_course import new_course
class TestLMSCertificate(unittest.TestCase):
def test_certificate_creation(self):
course = new_course("Test Certificate", {
"enable_certification": 1,
"expiry": 2
})
course = new_course("Test Certificate", {"enable_certification": 1, "expiry": 2})
certificate = create_certificate(course.name)
self.assertEqual(certificate.member, "Administrator")

View File

@@ -1,34 +1,34 @@
// Copyright (c) 2022, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Certificate Evaluation', {
refresh: function(frm) {
frappe.ui.form.on("LMS Certificate Evaluation", {
refresh: function (frm) {
if (frm.doc.status == "Pass") {
frm.add_custom_button(__("Create LMS Certificate"), () => {
frappe.model.open_mapped_doc({
method: "lms.lms.doctype.lms_certificate_evaluation.lms_certificate_evaluation.create_lms_certificate",
frm: frm
frm: frm,
});
});
}
},
onload: function(frm) {
frm.set_query("course", function(doc) {
onload: function (frm) {
frm.set_query("course", function (doc) {
return {
filters: {
"enable_certification": true,
"grant_certificate_after": "Evaluation"
}
enable_certification: true,
grant_certificate_after: "Evaluation",
},
};
});
frm.set_query('member', function(doc) {
frm.set_query("member", function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
ignore_user_type: 1,
},
};
});
}
},
});

View File

@@ -5,14 +5,17 @@ import frappe
from frappe.model.document import Document
from frappe.model.mapper import get_mapped_doc
class LMSCertificateEvaluation(Document):
pass
@frappe.whitelist()
def create_lms_certificate(source_name, target_doc=None):
doc = get_mapped_doc("LMS Certificate Evaluation", source_name, {
"LMS Certificate Evaluation": {
"doctype": "LMS Certificate"
}
}, target_doc)
doc = get_mapped_doc(
"LMS Certificate Evaluation",
source_name,
{"LMS Certificate Evaluation": {"doctype": "LMS Certificate"}},
target_doc,
)
return doc

View File

@@ -1,23 +1,23 @@
// Copyright (c) 2022, Frappe and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Certificate Request', {
refresh: function(frm) {
frappe.ui.form.on("LMS Certificate Request", {
refresh: function (frm) {
frm.add_custom_button(__("Create LMS Certificate Evaluation"), () => {
frappe.model.open_mapped_doc({
method: "lms.lms.doctype.lms_certificate_request.lms_certificate_request.create_lms_certificate_evaluation",
frm: frm
frm: frm,
});
});
},
onload: function(frm) {
frm.set_query('member', function(doc) {
onload: function (frm) {
frm.set_query("member", function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
ignore_user_type: 1,
},
};
});
}
},
});

View File

@@ -2,54 +2,61 @@
# For license information, please see license.txt
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.model.mapper import get_mapped_doc
from frappe import _
from frappe.utils import getdate, format_date, format_time
from frappe.utils import format_date, format_time, getdate
class LMSCertificateRequest(Document):
def validate(self):
self.validate_if_existing_requests()
def validate_if_existing_requests(self):
existing_requests = frappe.get_all("LMS Certificate Request", {
"member": self.member,
"course": self.course
}, ["date", "start_time", "course"])
existing_requests = frappe.get_all(
"LMS Certificate Request",
{"member": self.member, "course": self.course},
["date", "start_time", "course"],
)
for req in existing_requests:
if req.date == getdate(self.date) and getdate() <= getdate(self.date):
course_title = frappe.db.get_value("LMS Course", req.course, "title")
frappe.throw(_(f"You already have an evaluation on {format_date(req.date, 'medium')} at {format_time(req.start_time, 'short')} for the course {course_title}."))
frappe.throw(
_(
f"You already have an evaluation on {format_date(req.date, 'medium')} at {format_time(req.start_time, 'short')} for the course {course_title}."
)
)
@frappe.whitelist()
def create_certificate_request(course, date, day, start_time, end_time):
is_member = frappe.db.exists({
"doctype": "LMS Batch Membership",
"course": course,
"member": frappe.session.user
})
is_member = frappe.db.exists(
{"doctype": "LMS Batch Membership", "course": course, "member": frappe.session.user}
)
if not is_member:
return
frappe.get_doc({
frappe.get_doc(
{
"doctype": "LMS Certificate Request",
"course": course,
"member": frappe.session.user,
"date": date,
"day": day,
"start_time": start_time,
"end_time": end_time
}).save(ignore_permissions=True)
"end_time": end_time,
}
).save(ignore_permissions=True)
@frappe.whitelist()
def create_lms_certificate_evaluation(source_name, target_doc=None):
doc = get_mapped_doc("LMS Certificate Request", source_name, {
"LMS Certificate Request": {
"doctype": "LMS Certificate Evaluation"
}
}, target_doc)
doc = get_mapped_doc(
"LMS Certificate Request",
source_name,
{"LMS Certificate Request": {"doctype": "LMS Certificate Evaluation"}},
target_doc,
)
return doc

View File

@@ -1,33 +1,30 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Course', {
frappe.ui.form.on("LMS Course", {
onload: function (frm) {
frm.set_query("chapter", "chapters", function () {
return {
filters: {
"course": frm.doc.name,
}
course: frm.doc.name,
},
};
});
frm.set_query("instructor", "instructors", function () {
return {
filters: {
"ignore_user_type": 1,
}
ignore_user_type: 1,
},
};
});
frm.set_query("course", "related_courses", function () {
return {
filters: {
"published": true,
}
published: true,
},
};
});
}
},
});

View File

@@ -1,93 +1,89 @@
# Copyright (c) 2021, Frappe and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import json
import frappe
from frappe.model.document import Document
import json
from ...utils import generate_slug, validate_image
from frappe.utils import cint
from lms.lms.utils import get_chapters
from ...utils import generate_slug, validate_image
class LMSCourse(Document):
def validate(self):
self.validate_instructors()
self.validate_status()
self.image = validate_image(self.image)
def validate_instructors(self):
if self.is_new() and not self.instructors:
frappe.get_doc({
frappe.get_doc(
{
"doctype": "Course Instructor",
"instructor": self.owner,
"parent": self.name,
"parentfield": "instructors",
"parenttype": "LMS Course"
}).save(ignore_permissions=True)
"parenttype": "LMS Course",
}
).save(ignore_permissions=True)
def validate_status(self):
if self.published:
self.status = "Approved"
def on_update(self):
if not self.upcoming and self.has_value_changed("upcoming"):
self.send_email_to_interested_users()
def send_email_to_interested_users(self):
interested_users = frappe.get_all("LMS Course Interest", {
"course": self.name
},
["name", "user"])
interested_users = frappe.get_all(
"LMS Course Interest", {"course": self.name}, ["name", "user"]
)
subject = self.title + " is available!"
args = {
"title": self.title,
"course_link": "/courses/{0}".format(self.name),
"course_link": f"/courses/{self.name}",
"app_name": frappe.db.get_single_value("System Settings", "app_name"),
"site_url": frappe.utils.get_url()
"site_url": frappe.utils.get_url(),
}
for user in interested_users:
args["first_name"] = frappe.db.get_value("User", user.user, "first_name")
email_args = frappe._dict(
recipients = user.user,
subject = subject,
header = [subject, "green"],
template = "lms_course_interest",
args = args,
now = True)
frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, is_async=True, **email_args)
recipients=user.user,
subject=subject,
header=[subject, "green"],
template="lms_course_interest",
args=args,
now=True,
)
frappe.enqueue(
method=frappe.sendmail, queue="short", timeout=300, is_async=True, **email_args
)
frappe.db.set_value("LMS Course Interest", user.name, "email_sent", True)
def autoname(self):
if not self.name:
self.name = generate_slug(self.title, "LMS Course")
def __repr__(self):
return f"<Course#{self.name}>"
def has_mentor(self, email):
"""Checks if this course has a mentor with given email.
"""
"""Checks if this course has a mentor with given email."""
if not email or email == "Guest":
return False
mapping = frappe.get_all("LMS Course Mentor Mapping", {"course": self.name, "mentor": email})
mapping = frappe.get_all(
"LMS Course Mentor Mapping", {"course": self.name, "mentor": email}
)
return mapping != []
def add_mentor(self, email):
"""Adds a new mentor to the course.
"""
"""Adds a new mentor to the course."""
if not email:
raise ValueError("Invalid email")
if email == "Guest":
@@ -97,14 +93,11 @@ class LMSCourse(Document):
if self.has_mentor(email):
return
doc = frappe.get_doc({
"doctype": "LMS Course Mentor Mapping",
"course": self.name,
"mentor": email
})
doc = frappe.get_doc(
{"doctype": "LMS Course Mentor Mapping", "course": self.name, "mentor": email}
)
doc.insert()
def get_student_batch(self, email):
"""Returns the batch the given student is part of.
@@ -115,44 +108,37 @@ class LMSCourse(Document):
batch_name = frappe.get_value(
doctype="LMS Batch Membership",
filters={
"course": self.name,
"member_type": "Student",
"member": email
},
fieldname="batch")
filters={"course": self.name, "member_type": "Student", "member": email},
fieldname="batch",
)
return batch_name and frappe.get_doc("LMS Batch", batch_name)
def get_batches(self, mentor=None):
batches = frappe.get_all("LMS Batch", {"course": self.name})
if mentor:
# TODO: optimize this
memberships = frappe.db.get_all(
"LMS Batch Membership",
{"member": mentor},
["batch"])
"LMS Batch Membership", {"member": mentor}, ["batch"]
)
batch_names = {m.batch for m in memberships}
return [b for b in batches if b.name in batch_names]
def get_cohorts(self):
return frappe.get_all("Cohort",
return frappe.get_all(
"Cohort",
{"course": self.name},
["name", "slug", "title", "begin_date", "end_date"],
order_by="creation")
order_by="creation",
)
def get_cohort(self, cohort_slug):
name = frappe.get_value("Cohort", {"course": self.name, "slug": cohort_slug})
return name and frappe.get_doc("Cohort", name)
def reindex_exercises(self):
for i, c in enumerate(get_chapters(self.name), start=1):
self._reindex_exercises_in_chapter(c, i)
def _reindex_exercises_in_chapter(self, c, index):
i = 1
for lesson in self.get_lessons(c):
@@ -162,9 +148,10 @@ class LMSCourse(Document):
exercise.save()
i += 1
def get_all_memberships(self, member):
all_memberships = frappe.get_all("LMS Batch Membership", {"member": member, "course": self.name}, ["batch"])
all_memberships = frappe.get_all(
"LMS Batch Membership", {"member": member, "course": self.name}, ["batch"]
)
for membership in all_memberships:
membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title")
return all_memberships
@@ -173,7 +160,7 @@ class LMSCourse(Document):
@frappe.whitelist()
def reindex_exercises(doc):
course_data = json.loads(doc)
course = frappe.get_doc("LMS Course", course_data['name'])
course = frappe.get_doc("LMS Course", course_data["name"])
course.reindex_exercises()
frappe.msgprint("All exercises in this course have been re-indexed.")
@@ -181,16 +168,16 @@ def reindex_exercises(doc):
@frappe.whitelist(allow_guest=True)
def search_course(text):
search_courses = []
courses = frappe.get_all("LMS Course",
filters= {
"published": True
courses = frappe.get_all(
"LMS Course",
filters={"published": True},
or_filters={
"title": ["like", f"%{text}%"],
"tags": ["like", f"%{text}%"],
"short_introduction": ["like", f"%{text}%"],
"description": ["like", f"%{text}%"],
},
or_filters = {
"title": ["like", "%{0}%".format(text)],
"tags": ["like", "%{0}%".format(text)],
"short_introduction": ["like", "%{0}%".format(text)],
"description": ["like", "%{0}%".format(text)],
})
)
""" for course in courses:
search_courses.append(frappe.get_doc("LMS Course", course)) """
@@ -214,15 +201,24 @@ def submit_for_review(course):
@frappe.whitelist()
def save_course(tags, title, short_introduction, video_link, description, course, published, upcoming, image=None):
def save_course(
tags,
title,
short_introduction,
video_link,
description,
course,
published,
upcoming,
image=None,
):
if course:
doc = frappe.get_doc("LMS Course", course)
else:
doc = frappe.get_doc({
"doctype": "LMS Course"
})
doc = frappe.get_doc({"doctype": "LMS Course"})
doc.update({
doc.update(
{
"title": title,
"short_introduction": short_introduction,
"video_link": video_link,
@@ -230,8 +226,9 @@ def save_course(tags, title, short_introduction, video_link, description, course
"description": description,
"tags": tags,
"published": cint(published),
"upcoming": cint(upcoming)
})
"upcoming": cint(upcoming),
}
)
doc.save(ignore_permissions=True)
return doc.name
@@ -241,27 +238,23 @@ def save_chapter(course, title, chapter_description, idx, chapter):
if chapter:
doc = frappe.get_doc("Course Chapter", chapter)
else:
doc = frappe.get_doc({
"doctype": "Course Chapter"
})
doc = frappe.get_doc({"doctype": "Course Chapter"})
doc.update({
"course": course,
"title": title,
"description": chapter_description
})
doc.update({"course": course, "title": title, "description": chapter_description})
doc.save(ignore_permissions=True)
if chapter:
chapter_reference = frappe.get_doc("Chapter Reference", {"chapter": chapter})
else:
chapter_reference = frappe.get_doc({
chapter_reference = frappe.get_doc(
{
"doctype": "Chapter Reference",
"parent": course,
"parenttype": "LMS Course",
"parentfield": "chapters",
"idx": idx
})
"idx": idx,
}
)
chapter_reference.update({"chapter": doc.name})
chapter_reference.save(ignore_permissions=True)
@@ -270,15 +263,25 @@ def save_chapter(course, title, chapter_description, idx, chapter):
@frappe.whitelist()
def save_lesson(title, body, chapter, preview, idx, lesson, youtube=None, quiz_id=None, question=None, file_type=None):
def save_lesson(
title,
body,
chapter,
preview,
idx,
lesson,
youtube=None,
quiz_id=None,
question=None,
file_type=None,
):
if lesson:
doc = frappe.get_doc("Course Lesson", lesson)
else:
doc = frappe.get_doc({
"doctype": "Course Lesson"
})
doc = frappe.get_doc({"doctype": "Course Lesson"})
doc.update({
doc.update(
{
"chapter": chapter,
"title": title,
"body": body,
@@ -286,20 +289,23 @@ def save_lesson(title, body, chapter, preview, idx, lesson, youtube=None, quiz_i
"youtube": youtube,
"quiz_id": quiz_id,
"question": question,
"file_type": file_type
})
"file_type": file_type,
}
)
doc.save(ignore_permissions=True)
if lesson:
lesson_reference = frappe.get_doc("Lesson Reference", {"lesson": lesson})
else:
lesson_reference = frappe.get_doc({
lesson_reference = frappe.get_doc(
{
"doctype": "Lesson Reference",
"parent": chapter,
"parenttype": "Course Chapter",
"parentfield": "lessons",
"idx": idx
})
"idx": idx,
}
)
lesson_reference.update({"lesson": doc.name})
lesson_reference.save(ignore_permissions=True)

View File

@@ -1,22 +1,19 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
from __future__ import unicode_literals
import unittest
import frappe
from .lms_course import LMSCourse
import unittest
class TestLMSCourse(unittest.TestCase):
def test_new_course(self):
course = new_course("Test Course")
assert course.title == "Test Course"
assert course.name == "test-course"
# disabled this test as it is failing
def _test_add_mentors(self):
course = new_course("Test Course")
@@ -26,10 +23,11 @@ class TestLMSCourse(unittest.TestCase):
course.add_mentor("tester@example.com")
mentors = course.get_mentors()
mentors_data = [dict(email=mentor.email, batch_count=mentor.batch_count) for mentor in mentors]
mentors_data = [
dict(email=mentor.email, batch_count=mentor.batch_count) for mentor in mentors
]
assert mentors_data == [{"email": "tester@example.com", "batch_count": 0}]
def tearDown(self):
if frappe.db.exists("User", "tester@example.com"):
frappe.delete_doc("User", "tester@example.com")
@@ -42,7 +40,7 @@ class TestLMSCourse(unittest.TestCase):
frappe.db.delete("LMS Batch", {"course": "test-course"})
frappe.db.delete("LMS Course Mentor Mapping", {"course": "test-course"})
frappe.db.delete("Course Instructor", {"parent": "test-course"})
frappe.db.sql('delete from `tabCourse Instructor`')
frappe.db.sql("delete from `tabCourse Instructor`")
frappe.delete_doc("LMS Course", "test-course")
@@ -55,7 +53,7 @@ def new_user(name, email):
"doctype": "User",
"email": email,
"first_name": name,
"send_welcome_email": False
"send_welcome_email": False,
}
doc = frappe.get_doc(filters)
@@ -64,7 +62,7 @@ def new_user(name, email):
def new_course(title, additional_filters=None):
course = frappe.db.exists("LMS Course", { "title": title })
course = frappe.db.exists("LMS Course", {"title": title})
if course:
return frappe.get_doc("LMS Course", course)
else:
@@ -73,7 +71,7 @@ def new_course(title, additional_filters=None):
"doctype": "LMS Course",
"title": title,
"short_introduction": title,
"description": title
"description": title,
}
if additional_filters:
@@ -87,7 +85,6 @@ def new_course(title, additional_filters=None):
def create_evaluator():
if not frappe.db.exists("Course Evaluator", "evaluator@example.com"):
new_user("Evaluator", "evaluator@example.com")
frappe.get_doc({
"doctype": "Course Evaluator",
"evaluator": "evaluator@example.com"
}).save(ignore_permissions=True)
frappe.get_doc(
{"doctype": "Course Evaluator", "evaluator": "evaluator@example.com"}
).save(ignore_permissions=True)

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Course Enrollment', {
frappe.ui.form.on("LMS Course Enrollment", {
// refresh: function(frm) {
// }
});

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class LMSCourseEnrollment(Document):
pass

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestLMSCourseEnrollment(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Course Interest', {
frappe.ui.form.on("LMS Course Interest", {
// refresh: function(frm) {
// }
});

View File

@@ -4,15 +4,17 @@
import frappe
from frappe.model.document import Document
class LMSCourseInterest(Document):
pass
@frappe.whitelist()
def capture_interest(course):
data = {
"doctype": "LMS Course Interest",
"course": course,
"user": frappe.session.user
"user": frappe.session.user,
}
if not frappe.db.exists(data):
frappe.get_doc(data).save(ignore_permissions=True)

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestLMSCourseInterest(unittest.TestCase):
pass

View File

@@ -1,13 +1,13 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Course Mentor Mapping', {
onload: function(frm) {
frm.set_query('mentor', function(doc) {
frappe.ui.form.on("LMS Course Mentor Mapping", {
onload: function (frm) {
frm.set_query("mentor", function (doc) {
return {
filters: {
"ignore_user_type": 1,
}
ignore_user_type: 1,
},
};
});
},

View File

@@ -1,18 +1,17 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
from frappe.model.document import Document
class LMSCourseMentorMapping(Document):
def validate(self):
duplicate_mapping = frappe.get_all("LMS Course Mentor Mapping",
filters = {
"course": self.course,
"mentor": self.mentor
})
duplicate_mapping = frappe.get_all(
"LMS Course Mentor Mapping", filters={"course": self.course, "mentor": self.mentor}
)
if len(duplicate_mapping):
frappe.throw(_("{0} is already a mentor for course {1}").format(self.mentor_name, self.course))
frappe.throw(
_("{0} is already a mentor for course {1}").format(self.mentor_name, self.course)
)

View File

@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestLMSCourseMentorMapping(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Course Progress', {
frappe.ui.form.on("LMS Course Progress", {
// refresh: function(frm) {
// }
});

View File

@@ -4,5 +4,6 @@
# import frappe
from frappe.model.document import Document
class LMSCourseProgress(Document):
pass

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestLMSCourseProgress(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Course Review', {
frappe.ui.form.on("LMS Course Review", {
// refresh: function(frm) {
// }
});

View File

@@ -5,23 +5,19 @@ import frappe
from frappe.model.document import Document
from frappe.utils import cint
class LMSCourseReview(Document):
pass
@frappe.whitelist()
def submit_review(rating, review, course):
out_of_ratings = frappe.db.get_all("DocField",
{
"parent": "LMS Course Review",
"fieldtype": "Rating"
},
["options"])
out_of_ratings = frappe.db.get_all(
"DocField", {"parent": "LMS Course Review", "fieldtype": "Rating"}, ["options"]
)
out_of_ratings = (len(out_of_ratings) and out_of_ratings[0].options) or 5
rating = cint(rating)/out_of_ratings
frappe.get_doc({
"doctype": "LMS Course Review",
"rating": rating,
"review": review,
"course": course
}).save(ignore_permissions=True)
rating = cint(rating) / out_of_ratings
frappe.get_doc(
{"doctype": "LMS Course Review", "rating": rating, "review": review, "course": course}
).save(ignore_permissions=True)
return "OK"

View File

@@ -4,5 +4,6 @@
# import frappe
import unittest
class TestLMSCourseReview(unittest.TestCase):
pass

View File

@@ -1,8 +1,7 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Mentor Request', {
frappe.ui.form.on("LMS Mentor Request", {
// refresh: function(frm) {
// }
});

Some files were not shown because too many files have changed in this diff Show More