Compare commits
20 Commits
ui-fixes
...
switch-bat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94b3ccd3d9 | ||
|
|
4c3645f0d4 | ||
|
|
20b3ae7d76 | ||
|
|
f303be4db5 | ||
|
|
fc1c393f15 | ||
|
|
5abfa35095 | ||
|
|
6c751cdf39 | ||
|
|
2c570ea214 | ||
|
|
ecfcc8a2f7 | ||
|
|
3384f974e5 | ||
|
|
eb435261fe | ||
|
|
dc7eabefb9 | ||
|
|
fed4b5568b | ||
|
|
aa77c60abd | ||
|
|
9c1506d3c8 | ||
|
|
e94c3f27ab | ||
|
|
526ded784b | ||
|
|
6b5ddcd54a | ||
|
|
c42247db42 | ||
|
|
8f8d4901ff |
@@ -165,6 +165,7 @@ whitelist = [
|
|||||||
"/add-a-new-batch",
|
"/add-a-new-batch",
|
||||||
"/new-sign-up",
|
"/new-sign-up",
|
||||||
"/message"
|
"/message"
|
||||||
|
"/about"
|
||||||
]
|
]
|
||||||
whitelist_rules = [{"from_route": p, "to_route": p[1:]} for p in whitelist]
|
whitelist_rules = [{"from_route": p, "to_route": p[1:]} for p in whitelist]
|
||||||
|
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ def submit_solution(exercise, code):
|
|||||||
return {"name": doc.name, "creation": doc.creation}
|
return {"name": doc.name, "creation": doc.creation}
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def save_current_lesson(batch_name, lesson_name):
|
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(
|
name = frappe.get_value(
|
||||||
doctype="LMS Batch Membership",
|
doctype="LMS Batch Membership",
|
||||||
filters={
|
filters={
|
||||||
"batch": batch_name,
|
"course": course_name,
|
||||||
"member": frappe.session.user
|
"member": frappe.session.user
|
||||||
},
|
},
|
||||||
fieldname="name")
|
fieldname="name")
|
||||||
|
|||||||
@@ -3,12 +3,9 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from ..lms_sketch.livecode import livecode_to_svg
|
# from ..lms_sketch.livecode import livecode_to_svg
|
||||||
|
|
||||||
class Exercise(Document):
|
class Exercise(Document):
|
||||||
def before_save(self):
|
|
||||||
self.image = livecode_to_svg(None, self.answer)
|
|
||||||
|
|
||||||
def get_user_submission(self):
|
def get_user_submission(self):
|
||||||
"""Returns the latest submission for this user.
|
"""Returns the latest submission for this user.
|
||||||
"""
|
"""
|
||||||
@@ -42,8 +39,6 @@ class Exercise(Document):
|
|||||||
course = frappe.get_doc("LMS Course", self.course)
|
course = frappe.get_doc("LMS Course", self.course)
|
||||||
batch = course.get_student_batch(user)
|
batch = course.get_student_batch(user)
|
||||||
|
|
||||||
image = livecode_to_svg(None, code)
|
|
||||||
|
|
||||||
doc = frappe.get_doc(
|
doc = frappe.get_doc(
|
||||||
doctype="Exercise Submission",
|
doctype="Exercise Submission",
|
||||||
exercise=self.name,
|
exercise=self.name,
|
||||||
@@ -51,7 +46,6 @@ class Exercise(Document):
|
|||||||
course=self.course,
|
course=self.course,
|
||||||
lesson=self.lesson,
|
lesson=self.lesson,
|
||||||
batch=batch and batch.name,
|
batch=batch and batch.name,
|
||||||
image=image,
|
|
||||||
solution=code)
|
solution=code)
|
||||||
doc.insert(ignore_permissions=True)
|
doc.insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ class Lesson(Document):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def save_progress(lesson, batch):
|
def save_progress(lesson, course):
|
||||||
if not frappe.db.exists("LMS Batch Membership",
|
if not frappe.db.exists("LMS Batch Membership",
|
||||||
{
|
{
|
||||||
"member": frappe.session.user,
|
"member": frappe.session.user,
|
||||||
"batch": batch
|
"course": course
|
||||||
}):
|
}):
|
||||||
return
|
return
|
||||||
if frappe.db.exists("LMS Course Progress",
|
if frappe.db.exists("LMS Course Progress",
|
||||||
|
|||||||
@@ -33,8 +33,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "title",
|
"fieldname": "title",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Title",
|
"label": "Title"
|
||||||
"unique": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "description",
|
"fieldname": "description",
|
||||||
@@ -120,7 +119,7 @@
|
|||||||
"link_fieldname": "batch"
|
"link_fieldname": "batch"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2021-05-26 16:43:57.399747",
|
"modified": "2021-06-16 10:51:05.403726",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Batch",
|
"name": "LMS Batch",
|
||||||
|
|||||||
@@ -19,15 +19,7 @@ class LMSBatch(Document):
|
|||||||
frappe.throw(_("You are not a mentor of the course {0}").format(course.title))
|
frappe.throw(_("You are not a mentor of the course {0}").format(course.title))
|
||||||
|
|
||||||
def after_insert(self):
|
def after_insert(self):
|
||||||
create_membership(batch=self.name, member_type="Mentor")
|
create_membership(batch=self.name, course=self.course, member_type="Mentor")
|
||||||
|
|
||||||
def get_mentors(self):
|
|
||||||
memberships = frappe.get_all(
|
|
||||||
"LMS Batch Membership",
|
|
||||||
{"batch": self.name, "member_type": "Mentor"},
|
|
||||||
["member"])
|
|
||||||
member_names = [m['member'] for m in memberships]
|
|
||||||
return find_all("User", name=["IN", member_names])
|
|
||||||
|
|
||||||
def is_member(self, email, member_type=None):
|
def is_member(self, email, member_type=None):
|
||||||
"""Checks if a person is part of a batch.
|
"""Checks if a person is part of a batch.
|
||||||
@@ -43,16 +35,6 @@ class LMSBatch(Document):
|
|||||||
filters['member_type'] = member_type
|
filters['member_type'] = member_type
|
||||||
return frappe.db.exists("LMS Batch Membership", filters)
|
return frappe.db.exists("LMS Batch Membership", filters)
|
||||||
|
|
||||||
def get_students(self):
|
|
||||||
"""Returns (email, full_name, username) of all the students of this batch as a list of dict.
|
|
||||||
"""
|
|
||||||
memberships = frappe.get_all(
|
|
||||||
"LMS Batch Membership",
|
|
||||||
{"batch": self.name, "member_type": "Student"},
|
|
||||||
["member"])
|
|
||||||
member_names = [m['member'] for m in memberships]
|
|
||||||
return find_all("User", name=["IN", member_names])
|
|
||||||
|
|
||||||
def get_messages(self):
|
def get_messages(self):
|
||||||
messages = frappe.get_all("LMS Message", {"batch": self.name}, ["*"], order_by="creation")
|
messages = frappe.get_all("LMS Message", {"batch": self.name}, ["*"], order_by="creation")
|
||||||
for message in messages:
|
for message in messages:
|
||||||
@@ -89,3 +71,38 @@ def save_message(message, batch):
|
|||||||
"message": message
|
"message": message
|
||||||
})
|
})
|
||||||
doc.save(ignore_permissions=True)
|
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.
|
||||||
|
"""
|
||||||
|
membership = frappe.get_last_doc(
|
||||||
|
"LMS Batch Membership",
|
||||||
|
filters={"course": course_name, "member": email})
|
||||||
|
|
||||||
|
batch = frappe.get_doc("LMS Batch", batch_name)
|
||||||
|
if not batch:
|
||||||
|
raise ValueError(f"Invalid Batch: {batch_name}")
|
||||||
|
|
||||||
|
if batch.course != course_name:
|
||||||
|
raise ValueError("Can not switch batches across courses")
|
||||||
|
|
||||||
|
if batch.is_member(email):
|
||||||
|
print(f"{email} is already a member of {batch.title}")
|
||||||
|
return
|
||||||
|
|
||||||
|
old_batch = frappe.get_doc("LMS Batch", membership.batch)
|
||||||
|
|
||||||
|
print("updating membership", membership.name)
|
||||||
|
membership.batch = 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'):
|
||||||
|
doc = frappe.get_doc("Exercise Submission", name)
|
||||||
|
print("updating exercise submission", name)
|
||||||
|
doc.batch = batch_name
|
||||||
|
doc.save()
|
||||||
|
|||||||
@@ -13,8 +13,7 @@
|
|||||||
"course",
|
"course",
|
||||||
"member_type",
|
"member_type",
|
||||||
"role",
|
"role",
|
||||||
"current_lesson",
|
"current_lesson"
|
||||||
"is_current"
|
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -81,19 +80,11 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Memeber Username",
|
"label": "Memeber Username",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "is_current",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 1,
|
|
||||||
"label": "Is Currently Being Used",
|
|
||||||
"read_only": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-06-14 10:24:35.425498",
|
"modified": "2021-06-21 12:10:28.808803",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Batch Membership",
|
"name": "LMS Batch Membership",
|
||||||
|
|||||||
@@ -14,40 +14,53 @@ class LMSBatchMembership(Document):
|
|||||||
self.validate_membership_in_different_batch_same_course()
|
self.validate_membership_in_different_batch_same_course()
|
||||||
|
|
||||||
def validate_membership_in_same_batch(self):
|
def validate_membership_in_same_batch(self):
|
||||||
previous_membership = frappe.db.get_value("LMS Batch Membership",
|
|
||||||
filters={
|
filters={
|
||||||
"member": self.member,
|
"member": self.member,
|
||||||
"batch": self.batch,
|
"course": self.course,
|
||||||
"name": ["!=", self.name]
|
"name": ["!=", self.name]
|
||||||
},
|
}
|
||||||
|
if self.batch:
|
||||||
|
filters["batch"] = self.batch
|
||||||
|
previous_membership = frappe.db.get_value("LMS Batch Membership",
|
||||||
|
filters,
|
||||||
fieldname=["member_type","member"],
|
fieldname=["member_type","member"],
|
||||||
as_dict=1)
|
as_dict=1)
|
||||||
|
|
||||||
if previous_membership:
|
if previous_membership:
|
||||||
member_name = frappe.db.get_value("User", self.member, "full_name")
|
member_name = frappe.db.get_value("User", self.member, "full_name")
|
||||||
frappe.throw(_("{0} is already a {1} of {2}").format(member_name, previous_membership.member_type, self.batch))
|
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))
|
||||||
|
|
||||||
def validate_membership_in_different_batch_same_course(self):
|
def validate_membership_in_different_batch_same_course(self):
|
||||||
|
"""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
|
||||||
|
|
||||||
course = frappe.db.get_value("LMS Batch", self.batch, "course")
|
course = frappe.db.get_value("LMS Batch", self.batch, "course")
|
||||||
previous_membership = frappe.get_all("LMS Batch Membership",
|
memberships = frappe.get_all(
|
||||||
|
"LMS Batch Membership",
|
||||||
filters={
|
filters={
|
||||||
"member": self.member,
|
"member": self.member,
|
||||||
"name": ["!=", self.name]
|
"name": ["!=", self.name],
|
||||||
|
"member_type": "Student",
|
||||||
|
"course": self.course
|
||||||
},
|
},
|
||||||
fields=["batch", "member_type", "name"]
|
fields=["batch", "member_type", "name"]
|
||||||
)
|
)
|
||||||
|
|
||||||
for membership in previous_membership:
|
if memberships:
|
||||||
batch_course = frappe.db.get_value("LMS Batch", membership.batch, "course")
|
membership = memberships[0]
|
||||||
if batch_course == course and (membership.member_type == "Student" or self.member_type == "Student"):
|
|
||||||
member_name = frappe.db.get_value("User", self.member, "full_name")
|
member_name = frappe.db.get_value("User", self.member, "full_name")
|
||||||
frappe.throw(_("{0} is already a {1} of {2} course through {3} batch").format(member_name, membership.member_type, course, membership.batch))
|
frappe.throw(_("{0} is already a Student of {1} course through {2} batch").format(member_name, course, membership.batch))
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def create_membership(batch, member=None, member_type="Student", role="Member"):
|
def create_membership(course, batch=None, member=None, member_type="Student", role="Member"):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "LMS Batch Membership",
|
"doctype": "LMS Batch Membership",
|
||||||
"batch": batch,
|
"batch": batch,
|
||||||
|
"course": course,
|
||||||
"role": role,
|
"role": role,
|
||||||
"member_type": member_type,
|
"member_type": member_type,
|
||||||
"member": member or frappe.session.user
|
"member": member or frappe.session.user
|
||||||
@@ -55,7 +68,7 @@ def create_membership(batch, member=None, member_type="Student", role="Member"):
|
|||||||
return "OK"
|
return "OK"
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def update_current_membership(batch, course, member=frappe.session.user):
|
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:
|
for membership in all_memberships:
|
||||||
frappe.db.set_value("LMS Batch Membership", membership.name, "is_current", 0)
|
frappe.db.set_value("LMS Batch Membership", membership.name, "is_current", 0)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"title",
|
"title",
|
||||||
"is_published",
|
"is_published",
|
||||||
|
"disable_self_learning",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"short_code",
|
"short_code",
|
||||||
"video_link",
|
"video_link",
|
||||||
@@ -73,6 +74,12 @@
|
|||||||
"fieldtype": "Small Text",
|
"fieldtype": "Small Text",
|
||||||
"label": "Short Introduction",
|
"label": "Short Introduction",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "disable_self_learning",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Disable Self Learning"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
@@ -99,7 +106,7 @@
|
|||||||
"link_fieldname": "course"
|
"link_fieldname": "course"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2021-06-01 04:36:45.696776",
|
"modified": "2021-06-21 11:34:04.552376",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Course",
|
"name": "LMS Course",
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ class LMSCourse(Document):
|
|||||||
"""
|
"""
|
||||||
if not email:
|
if not email:
|
||||||
return False
|
return False
|
||||||
return frappe.db.exists({
|
return frappe.db.count("LMS Course Mentor Mapping",
|
||||||
"doctype": "LMS Course Mentor Mapping",
|
{
|
||||||
"course": self.name,
|
"course": self.name,
|
||||||
"mentor": email
|
"mentor": email
|
||||||
})
|
})
|
||||||
@@ -192,22 +192,53 @@ class LMSCourse(Document):
|
|||||||
return
|
return
|
||||||
return f"/courses/{self.name}/learn/{lesson_number}"
|
return f"/courses/{self.name}/learn/{lesson_number}"
|
||||||
|
|
||||||
def get_current_batch(self, member=frappe.session.user):
|
def get_membership(self, member, batch=None):
|
||||||
current_membership = frappe.get_all("LMS Batch Membership", {"member": member, "course": self.name, "is_current": 1}, pluck="batch")
|
filters = {
|
||||||
print(current_membership, member, self.name)
|
"member": member,
|
||||||
if len(current_membership):
|
"course": self.name
|
||||||
return current_membership[0]
|
}
|
||||||
print(frappe.db.get_value("LMS Batch Membership", {"member": member, "course": self.name}, "batch"))
|
if batch:
|
||||||
return frappe.db.get_value("LMS Batch Membership", {"member": member, "course": self.name}, "batch")
|
filters["batch"] = batch
|
||||||
|
return frappe.db.get_value("LMS Batch Membership", filters, ["name","batch", "current_lesson"], as_dict=True)
|
||||||
|
|
||||||
def get_all_memberships(self, member=frappe.session.user):
|
def get_all_memberships(self, member=frappe.session.user):
|
||||||
print(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", "is_current"])
|
|
||||||
print(all_memberships)
|
|
||||||
for membership in all_memberships:
|
for membership in all_memberships:
|
||||||
membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title")
|
membership.batch_title = frappe.db.get_value("LMS Batch", membership.batch, "title")
|
||||||
|
print(all_memberships)
|
||||||
return all_memberships
|
return all_memberships
|
||||||
|
|
||||||
|
def get_mentors(self, batch=None):
|
||||||
|
filters = {
|
||||||
|
"course": self.name,
|
||||||
|
"member_type": "Mentor"
|
||||||
|
}
|
||||||
|
if batch:
|
||||||
|
filters["batch"] = batch
|
||||||
|
|
||||||
|
memberships = frappe.get_all(
|
||||||
|
"LMS Batch Membership",
|
||||||
|
filters,
|
||||||
|
["member"])
|
||||||
|
member_names = [m['member'] for m in memberships]
|
||||||
|
return find_all("User", name=["IN", member_names])
|
||||||
|
|
||||||
|
def get_students(self, batch=None):
|
||||||
|
"""Returns (email, full_name, username) of all the students of this batch as a list of dict.
|
||||||
|
"""
|
||||||
|
filters = {
|
||||||
|
"course": self.name,
|
||||||
|
"member_type": "Student"
|
||||||
|
}
|
||||||
|
if batch:
|
||||||
|
filters["batch"] = batch
|
||||||
|
memberships = frappe.get_all(
|
||||||
|
"LMS Batch Membership",
|
||||||
|
filters,
|
||||||
|
["member"])
|
||||||
|
member_names = [m['member'] for m in memberships]
|
||||||
|
return find_all("User", name=["IN", member_names])
|
||||||
|
|
||||||
def get_outline(self):
|
def get_outline(self):
|
||||||
return CourseOutline(self)
|
return CourseOutline(self)
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ class TestLMSCourse(unittest.TestCase):
|
|||||||
course = self.new_course("Test Course")
|
course = self.new_course("Test Course")
|
||||||
assert course.title == "Test Course"
|
assert course.title == "Test Course"
|
||||||
assert course.name == "test-course"
|
assert course.name == "test-course"
|
||||||
assert course.get_mentors() == []
|
|
||||||
|
|
||||||
def test_find_all(self):
|
def test_find_all(self):
|
||||||
courses = LMSCourse.find_all()
|
courses = LMSCourse.find_all()
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ def find_macros(text):
|
|||||||
('Exercise', 'four-circles')
|
('Exercise', 'four-circles')
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
|
if not text:
|
||||||
|
return []
|
||||||
macros = re.findall(MACRO_RE, text)
|
macros = re.findall(MACRO_RE, text)
|
||||||
# remove the quotes around the argument
|
# remove the quotes around the argument
|
||||||
return [(name, _remove_quotes(arg)) for name, arg in macros]
|
return [(name, _remove_quotes(arg)) for name, arg in macros]
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"login_required": 1,
|
"login_required": 1,
|
||||||
"max_attachment_size": 0,
|
"max_attachment_size": 0,
|
||||||
"modified": "2021-06-14 15:28:08.206622",
|
"modified": "2021-06-15 18:49:50.530001",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "add-a-new-batch",
|
"name": "add-a-new-batch",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
{
|
{
|
||||||
"allow_read_on_all_link_options": 0,
|
"allow_read_on_all_link_options": 0,
|
||||||
"fieldname": "course",
|
"fieldname": "course",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Data",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Course",
|
"label": "Course",
|
||||||
"max_length": 0,
|
"max_length": 0,
|
||||||
|
|||||||
@@ -9,68 +9,57 @@
|
|||||||
Switch Batch
|
Switch Batch
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
{% for membership in all_memberships %}
|
{% for data in all_memberships %}
|
||||||
{% if not membership.is_current %}
|
{% if data.batch != membership.batch %}
|
||||||
<a class="dropdown-item switch-batch" href="#" data-batch="{{ membership.batch | urlencode }}" data-course="{{ course.name | urlencode }}">{{ membership.batch_title }}</a>
|
<a class="dropdown-item switch-batch" href="/courses/{{ course.name }}/home?batch={{ data.batch }}">{{ data.batch_title }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if not batch %}
|
{% if not membership %}
|
||||||
{% set display_class = "hide" %}
|
{% set display_class = "hide" %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set display_class = "" %}
|
{% set display_class = "" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<ul class="nav nav-tabs mt-4">
|
<ul class="nav nav-tabs mt-4">
|
||||||
<li class="nav-item {{ display_class }}">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="home" href="/courses/{{course.name}}/home">Home</a>
|
<a class="nav-link" id="home" href="/courses/{{course.name}}/home{{ course.query_parameter }}">Home</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="learn" href="/courses/{{course.name}}/learn">Lessons</a>
|
{% set lesson_index = course.get_lesson_index(membership.current_lesson) if membership and membership.current_lesson else '1.1' %}
|
||||||
|
<a class="nav-link" id="learn"
|
||||||
|
href="{{ course.get_learn_url(lesson_index) }}{{ course.query_parameter }}">Lessons</a>
|
||||||
</li>
|
</li>
|
||||||
<!-- <li class="nav-item">
|
<!-- <li class="nav-item">
|
||||||
<a class="nav-link" id="schedule" href="/courses/{{course.name}}/schedule">Schedule</a>
|
<a class="nav-link" id="schedule" href="/courses/{{course.name}}/schedule">Schedule</a>
|
||||||
</li> -->
|
</li> -->
|
||||||
<li class="nav-item {{ display_class }}">
|
<li class="nav-item {{ display_class }}">
|
||||||
<a class="nav-link" id="members" href="/courses/{{course.name}}/members">Members</a>
|
<a class="nav-link" id="members" href="/courses/{{course.name}}/members{{ course.query_parameter }}">Members</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item {{ display_class }}">
|
<!-- <li class="nav-item {{ display_class }}">
|
||||||
<a class="nav-link" id="discussion" href="/courses/{{course.name}}/discuss">Discussion</a>
|
<a class="nav-link" id="discussion" href="/courses/{{course.name}}/discuss">Discussion</a>
|
||||||
</li>
|
</li> -->
|
||||||
<!-- <li class="nav-item">
|
<!-- <li class="nav-item">
|
||||||
<a class="nav-link" id="about" href="/courses/{{course.name}}/about">About</a>
|
<a class="nav-link" id="about" href="/courses/{{course.name}}/about">About</a>
|
||||||
</li> -->
|
</li> -->
|
||||||
{% if batch and batch.is_member(frappe.session.user, member_type="Mentor") %}
|
{% if membership and membership.batch and course.is_mentor(frappe.session.user) %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" id="progress" href="/courses/{{course.name}}/progress">Progress</a>
|
<a class="nav-link" id="progress" href="/courses/{{course.name}}/progress{{ course.query_parameter }}">Progress</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
{% block script %}
|
||||||
<script>
|
<script>
|
||||||
frappe.ready(() => {
|
frappe.ready(() => {
|
||||||
var selector = document.querySelector(`a[href="${decodeURIComponent(window.location.pathname)}"]`)
|
var selector = document.querySelector(`a[href="${decodeURIComponent(window.location.pathname)}{{ course.query_parameter }}"]`)
|
||||||
if (selector) {
|
if (selector) {
|
||||||
selector.classList.add('active');
|
selector.classList.add('active');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$("#learn").addClass('active')
|
$("#learn").addClass('active')
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".switch-batch").click((e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
var batch = decodeURIComponent($(e.currentTarget).attr("data-batch"));
|
|
||||||
var course = decodeURIComponent($(e.currentTarget).attr("data-course"));
|
|
||||||
frappe.call({
|
|
||||||
method: "community.lms.doctype.lms_batch_membership.lms_batch_membership.update_current_membership",
|
|
||||||
args: {
|
|
||||||
batch: batch,
|
|
||||||
course: course
|
|
||||||
},
|
|
||||||
callback: (data) => {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
@@ -8,11 +8,10 @@
|
|||||||
{% for lesson in chapter.get_lessons() %}
|
{% for lesson in chapter.get_lessons() %}
|
||||||
<div class="lesson-teaser">
|
<div class="lesson-teaser">
|
||||||
<a {% if show_link or lesson.include_in_preview %}
|
<a {% if show_link or lesson.include_in_preview %}
|
||||||
href="{{ course.get_learn_url(course.get_lesson_index(lesson.name)) }}" {% else %} href="" class="no-preview"
|
href="{{ course.get_learn_url(course.get_lesson_index(lesson.name)) }}{{course.query_parameter}}" {% else %} href="" class="no-preview"
|
||||||
{% endif %} data-course="{{ course.name }}">{{ lesson.title }}</a>
|
{% endif %} data-course="{{ course.name }}">{{ lesson.title }}</a>
|
||||||
{% if show_progress and not course.is_mentor(frappe.session.user) and lesson.get_progress() %}
|
{% if show_progress and not course.is_mentor(frappe.session.user) and lesson.get_progress() %}
|
||||||
<a class="ml-5 badge p-1 {{ lesson.get_slugified_class() }}"> <img class="progress-image"
|
<span class="ml-5 badge p-2 {{ lesson.get_slugified_class() }}"> {{ lesson.get_progress() }}</span>
|
||||||
src="/assets/community/images/Vector.png"> {{ lesson.get_progress() }}</a>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<div>Starting {{frappe.utils.format_date(batch.start_date, "medium")}}</div>
|
<div>Starting {{frappe.utils.format_date(batch.start_date, "medium")}}</div>
|
||||||
<div class="course-type" style="color: #888; padding: 10px 0px;">mentors</div>
|
<div class="course-type" style="color: #888; padding: 10px 0px;">mentors</div>
|
||||||
|
|
||||||
{% for m in batch.get_mentors() %}
|
{% for m in course.get_mentors(batch.name) %}
|
||||||
<div>
|
<div>
|
||||||
{{ widgets.Avatar(member=m, avatar_class="avatar-medium" ) }}
|
{{ widgets.Avatar(member=m, avatar_class="avatar-medium" ) }}
|
||||||
<span class="instructor-title">{{m.full_name}}</span>
|
<span class="instructor-title">{{m.full_name}}</span>
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
<div class="cta">
|
<div class="cta">
|
||||||
<div class="">
|
<div class="">
|
||||||
{% if can_manage %}
|
{% if can_manage %}
|
||||||
<a href="" class="btn btn-primary manage-batch" data-batch="{{ batch.name | urlencode }}"
|
<a href="/courses/{{ course.name }}/home?batch={{ batch.name }}" class="btn btn-primary manage-batch" data-batch="{{ batch.name | urlencode }}"
|
||||||
data-course="{{ course.name | urlencode }}">Manage</a>
|
data-course="{{ course.name | urlencode }}">Manage</a>
|
||||||
{% elif can_join %}
|
{% elif can_join %}
|
||||||
<button class="join-batch btn btn-primary" data-batch="{{ batch.name | urlencode }}"
|
<button class="join-batch btn btn-secondary" data-batch="{{ batch.name | urlencode }}"
|
||||||
data-course="{{ course.name | urlencode }}">Join this Batch</button>
|
data-course="{{ course.name | urlencode }}">Join this Batch</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
--cta-color: var(--c4);
|
--cta-color: var(--c4);
|
||||||
--send-message: var(--c7);
|
--send-message: var(--c7);
|
||||||
--received-message: var(--c8);
|
--received-message: var(--c8);
|
||||||
|
--control-bg: var(--gray-100);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||||
<div class="messages-container mt-5">
|
<div class="messages-container mt-5">
|
||||||
{{ widgets.BatchHeader(batch_name=batch.title, member_count=member_count)}}
|
{{ widgets.BatchHeader(batch_name=batch.title, member_count=member_count)}}
|
||||||
<ol class="messages">
|
<ol class="messages">
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ from . import utils
|
|||||||
def get_context(context):
|
def get_context(context):
|
||||||
utils.get_common_context(context)
|
utils.get_common_context(context)
|
||||||
context.messages = context.batch.get_messages()
|
context.messages = context.batch.get_messages()
|
||||||
if not context.batch:
|
if not context.membership:
|
||||||
utils.redirect_to_lesson(context.course)
|
utils.redirect_to_lesson(context.course)
|
||||||
|
|||||||
@@ -8,15 +8,13 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% set invite_link = frappe.utils.get_url() + "/courses/" + course.name + "/join?batch=" + batch.name %}
|
|
||||||
<div class="container mt-5">
|
<div class="container mt-5">
|
||||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||||
<!-- <div>
|
|
||||||
<h1 class="mt-5">{{ batch.title }}</h1>
|
|
||||||
</div> -->
|
|
||||||
<div class="course-details mt-5">
|
<div class="course-details mt-5">
|
||||||
{{ widgets.CourseOutline(course=course, batch=batch, show_link=True, show_progress=True) }}
|
{{ widgets.CourseOutline(course=course, batch=batch, show_link=True, show_progress=True) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if batch %}
|
||||||
<div class="w-25">
|
<div class="w-25">
|
||||||
<h3>Batch Schedule</h3>
|
<h3>Batch Schedule</h3>
|
||||||
{{ widgets.RenderBatch(course=course, batch=batch) }}
|
{{ widgets.RenderBatch(course=course, batch=batch) }}
|
||||||
@@ -28,8 +26,9 @@
|
|||||||
{{ frappe.utils.md_to_html(batch.description) }}
|
{{ frappe.utils.md_to_html(batch.description) }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% if course.is_mentor(frappe.session.user) %}
|
{% if course.is_mentor(frappe.session.user) %}
|
||||||
|
{% set invite_link = frappe.utils.get_url() + "/courses/" + course.name + "/join?batch=" + batch.name %}
|
||||||
<div class="">
|
<div class="">
|
||||||
<h3> Invite Members </h3>
|
<h3> Invite Members </h3>
|
||||||
<a href="" class="" id="invite-link" data-link="{{ invite_link }}">Get Batch Invitation
|
<a href="" class="" id="invite-link" data-link="{{ invite_link }}">Get Batch Invitation
|
||||||
|
|||||||
@@ -3,5 +3,3 @@ from . import utils
|
|||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
utils.get_common_context(context)
|
utils.get_common_context(context)
|
||||||
if not context.batch:
|
|
||||||
utils.redirect_to_lesson(context.course)
|
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ frappe.ready(() => {
|
|||||||
frappe.call({
|
frappe.call({
|
||||||
"method": "community.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership",
|
"method": "community.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership",
|
||||||
"args": {
|
"args": {
|
||||||
"batch": "{{ batch.name }}"
|
"batch": {{ batch.name }},
|
||||||
|
"course": {{ batch.course }}
|
||||||
},
|
},
|
||||||
"callback": (data) => {
|
"callback": (data) => {
|
||||||
if (data.message == "OK") {
|
if (data.message == "OK") {
|
||||||
@@ -66,19 +67,6 @@ frappe.ready(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
$("#batch-home").click((e) => {
|
|
||||||
frappe.call({
|
|
||||||
method: "community.lms.doctype.lms_batch_membership.lms_batch_membership.update_current_membership",
|
|
||||||
args: {
|
|
||||||
"batch": "{{ batch.name }}",
|
|
||||||
"course": "{{ batch.course}}"
|
|
||||||
},
|
|
||||||
callback: (data) => {
|
|
||||||
window.location.href = "/courses/{{ batch.course }}/home"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -22,17 +22,18 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||||
<div class="lesson-page">
|
<div class="lesson-page">
|
||||||
|
|
||||||
<h2 class="title {% if course.is_mentor(frappe.session.user) %} is_mentor {% endif %}" data-name="{{ lesson.name }}" {% if batch %} data-batch="{{ batch.name }}" {% endif %}>{{ lesson.title }}</h2>
|
<h2 class="title {% if course.is_mentor(frappe.session.user) %} is_mentor {% endif %}" data-lesson="{{ lesson.name }}"
|
||||||
|
data-course="{{ course.name }}" {% if membership%} data-membership="{{membership.name}}" {% endif %}>{{ lesson.title }}</h2>
|
||||||
|
|
||||||
{% if batch or lesson.include_in_preview %}
|
{% if membership or lesson.include_in_preview %}
|
||||||
{{ lesson.render_html() }}
|
{{ lesson.render_html() }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="no-preview-message">
|
<div class="no-preview-message">
|
||||||
<span>This lesson is not available for Preview. Please join a batch to access the complete course.</span>
|
<span>This lesson is not available for Preview. Please join the course to access this lesson.</span>
|
||||||
<a href="/courses/{{ course.name }}">Checkout Upcoming Batches</a>
|
<a href="/courses/{{ course.name }}">Checkout Course Details.</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -63,5 +64,4 @@
|
|||||||
{% for ext in page_extensions %}
|
{% for ext in page_extensions %}
|
||||||
{{ ext.render_footer() }}
|
{{ ext.render_footer() }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{%- endblock %}
|
{%- endblock %}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
frappe.ready(() => {
|
frappe.ready(() => {
|
||||||
if ($(".title").attr("data-batch") && !$(".title").hasClass("is_mentor")) {
|
if ($(".title").attr("data-membership") && !$(".title").hasClass("is_mentor")) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "community.lms.doctype.lesson.lesson.save_progress",
|
method: "community.lms.doctype.lesson.lesson.save_progress",
|
||||||
args: {
|
args: {
|
||||||
lesson: $(".title").attr("data-name"),
|
lesson: $(".title").attr("data-lesson"),
|
||||||
batch: $(".title").attr("data-batch")
|
course: $(".title").attr("data-course")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if ($(".title").attr("data-batch")) {
|
if ($(".title").attr("data-membership")) {
|
||||||
frappe.call("community.lms.api.save_current_lesson", {
|
frappe.call("community.lms.api.save_current_lesson", {
|
||||||
"batch_name": $(".title").attr("data-batch"),
|
course_name: $(".title").attr("data-course"),
|
||||||
"lesson_name": $(".title").attr("data-name")
|
lesson_name: $(".title").attr("data-lesson")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ def get_context(context):
|
|||||||
index_ = get_lesson_index(context.course, context.batch, frappe.session.user) or "1.1"
|
index_ = get_lesson_index(context.course, context.batch, frappe.session.user) or "1.1"
|
||||||
else:
|
else:
|
||||||
index_ = "1.1"
|
index_ = "1.1"
|
||||||
frappe.local.flags.redirect_location = context.course.get_learn_url(index_)
|
frappe.local.flags.redirect_location = context.course.get_learn_url(index_) + context.course.query_parameter
|
||||||
raise frappe.Redirect
|
raise frappe.Redirect
|
||||||
|
|
||||||
context.lesson = context.course.get_lesson(chapter_index, lesson_index)
|
context.lesson = context.course.get_lesson(chapter_index, lesson_index)
|
||||||
@@ -30,8 +30,8 @@ def get_context(context):
|
|||||||
next_ = outline.get_next(lesson_number)
|
next_ = outline.get_next(lesson_number)
|
||||||
context.prev_chap = get_chapter_title(course_name, prev_)
|
context.prev_chap = get_chapter_title(course_name, prev_)
|
||||||
context.next_chap = get_chapter_title(course_name, next_)
|
context.next_chap = get_chapter_title(course_name, next_)
|
||||||
context.next_url = context.course.get_learn_url(next_)
|
context.next_url = context.course.get_learn_url(next_) + context.course.query_parameter
|
||||||
context.prev_url = context.course.get_learn_url(prev_)
|
context.prev_url = context.course.get_learn_url(prev_) + context.course.query_parameter
|
||||||
|
|
||||||
context.page_extensions = get_page_extensions()
|
context.page_extensions = get_page_extensions()
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||||
{{ MembersList(members)}}
|
{{ MembersList(members)}}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ from . import utils
|
|||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
utils.get_common_context(context)
|
utils.get_common_context(context)
|
||||||
if not context.batch:
|
if not context.membership:
|
||||||
utils.redirect_to_lesson(context.course)
|
utils.redirect_to_lesson(context.course)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||||
<div class="mentor-dashboard">
|
<div class="mentor-dashboard">
|
||||||
<h3>Batch Progress</h3>
|
<h3>Batch Progress</h3>
|
||||||
{% for exercise in report.exercises %}
|
{% for exercise in report.exercises %}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ def get_context(context):
|
|||||||
|
|
||||||
class BatchReport:
|
class BatchReport:
|
||||||
def __init__(self, course, batch):
|
def __init__(self, course, batch):
|
||||||
self.submissions = get_submissions(batch)
|
self.submissions = get_submissions(course, batch)
|
||||||
self.exercises = self.get_exercises(course.name)
|
self.exercises = self.get_exercises(course.name)
|
||||||
self.submissions_by_exercise = defaultdict(list)
|
self.submissions_by_exercise = defaultdict(list)
|
||||||
for s in self.submissions:
|
for s in self.submissions:
|
||||||
@@ -29,8 +29,10 @@ class BatchReport:
|
|||||||
def get_submissions_of_exercise(self, exercise_name):
|
def get_submissions_of_exercise(self, exercise_name):
|
||||||
return self.submissions_by_exercise[exercise_name]
|
return self.submissions_by_exercise[exercise_name]
|
||||||
|
|
||||||
def get_submissions(batch):
|
def get_submissions(course, batch):
|
||||||
students = batch.get_students()
|
students = course.get_students(batch.name)
|
||||||
|
if not len(students):
|
||||||
|
return []
|
||||||
students_map = {s.email: s for s in students}
|
students_map = {s.email: s for s in students}
|
||||||
names, values = nparams("s", students_map.keys())
|
names, values = nparams("s", students_map.keys())
|
||||||
sql = """
|
sql = """
|
||||||
|
|||||||
@@ -5,26 +5,34 @@ def get_common_context(context):
|
|||||||
context.no_cache = 1
|
context.no_cache = 1
|
||||||
|
|
||||||
course_name = frappe.form_dict["course"]
|
course_name = frappe.form_dict["course"]
|
||||||
|
try:
|
||||||
|
batch_name = frappe.form_dict["batch"]
|
||||||
|
except KeyError:
|
||||||
|
batch_name = None
|
||||||
|
|
||||||
course = Course.find(course_name)
|
course = Course.find(course_name)
|
||||||
if not course:
|
if not course:
|
||||||
context.template = "www/404.html"
|
context.template = "www/404.html"
|
||||||
return
|
return
|
||||||
|
context.course = course
|
||||||
|
|
||||||
batch_name = course.get_current_batch()
|
membership = course.get_membership(frappe.session.user, batch_name)
|
||||||
batch = course.get_batch(batch_name)
|
if membership:
|
||||||
|
context.membership = membership
|
||||||
|
batch = course.get_batch(membership.batch)
|
||||||
|
|
||||||
|
if batch:
|
||||||
context.batch = batch
|
context.batch = batch
|
||||||
if batch_name:
|
|
||||||
context.members = batch.get_mentors() + batch.get_students()
|
context.members = course.get_mentors(membership.batch) + course.get_students(membership.batch)
|
||||||
context.member_count = len(context.members)
|
context.member_count = len(context.members)
|
||||||
|
|
||||||
|
context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else ""
|
||||||
context.course = course
|
|
||||||
context.livecode_url = get_livecode_url()
|
context.livecode_url = get_livecode_url()
|
||||||
|
|
||||||
def get_livecode_url():
|
def get_livecode_url():
|
||||||
return frappe.db.get_single_value("LMS Settings", "livecode_url")
|
return frappe.db.get_single_value("LMS Settings", "livecode_url")
|
||||||
|
|
||||||
def redirect_to_lesson(course, index_="1.1"):
|
def redirect_to_lesson(course, index_="1.1"):
|
||||||
frappe.local.flags.redirect_location = course.get_learn_url(index_)
|
frappe.local.flags.redirect_location = course.get_learn_url(index_) + course.query_parameter
|
||||||
raise frappe.Redirect
|
raise frappe.Redirect
|
||||||
|
|||||||
@@ -12,7 +12,14 @@
|
|||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<a class="anchor_style" href="/courses">Courses</a> / <span class="text-muted">{{ course.title }}</span>
|
<a class="anchor_style" href="/courses">Courses</a> / <span class="text-muted">{{ course.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-flex justify-content-between align-items-end">
|
||||||
<h2 id="course-title" data-course="{{course.name}}">{{course.title}}</h2>
|
<h2 id="course-title" data-course="{{course.name}}">{{course.title}}</h2>
|
||||||
|
{% if not course.disable_self_learning and not course.is_mentor(frappe.session.user) %}
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-primary join-batch" data-course="{{ course.name | urlencode }}"> Start Learning </button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
<div class="course-short-intro">{{ course.short_introduction }}</div>
|
<div class="course-short-intro">{{ course.short_introduction }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -75,12 +82,12 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a class="add-batch margin-bottom" href="/add-a-new-batch?new=1&course={{course.title}}&slug={{course.name}}">Add a new
|
<a class="add-batch margin-bottom" href="/add-a-new-batch?new=1&course={{course.name}}">Add a new
|
||||||
batch</a>
|
batch</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="mentor_message">
|
<div class="mentor_message">
|
||||||
<p> You are a mentor for this course. </p>
|
<p> You are a mentor for this course. </p>
|
||||||
<a class="" href="/add-a-new-batch?new=1&course={{course.title}}&slug={{course.name}}">Create your first batch</a>
|
<a class="" href="/add-a-new-batch?new=1&course={{course.name}}">Create your first batch</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|||||||
@@ -57,11 +57,13 @@ frappe.ready(() => {
|
|||||||
window.location.href = `/login?redirect-to=/courses/${course}`;
|
window.location.href = `/login?redirect-to=/courses/${course}`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
batch = decodeURIComponent($(e.currentTarget).attr("data-batch"))
|
var batch = $(e.currentTarget).attr("data-batch");
|
||||||
|
batch = batch ? decodeURIComponent(batch) : "";
|
||||||
frappe.call({
|
frappe.call({
|
||||||
"method": "community.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership",
|
"method": "community.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership",
|
||||||
"args": {
|
"args": {
|
||||||
"batch": batch
|
"batch": batch ? batch : "",
|
||||||
|
"course": course
|
||||||
},
|
},
|
||||||
"callback": (data) => {
|
"callback": (data) => {
|
||||||
if (data.message == "OK") {
|
if (data.message == "OK") {
|
||||||
@@ -73,20 +75,4 @@ frappe.ready(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
$(".manage-batch").click((e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
var batch = decodeURIComponent($(e.currentTarget).attr("data-batch"));
|
|
||||||
var course = decodeURIComponent($(e.currentTarget).attr("data-course"));
|
|
||||||
frappe.call({
|
|
||||||
method: "community.lms.doctype.lms_batch_membership.lms_batch_membership.update_current_membership",
|
|
||||||
args: {
|
|
||||||
batch: batch,
|
|
||||||
course: course
|
|
||||||
},
|
|
||||||
callback: (data) => {
|
|
||||||
window.location.href = `/courses/${course}/home`;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ def get_context(context):
|
|||||||
raise frappe.Redirect
|
raise frappe.Redirect
|
||||||
|
|
||||||
context.course = course
|
context.course = course
|
||||||
|
context.course.query_parameter = ""
|
||||||
batch = course.get_student_batch(frappe.session.user)
|
if not course.is_mentor(frappe.session.user):
|
||||||
|
batch = course.get_membership(frappe.session.user)
|
||||||
if batch:
|
if batch:
|
||||||
frappe.local.flags.redirect_location = f"/courses/{course.name}/learn"
|
frappe.local.flags.redirect_location = f"/courses/{course.name}/learn"
|
||||||
raise frappe.Redirect
|
raise frappe.Redirect
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user