Merge pull request #303 from pateljannat/course-page-redesign

This commit is contained in:
Jannat Patel
2022-02-18 12:52:05 +05:30
committed by GitHub
9 changed files with 97 additions and 56 deletions

View File

@@ -183,7 +183,8 @@ jinja = {
"school.lms.utils.get_reviews", "school.lms.utils.get_reviews",
"school.lms.utils.is_eligible_to_review", "school.lms.utils.is_eligible_to_review",
"school.lms.utils.get_initial_members", "school.lms.utils.get_initial_members",
"school.lms.utils.get_sorted_reviews" "school.lms.utils.get_sorted_reviews",
"school.lms.utils.is_instructor"
], ],
"filters": [] "filters": []
} }

View File

@@ -81,7 +81,7 @@ def get_lesson_details(chapter):
for row in lesson_list: for row in lesson_list:
lesson_details = frappe.db.get_value("Course Lesson", row.lesson, lesson_details = frappe.db.get_value("Course Lesson", row.lesson,
["name", "title", "include_in_preview", "body"], as_dict=True) ["name", "title", "include_in_preview", "body", "creation"], as_dict=True)
lesson_details.number = flt("{}.{}".format(chapter.idx, row.idx)) lesson_details.number = flt("{}.{}".format(chapter.idx, row.idx))
lessons.append(lesson_details) lessons.append(lesson_details)
return lessons return lessons
@@ -289,3 +289,6 @@ def get_initial_members(course):
member.member, ["name", "username", "full_name", "user_image"], as_dict=True)) member.member, ["name", "username", "full_name", "user_image"], as_dict=True))
return member_details return member_details
def is_instructor(course):
return len(list(filter(lambda x: x.name == frappe.session.user, get_instructors(course)))) > 0

View File

