feat: batch folders, redirects, members page

This commit is contained in:
pateljannat
2021-04-26 10:16:53 +05:30
parent c18916096e
commit 44dc42d7dd
21 changed files with 262 additions and 24 deletions

View File

@@ -137,7 +137,12 @@ primary_rules = [
{"from_route": "/hackathons/<hackathon>", "to_route": "hackathons/hackathon"},
{"from_route": "/hackathons/<hackathon>/<project>", "to_route": "hackathons/project"},
{"from_route": "/dashboard", "to_route": ""},
{"from_route": "/add-a-new-batch", "to_route": "add-a-new-batch"}
{"from_route": "/add-a-new-batch", "to_route": "add-a-new-batch"},
{"from_route": "/courses/<course>/<batch>/learn", "to_route": "courses/learn"},
{"from_route": "/courses/<course>/<batch>/schedule", "to_route": "courses/schedule"},
{"from_route": "/courses/<course>/<batch>/members", "to_route": "courses/members"},
{"from_route": "/courses/<course>/<batch>/discuss", "to_route": "courses/discuss"},
{"from_route": "/courses/<course>/<batch>/about", "to_route": "courses/about"}
]
# Any frappe default URL is blocked by profile-rules, add it here to unblock it

View File

@@ -17,6 +17,7 @@
"fieldname": "batch",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Batch",
"options": "LMS Batch"
},
@@ -24,6 +25,7 @@
"fieldname": "member",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Member",
"options": "Community Member"
},
@@ -38,6 +40,7 @@
"fieldname": "role",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Role",
"options": "\nMember\nAdmin"
},
@@ -56,7 +59,7 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-04-16 09:57:52.926943",
"modified": "2021-04-22 15:30:00.069946",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Batch Membership",

View File

