fix: pre commit issues
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
batch_name = frappe.form_dict["batch"]
|
||||
context.batch = frappe.get_doc("LMS Batch", batch_name)
|
||||
context.already_a_member = context.batch.is_member(frappe.session.user)
|
||||
context.batch.course_title = frappe.db.get_value("LMS Course", context.batch.course, "title")
|
||||
context.no_cache = 1
|
||||
batch_name = frappe.form_dict["batch"]
|
||||
context.batch = frappe.get_doc("LMS Batch", batch_name)
|
||||
context.already_a_member = context.batch.is_member(frappe.session.user)
|
||||
context.batch.course_title = frappe.db.get_value(
|
||||
"LMS Course", context.batch.course, "title"
|
||||
)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
frappe.ready(() => {
|
||||
|
||||
this.marked_as_complete = false;
|
||||
this.quiz_submitted = false;
|
||||
this.file_type;
|
||||
@@ -19,7 +18,11 @@ frappe.ready(() => {
|
||||
|
||||
$(window).scroll(() => {
|
||||
let self = this;
|
||||
if (!$("#status-indicator").length && !self.marked_as_complete && $(".title").hasClass("is-member")) {
|
||||
if (
|
||||
!$("#status-indicator").length &&
|
||||
!self.marked_as_complete &&
|
||||
$(".title").hasClass("is-member")
|
||||
) {
|
||||
self.marked_as_complete = true;
|
||||
mark_progress();
|
||||
}
|
||||
@@ -94,32 +97,31 @@ frappe.ready(() => {
|
||||
}
|
||||
|
||||
$("#file-type").change((e) => {
|
||||
$("#file-type option:selected" ).each(function() {
|
||||
$("#file-type option:selected").each(function () {
|
||||
self.file_type = $(this).val();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
const save_current_lesson = () => {
|
||||
if ($(".title").hasClass("is-member")) {
|
||||
frappe.call("lms.lms.api.save_current_lesson", {
|
||||
course_name: $(".title").attr("data-course"),
|
||||
lesson_name: $(".title").attr("data-lesson")
|
||||
lesson_name: $(".title").attr("data-lesson"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const enable_check = (e) => {
|
||||
if ($(".option:checked").length) {
|
||||
$("#check").removeAttr("disabled");
|
||||
$(".custom-checkbox").removeClass("active-option");
|
||||
$(".option:checked").closest(".custom-checkbox").addClass("active-option");
|
||||
$(".option:checked")
|
||||
.closest(".custom-checkbox")
|
||||
.addClass("active-option");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const mark_active_question = (e = undefined) => {
|
||||
$(".timer").addClass("hide");
|
||||
calculate_and_display_time(100);
|
||||
@@ -129,7 +131,9 @@ const mark_active_question = (e = undefined) => {
|
||||
let next_index = parseInt(current_index) + 1;
|
||||
|
||||
$(".question").addClass("hide").removeClass("active-question");
|
||||
$(`.question[data-qt-index='${next_index}']`).removeClass("hide").addClass("active-question");
|
||||
$(`.question[data-qt-index='${next_index}']`)
|
||||
.removeClass("hide")
|
||||
.addClass("active-question");
|
||||
$(".current-question").text(`${next_index}`);
|
||||
$("#check").removeClass("hide").attr("disabled", true);
|
||||
$("#next").addClass("hide");
|
||||
@@ -137,36 +141,37 @@ const mark_active_question = (e = undefined) => {
|
||||
initialize_timer();
|
||||
};
|
||||
|
||||
|
||||
const mark_progress = () => {
|
||||
let status = "Complete"
|
||||
let status = "Complete";
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.course_lesson.course_lesson.save_progress",
|
||||
args: {
|
||||
lesson: $(".title").attr("data-lesson"),
|
||||
course: $(".title").attr("data-course"),
|
||||
status: status
|
||||
status: status,
|
||||
},
|
||||
callback: (data) => {
|
||||
change_progress_indicators();
|
||||
show_certificate_if_course_completed(data);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const change_progress_indicators = () => {
|
||||
$(".active-lesson .lesson-progress-tick").removeClass("hide");
|
||||
};
|
||||
|
||||
|
||||
const show_certificate_if_course_completed = (data) => {
|
||||
if (data.message == 100 && !$(".next").length && $("#certification").hasClass("hide")) {
|
||||
if (
|
||||
data.message == 100 &&
|
||||
!$(".next").length &&
|
||||
$("#certification").hasClass("hide")
|
||||
) {
|
||||
$("#certification").removeClass("hide");
|
||||
}
|
||||
};
|
||||
|
||||
const quiz_summary = (e=undefined) => {
|
||||
const quiz_summary = (e = undefined) => {
|
||||
e && e.preventDefault();
|
||||
let quiz_name = $("#quiz-title").data("name");
|
||||
let total_questions = $(".question").length;
|
||||
@@ -175,31 +180,35 @@ const quiz_summary = (e=undefined) => {
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_quiz.lms_quiz.quiz_summary",
|
||||
args: {
|
||||
"quiz": quiz_name,
|
||||
"results": localStorage.getItem(quiz_name)
|
||||
quiz: quiz_name,
|
||||
results: localStorage.getItem(quiz_name),
|
||||
},
|
||||
callback: (data) => {
|
||||
let message = data.message == total_questions ? __("Excellent Work 👏") : __("Better luck next time")
|
||||
let message =
|
||||
data.message == total_questions
|
||||
? __("Excellent Work 👏")
|
||||
: __("Better luck next time");
|
||||
$(".question").addClass("hide");
|
||||
$("#summary").addClass("hide");
|
||||
$("#quiz-form").parent().prepend(
|
||||
`<div class="text-center summary">
|
||||
$("#quiz-form")
|
||||
.parent()
|
||||
.prepend(
|
||||
`<div class="text-center summary">
|
||||
<h2> ${message} </h2>
|
||||
<div class="font-weight-bold"> ${data.message}/${total_questions} </div>
|
||||
</div>`);
|
||||
</div>`
|
||||
);
|
||||
$("#try-again").removeClass("hide");
|
||||
self.quiz_submitted = true;
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const try_quiz_again = (e) => {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
|
||||
const check_answer = (e=undefined) => {
|
||||
const check_answer = (e = undefined) => {
|
||||
e && e.preventDefault();
|
||||
clearInterval(self.timer);
|
||||
$(".timer").addClass("hide");
|
||||
@@ -212,19 +221,16 @@ const check_answer = (e=undefined) => {
|
||||
if (current_index == total_questions) {
|
||||
if ($(".eligible-for-submission").length) {
|
||||
$("#summary").removeClass("hide");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$("#submission-message").removeClass("hide");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$("#next").removeClass("hide");
|
||||
}
|
||||
let [answer, is_correct] = parse_options();
|
||||
add_to_local_storage(current_index, answer, is_correct);
|
||||
};
|
||||
|
||||
|
||||
const parse_options = () => {
|
||||
let answer = [];
|
||||
let is_correct = [];
|
||||
@@ -234,16 +240,16 @@ const parse_options = () => {
|
||||
answer.push(decodeURIComponent($(element).val()));
|
||||
correct && is_correct.push(1);
|
||||
correct ? add_icon(element, "check") : add_icon(element, "wrong");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
correct && is_correct.push(0);
|
||||
correct ? add_icon(element, "minus-circle-green") : add_icon(element, "minus-circle");
|
||||
correct
|
||||
? add_icon(element, "minus-circle-green")
|
||||
: add_icon(element, "minus-circle");
|
||||
}
|
||||
});
|
||||
return [answer, is_correct];
|
||||
};
|
||||
|
||||
|
||||
const add_icon = (element, icon) => {
|
||||
$(element).closest(".custom-checkbox").removeClass("active-option");
|
||||
let label = $(element).siblings(".option-text").text();
|
||||
@@ -256,50 +262,46 @@ const add_icon = (element, icon) => {
|
||||
//$(element).parent().empty().html(`<div class="option-text"><img class="mr-3" src="/assets/lms/icons/${icon}.svg"> ${label}</div>`);
|
||||
};
|
||||
|
||||
|
||||
const add_to_local_storage = (current_index, answer, is_correct) => {
|
||||
let quiz_name = $("#quiz-title").data("name")
|
||||
let quiz_name = $("#quiz-title").data("name");
|
||||
let quiz_stored = JSON.parse(localStorage.getItem(quiz_name));
|
||||
|
||||
let quiz_obj = {
|
||||
"question_index": current_index,
|
||||
"answer": answer.join(),
|
||||
"is_correct": is_correct
|
||||
}
|
||||
question_index: current_index,
|
||||
answer: answer.join(),
|
||||
is_correct: is_correct,
|
||||
};
|
||||
|
||||
quiz_stored ? quiz_stored.push(quiz_obj) : quiz_stored = [quiz_obj]
|
||||
localStorage.setItem(quiz_name, JSON.stringify(quiz_stored))
|
||||
quiz_stored ? quiz_stored.push(quiz_obj) : (quiz_stored = [quiz_obj]);
|
||||
localStorage.setItem(quiz_name, JSON.stringify(quiz_stored));
|
||||
};
|
||||
|
||||
|
||||
const create_certificate = (e) => {
|
||||
e.preventDefault();
|
||||
course = $(".title").attr("data-course");
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_certificate.lms_certificate.create_certificate",
|
||||
args: {
|
||||
"course": course
|
||||
course: course,
|
||||
},
|
||||
callback: (data) => {
|
||||
window.location.href = `/courses/${course}/${data.message.name}`;
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const attach_work = (e) => {
|
||||
const target = $(e.currentTarget);
|
||||
let files = target.siblings(".attach-file").prop("files")
|
||||
let files = target.siblings(".attach-file").prop("files");
|
||||
if (files && files.length) {
|
||||
files = add_files(files)
|
||||
return_as_dataurl(files)
|
||||
files = add_files(files);
|
||||
return_as_dataurl(files);
|
||||
files.map((file) => {
|
||||
upload_file(file, target);
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const upload_file = (file, target) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let xhr = new XMLHttpRequest();
|
||||
@@ -307,34 +309,39 @@ const upload_file = (file, target) => {
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState == XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
let response = JSON.parse(xhr.responseText)
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
create_lesson_work(response.message, target);
|
||||
} else if (xhr.status === 403) {
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
frappe.msgprint(`Not permitted. ${response._error_message || ''}`);
|
||||
|
||||
frappe.msgprint(
|
||||
`Not permitted. ${response._error_message || ""}`
|
||||
);
|
||||
} else if (xhr.status === 413) {
|
||||
frappe.msgprint('Size exceeds the maximum allowed file size.');
|
||||
|
||||
frappe.msgprint(
|
||||
"Size exceeds the maximum allowed file size."
|
||||
);
|
||||
} else {
|
||||
frappe.msgprint(xhr.status === 0 ? 'XMLHttpRequest Error' : `${xhr.status} : ${xhr.statusText}`);
|
||||
frappe.msgprint(
|
||||
xhr.status === 0
|
||||
? "XMLHttpRequest Error"
|
||||
: `${xhr.status} : ${xhr.statusText}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
xhr.open('POST', '/api/method/upload_file', true);
|
||||
xhr.setRequestHeader('Accept', 'application/json');
|
||||
xhr.setRequestHeader('X-Frappe-CSRF-Token', frappe.csrf_token);
|
||||
};
|
||||
xhr.open("POST", "/api/method/upload_file", true);
|
||||
xhr.setRequestHeader("Accept", "application/json");
|
||||
xhr.setRequestHeader("X-Frappe-CSRF-Token", frappe.csrf_token);
|
||||
|
||||
let form_data = new FormData();
|
||||
if (file.file_obj) {
|
||||
form_data.append('file', file.file_obj, file.name);
|
||||
form_data.append("file", file.file_obj, file.name);
|
||||
}
|
||||
|
||||
xhr.send(form_data);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const create_lesson_work = (file, target) => {
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lesson_assignment.lesson_assignment.upload_assignment",
|
||||
@@ -345,17 +352,19 @@ const create_lesson_work = (file, target) => {
|
||||
callback: (data) => {
|
||||
target.siblings(".attach-file").addClass("hide");
|
||||
target.siblings(".preview-work").removeClass("hide");
|
||||
target.siblings(".preview-work").find("a").attr("href", file.file_url).text(file.file_name)
|
||||
target
|
||||
.siblings(".preview-work")
|
||||
.find("a")
|
||||
.attr("href", file.file_url)
|
||||
.text(file.file_name);
|
||||
target.addClass("hide");
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const return_as_dataurl = (files) => {
|
||||
let promises = files.map(file =>
|
||||
frappe.dom.file_to_base64(file.file_obj)
|
||||
.then(dataurl => {
|
||||
let promises = files.map((file) =>
|
||||
frappe.dom.file_to_base64(file.file_obj).then((dataurl) => {
|
||||
file.dataurl = dataurl;
|
||||
this.on_success && this.on_success(file);
|
||||
})
|
||||
@@ -363,10 +372,9 @@ const return_as_dataurl = (files) => {
|
||||
return Promise.all(promises);
|
||||
};
|
||||
|
||||
|
||||
const add_files = (files) => {
|
||||
files = Array.from(files).map(file => {
|
||||
let is_image = file.type.startsWith('image');
|
||||
files = Array.from(files).map((file) => {
|
||||
let is_image = file.type.startsWith("image");
|
||||
return {
|
||||
file_obj: file,
|
||||
cropper_file: file,
|
||||
@@ -380,13 +388,12 @@ const add_files = (files) => {
|
||||
request_succeeded: false,
|
||||
error_message: null,
|
||||
uploading: false,
|
||||
private: !is_image
|
||||
}
|
||||
private: !is_image,
|
||||
};
|
||||
});
|
||||
return files
|
||||
return files;
|
||||
};
|
||||
|
||||
|
||||
const clear_work = (e) => {
|
||||
const target = $(e.currentTarget);
|
||||
const parent = target.closest(".preview-work");
|
||||
@@ -395,14 +402,12 @@ const clear_work = (e) => {
|
||||
parent.siblings(".submit-work").removeClass("hide");
|
||||
};
|
||||
|
||||
|
||||
const fetch_assignments = () => {
|
||||
if ($(".attach-file").length <= 0)
|
||||
return;
|
||||
if ($(".attach-file").length <= 0) return;
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lesson_assignment.lesson_assignment.get_assignment",
|
||||
args: {
|
||||
"lesson": $(".title").attr("data-lesson")
|
||||
lesson: $(".title").attr("data-lesson"),
|
||||
},
|
||||
callback: (data) => {
|
||||
if (data.message) {
|
||||
@@ -411,13 +416,16 @@ const fetch_assignments = () => {
|
||||
target.addClass("hide");
|
||||
target.siblings(".submit-work").addClass("hide");
|
||||
target.siblings(".preview-work").removeClass("hide");
|
||||
target.siblings(".preview-work").find("a").attr("href", assignment.assignment).text(assignment.file_name);
|
||||
target
|
||||
.siblings(".preview-work")
|
||||
.find("a")
|
||||
.attr("href", assignment.assignment)
|
||||
.text(assignment.file_name);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const initialize_timer = () => {
|
||||
this.time_left = $(".timer").data("time");
|
||||
calculate_and_display_time(100, this.time_left);
|
||||
@@ -428,7 +436,7 @@ const initialize_timer = () => {
|
||||
let old_diff;
|
||||
|
||||
this.timer = setInterval(function () {
|
||||
var diff = (new Date().getTime() - self.start_time)/1000;
|
||||
var diff = (new Date().getTime() - self.start_time) / 1000;
|
||||
var variation = old_diff ? diff - old_diff : diff;
|
||||
old_diff = diff;
|
||||
self.time_left -= variation;
|
||||
@@ -442,7 +450,6 @@ const initialize_timer = () => {
|
||||
}, 100);
|
||||
};
|
||||
|
||||
|
||||
const calculate_and_display_time = (percent_time) => {
|
||||
$(".timer .progress-bar").attr("aria-valuenow", percent_time);
|
||||
$(".timer .progress-bar").attr("aria-valuemax", percent_time);
|
||||
@@ -451,25 +458,24 @@ const calculate_and_display_time = (percent_time) => {
|
||||
$(".timer .progress-bar").css("background-color", progress_color);
|
||||
};
|
||||
|
||||
|
||||
const save_lesson = (e) => {
|
||||
let lesson = $("#title").data("lesson");
|
||||
let self = this;
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.save_lesson",
|
||||
args: {
|
||||
"title": $("#title").text(),
|
||||
"body": this.code_field_group.fields_dict["code_md"].value,
|
||||
"youtube": $("#youtube").text(),
|
||||
"quiz_id": $("#quiz-id").text(),
|
||||
"chapter": $("#title").data("chapter"),
|
||||
"preview": $("#preview").prop("checked") ? 1 : 0,
|
||||
"idx": $("#title").data("index"),
|
||||
"lesson": lesson ? lesson : "",
|
||||
"question": $("#assignment-question").text(),
|
||||
"file_type": self.file_type
|
||||
title: $("#title").text(),
|
||||
body: this.code_field_group.fields_dict["code_md"].value,
|
||||
youtube: $("#youtube").text(),
|
||||
quiz_id: $("#quiz-id").text(),
|
||||
chapter: $("#title").data("chapter"),
|
||||
preview: $("#preview").prop("checked") ? 1 : 0,
|
||||
idx: $("#title").data("index"),
|
||||
lesson: lesson ? lesson : "",
|
||||
question: $("#assignment-question").text(),
|
||||
file_type: self.file_type,
|
||||
},
|
||||
callback: (data) => {;
|
||||
callback: (data) => {
|
||||
frappe.show_alert({
|
||||
message: __("Saved"),
|
||||
indicator: "green",
|
||||
@@ -477,16 +483,15 @@ const save_lesson = (e) => {
|
||||
setTimeout(() => {
|
||||
window.location.href = window.location.href.split("?")[0];
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const show_upload_modal = () => {
|
||||
new frappe.ui.FileUploader({
|
||||
folder: "Home/Attachments",
|
||||
restrictions: {
|
||||
allowed_file_types: ['image/*', 'video/*']
|
||||
allowed_file_types: ["image/*", "video/*"],
|
||||
},
|
||||
on_success: (file_doc) => {
|
||||
$(".attachments").append(build_attachment_table(file_doc));
|
||||
@@ -498,12 +503,13 @@ const show_upload_modal = () => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const build_attachment_table = (file_doc) => {
|
||||
let video_types = ["mov", "mp4", "mkv"];
|
||||
let video_extension = file_doc.file_url.split(".").pop();
|
||||
let video_extension = file_doc.file_url.split(".").pop();
|
||||
let is_video = video_types.indexOf(video_extension) >= 0;
|
||||
let link = is_video ? `{{ Video('${file_doc.file_url}') }}` : ``;
|
||||
let link = is_video
|
||||
? `{{ Video('${file_doc.file_url}') }}`
|
||||
: ``;
|
||||
|
||||
return $(`
|
||||
<tr class="attachment-row">
|
||||
@@ -517,7 +523,6 @@ const build_attachment_table = (file_doc) => {
|
||||
`);
|
||||
};
|
||||
|
||||
|
||||
const make_editor = () => {
|
||||
this.code_field_group = new frappe.ui.FieldGroup({
|
||||
fields: [
|
||||
@@ -530,7 +535,7 @@ const make_editor = () => {
|
||||
min_lines: 20,
|
||||
default: $("#body").data("body"),
|
||||
depends_on: 'eval:doc.type=="Markdown"',
|
||||
}
|
||||
},
|
||||
],
|
||||
body: $("#body").get(0),
|
||||
});
|
||||
@@ -540,7 +545,6 @@ const make_editor = () => {
|
||||
$("#body .form-column").addClass("p-0");
|
||||
};
|
||||
|
||||
|
||||
const set_file_type = () => {
|
||||
let self = this;
|
||||
let file_type = $("#file-type").data("type");
|
||||
@@ -550,6 +554,6 @@ const set_file_type = () => {
|
||||
$(elem).attr("selected", true);
|
||||
self.file_type = file_type;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,90 +1,103 @@
|
||||
import frappe
|
||||
from lms.www.utils import get_common_context, redirect_to_lesson
|
||||
from lms.lms.utils import get_lesson_url, has_course_moderator_role, is_instructor
|
||||
from frappe.utils import cstr, flt
|
||||
from frappe import _
|
||||
from frappe.utils import cstr, flt
|
||||
|
||||
from lms.lms.utils import (get_lesson_url, has_course_moderator_role,
|
||||
is_instructor)
|
||||
from lms.www.utils import get_common_context, redirect_to_lesson
|
||||
|
||||
|
||||
def get_context(context):
|
||||
get_common_context(context)
|
||||
get_common_context(context)
|
||||
|
||||
chapter_index = frappe.form_dict.get("chapter")
|
||||
lesson_index = frappe.form_dict.get("lesson")
|
||||
lesson_number = f"{chapter_index}.{lesson_index}"
|
||||
context.lesson_index = lesson_index
|
||||
context.chapter = frappe.db.get_value("Chapter Reference", {
|
||||
"idx": chapter_index,
|
||||
"parent": context.course.name
|
||||
}, "chapter")
|
||||
chapter_index = frappe.form_dict.get("chapter")
|
||||
lesson_index = frappe.form_dict.get("lesson")
|
||||
lesson_number = f"{chapter_index}.{lesson_index}"
|
||||
context.lesson_index = lesson_index
|
||||
context.chapter = frappe.db.get_value(
|
||||
"Chapter Reference", {"idx": chapter_index, "parent": context.course.name}, "chapter"
|
||||
)
|
||||
|
||||
if not chapter_index or not lesson_index:
|
||||
index_ = "1.1"
|
||||
redirect_to_lesson(context.course, index_)
|
||||
if not chapter_index or not lesson_index:
|
||||
index_ = "1.1"
|
||||
redirect_to_lesson(context.course, index_)
|
||||
|
||||
context.lesson = get_current_lesson_details(lesson_number, context)
|
||||
instructor = is_instructor(context.course.name)
|
||||
context.show_lesson = context.membership or (context.lesson and context.lesson.include_in_preview) or instructor or has_course_moderator_role()
|
||||
context.lesson = get_current_lesson_details(lesson_number, context)
|
||||
instructor = is_instructor(context.course.name)
|
||||
context.show_lesson = (
|
||||
context.membership
|
||||
or (context.lesson and context.lesson.include_in_preview)
|
||||
or instructor
|
||||
or has_course_moderator_role()
|
||||
)
|
||||
|
||||
if not context.lesson:
|
||||
context.lesson = frappe._dict()
|
||||
if not context.lesson:
|
||||
context.lesson = frappe._dict()
|
||||
|
||||
if frappe.form_dict.get("edit"):
|
||||
if not instructor and not has_course_moderator_role():
|
||||
raise frappe.PermissionError(_("You do not have permission to access this page."))
|
||||
context.lesson.edit_mode = True
|
||||
else:
|
||||
neighbours = get_neighbours(lesson_number, context.lessons)
|
||||
context.next_url = get_url(neighbours["next"], context.course)
|
||||
context.prev_url = get_url(neighbours["prev"], context.course)
|
||||
if frappe.form_dict.get("edit"):
|
||||
if not instructor and not has_course_moderator_role():
|
||||
raise frappe.PermissionError(_("You do not have permission to access this page."))
|
||||
context.lesson.edit_mode = True
|
||||
else:
|
||||
neighbours = get_neighbours(lesson_number, context.lessons)
|
||||
context.next_url = get_url(neighbours["next"], context.course)
|
||||
context.prev_url = get_url(neighbours["prev"], context.course)
|
||||
|
||||
meta_info = context.lesson.title + " - " + context.course.title if context.lesson.title else "New Lesson"
|
||||
context.metatags = {
|
||||
"title": meta_info,
|
||||
"keywords": meta_info,
|
||||
"description": meta_info
|
||||
}
|
||||
meta_info = (
|
||||
context.lesson.title + " - " + context.course.title
|
||||
if context.lesson.title
|
||||
else "New Lesson"
|
||||
)
|
||||
context.metatags = {
|
||||
"title": meta_info,
|
||||
"keywords": meta_info,
|
||||
"description": meta_info,
|
||||
}
|
||||
|
||||
context.page_extensions = get_page_extensions(context)
|
||||
context.page_context = {
|
||||
"course": context.course.name,
|
||||
"batch": context.batch,
|
||||
"lesson": context.lesson.name if context.lesson.name else "New Lesson",
|
||||
"is_member": context.membership is not None
|
||||
}
|
||||
context.page_extensions = get_page_extensions(context)
|
||||
context.page_context = {
|
||||
"course": context.course.name,
|
||||
"batch": context.batch,
|
||||
"lesson": context.lesson.name if context.lesson.name else "New Lesson",
|
||||
"is_member": context.membership is not None,
|
||||
}
|
||||
|
||||
|
||||
def get_current_lesson_details(lesson_number, context):
|
||||
details_list = list(filter(lambda x: cstr(x.number) == lesson_number, context.lessons))
|
||||
details_list = list(filter(lambda x: cstr(x.number) == lesson_number, context.lessons))
|
||||
|
||||
if not len(details_list):
|
||||
if frappe.form_dict.get("edit"):
|
||||
return None
|
||||
else:
|
||||
redirect_to_lesson(context.course)
|
||||
if not len(details_list):
|
||||
if frappe.form_dict.get("edit"):
|
||||
return None
|
||||
else:
|
||||
redirect_to_lesson(context.course)
|
||||
|
||||
lesson_info = details_list[0]
|
||||
lesson_info.body = lesson_info.body.replace("\"", "'")
|
||||
return lesson_info
|
||||
lesson_info = details_list[0]
|
||||
lesson_info.body = lesson_info.body.replace('"', "'")
|
||||
return lesson_info
|
||||
|
||||
|
||||
def get_url(lesson_number, course):
|
||||
return get_lesson_url(course.name, lesson_number) and get_lesson_url(course.name, lesson_number) + course.query_parameter
|
||||
return (
|
||||
get_lesson_url(course.name, lesson_number)
|
||||
and get_lesson_url(course.name, lesson_number) + course.query_parameter
|
||||
)
|
||||
|
||||
|
||||
def get_page_extensions(context):
|
||||
default_value = ["lms.plugins.PageExtension"]
|
||||
classnames = frappe.get_hooks("lms_lesson_page_extensions") or default_value
|
||||
extensions = [frappe.get_attr(name)() for name in classnames]
|
||||
for e in extensions:
|
||||
e.set_context(context)
|
||||
return extensions
|
||||
default_value = ["lms.plugins.PageExtension"]
|
||||
classnames = frappe.get_hooks("lms_lesson_page_extensions") or default_value
|
||||
extensions = [frappe.get_attr(name)() for name in classnames]
|
||||
for e in extensions:
|
||||
e.set_context(context)
|
||||
return extensions
|
||||
|
||||
|
||||
def get_neighbours(current, lessons):
|
||||
current = flt(current)
|
||||
numbers = sorted(lesson.number for lesson in lessons)
|
||||
index = numbers.index(current)
|
||||
return {
|
||||
"prev": numbers[index-1] if index-1 >= 0 else None,
|
||||
"next": numbers[index+1] if index+1 < len(numbers) else None
|
||||
}
|
||||
current = flt(current)
|
||||
numbers = sorted(lesson.number for lesson in lessons)
|
||||
index = numbers.index(current)
|
||||
return {
|
||||
"prev": numbers[index - 1] if index - 1 >= 0 else None,
|
||||
"next": numbers[index + 1] if index + 1 < len(numbers) else None,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
frappe.ready(() => {
|
||||
|
||||
if(!$(".quiz-card").length) {
|
||||
if (!$(".quiz-card").length) {
|
||||
add_question();
|
||||
}
|
||||
|
||||
@@ -17,52 +16,57 @@ frappe.ready(() => {
|
||||
});
|
||||
|
||||
get_questions();
|
||||
|
||||
});
|
||||
|
||||
|
||||
const add_question = () => {
|
||||
/* if ($(".new-quiz-card").length) {
|
||||
scroll_to_question_container();
|
||||
return;
|
||||
} */
|
||||
|
||||
let add_after = $(".quiz-card").length ? $(".quiz-card:last") : $("#quiz-title");
|
||||
let add_after = $(".quiz-card").length
|
||||
? $(".quiz-card:last")
|
||||
: $("#quiz-title");
|
||||
let question_template = `<div class="quiz-card new-quiz-card">
|
||||
<div contenteditable="true" data-placeholder="${__("Question")}" class="question mb-4"></div>
|
||||
<div contenteditable="true" data-placeholder="${__(
|
||||
"Question"
|
||||
)}" class="question mb-4"></div>
|
||||
</div>`;
|
||||
$(question_template).insertAfter(add_after);
|
||||
get_question_template();
|
||||
$(".btn-save-question").removeClass("hide");
|
||||
};
|
||||
|
||||
|
||||
const get_question_template = () => {
|
||||
Array.from({length: 4}, (x, num) => {
|
||||
Array.from({ length: 4 }, (x, num) => {
|
||||
let option_template = get_option_template(num + 1);
|
||||
let add_after = $(".quiz-card:last .option-group").length ? $(".quiz-card:last .option-group").last() : $(".question:last");
|
||||
let add_after = $(".quiz-card:last .option-group").length
|
||||
? $(".quiz-card:last .option-group").last()
|
||||
: $(".question:last");
|
||||
question_template = $(option_template).insertAfter(add_after);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const get_option_template = (num) => {
|
||||
return `<div class="option-group mt-4">
|
||||
<label class="">${__("Option")} ${num}</label>
|
||||
<div class="d-flex justify-content-between option-${num}">
|
||||
<div contenteditable="true" data-placeholder="${ __("Option") }"
|
||||
<div contenteditable="true" data-placeholder="${__(
|
||||
"Option"
|
||||
)}"
|
||||
class="option-input"></div>
|
||||
<div contenteditable="true" data-placeholder="${ __('Explanation') }"
|
||||
<div contenteditable="true" data-placeholder="${__(
|
||||
"Explanation"
|
||||
)}"
|
||||
class="option-input"></div>
|
||||
<div class="option-checkbox">
|
||||
<input type="checkbox">
|
||||
<label class="mb-0"> ${ __("Is Correct") } </label>
|
||||
<label class="mb-0"> ${__("Is Correct")} </label>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
};
|
||||
|
||||
|
||||
const save_question = (e) => {
|
||||
if (!$("#quiz-title").text()) {
|
||||
frappe.throw(__("Quiz Title is mandatory."));
|
||||
@@ -71,47 +75,54 @@ const save_question = (e) => {
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_quiz.lms_quiz.save_quiz",
|
||||
args: {
|
||||
"quiz_title": $("#quiz-title").text(),
|
||||
"questions": get_questions(),
|
||||
"quiz": $("#quiz-title").data("name") || ""
|
||||
quiz_title: $("#quiz-title").text(),
|
||||
questions: get_questions(),
|
||||
quiz: $("#quiz-title").data("name") || "",
|
||||
},
|
||||
callback: (data) => {
|
||||
window.location.href = "/quizzes";
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const get_questions = () => {
|
||||
let questions = [];
|
||||
|
||||
$(".quiz-card").each((i, el) => {
|
||||
if (!$(el).find(".question").text())
|
||||
return;
|
||||
if (!$(el).find(".question").text()) return;
|
||||
|
||||
let details = {};
|
||||
let one_correct_option = false;
|
||||
details["question"] = $(el).find(".question").text();
|
||||
details["question_name"] = $(el).find(".question").data("question") || "";
|
||||
details["question_name"] =
|
||||
$(el).find(".question").data("question") || "";
|
||||
|
||||
Array.from({length: 4}, (x, i) => {
|
||||
Array.from({ length: 4 }, (x, i) => {
|
||||
let num = i + 1;
|
||||
|
||||
details[`option_${num}`] = $(el).find(`.option-${num} .option-input:first`).text();
|
||||
details[`explanation_${num}`] = $(el).find(`.option-${num} .option-input:last`).text();
|
||||
details[`option_${num}`] = $(el)
|
||||
.find(`.option-${num} .option-input:first`)
|
||||
.text();
|
||||
details[`explanation_${num}`] = $(el)
|
||||
.find(`.option-${num} .option-input:last`)
|
||||
.text();
|
||||
|
||||
let is_correct = $(el).find(`.option-${num} .option-checkbox`).find("input").prop("checked");
|
||||
if (is_correct)
|
||||
one_correct_option = true;
|
||||
let is_correct = $(el)
|
||||
.find(`.option-${num} .option-checkbox`)
|
||||
.find("input")
|
||||
.prop("checked");
|
||||
if (is_correct) one_correct_option = true;
|
||||
|
||||
details[`is_correct_${num}`] = is_correct;
|
||||
});
|
||||
|
||||
if (!details["option_1"] || !details["option_2"])
|
||||
frappe.throw(__("Each question must have at least two options."))
|
||||
frappe.throw(__("Each question must have at least two options."));
|
||||
|
||||
if (!one_correct_option)
|
||||
frappe.throw(__("Each question must have at least one correct option."))
|
||||
frappe.throw(
|
||||
__("Each question must have at least one correct option.")
|
||||
);
|
||||
|
||||
questions.push(details);
|
||||
});
|
||||
@@ -119,10 +130,12 @@ const get_questions = () => {
|
||||
return questions;
|
||||
};
|
||||
|
||||
|
||||
const scroll_to_question_container = () => {
|
||||
$([document.documentElement, document.body]).animate({
|
||||
scrollTop: $(".new-quiz-card").offset().top
|
||||
}, 1000);
|
||||
$([document.documentElement, document.body]).animate(
|
||||
{
|
||||
scrollTop: $(".new-quiz-card").offset().top,
|
||||
},
|
||||
1000
|
||||
);
|
||||
$(".new-quiz-card").find(".question").focus();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,20 +3,19 @@ from frappe.utils import cstr
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
quizname = frappe.form_dict["quizname"]
|
||||
if quizname == "new-quiz":
|
||||
context.quiz = frappe._dict()
|
||||
context.quiz.edit_mode = 1
|
||||
else:
|
||||
fields_arr = ["name","question"]
|
||||
for num in range(1,5):
|
||||
fields_arr.append("option_" + cstr(num))
|
||||
fields_arr.append("is_correct_" + cstr(num))
|
||||
fields_arr.append("explanation_" + cstr(num))
|
||||
context.no_cache = 1
|
||||
quizname = frappe.form_dict["quizname"]
|
||||
if quizname == "new-quiz":
|
||||
context.quiz = frappe._dict()
|
||||
context.quiz.edit_mode = 1
|
||||
else:
|
||||
fields_arr = ["name", "question"]
|
||||
for num in range(1, 5):
|
||||
fields_arr.append("option_" + cstr(num))
|
||||
fields_arr.append("is_correct_" + cstr(num))
|
||||
fields_arr.append("explanation_" + cstr(num))
|
||||
|
||||
context.quiz = frappe.db.get_value("LMS Quiz", quizname, ["title", "name"], as_dict=1)
|
||||
context.quiz.questions = frappe.get_all("LMS Quiz Question", {
|
||||
"parent": quizname
|
||||
}, fields_arr,
|
||||
order_by="idx")
|
||||
context.quiz = frappe.db.get_value("LMS Quiz", quizname, ["title", "name"], as_dict=1)
|
||||
context.quiz.questions = frappe.get_all(
|
||||
"LMS Quiz Question", {"parent": quizname}, fields_arr, order_by="idx"
|
||||
)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
context.quiz_list = frappe.get_all("LMS Quiz", {"owner": frappe.session.user}, ["name", "title"])
|
||||
context.no_cache = 1
|
||||
context.quiz_list = frappe.get_all(
|
||||
"LMS Quiz", {"owner": frappe.session.user}, ["name", "title"]
|
||||
)
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
import frappe
|
||||
|
||||
from . import utils
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
course = utils.get_course()
|
||||
cohort = course and utils.get_cohort(course, frappe.form_dict["cohort"])
|
||||
if not cohort:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
context.no_cache = 1
|
||||
course = utils.get_course()
|
||||
cohort = course and utils.get_cohort(course, frappe.form_dict["cohort"])
|
||||
if not cohort:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
|
||||
user = frappe.session.user
|
||||
mentor = cohort.get_mentor(user)
|
||||
is_mentor = mentor is not None
|
||||
is_admin = cohort.is_admin(user) or "System Manager" in frappe.get_roles()
|
||||
user = frappe.session.user
|
||||
mentor = cohort.get_mentor(user)
|
||||
is_mentor = mentor is not None
|
||||
is_admin = cohort.is_admin(user) or "System Manager" in frappe.get_roles()
|
||||
|
||||
utils.add_nav(context, "All Courses", "/courses")
|
||||
utils.add_nav(context, course.title, "/courses/" + course.name)
|
||||
utils.add_nav(context, "Cohorts", "/courses/" + course.name + "/manage")
|
||||
utils.add_nav(context, "All Courses", "/courses")
|
||||
utils.add_nav(context, course.title, "/courses/" + course.name)
|
||||
utils.add_nav(context, "Cohorts", "/courses/" + course.name + "/manage")
|
||||
|
||||
context.course = course
|
||||
context.cohort = cohort
|
||||
context.mentor = mentor
|
||||
context.is_mentor = is_mentor
|
||||
context.is_admin = is_admin
|
||||
context.page = frappe.form_dict.get("page") or ""
|
||||
context.page_scope = "Cohort"
|
||||
context.course = course
|
||||
context.cohort = cohort
|
||||
context.mentor = mentor
|
||||
context.is_mentor = is_mentor
|
||||
context.is_admin = is_admin
|
||||
context.page = frappe.form_dict.get("page") or ""
|
||||
context.page_scope = "Cohort"
|
||||
|
||||
# Function to render to custom page given the slug
|
||||
context.render_page = lambda page: frappe.render_template(
|
||||
cohort.get_page_template(page, scope="Cohort"),
|
||||
context)
|
||||
# Function to render to custom page given the slug
|
||||
context.render_page = lambda page: frappe.render_template(
|
||||
cohort.get_page_template(page, scope="Cohort"), context
|
||||
)
|
||||
|
||||
@@ -1,32 +1,41 @@
|
||||
import frappe
|
||||
from .utils import get_course, add_nav
|
||||
from frappe.utils import get_url
|
||||
|
||||
from .utils import add_nav, get_course
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
context.course = get_course()
|
||||
if frappe.session.user == "Guest":
|
||||
frappe.local.flags.redirect_location = "/login?redirect-to=" + frappe.request.path
|
||||
raise frappe.Redirect()
|
||||
context.no_cache = 1
|
||||
context.course = get_course()
|
||||
if frappe.session.user == "Guest":
|
||||
frappe.local.flags.redirect_location = "/login?redirect-to=" + frappe.request.path
|
||||
raise frappe.Redirect()
|
||||
|
||||
if not context.course:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
if not context.course:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
|
||||
context.cohorts = get_cohorts(context.course)
|
||||
if len(context.cohorts) == 1:
|
||||
frappe.local.flags.redirect_location = f"{get_url()}/courses/{context.course.name}/cohorts/{context.cohorts[0].slug}"
|
||||
raise frappe.Redirect
|
||||
context.cohorts = get_cohorts(context.course)
|
||||
if len(context.cohorts) == 1:
|
||||
frappe.local.flags.redirect_location = (
|
||||
f"{get_url()}/courses/{context.course.name}/cohorts/{context.cohorts[0].slug}"
|
||||
)
|
||||
raise frappe.Redirect
|
||||
|
||||
add_nav(context, "All Courses", "/courses")
|
||||
add_nav(context, context.course.title, "/courses/" + context.course.name)
|
||||
|
||||
add_nav(context, "All Courses", "/courses")
|
||||
add_nav(context, context.course.title, "/courses/" + context.course.name)
|
||||
|
||||
def get_cohorts(course):
|
||||
if "System Manager" in frappe.get_roles():
|
||||
return course.get_cohorts()
|
||||
if "System Manager" in frappe.get_roles():
|
||||
return course.get_cohorts()
|
||||
|
||||
staff_roles = frappe.get_all("Cohort Staff", filters={"course": course.name}, fields=["cohort"])
|
||||
mentor_roles = frappe.get_all("Cohort Mentor", filters={"course": course.name}, fields=["cohort"])
|
||||
roles = staff_roles + mentor_roles
|
||||
names = {role.cohort for role in roles}
|
||||
return [frappe.get_doc("Cohort", name) for name in names]
|
||||
staff_roles = frappe.get_all(
|
||||
"Cohort Staff", filters={"course": course.name}, fields=["cohort"]
|
||||
)
|
||||
mentor_roles = frappe.get_all(
|
||||
"Cohort Mentor", filters={"course": course.name}, fields=["cohort"]
|
||||
)
|
||||
roles = staff_roles + mentor_roles
|
||||
names = {role.cohort for role in roles}
|
||||
return [frappe.get_doc("Cohort", name) for name in names]
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
import frappe
|
||||
|
||||
from . import utils
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
context.no_cache = 1
|
||||
|
||||
course = utils.get_course(frappe.form_dict["course"])
|
||||
cohort = course and utils.get_cohort(course, frappe.form_dict["cohort"])
|
||||
subgroup = cohort and utils.get_subgroup(cohort, frappe.form_dict["subgroup"])
|
||||
if not subgroup:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
course = utils.get_course(frappe.form_dict["course"])
|
||||
cohort = course and utils.get_cohort(course, frappe.form_dict["cohort"])
|
||||
subgroup = cohort and utils.get_subgroup(cohort, frappe.form_dict["subgroup"])
|
||||
if not subgroup:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
|
||||
invite_code = frappe.form_dict["invite_code"]
|
||||
if subgroup.invite_code != invite_code:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
invite_code = frappe.form_dict["invite_code"]
|
||||
if subgroup.invite_code != invite_code:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
|
||||
utils.add_nav(context, "All Courses", "/courses")
|
||||
utils.add_nav(context, course.title, "/courses/" + course.name)
|
||||
utils.add_nav(context, "All Courses", "/courses")
|
||||
utils.add_nav(context, course.title, "/courses/" + course.name)
|
||||
|
||||
context.course = course
|
||||
context.cohort = cohort
|
||||
context.subgroup = subgroup
|
||||
context.course = course
|
||||
context.cohort = cohort
|
||||
context.subgroup = subgroup
|
||||
|
||||
@@ -1,67 +1,73 @@
|
||||
import frappe
|
||||
|
||||
from . import utils
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
course = utils.get_course()
|
||||
context.no_cache = 1
|
||||
course = utils.get_course()
|
||||
|
||||
cohort = utils.get_cohort(course, frappe.form_dict['cohort'])
|
||||
subgroup = utils.get_subgroup(cohort, frappe.form_dict['subgroup'])
|
||||
cohort = utils.get_cohort(course, frappe.form_dict["cohort"])
|
||||
subgroup = utils.get_subgroup(cohort, frappe.form_dict["subgroup"])
|
||||
|
||||
if not subgroup:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
if not subgroup:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
|
||||
page = frappe.form_dict.get("page")
|
||||
is_mentor = subgroup.is_mentor(frappe.session.user)
|
||||
is_admin = cohort.is_admin(frappe.session.user) or "System Manager" in frappe.get_roles()
|
||||
page = frappe.form_dict.get("page")
|
||||
is_mentor = subgroup.is_mentor(frappe.session.user)
|
||||
is_admin = (
|
||||
cohort.is_admin(frappe.session.user) or "System Manager" in frappe.get_roles()
|
||||
)
|
||||
|
||||
if is_admin:
|
||||
role = "Admin"
|
||||
elif is_mentor:
|
||||
role = "Mentor"
|
||||
else:
|
||||
role = "Public"
|
||||
if is_admin:
|
||||
role = "Admin"
|
||||
elif is_mentor:
|
||||
role = "Mentor"
|
||||
else:
|
||||
role = "Public"
|
||||
|
||||
pages = [
|
||||
("mentors", ["Admin", "Mentor", "Public"]),
|
||||
("students", ["Admin", "Mentor", "Public"]),
|
||||
("join-requests", ["Admin", "Mentor"]),
|
||||
("admin", ["Admin"])
|
||||
]
|
||||
pages += [(p.slug, ["Admin", "Mentor"]) for p in cohort.get_pages(scope="Subgroup")]
|
||||
pages = [
|
||||
("mentors", ["Admin", "Mentor", "Public"]),
|
||||
("students", ["Admin", "Mentor", "Public"]),
|
||||
("join-requests", ["Admin", "Mentor"]),
|
||||
("admin", ["Admin"]),
|
||||
]
|
||||
pages += [(p.slug, ["Admin", "Mentor"]) for p in cohort.get_pages(scope="Subgroup")]
|
||||
|
||||
page_names = [p for p, roles in pages if role in roles]
|
||||
page_names = [p for p, roles in pages if role in roles]
|
||||
|
||||
if page not in page_names:
|
||||
frappe.local.flags.redirect_location = subgroup.get_url() + "/mentors"
|
||||
raise frappe.Redirect
|
||||
if page not in page_names:
|
||||
frappe.local.flags.redirect_location = subgroup.get_url() + "/mentors"
|
||||
raise frappe.Redirect
|
||||
|
||||
utils.add_nav(context, "All Courses", "/courses")
|
||||
utils.add_nav(context, course.title, f"/courses/{course.name}")
|
||||
utils.add_nav(context, "Cohorts", f"/courses/{course.name}/manage")
|
||||
utils.add_nav(context, cohort.title, f"/courses/{course.name}/cohorts/{cohort.slug}")
|
||||
utils.add_nav(context, "All Courses", "/courses")
|
||||
utils.add_nav(context, course.title, f"/courses/{course.name}")
|
||||
utils.add_nav(context, "Cohorts", f"/courses/{course.name}/manage")
|
||||
utils.add_nav(context, cohort.title, f"/courses/{course.name}/cohorts/{cohort.slug}")
|
||||
|
||||
context.course = course
|
||||
context.cohort = cohort
|
||||
context.subgroup = subgroup
|
||||
context.stats = get_stats(subgroup)
|
||||
context.page = page
|
||||
context.is_admin = is_admin
|
||||
context.is_mentor = is_mentor
|
||||
context.page_scope = "Subgroup"
|
||||
context.course = course
|
||||
context.cohort = cohort
|
||||
context.subgroup = subgroup
|
||||
context.stats = get_stats(subgroup)
|
||||
context.page = page
|
||||
context.is_admin = is_admin
|
||||
context.is_mentor = is_mentor
|
||||
context.page_scope = "Subgroup"
|
||||
|
||||
# Function to render to custom page given the slug
|
||||
context.render_page = lambda page: frappe.render_template(
|
||||
cohort.get_page_template(page, scope="Subgroup"), context
|
||||
)
|
||||
|
||||
# Function to render to custom page given the slug
|
||||
context.render_page = lambda page: frappe.render_template(
|
||||
cohort.get_page_template(page, scope="Subgroup"),
|
||||
context)
|
||||
|
||||
def get_stats(subgroup):
|
||||
return {
|
||||
"join_requests": len(subgroup.get_join_requests()),
|
||||
"students": len(subgroup.get_students()),
|
||||
"mentors": len(subgroup.get_mentors())
|
||||
}
|
||||
return {
|
||||
"join_requests": len(subgroup.get_join_requests()),
|
||||
"students": len(subgroup.get_students()),
|
||||
"mentors": len(subgroup.get_mentors()),
|
||||
}
|
||||
|
||||
|
||||
def has_page(cohort, page):
|
||||
return cohort.get_page(page, scope="Subgroup")
|
||||
return cohort.get_page(page, scope="Subgroup")
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def get_course(course_name=None):
|
||||
course_name = course_name or frappe.form_dict["course"]
|
||||
return course_name and get_doc("LMS Course", course_name)
|
||||
course_name = course_name or frappe.form_dict["course"]
|
||||
return course_name and get_doc("LMS Course", course_name)
|
||||
|
||||
|
||||
def get_doc(doctype, name):
|
||||
try:
|
||||
return frappe.get_doc(doctype, name)
|
||||
except frappe.exceptions.DoesNotExistError:
|
||||
return
|
||||
try:
|
||||
return frappe.get_doc(doctype, name)
|
||||
except frappe.exceptions.DoesNotExistError:
|
||||
return
|
||||
|
||||
|
||||
def get_cohort(course, cohort_slug):
|
||||
name = frappe.get_value("Cohort", {"course": course.name, "slug": cohort_slug})
|
||||
return name and frappe.get_doc("Cohort", name)
|
||||
name = frappe.get_value("Cohort", {"course": course.name, "slug": cohort_slug})
|
||||
return name and frappe.get_doc("Cohort", name)
|
||||
|
||||
|
||||
def get_subgroup(cohort, subgroup_slug):
|
||||
name = frappe.get_value("Cohort Subgroup", {"cohort": cohort.name, "slug": subgroup_slug})
|
||||
return name and frappe.get_doc("Cohort Subgroup", name)
|
||||
name = frappe.get_value(
|
||||
"Cohort Subgroup", {"cohort": cohort.name, "slug": subgroup_slug}
|
||||
)
|
||||
return name and frappe.get_doc("Cohort Subgroup", name)
|
||||
|
||||
|
||||
def add_nav(context, title, href):
|
||||
"""Adds a breadcrumb to the navigation.
|
||||
"""
|
||||
nav = context.setdefault("nav", [])
|
||||
nav.append({"title": title, "href": href})
|
||||
"""Adds a breadcrumb to the navigation."""
|
||||
nav = context.setdefault("nav", [])
|
||||
nav.append({"title": title, "href": href})
|
||||
|
||||
@@ -1,58 +1,56 @@
|
||||
frappe.ready(() => {
|
||||
$("#load-more").click((e) => {
|
||||
search(e);
|
||||
});
|
||||
|
||||
$("#load-more").click((e) => {
|
||||
search(e);
|
||||
});
|
||||
|
||||
$(".close-search-empty-state").click((e) => {
|
||||
close_search_empty_state(e);
|
||||
});
|
||||
|
||||
$("#search-user").keyup(function() {
|
||||
let timer;
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => { search.apply(this, arguments); }, 300);
|
||||
});
|
||||
$(".close-search-empty-state").click((e) => {
|
||||
close_search_empty_state(e);
|
||||
});
|
||||
|
||||
$("#search-user").keyup(function () {
|
||||
let timer;
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
search.apply(this, arguments);
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
|
||||
const search = (e) => {
|
||||
$("#search-empty-state").addClass("hide");
|
||||
let start = $(e.currentTarget).data("start")
|
||||
let input = $("#search-user").val();
|
||||
if ($(e.currentTarget).prop("nodeName") == "INPUT")
|
||||
start = 0;
|
||||
$("#search-empty-state").addClass("hide");
|
||||
let start = $(e.currentTarget).data("start");
|
||||
let input = $("#search-user").val();
|
||||
if ($(e.currentTarget).prop("nodeName") == "INPUT") start = 0;
|
||||
|
||||
frappe.call({
|
||||
method: "lms.overrides.user.search_users",
|
||||
args: {
|
||||
"start": start,
|
||||
"text": input
|
||||
},
|
||||
callback: (data) => {
|
||||
if ($(e.currentTarget).prop("nodeName") == "INPUT")
|
||||
$(".member-parent").empty();
|
||||
frappe.call({
|
||||
method: "lms.overrides.user.search_users",
|
||||
args: {
|
||||
start: start,
|
||||
text: input,
|
||||
},
|
||||
callback: (data) => {
|
||||
if ($(e.currentTarget).prop("nodeName") == "INPUT")
|
||||
$(".member-parent").empty();
|
||||
|
||||
if (data.message.user_details.length)
|
||||
$("#load-more").removeClass("hide");
|
||||
else
|
||||
$("#search-empty-state").removeClass("hide");
|
||||
if (data.message.user_details.length)
|
||||
$("#load-more").removeClass("hide");
|
||||
else $("#search-empty-state").removeClass("hide");
|
||||
|
||||
$(".member-parent").append(data.message.user_details);
|
||||
update_load_more_state(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
$(".member-parent").append(data.message.user_details);
|
||||
update_load_more_state(data);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const close_search_empty_state = (e) => {
|
||||
$("#search-empty-state").addClass("hide");
|
||||
$("#search-user").val("").keyup();
|
||||
}
|
||||
$("#search-empty-state").addClass("hide");
|
||||
$("#search-user").val("").keyup();
|
||||
};
|
||||
|
||||
const update_load_more_state = (data) => {
|
||||
$("#load-more").data("start", data.message.start);
|
||||
$("#load-more").data("count", data.message.count);
|
||||
if ($(".member-card").length == $("#load-more").data("count")) {
|
||||
$("#load-more").addClass("hide");
|
||||
}
|
||||
}
|
||||
$("#load-more").data("start", data.message.start);
|
||||
$("#load-more").data("count", data.message.count);
|
||||
if ($(".member-card").length == $("#load-more").data("count")) {
|
||||
$("#load-more").addClass("hide");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.user_count = frappe.db.count("User", {"enabled": True})
|
||||
context.users = frappe.get_all("User",
|
||||
filters={"enabled": True},
|
||||
fields=["name", "username", "full_name", "user_image", "headline"],
|
||||
start=0,
|
||||
page_length=24,
|
||||
order_by="creation desc")
|
||||
context.user_count = frappe.db.count("User", {"enabled": True})
|
||||
context.users = frappe.get_all(
|
||||
"User",
|
||||
filters={"enabled": True},
|
||||
fields=["name", "username", "full_name", "user_image", "headline"],
|
||||
start=0,
|
||||
page_length=24,
|
||||
order_by="creation desc",
|
||||
)
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
frappe.ready(() => {
|
||||
|
||||
$("#export-as-pdf").click((e) => {
|
||||
export_as_png(e);
|
||||
})
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
const export_as_pdf = (e) => {
|
||||
|
||||
var formData = new FormData();
|
||||
|
||||
//Push the HTML content into an element
|
||||
formData.append("html", $("#certificate-card").html());
|
||||
|
||||
var blob = new Blob([], { type: "text/xml"});
|
||||
var blob = new Blob([], { type: "text/xml" });
|
||||
formData.append("blob", blob);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", '/api/method/lms.lms.doctype.lms_certificate.lms_certificate.get_certificate_pdf');
|
||||
xhr.open(
|
||||
"POST",
|
||||
"/api/method/lms.lms.doctype.lms_certificate.lms_certificate.get_certificate_pdf"
|
||||
);
|
||||
xhr.setRequestHeader("X-Frappe-CSRF-Token", frappe.csrf_token);
|
||||
xhr.responseType = "arraybuffer";
|
||||
|
||||
xhr.onload = function(success) {
|
||||
xhr.onload = function (success) {
|
||||
if (this.status === 200) {
|
||||
var blob = new Blob([success.currentTarget.response], {type: "application/pdf"});
|
||||
var blob = new Blob([success.currentTarget.response], {
|
||||
type: "application/pdf",
|
||||
});
|
||||
var objectUrl = URL.createObjectURL(blob);
|
||||
|
||||
//Open report in a new window
|
||||
@@ -31,23 +33,24 @@ const export_as_pdf = (e) => {
|
||||
}
|
||||
};
|
||||
xhr.send(formData);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const export_as_png = (e) => {
|
||||
let button = $(e.currentTarget);
|
||||
button.text(__("Exporting..."));
|
||||
|
||||
html2canvas(document.querySelector('#certificate-card'), {
|
||||
html2canvas(document.querySelector("#certificate-card"), {
|
||||
scrollY: -window.scrollY,
|
||||
scrollX: 0
|
||||
}).then(function(canvas) {
|
||||
let dataURL = canvas.toDataURL('image/png');
|
||||
let a = document.createElement('a');
|
||||
a.href = dataURL;
|
||||
a.download = button.attr("data-certificate-name");
|
||||
a.click();
|
||||
}).finally(() => {
|
||||
button.text(__("Export"))
|
||||
});
|
||||
}
|
||||
scrollX: 0,
|
||||
})
|
||||
.then(function (canvas) {
|
||||
let dataURL = canvas.toDataURL("image/png");
|
||||
let a = document.createElement("a");
|
||||
a.href = dataURL;
|
||||
a.download = button.attr("data-certificate-name");
|
||||
a.click();
|
||||
})
|
||||
.finally(() => {
|
||||
button.text(__("Export"));
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,31 +1,46 @@
|
||||
import frappe
|
||||
from frappe.utils.jinja import render_template
|
||||
|
||||
from lms.lms.utils import get_instructors
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
context.no_cache = 1
|
||||
|
||||
try:
|
||||
course_name = frappe.form_dict["course"]
|
||||
certificate_name = frappe.form_dict["certificate"]
|
||||
except KeyError:
|
||||
redirect_to_course_list()
|
||||
try:
|
||||
course_name = frappe.form_dict["course"]
|
||||
certificate_name = frappe.form_dict["certificate"]
|
||||
except KeyError:
|
||||
redirect_to_course_list()
|
||||
|
||||
context.certificate = frappe.db.get_value("LMS Certificate", certificate_name,
|
||||
["name", "member", "issue_date", "expiry_date", "course"], as_dict=True)
|
||||
context.certificate = frappe.db.get_value(
|
||||
"LMS Certificate",
|
||||
certificate_name,
|
||||
["name", "member", "issue_date", "expiry_date", "course"],
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
if context.certificate.course != course_name:
|
||||
redirect_to_course_list()
|
||||
if context.certificate.course != course_name:
|
||||
redirect_to_course_list()
|
||||
|
||||
context.course = frappe.db.get_value("LMS Course", course_name, ["title", "name", "image"], as_dict=True)
|
||||
context.instructors = (", ").join([x.full_name for x in get_instructors(course_name)])
|
||||
context.member = frappe.db.get_value("User", context.certificate.member, ["full_name"], as_dict=True)
|
||||
context.course = frappe.db.get_value(
|
||||
"LMS Course", course_name, ["title", "name", "image"], as_dict=True
|
||||
)
|
||||
context.instructors = (", ").join([x.full_name for x in get_instructors(course_name)])
|
||||
context.member = frappe.db.get_value(
|
||||
"User", context.certificate.member, ["full_name"], as_dict=True
|
||||
)
|
||||
|
||||
context.logo = frappe.db.get_single_value("Website Settings", "banner_image")
|
||||
template_name = frappe.db.get_single_value(
|
||||
"LMS Settings", "custom_certificate_template"
|
||||
)
|
||||
context.custom_certificate_template = frappe.db.get_value(
|
||||
"Web Template", template_name, "template"
|
||||
)
|
||||
context.custom_template = render_template(context.custom_certificate_template, context)
|
||||
|
||||
context.logo = frappe.db.get_single_value("Website Settings", "banner_image")
|
||||
template_name = frappe.db.get_single_value("LMS Settings", "custom_certificate_template")
|
||||
context.custom_certificate_template = frappe.db.get_value("Web Template", template_name, "template")
|
||||
context.custom_template = render_template(context.custom_certificate_template, context)
|
||||
|
||||
def redirect_to_course_list():
|
||||
frappe.local.flags.redirect_location = "/courses"
|
||||
raise frappe.Redirect
|
||||
frappe.local.flags.redirect_location = "/courses"
|
||||
raise frappe.Redirect
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
frappe.ready(() => {
|
||||
|
||||
hide_wrapped_mentor_cards();
|
||||
|
||||
$("#cancel-request").click((e) => {
|
||||
@@ -35,7 +34,7 @@ frappe.ready(() => {
|
||||
});
|
||||
|
||||
$("#slot-date").on("change", (e) => {
|
||||
display_slots(e);
|
||||
display_slots(e);
|
||||
});
|
||||
|
||||
$("#submit-slot").click((e) => {
|
||||
@@ -73,17 +72,15 @@ frappe.ready(() => {
|
||||
if ($("#description").length) {
|
||||
make_editor();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
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");
|
||||
$(this).addClass("wrapped").slideUp("fast");
|
||||
}
|
||||
if (!offset_top_prev) {
|
||||
offset_top_prev = offset_top;
|
||||
@@ -95,30 +92,33 @@ const hide_wrapped_mentor_cards = () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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"))
|
||||
method: "lms.lms.doctype.lms_mentor_request.lms_mentor_request.cancel_request",
|
||||
args: {
|
||||
course: decodeURIComponent($(e.currentTarget).attr("data-course")),
|
||||
},
|
||||
"callback": (data) => {
|
||||
callback: (data) => {
|
||||
if (data.message == "OK") {
|
||||
$("#mentor-request").removeClass("hide");
|
||||
$("#already-applied").addClass("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";
|
||||
});
|
||||
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") {
|
||||
@@ -128,24 +128,21 @@ const view_all_mentors = (e) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const show_review_dialog = (e) => {
|
||||
e.preventDefault();
|
||||
$("#review-modal").modal("show");
|
||||
};
|
||||
|
||||
|
||||
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) {
|
||||
if (i <= rating - 1) {
|
||||
$(elem).addClass("star-click");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const submit_review = (e) => {
|
||||
e.preventDefault();
|
||||
let rating = $(".rating-field").children(".star-click").length;
|
||||
@@ -157,122 +154,148 @@ const submit_review = (e) => {
|
||||
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"))
|
||||
rating: rating,
|
||||
review: review,
|
||||
course: decodeURIComponent($(e.currentTarget).attr("data-course")),
|
||||
},
|
||||
callback: (data) => {
|
||||
if (data.message == "OK") {
|
||||
$(".review-modal").modal("hide");
|
||||
frappe.show_alert({
|
||||
message: __("Review submitted."),
|
||||
indicator:'green'
|
||||
}, 3);
|
||||
frappe.show_alert(
|
||||
{
|
||||
message: __("Review submitted."),
|
||||
indicator: "green",
|
||||
},
|
||||
3
|
||||
);
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
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;
|
||||
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({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.submit_for_review",
|
||||
args: {
|
||||
"course": course
|
||||
course: course,
|
||||
},
|
||||
callback: (data) => {
|
||||
if (data.message == "No Chp") {
|
||||
frappe.msgprint(__(`There are no chapters in this course.
|
||||
Please add chapters and lessons to your course before you submit it for review.`));
|
||||
frappe.msgprint(
|
||||
__(`There are no chapters in this course.
|
||||
Please add chapters and lessons to your course before you submit it for review.`)
|
||||
);
|
||||
} else if (data.message == "OK") {
|
||||
frappe.show_alert({
|
||||
message: __("Your course has been submitted for review."),
|
||||
indicator:'green'
|
||||
}, 3);
|
||||
frappe.show_alert(
|
||||
{
|
||||
message: __(
|
||||
"Your course has been submitted for review."
|
||||
),
|
||||
indicator: "green",
|
||||
},
|
||||
3
|
||||
);
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const apply_cetificate = (e) => {
|
||||
$("#slot-modal").modal("show");
|
||||
};
|
||||
|
||||
|
||||
const submit_slot = (e) => {
|
||||
e.preventDefault();
|
||||
const slot = window.selected_slot;
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_certificate_request.lms_certificate_request.create_certificate_request",
|
||||
args: {
|
||||
"course": slot.data("course"),
|
||||
"date": $("#slot-date").val(),
|
||||
"day": slot.data("day"),
|
||||
"start_time": slot.data("start"),
|
||||
"end_time": slot.data("end")
|
||||
course: slot.data("course"),
|
||||
date: $("#slot-date").val(),
|
||||
day: slot.data("day"),
|
||||
start_time: slot.data("start"),
|
||||
end_time: slot.data("end"),
|
||||
},
|
||||
callback: (data) => {
|
||||
$("#slot-modal").modal("hide");
|
||||
frappe.show_alert({
|
||||
message: __("Your slot has been booked. Prepare well for the evaluations."),
|
||||
indicator:'green'
|
||||
}, 3);
|
||||
frappe.show_alert(
|
||||
{
|
||||
message: __(
|
||||
"Your slot has been booked. Prepare well for the evaluations."
|
||||
),
|
||||
indicator: "green",
|
||||
},
|
||||
3
|
||||
);
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 3000);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const display_slots = (e) => {
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.course_evaluator.course_evaluator.get_schedule",
|
||||
args: {
|
||||
"course": $(e.currentTarget).data("course"),
|
||||
"date": $(e.currentTarget).val()
|
||||
course: $(e.currentTarget).data("course"),
|
||||
date: $(e.currentTarget).val(),
|
||||
},
|
||||
callback: (data) => {
|
||||
let options = "";
|
||||
data.message.forEach((obj) => {
|
||||
options += `<button type="button" class="btn btn-sm btn-secondary mb-3 mr-3 slot hide"
|
||||
data-course="${$(e.currentTarget).data("course")}"
|
||||
data-day="${obj.day}" data-start="${obj.start_time}" data-end="${obj.end_time}">
|
||||
${format_time(obj.start_time)} - ${format_time(obj.end_time)}</button>`;
|
||||
data-day="${obj.day}" data-start="${
|
||||
obj.start_time
|
||||
}" data-end="${obj.end_time}">
|
||||
${format_time(obj.start_time)} - ${format_time(
|
||||
obj.end_time
|
||||
)}</button>`;
|
||||
});
|
||||
e.preventDefault();
|
||||
$("#slot-modal .slots").html(options);
|
||||
const weekday = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
|
||||
const day = weekday[new Date($(e.currentTarget).val()).getDay()]
|
||||
const weekday = [
|
||||
"Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday",
|
||||
];
|
||||
const day = weekday[new Date($(e.currentTarget).val()).getDay()];
|
||||
|
||||
$(".slot").addClass("hide");
|
||||
$(".slot-label").addClass("hide");
|
||||
@@ -284,74 +307,73 @@ const display_slots = (e) => {
|
||||
} else {
|
||||
$("#no-slots-message").removeClass("hide");
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
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/*']
|
||||
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);
|
||||
$(".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) => {
|
||||
$(`<div class="course-card-pills" contenteditable="true"
|
||||
data-placeholder="${__('Tag')}"></div>`).insertBefore(`.btn-tag`);
|
||||
data-placeholder="${__("Tag")}"></div>`).insertBefore(`.btn-tag`);
|
||||
};
|
||||
|
||||
|
||||
const save_course = (e) => {
|
||||
let tags = $('.course-card-pills').map((i, el) => $(el).text().trim()).get();
|
||||
tags = tags.filter(word => word.trim().length > 0);
|
||||
let tags = $(".course-card-pills")
|
||||
.map((i, el) => $(el).text().trim())
|
||||
.get();
|
||||
tags = tags.filter((word) => word.trim().length > 0);
|
||||
|
||||
frappe.call({
|
||||
method: "lms.lms.doctype.lms_course.lms_course.save_course",
|
||||
args: {
|
||||
"tags": tags.join(", "),
|
||||
"title": $("#title").text(),
|
||||
"short_introduction": $("#intro").text(),
|
||||
"video_link": $("#video-link").text(),
|
||||
"image": $("#image").attr("href"),
|
||||
"description": this.code_field_group.fields_dict["code_md"].value,
|
||||
"course": $("#title").data("course") ? $("#title").data("course") : "",
|
||||
"published": $("#published").prop("checked") ? 1 : 0,
|
||||
"upcoming": $("#upcoming").prop("checked") ? 1 : 0
|
||||
tags: tags.join(", "),
|
||||
title: $("#title").text(),
|
||||
short_introduction: $("#intro").text(),
|
||||
video_link: $("#video-link").text(),
|
||||
image: $("#image").attr("href"),
|
||||
description: this.code_field_group.fields_dict["code_md"].value,
|
||||
course: $("#title").data("course")
|
||||
? $("#title").data("course")
|
||||
: "",
|
||||
published: $("#published").prop("checked") ? 1 : 0,
|
||||
upcoming: $("#upcoming").prop("checked") ? 1 : 0,
|
||||
},
|
||||
callback: (data) => {
|
||||
frappe.show_alert({
|
||||
@@ -361,16 +383,14 @@ const save_course = (e) => {
|
||||
setTimeout(() => {
|
||||
window.location.href = `/courses/${data.message}?edit=1`;
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const remove_tag = (e) => {
|
||||
$(e.currentTarget).closest(".course-card-pills").remove();
|
||||
};
|
||||
|
||||
|
||||
const make_editor = () => {
|
||||
this.code_field_group = new frappe.ui.FieldGroup({
|
||||
fields: [
|
||||
@@ -383,7 +403,7 @@ const make_editor = () => {
|
||||
min_lines: 20,
|
||||
default: $("#description").data("description"),
|
||||
depends_on: 'eval:doc.type=="Markdown"',
|
||||
}
|
||||
},
|
||||
],
|
||||
body: $("#description").get(0),
|
||||
});
|
||||
|
||||
@@ -1,74 +1,106 @@
|
||||
import frappe
|
||||
from lms.lms.utils import can_create_courses, get_membership, has_course_moderator_role, is_instructor, is_certified, get_evaluation_details, redirect_to_courses_list
|
||||
from frappe import _
|
||||
|
||||
from lms.lms.utils import (can_create_courses, get_evaluation_details,
|
||||
get_membership, has_course_moderator_role,
|
||||
is_certified, is_instructor,
|
||||
redirect_to_courses_list)
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
context.no_cache = 1
|
||||
|
||||
try:
|
||||
course_name = frappe.form_dict["course"]
|
||||
except KeyError:
|
||||
redirect_to_courses_list()
|
||||
try:
|
||||
course_name = frappe.form_dict["course"]
|
||||
except KeyError:
|
||||
redirect_to_courses_list()
|
||||
|
||||
if course_name == "new-course":
|
||||
if not can_create_courses():
|
||||
message = "You do not have permission to access this page."
|
||||
if frappe.session.user == "Guest":
|
||||
message = "Please login to access this page."
|
||||
if course_name == "new-course":
|
||||
if not can_create_courses():
|
||||
message = "You do not have permission to access this page."
|
||||
if frappe.session.user == "Guest":
|
||||
message = "Please login to access this page."
|
||||
|
||||
raise frappe.PermissionError(_(message))
|
||||
raise frappe.PermissionError(_(message))
|
||||
|
||||
context.course = frappe._dict()
|
||||
context.course.edit_mode = True
|
||||
context.membership = None
|
||||
else:
|
||||
set_course_context(context, course_name)
|
||||
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",
|
||||
"price_certificate", "currency", "max_attempts", "duration"],
|
||||
as_dict=True)
|
||||
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",
|
||||
"price_certificate",
|
||||
"currency",
|
||||
"max_attempts",
|
||||
"duration",
|
||||
],
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
if frappe.form_dict.get("edit"):
|
||||
if not is_instructor(course.name) and not has_course_moderator_role():
|
||||
raise frappe.PermissionError(_("You do not have permission to access this page."))
|
||||
course.edit_mode = True
|
||||
if frappe.form_dict.get("edit"):
|
||||
if not is_instructor(course.name) and not has_course_moderator_role():
|
||||
raise frappe.PermissionError(_("You do not have permission to access this page."))
|
||||
course.edit_mode = True
|
||||
|
||||
if course is None:
|
||||
redirect_to_courses_list()
|
||||
if course is None:
|
||||
redirect_to_courses_list()
|
||||
|
||||
related_courses = frappe.get_all("Related Courses", {"parent": course.name}, ["course"])
|
||||
for csr in related_courses:
|
||||
csr.update(frappe.db.get_value("LMS Course",
|
||||
csr.course, ["name", "upcoming", "title", "image", "enable_certification"], as_dict=True))
|
||||
course.related_courses = related_courses
|
||||
related_courses = frappe.get_all(
|
||||
"Related Courses", {"parent": course.name}, ["course"]
|
||||
)
|
||||
for csr in related_courses:
|
||||
csr.update(
|
||||
frappe.db.get_value(
|
||||
"LMS Course",
|
||||
csr.course,
|
||||
["name", "upcoming", "title", "image", "enable_certification"],
|
||||
as_dict=True,
|
||||
)
|
||||
)
|
||||
course.related_courses = related_courses
|
||||
|
||||
context.course = course
|
||||
membership = get_membership(course.name, frappe.session.user)
|
||||
context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else ""
|
||||
context.membership = membership
|
||||
context.certificate = is_certified(course.name)
|
||||
eval_details = get_evaluation_details(course.name)
|
||||
context.eligible_for_evaluation = eval_details.eligible
|
||||
context.certificate_request = eval_details.request
|
||||
context.no_of_attempts = eval_details.no_of_attempts
|
||||
if context.course.upcoming:
|
||||
context.is_user_interested = get_user_interest(context.course.name)
|
||||
context.course = course
|
||||
membership = get_membership(course.name, frappe.session.user)
|
||||
context.course.query_parameter = (
|
||||
"?batch=" + membership.batch if membership and membership.batch else ""
|
||||
)
|
||||
context.membership = membership
|
||||
context.certificate = is_certified(course.name)
|
||||
eval_details = get_evaluation_details(course.name)
|
||||
context.eligible_for_evaluation = eval_details.eligible
|
||||
context.certificate_request = eval_details.request
|
||||
context.no_of_attempts = eval_details.no_of_attempts
|
||||
if context.course.upcoming:
|
||||
context.is_user_interested = get_user_interest(context.course.name)
|
||||
|
||||
context.metatags = {
|
||||
"title": course.title,
|
||||
"image": course.image,
|
||||
"description": course.short_introduction,
|
||||
"keywords": course.title
|
||||
}
|
||||
context.metatags = {
|
||||
"title": course.title,
|
||||
"image": course.image,
|
||||
"description": course.short_introduction,
|
||||
"keywords": course.title,
|
||||
}
|
||||
|
||||
|
||||
def get_user_interest(course):
|
||||
return frappe.db.count("LMS Course Interest", {
|
||||
"course": course,
|
||||
"user": frappe.session.user
|
||||
})
|
||||
|
||||
return frappe.db.count(
|
||||
"LMS Course Interest", {"course": course, "user": frappe.session.user}
|
||||
)
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
|
||||
frappe.ready(() => {
|
||||
generate_graph("New Signups");
|
||||
generate_graph("Course Enrollments");
|
||||
});
|
||||
|
||||
|
||||
const generate_graph = (chart_name) => {
|
||||
let date = frappe.datetime;
|
||||
|
||||
frappe.call({
|
||||
method: "lms.lms.utils.get_chart_data",
|
||||
args: {
|
||||
"chart_name": chart_name,
|
||||
"timespan": "Select Date Range",
|
||||
"timegrain": "Daily",
|
||||
"from_date": date.add_days(date.get_today(), -30),
|
||||
"to_date": date.add_days(date.get_today(), +1)
|
||||
chart_name: chart_name,
|
||||
timespan: "Select Date Range",
|
||||
timegrain: "Daily",
|
||||
from_date: date.add_days(date.get_today(), -30),
|
||||
to_date: date.add_days(date.get_today(), +1),
|
||||
},
|
||||
callback: (data) => {
|
||||
render_chart(data.message, chart_name);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const render_chart = (data, chart_name) => {
|
||||
let dom_element = chart_name == "Course Enrollments" ? "#course-enrollments" : "#new-signups";
|
||||
let dom_element =
|
||||
chart_name == "Course Enrollments"
|
||||
? "#course-enrollments"
|
||||
: "#new-signups";
|
||||
const chart = new frappe.Chart(dom_element, {
|
||||
title: chart_name,
|
||||
data: data,
|
||||
type: 'line',
|
||||
type: "line",
|
||||
height: 250,
|
||||
colors: ['#4563f1'],
|
||||
colors: ["#4563f1"],
|
||||
axisOptions: {
|
||||
xIsSeries: 1,
|
||||
},
|
||||
lineOptions: {
|
||||
"regionFill": 1
|
||||
}
|
||||
regionFill: 1,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,36 +1,50 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
from lms.lms.utils import can_create_courses, has_course_moderator_role, check_profile_restriction, get_restriction_details
|
||||
|
||||
from lms.lms.utils import (can_create_courses, check_profile_restriction,
|
||||
get_restriction_details, has_course_moderator_role)
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
context.live_courses, context.upcoming_courses = get_courses()
|
||||
context.restriction = check_profile_restriction()
|
||||
context.show_creators_section = can_create_courses()
|
||||
context.show_review_section = has_course_moderator_role() and frappe.session.user != "Guest"
|
||||
context.no_cache = 1
|
||||
context.live_courses, context.upcoming_courses = get_courses()
|
||||
context.restriction = check_profile_restriction()
|
||||
context.show_creators_section = can_create_courses()
|
||||
context.show_review_section = (
|
||||
has_course_moderator_role() and frappe.session.user != "Guest"
|
||||
)
|
||||
|
||||
if context.restriction:
|
||||
context.restriction_details = get_restriction_details()
|
||||
if context.restriction:
|
||||
context.restriction_details = get_restriction_details()
|
||||
|
||||
context.metatags = {
|
||||
"title": _("Course List"),
|
||||
"image": frappe.db.get_single_value("Website Settings", "banner_image"),
|
||||
"description": "This page lists all the courses published on our website",
|
||||
"keywords": "All Courses, Courses, Learn"
|
||||
}
|
||||
context.metatags = {
|
||||
"title": _("Course List"),
|
||||
"image": frappe.db.get_single_value("Website Settings", "banner_image"),
|
||||
"description": "This page lists all the courses published on our website",
|
||||
"keywords": "All Courses, Courses, Learn",
|
||||
}
|
||||
|
||||
|
||||
def get_courses():
|
||||
courses = frappe.get_all("LMS Course",
|
||||
filters={"published": True},
|
||||
fields=["name", "upcoming", "title", "image", "enable_certification",
|
||||
"paid_certificate", "price_certificate", "currency"])
|
||||
courses = frappe.get_all(
|
||||
"LMS Course",
|
||||
filters={"published": True},
|
||||
fields=[
|
||||
"name",
|
||||
"upcoming",
|
||||
"title",
|
||||
"image",
|
||||
"enable_certification",
|
||||
"paid_certificate",
|
||||
"price_certificate",
|
||||
"currency",
|
||||
],
|
||||
)
|
||||
|
||||
live_courses, upcoming_courses = [], []
|
||||
for course in courses:
|
||||
if course.upcoming:
|
||||
upcoming_courses.append(course)
|
||||
else:
|
||||
live_courses.append(course)
|
||||
return live_courses, upcoming_courses
|
||||
live_courses, upcoming_courses = [], []
|
||||
for course in courses:
|
||||
if course.upcoming:
|
||||
upcoming_courses.append(course)
|
||||
else:
|
||||
live_courses.append(course)
|
||||
return live_courses, upcoming_courses
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.jobs = frappe.get_all("Job Opportunity",
|
||||
{
|
||||
"status": "Open",
|
||||
"disabled": False
|
||||
},
|
||||
[
|
||||
"job_title", "location", "type", "company_name",
|
||||
"company_logo", "name", "creation"
|
||||
],
|
||||
order_by="creation desc")
|
||||
context.title = frappe.db.get_single_value("Job Settings", "title")
|
||||
context.subtitle = frappe.db.get_single_value("Job Settings", "subtitle")
|
||||
context.allow_posting = frappe.db.get_single_value("Job Settings", "allow_posting")
|
||||
context.jobs = frappe.get_all(
|
||||
"Job Opportunity",
|
||||
{"status": "Open", "disabled": False},
|
||||
["job_title", "location", "type", "company_name", "company_logo", "name", "creation"],
|
||||
order_by="creation desc",
|
||||
)
|
||||
context.title = frappe.db.get_single_value("Job Settings", "title")
|
||||
context.subtitle = frappe.db.get_single_value("Job Settings", "subtitle")
|
||||
context.allow_posting = frappe.db.get_single_value("Job Settings", "allow_posting")
|
||||
|
||||
@@ -1,35 +1,42 @@
|
||||
frappe.ready(() => {
|
||||
$("#report").click((e) => {
|
||||
open_report_dialog(e);
|
||||
});
|
||||
$("#report").click((e) => {
|
||||
open_report_dialog(e);
|
||||
});
|
||||
|
||||
$("#submit-report").click((e) => {
|
||||
report(e);
|
||||
});
|
||||
$("#submit-report").click((e) => {
|
||||
report(e);
|
||||
});
|
||||
});
|
||||
|
||||
const open_report_dialog = (e) => {
|
||||
e.preventDefault();
|
||||
if (frappe.session.user == "Guest") {
|
||||
window.location.href = `/login?redirect-to=/jobs/${$(e.currentTarget).data("job")}`;
|
||||
return;
|
||||
}
|
||||
$("#report-modal").modal("show");
|
||||
e.preventDefault();
|
||||
if (frappe.session.user == "Guest") {
|
||||
window.location.href = `/login?redirect-to=/jobs/${$(
|
||||
e.currentTarget
|
||||
).data("job")}`;
|
||||
return;
|
||||
}
|
||||
$("#report-modal").modal("show");
|
||||
};
|
||||
|
||||
const report = (e) => {
|
||||
frappe.call({
|
||||
method: "lms.job.doctype.job_opportunity.job_opportunity.report",
|
||||
args: {
|
||||
"job": $(e.currentTarget).data("job"),
|
||||
"reason": $(".report-field").val()
|
||||
job: $(e.currentTarget).data("job"),
|
||||
reason: $(".report-field").val(),
|
||||
},
|
||||
callback: (data) => {
|
||||
$(".report-modal").modal("hide");
|
||||
frappe.show_alert({
|
||||
message: __("Thanks for informing us about this post. The admin will look into it and take an appropriate action soon."),
|
||||
indicator:'green'
|
||||
}, 5);
|
||||
}
|
||||
frappe.show_alert(
|
||||
{
|
||||
message: __(
|
||||
"Thanks for informing us about this post. The admin will look into it and take an appropriate action soon."
|
||||
),
|
||||
indicator: "green",
|
||||
},
|
||||
5
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
try:
|
||||
job = frappe.form_dict["job"]
|
||||
except KeyError:
|
||||
frappe.local.flags.redirect_location = "/jobs"
|
||||
raise frappe.Redirect
|
||||
context.job = frappe.get_doc("Job Opportunity", job)
|
||||
try:
|
||||
job = frappe.form_dict["job"]
|
||||
except KeyError:
|
||||
frappe.local.flags.redirect_location = "/jobs"
|
||||
raise frappe.Redirect
|
||||
context.job = frappe.get_doc("Job Opportunity", job)
|
||||
|
||||
@@ -1,34 +1,32 @@
|
||||
frappe.ready(() => {
|
||||
|
||||
make_profile_active_in_navbar();
|
||||
|
||||
$(".role").change((e) => {
|
||||
save_role(e);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
const make_profile_active_in_navbar = () => {
|
||||
let member_name = $(".profile-name").data("name");
|
||||
if (member_name == frappe.session.user) {
|
||||
setTimeout(() => {
|
||||
let link_array = $('.nav-link').filter((i, elem) => $(elem).text().trim() === "My Profile");
|
||||
let link_array = $(".nav-link").filter(
|
||||
(i, elem) => $(elem).text().trim() === "My Profile"
|
||||
);
|
||||
link_array.length && $(link_array[0]).addClass("active");
|
||||
}, 0)
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const save_role = (e) => {
|
||||
let member_name = $(".profile-name").data("name");
|
||||
let role = $(e.currentTarget).children("input");
|
||||
let role = $(e.currentTarget).children("input");
|
||||
frappe.call({
|
||||
method: "lms.overrides.user.save_role",
|
||||
args: {
|
||||
"user": member_name,
|
||||
"role": role.data("role"),
|
||||
"value": role.prop("checked") ? 1 : 0
|
||||
user: member_name,
|
||||
role: role.data("role"),
|
||||
value: role.prop("checked") ? 1 : 0,
|
||||
},
|
||||
callback: (data) => {
|
||||
if (data.message) {
|
||||
@@ -37,6 +35,6 @@ const save_role = (e) => {
|
||||
indicator: "green",
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,47 +1,51 @@
|
||||
import frappe
|
||||
from lms.page_renderers import get_profile_url_prefix
|
||||
|
||||
from lms.lms.utils import get_lesson_index
|
||||
from lms.page_renderers import get_profile_url_prefix
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.no_cache = 1
|
||||
context.no_cache = 1
|
||||
|
||||
try:
|
||||
username = frappe.form_dict["username"]
|
||||
except KeyError:
|
||||
username = frappe.db.get_value("User", frappe.session.user, ["username"])
|
||||
if username:
|
||||
frappe.local.flags.redirect_location = get_profile_url_prefix() + username
|
||||
raise frappe.Redirect
|
||||
try:
|
||||
username = frappe.form_dict["username"]
|
||||
except KeyError:
|
||||
username = frappe.db.get_value("User", frappe.session.user, ["username"])
|
||||
if username:
|
||||
frappe.local.flags.redirect_location = get_profile_url_prefix() + username
|
||||
raise frappe.Redirect
|
||||
|
||||
try:
|
||||
context.member = frappe.get_doc("User", {"username": username})
|
||||
except:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
try:
|
||||
context.member = frappe.get_doc("User", {"username": username})
|
||||
except:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
|
||||
context.profile_tabs = get_profile_tabs(context.member)
|
||||
context.notifications = get_notifications()
|
||||
context.profile_tabs = get_profile_tabs(context.member)
|
||||
context.notifications = get_notifications()
|
||||
|
||||
|
||||
def get_profile_tabs(user):
|
||||
"""Returns the enabled ProfileTab objects.
|
||||
"""Returns the enabled ProfileTab objects.
|
||||
|
||||
Each ProfileTab is rendered as a tab on the profile page and the
|
||||
they are specified as profile_tabs hook.
|
||||
"""
|
||||
tabs = frappe.get_hooks("profile_tabs") or []
|
||||
return [frappe.get_attr(tab)(user) for tab in tabs]
|
||||
Each ProfileTab is rendered as a tab on the profile page and the
|
||||
they are specified as profile_tabs hook.
|
||||
"""
|
||||
tabs = frappe.get_hooks("profile_tabs") or []
|
||||
return [frappe.get_attr(tab)(user) for tab in tabs]
|
||||
|
||||
|
||||
def get_notifications():
|
||||
notifications = frappe.get_all("Notification Log", {
|
||||
"document_type": "Course Lesson",
|
||||
"for_user": frappe.session.user
|
||||
}, ["subject", "creation", "from_user", "document_name"])
|
||||
notifications = frappe.get_all(
|
||||
"Notification Log",
|
||||
{"document_type": "Course Lesson", "for_user": frappe.session.user},
|
||||
["subject", "creation", "from_user", "document_name"],
|
||||
)
|
||||
|
||||
for notification in notifications:
|
||||
course = frappe.db.get_value("Course Lesson", notification.document_name, "course")
|
||||
notification.url = "/courses/{0}/learn/{1}".format(course, get_lesson_index(notification.document_name))
|
||||
for notification in notifications:
|
||||
course = frappe.db.get_value("Course Lesson", notification.document_name, "course")
|
||||
notification.url = (
|
||||
f"/courses/{course}/learn/{get_lesson_index(notification.document_name)}"
|
||||
)
|
||||
|
||||
return notifications
|
||||
return notifications
|
||||
|
||||
@@ -1,29 +1,43 @@
|
||||
import frappe
|
||||
from lms.lms.utils import slugify, get_membership, get_lessons, get_batch, get_lesson_url
|
||||
|
||||
from lms.lms.utils import (get_batch, get_lesson_url, get_lessons,
|
||||
get_membership, slugify)
|
||||
|
||||
|
||||
def get_common_context(context):
|
||||
context.no_cache = 1
|
||||
context.no_cache = 1
|
||||
|
||||
try:
|
||||
batch_name = frappe.form_dict["batch"]
|
||||
except KeyError:
|
||||
batch_name = None
|
||||
try:
|
||||
batch_name = frappe.form_dict["batch"]
|
||||
except KeyError:
|
||||
batch_name = None
|
||||
|
||||
course = frappe.db.get_value(
|
||||
"LMS Course",
|
||||
frappe.form_dict["course"],
|
||||
["name", "title", "video_link", "enable_certification", "status"],
|
||||
as_dict=True,
|
||||
)
|
||||
if not course:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
context.course = course
|
||||
context.lessons = get_lessons(course.name)
|
||||
membership = get_membership(course.name, frappe.session.user, batch_name)
|
||||
context.membership = membership
|
||||
context.batch = membership.batch if membership and membership.batch else None
|
||||
context.course.query_parameter = (
|
||||
"?batch=" + membership.batch if membership and membership.batch else ""
|
||||
)
|
||||
context.livecode_url = get_livecode_url()
|
||||
|
||||
course = frappe.db.get_value("LMS Course",
|
||||
frappe.form_dict["course"], ["name", "title", "video_link", "enable_certification", "status"], as_dict=True)
|
||||
if not course:
|
||||
context.template = "www/404.html"
|
||||
return
|
||||
context.course = course
|
||||
context.lessons = get_lessons(course.name)
|
||||
membership = get_membership(course.name, frappe.session.user, batch_name)
|
||||
context.membership = membership
|
||||
context.batch = membership.batch if membership and membership.batch else None
|
||||
context.course.query_parameter = "?batch=" + membership.batch if membership and membership.batch else ""
|
||||
context.livecode_url = get_livecode_url()
|
||||
|
||||
def get_livecode_url():
|
||||
return frappe.db.get_single_value("LMS Settings", "livecode_url")
|
||||
return frappe.db.get_single_value("LMS Settings", "livecode_url")
|
||||
|
||||
|
||||
def redirect_to_lesson(course, index_="1.1"):
|
||||
frappe.local.flags.redirect_location = get_lesson_url(course.name, index_) + course.query_parameter
|
||||
raise frappe.Redirect
|
||||
frappe.local.flags.redirect_location = (
|
||||
get_lesson_url(course.name, index_) + course.query_parameter
|
||||
)
|
||||
raise frappe.Redirect
|
||||
|
||||
Reference in New Issue
Block a user