@@ -41,14 +41,14 @@
{% elif is_instructor and not lesson.include_in_preview %} {% elif is_instructor and not lesson.include_in_preview %}
<a class="lesson-links" <a class="lesson-links"
title="This lesson is not available for preview. As you are the Instructor of the course only you can see it." title="This lesson is not available for preview. As you are the Instructor of the course only you can see it."
href="{{ course.get_lesson_url(lesson.number) }}{{course.query_parameter}}" href="{{ get_lesson_url(lesson.number) }}{{course.query_parameter}}"
data-course="{{ course.name }}"> data-course="{{ course.name }}">
<img class="mr-3" src="/assets/school/icons/lock.svg"> <img class="mr-3" src="/assets/school/icons/lock.svg">
<div>{{ lesson.title }}</div> <div>{{ lesson.title }}</div>
</a> </a>
{% else %} {% else %}
<div class="no-preview" title="This lesson is not available for preview"> <div class="no-preview" title="This lesson is not available for preview" data-course="{{ course.name }}">
<div class="lesson-links"> <div class="lesson-links">
<img class="mr-3" src="/assets/school/icons/lock.svg"> <img class="mr-3" src="/assets/school/icons/lock.svg">
<div>{{ lesson.title }}</div> <div>{{ lesson.title }}</div>
@@ -76,9 +76,13 @@ frappe.ready(() => {
rotate_chapter_icon(e); rotate_chapter_icon(e);
}); });
}) $(".no-preview").click((e) => {
show_no_preview_dialog(e);
});
var expand_the_first_chapter = () => { });
const expand_the_first_chapter = () => {
var elements = $(".course-outline .collapse"); var elements = $(".course-outline .collapse");
elements.each((i, element) => { elements.each((i, element) => {
if (i < 1) { if (i < 1) {
@@ -86,9 +90,9 @@ var expand_the_first_chapter = () => {
return false; return false;
} }
}); });
} };
var expand_the_active_chapter = () => { const expand_the_active_chapter = () => {
/* Find anchor matching the URL for course details page */ /* Find anchor matching the URL for course details page */
var selector = $(`a[href="${decodeURIComponent(window.location.pathname)}"]`).parent(); var selector = $(`a[href="${decodeURIComponent(window.location.pathname)}"]`).parent();
@@ -111,21 +115,30 @@ var expand_the_active_chapter = () => {
else { else {
expand_the_first_chapter(); expand_the_first_chapter();
} }
} };
var show_section = (element) => { const show_section = (element) => {
$(element).addClass("show"); $(element).addClass("show");
$(element).siblings(".chapter-title").children(".chapter-icon").css("transform", "rotate(90deg)"); $(element).siblings(".chapter-title").children(".chapter-icon").css("transform", "rotate(90deg)");
$(element).siblings(".chapter-title").attr("aria-expanded", true); $(element).siblings(".chapter-title").attr("aria-expanded", true);
} };
var rotate_chapter_icon = (e) => { const rotate_chapter_icon = (e) => {
var icon = $(e.currentTarget).children(".chapter-icon"); var icon = $(e.currentTarget).children(".chapter-icon");
if (icon.css("transform") == "none") { if (icon.css("transform") == "none") {
icon.css("transform", "rotate(90deg)"); icon.css("transform", "rotate(90deg)");
} else { } else {
icon.css("transform", "none"); icon.css("transform", "none");
} }
} };
const show_no_preview_dialog = (e) => {
frappe.warn(__("Not available for preview"),
__("This lesson is not available for preview. Please join the course to access it."),
() => {
window.location.href = `/courses/${ $(e.currentTarget).data("course") }`
},
__("Start Learning"), false);
};
</script> </script>

View File

@@ -114,10 +114,11 @@ def exercise_renderer(argument):
def youtube_video_renderer(video_id): def youtube_video_renderer(video_id):
return f""" return f"""
<iframe width="100%" height="315" <iframe width="100%" height="400"
src="https://www.youtube.com/embed/{video_id}" src="https://www.youtube.com/embed/{video_id}"
title="YouTube video player" title="YouTube video player"
frameborder="0" frameborder="0"
style="border-radius: var(--border-radius-lg)"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen> allowfullscreen>
</iframe> </iframe>

View File

@@ -403,6 +403,8 @@ input[type=checkbox] {
font-size: var(--text-md); font-size: var(--text-md);
line-height: 20px; line-height: 20px;
box-shadow: var(--btn-shadow); box-shadow: var(--btn-shadow);
border: none;
width: fit-content;
} }
.button:disabled { .button:disabled {
@@ -412,6 +414,7 @@ input[type=checkbox] {
.wide-button { .wide-button {
padding: 0.5rem 6rem; padding: 0.5rem 6rem;
font-weight: 500; font-weight: 500;
width: inherit;
} }
@media (max-width: 768px) { @media (max-width: 768px) {
@@ -435,10 +438,8 @@ input[type=checkbox] {
color: var(--gray-700); color: var(--gray-700);
} }
@media (max-width: 600px) { .is-default:disabled {
.video-preview { color: var(--gray-500);
margin-top: 16px;
}
} }
.is-primary { .is-primary {
@@ -561,7 +562,7 @@ input[type=checkbox] {
} }
.course-content-parent .lesson-links { .course-content-parent .lesson-links {
padding: 0 0 0 1rem; padding: 0.5rem 1rem;
margin-bottom: 0.75rem; margin-bottom: 0.75rem;
font-size: 0.85rem; font-size: 0.85rem;
line-height: 200%; line-height: 200%;
@@ -669,7 +670,7 @@ input[type=checkbox] {
font-weight: 600; font-weight: 600;
font-size: var(--text-3-5xl); font-size: var(--text-3-5xl);
letter-spacing: -0.0175em; letter-spacing: -0.0175em;
color: var(--gray-800); color: var(--gray-900);
margin-bottom: 1rem; margin-bottom: 1rem;
} }
@@ -859,8 +860,7 @@ input[type=checkbox] {
} }
.lesson-content-card { .lesson-content-card {
padding: 24px; margin-top: 2rem;
flex-direction: column;
} }
.lesson-content-card .alert-dismissible .close { .lesson-content-card .alert-dismissible .close {
@@ -905,8 +905,15 @@ input[type=checkbox] {
} }
.active-lesson { .active-lesson {
background-color: var(--gray-100); background-color: var(--blue-100);
border-radius: var(--border-radius-md); border-radius: var(--border-radius-md);
color: var(--blue-500);
}
.lesson-title {
display: flex;
align-items: center;
margin-bottom: 1rem;
} }
.lesson-progress { .lesson-progress {
@@ -914,7 +921,7 @@ input[type=checkbox] {
padding: 4px 8px 4px; padding: 4px 8px 4px;
font-size: 10px; font-size: 10px;
line-height: 120%; line-height: 120%;
margin: 0px 10px 20px; margin-left: 1rem;
border-radius: var(--border-radius-md); border-radius: var(--border-radius-md);
font-weight: bold; font-weight: bold;
} }

View File

@@ -47,9 +47,9 @@
</div> </div>
<div class="quiz-footer"> <div class="quiz-footer">
<span class="font-weight-bold"> <span class="current-question">1</span> of {{ quiz.questions | length }}</span> <span class="font-weight-bold"> <span class="current-question">1</span> of {{ quiz.questions | length }}</span>
<button class="button pull-right" id="check" disabled>Check</button> <button class="button pull-right is-default" id="check" disabled>Check</button>
<button class="button hide" id="next">Next Question</button> <div class="button is-secondary hide" id="next">Next Question</div>
<button class="button is-default hide" id="summary">Summary</button> <div class="button is-secondary is-default hide" id="summary">Summary</div>
<small id="submission-message" class="font-weight-bold hide"> Please join the course to submit the Quiz.</small> <small id="submission-message" class="font-weight-bold hide"> Please join the course to submit the Quiz.</small>
</div> </div>
<div class="button is-secondary pull-right hide" id="try-again">Try Again</div> <div class="button is-secondary pull-right hide" id="try-again">Try Again</div>

View File

@@ -33,34 +33,60 @@
{% endblock %} {% endblock %}
{% macro LessonContent(lesson) %} {% macro LessonContent(lesson) %}
{% set is_instructor = frappe.session.user == course.instructor %} {% set instructors = get_instructors(course.name) %}
{% set is_instructor = is_instructor(course.name) %}
<div class="lesson-content"> <div class="lesson-content">
<div class="course-home-headings title <div class="lesson-title">
{% if membership %} is-member {% endif %} <div class="course-home-headings title mb-0
{% if membership or is_instructor %} eligible-for-submission {% endif %}" data-lesson="{{ lesson.name }}" {% if membership %} is-member {% endif %}
data-course="{{ course.name }}"> {% if membership or is_instructor %} eligible-for-submission {% endif %}" data-lesson="{{ lesson.name }}"
{{ lesson.title }} data-course="{{ course.name }}">{{ lesson.title }}</div>
<span class="lesson-progress {{hide if get_progress(course.name, lesson.name) != 'Complete' else ''}}">COMPLETED</span> <span class="lesson-progress {{hide if get_progress(course.name, lesson.name) != 'Complete' else ''}}">COMPLETED</span>
</div> </div>
<div class="d-flex align-items-center">
{% set instructors = instructors %}
{% set ins_len = instructors | length %}
{% for instructor in instructors %}
{% if ins_len > 1 and loop.index == 1 %}
<div class="avatar-group overlap">
{% endif %}
{{ widgets.Avatar(member=instructor, avatar_class="avatar-small") }}
{% if ins_len > 1 and loop.index == ins_len %}
</div>
{% endif %}
{% endfor %}
<a class="button-links ml-2" href="{{ get_profile_url(instructors[0].username) }}">
<span class="course-creator-name">
{% if ins_len == 1 %}
{{ instructors[0].full_name }}
{% else %}
{% set suffix = "other" if ins_len - 1 == 1 else "others" %}
{{ instructors[0].full_name.split(" ")[0] }} and {{ ins_len - 1 }} {{ suffix }}
{% endif %}
</span>
</a>
<div class="ml-3 course-meta"> {{ frappe.utils.format_date(lesson.creation, "medium") }} </div>
</div>
<div class="markdown-source lesson-content-card">
{% if membership or lesson.include_in_preview or is_instructor %} {% if membership or lesson.include_in_preview or is_instructor %}
<div class="common-card-style lesson-content-card markdown-source"> {% if is_instructor and not lesson.include_in_preview %}
{% if is_instructor and not lesson.include_in_preview %} <div class="small alert alert-secondary alert-dismissible mt-4 mb-4">
<small class="alert alert-secondary alert-dismissible">
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">&times;</a> <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
</small>
{% endif %}
{{ render_html(lesson.body) }}</div>
{% else %}
<div class="common-card-style lesson-content-card">
<div class="w-25 text-center" style="margin: 0 auto;">
<small>This lesson is not available for preview. Please join the course to access it.</small>
<a class="button is-primary ml-auto mr-auto mt-3" href="/courses/{{ course.name }}"> Start Learning </a>
</div> </div>
</div>
{% endif %} {% endif %}
{{ render_html(lesson.body) }}
{% else %}
<div class="">
<a class="button is-primary pull-right" href="/courses/{{ course.name }}"> Start Learning </a>
<div class="">This lesson is not available for preview. Please join the course to access it.</div>
</div>
{% endif %}
</div>
</div> </div>
{% endmacro %} {% endmacro %}

View File

@@ -21,10 +21,6 @@ frappe.ready(() => {
view_all_mentors(e); view_all_mentors(e);
}); });
$(".video-preview").click((e) => {
show_video_dialog(e);
});
$(".review-link").click((e) => { $(".review-link").click((e) => {
show_review_dialog(e); show_review_dialog(e);
}); });
@@ -158,11 +154,6 @@ var view_all_mentors = (e) => {
} }
} }
var show_video_dialog = (e) => {
e.preventDefault();
$("#video-modal").modal("show");
}
var show_review_dialog = (e) => { var show_review_dialog = (e) => {
e.preventDefault(); e.preventDefault();
$("#review-modal").modal("show"); $("#review-modal").modal("show");

View File

@@ -1,6 +1,5 @@
import frappe import frappe
from school.lms.utils import slugify, get_membership, get_lessons, get_batch from school.lms.utils import slugify, get_membership, get_lessons, get_batch, get_lesson_url
def get_common_context(context): def get_common_context(context):
context.no_cache = 1 context.no_cache = 1