-
-
-
- {% if is_user_interested %}
-
{{ _("You have opted to be notified for this course. You will receive an email when the course becomes available.") }}
- {% else %}
-
{{ _("This lesson is not available for preview. Please join the course to access it.") }}
- {% endif %}
-
- {% if not is_user_interested %}
-
- {% endif %}
-
+{{ widgets.NoPreviewModal(course=course) }}
+
+{% elif course.edit_mode and course.name %}
+
+
+ {{ _("Course Content") }}
+
+
+
{% endif %}
diff --git a/lms/lms/widgets/NoPreviewModal.html b/lms/lms/widgets/NoPreviewModal.html
new file mode 100644
index 00000000..4dc95b1b
--- /dev/null
+++ b/lms/lms/widgets/NoPreviewModal.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ {% if is_user_interested %}
+
{{ _("You have opted to be notified for this course. You will receive an email when the course becomes available.") }}
+ {% else %}
+
{{ _("This lesson is not available for preview. Please join the course to access it.") }}
+ {% endif %}
+
+ {% if not is_user_interested %}
+
+ {% endif %}
+
+
+
diff --git a/lms/public/css/style.css b/lms/public/css/style.css
index 25691d06..78f4640c 100644
--- a/lms/public/css/style.css
+++ b/lms/public/css/style.css
@@ -376,16 +376,17 @@ input[type=checkbox] {
}
.chapter-title {
- cursor: pointer;
- border-radius: var(--border-radius-lg);
- padding: 0.5rem 0;
- color: var(--gray-900);
- display: flex;
- align-items: center;
+ cursor: pointer;
+ border-radius: var(--border-radius-lg);
+ padding: 0.5rem 0;
+ color: var(--gray-900);
+ display: flex;
+ align-items: center;
}
.chapter-description {
- margin: 0 2rem 0.5rem;
+ color: var(--gray-900);
+ font-size: var(--text-sm);
}
.course-content-parent .chapter-description {
@@ -1500,3 +1501,30 @@ li {
margin-top: 1rem;
}
}
+
+[contenteditable] {
+ border: 1px solid var(--gray-400);
+ padding: 0.5rem;
+ border-radius: var(--border-radius);
+}
+
+[contenteditable] {
+ outline: none;
+}
+
+[contenteditable]:empty:before{
+ content: attr(data-placeholder);
+ color: var(--gray-600);
+}
+
+.course-image-attachment {
+ margin-top: 1rem;
+ border: 1px solid var(--gray-400);
+ border-radius: var(--border-radius);
+ padding: 0.25rem 0.5rem;
+ width: fit-content;
+}
+
+.btn-delete-tag {
+ cursor: pointer;
+}
diff --git a/lms/www/courses/course.js b/lms/www/courses/course.js
index c9f217c3..92500c0f 100644
--- a/lms/www/courses/course.js
+++ b/lms/www/courses/course.js
@@ -1,5 +1,7 @@
frappe.ready(() => {
+ setup_vue_and_file_size();
+
hide_wrapped_mentor_cards();
$("#cancel-request").click((e) => {
@@ -50,116 +52,165 @@ frappe.ready(() => {
select_slot(e);
});
+ $(".btn-attach").click((e) => {
+ show_upload_modal(e);
+ });
+
+ $(".btn-clear").click((e) => {
+ clear_image(e);
+ });
+
+ $(".btn-tag").click((e) => {
+ add_tag(e);
+ });
+
+ $(".btn-save-course").click((e) => {
+ save_course(e);
+ });
+
+ $(".btn-delete-tag").click((e) => {
+ remove_tag(e);
+ });
+
});
-var hide_wrapped_mentor_cards = () => {
- var offset_top_prev;
- $(".member-parent .member-card").each(function () {
- var offset_top = $(this).offset().top;
- if (offset_top > offset_top_prev) {
- $(this).addClass('wrapped').slideUp("fast");
+const setup_vue_and_file_size = () => {
+ frappe.require("/assets/frappe/node_modules/vue/dist/vue.js", () => {
+ Vue.prototype.__ = window.__;
+ Vue.prototype.frappe = window.frappe;
+ });
+
+ frappe.provide("frappe.form.formatters");
+ frappe.form.formatters.FileSize = file_size;
+};
+
+
+const file_size = (value) => {
+ if(value > 1048576) {
+ value = flt(flt(value) / 1048576, 1) + "M";
+ } else if (value > 1024) {
+ value = flt(flt(value) / 1024, 1) + "K";
}
- if (!offset_top_prev) {
- offset_top_prev = offset_top;
+ return value;
+};
+
+
+const hide_wrapped_mentor_cards = () => {
+ let offset_top_prev;
+
+ $(".member-parent .member-card").each(function () {
+ var offset_top = $(this).offset().top;
+ if (offset_top > offset_top_prev) {
+ $(this).addClass('wrapped').slideUp("fast");
+ }
+ if (!offset_top_prev) {
+ offset_top_prev = offset_top;
+ }
+ });
+
+ if ($(".wrapped").length < 1) {
+ $(".view-all-mentors").hide();
}
+};
- });
- if ($(".wrapped").length < 1) {
- $(".view-all-mentors").hide();
- }
-}
+const cancel_mentor_request = (e) => {
+ e.preventDefault();
+ frappe.call({
+ "method": "lms.lms.doctype.lms_mentor_request.lms_mentor_request.cancel_request",
+ "args": {
+ "course": decodeURIComponent($(e.currentTarget).attr("data-course"))
+ },
+ "callback": (data) => {
+ if (data.message == "OK") {
+ $("#mentor-request").removeClass("hide");
+ $("#already-applied").addClass("hide")
+ }
+ }
+ });
+};
-var cancel_mentor_request = (e) => {
- e.preventDefault()
- frappe.call({
- "method": "lms.lms.doctype.lms_mentor_request.lms_mentor_request.cancel_request",
- "args": {
- "course": decodeURIComponent($(e.currentTarget).attr("data-course"))
- },
- "callback": (data) => {
- if (data.message == "OK") {
- $("#mentor-request").removeClass("hide");
- $("#already-applied").addClass("hide")
- }
+
+const view_all_mentors = (e) => {
+ $(".wrapped").each((i, element) => {
+ $(element).slideToggle("slow");
+ })
+ var text_element = $(".view-all-mentors .course-instructor .all-mentors-text");
+ var text = text_element.text() == "View all mentors" ? "View less" : "View all mentors";
+ text_element.text(text);
+
+ if ($(".mentor-icon").css("transform") == "none") {
+ $(".mentor-icon").css("transform", "rotate(180deg)");
+ } else {
+ $(".mentor-icon").css("transform", "");
}
- })
-}
+};
-var view_all_mentors = (e) => {
- $(".wrapped").each((i, element) => {
- $(element).slideToggle("slow");
- })
- var text_element = $(".view-all-mentors .course-instructor .all-mentors-text");
- var text = text_element.text() == "View all mentors" ? "View less" : "View all mentors";
- text_element.text(text);
- if ($(".mentor-icon").css("transform") == "none") {
- $(".mentor-icon").css("transform", "rotate(180deg)");
- } else {
- $(".mentor-icon").css("transform", "");
- }
-}
+const show_review_dialog = (e) => {
+ e.preventDefault();
+ $("#review-modal").modal("show");
+};
-var show_review_dialog = (e) => {
- e.preventDefault();
- $("#review-modal").modal("show");
-}
-var highlight_rating = (e) => {
- var rating = $(e.currentTarget).attr("data-rating");
- $(".icon-rating").removeClass("star-click");
- $(".icon-rating").each((i, elem) => {
- if (i <= rating-1) {
- $(elem).addClass("star-click");
- }
- })
-}
+const highlight_rating = (e) => {
+ var rating = $(e.currentTarget).attr("data-rating");
+ $(".icon-rating").removeClass("star-click");
+ $(".icon-rating").each((i, elem) => {
+ if (i <= rating-1) {
+ $(elem).addClass("star-click");
+ }
+ });
+};
+
var submit_review = (e) => {
- e.preventDefault();
- var rating = $(".rating-field").children(".star-click").length;
- var review = $(".review-field").val();
- if (!rating) {
- $(".error-field").text("Please provide a rating.");
- return;
- }
- frappe.call({
- method: "lms.lms.doctype.lms_course_review.lms_course_review.submit_review",
- args: {
- "rating": rating,
- "review": review,
- "course": decodeURIComponent($(e.currentTarget).attr("data-course"))
- },
- callback: (data) => {
- if (data.message == "OK") {
- $(".review-modal").modal("hide");
- window.location.reload();
- }
+ e.preventDefault();
+ var rating = $(".rating-field").children(".star-click").length;
+ var review = $(".review-field").val();
+ if (!rating) {
+ $(".error-field").text("Please provide a rating.");
+ return;
}
- })
+ frappe.call({
+ method: "lms.lms.doctype.lms_course_review.lms_course_review.submit_review",
+ args: {
+ "rating": rating,
+ "review": review,
+ "course": decodeURIComponent($(e.currentTarget).attr("data-course"))
+ },
+ callback: (data) => {
+ if (data.message == "OK") {
+ $(".review-modal").modal("hide");
+ window.location.reload();
+ }
+ }
+ });
};
+
const create_certificate = (e) => {
- e.preventDefault();
- course = $(e.currentTarget).attr("data-course");
- frappe.call({
- method: "lms.lms.doctype.lms_certificate.lms_certificate.create_certificate",
- args: {
- "course": course
- },
- callback: (data) => {
- window.location.href = `/courses/${course}/${data.message.name}`;
- }
- })
+ e.preventDefault();
+ course = $(e.currentTarget).attr("data-course");
+ frappe.call({
+ method: "lms.lms.doctype.lms_certificate.lms_certificate.create_certificate",
+ args: {
+ "course": course
+ },
+ callback: (data) => {
+ window.location.href = `/courses/${course}/${data.message.name}`;
+ }
+ });
};
+
const element_not_in_viewport = (el) => {
- const rect = el.getBoundingClientRect();
- return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight;
+ const rect = el.getBoundingClientRect();
+ return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight;
};
+
const submit_for_review = (e) => {
let course = $(e.currentTarget).data("course");
frappe.call({
@@ -184,12 +235,12 @@ const submit_for_review = (e) => {
});
};
+
const apply_cetificate = (e) => {
$("#slot-modal").modal("show");
-
-
};
+
const submit_slot = (e) => {
e.preventDefault();
const slot = window.selected_slot;
@@ -215,6 +266,7 @@ const submit_slot = (e) => {
});
};
+
const display_slots = (e) => {
frappe.call({
method: "lms.lms.doctype.course_evaluator.course_evaluator.get_schedule",
@@ -249,18 +301,73 @@ const display_slots = (e) => {
});
};
+
const select_slot = (e) => {
$(".slot").removeClass("btn-outline-primary");
$(e.currentTarget).addClass("btn-outline-primary");
window.selected_slot = $(e.currentTarget);
};
+
const format_time = (time) => {
let date = moment(new Date()).format("ddd MMM DD YYYY");
return moment(`${date} ${time}`).format("HH:mm a");
};
+
const close_slot_modal = (e) => {
$("#slot-date").val("");
$(".slot-label").addClass("hide");
-}
+};
+
+
+const show_upload_modal = () => {
+ new frappe.ui.FileUploader({
+ folder: "Home/Attachments",
+ restrictions: {
+ allowed_file_types: ['image/*']
+ },
+ on_success: (file_doc) => {
+ $(".course-image-attachment").removeClass("hide");
+ $(".course-image-attachment a").attr("href", file_doc.file_url).text(file_doc.file_url);
+ $(".btn-attach").addClass("hide");
+ },
+ });
+};
+
+
+const clear_image = () => {
+ $(".course-image-attachment").addClass("hide");
+ $(".course-image-attachment a").removeAttr("href");
+ $(".btn-attach").removeClass("hide");
+};
+
+
+const add_tag = (e) => {
+ $(`
`).insertBefore(`.btn-tag`);
+};
+
+
+const save_course = (e) => {
+ let course = $("#title").data("course");
+ frappe.call({
+ method: "lms.lms.doctype.lms_course.lms_course.save_course",
+ args: {
+ "tags": $('.course-card-pills').map((i, el) => $(el).text().trim()).get().join(", "),
+ "title": $("#title").text(),
+ "short_introduction": $("#intro").text(),
+ "video_link": $("#video-link").text(),
+ "image": $("#image").attr("href"),
+ "description": $("#description").text(),
+ "course": course ? course : ""
+ },
+ callback: (data) => {
+ window.location.href = `/courses/${data.message}?edit=1`;
+ }
+ });
+};
+
+const remove_tag = (e) => {
+ $(e.currentTarget).closest(".course-card-pills").remove();
+};
diff --git a/lms/www/courses/course.py b/lms/www/courses/course.py
index 097a38d1..81f468be 100644
--- a/lms/www/courses/course.py
+++ b/lms/www/courses/course.py
@@ -1,17 +1,25 @@
import frappe
from lms.lms.doctype.lms_settings.lms_settings import check_profile_restriction
from lms.lms.utils import get_membership, is_instructor, is_certified, get_evaluation_details
-from frappe.utils import add_months, getdate
def get_context(context):
context.no_cache = 1
try:
+ print(frappe.form_dict)
course_name = frappe.form_dict["course"]
except KeyError:
frappe.local.flags.redirect_location = "/courses"
raise frappe.Redirect
+ if course_name == "new-course":
+ context.course = frappe._dict()
+ context.course.edit_mode = True
+ context.membership = None
+ else:
+ set_course_context(context, course_name)
+
+def set_course_context(context, course_name):
course = frappe.db.get_value("LMS Course", course_name,
["name", "title", "image", "short_introduction", "description", "published", "upcoming", "disable_self_learning",
"status", "video_link", "enable_certification", "grant_certificate_after", "paid_certificate",
@@ -43,6 +51,9 @@ def get_context(context):
if context.course.upcoming:
context.is_user_interested = get_user_interest(context.course.name)
+ if frappe.form_dict.get("edit"):
+ context.course.edit_mode = True
+
context.metatags = {
"title": course.title,
"image": course.image,
diff --git a/lms/www/dashboard/index.html b/lms/www/dashboard/index.html
index 9f46f375..bd37483e 100644
--- a/lms/www/dashboard/index.html
+++ b/lms/www/dashboard/index.html
@@ -7,7 +7,7 @@