refactor: renamed app to school

This commit is contained in:
Jannat Patel
2021-10-11 20:31:27 +05:30
parent 13022e0bcc
commit d07dbcc50a
466 changed files with 2497 additions and 146 deletions

View File

@@ -0,0 +1,13 @@
<div class="breadcrumb">
{% if course %}
<a class="dark-links" href="/courses">All Courses</a>
<img class="ml-1 mr-1" src="/assets/school/icons/chevron-right.svg">
{% if lesson %}
<a class="dark-links" href="/courses/{{ course.name }}">{{ course.title }}</a>
<img class="ml-1 mr-1" src="/assets/school/icons/chevron-right.svg">
<span class="muted-text"> {{ lesson.title }}</span>
{% else %}
<span class="muted-text">{{ course.title }}</span>
{% endif %}
{% endif %}
</div>

View File

@@ -0,0 +1,123 @@
<div>
<div class="chapter-title small-title" data-target="#{{ course.get_slugified_chapter_title(chapter.title) }}"
data-toggle="collapse" aria-expanded="false">
<img class="chapter-icon" src="/assets/school/icons/chevron-right.svg">
{{ index }}. {{ chapter.title }}
</div>
<div class="chapter-content collapse navbar-collapse" id="{{ course.get_slugified_chapter_title(chapter.title) }}">
{% if chapter.description %}
<div class="chapter-description muted-text">
{{ chapter.description }}
</div>
{% endif %}
{% set is_instructor = frappe.session.user == course.instructor %}
<div class="lessons">
{% for lesson in course.get_lessons(chapter) %}
<div class="lesson-info {% if membership.current_lesson == lesson.name %} active-lesson {% endif %}">
{% if membership or lesson.include_in_preview %}
<a class="lesson-links" href="{{ course.get_learn_url(lesson.number) }}{{course.query_parameter}}"
data-course="{{ course.name }}">
{{ lesson.title }}
{% if membership %}
<img class="ml-1 lesson-progress-tick {{ course.get_progress(lesson.name) != 'Complete' and 'hide' }}"
src="/assets/school/icons/check.svg">
{% endif %}
</a>
{% elif is_instructor and not lesson.include_in_preview %}
<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."
href="{{ course.get_learn_url(lesson.number) }}{{course.query_parameter}}"
data-course="{{ course.name }}">
{{ lesson.title }}
<img class="ml-2" src="/assets/school/icons/lock.svg">
</a>
{% else %}
<div class="no-preview" title="This lesson is not available for preview">
<div class="lesson-links">
{{ lesson.title }}
<img class="ml-2" src="/assets/school/icons/lock.svg">
</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
{% if index != course.get_chapters() | length %}
<div class="card-divider"></div>
{% endif %}
<script>
frappe.ready(() => {
expand_the_active_chapter();
$(".chapter-title").unbind().click((e) => {
rotate_chapter_icon(e);
});
});
var expand_the_first_chapter = () => {
var elements = $(".course-outline .collapse");
elements.each((i, element) => {
if (i < 1) {
show_section(element);
return false;
}
});
}
var expand_the_active_chapter = () => {
/* Find anchor matching the URL for course details page */
var selector = $(`a[href="${decodeURIComponent(window.location.pathname)}"]`).parent();
if (!selector.length) {
selector = $(`a[href^="${decodeURIComponent(window.location.pathname)}"]`).parent();
}
if (selector.length && $(".course-details-page").length) {
$(".lesson-info").removeClass("active-lesson")
selector.addClass("active-lesson");
show_section(selector.parent().parent());
}
/* For course home page */
else if ($(".active-lesson").length) {
selector = $(".active-lesson")
show_section(selector.parent().parent());
}
/* If no active chapter then exapand the first chapter */
else {
expand_the_first_chapter();
}
}
var show_section = (element) => {
$(element).addClass("show");
$(element).siblings(".chapter-title").children(".chapter-icon").css("transform", "rotate(90deg)");
}
var rotate_chapter_icon = (e) => {
var icon = $(e.currentTarget).children(".chapter-icon");
if (icon.css("transform") == "none") {
icon.css("transform", "rotate(90deg)");
} else {
icon.css("transform", "none");
}
}
</script>

