From 52f16131affdf437ba674126668b60f7751498d9 Mon Sep 17 00:00:00 2001 From: pateljannat Date: Sat, 1 May 2021 14:37:57 +0530 Subject: [PATCH] fix: add new batch form enhancements (#43) invite request doctype and flow (#42) --- .../community_course_member.py | 15 --- community/hooks.py | 4 +- .../lms/doctype/invite_request/__init__.py | 0 .../doctype/invite_request/invite_request.js | 8 ++ .../invite_request/invite_request.json | 100 ++++++++++++++++++ .../doctype/invite_request/invite_request.py | 73 +++++++++++++ .../invite_request/test_invite_request.py | 10 ++ .../lms/doctype/lms_batch/lms_batch.json | 7 +- .../lms_batch_membership.py | 7 +- .../lms_mentor_request/lms_mentor_request.py | 6 +- .../doctype/lms_settings/lms_settings.json | 11 +- .../add_a_new_batch/add_a_new_batch.js | 16 ++- .../add_a_new_batch/add_a_new_batch.json | 13 +-- .../emails/lms_invite_request_approved.html | 18 ++++ community/www/courses/course.html | 4 +- community/www/new-sign-up.html | 65 ++++++++++++ community/www/profiles/profile.py | 6 +- 17 files changed, 323 insertions(+), 40 deletions(-) create mode 100644 community/lms/doctype/invite_request/__init__.py create mode 100644 community/lms/doctype/invite_request/invite_request.js create mode 100644 community/lms/doctype/invite_request/invite_request.json create mode 100644 community/lms/doctype/invite_request/invite_request.py create mode 100644 community/lms/doctype/invite_request/test_invite_request.py create mode 100644 community/templates/emails/lms_invite_request_approved.html create mode 100644 community/www/new-sign-up.html diff --git a/community/community/doctype/community_course_member/community_course_member.py b/community/community/doctype/community_course_member/community_course_member.py index 06861201..8455178f 100644 --- a/community/community/doctype/community_course_member/community_course_member.py +++ b/community/community/doctype/community_course_member/community_course_member.py @@ -50,18 +50,3 @@ class CommunityCourseMember(WebsiteGenerator): send_priority=0, queue_separately=True, args=args) - - def create_user(self): - user = frappe.get_doc({ - "doctype": "User", - "email": self.email, - "first_name": self.full_name.split(" ")[0], - "full_name": self.full_name, - "username": self.user_name, - "send_welcome_email": 0, - "user_type": 'Website User', - "redirect_url": self.name - }) - user.save(ignore_permissions=True) - update_password_link = user.reset_password() - return user, update_password_link diff --git a/community/hooks.py b/community/hooks.py index 90ad31b8..eec63a4f 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": ""}, @@ -163,7 +162,8 @@ whitelist = [ "/hackathons", "/dashboard", "/join-request" - "/add-a-new-batch" + "/add-a-new-batch", + "/new-sign-up" ] whitelist_rules = [{"from_route": p, "to_route": p[1:]} for p in whitelist] diff --git a/community/lms/doctype/invite_request/__init__.py b/community/lms/doctype/invite_request/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/community/lms/doctype/invite_request/invite_request.js b/community/lms/doctype/invite_request/invite_request.js new file mode 100644 index 00000000..9f9006b7 --- /dev/null +++ b/community/lms/doctype/invite_request/invite_request.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, FOSS United and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Invite Request', { + // refresh: function(frm) { + + // } +}); diff --git a/community/lms/doctype/invite_request/invite_request.json b/community/lms/doctype/invite_request/invite_request.json new file mode 100644 index 00000000..426f53e0 --- /dev/null +++ b/community/lms/doctype/invite_request/invite_request.json @@ -0,0 +1,100 @@ +{ + "actions": [], + "creation": "2021-04-29 16:29:56.857914", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "invite_email", + "signup_email", + "column_break_4", + "status", + "full_name", + "username", + "invite_code" + ], + "fields": [ + { + "allow_in_quick_entry": 1, + "fieldname": "invite_email", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Invite Email", + "options": "Email", + "unique": 1 + }, + { + "fieldname": "full_name", + "fieldtype": "Data", + "label": "Full Name" + }, + { + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, + { + "fieldname": "signup_email", + "fieldtype": "Data", + "label": "Signup Email", + "options": "Email" + }, + { + "fieldname": "username", + "fieldtype": "Data", + "label": "Username" + }, + { + "fieldname": "invite_code", + "fieldtype": "Data", + "label": "Invite Code" + }, + { + "default": "Pending", + "fieldname": "status", + "fieldtype": "Select", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Status", + "options": "Pending\nApproved\nRejected\nRegistered" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-05-01 13:59:27.624814", + "modified_by": "Administrator", + "module": "LMS", + "name": "Invite Request", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Guest", + "share": 1, + "write": 1 + } + ], + "quick_entry": 1, + "search_fields": "invite_email, signup_email", + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "invite_email", + "track_changes": 1 +} \ No newline at end of file diff --git a/community/lms/doctype/invite_request/invite_request.py b/community/lms/doctype/invite_request/invite_request.py new file mode 100644 index 00000000..39ca37c7 --- /dev/null +++ b/community/lms/doctype/invite_request/invite_request.py @@ -0,0 +1,73 @@ +# -*- 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 +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": + self.send_email() + + def create_user(self, password): + user = frappe.get_doc({ + "doctype": "User", + "email": self.signup_email, + "first_name": self.full_name.split(" ")[0], + "full_name": self.full_name, + "username": self.username, + "send_welcome_email": 0, + "user_type": 'Website User', + "new_password": password + }) + user.save(ignore_permissions=True) + return user + + def send_email(self): + subject = _("Your request has been approved.") + args = { + "full_name": self.full_name, + "signup_form_link": "/new-sign-up?invite_code={0}".format(self.name), + "site_url": frappe.utils.get_url() + } + frappe.sendmail( + recipients=self.invite_email, + sender=frappe.db.get_single_value("LMS Settings", "email_sender"), + subject=subject, + header=[subject, "green"], + template = "lms_invite_request_approved", + args=args) + +@frappe.whitelist(allow_guest=True) +def create_invite_request(email): + frappe.get_doc({ + "doctype": "Invite Request", + "invite_email": email + }).save(ignore_permissions=True) + +@frappe.whitelist(allow_guest=True) +def update_invite(data): + data = frappe._dict(json.loads(data)) + + try: + doc = frappe.get_doc("Invite Request", data.invite_code) + except frappe.DoesNotExistError: + frappe.throw(_("Invalid Invite Code.")) + + doc.signup_email = data.signup_email + doc.username = data.username + doc.full_name = data.full_name + doc.invite_code = data.invite_code + doc.save(ignore_permissions=True) + + user = doc.create_user(data.password) + if user: + doc.status = "Registered" + doc.save(ignore_permissions=True) + + return "OK" \ No newline at end of file diff --git a/community/lms/doctype/invite_request/test_invite_request.py b/community/lms/doctype/invite_request/test_invite_request.py new file mode 100644 index 00000000..557d95e9 --- /dev/null +++ b/community/lms/doctype/invite_request/test_invite_request.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2021, FOSS United and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestInviteRequest(unittest.TestCase): + pass diff --git a/community/lms/doctype/lms_batch/lms_batch.json b/community/lms/doctype/lms_batch/lms_batch.json index 0e7f5de1..8f0b94f0 100644 --- a/community/lms/doctype/lms_batch/lms_batch.json +++ b/community/lms/doctype/lms_batch/lms_batch.json @@ -27,6 +27,8 @@ { "fieldname": "course", "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, "label": "Course", "options": "LMS Course" }, @@ -91,11 +93,13 @@ { "fieldname": "start_date", "fieldtype": "Date", + "in_list_view": 1, "label": "Start Date" }, { "fieldname": "start_time", "fieldtype": "Time", + "in_list_view": 1, "label": "Start Time" }, { @@ -106,6 +110,7 @@ { "fieldname": "end_time", "fieldtype": "Time", + "in_list_view": 1, "label": "End Time" } ], @@ -117,7 +122,7 @@ "link_fieldname": "batch" } ], - "modified": "2021-04-21 12:45:21.144972", + "modified": "2021-04-30 09:52:18.941276", "modified_by": "Administrator", "module": "LMS", "name": "LMS Batch", 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 87ae7962..ba218209 100644 --- a/community/lms/doctype/lms_batch_membership/lms_batch_membership.py +++ b/community/lms/doctype/lms_batch_membership/lms_batch_membership.py @@ -14,7 +14,7 @@ class LMSBatchMembership(Document): 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}, ["member_type","member"], as_dict=1) + 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)) @@ -29,7 +29,7 @@ class LMSBatchMembership(Document): 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, member=None, member_type="Student", role="Member"): +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({ @@ -39,4 +39,5 @@ def create_membership(batch, member=None, member_type="Student", role="Member"): "member_type": member_type, "member": member }).save(ignore_permissions=True) - return "OK" \ No newline at end of file + course_slug = frappe.db.get_value("LMS Course", {"title": course}, ["slug"]) + return course_slug \ No newline at end of file diff --git a/community/lms/doctype/lms_mentor_request/lms_mentor_request.py b/community/lms/doctype/lms_mentor_request/lms_mentor_request.py index 640bd94b..b98a2f45 100644 --- a/community/lms/doctype/lms_mentor_request/lms_mentor_request.py +++ b/community/lms/doctype/lms_mentor_request/lms_mentor_request.py @@ -79,7 +79,7 @@ def send_creation_email(course, member): subject = _('Request for Mentorship') send_email([frappe.session.user, get_course_author(course)], None, subject, message) -def send_email(recipients, cc, subject, message): +def send_email(recipients, cc=None, subject=None, message=None, template=None, args=None): frappe.sendmail( recipients = recipients, cc = cc, @@ -87,5 +87,7 @@ def send_email(recipients, cc, subject, message): subject = subject, send_priority = 0, queue_separately = True, - message = message + message = message, + template=template, + args=args ) \ No newline at end of file diff --git a/community/lms/doctype/lms_settings/lms_settings.json b/community/lms/doctype/lms_settings/lms_settings.json index b08996d2..f5b7a03f 100644 --- a/community/lms/doctype/lms_settings/lms_settings.json +++ b/community/lms/doctype/lms_settings/lms_settings.json @@ -6,10 +6,11 @@ "engine": "InnoDB", "field_order": [ "livecode_url", + "column_break_2", + "email_sender", "mentor_request_section", "mentor_request_creation", - "mentor_request_status_update", - "email_sender" + "mentor_request_status_update" ], "fields": [ { @@ -40,12 +41,16 @@ "fieldname": "mentor_request_section", "fieldtype": "Section Break", "label": "Mentor Request" + }, + { + "fieldname": "column_break_2", + "fieldtype": "Column Break" } ], "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-04-21 13:28:35.783395", + "modified": "2021-04-29 17:14:43.589700", "modified_by": "Administrator", "module": "LMS", "name": "LMS Settings", diff --git a/community/lms/web_form/add_a_new_batch/add_a_new_batch.js b/community/lms/web_form/add_a_new_batch/add_a_new_batch.js index 6cabe776..7ffcc114 100644 --- a/community/lms/web_form/add_a_new_batch/add_a_new_batch.js +++ b/community/lms/web_form/add_a_new_batch/add_a_new_batch.js @@ -5,27 +5,35 @@ frappe.ready(function () { "method": "community.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership", "args": { "batch": data.title, - "member_type": "Mentor" + "member_type": "Mentor", + "course": data.course }, "callback": (data) => { - if (data.message == "OK") { - window.location.href = "/courses" + if (data.message) { + window.location.href = `courses/${data.message}` } } }) } frappe.web_form.validate = () => { + let sysdefaults = frappe.boot.sysdefaults; + let time_format = sysdefaults && sysdefaults.time_format ? sysdefaults.time_format : 'HH:mm:ss'; let data = frappe.web_form.get_values(); + + data.start_time = moment(data.start_time,time_format).format(time_format) + data.end_time = moment(data.end_time,time_format).format(time_format) + if (!frappe.datetime.validate(data.start_time) || !frappe.datetime.validate(data.end_time)) { frappe.msgprint(__('Invalid Start or End Time.')); return false; } + if (data.start_time > data.end_time) { frappe.msgprint(__('Start Time should be less than End Time.')); return false; } - console.log(data.start_date, date.nowdate()) + if (data.start_date < date.nowdate()) { frappe.msgprint(__('Start date cannot be a past date.')) return false; diff --git a/community/lms/web_form/add_a_new_batch/add_a_new_batch.json b/community/lms/web_form/add_a_new_batch/add_a_new_batch.json index 61903c7c..8d384728 100644 --- a/community/lms/web_form/add_a_new_batch/add_a_new_batch.json +++ b/community/lms/web_form/add_a_new_batch/add_a_new_batch.json @@ -11,6 +11,7 @@ "apply_document_permissions": 0, "button_label": "Save", "creation": "2021-04-20 11:37:49.135114", + "custom_css": ".datepicker.active {\n background-color: white;\n}", "doc_type": "LMS Batch", "docstatus": 0, "doctype": "Web Form", @@ -18,7 +19,7 @@ "is_standard": 1, "login_required": 1, "max_attachment_size": 0, - "modified": "2021-04-26 11:08:00.026388", + "modified": "2021-04-30 11:22:18.188712", "modified_by": "Administrator", "module": "LMS", "name": "add-a-new-batch", @@ -37,13 +38,13 @@ { "allow_read_on_all_link_options": 0, "fieldname": "course", - "fieldtype": "Link", + "fieldtype": "Data", "hidden": 0, "label": "Course", "max_length": 0, "max_value": 0, - "options": "LMS Course", - "read_only": 0, + "options": "", + "read_only": 1, "reqd": 0, "show_in_filter": 0 }, @@ -90,7 +91,7 @@ "fieldname": "start_time", "fieldtype": "Data", "hidden": 0, - "label": "Start Time (HH:MM:SS)", + "label": "Start Time", "max_length": 0, "max_value": 0, "read_only": 0, @@ -102,7 +103,7 @@ "fieldname": "end_time", "fieldtype": "Data", "hidden": 0, - "label": "End Time (HH:MM:SS)", + "label": "End Time", "max_length": 0, "max_value": 0, "read_only": 0, diff --git a/community/templates/emails/lms_invite_request_approved.html b/community/templates/emails/lms_invite_request_approved.html new file mode 100644 index 00000000..0b454f91 --- /dev/null +++ b/community/templates/emails/lms_invite_request_approved.html @@ -0,0 +1,18 @@ +
+ {% set site_link = "" + site_url + "" %} +

{{_("Dear Community Member,")}}

+

{{_("Your Invite Request to be a part of {0} has + been approved.").format(site_link)}}

+

Click on the link below to complete your Sign up and set a new password

+

+ {{ _("Complete Sign Up") }} +

+
+

+ {{_("You can also copy-paste following link in your browser")}}
+ {{ site_url }}{{ signup_form_link }} +

+
+

Thanks and Regards,

+

Your Community.

+
\ No newline at end of file diff --git a/community/www/courses/course.html b/community/www/courses/course.html index 5989e0f6..ef365089 100644 --- a/community/www/courses/course.html +++ b/community/www/courses/course.html @@ -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 %} diff --git a/community/www/new-sign-up.html b/community/www/new-sign-up.html new file mode 100644 index 00000000..51247f4a --- /dev/null +++ b/community/www/new-sign-up.html @@ -0,0 +1,65 @@ +{% extends "templates/web.html" %} + +{% block title %} {{_("New Sign Up")}} {% endblock %} + +{% block page_content %} + +
+
+ +
+
+ +
+
+ +
+
+ + + +
+ +
+ +
+ +
+ + + +{% endblock %} \ No newline at end of file diff --git a/community/www/profiles/profile.py b/community/www/profiles/profile.py index cbb48edd..30c5b2a5 100644 --- a/community/www/profiles/profile.py +++ b/community/www/profiles/profile.py @@ -1,14 +1,16 @@ 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.username = frappe.form_dict["username"] + print(frappe.form_dict["username"]) context.member = get_member(context.username) + print(context.member) 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 = list(filter(lambda x: x.owner == context.member.email, Sketch.get_recent_sketches())) def get_member(username): try: