feat: publish batches
This commit is contained in:
@@ -304,6 +304,7 @@ lms_markdown_macro_renderers = {
|
|||||||
"YouTubeVideo": "lms.plugins.youtube_video_renderer",
|
"YouTubeVideo": "lms.plugins.youtube_video_renderer",
|
||||||
"Video": "lms.plugins.video_renderer",
|
"Video": "lms.plugins.video_renderer",
|
||||||
"Assignment": "lms.plugins.assignment_renderer",
|
"Assignment": "lms.plugins.assignment_renderer",
|
||||||
|
"Embed": "lms.plugins.embed_renderer",
|
||||||
}
|
}
|
||||||
|
|
||||||
# page_renderer to manage profile pages
|
# page_renderer to manage profile pages
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"file_type",
|
"file_type",
|
||||||
"section_break_11",
|
"section_break_11",
|
||||||
"body",
|
"body",
|
||||||
|
"instructor_notes",
|
||||||
"help_section",
|
"help_section",
|
||||||
"help"
|
"help"
|
||||||
],
|
],
|
||||||
@@ -131,11 +132,16 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_15",
|
"fieldname": "column_break_15",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "instructor_notes",
|
||||||
|
"fieldtype": "Text",
|
||||||
|
"label": "Instructor Notes"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-05-02 12:42:16.926753",
|
"modified": "2023-08-31 21:47:06.314995",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Course Lesson",
|
"name": "Course Lesson",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"column_break_4",
|
"column_break_4",
|
||||||
"start_time",
|
"start_time",
|
||||||
"end_time",
|
"end_time",
|
||||||
|
"published",
|
||||||
"section_break_rgfj",
|
"section_break_rgfj",
|
||||||
"medium",
|
"medium",
|
||||||
"category",
|
"category",
|
||||||
@@ -192,11 +193,17 @@
|
|||||||
"fieldtype": "Text Editor",
|
"fieldtype": "Text Editor",
|
||||||
"label": "Batch Details",
|
"label": "Batch Details",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "published",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Published"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-08-23 17:35:42.750754",
|
"modified": "2023-09-12 12:30:06.565104",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Batch",
|
"name": "LMS Batch",
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ def create_batch(
|
|||||||
amount=0,
|
amount=0,
|
||||||
currency=None,
|
currency=None,
|
||||||
name=None,
|
name=None,
|
||||||
|
published=0,
|
||||||
):
|
):
|
||||||
frappe.only_for("Moderator")
|
frappe.only_for("Moderator")
|
||||||
if name:
|
if name:
|
||||||
@@ -223,6 +224,7 @@ def create_batch(
|
|||||||
"paid_batch": paid_batch,
|
"paid_batch": paid_batch,
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
"currency": currency,
|
"currency": currency,
|
||||||
|
"published": published,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
doc.save()
|
doc.save()
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ def save_lesson(
|
|||||||
preview,
|
preview,
|
||||||
idx,
|
idx,
|
||||||
lesson,
|
lesson,
|
||||||
|
instructor_notes=None,
|
||||||
youtube=None,
|
youtube=None,
|
||||||
quiz_id=None,
|
quiz_id=None,
|
||||||
question=None,
|
question=None,
|
||||||
@@ -296,6 +297,7 @@ def save_lesson(
|
|||||||
"chapter": chapter,
|
"chapter": chapter,
|
||||||
"title": title,
|
"title": title,
|
||||||
"body": body,
|
"body": body,
|
||||||
|
"instructor_notes": instructor_notes,
|
||||||
"include_in_preview": preview,
|
"include_in_preview": preview,
|
||||||
"youtube": youtube,
|
"youtube": youtube,
|
||||||
"quiz_id": quiz_id,
|
"quiz_id": quiz_id,
|
||||||
|
|||||||
@@ -145,11 +145,14 @@ def get_lesson_details(chapter):
|
|||||||
"quiz_id",
|
"quiz_id",
|
||||||
"question",
|
"question",
|
||||||
"file_type",
|
"file_type",
|
||||||
|
"instructor_notes",
|
||||||
],
|
],
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
)
|
)
|
||||||
lesson_details.number = flt(f"{chapter.idx}.{row.idx}")
|
lesson_details.number = flt(f"{chapter.idx}.{row.idx}")
|
||||||
lesson_details.icon = get_lesson_icon(lesson_details.body)
|
lesson_details.icon = get_lesson_icon(lesson_details.body)
|
||||||
|
if lesson_details.instructor_notes:
|
||||||
|
lesson_details.instructor_notes = markdown_to_html(lesson_details.instructor_notes)
|
||||||
|
|
||||||
lessons.append(lesson_details)
|
lessons.append(lesson_details)
|
||||||
return lessons
|
return lessons
|
||||||
|
|||||||
@@ -67,3 +67,4 @@ lms.patches.v1_0.rename_lms_batch_doctype
|
|||||||
lms.patches.v1_0.rename_lms_batch_membership_doctype
|
lms.patches.v1_0.rename_lms_batch_membership_doctype
|
||||||
lms.patches.v1_0.rename_lms_class_to_lms_batch
|
lms.patches.v1_0.rename_lms_class_to_lms_batch
|
||||||
lms.patches.v1_0.rename_classes_in_navbar
|
lms.patches.v1_0.rename_classes_in_navbar
|
||||||
|
lms.patches.v1_0.publish_batches
|
||||||
8
lms/patches/v1_0/publish_batches.py
Normal file
8
lms/patches/v1_0/publish_batches.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
batches = frappe.get_all("LMS Batch", pluck="name")
|
||||||
|
|
||||||
|
for batch in batches:
|
||||||
|
frappe.db.set_value("LMS Batch", batch, "Published", 1)
|
||||||
@@ -155,6 +155,28 @@ def youtube_video_renderer(video_id):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def embed_renderer(details):
|
||||||
|
type = details.split("|||")[0]
|
||||||
|
src = details.split("|||")[1]
|
||||||
|
width = "100%"
|
||||||
|
height = "400"
|
||||||
|
|
||||||
|
if type == "pdf":
|
||||||
|
width = "75%"
|
||||||
|
height = "600"
|
||||||
|
|
||||||
|
return f"""
|
||||||
|
<iframe width={width} height={height}
|
||||||
|
src={src}
|
||||||
|
title="Embedded Content"
|
||||||
|
frameborder="0"
|
||||||
|
style="border-radius: var(--border-radius-lg)"
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowfullscreen>
|
||||||
|
</iframe>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def video_renderer(src):
|
def video_renderer(src):
|
||||||
return (
|
return (
|
||||||
f"<video controls width='100%'><source src={quote(src)} type='video/mp4'></video>"
|
f"<video controls width='100%'><source src={quote(src)} type='video/mp4'></video>"
|
||||||
|
|||||||
@@ -2340,3 +2340,7 @@ select {
|
|||||||
.batch-course-list .cards-parent {
|
.batch-course-list .cards-parent {
|
||||||
row-gap: 3rem
|
row-gap: 3rem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.embed-tool__caption {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
@@ -261,6 +261,24 @@ const open_batch_dialog = () => {
|
|||||||
reqd: 1,
|
reqd: 1,
|
||||||
default: batch_info && batch_info.title,
|
default: batch_info && batch_info.title,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Check",
|
||||||
|
label: __("Published"),
|
||||||
|
fieldname: "published",
|
||||||
|
default: batch_info && batch_info.published,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Column Break",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Int",
|
||||||
|
label: __("Seat Count"),
|
||||||
|
fieldname: "seat_count",
|
||||||
|
default: batch_info && batch_info.seat_count,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldtype: "Section Break",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldtype: "Date",
|
fieldtype: "Date",
|
||||||
label: __("Start Date"),
|
label: __("Start Date"),
|
||||||
@@ -297,12 +315,6 @@ const open_batch_dialog = () => {
|
|||||||
fieldname: "end_time",
|
fieldname: "end_time",
|
||||||
default: batch_info && batch_info.end_time,
|
default: batch_info && batch_info.end_time,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
fieldtype: "Int",
|
|
||||||
label: __("Seat Count"),
|
|
||||||
fieldname: "seat_count",
|
|
||||||
default: batch_info && batch_info.seat_count,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
label: __("Category"),
|
label: __("Category"),
|
||||||
|
|||||||
@@ -66,14 +66,9 @@
|
|||||||
{% macro CreateLesson() %}
|
{% macro CreateLesson() %}
|
||||||
<article class="field-parent">
|
<article class="field-parent">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<div>
|
|
||||||
<div class="field-label">
|
<div class="field-label">
|
||||||
{{ _("Title") }}
|
{{ _("Title") }}
|
||||||
</div>
|
</div>
|
||||||
<div class="field-description">
|
|
||||||
{{ _("Something Short and Concise") }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="">
|
<div class="">
|
||||||
<input id="lesson-title" type="text" class="field-input" data-index="{{ lesson_index }}" data-chapter="{{ chapter }}" data-course="{{ course.name }}" {% if lesson.name %} data-lesson="{{ lesson.name }}" value="{{ lesson.title }}" {% endif %}>
|
<input id="lesson-title" type="text" class="field-input" data-index="{{ lesson_index }}" data-chapter="{{ chapter }}" data-course="{{ course.name }}" {% if lesson.name %} data-lesson="{{ lesson.name }}" value="{{ lesson.title }}" {% endif %}>
|
||||||
</div>
|
</div>
|
||||||
@@ -86,6 +81,19 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group">
|
||||||
|
<div class="field-label">
|
||||||
|
{{ _("Instructor Notes") }}
|
||||||
|
</div>
|
||||||
|
<div class="field-description">
|
||||||
|
{{ _("These notes will only be visible to the Course Creator, Course Evaluaor and Moderator.") }}
|
||||||
|
</div>
|
||||||
|
<div id="instructor-notes"></div>
|
||||||
|
{% if lesson.instructor_notes %}
|
||||||
|
<div id="current-instructor-notes" class="hide">{{ lesson.instructor_notes }}</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<div>
|
<div>
|
||||||
<div class="field-label">
|
<div class="field-label">
|
||||||
@@ -117,9 +125,9 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ include_script('controls.bundle.js') }}
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/paragraph@latest"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@editorjs/embed@latest"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
frappe.ready(() => {
|
frappe.ready(() => {
|
||||||
frappe.telemetry.capture("on_lesson_creation_page", "lms");
|
|
||||||
let self = this;
|
let self = this;
|
||||||
this.quiz_in_lesson = [];
|
this.quiz_in_lesson = [];
|
||||||
|
|
||||||
|
frappe.telemetry.capture("on_lesson_creation_page", "lms");
|
||||||
|
|
||||||
|
if ($("#instructor-notes").length) {
|
||||||
|
frappe.require("controls.bundle.js", () => {
|
||||||
|
make_instructor_notes_component();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if ($("#current-lesson-content").length) {
|
if ($("#current-lesson-content").length) {
|
||||||
parse_string_to_lesson();
|
parse_string_to_lesson();
|
||||||
}
|
}
|
||||||
@@ -18,6 +26,27 @@ const setup_editor = () => {
|
|||||||
self.editor = new EditorJS({
|
self.editor = new EditorJS({
|
||||||
holder: "lesson-content",
|
holder: "lesson-content",
|
||||||
tools: {
|
tools: {
|
||||||
|
embed: {
|
||||||
|
class: Embed,
|
||||||
|
config: {
|
||||||
|
services: {
|
||||||
|
youtube: true,
|
||||||
|
vimeo: true,
|
||||||
|
codepen: true,
|
||||||
|
slides: {
|
||||||
|
regex: /https:\/\/docs\.google\.com\/presentation\/d\/e\/([A-Za-z0-9_-]+)\/pub/,
|
||||||
|
embedUrl:
|
||||||
|
"https://docs.google.com/presentation/d/e/<%= remote_id %>/embed",
|
||||||
|
html: "<iframe width='100%' height='300' frameborder='0' allowfullscreen='true'></iframe>",
|
||||||
|
},
|
||||||
|
pdf: {
|
||||||
|
regex: /(https?:\/\/.*\.pdf)/,
|
||||||
|
embedUrl: "<%= remote_id %>",
|
||||||
|
html: "<iframe width='100%' height='600px' frameborder='0'></iframe>",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
header: {
|
header: {
|
||||||
class: Header,
|
class: Header,
|
||||||
inlineToolbar: ["bold", "italic", "link"],
|
inlineToolbar: ["bold", "italic", "link"],
|
||||||
@@ -76,6 +105,15 @@ const parse_string_to_lesson = () => {
|
|||||||
file_url: video,
|
file_url: video,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} else if (block.includes("{{ Embed")) {
|
||||||
|
let embed = block.match(/'([^']+)'/)[1];
|
||||||
|
lesson_blocks.push({
|
||||||
|
type: "embed",
|
||||||
|
data: {
|
||||||
|
service: embed.split("|||")[0],
|
||||||
|
embed: embed.split("|||")[1],
|
||||||
|
},
|
||||||
|
});
|
||||||
} else if (block.includes("![]")) {
|
} else if (block.includes("![]")) {
|
||||||
let image = block.match(/\((.*?)\)/)[1];
|
let image = block.match(/\((.*?)\)/)[1];
|
||||||
lesson_blocks.push({
|
lesson_blocks.push({
|
||||||
@@ -131,6 +169,15 @@ const parse_lesson_to_string = (data) => {
|
|||||||
"#".repeat(block.data.level) + ` ${block.data.text}\n`;
|
"#".repeat(block.data.level) + ` ${block.data.text}\n`;
|
||||||
} else if (block.type == "paragraph") {
|
} else if (block.type == "paragraph") {
|
||||||
lesson_content += `${block.data.text}\n`;
|
lesson_content += `${block.data.text}\n`;
|
||||||
|
} else if (block.type == "embed") {
|
||||||
|
if (block.data.service == "pdf") {
|
||||||
|
if (!block.data.embed.startsWith(window.location.origin)) {
|
||||||
|
frappe.throw(__("Invalid PDF URL"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lesson_content += `{{ Embed("${
|
||||||
|
block.data.service
|
||||||
|
}|||${block.data.embed.replace(/&/g, "&")}") }}\n`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
save(lesson_content);
|
save(lesson_content);
|
||||||
@@ -149,6 +196,8 @@ const save = (lesson_content) => {
|
|||||||
preview: $("#preview").prop("checked") ? 1 : 0,
|
preview: $("#preview").prop("checked") ? 1 : 0,
|
||||||
idx: $("#lesson-title").data("index"),
|
idx: $("#lesson-title").data("index"),
|
||||||
lesson: lesson ? lesson : "",
|
lesson: lesson ? lesson : "",
|
||||||
|
instructor_notes:
|
||||||
|
this.instructor_notes.get_values().instructor_notes,
|
||||||
},
|
},
|
||||||
callback: (data) => {
|
callback: (data) => {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
@@ -466,3 +515,20 @@ class Upload {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const make_instructor_notes_component = () => {
|
||||||
|
this.instructor_notes = new frappe.ui.FieldGroup({
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
fieldname: "instructor_notes",
|
||||||
|
fieldtype: "Text Editor",
|
||||||
|
default: $("#current-instructor-notes").html(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
body: $("#instructor-notes").get(0),
|
||||||
|
});
|
||||||
|
this.instructor_notes.make();
|
||||||
|
$("#instructor-notes .form-section:last").removeClass("empty-section");
|
||||||
|
$("#instructor-notes .frappe-control").removeClass("hide-control");
|
||||||
|
$("#instructor-notes .form-column").addClass("p-0");
|
||||||
|
};
|
||||||
|
|||||||
@@ -149,17 +149,28 @@
|
|||||||
{% if show_lesson %}
|
{% if show_lesson %}
|
||||||
|
|
||||||
{% if is_instructor and not lesson.include_in_preview %}
|
{% if is_instructor and not lesson.include_in_preview %}
|
||||||
<div class="medium alert alert-info alert-dismissible mb-4">
|
<div class="alert alert-info alert-dismissible mb-4">
|
||||||
{{ _("This lesson is not available for preview. As you are the Instructor of the course only you can see it.") }}
|
{{ _("This lesson is not available for preview. As you are the Instructor of the course only you can see it.") }}
|
||||||
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
|
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if lesson.instructor_notes and (is_moderator or instructor or is_evaluator) %}
|
||||||
|
<div class="alert alert-info mb-4">
|
||||||
|
<div class="bold-heading mb-2">
|
||||||
|
{{ _("Instructor Notes") }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ lesson.instructor_notes }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{{ render_html(lesson) }}
|
{{ render_html(lesson) }}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set course_link = "<a class='enroll-in-course' data-course=" + course.name | urlencode + " href=''>" + _('here') + "</a>" %}
|
{% set course_link = "<a class='enroll-in-course' data-course=" + course.name | urlencode + " href=''>" + _('here') + "</a>" %}
|
||||||
<div class="alert alert-info medium mb-0">
|
<div class="alert alert-info mb-0">
|
||||||
{{ _("There is no preview available for this lesson.
|
{{ _("There is no preview available for this lesson.
|
||||||
Please join the course to access it.
|
Please join the course to access it.
|
||||||
Click {0} to enroll.").format(course_link) }}
|
Click {0} to enroll.").format(course_link) }}
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cstr, flt
|
from frappe.utils import cstr, flt
|
||||||
|
|
||||||
from lms.lms.utils import get_lesson_url, has_course_moderator_role, is_instructor
|
from lms.lms.utils import (
|
||||||
|
get_lesson_url,
|
||||||
|
has_course_moderator_role,
|
||||||
|
is_instructor,
|
||||||
|
has_course_evaluator_role,
|
||||||
|
)
|
||||||
from lms.www.utils import (
|
from lms.www.utils import (
|
||||||
get_common_context,
|
get_common_context,
|
||||||
redirect_to_lesson,
|
redirect_to_lesson,
|
||||||
@@ -37,20 +42,23 @@ def get_context(context):
|
|||||||
redirect_to_lesson(context.course, index_)
|
redirect_to_lesson(context.course, index_)
|
||||||
|
|
||||||
context.lesson = get_current_lesson_details(lesson_number, context)
|
context.lesson = get_current_lesson_details(lesson_number, context)
|
||||||
instructor = is_instructor(context.course.name)
|
context.instructor = is_instructor(context.course.name)
|
||||||
|
context.is_moderator = has_course_moderator_role()
|
||||||
|
context.is_evaluator = has_course_evaluator_role()
|
||||||
|
|
||||||
context.show_lesson = (
|
context.show_lesson = (
|
||||||
context.membership
|
context.membership
|
||||||
or (context.lesson and context.lesson.include_in_preview)
|
or (context.lesson and context.lesson.include_in_preview)
|
||||||
or instructor
|
or context.instructor
|
||||||
or has_course_moderator_role()
|
or context.is_moderator
|
||||||
|
or context.is_evaluator
|
||||||
)
|
)
|
||||||
|
|
||||||
if not context.lesson:
|
if not context.lesson:
|
||||||
context.lesson = frappe._dict()
|
context.lesson = frappe._dict()
|
||||||
|
|
||||||
if frappe.form_dict.get("edit"):
|
if frappe.form_dict.get("edit"):
|
||||||
if not instructor and not has_course_moderator_role():
|
if not context.instructor and not context.is_moderator:
|
||||||
raise frappe.PermissionError(_("You do not have permission to access this page."))
|
raise frappe.PermissionError(_("You do not have permission to access this page."))
|
||||||
context.lesson.edit_mode = True
|
context.lesson.edit_mode = True
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ def get_context(context):
|
|||||||
"amount",
|
"amount",
|
||||||
"currency",
|
"currency",
|
||||||
"batch_details",
|
"batch_details",
|
||||||
|
"published",
|
||||||
],
|
],
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
from frappe import _
|
||||||
from lms.lms.utils import has_course_moderator_role, has_course_evaluator_role
|
from lms.lms.utils import has_course_moderator_role, has_course_evaluator_role
|
||||||
from lms.www.utils import is_student
|
from lms.www.utils import is_student
|
||||||
|
|
||||||
@@ -23,10 +24,17 @@ def get_context(context):
|
|||||||
"start_time",
|
"start_time",
|
||||||
"end_time",
|
"end_time",
|
||||||
"seat_count",
|
"seat_count",
|
||||||
|
"published",
|
||||||
],
|
],
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
context.is_moderator = has_course_moderator_role()
|
||||||
|
context.is_evaluator = has_course_evaluator_role()
|
||||||
|
|
||||||
|
if not context.is_moderator and not context.batch_info.published:
|
||||||
|
raise frappe.PermissionError(_("You do not have permission to access this page."))
|
||||||
|
|
||||||
context.courses = frappe.get_all(
|
context.courses = frappe.get_all(
|
||||||
"Batch Course",
|
"Batch Course",
|
||||||
{"parent": batch_name},
|
{"parent": batch_name},
|
||||||
@@ -44,6 +52,4 @@ def get_context(context):
|
|||||||
context.student_count = frappe.db.count("Batch Student", {"parent": batch_name})
|
context.student_count = frappe.db.count("Batch Student", {"parent": batch_name})
|
||||||
context.seats_left = context.batch_info.seat_count - context.student_count
|
context.seats_left = context.batch_info.seat_count - context.student_count
|
||||||
|
|
||||||
context.is_moderator = has_course_moderator_role()
|
|
||||||
context.is_evaluator = has_course_evaluator_role()
|
|
||||||
context.is_student = is_student(batch_name)
|
context.is_student = is_student(batch_name)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
<div class="common-page-style lms-page-style">
|
<div class="common-page-style lms-page-style">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{ Header() }}
|
{{ Header() }}
|
||||||
{% if past_batches | length or upcoming_batches | length %}
|
{% if past_batches | length or upcoming_batches | length or private_batches | length %}
|
||||||
{{ BatchTabs(past_batches, upcoming_batches, my_batches) }}
|
{{ BatchTabs(past_batches, upcoming_batches, private_batches, my_batches) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ EmptyState() }}
|
{{ EmptyState() }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
</header>
|
</header>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro BatchTabs(past_batches, upcoming_batches, my_batches) %}
|
{% macro BatchTabs(past_batches, upcoming_batches, private_batches, my_batches) %}
|
||||||
<article>
|
<article>
|
||||||
<ul class="nav lms-nav" id="courses-tab">
|
<ul class="nav lms-nav" id="courses-tab">
|
||||||
|
|
||||||
@@ -49,6 +49,15 @@
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" data-toggle="tab" href="#private">
|
||||||
|
{{ _("Private") }}
|
||||||
|
<span class="course-list-count">
|
||||||
|
{{ private_batches | length }}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if frappe.session.user != "Guest" %}
|
{% if frappe.session.user != "Guest" %}
|
||||||
@@ -75,6 +84,10 @@
|
|||||||
<div class="tab-pane" id="past" role="tabpanel" aria-labelledby="past">
|
<div class="tab-pane" id="past" role="tabpanel" aria-labelledby="past">
|
||||||
{{ BatchCard(past_batches, show_price=False, label="Archived") }}
|
{{ BatchCard(past_batches, show_price=False, label="Archived") }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane" id="private" role="tabpanel" aria-labelledby="private">
|
||||||
|
{{ BatchCard(private_batches, show_price=False, label="Private") }}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if frappe.session.user != "Guest" %}
|
{% if frappe.session.user != "Guest" %}
|
||||||
|
|||||||
@@ -19,25 +19,29 @@ def get_context(context):
|
|||||||
"amount",
|
"amount",
|
||||||
"currency",
|
"currency",
|
||||||
"seat_count",
|
"seat_count",
|
||||||
|
"published",
|
||||||
],
|
],
|
||||||
order_by="start_date",
|
order_by="start_date",
|
||||||
)
|
)
|
||||||
|
|
||||||
past_batches, upcoming_batches = [], []
|
past_batches, upcoming_batches, private_batches = [], [], []
|
||||||
for batch in batches:
|
for batch in batches:
|
||||||
batch.student_count = frappe.db.count("Batch Student", {"parent": batch.name})
|
batch.student_count = frappe.db.count("Batch Student", {"parent": batch.name})
|
||||||
batch.course_count = frappe.db.count("Batch Course", {"parent": batch.name})
|
batch.course_count = frappe.db.count("Batch Course", {"parent": batch.name})
|
||||||
batch.seats_left = (
|
batch.seats_left = (
|
||||||
batch.seat_count - batch.student_count if batch.seat_count else None
|
batch.seat_count - batch.student_count if batch.seat_count else None
|
||||||
)
|
)
|
||||||
print(batch.seat_count, batch.student_count, batch.seats_left)
|
print(batch.name, batch.published)
|
||||||
if getdate(batch.start_date) < getdate():
|
if not batch.published:
|
||||||
|
private_batches.append(batch)
|
||||||
|
elif getdate(batch.start_date) < getdate():
|
||||||
past_batches.append(batch)
|
past_batches.append(batch)
|
||||||
else:
|
else:
|
||||||
upcoming_batches.append(batch)
|
upcoming_batches.append(batch)
|
||||||
|
|
||||||
context.past_batches = sorted(past_batches, key=lambda d: d.start_date)
|
context.past_batches = sorted(past_batches, key=lambda d: d.start_date)
|
||||||
context.upcoming_batches = sorted(upcoming_batches, key=lambda d: d.start_date)
|
context.upcoming_batches = sorted(upcoming_batches, key=lambda d: d.start_date)
|
||||||
|
context.private_batches = sorted(private_batches, key=lambda d: d.start_date)
|
||||||
|
|
||||||
if frappe.session.user != "Guest":
|
if frappe.session.user != "Guest":
|
||||||
my_batches_info = []
|
my_batches_info = []
|
||||||
|
|||||||
Reference in New Issue
Block a user