View File

@@ -0,0 +1,147 @@
{% set membership = course.get_membership(frappe.session.user) %}
{% set progress = course.get_course_progress() %}
<div class="common-card-style course-card">
<div class="course-image {% if not course.image %}default-image{% endif %}"
{% if course.image %} style="background-image: url( {{ course.image }} );" {% endif %}>
<div class="course-tags">
{% for tag in course.get_tags() %}
<div class="course-card-pills">{{ tag }}</div>
{% endfor %}
{% if membership and not read_only %}
{% if progress < 100 %}
 <div class="course-card-pills dark-pills ml-auto">{{ frappe.utils.rounded(progress) }}% Completed</div>
{% else %}
<div class="course-card-pills dark-pills ml-auto"> <img src="/assets/school/icons/check.svg"> Completed </div>
{% endif %}
{% endif %}
</div>
{% if not course.image %}
<div class="default-image-text">{{ course.title[0] }}</div>
{% endif %}
</div>
<div class="course-card-content">
<div class="course-card-meta muted-text">
{% if course.get_chapters() | length %}
<span>
{{ course.get_chapters() | length }} Chapters
</span>
{% endif %}
{% if course.get_chapters() | length and course.get_upcoming_batches() | length %}
<span class="font-weight-bold ml-3 mr-3"> . </span>
{% endif %}
{% if course.get_upcoming_batches() | length %}
<span class="">
{{ course.get_upcoming_batches() | length }} Open Batches
</span>
{% endif %}
</div>
<div class="course-card-title">{{ course.title }}</div>
<div {% if not read_only %} class="mb-4" {% endif %}>
<span class="zindex">
{{ widgets.Avatar(member=course.get_instructor(), avatar_class="avatar-small") }}
<a class="button-links" href="{{ get_profile_url(course.get_instructor().username) }}">
<span class="course-instructor">
{{ course.get_instructor().full_name }}
</span>
</a>
</span>
<span class="course-student-count">
{% if course.get_students() | length %}
<span class="mr-4">
<img class="icon-background" src="/assets/school/icons/user.svg" />
{{ course.get_students() | length }}
</span> {% endif %}
{% set avg_rating = course.get_average_rating() %}
{% if avg_rating %}
<span class="">
<img class="icon-background" src="/assets/school/icons/rating.svg" />
{{ avg_rating }}
</span>
{% endif %}
</span>
</div>
{% if read_only %}
<a class="stretched-link" href="/courses/{{ course.name }}"></a>
{% else %}
{% set lesson_index = course.get_lesson_index(membership.current_lesson) if membership and
membership.current_lesson else '1.1' %}
{% set query_parameter = "?batch=" + membership.batch if membership and
membership.batch else "" %}
{% set certificate = course.is_certified() %}
{% if certificate %}
<div class="view-course-link is-default">
Get Certificate <img class="ml-3" src="/assets/school/icons/black-arrow.svg" />
</div>
<a class="stretched-link" href="/courses/{{ course.name }}/{{ certificate }}"></a>
{% elif course.enable_certification and progress == 100 %}
<div class="view-course-link is-default" id="certification" data-course="{{ course.name }}">
Get Certificate <img class="ml-3" src="/assets/school/icons/black-arrow.svg" />
</div>
{% elif progress == 100 %}
<div class="view-course-link is-default">
Course Completed <img class="ml-3" src="/assets/school/icons/black-arrow.svg" />
</div>
<a class="stretched-link" href="/courses/{{ course.name }}"></a>
{% elif course.upcoming %}
<div class="view-course-link is-secondary border">
Upcoming Course <img class="ml-3" src="/assets/school/icons/black-arrow.svg" />
</div>
<a class="stretched-link" href="/courses/{{ course.name }}"></a>
{% elif membership %}
<div class="view-course-link is-primary">
Continue Course <img class="ml-3" src="/assets/school/icons/white-arrow.svg" />
</div>
<a class="stretched-link" href="{{ course.get_learn_url(lesson_index) }}{{ query_parameter }}"></a>
{% else %}
<div class="view-course-link is-default">
View Course <img class="ml-3" src="/assets/school/icons/black-arrow.svg" />
</div>
<a class="stretched-link" href="/courses/{{ course.name }}"></a>
{% endif %}
{% endif %}
</div>
</div>
<script>
frappe.ready(() => {
trim_course_titles();
$("#certification").unbind().click((e) => {
create_certificate(e);
});
})
var trim_course_titles = () => {
$(".course-card-title").each((i, element) => {
var title = $(element).text();
var length = $(window).width() <= 375 ? 60 : 65;
var suffix = title.length > length ? "..." : "";
$(element).text(title.substring(0, length) + suffix);
});
}
var create_certificate = (e) => {
e.preventDefault();
course = $(e.currentTarget).attr("data-course");
frappe.call({
method: "school.lms.doctype.lms_certification.lms_certification.create_certificate",
args: {
"course": course
},
callback: (data) => {
window.location.href = `/courses/${course}/${data.message}`;
}
})
}
</script>

