fix: conflicts
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
||||
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||
<div class="messages-container mt-5">
|
||||
{{ widgets.BatchHeader(batch_name=batch.title, member_count=member_count)}}
|
||||
<ol class="messages">
|
||||
|
||||
@@ -4,3 +4,5 @@ from . import utils
|
||||
def get_context(context):
|
||||
utils.get_common_context(context)
|
||||
context.messages = context.batch.get_messages()
|
||||
if not context.membership:
|
||||
utils.redirect_to_lesson(context.course)
|
||||
|
||||
@@ -8,31 +8,32 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% set invite_link = frappe.utils.get_url() + "/courses/" + course.name + "/" + batch.name + "/join" %}
|
||||
<div class="container mt-5">
|
||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
||||
<div>
|
||||
<h1 class="mt-5">{{ batch.title }}</h1>
|
||||
</div>
|
||||
<div class="course-details">
|
||||
{{ widgets.CourseOutline(course=course, batch=batch, show_link=True) }}
|
||||
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||
<div class="course-details mt-5">
|
||||
{{ widgets.CourseOutline(course=course, batch=batch, show_link=True, show_progress=True) }}
|
||||
</div>
|
||||
|
||||
{% if batch %}
|
||||
<div class="w-25">
|
||||
<h2>Batch Schedule</h2>
|
||||
<h3>Batch Schedule</h3>
|
||||
{{ widgets.RenderBatch(course=course, batch=batch) }}
|
||||
</div>
|
||||
|
||||
{% if batch.description %}
|
||||
<h2>Batch Details</h2>
|
||||
{{ frappe.utils.md_to_html(batch.description) }}
|
||||
<div class="mt-5">
|
||||
<h3>Batch Details</h3>
|
||||
{{ frappe.utils.md_to_html(batch.description) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if course.is_mentor(frappe.session.user) %}
|
||||
{% set invite_link = frappe.utils.get_url() + "/courses/" + course.name + "/join?batch=" + batch.name %}
|
||||
<div class="">
|
||||
<h2> Invite Members </h2>
|
||||
<a href="" class="anchor_style mr-5" id="invite-link" data-link="{{ invite_link }}">Get Batch Invitation
|
||||
<h3> Invite Members </h3>
|
||||
<a href="" class="" id="invite-link" data-link="{{ invite_link }}">Get Batch Invitation
|
||||
Link</a>
|
||||
<small id="copy-message" class="text-muted pull-right" style="display: none;">Copied to Clipboard.</small>
|
||||
<small id="copy-message" class="text-muted" style="display: none;">Copied to Clipboard.</small>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -52,7 +53,7 @@
|
||||
$("#copy-message").slideDown(function () {
|
||||
setTimeout(function () {
|
||||
$("#copy-message").slideUp();
|
||||
}, 5000);
|
||||
}, 2000);
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator blue password-box'>Login Required</span>
|
||||
</div>
|
||||
<div class=''>Please log in to confirm to join the course {{ batch.course_title }}.</div>
|
||||
<div class=''>Please log in to confirm joining the course {{ batch.course_title }}.</div>
|
||||
<a type="submit" id="login" class="btn btn-primary w-100"
|
||||
href="/login?redirect-to=/courses/{{ batch.course }}/{{ batch.name }}/join">{{_("Login")}}</a>
|
||||
href="/login?redirect-to=/courses/{{ batch.course }}/join?batch={{ batch.name }}">{{_("Login")}}</a>
|
||||
</div>
|
||||
|
||||
{% elif already_a_member %}
|
||||
@@ -26,7 +26,7 @@
|
||||
</div>
|
||||
<div class=''>You are already a member of the batch {{ batch.title }} for the course {{ batch.course_title }}.
|
||||
</div>
|
||||
<a type="submit" id="batch-home" class="btn btn-primary w-100" href="/courses/{{batch.course}}/{{batch.name}}/home">{{_("Go to Batch Home")}}</a>
|
||||
<a type="submit" id="batch-home" class="btn btn-primary w-100" href="">{{_("Go to Batch Home")}}</a>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
@@ -38,23 +38,21 @@
|
||||
<div>Please provide your confirmation to be a part of the batch {{ batch.title }} for the course
|
||||
{{ batch.course_title }}.
|
||||
</div>
|
||||
<a type="submit" id="confirm" class="btn btn-primary w-100" data-batch="{{ batch.name | urlencode }}"
|
||||
data-course="{{ batch.course | urlencode }}">{{_("Confirm")}}</a>
|
||||
<a type="submit" id="confirm" class="btn btn-primary w-100">{{_("Confirm")}}</a>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
frappe.ready(() => {
|
||||
var confirm_element = $("#confirm");
|
||||
var batch = decodeURIComponent(confirm_element.attr("data-batch"));
|
||||
var course = decodeURIComponent(confirm_element.attr("data-course"));
|
||||
|
||||
confirm_element.click((e) => {
|
||||
frappe.ready(() => {
|
||||
$("#confirm").click((e) => {
|
||||
frappe.call({
|
||||
"method": "community.lms.doctype.lms_batch_membership.lms_batch_membership.create_membership",
|
||||
"args": {
|
||||
"batch": batch
|
||||
"batch": {{ batch.name }},
|
||||
"course": {{ batch.course }}
|
||||
},
|
||||
"callback": (data) => {
|
||||
if (data.message == "OK") {
|
||||
@@ -63,7 +61,7 @@
|
||||
clear: true
|
||||
});
|
||||
setTimeout(function () {
|
||||
window.location.href = "/courses/" + course + "/" + batch + "/home";
|
||||
window.location.href = "/courses/{{ batch.course }}/home";
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,65 +9,39 @@
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="/assets/frappe/css/font-awesome.css">
|
||||
<link rel="stylesheet" href="{{ livecode_url }}/static/codemirror/lib/codemirror.css">
|
||||
<link rel="stylesheet" href="/assets/css/lms.css">
|
||||
<link rel="stylesheet" href="/assets/frappe/css/hljs-night-owl.css">
|
||||
|
||||
<script src="{{ livecode_url }}/static/codemirror/lib/codemirror.js"></script>
|
||||
<script src="{{ livecode_url }}/static/codemirror/mode/python/python.js"></script>
|
||||
<script src="{{ livecode_url }}/static/codemirror/keymap/sublime.js"></script>
|
||||
{% for ext in page_extensions %}
|
||||
{{ ext.render_header() }}
|
||||
{% endfor %}
|
||||
|
||||
<script src="{{ livecode_url }}/static/codemirror/addon/edit/matchbrackets.js"></script>
|
||||
<script src="{{ livecode_url }}/static/codemirror/addon/comment/comment.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
||||
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||
<div class="lesson-page">
|
||||
|
||||
<h2>{{ lesson.title }}</h2>
|
||||
<h2 class="title {% if course.is_mentor(frappe.session.user) %} is_mentor {% endif %}" data-lesson="{{ lesson.name }}"
|
||||
data-course="{{ course.name }}" {% if membership%} data-membership="{{membership.name}}" {% endif %}>{{ lesson.title }}</h2>
|
||||
|
||||
{% for s in lesson.get_sections() %}
|
||||
<div class="section section-{{ s.type }}">
|
||||
{{ render_section(s) }}
|
||||
{% if membership or lesson.include_in_preview %}
|
||||
{{ lesson.render_html() }}
|
||||
{% else %}
|
||||
<div class="no-preview-message">
|
||||
<span>This lesson is not available for Preview. Please join the course to access this lesson.</span>
|
||||
<a href="/courses/{{ course.name }}">Checkout Course Details.</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{{ pagination(prev_chap, prev_url, next_chap, next_url) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% macro render_section(s) %}
|
||||
{% if s.type == "text" %}
|
||||
{{ render_section_text(s) }}
|
||||
{% elif s.type == "example" or s.type == "code" %}
|
||||
{{ LiveCodeEditor(s.name,
|
||||
code=s.get_latest_code_for_user(),
|
||||
reset_code=s.contents,
|
||||
is_exercise=False)
|
||||
}}
|
||||
{% elif s.type == "exercise" %}
|
||||
{{ widgets.Exercise(exercise=s.get_exercise())}}
|
||||
{% elif s.type == "quiz" %}
|
||||
{{ widgets.Quiz(quiz=s.get_quiz())}}
|
||||
{% else %}
|
||||
<div>Unknown section type: {{s.type}}</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_section_text(s) %}
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
{{ frappe.utils.md_to_html(s.contents) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro pagination(prev_chap, prev_url, next_chap, next_url) %}
|
||||
<div class="lesson-pagination">
|
||||
{% if prev_url %}
|
||||
@@ -86,18 +60,7 @@
|
||||
|
||||
{%- block script %}
|
||||
{{ super() }}
|
||||
{{ LiveCodeEditorJS() }}
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
var batch_name = "{{ batch.name }}";
|
||||
var lesson_name = "{{ lesson.name }}";
|
||||
|
||||
frappe.call("community.lms.api.save_current_lesson", {
|
||||
"batch_name": batch_name,
|
||||
"lesson_name": lesson_name
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
{% for ext in page_extensions %}
|
||||
{{ ext.render_footer() }}
|
||||
{% endfor %}
|
||||
{%- endblock %}
|
||||
|
||||
17
community/www/batch/learn.js
Normal file
17
community/www/batch/learn.js
Normal file
@@ -0,0 +1,17 @@
|
||||
frappe.ready(() => {
|
||||
if ($(".title").attr("data-membership") && !$(".title").hasClass("is_mentor")) {
|
||||
frappe.call({
|
||||
method: "community.lms.doctype.lesson.lesson.save_progress",
|
||||
args: {
|
||||
lesson: $(".title").attr("data-lesson"),
|
||||
course: $(".title").attr("data-course")
|
||||
}
|
||||
})
|
||||
}
|
||||
if ($(".title").attr("data-membership")) {
|
||||
frappe.call("community.lms.api.save_current_lesson", {
|
||||
course_name: $(".title").attr("data-course"),
|
||||
lesson_name: $(".title").attr("data-lesson")
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,6 +1,9 @@
|
||||
from re import I
|
||||
import frappe
|
||||
from . import utils
|
||||
from frappe.utils import cstr
|
||||
|
||||
from community.www import batch
|
||||
|
||||
def get_context(context):
|
||||
utils.get_common_context(context)
|
||||
@@ -10,10 +13,12 @@ def get_context(context):
|
||||
lesson_number = f"{chapter_index}.{lesson_index}"
|
||||
|
||||
course_name = context.course.name
|
||||
|
||||
if not chapter_index or not lesson_index:
|
||||
index_ = get_lesson_index(context.course, context.batch, frappe.session.user) or "1.1"
|
||||
frappe.local.flags.redirect_location = context.batch.get_learn_url(index_)
|
||||
if context.batch:
|
||||
index_ = get_lesson_index(context.course, context.batch, frappe.session.user) or "1.1"
|
||||
else:
|
||||
index_ = "1.1"
|
||||
frappe.local.flags.redirect_location = context.course.get_learn_url(index_) + context.course.query_parameter
|
||||
raise frappe.Redirect
|
||||
|
||||
context.lesson = context.course.get_lesson(chapter_index, lesson_index)
|
||||
@@ -25,16 +30,17 @@ def get_context(context):
|
||||
next_ = outline.get_next(lesson_number)
|
||||
context.prev_chap = get_chapter_title(course_name, prev_)
|
||||
context.next_chap = get_chapter_title(course_name, next_)
|
||||
context.next_url = context.batch.get_learn_url(next_)
|
||||
context.prev_url = context.batch.get_learn_url(prev_)
|
||||
|
||||
context.next_url = context.course.get_learn_url(next_) + context.course.query_parameter
|
||||
context.prev_url = context.course.get_learn_url(prev_) + context.course.query_parameter
|
||||
|
||||
context.page_extensions = get_page_extensions()
|
||||
|
||||
def get_chapter_title(course_name, lesson_number):
|
||||
if not lesson_number:
|
||||
return
|
||||
chapter_index = lesson_number.split(".")[0]
|
||||
lesson_index = lesson_number.split(".")[1]
|
||||
lesson_split = cstr(lesson_number).split(".")
|
||||
chapter_index = lesson_split[0]
|
||||
lesson_index = lesson_split[1]
|
||||
chapter_name = frappe.db.get_value("Chapter", {"course": course_name, "index_": chapter_index}, "name")
|
||||
return frappe.db.get_value("Lesson", {"chapter": chapter_name, "index_": lesson_index}, "title")
|
||||
|
||||
@@ -42,4 +48,8 @@ def get_lesson_index(course, batch, user):
|
||||
lesson = batch.get_current_lesson(user)
|
||||
return lesson and course.get_lesson_index(lesson)
|
||||
|
||||
|
||||
def get_page_extensions():
|
||||
default_value = ["community.community.plugins.PageExtension"]
|
||||
classnames = frappe.get_hooks("community_lesson_page_extensions") or default_value
|
||||
extensions = [frappe.get_attr(name)() for name in classnames]
|
||||
return extensions
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
||||
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||
{{ MembersList(members)}}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -19,23 +19,19 @@
|
||||
{% macro MembersList(members) %}
|
||||
<div class="mt-5">
|
||||
{% for member in members %}
|
||||
<div class="row mb-5">
|
||||
<div>
|
||||
{{ widgets.Avatar(member=member, avatar_class="avatar-large") }}
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="row ml-1">
|
||||
<a class="anchor_style" href="/{{member.username}}">
|
||||
<div class="d-flex align-items-center">
|
||||
{{ widgets.Avatar(member=member, avatar_class="avatar-large") }}
|
||||
<div class="d-flex flex-column ml-2">
|
||||
<div class="d-flex">
|
||||
<a class="anchor_style ml-2" href="/{{member.username}}">
|
||||
<h3>{{ member.full_name }}</h3>
|
||||
</a>
|
||||
{% if course.is_mentor(member.name) %}
|
||||
<div class="ml-2">
|
||||
<div class="badge badge-success">Mentor</div>
|
||||
</div>
|
||||
<div class="badge badge-success ml-2 align-self-start">Mentor</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if member.bio %}
|
||||
<i>{{member.bio}}</i>
|
||||
<i class="ml-2">{{member.bio}}</i>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,4 +3,5 @@ from . import utils
|
||||
|
||||
def get_context(context):
|
||||
utils.get_common_context(context)
|
||||
print(context.members[0].bio)
|
||||
if not context.membership:
|
||||
utils.redirect_to_lesson(context.course)
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
{{ widgets.BatchTabs(course=course, batch=batch) }}
|
||||
{{ widgets.BatchTabs(course=course, membership=membership) }}
|
||||
<div class="mentor-dashboard">
|
||||
<h1>Batch Progress</h1>
|
||||
<h3>Batch Progress</h3>
|
||||
{% for exercise in report.exercises %}
|
||||
<div class="exercise-submissions">
|
||||
<h2>Exercise {{exercise.index_label}}: {{exercise.title}}</h2>
|
||||
|
||||
@@ -17,9 +17,8 @@ def get_context(context):
|
||||
|
||||
class BatchReport:
|
||||
def __init__(self, course, batch):
|
||||
self.submissions = get_submissions(batch)
|
||||
self.submissions = get_submissions(course, batch)
|
||||
self.exercises = self.get_exercises(course.name)
|
||||
|
||||
self.submissions_by_exercise = defaultdict(list)
|
||||
for s in self.submissions:
|
||||
self.submissions_by_exercise[s.exercise].append(s)
|
||||
@@ -30,11 +29,12 @@ class BatchReport:
|
||||
def get_submissions_of_exercise(self, exercise_name):
|
||||
return self.submissions_by_exercise[exercise_name]
|
||||
|
||||
def get_submissions(batch):
|
||||
students = batch.get_students()
|
||||
def get_submissions(course, batch):
|
||||
students = course.get_students(batch.name)
|
||||
if not len(students):
|
||||
return []
|
||||
students_map = {s.email: s for s in students}
|
||||
names, values = nparams("s", students_map.keys())
|
||||
|
||||
sql = """
|
||||
select owner, exercise, name, solution, creation, image
|
||||
from (
|
||||
@@ -45,7 +45,6 @@ def get_submissions(batch):
|
||||
""".format(names)
|
||||
|
||||
data = frappe.db.sql(sql, values=values, as_dict=True)
|
||||
|
||||
for row in data:
|
||||
row['owner'] = students_map[row['owner']]
|
||||
return data
|
||||
|
||||
@@ -5,24 +5,34 @@ def get_common_context(context):
|
||||
context.no_cache = 1
|
||||
|
||||
course_name = frappe.form_dict["course"]
|
||||
batch_name = frappe.form_dict["batch"]
|
||||
try:
|
||||
batch_name = frappe.form_dict["batch"]
|
||||
except KeyError:
|
||||
batch_name = None
|
||||
|
||||
course = Course.find(course_name)
|
||||
if not course:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
|
||||
batch = course.get_batch(batch_name)
|
||||
if not batch or not batch.is_member(frappe.session.user):
|
||||
frappe.local.flags.redirect_location = "/courses/" + course_name
|
||||
raise frappe.Redirect
|
||||
|
||||
context.course = course
|
||||
context.batch = batch
|
||||
context.members = batch.get_mentors() + batch.get_students()
|
||||
context.member_count = len(context.members)
|
||||
|
||||
membership = course.get_membership(frappe.session.user, batch_name)
|
||||
if membership:
|
||||
context.membership = membership
|
||||
batch = course.get_batch(membership.batch)
|
||||
|
||||
if batch:
|
||||
context.batch = batch
|
||||
|
||||
context.members = course.get_mentors(membership.batch) + course.get_students(membership.batch)
|
||||
context.member_count = len(context.members)
|
||||
|
||||
context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else ""
|
||||
context.livecode_url = get_livecode_url()
|
||||
|
||||
def get_livecode_url():
|
||||
return frappe.db.get_single_value("LMS Settings", "livecode_url")
|
||||
|
||||
def redirect_to_lesson(course, index_="1.1"):
|
||||
frappe.local.flags.redirect_location = course.get_learn_url(index_) + course.query_parameter
|
||||
raise frappe.Redirect
|
||||
|
||||
Reference in New Issue
Block a user