fix: ui cleanup

This commit is contained in:
Jannat Patel
2022-05-04 16:54:16 +05:30
parent 503c74c488
commit 8017715bc7
9 changed files with 31 additions and 381 deletions

View File

@@ -24,6 +24,7 @@
"fieldname": "chapter", "fieldname": "chapter",
"fieldtype": "Link", "fieldtype": "Link",
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 1,
"label": "Course Chapter", "label": "Course Chapter",
"options": "Course Chapter", "options": "Course Chapter",
"reqd": 1 "reqd": 1
@@ -75,6 +76,8 @@
"fetch_from": "chapter.course", "fetch_from": "chapter.course",
"fieldname": "course", "fieldname": "course",
"fieldtype": "Link", "fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Course", "label": "Course",
"options": "LMS Course", "options": "LMS Course",
"read_only": 1 "read_only": 1
@@ -82,7 +85,7 @@
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2022-04-22 12:59:23.641915", "modified": "2022-05-02 17:16:12.450460",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "Course Lesson", "name": "Course Lesson",

View File

@@ -34,10 +34,11 @@
"related_courses", "related_courses",
"certification_section", "certification_section",
"enable_certification", "enable_certification",
"expiry",
"section_break_23",
"grant_certificate_after", "grant_certificate_after",
"evaluator", "evaluator",
"column_break_22", "column_break_26",
"expiry",
"max_attempts", "max_attempts",
"duration", "duration",
"pricing_section", "pricing_section",
@@ -177,10 +178,6 @@
"fieldtype": "Check", "fieldtype": "Check",
"label": "Paid Certificate" "label": "Paid Certificate"
}, },
{
"fieldname": "column_break_22",
"fieldtype": "Column Break"
},
{ {
"depends_on": "enable_certification", "depends_on": "enable_certification",
"fieldname": "grant_certificate_after", "fieldname": "grant_certificate_after",
@@ -228,6 +225,14 @@
"fieldtype": "Select", "fieldtype": "Select",
"label": "Duration for Attempts", "label": "Duration for Attempts",
"options": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12" "options": "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12"
},
{
"fieldname": "section_break_23",
"fieldtype": "Section Break"
},
{
"fieldname": "column_break_26",
"fieldtype": "Column Break"
} }
], ],
"is_published_field": "published", "is_published_field": "published",
@@ -253,7 +258,7 @@
"link_fieldname": "course" "link_fieldname": "course"
} }
], ],
"modified": "2022-04-28 16:15:10.047183", "modified": "2022-05-04 11:03:24.001015",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Course", "name": "LMS Course",

View File

@@ -105,7 +105,7 @@ def sanitize_html(html, macro):
any broken tags. This makes sures that all those things are fixed any broken tags. This makes sures that all those things are fixed
before passing to the etree parser. before passing to the etree parser.
""" """
soup = BeautifulSoup(html, features="lxml") soup = BeautifulSoup(html, features="html5lib")
nodes = soup.body.children nodes = soup.body.children
classname = "" classname = ""
if macro == "YouTubeVideo": if macro == "YouTubeVideo":

View File

@@ -30,7 +30,7 @@
<a class="lesson-links" href="{{ get_lesson_url(course.name, lesson.number) }}{{course.query_parameter}}" <a class="lesson-links" href="{{ get_lesson_url(course.name, lesson.number) }}{{course.query_parameter}}"
data-course="{{ course.name }}"> data-course="{{ course.name }}">
<svg class="icon icon-md mr-2"> <svg class="icon icon-md mr-2">
<use class="" href="#{{ lesson.icon }}{% if active %}-blue{% endif %}"> <use class="" href="#{{ lesson.icon }}">
</svg> </svg>
{{ lesson.title }} {{ lesson.title }}
@@ -148,8 +148,6 @@ const expand_the_active_chapter = () => {
}) })
selector.addClass("active-lesson"); selector.addClass("active-lesson");
let href = selector.find("use").attr("href");
!href.endsWith("blue") && selector.find("use").attr("href", `${href}-blue`);
show_section(selector.parent().parent()); show_section(selector.parent().parent());
} }

View File