View File

@@ -0,0 +1,12 @@
{% if course.get_chapters() | length %}
<div class="">
<div class="course-home-headings">
Course Outline
</div>
<div class="common-card-style course-outline">
{% for chapter in course.get_chapters() %}
{{ widgets.ChapterTeaser(index=loop.index, chapter=chapter, course=course, batch=batch, membership=membership) }}
{% endfor %}
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,19 @@
<div class="course-teaser">
<div class="course-body">
<h3 class="course-title"><a href="/courses/{{ course.name }}">{{ course.title }}</a></h3>
<div class="course-intro">
{{ course.short_introduction or "" }}
</div>
</div>
<div class="course-footer">
{% set batch = course.get_student_batch(frappe.session.user) %}
{% if batch %}
<a class="btn btn-secondary pull-right" href="/courses/{{course.name}}/{{batch.name}}/learn">Resume Course</a>
{% endif %}
<div class="course-author">
{% with author = course.get_instructor() %}
{{ widgets.Avatar(member=author, avatar_class="avatar-medium") }} <a href="{{get_profile_url(author.username)}}">{{ author.full_name }}</a>
{% endwith %}
</div>
</div>
</div>

View File

@@ -0,0 +1,18 @@
{% from "www/macros/livecode.html" import LiveCodeEditorJS, LiveCodeEditor with context %}
<div class="exercise">
<h2>Exercise {{exercise.index_label}}: {{ exercise.title }}</h2>
<div class="exercise-description">{{frappe.utils.md_to_html(exercise.description)}}</div>
{% if exercise.image %}
<div class="exercise-image">{{exercise.image}}</div>
{% endif %}
{% set submission = exercise.get_user_submission() %}
{{ LiveCodeEditor(exercise.name,
code=submission.solution if submission else exercise.code,
reset_code=exercise.code,
is_exercise=True,
last_submitted=submission and submission.creation) }}
</div>

View File

