fix: text editor for lesson
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from codecs import ignore_errors
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
import json
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<div class="mt-2">
|
||||
<button class="btn btn-sm btn-secondary btn-save-chapter"
|
||||
data-index="{{ loop.index }}" data-chapter="{{ chapter.name }}"> {{ _('Save') }} </button>
|
||||
<a class="btn btn-sm btn-secondary btn-lesson ml-4"
|
||||
<a class="btn btn-sm btn-secondary btn-lesson ml-2"
|
||||
href="/courses/{{ course.name }}/learn/{{loop.index}}.{{ lessons | length + 1 }}?edit=1"> {{ _("New Lesson") }} </a>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -55,9 +55,12 @@
|
||||
{% set active = membership.current_lesson == lesson.name %}
|
||||
<div class="lesson-info {% if active and not course.edit_mode %} active-lesson {% endif %}">
|
||||
|
||||
{% if membership or lesson.include_in_preview %}
|
||||
<a class="lesson-links" href="{{ get_lesson_url(course.name, lesson.number) }}{{course.query_parameter}}"
|
||||
data-course="{{ course.name }}">
|
||||
{% if membership or lesson.include_in_preview or is_instructor %}
|
||||
<a class="lesson-links" data-course="{{ course.name }}"
|
||||
{% if is_instructor and not lesson.include_in_preview %}
|
||||
title="{{ _('This lesson is not available for preview. As you are the Instructor of the course only you can see it.') }}"
|
||||
{% endif %}
|
||||
href="{{ get_lesson_url(course.name, lesson.number) }}{% if course.edit_mode and is_instructor %}?edit=1{% endif %}{{course.query_parameter}}">
|
||||
|
||||
<svg class="icon icon-sm mr-2">
|
||||
<use class="" href="#{{ lesson.icon }}">
|
||||
@@ -73,17 +76,6 @@
|
||||
|
||||
</a>
|
||||
|
||||
{% elif is_instructor and not lesson.include_in_preview %}
|
||||
<a class="lesson-links" data-course="{{ course.name }}"
|
||||
title="This lesson is not available for preview. As you are the Instructor of the course only you can see it."
|
||||
href="{{ get_lesson_url(course.name, lesson.number) }}{% if course.edit_mode %}?edit=1{% endif %}{{course.query_parameter}}">
|
||||
|
||||
<svg class="icon icon-sm mr-2">
|
||||
<use class="" href="#icon-lock">
|
||||
</svg>
|
||||
<div>{{ lesson.title }}</div>
|
||||
</a>
|
||||
|
||||
{% else %}
|
||||
<div class="no-preview" title="This lesson is not available for preview" data-course="{{ course.name }}">
|
||||
<div class="lesson-links">
|
||||
@@ -108,20 +100,8 @@
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{{ widgets.NoPreviewModal(course=course) }}
|
||||
|
||||
|
||||
<div class="course-home-outline">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- No Preview Modal -->
|
||||
|
||||
{{ widgets.NoPreviewModal(course=course) }}
|
||||
|
||||
<script>
|
||||
|
||||
@@ -139,6 +119,7 @@ frappe.ready(() => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
const expand_the_first_chapter = () => {
|
||||
let elements = $(".course-home-outline .collapse");
|
||||
elements.each((i, element) => {
|
||||
@@ -149,6 +130,7 @@ const expand_the_first_chapter = () => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const expand_the_active_chapter = () => {
|
||||
|
||||
/* Find anchor matching the URL for course details page */
|
||||
@@ -180,12 +162,14 @@ const expand_the_active_chapter = () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const show_section = (element) => {
|
||||
$(element).addClass("show");
|
||||
$(element).siblings(".chapter-title").children(".chapter-icon").css("transform", "rotate(90deg)");
|
||||
$(element).siblings(".chapter-title").attr("aria-expanded", true);
|
||||
};
|
||||
|
||||
|
||||
const rotate_chapter_icon = (e) => {
|
||||
let icon = $(e.currentTarget).children(".chapter-icon");
|
||||
if (icon.css("transform") == "none") {
|
||||
@@ -195,6 +179,7 @@ const rotate_chapter_icon = (e) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const show_no_preview_dialog = (e) => {
|
||||
$("#no-preview-modal").modal("show");
|
||||
};
|
||||
|
||||
@@ -329,7 +329,7 @@ input[type=checkbox] {
|
||||
.wide-button {
|
||||
padding: 0.5rem 6rem;
|
||||
font-weight: 500;
|
||||
width: inherit;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@@ -1505,7 +1505,7 @@ li {
|
||||
outline: none;
|
||||
background-color: var(--bg-light-gray);
|
||||
border-radius: var(--border-radius);
|
||||
border: 1px dashed var(--gray-400);
|
||||
border: 1px dashed var(--gray-600);
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
@@ -1555,5 +1555,4 @@ li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: var(--text-md);
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@@ -20,10 +20,6 @@ frappe.ready(() => {
|
||||
save_chapter(e);
|
||||
});
|
||||
|
||||
if ($("#body").length) {
|
||||
make_editor();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -108,9 +104,13 @@ const notify_user = (e) => {
|
||||
|
||||
|
||||
const add_chapter = (e) => {
|
||||
let next_index = $("[data-index]").last().data("index");
|
||||
if ($(".new-chapter").length) {
|
||||
scroll_to_chapter_container();
|
||||
return;
|
||||
}
|
||||
|
||||
$(`<div class="chapter-parent chapter-edit">
|
||||
let next_index = $("[data-index]").last().data("index");
|
||||
$(`<div class="chapter-parent chapter-edit new-chapter">
|
||||
<div contenteditable="true" data-placeholder="${__('Chapter Name')}" class="chapter-title-main"></div>
|
||||
<div class="small my-2" contenteditable="true" data-placeholder="${__('Short Description')}"
|
||||
class="chapter-description"></div>
|
||||
@@ -118,15 +118,18 @@ const add_chapter = (e) => {
|
||||
data-index="${next_index}"> ${__('Save')} </button>
|
||||
</div>`).insertAfter(`.chapter-parent:last`);
|
||||
|
||||
$(".btn-chapter").attr("disabled", true);
|
||||
$([document.documentElement, document.body]).animate({
|
||||
scrollTop: $(".chapter-parent:last").offset().top
|
||||
}, 1000);
|
||||
|
||||
$(".chapter-parent:last").find(".chapter-title-main").focus();
|
||||
scroll_to_chapter_container();
|
||||
};
|
||||
|
||||
|
||||
const scroll_to_chapter_container = () => {
|
||||
$([document.documentElement, document.body]).animate({
|
||||
scrollTop: $(".new-chapter").offset().top
|
||||
}, 1000);
|
||||
$(".new-chapter").find(".chapter-title-main").focus();
|
||||
}
|
||||
|
||||
|
||||
const save_chapter = (e) => {
|
||||
let target = $(e.currentTarget);
|
||||
let parent = target.closest(".chapter-parent");
|
||||
@@ -146,23 +149,3 @@ const save_chapter = (e) => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const make_editor = () => {
|
||||
this.code_field_group = new frappe.ui.FieldGroup({
|
||||
fields: [
|
||||
{
|
||||
fieldname: "code_md",
|
||||
fieldtype: "Code",
|
||||
options: "Markdown",
|
||||
wrap: true,
|
||||
max_lines: Infinity,
|
||||
min_lines: 20,
|
||||
default: "Jannat Patel",
|
||||
depends_on: 'eval:doc.type=="Markdown"',
|
||||
}
|
||||
],
|
||||
body: $("#body").get(0),
|
||||
});
|
||||
this.code_field_group.make();
|
||||
$("#body .form-section:last").removeClass("empty-section");
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Lesson Content -->
|
||||
<div class="markdown-source lesson-content-card">
|
||||
<div class="markdown-source lesson-content-card {% if lesson.edit_mode %} mb-0 mt-2 {% endif %} ">
|
||||
{% if membership or lesson.include_in_preview or is_instructor %}
|
||||
|
||||
{% if is_instructor and not lesson.include_in_preview and not lesson.edit_mode %}
|
||||
@@ -135,57 +135,52 @@
|
||||
|
||||
{% macro pagination(prev_url, next_url) %}
|
||||
<div class="lesson-pagination">
|
||||
<div>
|
||||
{% if prev_url %}
|
||||
<a class="button is-secondary dark-links prev" href="{{ prev_url }}">
|
||||
<img class="mr-2" src="/assets/lms/icons/left-arrow.svg">
|
||||
{{ _("Prev") }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% if prev_url %}
|
||||
<a class="button is-secondary dark-links prev" href="{{ prev_url }}">
|
||||
<img class="mr-2" src="/assets/lms/icons/left-arrow.svg">
|
||||
{{ _("Prev") }}
|
||||
</a>
|
||||
{% if not is_mentor(course.name, frappe.session.user) and membership %}
|
||||
{% set progress = get_progress(course.name, lesson.name) %}
|
||||
<div class="custom-checkbox {% if progress == 'Complete' %} hide {% endif %}">
|
||||
<label class="quiz-label">
|
||||
<input class="mark-progress" type="checkbox" checked>
|
||||
<img class="empty-checkbox" />
|
||||
<span class="small">{{ _("Mark as complete on moving to the next lesson") }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="button is-secondary mark-progress {{ progress }} {% if progress == 'Incomplete' or progress == None %} hide {% endif %}"
|
||||
data-progress="Incomplete">
|
||||
{{ _("Mark as Incomplete") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
{% if not is_mentor(course.name, frappe.session.user) and membership %}
|
||||
{% set progress = get_progress(course.name, lesson.name) %}
|
||||
<div class="custom-checkbox {% if progress == 'Complete' %} hide {% endif %}">
|
||||
<label class="quiz-label">
|
||||
<input class="mark-progress" type="checkbox" checked>
|
||||
<img class="empty-checkbox" />
|
||||
<span class="small">{{ _("Mark as complete on moving to the next lesson") }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="button is-secondary mark-progress {{ progress }} {% if progress == 'Incomplete' or progress == None %} hide {% endif %}"
|
||||
data-progress="Incomplete">
|
||||
{{ _("Mark as Incomplete") }}
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<a class="button is-primary next {% if membership.progress|int == 100 and not next_url %} hide {% endif %}"
|
||||
{% if next_url %} data-href="{{ next_url }}" {% endif %} href="">
|
||||
{% if next_url %} {{ _("Next") }} {% else %} {{ _("Mark as Complete") }} {% endif %}
|
||||
<img class="ml-2" src="/assets/lms/icons/side-arrow-white.svg">
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="button is-primary next {% if membership.progress|int == 100 and not next_url %} hide {% endif %}"
|
||||
{% if next_url %} data-href="{{ next_url }}" {% endif %} href="">
|
||||
{% if next_url %} {{ _("Next") }} {% else %} {{ _("Mark as Complete") }} {% endif %}
|
||||
<img class="ml-2" src="/assets/lms/icons/side-arrow-white.svg">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro EditLesson(lesson) %}
|
||||
<div contenteditable="true" data-placeholder="{{ _('Enter the lesson content.') }}"
|
||||
> {% if lesson.body %} {{ lesson.body }} {% endif %} </div>
|
||||
|
||||
<div id="body"></div>
|
||||
<div id="body" {% if lesson.body %} data-body="{{ lesson.body }}" {% endif %}></div>
|
||||
|
||||
<label class="preview">
|
||||
<input {% if lesson.include_in_preview %} checked {% endif %}
|
||||
type="checkbox" id="preview"> {{ _("Show preview of this lesson") }}
|
||||
<input {% if lesson.include_in_preview %} checked {% endif %} type="checkbox"
|
||||
id="preview"> {{ _("Show preview of this lesson") }}
|
||||
</label>
|
||||
|
||||
<div class="mt-8">
|
||||
<div class="mt-4">
|
||||
<a class="btn btn-secondary btn-md" href=""> {{ _("Back to Lesson") }} </a>
|
||||
<button class="btn btn-primary btn-md btn-lesson pull-right"> {{ _("Save") }} </button>
|
||||
|
||||
<div class="attachments-parent">
|
||||
@@ -210,6 +205,8 @@
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Discussions Component -->
|
||||
{% macro Discussions() %}
|
||||
{% set topics_count = frappe.db.count("Discussion Topic",
|
||||
{"reference_doctype": "Course Lesson", "reference_docname": lesson.name}) %}
|
||||
@@ -222,17 +219,17 @@
|
||||
{% set redirect_to = "/courses/" + course.name %}
|
||||
{% set empty_state_title = _("Have a doubt?") %}
|
||||
{% set empty_state_subtitle = _("Post it here, our mentors will help you out.") %}
|
||||
|
||||
{% include "frappe/templates/discussions/discussions_section.html" %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Scripts -->
|
||||
{%- block script %}
|
||||
{{ super() }}
|
||||
|
||||
<script type="text/javascript">
|
||||
var page_context = {{ page_context | tojson }};
|
||||
var page_context = {{ page_context | tojson }};
|
||||
</script>
|
||||
|
||||
{{ include_script('controls.bundle.js') }}
|
||||
{% for ext in page_extensions %}
|
||||
{{ ext.render_footer() }}
|
||||
{% endfor %}
|
||||
|
||||
@@ -75,6 +75,10 @@ frappe.ready(() => {
|
||||
$(".active-question").length && quiz_summary();
|
||||
});
|
||||
}
|
||||
|
||||
if ($("#body").length) {
|
||||
make_editor();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -479,14 +483,14 @@ const save_lesson = (e) => {
|
||||
method: "lms.lms.doctype.lms_course.lms_course.save_lesson",
|
||||
args: {
|
||||
"title": $("#title").text(),
|
||||
"body": $("#body").find("br").replaceWith("\n\n").end().text(),
|
||||
"body": this.code_field_group.fields_dict["code_md"].last_value,
|
||||
"chapter": $("#title").data("chapter"),
|
||||
"preview": $("#preview").prop("checked") ? 1 : 0,
|
||||
"idx": $("#title").data("index"),
|
||||
"lesson": lesson ? lesson : ""
|
||||
},
|
||||
callback: (data) => {
|
||||
window.location.reload();
|
||||
window.location.href = window.location.href.split("?")[0];
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -518,3 +522,26 @@ const build_attachment_table = (file_doc) => {
|
||||
</tr>
|
||||
`);
|
||||
};
|
||||
|
||||
|
||||
const make_editor = () => {
|
||||
this.code_field_group = new frappe.ui.FieldGroup({
|
||||
fields: [
|
||||
{
|
||||
fieldname: "code_md",
|
||||
fieldtype: "Code",
|
||||
options: "Markdown",
|
||||
wrap: true,
|
||||
max_lines: Infinity,
|
||||
min_lines: 20,
|
||||
default: $("#body").data("body"),
|
||||
depends_on: 'eval:doc.type=="Markdown"',
|
||||
}
|
||||
],
|
||||
body: $("#body").get(0),
|
||||
});
|
||||
this.code_field_group.make();
|
||||
$("#body .form-section:last").removeClass("empty-section");
|
||||
$("#body .frappe-control").removeClass("hide-control");
|
||||
$("#body .form-column").addClass("p-0");
|
||||
};
|
||||
|
||||
@@ -54,7 +54,10 @@ def get_current_lesson_details(lesson_number, context):
|
||||
details_list = list(filter(lambda x: cstr(x.number) == lesson_number, context.lessons))
|
||||
if not len(details_list):
|
||||
redirect_to_lesson(context.course)
|
||||
return details_list[0]
|
||||
lesson_info = details_list[0]
|
||||
lesson_info.body = lesson_info.body.replace("\"", "'")
|
||||
print(lesson_info)
|
||||
return lesson_info
|
||||
|
||||
|
||||
def get_url(lesson_number, course):
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
{{ course.title if course.title else _("New Course") }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block head_include %}
|
||||
{% include "public/icons/symbol-defs.svg" %}
|
||||
<link rel="stylesheet" href="/assets/frappe/css/font-awesome.css">
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="common-page-style pt-0 pb-0">
|
||||
<div class="course-home-top-container">
|
||||
@@ -118,7 +120,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro%}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Overlay -->
|
||||
@@ -133,25 +135,7 @@
|
||||
<div class="course-overlay-content">
|
||||
<div class="course-overlay-title"> {{ course.title }} </div>
|
||||
|
||||
<div id="interest-alert" class="{% if not is_user_interested %} hide {% endif %}">
|
||||
{{ _("You have opted to be notified for this course. You will receive an email when the course becomes available.") }}
|
||||
</div>
|
||||
|
||||
{% if certificate_request and not certificate %}
|
||||
<p class="mb-2"> <b>{{ _("Evaluation On: ") }}</b>
|
||||
{{ _("{0} at {1}").format(frappe.utils.format_date(certificate_request.date, "medium"),
|
||||
frappe.utils.format_time(certificate_request.start_time, "short")) }} </p>
|
||||
{% endif %}
|
||||
|
||||
{% if course.status == "Under Review" %}
|
||||
<div class="mb-4">
|
||||
{{ _("Your course is currently under review. Once the review is complete, the System Admins will publish it on the website.") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if no_of_attempts and no_of_attempts >= course.max_attempts %}
|
||||
<p> {{ _("You have exceeded the maximum number of attempts allowed to appear for evaluations of this course.") }} </p>
|
||||
{% endif %}
|
||||
{{ Notes(course) }}
|
||||
|
||||
<div class="vertically-center mb-3">
|
||||
<svg class="icon icon-md mr-1">
|
||||
@@ -181,73 +165,184 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% set lesson_index = get_lesson_index(membership.current_lesson) if membership and
|
||||
membership.current_lesson else "1.1" if first_lesson_exists(course.name) else None %}
|
||||
|
||||
{% if show_start_learing_cta %}
|
||||
<div class="button wide-button is-primary join-batch" data-course="{{ course.name | urlencode }}">
|
||||
{{ _("Start Learning") }}
|
||||
<img class="ml-2" src="/assets/lms/icons/white-arrow.svg" />
|
||||
</div>
|
||||
|
||||
{% elif is_instructor(course.name) and not course.published and course.status == "Under Review" %}
|
||||
<div class="button wide-button is-primary" id="submit-for-review" data-course="{{ course.name | urlencode }}">
|
||||
{{ _("Submit for Review") }}
|
||||
<img class="ml-2" src="/assets/lms/icons/white-arrow.svg" />
|
||||
</div>
|
||||
|
||||
{% elif is_instructor(course.name) and lesson_index %}
|
||||
<a class="button wide-button is-primary" id="continue-learning"
|
||||
href="{{ get_lesson_url(course.name, lesson_index) }}{{ course.query_parameter }}">
|
||||
{{ _("Checkout Course") }} <img class="ml-2" src="/assets/lms/icons/white-arrow.svg" />
|
||||
</a>
|
||||
|
||||
{% elif course.upcoming and not is_user_interested %}
|
||||
<div class="button wide-button is-default notify-me" data-course="{{course.name | urlencode}}">
|
||||
{{ _("Notify me when available") }}
|
||||
</div>
|
||||
|
||||
{% elif is_cohort_staff(course.name, frappe.session.user) %}
|
||||
<a class="button wide-button is-secondary"
|
||||
href="/courses/{{course.name}}/manage"
|
||||
style="color: inherit;">
|
||||
{{ _("Manage the course") }}
|
||||
</a>
|
||||
|
||||
{% elif membership %}
|
||||
<a class="button wide-button is-primary" id="continue-learning"
|
||||
href="{{ get_lesson_url(course.name, lesson_index) }}{{ course.query_parameter }}">
|
||||
{{ _("Continue Learning") }} <img class="ml-2" src="/assets/lms/icons/white-arrow.svg" />
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% set progress = frappe.utils.cint(membership.progress) %}
|
||||
|
||||
{% if membership and course.enable_certification %}
|
||||
{% if certificate %}
|
||||
<a class="button wide-button is-secondary mt-3" href="/courses/{{ course.name }}/{{ certificate }}">
|
||||
{{ _("Get Certificate") }}
|
||||
</a>
|
||||
|
||||
{% elif eligible_for_evaluation %}
|
||||
<a class="button wide-button is-secondary mt-3" id="apply-certificate" data-course="{{ course.name }}">
|
||||
{{ _("Apply for Certificate") }}
|
||||
</a>
|
||||
|
||||
{% elif course.grant_certificate_after == "Completion" and progress == 100 %}
|
||||
<div class="button wide-button is-secondary mt-3" id="certification" data-course="{{ course.name }}">
|
||||
{{ _("Get Certificate") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if is_instructor(course.name) %}
|
||||
<a class="btn btn-secondary btn-block" href="/courses/{{ course.name }}?edit=1"> {{ _("Edit Course") }} </a>
|
||||
{% endif %}
|
||||
{{ CTASection(course, membership) }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{{ SlotModal(course) }}
|
||||
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Description -->
|
||||
{% macro Description(course) %}
|
||||
<div class="course-description-section" {% if course.edit_mode %} style="min-height: 100px" {% endif %}
|
||||
{% if course.edit_mode %} contenteditable="true" {% endif %} id="description"
|
||||
data-placeholder="Description">{% if course.description %}{{ frappe.utils.md_to_html(course.description) }}{% endif %}</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Save -->
|
||||
{% macro Save(course) %}
|
||||
{% if course.edit_mode %}
|
||||
<div class="my-4">
|
||||
<button class="btn btn-primary btn-md btn-save-course">
|
||||
{{ _("Save Course Details") }} </button>
|
||||
<a class="btn btn-secondary btn-md btn-exit-edit ml-2" href="/courses/{{ course.name }}">
|
||||
{{ _("Back to Course") }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% macro CourseCreator(course) %}
|
||||
<div class="course-home-headings"> {{ _("Course Creators") }} </div>
|
||||
|
||||
<div class="common-card-style course-creators-card">
|
||||
{% set instructors = get_instructors(course.name) %}
|
||||
{% for instructor in instructors %}
|
||||
<div class="d-flex align-items-center">
|
||||
{{ widgets.Avatar(member=instructor, avatar_class="avatar-medium") }}
|
||||
<div class="ml-4">
|
||||
<div class="course-creator-name"> {{ instructor.full_name }} </div>
|
||||
<div class="course-meta"> {{ get_authored_courses(instructor.name) | length }} {{ _("Courses Created") }} </div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Related Courses Section -->
|
||||
{% macro RelatedCourses(course) %}
|
||||
{% if course.related_courses | length %}
|
||||
<div class="related-courses">
|
||||
<div class="container">
|
||||
<div class="course-home-headings"> {{ _("Other Courses") }} </div>
|
||||
<div class="carousel slide" id="carouselExampleControls" data-ride="carousel" data-interval="false">
|
||||
<div class="carousel-inner">
|
||||
{% for crs in course.related_courses %}
|
||||
{% if loop.index % 3 == 1 %}
|
||||
<div class="carousel-item {% if loop.index == 1 %} active {% endif %}"><div class="cards-parent">
|
||||
{% endif %}
|
||||
{{ widgets.CourseCard(course=crs, read_only=False) }}
|
||||
{% if loop.index % 3 == 0 or loop.index == course.related_courses | length %} </div> </div> {% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if course.related_courses | length > 3 %}
|
||||
<div class="slider-controls">
|
||||
<a class="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
</a>
|
||||
|
||||
<a class="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endif%}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- CTA's -->
|
||||
{% macro CTASection(course, membership) %}
|
||||
{% set lesson_index = get_lesson_index(membership.current_lesson) if membership and
|
||||
membership.current_lesson else "1.1" if first_lesson_exists(course.name) else None %}
|
||||
|
||||
{% if show_start_learing_cta %}
|
||||
<div class="btn btn-primary wide-button join-batch" data-course="{{ course.name | urlencode }}">
|
||||
{{ _("Start Learning") }}
|
||||
<img class="ml-2" src="/assets/lms/icons/white-arrow.svg" />
|
||||
</div>
|
||||
|
||||
{% elif is_instructor(course.name) and not course.published and course.status != "Under Review" %}
|
||||
<div class="btn btn-primary wide-button mb-2" id="submit-for-review" data-course="{{ course.name | urlencode }}">
|
||||
{{ _("Submit for Review") }}
|
||||
</div>
|
||||
|
||||
{% elif is_instructor(course.name) and lesson_index %}
|
||||
<a class="btn btn-primary wide-button" id="continue-learning"
|
||||
href="{{ get_lesson_url(course.name, lesson_index) }}{{ course.query_parameter }}">
|
||||
{{ _("Checkout Course") }} <img class="ml-2" src="/assets/lms/icons/white-arrow.svg" />
|
||||
</a>
|
||||
|
||||
{% elif course.upcoming and not is_user_interested %}
|
||||
<div class="btn btn-secondary wide-button notify-me" data-course="{{course.name | urlencode}}">
|
||||
{{ _("Notify me when available") }}
|
||||
</div>
|
||||
|
||||
{% elif is_cohort_staff(course.name, frappe.session.user) %}
|
||||
<a class="btn btn-secondary button-links wide-button" href="/courses/{{course.name}}/manage">
|
||||
{{ _("Manage the course") }}
|
||||
</a>
|
||||
|
||||
{% elif membership %}
|
||||
<a class="btn btn-primary wide-button" id="continue-learning"
|
||||
href="{{ get_lesson_url(course.name, lesson_index) }}{{ course.query_parameter }}">
|
||||
{{ _("Continue Learning") }} <img class="ml-2" src="/assets/lms/icons/white-arrow.svg" />
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% set progress = frappe.utils.cint(membership.progress) %}
|
||||
|
||||
{% if membership and course.enable_certification %}
|
||||
{% if certificate %}
|
||||
<a class="btn btn-secondary wide-button mt-3" href="/courses/{{ course.name }}/{{ certificate }}">
|
||||
{{ _("Get Certificate") }}
|
||||
</a>
|
||||
|
||||
{% elif eligible_for_evaluation %}
|
||||
<a class="btn btn-secondary wide-button mt-3" id="apply-certificate" data-course="{{ course.name }}">
|
||||
{{ _("Apply for Certificate") }}
|
||||
</a>
|
||||
|
||||
{% elif course.grant_certificate_after == "Completion" and progress == 100 %}
|
||||
<div class="btn btn-secondary wide-button is-secondary mt-3" id="certification" data-course="{{ course.name }}">
|
||||
{{ _("Get Certificate") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if is_instructor(course.name) %}
|
||||
<a class="btn btn-secondary wide-button" href="/courses/{{ course.name }}?edit=1"> {{ _("Edit Course") }} </a>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Notes and Messages -->
|
||||
{% macro Notes(course) %}
|
||||
<div id="interest-alert" class="{% if not is_user_interested %} hide {% endif %}">
|
||||
{{ _("You have opted to be notified for this course. You will receive an email when the course becomes available.") }}
|
||||
</div>
|
||||
|
||||
{% if certificate_request and not certificate %}
|
||||
<p class="mb-2"> <b>{{ _("Evaluation On: ") }}</b>
|
||||
{{ _("{0} at {1}").format(frappe.utils.format_date(certificate_request.date, "medium"),
|
||||
frappe.utils.format_time(certificate_request.start_time, "short")) }} </p>
|
||||
{% endif %}
|
||||
|
||||
{% if course.status == "Under Review" %}
|
||||
<div class="mb-4">
|
||||
{{ _("Your course is currently under review. Once the review is complete, the System Admins will publish it on the website.") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if no_of_attempts and no_of_attempts >= course.max_attempts %}
|
||||
<p> {{ _("You have exceeded the maximum number of attempts allowed to appear for evaluations of this course.") }} </p>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Modal for Slots -->
|
||||
{% macro SlotModal(course) %}
|
||||
<div class="modal fade" id="slot-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
@@ -291,76 +386,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Description -->
|
||||
{% macro Description(course) %}
|
||||
<div class="course-description-section" {% if course.edit_mode %} style="min-height: 100px" {% endif %}
|
||||
{% if course.edit_mode %} contenteditable="true" {% endif %} id="description"
|
||||
data-placeholder="Description">{% if course.description %}{{ frappe.utils.md_to_html(course.description) }}{% endif %}</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
<!-- Save -->
|
||||
{% macro Save(course) %}
|
||||
{% if course.edit_mode %}
|
||||
<div>
|
||||
<button class="btn btn-primary btn-md btn-save-course my-4">
|
||||
{{ _("Save Course Details") }} </button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro CourseCreator(course) %}
|
||||
<div class="course-home-headings"> {{ _("Course Creators") }} </div>
|
||||
|
||||
<div class="common-card-style course-creators-card">
|
||||
{% set instructors = get_instructors(course.name) %}
|
||||
{% for instructor in instructors %}
|
||||
<div class="d-flex align-items-center">
|
||||
{{ widgets.Avatar(member=instructor, avatar_class="avatar-medium") }}
|
||||
<div class="ml-4">
|
||||
<div class="course-creator-name"> {{ instructor.full_name }} </div>
|
||||
<div class="course-meta"> {{ get_authored_courses(instructor.name) | length }} {{ _("Courses Created") }} </div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro RelatedCourses(course) %}
|
||||
{% if course.related_courses | length %}
|
||||
<div class="related-courses">
|
||||
<div class="container">
|
||||
<div class="course-home-headings"> {{ _("Other Courses") }} </div>
|
||||
<div class="carousel slide" id="carouselExampleControls" data-ride="carousel" data-interval="false">
|
||||
<div class="carousel-inner">
|
||||
{% for crs in course.related_courses %}
|
||||
{% if loop.index % 3 == 1 %}
|
||||
<div class="carousel-item {% if loop.index == 1 %} active {% endif %}"><div class="cards-parent">
|
||||
{% endif %}
|
||||
{{ widgets.CourseCard(course=crs, read_only=False) }}
|
||||
{% if loop.index % 3 == 0 or loop.index == course.related_courses | length %} </div> </div> {% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if course.related_courses | length > 3 %}
|
||||
<div class="slider-controls">
|
||||
<a class="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
</a>
|
||||
|
||||
<a class="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endif%}
|
||||
{% endmacro %}
|
||||
|
||||
Reference in New Issue
Block a user