feat: #28 info page, #27 discussion page initial structure, add batch webform change

This commit is contained in:
pateljannat
2021-04-27 10:33:49 +05:30
parent 44dc42d7dd
commit 424967b03e
18 changed files with 372 additions and 185 deletions

View File

@@ -1,5 +1,7 @@
{% extends "templates/base.html" %}
{% from "www/macros/sidebar.html" import Sidebar %}
{% from "www/macros/common_macro.html" import InstructorsSection, MentorsSection %}
{% block title %}About{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
@@ -7,7 +9,38 @@
{% endblock %}
{% block content %}
{{ Sidebar(course, batch_code) }}
{{ Sidebar(course_slug, batch_code) }}
<div class="container">
{{ CourseBasicDetail(course)}}
{{ InstructorsSection(instructor) }}
{% if batch.description %}
{{ BatchDetails(batch.description) }}
{% endif %}
{{ MentorsSection(mentors, True) }}
</div>
{% endblock %}
{% macro CourseBasicDetail(course) %}
<h2>{{course.name}}</h2>
<div class="course-description">
{{course.short_introduction}}
</div>
{% if course.video_link %}
<div class="preview-video">
<iframe width="560" height="315" src="{{course.video_link}}" title="YouTube video player" frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen></iframe>
</div>
{% endif %}
<h2>About the Course</h2>
<div>{{frappe.utils.md_to_html(course.description)}}</div>
{% endmacro %}
{% macro BatchDetails(description) %}
<div class="mt-5">
<h3>About the Batch</h3>
<div>
{{ frappe.utils.md_to_html(description) }}
</div>
</div>
{% endmacro %}

View File

@@ -1,8 +1,23 @@
import frappe
from community.www.courses.utils import redirect_if_not_a_member
from community.www.courses.utils import redirect_if_not_a_member, get_course, get_instructor, get_batch
def get_context(context):
context.no_cache = 1
context.course = frappe.form_dict["course"]
context.course_slug = frappe.form_dict["course"]
context.course = get_course(context.course_slug)
context.batch_code = frappe.form_dict["batch"]
redirect_if_not_a_member(context.course, context.batch_code)
redirect_if_not_a_member(context.course_slug, context.batch_code)
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"}))
mentors.append(member)
return mentors

View File

@@ -1,4 +1,5 @@
{% extends "templates/base.html" %}
{% from "www/macros/common_macro.html" import InstructorsSection, MentorsSection %}
{% block title %}{{ course.title }}{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
@@ -27,7 +28,7 @@
</div>
<div class="sidebar">
{{ MentorsSection(mentors) }}
{{ MentorsSection(mentors, is_mentor) }}
</div>
</div>
</div>
@@ -59,7 +60,7 @@
{% macro BatchSection(course, is_mentor, upcoming_batches, mentor_batches) %}
{% if is_mentor %}
{{ BatchSectionForMentors(course, mentor_batches) }}
{% else %}
{% else %}
{{ BatchSectionForStudents(course, upcoming_batches) }}
{% endif %}
{% endmacro %}
@@ -152,27 +153,3 @@
</div>
{% endfor %}
{% endmacro %}
{% macro InstructorsSection(instructor) %}
<h3>Instructor</h3>
<div class="instructor">
<div class="instructor-title">{{instructor.full_name}}</div>
<div class="instructor-subtitle">Created {{instructor.course_count}} courses</div>
</div>
{% endmacro %}
{% macro MentorsSection(instructor) %}
<h3>Mentors</h3>
{% for m in mentors %}
<div class="instructor">
<div class="instructor-title">{{m.full_name}}</div>
<div class="instructor-subtitle">Mentored {{m.batch_count}} batches</div>
</div>
{% endfor %}
<div class="notice">
Interested to become a mentor?
<div><a href="#">Apply Now!</a></div>
</div>
{% endmacro %}

View File

@@ -1,4 +1,15 @@
frappe.ready(() => {
frappe.require("/assets/frappe/js/lib/socket.io.min.js");
frappe.require("/assets/frappe/js/frappe/socketio_client.js");
if (window.dev_server) {
frappe.boot.socketio_port = "9000" //use socketio port shown when bench starts
}
frappe.socketio.init();
console.log(frappe.socketio)
//frappe.socketio.emittedDemo("mydata");
frappe.realtime.on("new_lms_message", (data) => {
console.log(data)
})
if (frappe.session.user != "Guest") {
frappe.call({
'method': 'community.lms.doctype.lms_mentor_request.lms_mentor_request.has_requested',
@@ -29,28 +40,6 @@ frappe.ready(() => {
})
})
$(".send-message").click((e) => {
var message = $(".message-text").val().trim();
if (message) {
frappe.call({
"method": "community.www.courses.course.save_message",
"args": {
"batch": decodeURIComponent($(e.target).attr("data-batch")),
"author": decodeURIComponent($(e.target).attr("data-author")),
"message": message
},
"callback": (data) => {
$(".message-text").val("");
var element = add_message(data.message, true)
$(".discussions").prepend(element);
}
})
}
else {
$(".message-text").val("");
}
})
$(".apply-now").click((e) => {
if (frappe.session.user == "Guest") {
window.location.href = "/login";
@@ -104,15 +93,6 @@ frappe.ready(() => {
}
})
})
var add_message = (message, session_user = false) => {
var author_name = session_user ? "You" : message.author_name
return `<div class="list-group-item">
<h6> ${author_name} </h6>
${message.message}
<div class="small text-muted text-right"> ${message.creation} </div>
</div>`;
}
})
/*
var show_enrollment_badge = () => {

View File

@@ -1,4 +1,5 @@
import frappe
from community.www.courses.utils import get_instructor
from frappe.utils import nowdate, getdate
def get_context(context):
@@ -61,16 +62,6 @@ def get_membership(batches):
memberships.append(membership)
return memberships
def get_instructor(owner):
instructor = frappe._dict()
try:
instructor = frappe.get_doc("Community Member", {"email": owner})
except frappe.DoesNotExistError:
instructor.full_name = owner
instructor.abbr = ("").join([ s[0] for s in owner.split() ])
instructor.course_count = len(frappe.get_all("LMS Course", {"owner": owner}))
return instructor
def get_mentors(course):
course_mentors = []
mentors = frappe.get_all("LMS Course Mentor Mapping", {"course": course}, ["mentor"])
@@ -108,25 +99,3 @@ def is_mentor(course):
if len(mapping):
return True
@frappe.whitelist()
def get_messages(batch):
messages = frappe.get_all("LMS Message", {"batch": batch}, ["*"], order_by="creation desc")
for message in messages:
message.message = frappe.utils.md_to_html(message.message)
message.creation = frappe.utils.format_datetime(message.creation, "medium")
message.author_name, member_email = frappe.db.get_value("Community Member", message.author, ["full_name","email"])
if member_email == frappe.session.user:
message.author_name = "You"
return messages
@frappe.whitelist()
def save_message(message, author, batch):
doc = frappe.get_doc({
"doctype": "LMS Message",
"author": author,
"batch": batch,
"message": message
})
doc.save(ignore_permissions=True)
return doc

View File

@@ -1,5 +1,7 @@
{% extends "templates/base.html" %}
{% from "www/macros/sidebar.html" import Sidebar %}
{% from "www/macros/common_macro.html" import BatchHearder %}
{% block title %}Discuss{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
@@ -7,7 +9,40 @@
{% endblock %}
{% block content %}
{{ Sidebar(course, batch_code) }}
<div class="container">
{{ Sidebar(course_slug, batch_code) }}
<div class="">
<div class="batch-header">
{{ BatchHearder(course.name, member_count) }}
</div>
<div class="message-section">
{{ Messages(messages) }}
</div>
{{ TextArea() }}
</div>
{% endblock %}
{% macro Messages(messages) %}
{% for message in messages %}
<div class="discussion {% if message.is_author %} is-author {% endif %}">
<div class="d-flex justify-content-between">
<div class="font-weight-bold">
{{ message.author_name }}
</div>
<div class="text-muted">
{{ frappe.utils.pretty_date(message.creation) }}
</div>
</div>
<div class="mt-5">
{{ message.message }}
</div>
</div>
{% endfor %}
{% endmacro %}
{% macro TextArea() %}
<form class="msger-inputarea">
<input type="text" class="msger-input" placeholder="Write your message...">
<button type="submit" class="msger-send-btn" data-batch="{{batch.name | urlencode }}">Send</button>
</form>
{% endmacro %}

View File

@@ -0,0 +1,41 @@
frappe.ready(() => {
const assets = [
"/assets/frappe/js/lib/socket.io.min.js",
"/assets/frappe/js/frappe/socketio_client.js"
]
frappe.require(assets, () => {
if (window.dev_server) {
frappe.boot.socketio_port = "9000" //use socketio port shown when bench starts
}
frappe.socketio.init(9000);
console.log(frappe.socketio)
})
frappe.realtime.on("new_lms_message", (data) => {
console.log(data)
})
setTimeout(() => {
window.scrollTo(0, document.body.scrollHeight);
}, 0);
$(".msger-send-btn").click((e) => {
e.preventDefault();
var message = $(".msger-input").val().trim();
if (message) {
frappe.call({
"method": "community.lms.doctype.lms_batch.lms_batch.save_message",
"args": {
"batch": decodeURIComponent($(e.target).attr("data-batch")),
"message": message
},
"callback": (data) => {
$(".msger-input").val("");
frappe.realtime.publish("new_lms_message", {"message":"JJK"})
}
})
}
else {
$(".msger-input").val("");
}
})
})

View File

@@ -1,8 +1,15 @@
import frappe
from community.www.courses.utils import redirect_if_not_a_member
from community.www.courses.utils import redirect_if_not_a_member, get_course, get_batch_members, get_batch
from community.lms.doctype.lms_batch.lms_batch import get_messages
def get_context(context):
context.no_cache = 1
context.course = frappe.form_dict["course"]
context.course_slug = frappe.form_dict["course"]
context.course = get_course(context.course_slug)
context.batch_code = frappe.form_dict["batch"]
redirect_if_not_a_member(context.course, context.batch_code)
redirect_if_not_a_member(context.course_slug, context.batch_code)
context.batch = get_batch(context.batch_code)
context.members = get_batch_members(context.batch.name)
context.member_count = len(context.members)
context.messages = get_messages(context.batch.name)

View File

@@ -1,6 +1,8 @@
{% extends "templates/base.html" %}
{% from "www/macros/sidebar.html" import Sidebar %}
{% from "www/macros/profile.html" import Profile %}
{% from "www/macros/common_macro.html" import BatchHearder %}
{% block title %}Members{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
@@ -8,28 +10,29 @@
{% endblock %}
{% block content %}
{{ Sidebar(course, batch_code) }}
{{ Sidebar(course_slug, batch_code) }}
<div class="container">
<div class="border p-3">
<h3>{{course.name}}</h3>
<div class="text-muted">{{member_count}} members</div>
</div>
<div class="mt-5">
{% for member in members %}
<div class="d-flex align-items-center">
<div>
{{ Profile(member.photo, member.full_name, member.abbr, "small") }}
</div>
<div class="mr-5">
{{member.full_name}}
</div>
{% if member.is_mentor %}
<div class="badge badge-success">Mentor</div>
{% endif %}
</div>
<hr>
{% endfor %}
</div>
{{ BatchHearder(course.name, member_count)}}
{{ MembersList(members)}}
</div>
{% endblock %}
{% endblock %}
{% macro MembersList(members) %}
<div class="mt-5">
{% for member in members %}
<div class="d-flex align-items-center">
<div>
{{ Profile(member.photo, member.full_name, member.abbr, "small") }}
</div>
<div class="mr-5">
{{member.full_name}}
</div>
{% if member.is_mentor %}
<div class="badge badge-success">Mentor</div>
{% endif %}
</div>
<hr>
{% endfor %}
</div>
{% endmacro %}

View File

@@ -1,5 +1,5 @@
import frappe
from community.www.courses.utils import redirect_if_not_a_member, get_batch, get_member_with_name, get_course
from community.www.courses.utils import redirect_if_not_a_member, get_batch, get_member_with_name, get_course, get_batch_members
def get_context(context):
context.no_cache = 1
@@ -8,16 +8,5 @@ def get_context(context):
context.batch_code = frappe.form_dict["batch"]
redirect_if_not_a_member(context.course_slug, context.batch_code)
context.batch = get_batch(context.batch_code)
context.members = get_members(context.batch)
context.member_count = len(context.members)
def get_members(batch):
members = []
memberships = frappe.get_all("LMS Batch Membership", {"batch": batch}, ["member", "member_type"])
for membership in memberships:
member = get_member_with_name(membership.member)
if membership.member_type == "Mentor":
member.is_mentor = True
members.append(member)
return members
context.members = get_batch_members(context.batch.name)
context.member_count = len(context.members)

View File

@@ -14,12 +14,12 @@ def get_member_with_name(name):
def get_batch(code):
try:
return frappe.db.get_value("LMS Batch", {"code": code}, "name")
return frappe.db.get_value("LMS Batch", {"code": code}, ["name", "description"], as_dict=True)
except frappe.DoesNotExistError:
return
def is_member_of_batch(batch_code):
membership = frappe.get_all("LMS Batch Membership", {"batch": get_batch(batch_code), "member": get_member_with_email()})
membership = frappe.get_all("LMS Batch Membership", {"batch": get_batch(batch_code).name, "member": get_member_with_email()})
if len(membership):
return True
return False
@@ -31,6 +31,27 @@ def redirect_if_not_a_member(course,batch_code):
def get_course(slug):
try:
return frappe.db.get_value("LMS Course", {"slug": slug}, "name", as_dict=True)
return frappe.get_doc("LMS Course", {"slug": slug})
except frappe.DoesNotExistError:
return
return
def get_instructor(owner):
instructor = frappe._dict()
try:
instructor = frappe.get_doc("Community Member", {"email": owner})
except frappe.DoesNotExistError:
instructor.full_name = owner
instructor.abbr = ("").join([ s[0] for s in owner.split() ])
instructor.course_count = len(frappe.get_all("LMS Course", {"owner": owner}))
return instructor
def get_batch_members(batch):
members = []
memberships = frappe.get_all("LMS Batch Membership", {"batch": batch}, ["member", "member_type"])
for membership in memberships:
member = get_member_with_name(membership.member)
if membership.member_type == "Mentor":
member.is_mentor = True
members.append(member)
return members

View File

@@ -0,0 +1,32 @@
{% macro InstructorsSection(instructor) %}
<h3>Instructor</h3>
<div class="instructor">
<div class="instructor-title">{{instructor.full_name}}</div>
<div class="instructor-subtitle">Created {{instructor.course_count}} courses</div>
</div>
{% endmacro %}
{% macro MentorsSection(mentors, is_mentor) %}
<h3>Mentors</h3>
{% for m in mentors %}
<div class="instructor">
<div class="instructor-title">{{m.full_name}}</div>
<div class="instructor-subtitle">Mentored {{m.batch_count}} batches</div>
</div>
{% endfor %}
{% if not is_mentor %}
<div class="notice">
Interested to become a mentor?
<div><a href="#">Apply Now!</a></div>
</div>
{% endif %}
{% endmacro %}
{% macro BatchHearder(course_name, member_count) %}
<div class="border p-3">
<h3>{{course_name}}</h3>
<div class="text-muted">{{member_count}} members</div>
</div>
{% endmacro %}