@@ -0,0 +1,14 @@
{#
Widget to demonostrate how to write a widget.
A wiget is a reusable template, that can be used in
other templates.
To this widget can be called as:
{{ widgets.HelloWorld(name="World") }}
#}
<div class="hello">
Hello, <em>{{ name }}</em>!
</div>

View File

@@ -0,0 +1,15 @@
<div class="common-card-style member-card {{dimension_class}} ">
{% set avatar_class = "avatar-large" if not dimension_class else "avatar-large"%}
{{ widgets.Avatar(member=member, avatar_class=avatar_class) }}
<div class="small-title member-card-title">
{{ member.full_name }}
</div>
{% set course_count = member.get_authored_courses() | length %}
{% if show_course_count and course_count > 0 %}
{% set suffix = "Courses" if course_count > 1 else "Course" %}
<div class="small-title">
Created {{ course_count }} {{ suffix }}
</div>
{% endif %}
<a class="stretched-link" href="{{ get_profile_url(member.username) }}"></a>
</div>

View File

@@ -0,0 +1,64 @@
<form id="invite-request-form">
<div class="row">
<div class="col-md">
<input class="form-control w-100 mr-5 mb-5 mt-2" id="invite_email" type="email" placeholder="Email Address">
</div>
<div class="col-md">
<a type="submit" id="submit-invite-request" class="btn btn-primary btn-lg" role="button">Request
Invite</a>
</div>
</div>
</form>
<script>
frappe.ready(() => {
$("#submit-invite-request").click(function () {
var invite_email = $("#invite_email").val()
frappe.call({
method: "school.lms.doctype.invite_request.invite_request.create_invite_request",
args: {
invite_email: invite_email
},
callback: (data) => {
if (data.message == "invalid email") {
$(".email-validation") && $(".email-validation").remove();
if (invite_email) {
var message = `<div>
<small class="email-validation" style="color: red;">${invite_email} is not a valid email address.</small>
</div>`;
}
else {
var message = `<div>
<small class="email-validation" style="color: red;">Please enter an email address.</small>
</div>`;
}
$("#invite-request-form").append(message);
}
else {
$("#invite-request-form").hide();
if (data.message == "OK") {
var message = `<div>
<p class="lead alert alert-secondary">Thanks for your interest in Mon School. We have recorded your interest and we will get back to you shortly.</p>
</div>`;
}
else if (data.message == "invite") {
var message = `<div>
<p class="lead alert alert-secondary">Email ${invite_email} has already been used to request an invitation.</p>
</div>`;
}
else if (data.message == "user") {
var message = `<div>
<p class="lead alert alert-secondary">Looks like there is already an account with email ${invite_email}. Would you like to <a href="/login">login</a>?</p>
</div>`;
}
$(".jumbotron").append(message);
}
}
})
})
})
</script>

View File

@@ -0,0 +1,107 @@
{% if not course.upcoming %}
<div class="reviews-parent">
{% set reviews = course.get_reviews() %}
<div class="mb-5">
<span class="course-home-headings">Reviews</span>
{% if course.is_eligible_to_review(membership) and reviews | length %}
<span class="review-link button is-secondary pull-right">
Write a review
</span>
{% endif %}
</div>
{% if reviews | length %}
<div class="reviews-section">
{% for review in reviews %}
<div class="review-card">
<div class="common-card-style review-content small-title"> {{ review.review }} </div>
<div class="review-card-footer">
<div>
{{ widgets.Avatar(member=review.owner_details, avatar_class="avatar-medium") }}
<a class="button-links" href="{{get_profile_url(review.owner_details.username) }}">
<span class="course-instructor">
{{ review.owner_details.full_name }}
</span>
</a>
</div>
<div class="rating">
{% for i in [1, 2, 3, 4, 5] %}
<svg class="icon icon-md {% if i <= review.rating %} star-click {% endif %}" data-rating="{{ i }}">
<use href="#icon-star"></use>
</svg>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="common-card-style thread-card">
<div class="w-25 text-center" style="margin: 0 auto;">
<span class="font-weight-bold"> No Reviews </span>
<div class="small">
There are no reviews for this course.
</div>
{% if course.is_eligible_to_review(membership) %}
<span class="review-link button is-secondary ml-auto mr-auto mt-3">
Write a review
</span>
{% endif %}
</div>
</div>
{% endif %}
</div>
<div class="modal fade review-modal" id="review-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="font-weight-bold">Write a Review</div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="review-form" id="review-form">
<div class="form-group">
<div class="clearfix">
<label class="control-label reqd" style="padding-right: 0px;">Rating</label>
</div>
<div class="control-input-wrapper">
<div class="control-input">
<div class="rating rating-field" id="rating">
{% for i in [1, 2, 3, 4, 5] %}
<svg class="icon icon-md icon-rating" data-rating="{{ i }}">
<use href="#icon-star"></use>
</svg>
{% endfor %}
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="clearfix">
<label class="control-label reqd" style="padding-right: 0px;">Review</label>
</div>
<div class="control-input-wrapper">
<div class="control-input">
<textarea type="text" autocomplete="off" class="input-with-feedback form-control review-field"
data-fieldtype="Text" data-fieldname="feedback_comments" placeholder="" style="height: 300px;"
spellcheck="false"></textarea>
</div>
</div>
</div>
<p class="error-field muted-text"></p>
</form>
</div>
<div class="modal-footer">
<div class="button submit-review is-primary" data-course="{{ course.name | urlencode}}" id="submit-review">
Submit</div>
</div>
</div>
</div>
</div>
{% endif %}