@@ -275,11 +275,7 @@ input[type=checkbox] {
} }
.course-card-wide { .course-card-wide {
background-color: white;
padding: 0 1.25rem 1.25rem;
border-radius: var(--border-radius);
width: 50%; width: 50%;
box-shadow: var(--shadow-base);
font-size: var(--text-base); font-size: var(--text-base);
} }
@@ -611,7 +607,7 @@ input[type=checkbox] {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin: 24px 0px 0px; margin: 2rem 0 4rem;
} }
.lesson-pagination-parent { .lesson-pagination-parent {
@@ -629,9 +625,8 @@ input[type=checkbox] {
} }
.active-lesson { .active-lesson {
background-color: var(--blue-100); background-color: var(--gray-200);
border-radius: var(--border-radius-md); border-radius: var(--border-radius-md);
color: var(--blue-500);
} }
.lesson-title { .lesson-title {
@@ -854,7 +849,7 @@ pre {
.certificate-price { .certificate-price {
font-weight: bold; font-weight: bold;
margin-bottom: 0.5rem; margin-bottom: 1rem;
} }
.certificate-ribbon { .certificate-ribbon {
@@ -1158,10 +1153,12 @@ pre {
.job-card-heading { .job-card-heading {
font-weight: 600; font-weight: 600;
color: var(--gray-900); color: var(--gray-900);
margin-bottom: 0.4rem;
} }
.course-head-container { .course-head-container {
color: var(--gray-900); color: var(--gray-900);
background-color: var(--gray-200);
} }
.seperator { .seperator {
@@ -1178,8 +1175,8 @@ pre {
box-shadow: var(--shadow-sm); box-shadow: var(--shadow-sm);
overflow: auto; overflow: auto;
width: fit-content; width: fit-content;
position: fixed; position: absolute;
top: 50%; top: 10%;
right: 7%; right: 7%;
max-width: 400px; max-width: 400px;
z-index: 4; z-index: 4;
@@ -1196,10 +1193,6 @@ pre {
} }
} }
.video-in-overlay {
top: 40%;
}
.course-overlay-content { .course-overlay-content {
padding: 1.25rem; padding: 1.25rem;
font-size: var(--text-base); font-size: var(--text-base);

View File

@@ -1,326 +1 @@
{% extends "templates/base.html" %} `
{% block title %}{{ course.title }}
{% 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">
{{ CourseHomeHeader(course) }}
<div class="course-home-page">
<div class="container">
<div class="course-body-container">
{{ CourseHeaderOverlay(course) }}
{{ Description(course) }}
{{ widgets.CourseOutline(course=course, membership=membership, is_user_interested=is_user_interested) }}
{{ widgets.Reviews(course=course, membership=membership) }}
</div>
</div>
</div>
</div>
{{ RelatedCourses(course) }}
</div>
{% endblock %}
{% macro CourseHomeHeader(course) %}
<div class="course-head-container"
style=" {% if course.image %}
background-position: center;
background-size: cover;
background-image: url({{ course.image }});
{% else %} background-color: var(--gray-200) {% endif %}">
<div class="container pt-5 pb-5">
<div class="course-card-wide" style="">
{{ BreadCrumb(course) }}
{{ CourseCardWide(course) }}
</div>
</div>
</div>
{% endmacro %}
<!-- BreadCrumb -->
{% macro BreadCrumb(course) %}
<div class="breadcrumb">
<a class="dark-links" href="/courses">{{ _("All Courses") }}</a>
<img class="ml-1 mr-1" src="/assets/lms/icons/chevron-right.svg">
<span class="breadcrumb-destination">{{ course.title }}</span>
</div>
{% endmacro %}
<!-- Course Card -->
{% macro CourseCardWide(course) %}
<div class="">
<div class="d-flex align-items-center">
{% for tag in get_tags(course.name) %}
<div class="course-card-pills">{{ tag }}</div>
{% endfor %}
</div>
<div class="course-card-wide-title">
{{ course.title }}
</div>
<div class="">
{{ course.short_introduction }}
</div>
{% if membership %}
{% set progress = frappe.utils.cint(membership.progress) %}
<div class="progress" title="{{ progress }}% Completed">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ progress }}"
aria-valuemin="0" aria-valuemax="100" style="width:{{ progress }}%">
</div>
</div>
{% endif %}
<div class="mt-3">
<div class="bold-heading">Instructors:</div>
{% for instructor in get_instructors(course.name) %}
<div class="mt-1">
{{ widgets.Avatar(member=instructor, avatar_class="avatar-small") }}
<a class="button-links" href="{{ get_profile_url(instructor.username) }}">
<span class="course-instructor"> {{ instructor.full_name }} </span>
</a>
</div>
{% endfor %}
</div>
</div>
{% endmacro%}
{% macro CourseHeaderOverlay(course) %}
<div class="course-overlay-card {% if course.video_link %} video-in-overlay {% endif %}">
{% if course.video_link %}
<iframe class="preview-video" src="{{ course.video_link }}"></iframe>
{% endif %}
<div class="course-overlay-content">
<div class="course-home-headings"> {{ 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 >= course.max_attempts %}
<p> {{ _("You have exceeded the maximum number of attempts allowed to appear for evaluations of this course.") }} </p>
{% endif %}
{% if is_instructor(course.name) %}
<div class="vertically-center mb-4">
<a class="button is-default button-links mr-2" href="/course?name={{ course.name }}"> {{ _("Edit") }} </a>
<a class="button is-default button-links mr-2" href="/chapter">
<svg class="icon icon-sm mr-1"><use href="#icon-add"></use></svg>
{{ _("Add Chapter") }}
</a>
<a class="button is-default button-links mr-2" href="/lesson">
<svg class="icon icon-sm mr-1"><use href="#icon-add"></use></svg>
{{ _("Add Lesson") }}
</a>
</div>
{% endif %}
<div class="vertically-center justify-content-center mb-2">
<div class="">
<svg class="icon icon-md mr-1">
<use class="" href="#icon-users">
</svg>
{{ get_students(course.name) | length }} {{ _("Enrolled") }}
</div>
<span class="seperator"></span>
{% if get_lessons(course.name) | length %}
<div class="">
<svg class="icon icon-md mr-1">
<use href="#icon-education"></use>
</svg>
{{ get_lessons(course.name) | length }} {{ _("Lessons") }}
</div>
{% endif %}
</div>
{% if course.paid_certificate %}
<div class="certificate-price" data-price="{{ course.price_certificate }}">
{{ _("Certificate Price:") }} {{ frappe.utils.fmt_money(course.price_certificate, 2, course.currency) }}
</div>
{% endif %}
{% set lesson_index = get_lesson_index(membership.current_lesson) if membership and
membership.current_lesson
else '1.1' %}
{% 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) %}
<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-2" href="/courses/{{ course.name }}/{{ certificate }}">
{{ _("Get Certificate") }}
</a>
{% elif eligible %}
<a class="button wide-button is-secondary mt-2" 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-4" id="certification" data-course="{{ course.name }}">
{{ _("Get Certificate") }}
</div>
{% endif %}
{% endif %}
</div>
</div>
<div class="modal fade" id="slot-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="font-weight-bold">{{ _("Pick a Slot") }}</div>
<button type="button" class="close close-slot-modal" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="slot-form">
<p class="">{{ _("This course requires you to complete an evaluation to get certified. Please pick a slot based on your convenience for the evaluations. ") }}</p>
<div class="form-group">
<div class="clearfix">
<label class="control-label reqd" style="padding-right: 0px;">{{ _("Date") }}</label>
</div>
<div class="control-input-wrapper">
<div class="control-input">
<input type="date" class="input-with-feedback form-control bold" data-fieldtype="Date" data-course="{{ course.name | urlencode }}"
id="slot-date" min="{{ frappe.utils.format_date(frappe.utils.add_days(frappe.utils.getdate(), 1), 'yyyy-mm-dd') }}">
</div>
</div>
</div>
<div class="form-group">
<div class="clearfix">
<label class="control-label reqd slot-label hide" style="padding-right: 0px;">{{ _("Slots") }}</label>
</div>
<div class="control-input-wrapper">
<div class="control-input">
<div class="slots"></div>
</div>
</div>
</div>
<p id="no-slots-message" class="small text-danger hide"> {{ _("There are no slots available on this day.") }} </p>
</form>
</div>
<div class="modal-footer">
<div class="button is-primary" data-course="{{ course.name | urlencode}}" id="submit-slot">
{{ _("Submit") }}</div>
</div>
</div>
</div>
</div>
{% endmacro %}
{% macro Description(course) %}
<div class="course-description-section">
{{ frappe.utils.md_to_html(course.description) }}
</div>
{% 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 %}

View File

@@ -50,12 +50,6 @@ frappe.ready(() => {
select_slot(e); select_slot(e);
}); });
$(document).scroll(function() {
let timer;
clearTimeout(timer);
timer = setTimeout(() => { handle_overlay_display.apply(this, arguments); }, 500);
});
}); });
var hide_wrapped_mentor_cards = () => { var hide_wrapped_mentor_cards = () => {
@@ -127,8 +121,8 @@ var submit_review = (e) => {
e.preventDefault(); e.preventDefault();
var rating = $(".rating-field").children(".star-click").length; var rating = $(".rating-field").children(".star-click").length;
var review = $(".review-field").val(); var review = $(".review-field").val();
if (!review || !rating) { if (!rating) {
$(".error-field").text("Both Rating and Review are required."); $(".error-field").text("Please provide a rating.");
return; return;
} }
frappe.call({ frappe.call({
@@ -166,24 +160,6 @@ const element_not_in_viewport = (el) => {
return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight; return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight;
}; };
const handle_overlay_display = () => {
const element = $(".related-courses").length && $(".related-courses")[0];
if (element && element_not_in_viewport(element)) {
$(".course-overlay-card").css({
"position": "fixed",
"top": "30%",
"bottom": "inherit"
});
}
else if (element && !element_not_in_viewport(element)) {
$(".course-overlay-card").css({
"position": "absolute",
"top": "inherit",
"bottom": "5%"
});
}
};
const submit_for_review = (e) => { const submit_for_review = (e) => {
let course = $(e.currentTarget).data("course"); let course = $(e.currentTarget).data("course");
frappe.call({ frappe.call({

View File

@@ -26,7 +26,7 @@
<div class="job-card-info"> <div class="job-card-info">
<div class="job-card-heading">{{ _(job.job_title) }}</div> <div class="job-card-heading">{{ _(job.job_title) }}</div>
<div class="vertically-center course-meta"> <div class="vertically-center course-meta">
<div class="mr-3">{{ job.company_name }}</div> <div class="mr-5">{{ job.company_name }}</div>
<div class="vertically-center"> <div class="vertically-center">
<svg class="icon icon-sm"> <svg class="icon icon-sm">
<use class="" href="#icon-location"> <use class="" href="#icon-location">
@@ -38,7 +38,7 @@
<div class="job-card-logo-section course-meta"> <div class="job-card-logo-section course-meta">
<div class="indicator-pill green ml-3"> {{ job.type }} </div> <div class="indicator-pill green ml-3"> {{ job.type }} </div>
<div class="">{{ frappe.utils.format_date(job.creation, "medium") }}</div> <div class="mt-2 text-muted">{{ frappe.utils.format_date(job.creation, "medium") }}</div>
</div> </div>
<a class="stretched-link" href="/jobs/{{ job.name }}"></a> <a class="stretched-link" href="/jobs/{{ job.name }}"></a>
</div> </div>

View File

@@ -22,7 +22,7 @@
<div class="course-home-headings mb-0">{{ _(job.job_title) }}</div> <div class="course-home-headings mb-0">{{ _(job.job_title) }}</div>
<div class="indicator-pill green ml-5"> {{ job.type }} </div> <div class="indicator-pill green ml-5"> {{ job.type }} </div>
</div> </div>
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mt-2">
<a class="dark-links course-meta mr-5" href="{{ job.company_website }}">{{ job.company_name }}</a> <a class="dark-links course-meta mr-5" href="{{ job.company_website }}">{{ job.company_name }}</a>
<div class="vertically-center course-meta mr-5"> <div class="vertically-center course-meta mr-5">
<svg class="icon icon-sm"> <svg class="icon icon-sm">