diff --git a/community/community/doctype/community_member/community_member.py b/community/community/doctype/community_member/community_member.py index d90fe498..333771f0 100644 --- a/community/community/doctype/community_member/community_member.py +++ b/community/community/doctype/community_member/community_member.py @@ -42,7 +42,7 @@ class CommunityMember(Document): return frappe.db.count( 'LMS Batch Membership', { 'member': self.name, - 'member_role': 'Mentor' + 'member_type': 'Mentor' }) def __repr__(self): diff --git a/community/hooks.py b/community/hooks.py index 6b1fb371..1332aebd 100644 --- a/community/hooks.py +++ b/community/hooks.py @@ -136,7 +136,6 @@ primary_rules = [ {"from_route": "/sketches/", "to_route": "sketches/sketch"}, {"from_route": "/courses/", "to_route": "courses/course"}, {"from_route": "/courses//", "to_route": "courses/topic"}, - {"from_route": "/hackathons", "to_route": "hackathons"}, {"from_route": "/hackathons/", "to_route": "hackathons/hackathon"}, {"from_route": "/hackathons//", "to_route": "hackathons/project"}, {"from_route": "/dashboard", "to_route": ""}, @@ -164,7 +163,8 @@ whitelist = [ "/dashboard", "/join-request" "/add-a-new-batch", - "/new-sign-up" + "/new-sign-up", + "/message" ] whitelist_rules = [{"from_route": p, "to_route": p[1:]} for p in whitelist] diff --git a/community/lms/doctype/invite_request/invite_request.py b/community/lms/doctype/invite_request/invite_request.py index 5b422643..5818451c 100644 --- a/community/lms/doctype/invite_request/invite_request.py +++ b/community/lms/doctype/invite_request/invite_request.py @@ -11,7 +11,7 @@ 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": + if self.has_value_changed("status") and self.status == "Approved": self.send_email() def create_user(self, password): @@ -55,6 +55,7 @@ def create_invite_request(invite_email): except frappe.UniqueValidationError: frappe.throw(_("Email {0} has already been used to request an invite").format(invite_email)) + @frappe.whitelist(allow_guest=True) def update_invite(data): data = frappe._dict(json.loads(data)) if type(data) == str else frappe._dict(data) diff --git a/community/lms/doctype/lms_batch/lms_batch.py b/community/lms/doctype/lms_batch/lms_batch.py index ad5c32b1..7fc547f3 100644 --- a/community/lms/doctype/lms_batch/lms_batch.py +++ b/community/lms/doctype/lms_batch/lms_batch.py @@ -8,14 +8,25 @@ from frappe.model.document import Document from community.www.courses.utils import get_member_with_email class LMSBatch(Document): - def validate(self): - if not self.code: - self.generate_code() + def validate(self): + if not self.code: + self.generate_code() - def generate_code(self): - short_code = frappe.db.get_value("LMS Course", self.course, "short_code") - course_batches = frappe.get_all("LMS Batch",{"course":self.course}) - self.code = short_code + str(len(course_batches) + 1) + def generate_code(self): + short_code = frappe.db.get_value("LMS Course", self.course, "short_code") + course_batches = frappe.get_all("LMS Batch",{"course":self.course}) + self.code = short_code + str(len(course_batches) + 1) + + def get_mentors(self): + mentors = [] + memberships = frappe.get_all( + "LMS Batch Membership", + {"batch": self.name, "member_type": "Mentor"}, + ["member"]) + for membership in memberships: + member = frappe.db.get_value("Community Member", membership.member, ["full_name", "photo", "abbr"], as_dict=1) + mentors.append(member) + return mentors @frappe.whitelist() def get_messages(batch): @@ -36,4 +47,4 @@ def save_message(message, batch): "author": get_member_with_email(), "message": message }) - doc.save(ignore_permissions=True) \ No newline at end of file + doc.save(ignore_permissions=True) diff --git a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py index ba218209..a9f963a3 100644 --- a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py +++ b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py @@ -8,36 +8,38 @@ from frappe.model.document import Document from frappe import _ 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): - previous_membership = frappe.db.get_value("LMS Batch Membership", {"member": self.member, "batch": self.batch, "name": ["!=", self.name]}, ["member_type","member"], as_dict=1) - if previous_membership: - member_name = frappe.db.get_value("Community Member", self.member, "full_name") - frappe.throw(_("{0} is already a {1} of {2}").format(member_name, previous_membership.member_type, self.batch)) - def validate_membership_in_different_batch_same_course(self): - course = frappe.db.get_value("LMS Batch", self.batch, "course") - previous_membership = frappe.get_all("LMS Batch Membership", {"member": self.member}, ["batch", "member_type"]) - for membership in previous_membership: - batch_course = frappe.db.get_value("LMS Batch", membership.batch, "course") - if batch_course == course and (membership.member_type == "Student" or self.member_type == "Student"): - member_name = frappe.db.get_value("Community Member", 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)) + def validate(self): + self.validate_membership_in_same_batch() + self.validate_membership_in_different_batch_same_course() + + def validate_membership_in_same_batch(self): + previous_membership = frappe.db.get_value("LMS Batch Membership", {"member": self.member, "batch": self.batch, "name": ["!=", self.name]}, ["member_type","member"], as_dict=1) + if previous_membership: + member_name = frappe.db.get_value("Community Member", self.member, "full_name") + frappe.throw(_("{0} is already a {1} of {2}").format(member_name, previous_membership.member_type, self.batch)) + + def validate_membership_in_different_batch_same_course(self): + course = frappe.db.get_value("LMS Batch", self.batch, "course") + previous_membership = frappe.get_all("LMS Batch Membership", {"member": self.member}, ["batch", "member_type"]) + for membership in previous_membership: + batch_course = frappe.db.get_value("LMS Batch", membership.batch, "course") + if batch_course == course and (membership.member_type == "Student" or self.member_type == "Student"): + member_name = frappe.db.get_value("Community Member", 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.whitelist() -def create_membership(batch, course, member=None, member_type="Student", role="Member"): - if not member: - member = frappe.db.get_value("Community Member", {"email": frappe.session.user}, "name") - frappe.get_doc({ - "doctype": "LMS Batch Membership", - "batch": batch, - "role": role, - "member_type": member_type, - "member": member - }).save(ignore_permissions=True) - course_slug = frappe.db.get_value("LMS Course", {"title": course}, ["slug"]) - return course_slug \ No newline at end of file +def create_membership(batch, course=None, member=None, member_type="Student", role="Member"): + if not member: + member = frappe.db.get_value("Community Member", {"email": frappe.session.user}, "name") + frappe.get_doc({ + "doctype": "LMS Batch Membership", + "batch": batch, + "role": role, + "member_type": member_type, + "member": member + }).save(ignore_permissions=True) + if course: + course_slug = frappe.db.get_value("LMS Course", {"title": course}, ["slug"]) + return course_slug + return "OK" diff --git a/community/lms/doctype/lms_course/lms_course.py b/community/lms/doctype/lms_course/lms_course.py index f53e2c03..51e8b381 100644 --- a/community/lms/doctype/lms_course/lms_course.py +++ b/community/lms/doctype/lms_course/lms_course.py @@ -97,7 +97,7 @@ class LMSCourse(Document): for mentor in mentors: member = frappe.get_doc("Community Member", mentor.mentor) # TODO: change this to count query - member.batch_count = len(frappe.get_all("LMS Batch Membership", {"member": member, "member_type": "Mentor"})) + member.batch_count = len(frappe.get_all("LMS Batch Membership", {"member": member.name, "member_type": "Mentor"})) course_mentors.append(member) return course_mentors @@ -108,9 +108,9 @@ class LMSCourse(Document): return False member = self.get_community_member(email) return frappe.db.exists({ - 'doctype': 'LMS Course Mentor Mapping', + "doctype": "LMS Course Mentor Mapping", "course": self.name, - "member": member + "mentor": member }) def get_instructor(self): @@ -131,15 +131,16 @@ class LMSCourse(Document): memberships = frappe.db.get_all( "LMS Batch Membership", {"member": member}, - ["name"], as_dict=1) + ["batch"]) batch_names = {m.batch for m in memberships} return [b for b in batches if b.name in batch_names] def get_upcoming_batches(self): now = frappe.utils.nowdate() - return find_all("LMS Batch", + batches = find_all("LMS Batch", course=self.name, start_date=[">", now]) + return batches def find_all(doctype, order_by=None, **filters): """Queries the database for documents of a doctype matching given filters. diff --git a/community/lms/doctype/lms_sketch/lms_sketch.py b/community/lms/doctype/lms_sketch/lms_sketch.py index 5c665305..52275a6d 100644 --- a/community/lms/doctype/lms_sketch/lms_sketch.py +++ b/community/lms/doctype/lms_sketch/lms_sketch.py @@ -55,7 +55,7 @@ class LMSSketch(Document): def get_recent_sketches(limit=100, owner=None): """Returns the recent sketches. """ - filters = {} + filters = {} if owner: filters = {"owner": owner} sketches = frappe.get_all( diff --git a/community/lms/web_form/add_messages/__init__.py b/community/lms/web_form/add_messages/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/community/lms/web_form/add_messages/add_messages.js b/community/lms/web_form/add_messages/add_messages.js deleted file mode 100644 index 99c31b8f..00000000 --- a/community/lms/web_form/add_messages/add_messages.js +++ /dev/null @@ -1,12 +0,0 @@ -frappe.ready(function() { - // bind events here - frappe.web_form.after_load = () => { - frappe.web_form.set_value(["batch"], [frappe.utils.get_url_arg('batch')]); - frappe.web_form.set_value(["author"], [frappe.utils.get_url_arg('author')]); - } - frappe.web_form.success_url = `courses/course?course=${frappe.utils.get_url_arg('course')}`; - - $('.breadcrumb-container') - .html(`Back to my course`) - .addClass('py-4'); -}) \ No newline at end of file diff --git a/community/lms/web_form/add_messages/add_messages.json b/community/lms/web_form/add_messages/add_messages.json deleted file mode 100644 index b78ba8b8..00000000 --- a/community/lms/web_form/add_messages/add_messages.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "accept_payment": 0, - "allow_comments": 0, - "allow_delete": 0, - "allow_edit": 0, - "allow_incomplete": 0, - "allow_multiple": 0, - "allow_print": 0, - "amount": 0.0, - "amount_based_on_field": 0, - "apply_document_permissions": 0, - "button_label": "Send", - "client_script": "", - "creation": "2021-03-23 13:10:16.814983", - "doc_type": "LMS Message", - "docstatus": 0, - "doctype": "Web Form", - "idx": 0, - "is_standard": 1, - "login_required": 1, - "max_attachment_size": 0, - "modified": "2021-03-23 19:25:54.984968", - "modified_by": "Administrator", - "module": "LMS", - "name": "add-messages", - "owner": "Administrator", - "payment_button_label": "Buy Now", - "published": 0, - "route": "add-messages", - "route_to_success_link": 0, - "show_attachments": 0, - "show_in_grid": 0, - "show_sidebar": 0, - "sidebar_items": [], - "success_url": "", - "title": "Add Messages", - "web_form_fields": [ - { - "allow_read_on_all_link_options": 0, - "fieldname": "batch", - "fieldtype": "Link", - "hidden": 0, - "label": "Batch", - "max_length": 0, - "max_value": 0, - "options": "LMS Batch", - "read_only": 1, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "message", - "fieldtype": "Data", - "hidden": 0, - "label": "Message", - "max_length": 0, - "max_value": 0, - "read_only": 0, - "reqd": 0, - "show_in_filter": 0 - }, - { - "allow_read_on_all_link_options": 0, - "fieldname": "author", - "fieldtype": "Link", - "hidden": 1, - "label": "Author", - "max_length": 0, - "max_value": 0, - "options": "Community Member", - "read_only": 1, - "reqd": 0, - "show_in_filter": 0 - } - ] -} \ No newline at end of file diff --git a/community/lms/web_form/add_messages/add_messages.py b/community/lms/web_form/add_messages/add_messages.py deleted file mode 100644 index 2334f8b2..00000000 --- a/community/lms/web_form/add_messages/add_messages.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -def get_context(context): - # do your magic here - pass diff --git a/community/public/css/style.css b/community/public/css/style.css index f6ccce78..0038f26d 100644 --- a/community/public/css/style.css +++ b/community/public/css/style.css @@ -287,6 +287,7 @@ img.profile-photo { } .message-section { - margin-left: 5%; + margin-left: 3%; display: inline-block; + width: 95%; } diff --git a/community/www/courses/about/index.html b/community/www/courses/about/index.html index 1b17616c..ef417228 100644 --- a/community/www/courses/about/index.html +++ b/community/www/courses/about/index.html @@ -16,7 +16,7 @@ {% if batch.description %} {{ BatchDetails(batch.description) }} {% endif %} - {{ MentorsSection(mentors, True) }} + {{ MentorsSection(mentors, True, course.name) }} {% endblock %} @@ -43,4 +43,4 @@ {{ frappe.utils.md_to_html(description) }} -{% endmacro %} \ No newline at end of file +{% endmacro %} diff --git a/community/www/courses/about/index.py b/community/www/courses/about/index.py index 238177a6..780fee44 100644 --- a/community/www/courses/about/index.py +++ b/community/www/courses/about/index.py @@ -11,13 +11,11 @@ def get_context(context): context.instructor = get_instructor(context.course.owner) context.batch = get_batch(context.batch_code) context.mentors = get_mentors(context.batch.name) - print(context.mentors) def get_mentors(batch): mentors = [] memberships = frappe.get_all("LMS Batch Membership", {"batch": batch, "member_type": "Mentor"}, ["member"]) for membership in memberships: - member = frappe.db.get_value("Community Member", membership.member, ["name","full_name"], as_dict=True) - member.batch_count = len(frappe.get_all("LMS Batch Membership", {"member": member.name, "member_type": "Mentor"})) + member = frappe.get_doc("Community Member", membership.member) mentors.append(member) - return mentors \ No newline at end of file + return mentors diff --git a/community/www/courses/course.html b/community/www/courses/course.html index 9e974361..3c08fc97 100644 --- a/community/www/courses/course.html +++ b/community/www/courses/course.html @@ -10,7 +10,7 @@
course
-

{{course.title}}

+

{{course.title}}

@@ -28,7 +28,7 @@
@@ -74,7 +74,7 @@
Starting {{frappe.utils.format_date(batch.start_date, "medium")}}
mentors
- {% for m in batch.mentors %} + {% for m in batch.get_mentors() %}
{% if m.photo_url %} @@ -86,9 +86,9 @@
{% if can_manage %} - + {% else %} - + {% endif %}
@@ -111,11 +111,11 @@ {% endfor %}
- Add a new batch + Add a new batch {% else %}

You are a mentor for this course.

- Create your first batch + Create your first batch
{% endif %} {% endmacro %} @@ -123,11 +123,13 @@ {% macro BatchSectionForStudents(course, upcoming_batches) %}

Upcoming Batches

- {% for batch in upcoming_batches %} -
- {{ RenderBatch(batch, can_manage=False) }} +
+ {% for batch in upcoming_batches %} +
+ {{ RenderBatch(batch, can_manage=False) }} +
+ {% endfor %}
- {% endfor %} {% endmacro %} {% macro CourseOutline(course) %} diff --git a/community/www/courses/course.js b/community/www/courses/course.js index 79683fde..ce08b2e0 100644 --- a/community/www/courses/course.js +++ b/community/www/courses/course.js @@ -3,18 +3,19 @@ frappe.ready(() => { frappe.call({ 'method': 'community.lms.doctype.lms_mentor_request.lms_mentor_request.has_requested', 'args': { - course: decodeURIComponent($(".course-title").attr("data-course")), + course: decodeURIComponent($("#course-title").attr("data-course")), }, 'callback': (data) => { if (data.message) { - $(".mentor-request").addClass("hide"); - $(".already-applied").removeClass("hide") + $("#mentor-request").addClass("hide"); + $("#already-applied").removeClass("hide") } } }) } - $(".apply-now").click((e) => { + $("#apply-now").click((e) => { + e.preventDefault(); if (frappe.session.user == "Guest") { window.location.href = "/login"; return; @@ -26,14 +27,15 @@ frappe.ready(() => { }, "callback": (data) => { if (data.message == "OK") { - $(".mentor-request").addClass("hide"); - $(".already-applied").removeClass("hide") + $("#mentor-request").addClass("hide"); + $("#already-applied").removeClass("hide") } } }) }) - $(".cancel-request").click((e) => { + $("#cancel-request").click((e) => { + e.preventDefault() frappe.call({ "method": "community.lms.doctype.lms_mentor_request.lms_mentor_request.cancel_request", "args": { @@ -41,14 +43,15 @@ frappe.ready(() => { }, "callback": (data) => { if (data.message == "OK") { - $(".mentor-request").removeClass("hide"); - $(".already-applied").addClass("hide") + $("#mentor-request").removeClass("hide"); + $("#already-applied").addClass("hide") } } }) }) $(".join-batch").click((e) => { + e.preventDefault() if (frappe.session.user == "Guest") { window.location.href = "/login"; return; @@ -62,7 +65,6 @@ frappe.ready(() => { "callback": (data) => { if (data.message == "OK") { frappe.msgprint(__("You are now a student of this course.")) - $(".upcoming-batches").addClass("hide") } } }) diff --git a/community/www/courses/learn/index.py b/community/www/courses/learn/index.py index b69083d4..6219b647 100644 --- a/community/www/courses/learn/index.py +++ b/community/www/courses/learn/index.py @@ -6,5 +6,3 @@ def get_context(context): context.course = frappe.form_dict["course"] context.batch_code = frappe.form_dict["batch"] redirect_if_not_a_member(context.course, context.batch_code) - - print(context) \ No newline at end of file diff --git a/community/www/dashboard/index.py b/community/www/dashboard/index.py index 9ca3df4f..1172b77a 100644 --- a/community/www/dashboard/index.py +++ b/community/www/dashboard/index.py @@ -1,38 +1,42 @@ import frappe -from ...lms.doctype.lms_sketch.lms_sketch import get_recent_sketches +from community.lms.models import Sketch + def get_context(context): - context.no_cache = 1 - context.member = frappe.get_all("Community Member", {"email": frappe.session.user}, ["name", "email", "photo", "full_name", "abbr"])[0] - context.memberships = get_memberships(context.member.name) - context.courses = get_courses(context.memberships) - context.activity = get_activity(context.memberships) - context.sketches = list(filter(lambda x: x.owner == frappe.session.user, get_recent_sketches())) + context.no_cache = 1 + if frappe.session.user == "Guest": + frappe.local.flags.redirect_location = "/login" + raise frappe.Redirect + context.member = frappe.get_all("Community Member", {"email": frappe.session.user}, ["name", "email", "photo", "full_name", "abbr"])[0] + context.memberships = get_memberships(context.member.name) + context.courses = get_courses(context.memberships) + context.activity = get_activity(context.memberships) + context.sketches = list(filter(lambda x: x.owner == frappe.session.user, Sketch.get_recent_sketches(owner=context.member.email))) def get_memberships(member): - return frappe.get_all("LMS Batch Membership", {"member": member}, ["batch", "member_type", "creation"]) + return frappe.get_all("LMS Batch Membership", {"member": member}, ["batch", "member_type", "creation"]) def get_courses(memberships): - courses = [] - for membership in memberships: - course = frappe.db.get_value("LMS Batch", membership.batch, "course") - course_details = frappe.get_doc("LMS Course", course) - course_in_list = list(filter(lambda x: x.name == course_details.name, courses)) - if not len(course_in_list): - course_details.description = course_details.description[0:100] + "..." - course_details.joining = membership.creation - if membership.member_type != "Student": - course_details.member_type = membership.member_type - courses.append(course_details) - return courses + courses = [] + for membership in memberships: + course = frappe.db.get_value("LMS Batch", membership.batch, "course") + course_details = frappe.get_doc("LMS Course", course) + course_in_list = list(filter(lambda x: x.name == course_details.name, courses)) + if not len(course_in_list): + course_details.description = course_details.description[0:100] + "..." + course_details.joining = membership.creation + if membership.member_type != "Student": + course_details.member_type = membership.member_type + courses.append(course_details) + return courses def get_activity(memberships): - messages, courses = [], {} - batches = [x.batch for x in memberships] - for batch in batches: - courses[batch] = frappe.db.get_value("LMS Batch", batch, "course") - messages = frappe.get_all("LMS Message", {"batch": ["in", ",".join(batches)]}, ["message", "author", "creation", "batch"], order_by='creation desc') - for message in messages: - message.course = courses[message.batch] - message.profile, message.full_name, message.abbr = frappe.db.get_value("Community Member", message.author, ["photo", "full_name", "abbr"]) - return messages \ No newline at end of file + messages, courses = [], {} + batches = [x.batch for x in memberships] + for batch in batches: + courses[batch] = frappe.db.get_value("LMS Batch", batch, "course") + messages = frappe.get_all("LMS Message", {"batch": ["in", ",".join(batches)]}, ["message", "author", "creation", "batch"], order_by='creation desc') + for message in messages: + message.course = courses[message.batch] + message.profile, message.full_name, message.abbr = frappe.db.get_value("Community Member", message.author, ["photo", "full_name", "abbr"]) + return messages diff --git a/community/www/macros/common_macro.html b/community/www/macros/common_macro.html index ab21effd..85e7d6b5 100644 --- a/community/www/macros/common_macro.html +++ b/community/www/macros/common_macro.html @@ -6,7 +6,7 @@
{% endmacro %} -{% macro MentorsSection(mentors, is_mentor) %} +{% macro MentorsSection(mentors, is_mentor, course_name) %}

Mentors

{% for m in mentors %}
@@ -15,10 +15,15 @@
{% endfor %} {% if not is_mentor %} -
+
Interested to become a mentor? - + +
+
+ You've applied to become a mentor for this course. Your request is currently under review. + + If you are not any more interested to mentor this course, you can cancel your application.
{% endif %} {% endmacro %} @@ -26,7 +31,7 @@ {% macro BatchHearder(course_name, member_count) %}
-

{{course_name}}

-
{{member_count}} members
+

{{course_name}}

+
{{member_count}} members
{% endmacro %} diff --git a/community/www/profiles/profile.py b/community/www/profiles/profile.py index cbb48edd..d4229a30 100644 --- a/community/www/profiles/profile.py +++ b/community/www/profiles/profile.py @@ -1,5 +1,5 @@ import frappe -from ...lms.doctype.lms_sketch.lms_sketch import get_recent_sketches +from community.lms.models import Sketch def get_context(context): context.no_cache = 1 @@ -8,7 +8,7 @@ def get_context(context): if not context.member: context.template = "www/404.html" else: - context.sketches = list(filter(lambda x: x.owner == context.member.email, get_recent_sketches())) + context.sketches = Sketch.get_recent_sketches(owner=context.member.email) def get_member(username): try: diff --git a/license.txt b/license.txt index 2fdf7c7c..c013ae70 100644 --- a/license.txt +++ b/license.txt @@ -1 +1 @@ -License: MIT \ No newline at end of file +License: AGPL