feat: new design system for exisitng course home

This commit is contained in:
Jannat Patel
2023-04-20 17:55:03 +05:30
parent 2b6436915d
commit 6232f8703e
11 changed files with 364 additions and 240 deletions

View File

@@ -138,6 +138,7 @@ fixtures = ["Custom Field", "Function", "Industry"]
website_route_rules = [ website_route_rules = [
{"from_route": "/sketches/<sketch>", "to_route": "sketches/sketch"}, {"from_route": "/sketches/<sketch>", "to_route": "sketches/sketch"},
{"from_route": "/courses/<course>", "to_route": "courses/course"}, {"from_route": "/courses/<course>", "to_route": "courses/course"},
{"from_route": "/courses/<course>/edit", "to_route": "courses/create"},
{"from_route": "/courses/<course>/<certificate>", "to_route": "courses/certificate"}, {"from_route": "/courses/<course>/<certificate>", "to_route": "courses/certificate"},
{"from_route": "/courses/<course>/learn", "to_route": "batch/learn"}, {"from_route": "/courses/<course>/learn", "to_route": "batch/learn"},
{ {

View File

@@ -93,18 +93,24 @@ def get_chapters(course):
return chapters return chapters
def get_lessons(course, chapter=None): def get_lessons(course, chapter=None, get_details=True):
"""If chapter is passed, returns lessons of only that chapter. """If chapter is passed, returns lessons of only that chapter.
Else returns lessons of all chapters of the course""" Else returns lessons of all chapters of the course"""
lessons = [] lessons = []
lesson_count = 0
if chapter: if chapter:
if get_details:
return get_lesson_details(chapter) return get_lesson_details(chapter)
else:
return frappe.db.count("Lesson Reference", {"parent": chapter.name})
for chapter in get_chapters(course): for chapter in get_chapters(course):
lesson = get_lesson_details(chapter) if get_details:
lessons += lesson lessons += get_lesson_details(chapter)
else:
lesson_count += frappe.db.count("Lesson Reference", {"parent": chapter.name})
return lessons return lessons if get_details else lesson_count
def get_lesson_details(chapter): def get_lesson_details(chapter):

View File

@@ -1,81 +1,64 @@
{% set chapters = get_chapters(course.name) %} {% set chapters = get_chapters(course.name) %}
{% if course.edit_mode or chapters | length %}
<div class="course-home-outline">
{% if course.edit_mode and course.name %}
<button class="btn btn-sm btn-secondary btn-chapter pull-right"> {{ _("New Chapter") }} </button>
{% endif %}
{% if course.name and (course.edit_mode or chapters | length) %}
<div class="course-home-headings" id="outline-heading" data-course="{{ course.name }}">
{{ _("Course Content") }}
</div>
{% endif %}
{% if course.edit_mode and course.name and not chapters | length %}
<div class="chapter-parent chapter-edit new-chapter">
<div contenteditable="true" data-placeholder="{{ _('Chapter Name') }}" class="chapter-title-main"></div>
<div class="chapter-description small my-2" contenteditable="true" data-placeholder="{{ _('Short Description') }}"></div>
<button class="btn btn-sm btn-secondary d-block btn-save-chapter" data-index="1"> {{ _('Save') }} </button>
</div>
{% endif %}
{% if chapters | length %}
<div class="chapter-dropzone">
{% for chapter in chapters %}
<div class="chapter-parent {% if course.edit_mode %} chapter-edit {% endif %}" data-chapter="{{ chapter.name }}">
<div class="chapter-title" {% if not course.edit_mode %} data-toggle="collapse" aria-expanded="false"
data-target="#{{ get_slugified_chapter_title(chapter.title) }}" {% endif %} >
{% if not course.edit_mode %}
<img class="chapter-icon" src="/assets/lms/icons/chevron-right.svg">
{% endif %}
<div class="w-100 chapter-title-main" {% if course.edit_mode %} contenteditable="true" {% endif %} >{{ chapter.title }}</div>
</div>
{% set lessons = get_lessons(course.name, chapter) %}
<div class="chapter-content {% if not course.edit_mode %} collapse navbar-collapse {% endif %} "
id="{{ get_slugified_chapter_title(chapter.title) }}">
{% if chapter.description or course.edit_mode %}
<div {% if course.edit_mode %} contenteditable="true" {% endif %} class="chapter-description
{% if not course.edit_mode %} mx-8 mb-2 {% endif %} "
data-placeholder="{{ _('Short Description') }}">{% if chapter.description %}{{ chapter.description }}{% endif %}</div>
{% endif %}
{% if course.edit_mode %}
<div class="mt-2">
<button class="btn btn-sm btn-secondary btn-save-chapter"
data-index="{{ loop.index }}"> {{ _('Save') }} </button>
<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 %}
{% set is_instructor = is_instructor(course.name) %} {% set is_instructor = is_instructor(course.name) %}
{% if course.edit_mode %} {% if chapters | length %}
<div class="course-meta mt-8 font-weight-bold"> {{ _("Lessons") }}: </div> <div class="course-home-outline">
<div class="page-title mb-8" id="outline-heading" data-course="{{ course.name }}">
{{ _("Course Content") }}
</div>
<div class="mb-2">
<span>
{{ chapters | length }} chapters
</span>
<span>
. {{ get_lessons(course.name, None, False) }} lessons
</span>
</div>
{% if chapters | length %}
<div class="common-card-style column-card p-4">
{% for chapter in chapters %}
{% set lessons = get_lessons(course.name, chapter) %}
<div class="chapter-parent" data-chapter="{{ chapter.name }}">
<div class="chapter-title" data-toggle="collapse" aria-expanded="false"
data-target="#{{ get_slugified_chapter_title(chapter.title) }}">
<img class="chapter-icon" src="/assets/lms/icons/chevron-right.svg">
<div class="chapter-title-main">
{{ chapter.title }}
</div>
<div class="small ml-auto">
{{ lessons | length }} lessons
</div>
</div>
<div class="chapter-content collapse navbar-collapse" id="{{ get_slugified_chapter_title(chapter.title) }}">
{% if chapter.description %}
<div class="chapter-description ml-2 mb-2">
{{ chapter.description }}
</div>
{% endif %} {% endif %}
<div class="lessons {% if course.edit_mode %} lesson-dropzone {% endif %}"> <div class="lessons">
{% if lessons | length %} {% if lessons | length %}
{% for lesson in lessons %} {% for lesson in lessons %}
{% set active = membership.current_lesson == lesson.name %} {% set active = membership.current_lesson == lesson.name %}
<div data-lesson="{{ lesson.name }}" class="lesson-info {% if active and not course.edit_mode %} active-lesson {% endif %}"> <div data-lesson="{{ lesson.name }}" class="lesson-info {% if active %} active-lesson {% endif %}">
{% if membership or lesson.include_in_preview or is_instructor or has_course_moderator_role() %} {% if membership or lesson.include_in_preview or is_instructor or has_course_moderator_role() %}
<a class="lesson-links" <a class="lesson-links" href="{{ get_lesson_url(course.name, lesson.number) }}{{course.query_parameter}}"
{% if is_instructor and not lesson.include_in_preview %} {% 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.') }}" title="{{ _('This lesson is not available for preview. As you are the Instructor of the course only you can see it.') }}"
{% endif %} {% 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"> <svg class="icon icon-sm mr-2">
<use class="" href="#{{ lesson.icon }}"> <use class="" href="#{{ lesson.icon }}">

View File

@@ -21,7 +21,66 @@
border: 1px solid var(--primary-color) border: 1px solid var(--primary-color)
} }
.page-title {
font-size: 1.5rem;
font-weight: 600;
color: var(--gray-900);
line-height: 160%;
letter-spacing: 0.005em;
}
.rating .icon {
background: var(--gray-200);
border-radius: var(--border-radius-md);
padding: var(--padding-xs);
}
.rating .star-click {
--star-fill: var(--orange-500);
background: var(--gray-200);
border-radius: var(--border-radius-md);
padding: var(--padding-xs);
}
.cta-parent {
display: flex;
margin-bottom: 1rem;
}
.all-cta {
flex: 1
}
.field-label {
color: var(--gray-900);
font-weight: 600;
}
.field-input {
border: 1px solid var(--gray-300);
border-radius: var(--border-radius-sm);
padding: 0.5rem;
}
.field-description {
font-size: var(--text-sm);
}
.invisible-input {
border: none;
}
.invisible-input:focus-visible {
outline: none;
}
.image-preview {
width: 280px;
height: 178px;
border-radius: var(--border-radius-sm);
border: 1px solid var(--gray-300);
margin-top: 1rem;
}
body { body {
background-color: #FFFFFF; background-color: #FFFFFF;
@@ -93,7 +152,7 @@ input[type=checkbox] {
font-weight: 600; font-weight: 600;
color: var(--gray-900); color: var(--gray-900);
width: fit-content; width: fit-content;
box-shadow: var(--shadow-sm); border: 1px solid var(--gray-300);
} }
.dark-pills { .dark-pills {
@@ -106,9 +165,7 @@ input[type=checkbox] {
} }
.common-page-style { .common-page-style {
padding: 2rem 0 5rem; padding: 1.25rem 0 5rem;
padding-top: 3rem;
background-color: var(--bg-color);
font-size: var(--text-base); font-size: var(--text-base);
} }
@@ -117,7 +174,7 @@ input[type=checkbox] {
background: #FFFFFF; background: #FFFFFF;
border-radius: var(--border-radius-md); border-radius: var(--border-radius-md);
position: relative; position: relative;
box-shadow: var(--shadow-base); border: 1px solid var(--gray-300)
} }
.course-card { .course-card {
@@ -218,9 +275,7 @@ input[type=checkbox] {
.cards-parent { .cards-parent {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
-moz-column-gap: 40px; grid-gap: 2rem;
column-gap: 40px;
row-gap: 40px;
align-items: center; align-items: center;
} }
@@ -310,20 +365,20 @@ input[type=checkbox] {
.course-card-wide { .course-card-wide {
width: 50%; width: 50%;
font-size: var(--text-base); margin-bottom: 2rem;
} }
@media (max-width: 1000px) { @media (max-width: 1000px) {
.course-card-wide { .course-card-wide {
width: 75%; width: 75%;
margin: 0 auto; margin: 0 auto 2rem;
} }
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.course-card-wide { .course-card-wide {
width: 100%; width: 100%;
margin: 0; margin: 0 0 2rem;
} }
} }
@@ -361,14 +416,13 @@ input[type=checkbox] {
} }
.wide-button { .wide-button {
padding: 0.5rem 6rem; padding: 0.3rem 4rem;
font-weight: 500;
width: 100%; width: 100%;
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.wide-button { .wide-button {
padding: 0.5rem 4rem; padding: 0.3rem 4rem;
} }
} }
@@ -407,7 +461,7 @@ input[type=checkbox] {
.course-home-page { .course-home-page {
background-color: #FFFFFF; background-color: #FFFFFF;
padding-top: 4rem; padding-top: 2.5rem;
} }
.chapter-title { .chapter-title {
@@ -417,6 +471,11 @@ input[type=checkbox] {
display: flex; display: flex;
align-items: center; align-items: center;
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
font-size: var(--text-lg);
}
.chapter-title:last-child {
padding-bottom: 0;
} }
.chapter-description { .chapter-description {
@@ -433,7 +492,6 @@ input[type=checkbox] {
} }
.reviews-parent { .reviews-parent {
padding-bottom: 5rem;
color: var(--gray-900); color: var(--gray-900);
} }
@@ -457,10 +515,6 @@ input[type=checkbox] {
border-radius: var(--border-radius-md); border-radius: var(--border-radius-md);
} }
.lessons {
margin-left: 1.5rem;
}
.member-card { .member-card {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -823,7 +877,7 @@ input[type=checkbox] {
.progress-percent { .progress-percent {
margin: 0.5rem 0; margin: 0.5rem 0;
font-size: var(--text-base); font-size: var(--text-sm);
} }
pre { pre {
@@ -1224,8 +1278,7 @@ pre {
} }
.course-head-container { .course-head-container {
color: var(--gray-900); border-bottom: 1px solid var(--gray-300);
background-color: var(--gray-50);
} }
.seperator { .seperator {
@@ -1241,7 +1294,7 @@ pre {
position: absolute; position: absolute;
top: 10%; top: 10%;
right: 7%; right: 7%;
max-width: 400px; max-width: 350px;
z-index: 4; z-index: 4;
} }
@@ -1362,20 +1415,16 @@ pre {
margin: 0 1rem; margin: 0 1rem;
} }
.avg-rating-stars { .course-card-wide .avg-rating-stars {
background: var(--gray-200); margin-top: 2rem;
border-radius: 100px;
padding: 0.5rem 0.75rem;
margin: 1.25rem 0 0.5rem;
} }
.reviews-parent .progress { .reviews-parent .progress {
width: 200px; width: 200px;
color: var(--gray-900); color: var(--gray-900);
} }
.reviews-parent .progress-bar { .reviews-parent .progress-bar {
background-color: var(--gray-600); background-color: var(--accent-color);
} }
.course-home-top-container { .course-home-top-container {
@@ -1618,6 +1667,10 @@ li {
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.chapter-parent:last-child {
margin-bottom: 0;
}
.chapter-edit .chapter-title { .chapter-edit .chapter-title {
padding: 0.5rem 0; padding: 0.5rem 0;
} }
@@ -1825,7 +1878,7 @@ li {
} }
.course-description-section { .course-description-section {
padding-bottom: 4rem; padding-bottom: 2.5rem;
} }
input::file-selector-button { input::file-selector-button {

View File

@@ -1,11 +1,9 @@
{% if not course.upcoming %} {% if not course.upcoming %}
<div class="reviews-parent"> <div class="reviews-parent">
{% set reviews = get_reviews(course.name) %} {% set reviews = get_reviews(course.name) %}
<div class="course-home-headings mb-5"> {{ _("Reviews") }} </div> <div class="page-title mb-5"> {{ _("Reviews") }} </div>
{% set avg_rating = get_average_rating(course.name) %}
{% if avg_rating %} {% if avg_rating %}
<div class="reviews-header"> <div class="reviews-header">
<div class="text-center"> <div class="text-center">
@@ -13,21 +11,21 @@
{{ frappe.utils.flt(avg_rating, frappe.get_system_settings("float_precision") or 3) }} {{ frappe.utils.flt(avg_rating, frappe.get_system_settings("float_precision") or 3) }}
</div> </div>
<div class="course-meta"> {{ reviews | length }} {{ _("ratings") }} </div>
<div class="avg-rating-stars"> <div class="avg-rating-stars">
<div class="rating"> <div class="rating">
{% for i in [1, 2, 3, 4, 5] %} {% for i in [1, 2, 3, 4, 5] %}
<svg class="icon icon-md {% if i <= frappe.utils.ceil(avg_rating) %} star-click {% endif %}" data-rating="{{ i }}"> <svg class="icon icon-lg {% if i <= frappe.utils.ceil(avg_rating) %} star-click {% endif %}" data-rating="{{ i }}">
<use href="#icon-star"></use> <use href="#icon-star"></use>
</svg> </svg>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<div class="course-meta"> <div class="course-meta"> {{ reviews | length }} {{ _("ratings") }} </div>
{{ frappe.utils.flt(avg_rating, frappe.get_system_settings("float_precision") or 3) }} {{ _("out of 5 ") }} <!--
</div>
-->
<div class="mt-5"> <div class="mt-5">
{% include "lms/templates/reviews_cta.html" %} {% include "lms/templates/reviews_cta.html" %}

View File

@@ -5,7 +5,7 @@
{% block page_content %} {% block page_content %}
<div class="common-page-style pt-0 pb-0"> <div class="common-page-style">
<div class="course-home-top-container"> <div class="course-home-top-container">
{{ CourseHomeHeader(course) }} {{ CourseHomeHeader(course) }}
<div class="course-home-page"> <div class="course-home-page">
@@ -29,7 +29,7 @@
{% macro CourseHomeHeader(course) %} {% macro CourseHomeHeader(course) %}
<div class="course-head-container"> <div class="course-head-container">
<div class="container pt-8 pb-10"> <div class="container">
<div class="course-card-wide"> <div class="course-card-wide">
{{ BreadCrumb(course) }} {{ BreadCrumb(course) }}
{{ CourseCardWide(course) }} {{ CourseCardWide(course) }}
@@ -53,72 +53,35 @@
{% macro CourseCardWide(course) %} {% macro CourseCardWide(course) %}
<div class="d-flex align-items-center mt-8"> <div class="d-flex align-items-center mt-8">
{% for tag in get_tags(course.name) %} {% for tag in get_tags(course.name) %}
<div class="course-card-pills" {% if course.edit_mode %} contenteditable="true" {% endif %}>{{ tag }} <div class="course-card-pills">
{% if course.edit_mode %} {{ tag }}
<span class="btn-delete-tag">
<svg class="icon icon-sm">
<use class="" href="#icon-close"></use>
</svg>
</span>
{% endif %}
</div> </div>
{% endfor %} {% endfor %}
{% if course.edit_mode %} </div>
<button class="btn btn-default btn-sm btn-tag"> {{ _("Add Tag") }} </button>
<div id="title" {% if course.name %} data-course="{{ course.name | urlencode }}" {% endif %} class="page-title">
{% if course.title %} {{ course.title }} {% endif %}
</div>
<div id="intro">
{% if course.short_introduction %}
{{ course.short_introduction }}
{% endif %} {% endif %}
</div> </div>
<div {% if course.edit_mode %} data-placeholder="{{ _('Title') }}" contenteditable="true" {% endif %} <div class="avg-rating-stars">
id="title" {% if course.name %} data-course="{{ course.name | urlencode }}" {% endif %} <div class="rating">
class="course-card-wide-title">{% if course.title %} {{ course.title }} {% endif %}</div> {% for i in [1, 2, 3, 4, 5] %}
<svg class="icon icon-lg {% if i <= frappe.utils.ceil(avg_rating) %} star-click {% endif %}" data-rating="{{ i }}">
<div {% if course.edit_mode %} contenteditable="true" data-placeholder="{{ _('Short Introduction') }}" <use href="#icon-star"></use>
{% endif %} id="intro" >{% if course.short_introduction %} {{ course.short_introduction }} {% endif %}</div>
{% if course.edit_mode %}
<div class="preview-video-header">
<div class="d-block mt-1" contenteditable="true" id="video-link"
data-placeholder=" {{ _('Preview Video Link') }} ">{% if course.video_link %}{{ course.video_link }}{% endif %}</div>
<div class="preview-info">
<div class="tool-tip">
<div class="tooltiptext">
<span>
{{ _('If you have a video that provides a teaser or preview of the course, you can add it here.') }}
</span>
<span>
{{ _("Follow the steps mentioned below for the same.") }}
</span>
<ul>
<li>
{{ _("Upload the video on youtube.") }}
</li>
<li>
{{ _("When you share a youtube video, it shows an option called Embed.") }}
</li>
<li>
{{ _("On clicking it, it provides an iframe. Copy the source (src) of the iframe and paste it here.") }}
</li>
</ul>
</div>
<svg class="icon icon-md">
<use href="#icon-solid-info"></use>
</svg> </svg>
</div> {% endfor %}
</div> </div>
</div> </div>
<div class="course-image-attachment {% if not course.image %} hide {% endif %} ">
<a {% if course.image %} href="{{ course.image }}" {% endif %} id="image" target="_blank">
{{ course.image }}
</a>
<button class="btn btn-sm btn-default btn-clear ml-4"> {{ _("Clear") }} </button>
</div>
<a class="btn btn-default btn-sm btn-attach mt-1 {% if course.image %} hide {% endif %}"> {{ _("Attach Image") }} </a>
{% endif %}
{% if not course.edit_mode %}
<div class="mt-8"> <div class="mt-4">
<div class="bold-heading">{{ _("Instructors") }}:</div> <div class="bold-heading">{{ _("Instructors") }}:</div>
{% for instructor in get_instructors(course.name) %} {% for instructor in get_instructors(course.name) %}
<div class="mt-1"> <div class="mt-1">
@@ -129,9 +92,8 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% endif %}
{% if membership and not course.edit_mode %} {% if membership %}
{% set progress = frappe.utils.cint(membership.progress) %} {% set progress = frappe.utils.cint(membership.progress) %}
<div class="mt-8"> <div class="mt-8">
<div class="progress-percent m-0">{{ progress }}% {{ _("Completed") }}</div> <div class="progress-percent m-0">{{ progress }}% {{ _("Completed") }}</div>
@@ -147,7 +109,6 @@
<!-- Overlay --> <!-- Overlay -->
{% macro CourseHeaderOverlay(course) %} {% macro CourseHeaderOverlay(course) %}
{% if not course.edit_mode %}
<div class="course-overlay-card"> <div class="course-overlay-card">
{% if course.video_link %} {% if course.video_link %}
@@ -156,7 +117,10 @@
{% endif %} {% endif %}
<div class="course-overlay-content"> <div class="course-overlay-content">
<div class="course-overlay-title"> {{ course.title }} </div>
<div class="cta-parent">
{{ CTASection(course, membership) }}
</div>
{{ Notes(course) }} {{ Notes(course) }}
@@ -164,7 +128,7 @@
<svg class="icon icon-md mr-1"> <svg class="icon icon-md mr-1">
<use class="" href="#icon-users"> <use class="" href="#icon-users">
</svg> </svg>
{{ get_students(course.name) | length }} {{ _("Enrolled") }} {{ format_number(get_students(course.name) | length) }} {{ _("Enrolled") }}
</div> </div>
{% if get_lessons(course.name) | length %} {% if get_lessons(course.name) | length %}
@@ -172,29 +136,25 @@
<svg class="icon icon-md mr-1"> <svg class="icon icon-md mr-1">
<use href="#icon-education"></use> <use href="#icon-education"></use>
</svg> </svg>
{{ get_lessons(course.name) | length }} {{ _("Lessons") }} {{ get_lessons(course.name, None, False) }} {{ _("Lessons") }}
</div> </div>
{% endif %} {% endif %}
{% if course.paid_certificate %} {% if course.enable_certification %}
<div class="vertically-center mb-3"> <div class="vertically-center mb-3">
<svg class="icon icon-md mr-1"> <svg class="icon icon-md mr-1">
<use href="#icon-badge"></use> <use href="#icon-badge"></use>
</svg> </svg>
<span class="certificate-price" data-price="{{ course.price_certificate }}"> {{ _("Get Certified") }}
{{ format_amount(course.price_certificate, course.currency) }}
</span>
<span class="indicator-pill green ml-3"> {{ _("Get Certified") }} </span>
</div> </div>
{% endif %} {% endif %}
{{ CTASection(course, membership) }}
</div> </div>
</div> </div>
{{ SlotModal(course) }} {{ SlotModal(course) }}
{% endif %}
{% endmacro %} {% endmacro %}
@@ -254,7 +214,7 @@
{% if course.related_courses | length %} {% if course.related_courses | length %}
<div class="related-courses"> <div class="related-courses">
<div class="container"> <div class="container">
<div class="course-home-headings"> {{ _("Other Courses") }} </div> <div class="page-title"> {{ _("Other Courses") }} </div>
<div class="carousel slide" id="carouselExampleControls" data-ride="carousel" data-interval="false"> <div class="carousel slide" id="carouselExampleControls" data-ride="carousel" data-interval="false">
<div class="carousel-inner"> <div class="carousel-inner">
{% for crs in course.related_courses %} {% for crs in course.related_courses %}
@@ -291,6 +251,8 @@
{% set lesson_index = get_lesson_index(membership.current_lesson) if membership and {% 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 %} membership.current_lesson else "1.1" if first_lesson_exists(course.name) else None %}
<div class="all-cta">
{% if is_instructor(course.name) and not course.published and course.status != "Under Review" %} {% if is_instructor(course.name) and not course.published and course.status != "Under Review" %}
<div class="btn btn-primary wide-button" id="submit-for-review" data-course="{{ course.name | urlencode }}"> <div class="btn btn-primary wide-button" id="submit-for-review" data-course="{{ course.name | urlencode }}">
{{ _("Submit for Review") }} {{ _("Submit for Review") }}
@@ -343,10 +305,19 @@
</div> </div>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div>
<div>
{% if is_instructor(course.name) or has_course_moderator_role() %} {% if is_instructor(course.name) or has_course_moderator_role() %}
<a class="btn btn-secondary wide-button mt-2" href="/courses/{{ course.name }}?edit=1"> {{ _("Edit Course") }} </a> <a class="btn btn-default btn-sm pull-right ml-2" title="Edit Course" href="/courses/{{ course.name }}?edit=1">
<svg class="icon icon-md">
<use href="#icon-edit"></use>
</svg>
</a>
{% endif %} {% endif %}
</div>
{% endmacro %} {% endmacro %}

View File

@@ -9,6 +9,7 @@ from lms.lms.utils import (
is_certified, is_certified,
is_instructor, is_instructor,
redirect_to_courses_list, redirect_to_courses_list,
get_average_rating,
) )
@@ -33,6 +34,7 @@ def get_context(context):
context.membership = None context.membership = None
else: else:
set_course_context(context, course_name) set_course_context(context, course_name)
context.avg_rating = get_average_rating(context.course.name)
def set_course_context(context, course_name): def set_course_context(context, course_name):

View File

@@ -0,0 +1,67 @@
{% extends "lms/templates/lms_base.html" %}
{% block title %}
{{ course.title if course and course.title else _("New Course") }}
{% endblock %}
{% block content %}
<main class="common-page-style">
<div class="container">
<div class="page-title"> {{ _("Course Details") }} </div>
<div class="mt-10">
<div>
<div class="course-title">
<div class="field-label">
{{ _("Title") }}
</div>
<div class="field-description">
{{ _("Something Short and Concise") }}
</div>
</div>
<div class="">
<input type="text" class="field-input">
</div>
</div>
<div>
<div class="course-title">
<div class="field-label">
{{ _("Short Introduction") }}
</div>
<div class="field-description">
{{ _("A one line breif description") }}
</div>
</div>
<div class="">
<input type="text" class="field-input">
</div>
</div>
<div>
<div class="course-title">
<div class="field-label">
{{ _("Tags") }}
</div>
<div class="field-description">
{{ _("Add suitable tags") }}
</div>
</div>
<div class="tags field-input">
<input type="text" class="invisible-input" id="tags-input">
</div>
</div>
<div>
<div class="course-title">
<div class="field-label">
{{ _("Course Image") }}
</div>
<div class="field-description">
{{ _("Add an appropriate image") }}
</div>
</div>
<div class="">
<input type="file" class="field-input" id="image">
</div>
<img>
</div>
</div>
</div>
</main>
{% endblock %}

38
lms/www/courses/create.js Normal file
View File

@@ -0,0 +1,38 @@
frappe.ready(() => {
$(".tags").click((e) => {
e.preventDefault();
$("#tags-input").focus();
});
$("#tags-input").focusout((e) => {
create_tag(e);
});
$(document).on("click", ".btn-remove", (e) => {
$(e.target).parent().parent().remove();
});
$("#image").change((e) => {
$(e.target)
.parent()
.siblings("img")
.addClass("image-preview")
.attr("src", URL.createObjectURL(e.target.files[0]));
});
});
const create_tag = (e) => {
if ($(e.target).val() == "") {
return;
}
let tag = `<button class="btn btn-secondary btn-sm mr-2 text-uppercase">
${$(e.target).val()}
<span class="btn-remove">
<svg class="icon icon-sm" style="">
<use class="" href="#icon-close"></use>
</svg>
</span>
</button>`;
$(tag).insertBefore("#tags-input");
$(e.target).val("");
};

View File

@@ -0,0 +1,5 @@
import frappe
def get_context(context):
context.no_cache = 1

View File

@@ -7,7 +7,7 @@
{% block page_content %} {% block page_content %}
<div class="common-page-style"> <div class="common-page-style pt-8">
<div class="container"> <div class="container">
{% if restriction %} {% if restriction %}
{% set profile_link = "<a href='/edit-profile'> profile </a>" %} {% set profile_link = "<a href='/edit-profile'> profile </a>" %}
@@ -42,7 +42,7 @@
</a> </a>
</div> </div>
<div class="course-home-headings"> <div class="page-title mb-6">
{{ _("All Courses") }} {{ _("All Courses") }}
</div> </div>