@@ -1,4 +1,5 @@
@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css");
@import url("https://use.fontawesome.com/releases/v5.13.0/css/all.css");
:root {
--c1: #fefae0;
@@ -61,6 +62,19 @@ body {
color: var(--c2);
}
.sidebar-batch {
background: var(--sidebar-bg);
color: var(--text-color);
position: fixed;
left: 0;
height: 100%;
}
.sidebar-batch a {
padding: 16px 8px 8px 16px;
display: block;
}
.instructor {
padding: 10px;
}
@@ -193,3 +207,29 @@ nav.navbar {
padding: 20px;
border-radius: 10px;
}
.dashboard__profile {
width: 150px;
height: 155px;
border-radius: 50%;
}
.dashboard__profileSmall {
width: 59px;
height: 57px;
border-radius: 50%;
}
.dashboard__abbr {
font-size: 50px;
width: 155px;
height: 155px;
border-radius: 50%;
}
.dashboard__abbrSmall {
font-size: 20px;
width: 59px;
height: 57px;
border-radius: 50%;
}

View File

@@ -0,0 +1,13 @@
{% extends "templates/base.html" %}
{% from "www/macros/sidebar.html" import Sidebar %}
{% block title %}About{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
<meta name="keywords" content="" />
{% endblock %}
{% block content %}
{{ Sidebar(course, batch_code) }}
<div class="container">
</div>
{% endblock %}

View File

@@ -0,0 +1,8 @@
import frappe
from community.www.courses.utils import redirect_if_not_a_member
def get_context(context):
context.no_cache = 1
context.course = frappe.form_dict["course"]
context.batch_code = frappe.form_dict["batch"]
redirect_if_not_a_member(context.course, context.batch_code)

View File

@@ -110,7 +110,7 @@
{% endfor %}
</div>
<a class="btn btn-primary add-batch margin-bottom" href="/add-a-new-batch?new=1&course={{course.name}}" data-course="{{course.name | urlencode}}">Add a new batch</a>
<a class="btn btn-primary add-batch margin-bottom" href="/add-a-new-batch?new=1&course={{course.name}}">Add a new batch</a>
{% else %}
<div class="mentor_message">
<p> You are a mentor for this course. </p>

View File

@@ -12,11 +12,14 @@ def get_context(context):
context.course = get_course(course_id)
context.batches = get_course_batches(context.course.name)
context.is_mentor = is_mentor(context.course.name)
context.memberships = get_membership(context.batches)
context.upcoming_batches = [] if len(context.memberships) else get_upcoming_batches(context.course.name)
if len(context.memberships) and not context.is_mentor:
frappe.local.flags.redirect_location = "/courses/" + course_id + "/" + context.memberships[0].code + "/learn"
raise frappe.Redirect
context.upcoming_batches = get_upcoming_batches(context.course.name)
context.instructor = get_instructor(context.course.owner)
context.mentors = get_mentors(context.course.name)
context.is_mentor = is_mentor(context.course.name)
if context.is_mentor:
context.mentor_batches = get_mentor_batches(context.memberships) # Your Bacthes for mentor
@@ -48,19 +51,13 @@ def get_batch_mentors(batches):
batch.mentors.append(member)
return batches
def get_discussions(batches):
messages = []
memberships = get_membership(batches)
if len(memberships):
messages = get_messages(memberships[0].batch)
return messages, memberships
def get_membership(batches):
memberships = []
member = frappe.db.get_value("Community Member", {"email": frappe.session.user}, "name")
for batch in batches:
membership = frappe.db.get_value("LMS Batch Membership", {"member": member, "batch": batch.name}, ["batch", "member", "member_type"], as_dict=1)
if membership:
membership.code = batch.code
memberships.append(membership)
return memberships
@@ -84,7 +81,7 @@ def get_mentors(course):
return course_mentors
def get_course_batches(course):
return frappe.get_all("LMS Batch", {"course": course}, ["name"])
return frappe.get_all("LMS Batch", {"course": course}, ["name", "code"])
def get_mentor_batches(memberships):
mentor_batches = []

View File

@@ -0,0 +1,13 @@
{% extends "templates/base.html" %}
{% from "www/macros/sidebar.html" import Sidebar %}
{% block title %}Discuss{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
<meta name="keywords" content="" />
{% endblock %}
{% block content %}
{{ Sidebar(course, batch_code) }}
<div class="container">
</div>
{% endblock %}

View File

@@ -0,0 +1,8 @@
import frappe
from community.www.courses.utils import redirect_if_not_a_member
def get_context(context):
context.no_cache = 1
context.course = frappe.form_dict["course"]
context.batch_code = frappe.form_dict["batch"]
redirect_if_not_a_member(context.course, context.batch_code)

View File

@@ -0,0 +1,13 @@
{% extends "templates/base.html" %}
{% from "www/macros/sidebar.html" import Sidebar %}
{% block title %}Learn{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
<meta name="keywords" content="" />
{% endblock %}
{% block content %}
{{ Sidebar(course, batch_code) }}
<div class="container">
</div>
{% endblock %}

View File

@@ -0,0 +1,3 @@
frappe.ready(() => {
})

View File

@@ -0,0 +1,10 @@
import frappe
from community.www.courses.utils import redirect_if_not_a_member
def get_context(context):
context.no_cache = 1
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)

View File

@@ -0,0 +1,35 @@
{% extends "templates/base.html" %}
{% from "www/macros/sidebar.html" import Sidebar %}
{% from "www/macros/profile.html" import Profile %}
{% block title %}Members{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
<meta name="keywords" content="" />
{% endblock %}
{% block content %}
{{ Sidebar(course, 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>
</div>
{% endblock %}

View File

@@ -0,0 +1,23 @@
import frappe
from community.www.courses.utils import redirect_if_not_a_member, get_batch, get_member_with_name, get_course
def get_context(context):
context.no_cache = 1
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_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

View File

@@ -0,0 +1,13 @@
{% extends "templates/base.html" %}
{% from "www/macros/sidebar.html" import Sidebar %}
{% block title %}Schedule{% endblock %}
{% block head_include %}
<meta name="description" content="Courses" />
<meta name="keywords" content="" />
{% endblock %}
{% block content %}
{{ Sidebar(course, batch_code) }}
<div class="container">
</div>
{% endblock %}

View File

@@ -0,0 +1,8 @@
import frappe
from community.www.courses.utils import redirect_if_not_a_member
def get_context(context):
context.no_cache = 1
context.course = frappe.form_dict["course"]
context.batch_code = frappe.form_dict["batch"]
redirect_if_not_a_member(context.course, context.batch_code)

View File

@@ -0,0 +1,36 @@
import frappe
def get_member_with_email():
try:
return frappe.db.get_value("Community Member", {"email": frappe.session.user}, "name")
except frappe.DoesNotExistError:
return
def get_member_with_name(name):
try:
return frappe.get_doc("Community Member", name)
except frappe.DoesNotExistError:
return
def get_batch(code):
try:
return frappe.db.get_value("LMS Batch", {"code": code}, "name")
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()})
if len(membership):
return True
return False
def redirect_if_not_a_member(course,batch_code):
if not is_member_of_batch(batch_code):
frappe.local.flags.redirect_location = "/courses/" + course
raise frappe.Redirect
def get_course(slug):
try:
return frappe.db.get_value("LMS Course", {"slug": slug}, "name", as_dict=True)
except frappe.DoesNotExistError:
return

View File

@@ -1,5 +1,5 @@
{% extends "templates/base.html" %}
{% from "www/macros/profile.html" import profile %}
{% from "www/macros/profile.html" import Profile %}
{% block title %}{{ _("Community") }}{% endblock %}
{% block head_include %}
<meta name="description" content="{{ 'Community' }}" />
@@ -91,7 +91,7 @@
<section>
<div class="dashboard__parent">
<div>
{{ profile(member.photo, member.full_name, member.abbr, "large")}}
{{ Profile(member.photo, member.full_name, member.abbr, "large")}}
</div>
<div class="dashboard__details">
<div class="dashboard__name">
@@ -125,7 +125,7 @@
</div>
<div class="d-flex align-items-center w-100">
<div>
{{ profile(message.profile, message.full_name, message.abbr, "small")}}
{{ Profile(message.profile, message.full_name, message.abbr, "small")}}
</div>
<div class="ml-5 mt-5">{{ frappe.utils.md_to_html(message.message) }}</div>
</div>

View File

@@ -1,12 +1,10 @@
{% macro profile(photo, full_name, abbr, icon) %}
{% macro Profile(photo, full_name, abbr, icon) %}
{% if photo %}
<img class="avatar rounded-circle img-fluid mr-5{% if icon == 'large' %} avatar-xl {% else %} avatar-large {% endif %}"
<img class="avatar rounded-circle img-fluid mr-5{% if icon == 'large' %} dashboard__profile {% else %} dashboard__profileSmall {% endif %}"
src="{{ photo }}" alt="{{ full_name }}">
{% else %}
<div class="col-sm-2">
<div class="standard-image {% if icon == 'large' %} dashboard__abbr {% else %} dashboard__abbrSmall {% endif %}">
{{ abbr }}
</div>
<div class="standard-image mr-5 {% if icon == 'large' %} dashboard__abbr {% else %} dashboard__abbrSmall {% endif %}">
{{ abbr }}
</div>
{% endif %}
{% endmacro %}

View File

@@ -0,0 +1,12 @@
{% macro Sidebar(course, batch_code) %}
<div class="sidebar-batch">
<a href=""><i class="fas fa-bars fa-lg"></i></a>
<br>
<a href="/courses/{{course}}/{{batch_code}}/learn"><i class="fas fa-book fa-lg"></i></a>
<a href="/courses/{{course}}/{{batch_code}}/schedule"><i class="fas fa-calendar-alt fa-lg"></i></a>
<a href="/courses/{{course}}/{{batch_code}}/members"><i class="fas fa-users fa-lg"></i></a>
<a href="/courses/{{course}}/{{batch_code}}/discuss"><i class="fas fa-comments fa-lg"></i></a>
<a href="/courses/{{course}}/{{batch_code}}/about"><i class="fas fa-info-circle fa-lg"></i></a>
<!-- <a href="#contact"><i class="fas fa-home fa-lg"></i></a> -->
</div>
{% endmacro %}

View File

@@ -1,5 +1,5 @@
{% extends "templates/web.html" %}
{% from "www/macros/profile.html" import profile %}
{% from "www/macros/profile.html" import Profile %}
{% block head_include %}
<meta name="description" content="{{ 'Community' }}" />
<meta name="keywords" content="An app that supports Communities." />
@@ -89,7 +89,7 @@
<section>
<div class="dashboard__parent">
<div>
{{ profile(member.photo, member.full_name, member.abbr, "large")}}
{{ Profile(member.photo, member.full_name, member.abbr, "large")}}
</div>
<div class="dashboard__details">
<div class="dashboard__name">