Compare commits
2 Commits
sketch-red
...
upcoming-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9b4fe468e | ||
|
|
6cbca8d1bb |
@@ -13,6 +13,38 @@ from ...utils import slugify
|
|||||||
|
|
||||||
class LMSCourse(Document):
|
class LMSCourse(Document):
|
||||||
|
|
||||||
|
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"])
|
||||||
|
subject = self.title + " is available!"
|
||||||
|
args = {
|
||||||
|
"title": self.title,
|
||||||
|
"course_link": "/courses/{0}".format(self.name),
|
||||||
|
"app_name": frappe.db.get_single_value("System Settings", "app_name"),
|
||||||
|
"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,
|
||||||
|
sender = frappe.db.get_single_value("LMS Settings", "email_sender"),
|
||||||
|
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)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def find(name):
|
def find(name):
|
||||||
"""Returns the course with specified name.
|
"""Returns the course with specified name.
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2021, FOSS United and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('LMS Course Interest', {
|
||||||
|
// refresh: function(frm) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
});
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"creation": "2021-08-06 17:37:20.184849",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"course",
|
||||||
|
"user",
|
||||||
|
"email_sent"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "course",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Course",
|
||||||
|
"options": "LMS Course"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "user",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "User",
|
||||||
|
"options": "User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "email_sent",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Email Sent",
|
||||||
|
"options": "email_sent"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2021-08-06 18:06:21.370741",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "LMS Course Interest",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Copyright (c) 2021, FOSS United and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class LMSCourseInterest(Document):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def capture_interest(course):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "LMS Course Interest",
|
||||||
|
"course": course,
|
||||||
|
"user": frappe.session.user
|
||||||
|
}).save(ignore_permissions=True)
|
||||||
|
return "OK"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Copyright (c) 2021, FOSS United and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestLMSCourseInterest(unittest.TestCase):
|
||||||
|
pass
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
{% set query_parameter = "?batch=" + membership.batch if membership and membership.batch else "" %}
|
{% set query_parameter = "?batch=" + membership.batch if membership and membership.batch else "" %}
|
||||||
|
|
||||||
{% if course.upcoming %}
|
{% if course.upcoming %}
|
||||||
<div class="view-course-link is-default">
|
<div class="view-course-link is-secondary border">
|
||||||
Upcoming Course <img class="ml-3" src="/assets/community/icons/black-arrow.svg" />
|
Upcoming Course <img class="ml-3" src="/assets/community/icons/black-arrow.svg" />
|
||||||
</div>
|
</div>
|
||||||
<a class="stretched-link" href="/courses/{{ course.name }}"></a>
|
<a class="stretched-link" href="/courses/{{ course.name }}"></a>
|
||||||
|
|||||||
16
community/lms/widgets/SketchTeaser.html
Normal file
16
community/lms/widgets/SketchTeaser.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<div class="sketch-teaser">
|
||||||
|
<div class="sketch-image">
|
||||||
|
<a href="/sketches/{{sketch.sketch_id}}">
|
||||||
|
{{ sketch.to_svg() }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="sketch-footer">
|
||||||
|
<div class="sketch-title">
|
||||||
|
<a href="sketches/{{sketch.sketch_id}}">{{sketch.title}}</a>
|
||||||
|
</div>
|
||||||
|
<div class="sketch-author">
|
||||||
|
{% set owner = sketch.get_owner() %}
|
||||||
|
by <a href="/{{owner.username}}">{{owner.full_name}}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -635,6 +635,11 @@ input[type=checkbox] {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 135%;
|
line-height: 135%;
|
||||||
letter-spacing: -0.011em;
|
letter-spacing: -0.011em;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wide-button {
|
.wide-button {
|
||||||
@@ -660,6 +665,11 @@ input[type=checkbox] {
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-default {
|
||||||
|
background: #98A1A9;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.video-preview {
|
.video-preview {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
@@ -676,12 +686,6 @@ input[type=checkbox] {
|
|||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-default {
|
|
||||||
background-color: white;
|
|
||||||
border: 1px solid #C8CFD5;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.course-home-outline {
|
.course-home-outline {
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M13.0746 3.60967C12.7814 3.31071 12.4333 3.07355 12.0501 2.91174C11.6669 2.74994 11.2562 2.66666 10.8415 2.66666C10.4267 2.66666 10.016 2.74994 9.63283 2.91174C9.24966 3.07355 8.90152 3.31071 8.60831 3.60967L7.99979 4.22983L7.39126 3.60967C6.79899 3.00607 5.9957 2.66697 5.1581 2.66697C4.32051 2.66697 3.51721 3.00607 2.92494 3.60967C2.33267 4.21327 1.99994 5.03192 1.99994 5.88554C1.99994 6.73916 2.33267 7.55782 2.92494 8.16142L3.53347 8.78158L7.99979 13.3333L12.4661 8.78158L13.0746 8.16142C13.368 7.86259 13.6007 7.5078 13.7595 7.11729C13.9182 6.72679 13.9999 6.30824 13.9999 5.88554C13.9999 5.46284 13.9182 5.04429 13.7595 4.65379C13.6007 4.26329 13.368 3.90849 13.0746 3.60967V3.60967Z" stroke="#4C5A67" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 871 B |
19
community/templates/emails/lms_course_interest.html
Normal file
19
community/templates/emails/lms_course_interest.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<div>
|
||||||
|
{% set site_link = "<a href='" + site_url + "'>" + app_name + "</a>" %}
|
||||||
|
<p>{{ _("Hi {0},").format(first_name) }}</p>
|
||||||
|
<br>
|
||||||
|
<p>{{ _("The course {0} is now available on {1}.").format(frappe.bold(title), app_name) }}</p>
|
||||||
|
<br>
|
||||||
|
<p>Click on the link below to start learning.</p>
|
||||||
|
<p style="margin: 15px 0px;">
|
||||||
|
<a href="{{ course_link }}" rel="nofollow" class="btn btn-primary">{{ _("Start Learning") }}</a>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<p>
|
||||||
|
{{ _("You can also copy-paste following link in your browser") }}<br>
|
||||||
|
<a href="{{ course_link }}">{{ site_url }}{{ course_link }}</a>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<p>Thanks and Regards,</p>
|
||||||
|
<p>{{ app_name }}</p>
|
||||||
|
</div>
|
||||||
@@ -58,6 +58,12 @@
|
|||||||
Continue Learning <img class="ml-2" src="/assets/community/icons/white-arrow.svg" />
|
Continue Learning <img class="ml-2" src="/assets/community/icons/white-arrow.svg" />
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if course.upcoming %}
|
||||||
|
<button class="button wide-button is-default" id="notify-me" data-course="{{course.name | urlencode}}"
|
||||||
|
{% if is_user_interested %} disabled="disabled" title="Your interest has already been noted." {% endif %} >
|
||||||
|
Notify me when available
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
{% if course.video_link %}
|
{% if course.video_link %}
|
||||||
<div class="button wide-button is-secondary video-preview">
|
<div class="button wide-button is-secondary video-preview">
|
||||||
Watch Video Preview
|
Watch Video Preview
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ frappe.ready(() => {
|
|||||||
submit_review(e);
|
submit_review(e);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$("#notify-me").click((e) => {
|
||||||
|
notify_user(e);
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
var check_mentor_request = () => {
|
var check_mentor_request = () => {
|
||||||
@@ -209,3 +213,23 @@ var submit_review = (e) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var notify_user = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
var course = decodeURIComponent($(e.currentTarget).attr("data-course"));
|
||||||
|
if (frappe.session.user == "Guest") {
|
||||||
|
window.location.href = `/login?redirect-to=/courses/${course}`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.call({
|
||||||
|
method: "community.lms.doctype.lms_course_interest.lms_course_interest.capture_interest",
|
||||||
|
args: {
|
||||||
|
"course": course
|
||||||
|
},
|
||||||
|
callback: (data) => {
|
||||||
|
frappe.msgprint(__("Your interest has been noted. We'll notify you via email when this course becomes available."));
|
||||||
|
$("#notify-me").attr("disabled", true).attr("title", "Your interest has already been noted");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,9 +18,18 @@ def get_context(context):
|
|||||||
membership = course.get_membership(frappe.session.user)
|
membership = course.get_membership(frappe.session.user)
|
||||||
context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else ""
|
context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else ""
|
||||||
context.membership = membership
|
context.membership = membership
|
||||||
|
if context.course.upcoming:
|
||||||
|
context.is_user_interested = get_user_interest(context.course.name)
|
||||||
context.metatags = {
|
context.metatags = {
|
||||||
"title": course.title,
|
"title": course.title,
|
||||||
"image": course.image,
|
"image": course.image,
|
||||||
"description": course.short_introduction,
|
"description": course.short_introduction,
|
||||||
"keywords": course.title
|
"keywords": course.title
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_user_interest(course):
|
||||||
|
return frappe.db.count("LMS Course Interest",
|
||||||
|
{
|
||||||
|
"course": course,
|
||||||
|
"user": frappe.session.user
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user